/* ============================================================
   swv-kit.css — the design stylesheet, inlined here as the page's only
   <style>. Superset of what this file carried before: 80 selectors added,
   none dropped, so existing engine markup keeps styling as it did.
   Fonts load from assets/fonts/ (local files, not a network request).
   ============================================================ */

/* ============================================================
   WITH GRACE — VILLAGE PORTAL  ·  white-label buyer platform
   Skin: Secret Waterfall Village
   All brand tokens live here; re-skin via :root + PROJECT config.
   ============================================================ */









:root{
  /* secretwaterfallvillage.com — the SWV brand, not With Grace.
     The site is DARK: a deep forest ground under a paper texture, sand type,
     sage as the only accent. Token NAMES are kept so the ~400 var() uses across
     this file remap in one place; their VALUES are now SWV's.            */
  --cream:#1D2415;   /* page ground   — forest (was cream)                */
  --paper:#E6E1D1;   /* type on ground — sand                             */
  --ink:#E6E1D1;     /* foreground / inverse fill — sand (was near-black) */
  --well:#11150C;    /* behind media: map, hero, film, styler stage       */
  --stone:#314736;   /* raised ground — moss (the site's sticky bar)      */
  --midnight:#151A0F;/* deepest ground                                    */
  --terra:#949E86;   /* THE accent — sage. Not terracotta.                */
  --ghost:#9CAD85;   /* lighter sage                                      */
  /* Second accent — a brass yellow, added 2026-08. Sage is the voice of the
     place; --sun is the voice of the MONEY. Use it only where a number or a
     decision needs to be found: the price, the active state, the one line on
     a chart that matters. Never as a large fill, never for body type.
     --sun-ink is the type that sits ON a --sun fill.                   */
  --sun:#D8B24A;     /* brass on the forest ground — ~8.9:1 on #1D2415    */
  --sun-soft:color-mix(in srgb,var(--sun) 22%, transparent);
  --sun-ink:#1D2415; /* type on a --sun fill                              */
  /* Hover is a DIRECTION, not a colour: always away from the ground toward
     maximum contrast. On the forest ground that is white; inside the bone
     scope (which redefines --cream/--paper below) it has to invert to the
     deep forest, or a white hover fill puts sand type on white. Both halves
     are tokens so a single :hover rule is correct on either ground.     */
  --hover:#FFFFFF;   /* hover destination — fill or type, never a colour  */
  --hover-on:#1D2415;/* type sitting ON a --hover fill                    */
  /* Setting text BACK has one floor: 4.5:1 against the ground under it.
     Roughly forty rules used to reach for their own opacity:.6–.75, which
     lands between 3.2:1 and 4.2:1 — fine on a bright desktop, thin and grey
     on a phone in daylight. These two tokens are the only sanctioned way to
     mute type. Use --dim for labels and captions, --dim-soft only for the
     faintest tier; below --dim-soft there is nothing, by design.
     Both are redefined in the bone scope because that ground has far less
     headroom (sand on forest is 12:1; forest on bone only 8.3:1), so the
     same fraction that reads there is illegible here.               */
  --dim:color-mix(in srgb,var(--paper) 74%, transparent);       /* ~7.0:1 */
  --dim-soft:color-mix(in srgb,var(--paper) 58%, transparent);  /* ~4.7:1 */
  --ls:0.22em; --ls-wide:0.34em;   /* the site tracks 3px @13px, 8px @15px */
  --serif:'Cormorant Garamond', Georgia, serif;
  --sans:'Montserrat', system-ui, sans-serif;
  --label:'Lato', system-ui, sans-serif;
  --ease:cubic-bezier(0.83,0,0.17,1);
  --nav-h:64px;
}
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{scroll-behavior:smooth}
html,body{height:100%}
body{
  font-family:var(--serif); font-weight:400; color:var(--ink);
  background:var(--cream); font-size:19.5px; line-height:1.6;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
img{display:block;max-width:100%}
button{font-family:inherit;cursor:pointer;background:none;border:none;color:inherit}
a{color:inherit;text-decoration:none}
/* The reset above strips the UA focus ring from every button on the page, and
   nothing put one back — keyboard users had no visible focus at all. One base
   rule, in the accent, which is legible on both grounds because --terra is
   redefined inside the bone scope. :focus-visible only, so a mouse click never
   leaves a ring behind. */
:focus-visible{outline:2px solid var(--terra);outline-offset:3px;border-radius:3px}
::selection{background:var(--ink);color:var(--cream)}

/* ---------- type ---------- */
.caps{font-weight:400;text-transform:uppercase;letter-spacing:var(--ls);font-size:12.5px}
.caps.wide{letter-spacing:var(--ls-wide)}
h1,h2,h3{font-weight:300;line-height:1.08}
h2,.over,.sec{scroll-margin-top:150px}
@media(max-width:860px){h2,.over,.sec{scroll-margin-top:130px}}
.display{font-size:clamp(44px,7.5vw,104px);letter-spacing:0.01em}
.title{font-size:clamp(32px,4.4vw,58px)}
.lead{font-size:clamp(21px,2.3vw,27px);font-style:italic;font-weight:300;line-height:1.4}
.body-l{font-size:clamp(19px,1.6vw,22px)}
em{font-style:italic}
.dim{opacity:0.74}
.center{text-align:center}

/* ---------- nav ---------- */
.nav{
  position:fixed;inset:0 0 auto 0;height:var(--nav-h);z-index:600;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 28px;transition:background .5s,color .5s, transform .5s;
  color:var(--paper);
}
.nav.on-cream{color:var(--ink)}
.nav.scrolled{background:rgba(245,241,232,.98);color:var(--ink);
  backdrop-filter:blur(12px);border-bottom:1px solid color-mix(in srgb,var(--ink) 10%, transparent)}
/* readability: when the nav's light text sits over imagery (cover, story,
   idea) and hasn't picked up the cream scrolled/on-cream background, lay a
   soft top scrim behind it so the brand + burger never fight the photo. */
.nav::before{content:"";position:absolute;inset:0 0 auto 0;height:calc(var(--nav-h) + 22px);z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,rgba(10,9,6,.42),transparent);opacity:0;transition:opacity .5s}
.nav:not(.on-cream):not(.scrolled)::before{opacity:1}
.nav .brand{letter-spacing:var(--ls-wide);font-size:15px;font-weight:500;text-transform:uppercase;white-space:nowrap}
.nav .links{display:flex;gap:28px;align-items:center}
.nav .links button{letter-spacing:var(--ls);font-size:13px;text-transform:uppercase;font-weight:500;opacity:1;padding:6px 0;border-bottom:1px solid transparent;transition:.3s}
.nav .links button:hover{opacity:1;border-bottom-color:currentColor}
.nav .links button.active{opacity:1;border-bottom-color:currentColor}
.nav .mine-pill{border:1px solid currentColor;border-radius:99px;padding:7px 16px 8px;letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;transition:.3s}
/* .mine-pill hover is declared once, in the gated hover block further down */
.burger{display:none;font-size:24px;line-height:1;padding:8px}
@media(max-width:960px){
  .nav .links{position:fixed;inset:var(--nav-h) 0 auto 0;background:var(--cream);color:var(--ink);
    flex-direction:column;gap:0;padding:10px 0 22px;display:none;border-bottom:1px solid rgba(230,225,209,.12)}
  .nav .links.open{display:flex}
  .nav .links button{padding:13px 0;font-size:13px}
  .burger{display:block}
}

/* ---------- views ---------- */
.view{display:none}
.view.active{display:block}

/* ---------- full-bleed image beat ---------- */
.beat{position:relative;min-height:100vh;min-height:100dvh}
.beat .stage{position:sticky;top:0;height:100vh;height:100dvh;overflow:hidden}
.beat .stage img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transform-origin:center;will-change:transform}
.scrim{position:absolute;inset:auto 0 0 0;padding:130px 48px 46px;
  background:linear-gradient(to top,rgba(10,9,6,.82),rgba(10,9,6,.40) 55%,transparent);color:var(--paper)}
.scrim .over{letter-spacing:var(--ls-wide);font-size:12.5px;text-transform:uppercase;font-weight:500;opacity:.95;margin-bottom:10px;text-shadow:0 1px 8px rgba(0,0,0,.5)}
.scrim .line{font-size:clamp(25px,3.2vw,41px);font-weight:400;line-height:1.18;max-width:20em;text-shadow:0 1px 14px rgba(0,0,0,.45)}
.scrim .labels{display:flex;flex-wrap:wrap;gap:8px 34px;margin-top:18px}
.scrim .labels span{letter-spacing:var(--ls);font-size:12px;text-transform:uppercase;font-weight:500;opacity:.92;text-shadow:0 1px 8px rgba(0,0,0,.5)}
.scrim .labels b{font-weight:500;opacity:1}
@media(max-width:700px){.scrim{padding:90px 22px 30px}}
/* v26 §17 (M-08) — #story-cue is fixed at bottom:22px and paints over
   the caption (z-index 95 vs 60).  At <=700px the caption's .labels
   row ended at bottom-offset 30px, inside the cue caption's 22-40.4px
   band: measured glyph-on-glyph overlap up to 22.5 x 10.0px on all six
   villa stories.  Lift the caption clear; story captions only. */
@media(max-width:700px){.fstage .scap.scrim{padding-bottom:74px}}

/* ---------- generic section on cream ---------- */
.sec{padding:110px 7vw;max-width:1280px;margin:0 auto}
/* v23 A3 — chapter body gets extra bottom breathing room so terminal
   content (last P&L row, last accordion row, etc.) can always be scrolled
   clear of the fab's resting zone. */
#det-chapter-body{padding-top:52px;padding-bottom:88px}
@media(max-width:860px){#det-chapter-body{padding-top:40px;padding-bottom:120px}}
/* merged details pages: the villa-page divider + the Numbers colour bands */
.secdiv{height:1px;background:color-mix(in srgb,var(--ink) 12%, transparent);margin:52px 0}
.specgap{height:44px}
.band{border-radius:14px;padding:clamp(28px,3.6vw,50px) clamp(20px,3.4vw,42px);margin:0 0 22px}
.band>*:first-child{margin-top:0}
.band-invest{background:color-mix(in srgb,var(--midnight) 6%, var(--cream))}
.band-returns{background:var(--cream);border:1px solid color-mix(in srgb,var(--ink) 9%, transparent)}
.band-path{background:color-mix(in srgb,var(--terra) 12%, var(--cream))}
@media(max-width:700px){.band{border-radius:11px}}
/* one bottom conversion CTA (email the numbers / book a call) */
.convo{margin-top:44px;padding-top:8px}
.convo .cta-row{flex-wrap:wrap}
.cc-form{display:flex;flex-wrap:wrap;gap:12px;margin-top:18px;max-width:440px}
.cc-form input{flex:1;min-width:200px;background:var(--cream);border:1px solid color-mix(in srgb,var(--ink) 24%, transparent);
  border-radius:4px;color:var(--ink);font-family:inherit;font-size:16px;padding:13px 15px;outline:none}
.cc-form input:focus{border-color:var(--terra)}
.cc-ok{font-style:italic;opacity:.82;margin-top:16px}
[data-ponder]{cursor:help}
.sec .over{letter-spacing:var(--ls-wide);font-size:12.5px;text-transform:uppercase;font-weight:500;color:var(--dim);margin-bottom:16px}
.sec h2{margin-bottom:26px}
.rule{height:1px;background:color-mix(in srgb,var(--ink) 14%, transparent);margin:48px 0}
/* the idea page's "what we are building" list — the site's ✶ bullets, set as a
   terracotta rule-mark rather than a glyph so it stays inside the one family */
.ethos-list{list-style:none;display:flex;flex-direction:column;gap:11px}
.ethos-list li{position:relative;padding-left:26px;font-size:18.5px;line-height:1.5}
.ethos-list li::before{content:"";position:absolute;left:0;top:.62em;width:12px;height:1px;background:var(--terra)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:56px}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:34px}
@media(max-width:900px){.grid2,.grid3{grid-template-columns:1fr}}

/* ============================================================
   SELECTOR — the masterplan
   ============================================================ */
#map-wrap{position:fixed;inset:0;overflow:hidden;background:var(--well);touch-action:none}
@media(hover:hover) and (pointer:fine){body.on-map #map-wrap{cursor:grab}body.panning #map-wrap{cursor:grabbing}}
#map-cam{position:absolute;left:0;top:0;will-change:transform}
#map-cam img{position:absolute;left:0;top:0;width:100%;height:100%}
#hotspots{position:absolute;left:0;top:0;width:100%;height:100%;z-index:10}
/* ---- the chosen home lights up ----------------------------------------
   Two stacked layers inside #map-cam, so they pan and scale with the village.
   --sx/--sy are the home's own image coordinates, set from posFor().
   #spot-shade eases the rest of the village into dusk; #spot-glow lifts a
   warm light out of the chosen house, as though its windows just came on. */
#spot{position:absolute;left:0;top:0;width:100%;height:100%;z-index:9;pointer-events:none;
  opacity:0;transition:opacity .75s var(--ease)}
#spot.on{opacity:1}
#spot-shade,#spot-glow{position:absolute;inset:0;
  transition:background-position .85s var(--ease)}
#spot-shade{background:radial-gradient(circle at var(--sx,50%) var(--sy,50%),
  rgba(10,9,6,0) 0%, rgba(10,9,6,.06) var(--r1,7%), rgba(10,9,6,.40) var(--r2,26%), rgba(10,9,6,.54) 68%)}
#spot-glow{mix-blend-mode:screen;
  background:radial-gradient(circle at var(--sx,50%) var(--sy,50%),
    rgba(255,198,120,.34) 0%, rgba(255,180,98,.18) var(--r1,7%), rgba(255,170,90,0) var(--r2,26%))}
@media(prefers-reduced-motion:reduce){#spot,#spot-shade,#spot-glow{transition:none}}
/* the dot is a zero-size anchor — the point sits EXACTLY on the coordinate,
   the tag floats above it without shifting the geometry */
.dot{position:absolute;width:0;height:0;transition:opacity .5s}
.dot .pt{position:absolute;left:0;top:0;width:17px;height:17px;border-radius:50%;background:var(--paper);
  transform:translate(-50%,-50%);
  box-shadow:0 0 0 7px color-mix(in srgb,var(--paper) 30%, transparent),0 0 22px 4px rgba(232,221,198,.55),0 1px 10px rgba(0,0,0,.5);
  transition:.35s;}
.dot .pt::after{content:"";position:absolute;inset:-13px;border-radius:50%;border:1px solid color-mix(in srgb,var(--paper) 60%, transparent);
  animation:pulse 3.2s infinite}
.dot.lit .tag{opacity:1;transform:translate(calc(-50% + var(--tagdx)),0)}
@keyframes pulse{0%{transform:scale(.6);opacity:.9}70%{transform:scale(1.5);opacity:0}100%{opacity:0}}
.dot .tag{position:absolute;bottom:18px;left:0;--tagdx:0px;transform:translate(calc(-50% + var(--tagdx)),-4px);
  background:color-mix(in srgb,var(--well) 78%, transparent);backdrop-filter:blur(6px);color:var(--paper);
  padding:7px 13px 8px;border-radius:3px;text-align:center;opacity:0;transition:.35s;pointer-events:none;
  /* v26 §15 — was white-space:nowrap, which made the widest tag 483px against a 390px
     viewport (99-character subtitle on one line).  Wrapping + a cap is half the fix;
     clampTags() below is the other half. */
  white-space:normal;width:max-content;max-width:min(268px,calc(100vw - 24px))}
.dot .tag .nm{letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;font-weight:500}
.dot .tag .st{font-size:13.5px;font-style:italic;opacity:.9}
.dot:hover .tag,.dot.picked .tag{opacity:1;transform:translate(calc(-50% + var(--tagdx)),0)}
.dot:hover .pt{transform:translate(-50%,-50%) scale(1.35)}
.dot.off{opacity:.16;pointer-events:none}
.dot.reserved .pt{background:color-mix(in srgb,var(--paper) 40%, transparent);box-shadow:0 0 0 1px var(--paper) inset,0 1px 8px rgba(0,0,0,.45)}
.dot.reserved .pt::after{display:none}
.dot.show-villa .pt{background:var(--terra)}
.dot.amen{cursor:default}
.dot.amen .pt{width:8px;height:8px;background:color-mix(in srgb,var(--paper) 70%, transparent);box-shadow:0 1px 6px rgba(0,0,0,.4)}
.dot.amen .pt::after{display:none}
.dot.amen:hover .pt{transform:translate(-50%,-50%) scale(1.2)}
.dot.editing .pt{outline:2px dashed var(--terra);outline-offset:4px}

/* facility explore CTA */
#fac-cta{position:fixed;left:50%;bottom:150px;transform:translate(-50%,14px);z-index:32;
  background:var(--paper);color:var(--ink);border-radius:99px;padding:13px 28px 14px;
  letter-spacing:var(--ls);font-size:12.5px;text-transform:uppercase;font-weight:500;
  box-shadow:0 14px 44px rgba(0,0,0,.45);opacity:0;pointer-events:none;transition:.45s var(--ease)}
#fac-cta.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
#fac-cta:hover{background:var(--cream)}
@media(max-width:700px){#fac-cta{bottom:190px}}

/* map angle views */
#angle-layers{position:absolute;inset:0;pointer-events:none}
.angle-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .95s var(--ease)}
.ang-btn{position:fixed;top:50%;transform:translateY(-50%);z-index:30;width:54px;height:54px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;color:var(--paper);font-size:30px;line-height:1;padding-bottom:4px;
  background:color-mix(in srgb,var(--well) 45%, transparent);backdrop-filter:blur(8px);
  border:1px solid color-mix(in srgb,var(--paper) 35%, transparent);transition:.3s}
.ang-btn:hover{background:color-mix(in srgb,var(--well) 70%, transparent);border-color:var(--paper)}
#ang-left{left:22px}
#ang-right{right:22px}
@media(max-width:700px){.ang-btn{width:44px;height:44px;font-size:24px}#ang-left{left:10px}#ang-right{right:10px}}

/* selector chrome */
#sel-chrome{position:fixed;inset:0;pointer-events:none;z-index:20}
#sel-chrome::before{content:"";position:absolute;inset:0 0 auto 0;height:150px;
  background:linear-gradient(to bottom,rgba(10,9,6,.55),transparent)}
#sel-chrome::after{content:"";position:absolute;inset:auto 0 0 0;height:190px;
  background:linear-gradient(to top,rgba(10,9,6,.6),transparent)}
#sel-head{position:absolute;top:calc(var(--nav-h) + 16px);left:0;right:0;display:flex;flex-direction:column;align-items:center;z-index:2}
#sel-head .hint{color:var(--paper);letter-spacing:var(--ls-wide);font-size:12.5px;text-transform:uppercase;font-weight:500;opacity:.96;text-shadow:0 1px 4px rgba(0,0,0,.85),0 2px 16px rgba(0,0,0,.6)}
#sel-bottom{position:absolute;bottom:24px;left:0;right:0;display:flex;flex-direction:column;align-items:center;gap:14px;z-index:2}
.chips{display:flex;gap:10px;pointer-events:none;flex-wrap:wrap;justify-content:center}
.chips .chip{pointer-events:auto}
.chips.sub{max-height:0;opacity:0;overflow:hidden;transition:max-height .5s var(--ease),opacity .45s;padding:0 12px}
.chips.sub.open{max-height:170px;opacity:1}
.chips.sub .chip{font-size:11.5px;padding:8px 18px 9px;font-weight:500}
.gchip{padding:11px 26px 12px;font-size:12.5px}
.gchip.active{background:var(--paper);color:var(--ink);border-color:var(--paper)}
/* facility dots grow to full presence in facilities mode */
.dot.amen.big .pt{width:15px;height:15px;background:var(--paper);
  box-shadow:0 0 0 7px color-mix(in srgb,var(--paper) 30%, transparent),0 0 22px 4px rgba(232,221,198,.55),0 1px 10px rgba(0,0,0,.5)}
.dot.amen.big .pt::after{content:"";position:absolute;inset:-12px;border-radius:50%;
  border:1px solid color-mix(in srgb,var(--paper) 60%, transparent);animation:pulse 3.2s infinite;display:block}
.dot.amen.big:hover .pt{transform:translate(-50%,-50%) scale(1.3)}
.chip{border:1px solid color-mix(in srgb,var(--paper) 55%, transparent);color:var(--paper);border-radius:99px;
  padding:10px 22px 11px;letter-spacing:var(--ls);font-size:12.5px;text-transform:uppercase;font-weight:500;
  background:color-mix(in srgb,var(--well) 42%, transparent);backdrop-filter:blur(8px);transition:.3s}
.chip:hover{border-color:var(--paper)}
.chip.active{background:var(--paper);color:var(--ink);border-color:var(--paper)}
#sel-legend{display:flex;gap:30px;justify-content:center;color:var(--paper);pointer-events:none;flex-wrap:wrap}
#sel-legend span{display:flex;align-items:center;gap:9px;letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;font-weight:500;opacity:.95;text-shadow:0 1px 4px rgba(0,0,0,.85),0 2px 12px rgba(0,0,0,.6)}
#sel-legend i{width:10px;height:10px;border-radius:50%;background:var(--paper)}
#sel-legend i.r{background:color-mix(in srgb,var(--paper) 40%, transparent);box-shadow:0 0 0 1px var(--paper) inset}
#sel-legend i.s{background:var(--terra)}
@media(max-width:700px){
  #sel-legend{display:none}
  #sel-bottom{bottom:18px;padding:0 12px}
  body.on-map #c-fab .lbl{display:none}
  body.on-map #c-fab{padding:15px;border-radius:50%}
}

/* ============================================================
   MASTERPLAN — mobile touch pass
   1) real 44px tap targets   2) Grace's bubble clears the controls
   3) less chrome             4) available vs reserved you can scan
   ============================================================ */
@media(pointer:coarse){
  /* 1 — the visible dot stays small; the touch target does not */
  .dot .pt::before{content:"";position:absolute;left:50%;top:50%;width:46px;height:46px;
    transform:translate(-50%,-50%);border-radius:50%}
  /* 4 — status you can read at a glance: available reads first, reserved recedes */
  .dot.lit .pt, .dot:not(.off):not(.reserved):not(.amen) .pt{width:21px;height:21px}
  .dot.reserved .pt{width:13px;height:13px;opacity:.5;
    box-shadow:0 0 0 1px color-mix(in srgb,var(--paper) 70%, transparent) inset,0 1px 6px rgba(0,0,0,.4)}
  .dot.show-villa .pt{width:21px;height:21px}
  /* the lit villas name themselves rather than making you tap blind */
  .dot.lit .tag{opacity:1;transform:translate(calc(-50% + var(--tagdx)),0)}
  .dot.lit .tag .st{display:none}
  .dot.lit .tag{padding:5px 10px 6px;background:color-mix(in srgb,var(--well) 72%, transparent)}
  .dot.lit .tag .nm{font-size:10.5px}
  /* 3 — one row of controls, not two: the bedroom filters go behind Villas */
  #chips-sub.open{max-height:120px}
  #sel-bottom{gap:10px}
  #sel-head .hint{font-size:11.5px;padding:0 16px;text-align:center}
}
/* 2 — Grace's bubble sat on top of the chips it was pointing at */
body.on-map #fab-bubble{bottom:calc(18px + var(--map-chrome,150px))}
@media(max-width:860px){body.on-map #fab-bubble{bottom:calc(14px + var(--map-chrome,150px))}}

/* ============================================================
   MASTERPLAN (mobile + desktop) — the map is the backdrop, the cards browse.
   A swipeable rail of villa cards along the bottom; the card you
   land on lights and centres its pin. (?alt=1)
   ============================================================ */
#vrail{position:fixed;left:0;right:0;bottom:0;z-index:34;display:none;
  padding:0 0 calc(14px + env(safe-area-inset-bottom));pointer-events:none}
html[data-alt="1"] body.on-map #vrail{display:flex;flex-direction:column}
/* filter: homes or the shared places */
.vr-filter{display:flex;gap:0;align-self:center;pointer-events:auto;margin:0 0 2px;
  background:color-mix(in srgb,var(--well) 58%, transparent);backdrop-filter:blur(10px);
  border:1px solid color-mix(in srgb,var(--paper) 26%, transparent);border-radius:99px;overflow:hidden}
.vr-seg button{color:var(--dim);letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;
  padding:8px 20px 9px;transition:.25s}
.vr-seg button.on{background:var(--paper);color:var(--ink);font-weight:600}
.vr-note{display:block;margin-top:5px;font-size:12.5px;line-height:1.35;color:var(--dim);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.vr-price.sm{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls);text-transform:uppercase;color:var(--dim)}

/* ---- desktop: a column down the left, not a rail along the bottom ---- */
@media(min-width:861px){
  html[data-alt="1"] body.on-map #vrail{left:0;right:auto;top:var(--nav-h);bottom:0;
    width:min(370px,32vw);padding:16px 0 22px;
    background:linear-gradient(to right,rgba(10,9,6,.80),rgba(10,9,6,.55) 68%,transparent)}
  html[data-alt="1"] #vrail .vr-scroll{flex-direction:column;overflow-y:auto;overflow-x:hidden;
    scroll-snap-type:y proximity;flex:1;min-height:0;padding:12px 20px;gap:10px;scroll-padding-block:20px}
  html[data-alt="1"] #vrail .vr-scroll::before,html[data-alt="1"] #vrail .vr-scroll::after{display:none}
  html[data-alt="1"] .vrcard{flex:0 0 auto;width:100%;max-width:none;scroll-snap-align:center}
  html[data-alt="1"] body.on-map #c-fab{bottom:26px;right:26px}
  html[data-alt="1"] body.on-map #fab-bubble{bottom:96px;right:26px}
  html[data-alt="1"] body.on-map #ang-left{left:calc(min(370px,32vw) + 18px)}
}
html[data-alt="1"] body.on-map #chips-sub{display:none}
#vrail .vr-scroll{display:flex;gap:11px;overflow-x:auto;scroll-snap-type:x mandatory;
  padding:14px 0 6px;scrollbar-width:none;pointer-events:auto;-webkit-overflow-scrolling:touch;
  scroll-padding-inline:14px}
#vrail .vr-scroll::-webkit-scrollbar{display:none}
/* first/last card can still centre */
#vrail .vr-scroll::before,#vrail .vr-scroll::after{content:"";flex:0 0 14px}
/* An unfocused card recedes by SCALE and SHADOW, not by opacity. .82 here was
   multiplied by .5 on .vr-meta and again by .68 on .vr-st.rs — 0.28 of the
   ground, and "Reserved" measured 2.21:1. CLAUDE.md rule (b), three deep. */
.vrcard{scroll-snap-align:center;flex:0 0 min(83vw,330px);text-align:left;display:flex;gap:12px;align-items:stretch;
  background:color-mix(in srgb,var(--cream) 92%, transparent);color:var(--ink);border-radius:13px;
  padding:11px;box-shadow:0 8px 22px rgba(0,0,0,.26);border:1px solid transparent;
  transform:scale(.965);transition:transform .3s var(--ease),background .3s,box-shadow .3s,border-color .3s}
.vrcard.on{transform:none;background:color-mix(in srgb,var(--cream) 99%, transparent);
  border-color:color-mix(in srgb,var(--terra) 65%, transparent);
  box-shadow:0 18px 46px rgba(0,0,0,.44)}
.vrcard.muted .vr-thumb img{filter:grayscale(.45) brightness(.92)}
.vr-thumb{flex:0 0 84px;border-radius:8px;overflow:hidden;background:var(--stone);display:block}
.vr-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.vr-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:space-between}
.vrcard .vr-top{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.vrcard .vr-nm{font-family:var(--serif);font-size:17.5px;line-height:1.12;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vrcard .vr-st{letter-spacing:var(--ls);font-size:9px;text-transform:uppercase;font-weight:600;white-space:nowrap}
.vrcard .vr-st.av{color:var(--terra)}
.vrcard .vr-st.rs{color:var(--dim)}
.vrcard .vr-meta{display:flex;gap:12px;margin-top:5px;letter-spacing:var(--ls);font-size:9.5px;
  text-transform:uppercase;color:var(--dim);white-space:nowrap;overflow:hidden}
.vrcard .vr-row{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-top:9px}
.vrcard .vr-price{font-family:var(--serif);font-size:19px;white-space:nowrap}
.vrcard .vr-go{letter-spacing:var(--ls);font-size:9.5px;text-transform:uppercase;white-space:nowrap;
  color:var(--terra);font-weight:600;opacity:0;transition:opacity .3s}
.vrcard.on .vr-go{opacity:1}
/* the cards are the browser — the map's own group chips just repeat them */
html[data-alt="1"] body.on-map #sel-bottom{display:none}
html[data-alt="1"] body.on-map #sel-chrome::after{height:0}

/* ---- the cards rail, second pass ----------------------------------
   scarcity in the header, price-forward cards, the founders' houses
   grouped as reference, and a two-way hover link to the map.
   All of it scoped to data-alt="1"; mode 0 keeps the original card. */

/* header: the count is the argument, so it leads */
html[data-alt="1"] .vr-head{display:flex;align-items:center;justify-content:flex-start;gap:14px;
  pointer-events:auto;padding:0 20px 10px;color:var(--paper)}
html[data-alt="1"] .vr-count{letter-spacing:var(--ls-wide);font-size:10px;text-transform:uppercase;
  opacity:.62;white-space:nowrap;text-shadow:0 1px 6px rgba(0,0,0,.85)}
html[data-alt="1"] .vr-count b{font-weight:600;opacity:1;color:var(--terra)}

/* card: name, then price, then status and plot as a footnote.
   No per-card CTA — the card itself is the affordance. */
html[data-alt="1"] .vrcard .vr-row{margin-top:2px;gap:0}
html[data-alt="1"] .vrcard .vr-meta{margin-top:auto;padding-top:7px;color:var(--dim)}

/* the founders' houses: named, not sold — and shown by their land,
   since there is no exterior photograph of them to keep the column honest */
.vr-div{display:none;align-items:center;gap:10px;padding:12px 20px 4px;color:var(--paper);
  letter-spacing:var(--ls-wide);font-size:9px;text-transform:uppercase;opacity:.42}
.vr-div::after{content:"";flex:1;height:1px;background:color-mix(in srgb,var(--paper) 28%, transparent)}
html[data-alt="1"] .vrcard.slim{padding:9px}
html[data-alt="1"] .vrcard.slim .vr-thumb{flex:0 0 58px}
html[data-alt="1"] .vrcard.slim .vr-nm{font-size:15px}
html[data-alt="1"] .vrcard.slim .vr-price{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls);
  text-transform:uppercase;color:var(--dim)}
html[data-alt="1"] .vr-thumb.fig{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:1px;background:color-mix(in srgb,var(--stone) 42%, transparent);color:var(--ink)}
html[data-alt="1"] .vr-thumb.fig b{font-family:var(--serif);font-size:16px;font-weight:400;line-height:1}
html[data-alt="1"] .vr-thumb.fig em{font-style:normal;letter-spacing:var(--ls);font-size:7.5px;
  text-transform:uppercase;opacity:.55}

/* hovering either side lights the pair and quiets the rest — the whole
   point of pairing a map with a list */
html[data-alt="1"] #hotspots.hovering .dot:not(.hovlit){opacity:.2}
html[data-alt="1"] .dot.hovlit .pt{transform:translate(-50%,-50%) scale(1.4);background:var(--terra);
  box-shadow:0 0 0 5px color-mix(in srgb,var(--terra) 40%, transparent),0 2px 16px rgba(0,0,0,.6)}
html[data-alt="1"] .vrcard.hov{transform:none;
  border-color:color-mix(in srgb,var(--terra) 65%, transparent);box-shadow:0 18px 46px rgba(0,0,0,.44)}

/* plot footprints, sized true to area (k·√m² as a share of the render, so
   they hold scale as the camera box grows). Proportional, not surveyed —
   calibrated against the plot pitch across the villa rows. */
#map-cam{container-type:size}
.dot .plot{position:absolute;left:0;top:0;width:var(--pw,7.6cqw);aspect-ratio:1;
  transform:translate(-50%,-50%) scaleY(.44);border-radius:50%;
  border:1px solid color-mix(in srgb,var(--paper) 52%, transparent);
  background:radial-gradient(circle,color-mix(in srgb,var(--paper) 13%, transparent),transparent 72%);
  opacity:0;transition:opacity .4s var(--ease);pointer-events:none}
html[data-alt="1"] .dot.hovlit .plot{opacity:1;
  border-color:color-mix(in srgb,var(--terra) 85%, transparent);
  background:radial-gradient(circle,color-mix(in srgb,var(--terra) 22%, transparent),transparent 74%)}
html[data-alt="1"] .dot.picked .plot{opacity:.6}

/* the walk arrows name the angle they take you to */
.ang-btn b{position:absolute;left:50%;top:calc(100% + 8px);transform:translateX(-50%);
  letter-spacing:var(--ls-wide);font-size:8.5px;text-transform:uppercase;font-weight:500;
  white-space:nowrap;opacity:0;transition:opacity .3s;text-shadow:0 1px 6px rgba(0,0,0,.9)}
@media(hover:hover){.ang-btn:hover b{opacity:1;color:var(--hover)}}
@media(max-width:860px){
  html[data-alt="1"] .vr-head{padding:0 14px 8px;justify-content:center;gap:12px}
  .ang-btn b{display:none}
  .vr-div{display:none}
}
@media(min-width:861px){
  .vr-div{display:flex}
  /* text-overflow belongs on the flex ITEM, never on the flex container */
  html[data-alt="1"] .vrcard .vr-meta{gap:7px}
  html[data-alt="1"] .vrcard .vr-meta > span{min-width:0;overflow:hidden;text-overflow:ellipsis}
  /* keep the legend out from under the Ask Grace pill */
  html[data-alt="1"] body.on-map #sel-bottom{padding-right:200px}
}
/* 861–1120px: the rail is at its narrowest relative to the type, so the
   thumb and the name give ground rather than truncate */
@media(min-width:861px) and (max-width:1120px){
  html[data-alt="1"] .vr-thumb{flex:0 0 64px}
  html[data-alt="1"] .vrcard.slim .vr-thumb{flex:0 0 52px}
  html[data-alt="1"] .vrcard .vr-nm{font-size:15.5px}
  html[data-alt="1"] .vrcard .vr-meta{font-size:9px}
}

/* these offsets are for the BOTTOM rail only — on desktop the rail is a left
   column and --vrail-h is its full height, which would fling the fab off-screen */
@media(max-width:860px){
  html[data-alt="1"] body.on-map #fab-bubble{bottom:calc(var(--vrail-h,190px) + 16px)}
  html[data-alt="1"] body.on-map #c-fab{bottom:calc(var(--vrail-h,190px) + 12px)}
  html[data-alt="1"] body.on-map #vrail{
    background:linear-gradient(to top,rgba(10,9,6,.82),rgba(10,9,6,.42) 62%,transparent)}
}
/* the focused pin earns a ring so the link to its card is obvious */
html[data-alt="1"] .dot.picked .pt{box-shadow:0 0 0 4px var(--terra),0 0 0 9px color-mix(in srgb,var(--terra) 34%, transparent),0 2px 14px rgba(0,0,0,.6)}
/* the card already names the home — pin labels would say it twice */
html[data-alt="1"] .dot .tag{display:none}
/* the rail carries its own instruction, and Grace's map bubble points at
   chips this mode doesn't have */
html[data-alt="1"] body.on-map #sel-head{display:none}
html[data-alt="1"] body.on-map #fab-bubble{display:none}


/* soft "turn your phone" nudge — dims the map and suggests landscape,
   auto-clears on rotation, never blocks (see maybeShowNudge()) */
#rotate-nudge{position:fixed;inset:0;z-index:60;display:none;flex-direction:column;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--well) 74%, transparent);backdrop-filter:blur(3px);color:var(--paper);text-align:center;
  padding:0 34px;opacity:0;transition:opacity .5s}
#rotate-nudge.on{display:flex;opacity:1}
.rn-phone{width:52px;height:92px;border:2px solid var(--paper);border-radius:11px;position:relative;margin-bottom:32px;
  transform-origin:50% 50%;animation:rn-tilt 2.8s var(--ease) infinite}
.rn-phone .rn-scr{position:absolute;inset:6px;border-radius:4px;background:color-mix(in srgb,var(--paper) 22%, transparent)}
@keyframes rn-tilt{0%,12%{transform:rotate(0)}40%,62%{transform:rotate(-90deg)}90%,100%{transform:rotate(0)}}
.rn-t{letter-spacing:var(--ls-wide);font-size:13px;text-transform:uppercase;font-weight:500}
.rn-s{font-style:italic;opacity:.82;margin-top:11px;font-size:16px;max-width:18em}
.rn-x{margin-top:34px;border:1px solid color-mix(in srgb,var(--paper) 55%, transparent);border-radius:99px;
  padding:11px 24px 12px;letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;color:var(--paper);transition:.3s}
.rn-x:hover{background:var(--paper);color:var(--ink)}
@media(prefers-reduced-motion:reduce){.rn-phone{animation:none;transform:rotate(-90deg)}}

/* landscape phone — height is the scarce axis: fold the bottom chip stack
   into a slim left rail, drop the walk arrows to the bottom-centre, and
   keep the legend out. Portrait keeps its tidy bottom bar (above). */
@media (orientation:landscape) and (max-height:520px) and (pointer:coarse){
  body.on-map #sel-chrome::after{height:120px}
  body.on-map #sel-bottom{top:50%;bottom:auto;left:12px;right:auto;transform:translateY(-50%);
    align-items:flex-start;gap:9px;padding:0}
  body.on-map #sel-bottom .chips{flex-direction:column;align-items:flex-start;flex-wrap:nowrap;gap:8px;justify-content:flex-start}
  body.on-map #sel-bottom #chips-main{order:-1}        /* Villas / Facilities toggle sits above its filters */
  body.on-map #sel-bottom .chips.sub{padding:0}
  body.on-map #sel-bottom .chips.sub.open{max-height:none}
  body.on-map #sel-legend{display:none}
  body.on-map #sel-head{top:calc(var(--nav-h) + 6px)}
  body.on-map #ang-left{left:50%;right:auto;margin-left:-52px;top:auto;bottom:10px;transform:none}
  body.on-map #ang-right{left:50%;right:auto;margin-left:8px;top:auto;bottom:10px;transform:none}
  body.on-map #fac-cta{bottom:74px}
  /* villa story: the scroll counter/cue share the bottom with the caption's
     label row on a short landscape stage — tuck them into the right corner,
     clear of the left-aligned caption. (Only one shows at a time.) */
  body #story-count{left:auto;right:18px;bottom:14px;transform:none}
  body #story-cue{left:auto;right:26px;bottom:14px;transform:none}
}

/* mobile tap card */
#tapcard{position:fixed;left:50%;bottom:70px;transform:translate(-50%,20px);opacity:0;pointer-events:none;
  background:var(--cream);color:var(--ink);border-radius:4px;padding:20px 24px;z-index:40;width:min(88vw,360px);
  transition:.4s;box-shadow:0 18px 60px rgba(0,0,0,.45)}
#tapcard.open{opacity:1;transform:translate(-50%,0);pointer-events:auto}
#tapcard .nm{letter-spacing:var(--ls);font-size:12px;text-transform:uppercase;font-weight:400}
#tapcard .st{font-style:italic;margin:4px 0 14px;opacity:.75}
#tapcard .go{display:inline-block;border:1px solid var(--ink);border-radius:99px;padding:9px 20px 10px;letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase}

/* editor */
/* the bar was --terra under --paper: sage behind sand, about 1.6:1. It is the
   one piece of chrome whose whole job is to be read while you work. */
#editor-bar{position:fixed;bottom:0;left:0;right:0;z-index:700;background:#11150C;color:#E6E1D1;
  border-top:1px solid rgba(230,225,209,.22);
  display:none;align-items:center;gap:18px;justify-content:center;padding:13px;flex-wrap:wrap}
#editor-bar.on{display:flex}
#editor-bar .caps{font-size:11px}
#editor-bar button{border:1px solid rgba(230,225,209,.55);border-radius:3px;padding:8px 15px;
  color:#E6E1D1;letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;cursor:pointer;
  background:transparent;transition:.2s}
#editor-bar .ed-btns{display:flex;gap:9px;flex:none}
#editor-bar #ed-view{font-family:var(--serif);font-style:italic;text-transform:none;
  letter-spacing:0;font-size:14px;margin-left:12px;color:#D8B24A}
@media(hover:hover){#editor-bar button:hover{background:#E6E1D1;color:#11150C;border-color:#E6E1D1}}

/* ==========================================================================
   EDIT MODE — every pin reachable, named, and draggable.
   The design pass made reserved and sold pins pointer-events:none, faded the
   out-of-group ones to 16%, hid every label and parked a 420px rail over the
   left third of the map. All four are correct for a buyer and all four make
   the editor unusable, so edit mode undoes them — scoped to body.editing so
   none of it can leak into the real page.
   ========================================================================== */
html[data-alt="1"] body.editing .dot,
html[data-alt="1"] body.editing .dot .pt,
html[data-alt="1"] body.editing .dot .plot{pointer-events:auto}
html[data-alt="1"] body.editing .dot{opacity:1 !important;cursor:grab}
html[data-alt="1"] body.editing .dot.editing:active{cursor:grabbing}
html[data-alt="1"] body.editing .dot .pt{width:15px;height:15px;
  background:#D8B24A;box-shadow:0 0 0 3px rgba(17,21,12,.75),0 0 0 4px rgba(216,178,74,.5)}
html[data-alt="1"] body.editing .dot.amen .pt{background:#9BD1E8}
html[data-alt="1"] body.editing .dot .pt::after{display:none}     /* no pulse while aiming */
html[data-alt="1"] body.editing .dot .plot{opacity:.55}
/* every pin says what it is, all the time — you cannot place what you cannot name */
html[data-alt="1"] body.editing .dot .tag{display:block;opacity:1;pointer-events:none;
  transform:translate(calc(-50% + var(--tagdx,0px)),0)}
html[data-alt="1"] body.editing .dot .tag .nm{font-family:var(--sans);font-size:9.5px;
  letter-spacing:var(--ls);text-transform:uppercase}
html[data-alt="1"] body.editing .dot .tag .fx{display:none}
/* the rail and the reopen tab are 420px of map you cannot reach */
html[data-alt="1"] body.editing #vrail,
html[data-alt="1"] body.editing #c-fab,
html[data-alt="1"] body.editing #g-bubble{display:none}
body.editing #map-wrap{bottom:0}

/* ============================================================
   VILLA STORY overlay
   ============================================================ */
#story{position:relative;z-index:80;background:transparent}
#story .exit{position:fixed;top:calc(var(--nav-h) + 10px);left:26px;z-index:90;color:var(--paper);
  display:flex;gap:10px;align-items:center;letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;font-weight:400;
  background:color-mix(in srgb,var(--well) 45%, transparent);backdrop-filter:blur(8px);border-radius:99px;padding:9px 18px 10px;transition:.3s}
#story .exit:hover{background:var(--ink)}
.story-end{background:var(--cream);position:relative}

#story .fstage::before{content:"";position:absolute;inset:0 0 auto 0;height:130px;z-index:65;pointer-events:none;
  background:linear-gradient(to bottom,rgba(10,9,6,.5),transparent)}

/* scroll affordance inside a villa story */
#story-cue{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);z-index:95;color:var(--paper);
  display:flex;flex-direction:column;align-items:center;gap:11px;pointer-events:none;transition:opacity .6s;
  text-shadow:0 1px 12px rgba(0,0,0,.6)}
#story-cue .caps{font-size:11.5px;letter-spacing:var(--ls-wide);opacity:1;font-weight:500;text-shadow:0 1px 4px rgba(0,0,0,.8)}
.cue-line{width:1px;height:46px;background:color-mix(in srgb,var(--paper) 38%, transparent);position:relative;overflow:visible}
.cue-line i{position:absolute;left:50%;top:0;width:7px;height:7px;margin-left:-3.5px;border-radius:50%;
  background:var(--paper);box-shadow:0 0 10px rgba(232,221,198,.8);animation:cuedrop 2.3s infinite cubic-bezier(.45,0,.55,1)}
@keyframes cuedrop{0%{transform:translateY(-4px);opacity:0}18%{opacity:1}72%{opacity:1}100%{transform:translateY(44px);opacity:0}}
@media(prefers-reduced-motion:reduce){.cue-line i{animation:none;top:auto;bottom:0}}
#story-count{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:95;color:var(--paper);
  background:color-mix(in srgb,var(--well) 45%, transparent);backdrop-filter:blur(8px);border-radius:99px;
  padding:8px 18px 9px;font-size:11.5px;letter-spacing:var(--ls-wide);text-transform:uppercase;font-weight:500;
  pointer-events:none;transition:opacity .5s;white-space:nowrap}

/* facts sheet */
.facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:0;border-top:1px solid rgba(230,225,209,.16);border-bottom:1px solid rgba(230,225,209,.16)}
.facts>div{padding:16px 20px 17px}
/* villa spec — one tight row, no wrapping to a lonely second line */
.facts.specrow{grid-template-columns:repeat(6,1fr)}
.facts.specrow>div{padding:13px 14px 14px}
.facts.specrow .k{min-height:0;margin-bottom:5px;font-size:10.5px}
.facts.specrow .v{font-size:clamp(15px,1.35vw,19px);line-height:1.25}
.facts.specrow .v small{font-size:65%}
@media(max-width:900px){.facts.specrow{grid-template-columns:repeat(3,1fr)}}
@media(max-width:480px){.facts.specrow{grid-template-columns:repeat(2,1fr)}}
.facts .k{letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;font-weight:500;color:var(--dim);margin-bottom:6px;min-height:2.4em;line-height:1.2}
.facts .v{font-size:clamp(20px,1.9vw,26px)}
.facts .v small{font-size:70%;color:var(--dim)}
.facts .sub{margin-top:3px;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}

/* milestones */
.miles{display:flex;gap:0;margin-top:26px;border-left:1px solid rgba(230,225,209,.2)}
.miles>div{flex:1;padding:0 18px 6px;border-right:1px solid rgba(230,225,209,.2)}
.miles .pct{font-size:clamp(26px,3vw,40px)}
.miles .k{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;color:var(--dim);margin-top:2px}
@media(max-width:820px){.miles{flex-direction:column;border-left:none;border-top:1px solid rgba(230,225,209,.2)}
 .miles>div{border-right:none;border-bottom:1px solid rgba(230,225,209,.2);padding:14px 4px}}

/* CTA row */
.cta-row{display:flex;gap:16px;flex-wrap:wrap;margin-top:44px}
.btn{display:inline-flex;align-items:center;gap:10px;border:1px solid var(--ink);border-radius:99px;
  padding:14px 30px 15px;letter-spacing:var(--ls);font-size:12.5px;text-transform:uppercase;font-weight:400;transition:.3s}
/* NOTE — every .btn :hover declaration lives in ONE place now, the
   @media(hover:hover) block in the SWV section further down. The four that
   used to sit here were dead: the later block overrode all of them, and
   leaving them behind meant a coarse-pointer device (where the later block
   is gated off) fell back to a *different* hover skin. */
.btn.solid{background:var(--ink);color:var(--cream)}
.btn.paper{border-color:var(--paper);color:var(--paper)}
/* terra/ghost pair — save-form "Save & send" + /talk's primary CTA (terra),
   paired with their neighboring secondary action (ghost) — scoped to these
   two spots only (design-returns-v3 §7); .btn/.btn.solid elsewhere untouched. */
.btn.terra{background:var(--terra);border-color:var(--terra);color:var(--cream);padding:16px 30px;letter-spacing:var(--ls);font-size:12px}
.btn.ghost{padding:16px 30px;letter-spacing:var(--ls);font-size:12px}

/* pack cards — unreferenced since the packs were removed; kept only
   because .packs/.pack still style nothing and cost nothing */
.packs{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;align-items:stretch}
@media(max-width:960px){.packs{grid-template-columns:1fr}}
.pack{border-radius:4px;padding:38px 34px 34px;color:var(--paper);display:flex;flex-direction:column;min-height:420px;position:relative;overflow:hidden}
.pack.stone{background:var(--stone)}.pack.midnight{background:var(--midnight)}.pack.terra{background:var(--terra)}
.pack .grain{position:absolute;inset:0;opacity:.5;pointer-events:none;background-size:cover}
.pack>*{position:relative}
.pack .nm{font-size:clamp(26px,2.4vw,34px);margin:6px 0 2px}
.pack .pr{font-style:italic;opacity:.85;margin-bottom:20px}
.pack ul{list-style:none;display:flex;flex-direction:column;gap:9px;margin-bottom:26px}
.pack li{padding-left:20px;position:relative;font-size:18px;line-height:1.45}
.pack li::before{content:"—";position:absolute;left:0;opacity:.6}
.pack .pick{margin-top:auto;border:1px solid var(--paper);border-radius:99px;padding:11px 24px 12px;
  letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;color:var(--paper);align-self:flex-start;transition:.3s}
.pack .pick:hover,.pack .pick.picked{background:var(--paper);color:var(--ink)}

/* materials */
.mats{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:26px}
.mat .sw{height:150px;border-radius:3px;margin-bottom:14px;position:relative;overflow:hidden}
.mat .sw::after{content:"";position:absolute;inset:0;background:
  radial-gradient(120% 90% at 20% 0%,rgba(255,255,255,.14),transparent 55%),
  radial-gradient(130% 100% at 85% 100%,rgba(0,0,0,.18),transparent 60%)}
.mat .nm{font-size:21px}
.mat .wh{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;color:var(--dim);margin:3px 0 6px}
.mat .no{font-size:17px;opacity:.88;line-height:1.5}

/* inclusions */
.incl{columns:2;column-gap:64px}
@media(max-width:900px){.incl{columns:1}}
.incl .cat{break-inside:avoid;margin-bottom:38px}
.incl .cat h3{font-size:24px;margin-bottom:12px}
.incl ul{list-style:none}
.incl li{padding:9px 0 9px 24px;border-bottom:1px solid rgba(230,225,209,.12);position:relative;font-size:18px}
.incl li::before{content:"—";position:absolute;left:0;opacity:.5}

/* facilities sheet (full directory over the masterplan) */
#fac-sheet{position:fixed;inset:0;z-index:900;background:color-mix(in srgb,var(--well) 45%, transparent);
  opacity:0;pointer-events:none;transition:opacity .45s;display:flex;justify-content:center;align-items:flex-end}
#fac-sheet.open{opacity:1;pointer-events:auto}
#fac-sheet .fs-inner{background:var(--cream);color:var(--ink);width:min(1060px,100vw);max-height:88vh;overflow-y:auto;
  border-radius:6px 6px 0 0;padding:56px 6vw 48px;position:relative;transform:translateY(30px);transition:transform .5s var(--ease)}
#fac-sheet.open .fs-inner{transform:none}
#fac-sheet .fs-x{position:absolute;top:18px;right:22px;font-size:17px;opacity:.6;padding:8px}
#fac-sheet .fs-x:hover{opacity:1}
#fac-sheet .fs-imgs{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:44px}
#fac-sheet .fs-imgs img{border-radius:3px;aspect-ratio:4/3;object-fit:cover;width:100%}
#fac-sheet .fs-imgs figcaption{margin-top:8px;opacity:.55;font-size:10px}
#fac-sheet .cta-row{margin-top:40px}
@media(max-width:800px){#fac-sheet .fs-imgs{grid-template-columns:1fr}}

/* the idea — founders' film */
.film-wrap{padding:40px 7vw 0;max-width:1280px;margin:0 auto}
.film{position:relative;border-radius:5px;overflow:hidden;aspect-ratio:16/8.2;min-height:340px;background:var(--well)}
.film img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.85}
.film-veil{position:absolute;inset:0;background:radial-gradient(80% 80% at 50% 55%,rgba(10,9,6,.62),rgba(10,9,6,.28))}
.film-mid{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;color:var(--paper);text-align:center;padding:0 24px}
.film-mid .lead{max-width:26em;opacity:.92}
.play{width:84px;height:84px;border-radius:50%;border:1px solid color-mix(in srgb,var(--paper) 70%, transparent);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px);transition:.35s}
.play i{width:0;height:0;border-left:18px solid var(--paper);border-top:11px solid transparent;border-bottom:11px solid transparent;margin-left:5px}
.film.ready{cursor:pointer}
.film.ready:hover .play{transform:scale(1.07);background:color-mix(in srgb,var(--paper) 14%, transparent)}
.film.waiting .play{opacity:.55}
.film.waiting .play i{opacity:.7}
.film.waiting::after{content:"IN PRODUCTION";position:absolute;top:18px;right:20px;color:var(--paper);
  letter-spacing:var(--ls-wide);font-size:10px;border:1px solid color-mix(in srgb,var(--paper) 50%, transparent);
  border-radius:99px;padding:6px 13px 7px;opacity:.85}
@media(max-width:700px){.film{aspect-ratio:4/5}}

/* facilities directory */
.facl{display:grid;grid-template-columns:1fr 1fr;gap:0 64px}
@media(max-width:900px){.facl{grid-template-columns:1fr}}
.fac{padding:20px 0 21px;border-bottom:1px solid rgba(230,225,209,.12)}
.fac .fn{font-size:22px;display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.fac .fs{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:400;opacity:.55;border:1px solid rgba(230,225,209,.3);border-radius:99px;padding:3px 10px 4px}
.fac .fl{font-size:17.5px;opacity:.85;margin-top:4px;max-width:34em}

/* journey */
.journey{display:flex;flex-direction:column;gap:0;border-left:1px solid rgba(230,225,209,.22);margin-left:6px}
.jstep{padding:0 0 46px 40px;position:relative}
.jstep::before{content:"";position:absolute;left:-6px;top:8px;width:11px;height:11px;border-radius:50%;background:var(--ink)}
.jstep .k{letter-spacing:var(--ls-wide);font-size:11.5px;text-transform:uppercase;font-weight:500;color:var(--dim)}
.jstep h3{font-size:clamp(24px,2.4vw,32px);margin:4px 0 8px}
.jstep p{max-width:34em}
.jstep .pay{font-style:italic;opacity:.75;margin-top:8px}

/* ============================================================
   CONCIERGE
   ============================================================ */
#c-fab{position:fixed;right:26px;bottom:26px;z-index:800;background:var(--ink);color:var(--paper);
  border-radius:99px;padding:15px 26px 16px;display:flex;gap:12px;align-items:center;
  letter-spacing:var(--ls);font-size:12px;text-transform:uppercase;font-weight:400;
  box-shadow:0 14px 40px rgba(0,0,0,.35);transition:.3s}
#c-fab:hover{transform:translateY(-2px)}
#c-fab .pt{width:8px;height:8px;border-radius:50%;background:var(--paper);animation:pulse2 2.6s infinite}
/* the note Grace leaves by her icon — persistent, tappable (opens the chat) */
.fab-bubble{position:fixed;right:26px;bottom:96px;z-index:805;max-width:250px;
  display:flex;align-items:flex-start;gap:6px;
  background:var(--paper);color:var(--ink);font-family:var(--serif);font-size:15.5px;
  font-style:italic;line-height:1.42;padding:11px 12px 12px 16px;border-radius:14px 14px 5px 14px;
  box-shadow:0 14px 38px rgba(0,0,0,.34);opacity:0;transform:translateY(10px) scale(.96);
  transform-origin:bottom right;transition:opacity .42s var(--ease),transform .42s var(--ease),box-shadow .3s;
  pointer-events:none;cursor:pointer}
.fab-bubble.show{opacity:1;transform:none;pointer-events:auto}
.fab-bubble:hover{box-shadow:0 18px 48px rgba(0,0,0,.44)}
.fab-bubble-t{flex:1}
/* brand: one family, ever. The glyph is U+00D7, which Cormorant carries — the
   old system-ui declaration pushed the only sans face on the page. font-style
   still resets, because the bubble around it is italic. */
.fab-bubble-x{flex:none;font-style:normal;font-size:17px;line-height:1;
  opacity:.55;padding:0 2px;margin-top:1px;color:var(--ink);transition:opacity .2s}
.fab-bubble-x:hover{opacity:.8}
@media(max-width:600px){.fab-bubble{right:14px;bottom:80px;max-width:220px}}
/* the Villas / Facilities toggle pulses when Grace invites exploration */
@keyframes gblink{0%,100%{box-shadow:0 0 0 1px color-mix(in srgb,var(--paper) 28%, transparent)}
  50%{box-shadow:0 0 0 1px var(--paper),0 0 15px 2px color-mix(in srgb,var(--paper) 45%, transparent)}}
#chips-main.blink .gchip{animation:gblink 1.6s var(--ease) infinite}
@keyframes pulse2{0%,100%{opacity:1}50%{opacity:.35}}
#c-panel{position:fixed;right:22px;bottom:22px;z-index:810;width:min(430px,calc(100vw - 32px));
  height:min(640px,calc(100vh - 44px));height:min(640px,calc(100dvh - 44px));background:var(--midnight);color:var(--paper);border-radius:6px;
  display:flex;flex-direction:column;overflow:hidden;box-shadow:0 30px 90px rgba(0,0,0,.5);
  transform:translateY(24px);opacity:0;pointer-events:none;transition:.45s var(--ease)}
#c-panel.open{transform:none;opacity:1;pointer-events:auto}
/* When Grace is open on a wide screen her panel (fixed, bottom-right, ~452px)
   sits over the right of the reading column. The full-bleed chart band uses
   100vw and must not be reparented, so instead of shifting .sec we rein in the
   boxed figure blocks that carry right-aligned numbers — the P&L, the tiles,
   the sliders — so nothing they show slides under the chat. */
@media(min-width:1024px){
  body.chat-open .pgtiles{grid-template-columns:1fr 1fr;max-width:600px}
  body.chat-open .pnlwrap{max-width:520px}
  body.chat-open .pgsliders{max-width:520px}
  body.chat-open .rt-hero{max-width:620px}
}
#c-grain{position:absolute;inset:0;opacity:.75;pointer-events:none;background-size:cover}
#c-panel>*{position:relative}
#c-head{display:flex;align-items:center;justify-content:space-between;padding:20px 22px 16px;border-bottom:1px solid color-mix(in srgb,var(--paper) 18%, transparent)}
#c-head .t .caps{font-size:11px;opacity:.75}
#c-head .t .nm{font-size:21px}
#c-head .ops{display:flex;gap:6px}
#c-head button{opacity:.7;padding:6px;font-size:15px;transition:.3s}
#c-head button:hover{opacity:1}
#c-msgs{flex:1;overflow-y:auto;padding:20px 22px;display:flex;flex-direction:column;gap:14px;scrollbar-width:thin}
/* Cormorant is a light display serif; on the dark panel it reads thin, so the
   chat body is set a touch larger, at full weight, with a little tracking and a
   hairline same-colour shadow to firm up the strokes on dark. */
.msg{max-width:88%;line-height:1.62;font-size:19px;font-weight:400;letter-spacing:.006em}
.msg.you{align-self:flex-end;background:color-mix(in srgb,var(--paper) 14%, transparent);padding:11px 16px 12px;border-radius:4px}
.msg.ag{align-self:flex-start;text-shadow:0 0 .4px color-mix(in srgb,var(--paper) 50%, transparent)}
.msg.ag .who{letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:400;opacity:.62;display:block;margin-bottom:4px}
.msg.ag a{border-bottom:1px solid color-mix(in srgb,var(--paper) 45%, transparent)}
.msg .act{display:inline-block;margin-top:8px;border:1px solid color-mix(in srgb,var(--paper) 55%, transparent);border-radius:99px;
  padding:6px 14px 7px;letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;transition:.3s;cursor:pointer}
.msg .act:hover{background:var(--paper);color:var(--midnight)}
.msg .gline{font-style:italic;font-size:14.5px;opacity:.72;margin-top:8px}
/* guided qualification: stacked quick-reply options + inline lead capture */
.qopts{display:flex;flex-direction:column;gap:8px;align-self:stretch;margin-top:4px}
.qopt{text-align:left;border:1px solid color-mix(in srgb,var(--paper) 38%, transparent);border-radius:7px;
  padding:11px 15px;color:var(--paper);font-size:16.5px;line-height:1.42;transition:.22s;
  background:color-mix(in srgb,var(--paper) 5%, transparent)}
.qopt:hover{background:color-mix(in srgb,var(--paper) 15%, transparent);border-color:var(--paper)}
.c-capture{display:flex;flex-direction:column;gap:9px;margin-top:10px;align-self:stretch}
.c-capture input{background:color-mix(in srgb,var(--paper) 10%, transparent);border:1px solid color-mix(in srgb,var(--paper) 25%, transparent);
  border-radius:4px;color:var(--paper);font-family:inherit;font-size:16px;padding:11px 13px;outline:none}
.c-capture input::placeholder{color:color-mix(in srgb,var(--paper) 55%, transparent);font-style:italic}
.c-capture button{border:1px solid var(--paper);border-radius:99px;padding:9px 18px 10px;letter-spacing:var(--ls);
  font-size:11px;text-transform:uppercase;color:var(--paper);align-self:flex-start;transition:.3s}
.c-capture button:hover{background:var(--paper);color:var(--midnight)}
.c-capture button[disabled]{opacity:.55}
.c-capture .ok{font-style:italic;opacity:.85;font-size:14.5px}
/* Grace shares an image in-chat — tap to open the fullscreen lightbox */
.c-img{display:block;width:100%;margin-top:8px;border-radius:6px;overflow:hidden;
  border:1px solid color-mix(in srgb,var(--paper) 20%, transparent);text-align:left;transition:.25s;background:none}
.c-img:hover{border-color:color-mix(in srgb,var(--paper) 55%, transparent)}
.c-img img{width:100%;display:block}
.c-img .c-img-cap{display:block;padding:8px 12px 9px;font-size:10px;opacity:.7;letter-spacing:var(--ls);text-transform:uppercase}
#c-panel.half{height:min(46vh,420px)}
#c-panel.half #c-chips,#c-panel.half #c-note{display:none}
#c-head{cursor:pointer}
.typing{display:flex;gap:5px;padding:6px 0}
.typing i{width:6px;height:6px;border-radius:50%;background:var(--paper);opacity:.4;animation:ty 1.2s infinite}
.typing i:nth-child(2){animation-delay:.18s}.typing i:nth-child(3){animation-delay:.36s}
@keyframes ty{0%,100%{opacity:.25;transform:none}50%{opacity:1;transform:translateY(-3px)}}
#c-chips{display:flex;gap:8px;padding:0 22px 12px;flex-wrap:wrap}
#c-chips button{border:1px solid color-mix(in srgb,var(--paper) 40%, transparent);border-radius:99px;
  padding:7px 14px 8px;font-size:13.5px;font-style:italic;color:var(--paper);opacity:.9;transition:.3s}
#c-chips button:hover{background:color-mix(in srgb,var(--paper) 14%, transparent)}
#c-inrow{display:flex;gap:10px;padding:14px 18px 18px;border-top:1px solid color-mix(in srgb,var(--paper) 18%, transparent)}
#c-in{flex:1;background:color-mix(in srgb,var(--paper) 10%, transparent);border:1px solid color-mix(in srgb,var(--paper) 25%, transparent);
  border-radius:3px;color:var(--paper);font-family:inherit;font-size:16.5px;padding:12px 14px;outline:none}
#c-in::placeholder{color:color-mix(in srgb,var(--paper) 55%, transparent);font-style:italic}
#c-send{border:1px solid var(--paper);border-radius:99px;padding:0 22px;letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;color:var(--paper);transition:.3s}
#c-send:hover{background:var(--paper);color:var(--midnight)}
#c-note{padding:0 22px 14px;font-size:13.5px;font-style:italic;opacity:.82}
#c-key{padding:14px 22px;border-top:1px solid color-mix(in srgb,var(--paper) 18%, transparent);display:none;flex-direction:column;gap:9px}
#c-key.open{display:flex}
#c-key input{background:color-mix(in srgb,var(--paper) 10%, transparent);border:1px solid color-mix(in srgb,var(--paper) 25%, transparent);
  border-radius:3px;color:var(--paper);font-family:inherit;font-size:14px;padding:9px 12px;outline:none}
#c-key .caps{font-size:10px;opacity:.7}
@media(max-width:600px){#c-panel{right:8px;bottom:8px;width:calc(100vw - 16px);height:calc(100vh - 70px);height:calc(100dvh - 70px)}#c-fab{right:16px;bottom:16px}}

/* v23 A1 — icon-only fab on narrow screens: the pill+label footprint was
   colliding with real content (NOI value, occupancy slider, proof-band
   lines, accordion rows — design-polish-v23 §A). Cuts the footprint by
   roughly two thirds; the dot glyph (.pt) stays as the only visible child. */
@media(max-width:860px){
  #c-fab .lbl{display:none}
  #c-fab{width:52px;height:52px;padding:0;border-radius:50%;right:14px;bottom:14px;display:grid;place-items:center}
}
/* v23 A2 — the fab steps out of the way while the reader is actively
   scrolling and returns 900ms after they stop (see the scroll listener near
   the end of the script) — never while the chat panel (#c-panel.open) is
   open, since that already hides the fab outright via openChat(). */
#c-fab{transition:transform .28s ease, opacity .28s ease}
#c-fab.c-fab-away{transform:translateY(96px);opacity:0;pointer-events:none}
@media (prefers-reduced-motion:reduce){
  #c-fab{transition:opacity .01s linear}
  #c-fab.c-fab-away{transform:none;opacity:0}
}

/* proactive Grace bubble — rises from the fab with a context offer, once per
   context per session, replacing the scattered "Ask Grace" buttons. */
#g-bubble{position:fixed;right:24px;bottom:94px;z-index:805;max-width:min(282px,calc(100vw - 40px));
  background:var(--cream);color:var(--ink);border-radius:13px 13px 4px 13px;padding:13px 30px 14px 16px;
  box-shadow:0 16px 46px rgba(0,0,0,.30);opacity:0;transform:translateY(10px) scale(.96);transform-origin:bottom right;
  transition:.4s var(--ease);pointer-events:none;cursor:pointer}
#g-bubble.on{opacity:1;transform:none;pointer-events:auto}
#g-bubble .gb-who{letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:600;color:var(--terra);margin-bottom:4px}
#g-bubble .gb-txt{font-size:15px;line-height:1.42}
#g-bubble .gb-x{position:absolute;top:7px;right:9px;font-size:13px;opacity:.4;padding:4px;line-height:1}
#g-bubble .gb-x:hover{opacity:.9}
#g-bubble::after{content:"";position:absolute;right:20px;bottom:-6px;width:13px;height:13px;background:var(--cream);transform:rotate(45deg);border-radius:0 0 3px 0}
@media(max-width:860px){#g-bubble{right:14px;bottom:76px}}
@media(prefers-reduced-motion:reduce){#g-bubble{transition:opacity .2s}}

/* ============================================================
   MY VILLA
   ============================================================ */
.mine-hero{position:relative;min-height:72vh;min-height:72dvh;display:flex;align-items:flex-end;overflow:hidden}
.mine-hero img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.mine-hero .scrim{position:absolute}
.steps{display:flex;flex-direction:column}
.step{display:flex;gap:22px;padding:20px 0;border-bottom:1px solid rgba(230,225,209,.12);align-items:baseline}
.step .n{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;opacity:.5;min-width:70px}
.step .t{font-size:20px}
.step .s{margin-left:auto;font-style:italic;opacity:.7;font-size:16px;white-space:nowrap}
.step.done .t{opacity:.5;text-decoration:line-through;text-decoration-thickness:.5px}

/* villa details — gallery + lightbox */
.gal{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:16px}
.gal figure{cursor:zoom-in;overflow:hidden;border-radius:3px;position:relative}
.gal img{width:100%;aspect-ratio:4/3;object-fit:cover;transition:transform .6s var(--ease)}
.gal figure:hover img{transform:scale(1.04)}
.gal figcaption{position:absolute;left:0;right:0;bottom:0;padding:26px 12px 10px;color:var(--paper);font-size:10px;
  background:linear-gradient(to top,rgba(10,9,6,.65),transparent);letter-spacing:var(--ls)}
#lightbox{position:fixed;inset:0;z-index:950;background:color-mix(in srgb,var(--well) 94%, transparent);
  display:flex;align-items:center;justify-content:center;opacity:0;pointer-events:none;transition:opacity .35s}
#lightbox.open{opacity:1;pointer-events:auto}
#lightbox .lb-stage{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;overflow:hidden;touch-action:none}
#lightbox img{max-width:92vw;max-height:84vh;object-fit:contain;box-shadow:0 30px 90px rgba(0,0,0,.6);
  will-change:transform;cursor:zoom-in;user-select:none;-webkit-user-drag:none}
#lightbox.zoomed img{cursor:grab}
#lightbox.grabbing img{cursor:grabbing}
#lightbox .lb-hint{position:absolute;top:18px;left:0;right:0;text-align:center;color:var(--paper);font-size:10px;letter-spacing:var(--ls-wide);opacity:.5;pointer-events:none;transition:opacity .3s}
#lightbox.zoomed .lb-hint{opacity:0}
#lightbox .lb-cap{position:absolute;bottom:26px;left:0;right:0;text-align:center;color:var(--paper);font-size:11px;opacity:.85;pointer-events:none}
#lightbox button{position:absolute;color:var(--paper);font-size:26px;padding:14px;opacity:.75;transition:.3s;z-index:2}
#lightbox button:hover{opacity:1}
#lightbox .lb-x{top:16px;right:20px;font-size:20px}
#lightbox .lb-p{left:14px;top:50%;transform:translateY(-50%)}
#lightbox .lb-n{right:14px;top:50%;transform:translateY(-50%)}
.plans-grid svg{background:var(--cream)}

/* villa details */
/* clean text header for the individual study chapters (no image) */
.dhead{background:var(--cream);color:var(--ink);padding:calc(var(--nav-h) + 30px) 7vw 22px}
.dhead .over{letter-spacing:var(--ls-wide);font-size:12px;text-transform:uppercase;font-weight:500;color:var(--terra);margin-bottom:10px}
.dhead .dhead-line{font-family:var(--serif);font-size:clamp(27px,4vw,40px);line-height:1.1;margin-bottom:18px}
.dhead .labels{display:flex;flex-wrap:wrap;gap:8px 30px}
.dhead .labels span{letter-spacing:var(--ls);font-size:12px;text-transform:uppercase;font-weight:500;opacity:.82}
.dhead .labels b{font-weight:600;opacity:1}
.dhero{position:relative;height:54vh;height:54dvh;min-height:340px;overflow:hidden}
.dhero img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.plans-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:30px}
.plans-grid figure{background:color-mix(in srgb,var(--ink) 3%, var(--cream));border:1px solid rgba(230,225,209,.12);
  border-radius:4px;padding:26px 26px 20px;display:flex;flex-direction:column;gap:16px}
.plans-grid img{width:100%;max-height:56vh;object-fit:contain}
.plans-grid figcaption{font-size:16px;font-style:italic;opacity:.75;line-height:1.5}

/* footer */
footer{background:var(--cream);padding:100px 7vw 60px;border-top:1px solid rgba(230,225,209,.1)}
footer .inner{max-width:1280px;margin:0 auto}
.foot-grid{display:flex;justify-content:space-between;gap:40px;flex-wrap:wrap;margin-bottom:70px}
.foot-grid .caps{opacity:.6;margin-bottom:10px;font-size:11px}
.foot-grid p{font-size:17.5px;max-width:26em}
.sig{display:flex;justify-content:flex-end}
.sig svg,.sig img{height:56px;width:auto}
.smallprint{font-size:14px;color:var(--dim);font-style:italic;margin-top:26px;max-width:52em}
.footnav{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:56px}
.footnav button{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;color:var(--dim-soft);transition:.25s}
.footnav button:hover{color:var(--ink)}
.footnav .fnsep{color:color-mix(in srgb,var(--paper) 62%, transparent);opacity:.4;font-size:11px}

/* hero (cover) */
#v-cover .hero{position:relative;height:100vh;height:100dvh;overflow:hidden;background:var(--well);touch-action:pan-y}
@media(hover:hover) and (pointer:fine){
  #v-cover .hero,#v-cover .hero .mid{cursor:grab}
  #v-cover .hero.cover-grabbing,#v-cover .hero.cover-grabbing .mid{cursor:grabbing}
  #v-cover .ctas *{cursor:pointer}
}
#v-cover .hero > img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* The design's .cover-veil, not the portal's old one. The old scrim put .5 of
   near-black over the middle of the picture and .12-.3 across the rest; the
   whole cover measured 25% darker than the design and the village read as a
   photograph behind glass. The design darkens only the two bands it needs —
   the top for the mark and burger, the foot for the buttons — and lets the
   middle two thirds be the picture. */
#v-cover .hero .veil{position:absolute;inset:0;background:
  linear-gradient(to bottom,
    rgba(10,9,6,.62) 0%,
    rgba(10,9,6,.22) 15%,
    rgba(10,9,6,.02) 34%,
    rgba(10,9,6,.06) 62%,
    rgba(10,9,6,.62) 100%),
  radial-gradient(120% 80% at 50% 58%,rgba(10,9,6,.26) 0%,rgba(10,9,6,.04) 46%,rgba(10,9,6,.34) 100%)}
#v-cover .hero .mid{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--paper);text-align:center;padding:0 20px}
#v-cover .essence{height:120px;margin-bottom:26px;opacity:.9}
#v-cover .essence svg{height:100%;width:auto}
#v-cover .hero .over{letter-spacing:var(--ls-wide);font-size:12.5px;text-transform:uppercase;font-weight:400;opacity:.85;margin-bottom:18px}
#v-cover .hero .lead{margin-top:22px;opacity:.9;max-width:26em}
#v-cover .hero .ctas{margin-top:44px;display:flex;gap:16px;flex-wrap:wrap;justify-content:center}
#v-cover .scroll-cue{position:absolute;bottom:30px;left:50%;transform:translateX(-50%);color:var(--paper);opacity:.7;letter-spacing:var(--ls-wide);font-size:10.5px;text-transform:uppercase}

/* reveal-on-scroll */
.rv{opacity:0;transform:translateY(26px);transition:opacity .9s var(--ease),transform .9s var(--ease)}
.rv.in{opacity:1;transform:none}

/* reduced motion */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important;scroll-behavior:auto!important}
  .rv{opacity:1;transform:none}
}


/* ============================================================
   V15 — THE STUDY (chaptered villa details)
   ============================================================ */
.dhero.slim{height:30vh;height:30dvh;min-height:230px}
.chbar{position:sticky;top:var(--nav-h);z-index:560;background:rgba(17,21,12,.96);
  backdrop-filter:blur(10px);border-bottom:1px solid rgba(230,225,209,.14);
  display:flex;align-items:center;gap:8px;padding:0 7vw}
.chbar-scroll{display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;padding:14px 0;flex:1}
.chbar-scroll::-webkit-scrollbar{display:none}
.cbhome,.cbchip,.cbtalk{white-space:nowrap;letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;
  padding:14px 16px 15px;border-radius:99px;border:1px solid rgba(230,225,209,.22);color:var(--ink);opacity:.78;transition:.3s;
  box-sizing:border-box;display:inline-flex;align-items:center;position:relative}
.cbhome:hover,.cbchip:hover,.cbtalk:hover{opacity:1;border-color:rgba(230,225,209,.5)}
.cbchip.active{background:var(--ink);color:var(--cream);opacity:1;border-color:var(--ink)}
.cbchip.visited::after{content:"";position:absolute;left:50%;bottom:-8px;transform:translateX(-50%);
  width:4px;height:4px;border-radius:50%;background:var(--terra)}
.cbtalk{margin-left:auto;flex-shrink:0;border-color:var(--terra);color:var(--terra);opacity:1}
.cbtalk:hover,.cbtalk.active{background:var(--terra);color:var(--cream)}
@media(max-width:700px){.chbar{padding:0 5vw}.cbtalk{margin-left:10px}}

/* villa switcher — the leftmost chip toggles a dropdown: this villa's study,
   the six for sale, the founders'. #vsw-btn stays INSIDE .chbar-scroll (it's
   simply the first scrollable chip, so that row keeps its original flex:1
   width share on narrow screens); #vsw-menu is an independent position:fixed
   sibling of .chbar, positioned in JS from getBoundingClientRect() at
   open-time. position:fixed escapes .chbar-scroll's overflow-x:auto (which
   per spec also forces overflow-y to compute as auto, clipping any
   absolutely-positioned descendant) without stealing layout width from the
   chip row the way an extra non-scrolling flex sibling would. */
.vsw-menu{position:fixed;z-index:570;background:var(--cream);
  border:1px solid rgba(230,225,209,.22);border-radius:6px;box-shadow:0 18px 44px -20px rgba(23,20,15,.4);
  max-width:340px;min-width:280px;max-height:70vh;overflow-y:auto;padding:8px 0}
.vsw-menu[hidden]{display:none}
.vsw-item{display:flex;width:100%;justify-content:space-between;align-items:baseline;gap:16px;
  text-align:left;padding:11px 22px;font-size:13px;transition:.2s}
.vsw-item:hover{background:rgba(230,225,209,.05)}
.vsw-item.vsw-study{letter-spacing:var(--ls);font-size:11.5px;text-transform:uppercase;padding:13px 22px;opacity:.85}
.vsw-item.vsw-study:hover{opacity:1}
.vsw-name{letter-spacing:.03em;font-size:12.5px;text-transform:uppercase;display:inline-flex;align-items:center;gap:8px}
.vsw-item.mine .vsw-name{color:var(--terra)}
.vsw-dot{width:6px;height:6px;border-radius:50%;background:var(--terra);flex:none}
.vsw-price{font-family:var(--serif);font-size:15px;white-space:nowrap}
.vsw-price.on-request{font-style:italic;color:color-mix(in srgb,var(--paper) 62%, transparent);font-size:13px;text-transform:none;letter-spacing:normal}
.vsw-head{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent);opacity:.85;padding:14px 22px 6px}
.vsw-rule{height:1px;background:rgba(230,225,209,.14);margin:6px 0}
@media(max-width:700px){
  .vsw-menu{left:0;right:0;max-width:none;min-width:0;border-radius:0;
    box-shadow:0 18px 44px -12px rgba(23,20,15,.4)}
}

.doorcard{display:block;width:100%;text-align:left;border:1px solid var(--terra);border-radius:5px;
  padding:32px 30px;background:color-mix(in srgb,var(--terra) 7%, transparent);transition:.3s;margin-top:6px}
.doorcard:hover{background:color-mix(in srgb,var(--terra) 13%, transparent)}
.doorcard .over{color:var(--terra)}
.doorcard .chs{font-style:italic;opacity:.8;margin-top:8px;max-width:38em}

/* Grace "?" point-question dot — reuses wireDetailsCommon's generic
   [data-ask] delegate; any copy carrying one inside a fragment that
   recompute() re-injects must be re-wired by hand (see wireReturns). */
.gdot{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;
  border-radius:50%;border:1px solid rgba(230,225,209,.35);background:none;cursor:pointer;
  font-family:var(--serif);font-size:11px;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;
  color:var(--ink);opacity:.6;transition:.25s;vertical-align:middle;margin-left:6px}
.gdot:hover{opacity:1;border-color:var(--terra);color:var(--terra)}
.mnband .gdot,.ground-midnight .gdot,.ground-stone .gdot{border-color:rgba(232,221,198,.45);color:var(--paper);opacity:.65}
.mnband .gdot:hover,.ground-midnight .gdot:hover,.ground-stone .gdot:hover{border-color:var(--terra);color:var(--terra);opacity:1}

/* compare-the-six — ported .vcard grid (details-design-recon.md §2),
   re-themed to this file's own --ink/--paper/--terra + rgba/color-mix
   idiom (not the recon's own --ink-12/--paper-24 tokens, which don't exist
   in this file's :root) */
.vgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(258px,1fr));gap:18px;margin-top:26px}
.vcard{display:block;width:100%;text-align:left;cursor:pointer;position:relative;overflow:hidden;
  border:1px solid rgba(230,225,209,.12);border-radius:5px;background:rgba(232,221,198,.32);
  padding:24px 24px 22px;transition:transform .25s,box-shadow .25s,border-color .25s}
.vcard:hover{transform:translateY(-4px);box-shadow:0 16px 40px -22px rgba(23,20,15,.5);border-color:rgba(230,225,209,.4)}
.vcard.active{border-color:var(--terra);background:color-mix(in srgb,var(--terra) 7%, transparent)}
.vcard .ytag{position:absolute;top:20px;right:20px;text-align:right}
.vcard .ytag b{display:block;font-size:24px;font-weight:400;line-height:1;color:var(--terra)}
.vcard .ytag small{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;opacity:.6}
.vcard .vtag{display:inline-block;margin-bottom:16px;letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;color:var(--terra)}
.vcard .vname{font-family:var(--serif);font-size:26px;line-height:1.08;margin-bottom:.15em;max-width:72%}
.vcard .vspec{opacity:.72;font-size:14.5px;margin-bottom:16px}
.vcard .vprice{font-family:var(--serif);font-size:28px;font-weight:400;line-height:1}
.vcard .vmeta{display:flex;gap:16px;margin-top:16px;padding-top:16px;border-top:1px solid rgba(230,225,209,.12);opacity:.92;flex-wrap:wrap}
.vcard .vmeta div span{display:block;font-family:var(--serif);font-size:18px;line-height:1}
.vcard .vmeta div small{letter-spacing:.14em;font-size:10px;text-transform:uppercase;opacity:.62}
.vgridnote{font-style:italic;font-size:15px;color:color-mix(in srgb,var(--paper) 62%, transparent);opacity:.85;margin-top:22px}

.quietlink{display:inline-block;margin-top:22px;letter-spacing:var(--ls);font-size:12px;text-transform:uppercase;
  opacity:.6;border-bottom:1px solid currentColor;padding-bottom:2px;transition:.3s}
.quietlink:hover{opacity:1}
.smallprint button{font-style:italic;opacity:.85;border-bottom:1px solid currentColor}

.nextlink{display:block;font-family:var(--serif);font-weight:300;font-size:clamp(24px,3vw,32px);margin-top:8px;transition:.3s}
.nextlink:hover{color:var(--terra)}

.g-ask{display:inline-flex;align-items:center;gap:8px;border:1px solid rgba(230,225,209,.28);color:var(--ink);
  border-radius:999px;padding:12px 20px;letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;
  margin:30px 0 6px;transition:.25s;font-style:normal;background:transparent}
.g-ask:hover{background:var(--ink);color:var(--cream);border-color:var(--ink)}

.chhead{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px}
.curchip{display:inline-flex;border:1px solid rgba(230,225,209,.3);border-radius:99px;overflow:hidden}
.curchip button{padding:8px 16px 9px;font-size:11.5px;letter-spacing:var(--ls);text-transform:uppercase;transition:.3s}
.curchip button.active{background:var(--ink);color:var(--cream)}

.pricenotes p{max-width:44em;margin-bottom:16px;font-size:18px;line-height:1.55}

/* "what makes the price" — donut + ledger (details-design-recon.md §3.3 /
   §3.4.1, ranked port items 2-3), re-themed to this file's own tokens/rgba
   idiom rather than the recon's own --ink-12/rem scale. Two columns desktop
   (donut 40% / ledger 60%, vertically centered), stacks at this file's own
   700px breakpoint on mobile (donut ~220px, centered, above the ledger). */
.invbreak{display:grid;grid-template-columns:2fr 3fr;gap:6vw;align-items:center;margin-top:10px}
.invbreak .donutside{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px}
/* the price, under the chart — an HTML box, so it wraps and grows instead of
   overflowing a fixed SVG hole */
.dprice{text-align:center;max-width:100%}
.dprice-k{font-family:var(--sans);font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--stone)}
.dprice-v{font-family:var(--serif);font-size:clamp(24px,2.6vw,30px);font-weight:300;line-height:1.15;
  margin-top:6px;color:var(--ink);font-variant-numeric:lining-nums;overflow-wrap:anywhere}
.dprice-alt{font-family:var(--serif);font-size:12.5px;margin-top:4px;color:var(--dim);
  font-variant-numeric:lining-nums;overflow-wrap:anywhere}
.donut{width:100%;max-width:260px;height:auto;display:block}
.donut text{font-family:var(--serif);text-anchor:middle}
.dseg{cursor:pointer;transition:opacity .2s ease}
.donut.dim-others .dseg{opacity:.35}
.donut.dim-others .dseg.hi{opacity:1}
.dhole-caps{font-size:11px;letter-spacing:.18em;text-transform:uppercase;fill:var(--stone)}
/* .dhole-price / .dhole-idr are gone with the in-hole figure — see .dprice */
@media(max-width:700px){
  .invbreak{grid-template-columns:1fr;gap:30px}
  .invbreak .donutside{order:-1}
  .donut{max-width:220px;margin:0 auto}
}

.bdlist{width:100%}
.bd-row{display:flex;align-items:baseline;gap:14px;padding:14px 6px;margin:0 -6px;
  border-bottom:1px solid rgba(230,225,209,.18);cursor:pointer;transition:background .2s ease;border-radius:4px}
.bd-row:last-of-type{border-bottom:0}
.bd-row.hi-row{background:rgba(230,225,209,.04)}
.bd-sw{width:10px;height:10px;border-radius:3px;flex:0 0 auto;transform:translateY(3px)}
.bd-name{flex:1;min-width:0}
.bd-name .t{font-size:17px;color:var(--ink);display:block}
.bd-name .d{font-size:13.5px;opacity:.68;display:block;margin-top:4px;line-height:1.42}
.bd-row.margin .d{font-style:italic;color:color-mix(in srgb,var(--paper) 62%, transparent);opacity:1}
.bd-val{font-size:19px;white-space:nowrap;text-align:right;font-variant-numeric:lining-nums}
.bd-total{position:relative;display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  margin-top:16px;padding-top:16px;border-top:1px solid var(--ink)}
.bd-total::before{content:"";position:absolute;left:0;right:0;top:-4px;height:1px;background:var(--ink)}
.bd-total .t{font-size:19px}
.bd-total .v{font-size:26px;text-align:right;font-variant-numeric:lining-nums}
.bd-total .v small{font-size:13px;font-weight:400;display:block;margin-top:4px;font-style:normal}
.splitwrap{margin-top:30px}

.pathmiles .amt{font-size:15px;opacity:.7;margin-top:4px}

.totalbar{margin-top:28px;padding:20px 26px;border:1px solid var(--terra);border-radius:5px;
  background:color-mix(in srgb,var(--terra) 8%, transparent);font-family:var(--serif);font-size:clamp(20px,2.2vw,26px)}

.sumcard{border:1px solid rgba(230,225,209,.16);border-radius:6px;padding:32px 30px;margin:36px 0 40px}
.sumcard .sumname{font-size:clamp(24px,2.6vw,32px);margin-bottom:6px}
.sumcard .sumprice{font-size:19px;opacity:.85;margin-bottom:10px}
.sumcard .sumnums{font-style:italic;opacity:.72;font-size:16px}

/* the 30-year hero — the first thing the eye lands on in the returns
   chapter. Left = the compounded headline number; right = the two-line
   mechanism (year one vs year thirty, both live) that keeps the big number
   from reading as a trick. The hairline below the whole block is supplied
   by the tiles row that follows (.pgtiles>div already carries its own
   border-top) — deliberately not a separate <hr>. */
.rt-hero{display:grid;grid-template-columns:1.15fr 1fr;gap:64px;align-items:start;
  padding:8px 0 0;margin:0 0 56px}
@media (max-width:860px){ .rt-hero{grid-template-columns:1fr;gap:36px;margin-bottom:40px} }
.rt-hero-over{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}
.rt-hero-num{font-family:'Cormorant Garamond',serif;font-weight:300;
  font-size:clamp(84px,11vw,148px);line-height:.86;letter-spacing:-.02em;
  color:var(--ink);font-variant-numeric:lining-nums;margin-top:14px;display:block}
.rt-hero-num .pct{font-size:.44em;letter-spacing:0;margin-left:3px;
  color:rgba(230,225,209,.55);vertical-align:baseline}
.rt-hero-sub{font-style:italic;font-size:clamp(19px,1.5vw,21px);line-height:1.45;color:color-mix(in srgb,var(--paper) 62%, transparent);
  max-width:30ch;margin-top:18px}
.rt-ladder{margin-top:14px}
.rt-ladder-row{display:flex;justify-content:space-between;align-items:baseline;
  border-top:1px solid rgba(230,225,209,.22);padding:14px 0}
.rt-ladder-row .k{font-size:11px;letter-spacing:var(--ls);text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}
.rt-ladder-row .v{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:34px;
  line-height:1;color:var(--ink);font-variant-numeric:lining-nums}
.rt-hero-close{font-style:italic;font-size:16px;line-height:1.5;color:color-mix(in srgb,var(--paper) 62%, transparent);
  margin-top:16px}

/* stat tiles — "the facts of the money": same ledger construction as .facts,
   a hairline above each number, context subline underneath in stone italic */
.pgtiles{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin:34px 0}
.pgtiles>div{border-top:1px solid rgba(230,225,209,.22);padding:18px 24px 0 0}
.pgtl{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}
.pgtv{font-family:var(--serif);font-weight:300;font-size:clamp(40px,3.4vw,54px);line-height:1.05;color:var(--ink);
  font-variant-numeric:lining-nums;margin-top:6px}
.pgtsub{font-style:italic;font-size:15px;color:color-mix(in srgb,var(--paper) 62%, transparent);margin-top:6px}

/* scenario chips — the site's one chip system, matching the chapter-bar chip */
.schips{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:12px 10px}
.schip-row{display:flex;flex-wrap:wrap;gap:10px}
.schip{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;padding:12px 20px;border:1px solid rgba(230,225,209,.28);
  border-radius:999px;background:transparent;color:var(--ink);transition:.25s}
.schip:hover{border-color:var(--ink)}
.schip.active{background:var(--ink);color:var(--cream);border-color:var(--ink)}
.pgreset{font-size:15px;font-style:italic;color:color-mix(in srgb,var(--paper) 62%, transparent);opacity:.85;border-bottom:1px solid currentColor;padding-bottom:1px;transition:.3s}
.pgreset:hover{opacity:1}
.schips-note{font-style:italic;font-size:15px;color:color-mix(in srgb,var(--paper) 62%, transparent);margin-top:14px}

/* sliders — hairline track + node-dot thumb, result-first label hierarchy */
/* teaser gate — the analytical chapters until Grace opens them */
.chtease{max-width:34em;padding:8px 0 40px}
.chtease .over{letter-spacing:var(--ls-wide);font-size:12px;text-transform:uppercase;font-weight:500;color:var(--terra);margin-bottom:12px}
.chtease .title{margin-bottom:22px}
/* the Numbers teaser hero — the multiple is the headline, with the journey
   from price paid to total collected shown as a proportional bar. */
.tnum{margin:6px 0 30px}
.tnum-hero{display:flex;align-items:baseline;gap:clamp(14px,2vw,26px);flex-wrap:wrap}
.tnum-x{font-family:var(--serif);font-size:clamp(78px,13vw,150px);line-height:.82;color:var(--terra);
  font-variant-numeric:lining-nums;letter-spacing:-.02em}
.tnum-x span{font-size:.42em;opacity:.6;margin-left:-.02em;letter-spacing:0}
.tnum-cap b{display:block;font-family:var(--serif);font-weight:400;font-size:clamp(21px,2.5vw,30px);line-height:1.1;color:var(--ink)}
.tnum-cap span{display:block;margin-top:7px;font-style:italic;color:var(--dim);font-size:15.5px;max-width:19em}
.tnum-bar{margin:30px 0 0;max-width:640px}
.tnum-track{height:9px;border-radius:99px;background:color-mix(in srgb,var(--terra) 22%, transparent);overflow:hidden}
.tnum-fill{height:100%;border-radius:99px;background:var(--ink)}
.tnum-ends{display:flex;justify-content:space-between;gap:16px;margin-top:11px;
  letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;opacity:.7}
.tnum-ends b{font-weight:600;opacity:1}
.tnum-ends span:last-child{text-align:right;color:var(--terra)}
.tnum-stats{display:flex;flex-wrap:wrap;gap:10px 44px;margin-top:30px;padding-top:22px;
  border-top:1px solid color-mix(in srgb,var(--ink) 13%, transparent);max-width:640px}
.tnum-stats b{display:block;font-family:var(--serif);font-weight:400;font-size:clamp(24px,2.6vw,31px);line-height:1;color:var(--ink)}
.tnum-stats span{display:block;margin-top:6px;letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;color:var(--dim)}
@media(max-width:560px){.tnum-stats{gap:16px 30px}.tnum-hero{gap:10px}}
/* the three-scenario range — the number as a spectrum to interrogate */
.tnum-range{margin-top:28px;max-width:640px}
.tnum-range-k{letter-spacing:var(--ls-wide);font-size:10.5px;text-transform:uppercase;font-weight:500;opacity:.55;margin-bottom:12px}
.tnum-range-row{display:grid;grid-template-columns:repeat(3,1fr);border:1px solid color-mix(in srgb,var(--ink) 13%, transparent);border-radius:8px;overflow:hidden}
.tnum-range-row>div{padding:14px 12px 15px;text-align:center;border-right:1px solid color-mix(in srgb,var(--ink) 10%, transparent)}
.tnum-range-row>div:last-child{border-right:none}
.tnum-range-row b{display:block;font-family:var(--serif);font-weight:400;font-size:clamp(22px,2.4vw,28px);line-height:1;opacity:.55}
.tnum-range-row span{display:block;margin-top:6px;letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:500;opacity:.5}
.tnum-range-row .on{background:color-mix(in srgb,var(--terra) 9%, transparent)}
.tnum-range-row .on b{color:var(--terra);opacity:1}
.tnum-range-row .on span{opacity:.75}
.tnum-range-note{font-style:italic;color:var(--dim);font-size:14.5px;margin-top:12px;max-width:34em}
/* founders' note — the energy behind the price, in their own voice */
.fnote{margin-top:38px;padding:clamp(26px,3.2vw,42px) clamp(22px,3vw,40px);border-radius:10px;
  background:color-mix(in srgb,var(--terra) 7%, var(--cream));
  border-left:2px solid color-mix(in srgb,var(--terra) 55%, transparent);max-width:760px}
.fnote .over{letter-spacing:var(--ls-wide);font-size:10.5px;text-transform:uppercase;font-weight:600;color:var(--terra);margin-bottom:12px}
.fnote h3{font-family:var(--serif);font-weight:400;font-size:clamp(23px,2.6vw,32px);line-height:1.14;margin:0 0 18px;max-width:18em}
.fnote p{font-size:17px;line-height:1.6;margin:0 0 15px;max-width:40em;opacity:.9}
.fnote p em{font-style:italic;opacity:1}
.fnote .fnote-close{margin-top:20px;padding-top:18px;border-top:1px solid color-mix(in srgb,var(--ink) 12%, transparent);font-style:italic;opacity:.82}
.fnote-sign{margin-top:16px;letter-spacing:var(--ls-wide);font-size:11px;text-transform:uppercase;font-weight:500;color:var(--terra);opacity:.9}
/* the margin contrast — the one number that makes the case on its own */
.fcontrast{display:flex;align-items:center;gap:clamp(16px,3vw,34px);flex-wrap:wrap;
  margin:26px 0 24px;padding:22px 24px;border-radius:9px;background:color-mix(in srgb,var(--cream) 78%, transparent);
  border:1px solid color-mix(in srgb,var(--ink) 10%, transparent)}
.fcontrast b{display:block;font-family:var(--serif);font-weight:400;line-height:1;font-variant-numeric:lining-nums}
.fcontrast span{display:block;margin-top:8px;letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;opacity:.6;max-width:15em}
.fc-a b{font-size:clamp(30px,3.6vw,42px);opacity:.42}
.fc-b b{font-size:clamp(44px,5.6vw,68px);color:var(--terra)}
.fc-vs{font-style:italic;opacity:.4;font-size:15px}
@media(max-width:520px){.fcontrast{gap:14px}.fc-vs{display:none}}
.teaser-num{font-family:var(--serif);font-size:clamp(40px,7vw,60px);line-height:.95;color:var(--ink)}
/* --sans was never defined, so this declaration was invalid and dropped — the
   label has always rendered in the inherited serif. Removed rather than
   defined: the brand has one family. */
.teaser-num span{display:block;font-size:13px;letter-spacing:var(--ls);text-transform:uppercase;opacity:.6;margin-top:10px;font-weight:500}
.teaser-sub{font-style:italic;opacity:.78;margin-top:14px;max-width:26em}
.teaser-body{font-size:18px;line-height:1.55;margin:24px 0 30px;opacity:.9}
.teaser-body em{font-style:italic}
.teaser-actions{display:flex;flex-wrap:wrap;gap:14px 20px;align-items:center}
.teaser-actions .talklink{letter-spacing:var(--ls);font-size:12px;text-transform:uppercase;color:var(--dim)}
.teaser-actions .talklink:hover{color:var(--ink)}

/* "Tuned by Grace" banner + optional three-scenario compare on the returns page */
.qtuned{background:color-mix(in srgb,var(--terra) 12%, var(--cream));border:1px solid color-mix(in srgb,var(--terra) 34%, transparent);
  border-radius:6px;padding:15px 18px;margin:0 0 30px;display:flex;flex-wrap:wrap;gap:5px 14px;align-items:baseline}
.qtuned .qt-k{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:600;color:var(--terra);width:100%}
.qtuned .qt-v{font-size:15.5px}.qtuned .qt-v b{font-weight:600}
.qtuned .qt-note{width:100%;font-style:italic;opacity:.7;font-size:13.5px;margin-top:4px}
.qcompare{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:0 0 32px}
.qcompare .qc{border:1px solid rgba(230,225,209,.16);border-radius:6px;padding:15px 12px;text-align:center}
.qcompare .qc .qc-k{letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:500;opacity:.6;margin-bottom:7px}
.qcompare .qc .qc-y{font-family:var(--serif);font-size:25px;color:var(--ink);line-height:1}
.qcompare .qc .qc-s{font-size:11.5px;opacity:.7;margin-top:5px}
.qcompare .qc.base{border-color:color-mix(in srgb,var(--terra) 50%, transparent);background:color-mix(in srgb,var(--terra) 6%, transparent)}
@media(max-width:560px){.qcompare{grid-template-columns:1fr 1fr}.qcompare .qc.base{grid-column:span 2}}
.pgsliders{display:flex;flex-direction:column;gap:34px;max-width:560px;margin-bottom:14px}
.pgslide label{display:block}
.pgslabel{display:flex;justify-content:space-between;align-items:baseline;gap:14px;flex-wrap:wrap;margin-bottom:8px}
.pgsk{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}
.pgsr{font-family:var(--serif);font-size:22px;color:var(--ink);text-align:right}
.pgsd{width:100%;text-align:right;font-style:italic;font-size:13px;color:color-mix(in srgb,var(--paper) 62%, transparent);margin-top:4px}
.pgslide input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:30px;outline:none;padding:14px 0;
  /* height is the FULL border-box (this file resets *{box-sizing:border-box})
     — 2px content-box track + 14px padding top/bottom = 30px; a plain
     height:2px here would clamp the content-box to 0 against that same
     padding and make the --p fill gradient below paint into zero area
     (invisible in Chromium/WebKit, confirmed by pixel-sampling: see pw_v20
     8b/8c — a real WORK ORDER 4 #6a regression this fixes, not merely a
     cosmetic opacity tweak). */
  background:linear-gradient(to right,var(--ink) 0 var(--p,0%),rgba(230,225,209,.30) var(--p,0%) 100%);background-clip:content-box}
.pgslide input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:50%;
  background:var(--cream);border:1.5px solid var(--ink);box-shadow:none;cursor:pointer;transition:border-color .2s}
.pgslide input[type=range]::-moz-range-thumb{width:18px;height:18px;border:1.5px solid var(--ink);border-radius:50%;
  background:var(--cream);box-shadow:none;cursor:pointer;transition:border-color .2s}
.pgslide input[type=range]::-moz-range-track{height:2px;background:linear-gradient(to right,var(--ink) 0 var(--p,0%),rgba(230,225,209,.30) var(--p,0%) 100%)}
.pgslide input[type=range]:active::-webkit-slider-thumb,.pgslide input[type=range]:focus-visible::-webkit-slider-thumb{border-color:var(--terra)}
.pgslide input[type=range]:active::-moz-range-thumb,.pgslide input[type=range]:focus-visible::-moz-range-thumb{border-color:var(--terra)}

/* own-nights pull-line — sits directly below the midnight band, on cream;
   the money value stands upright (non-italic) inside the italic line */
.ownline{font-style:italic;font-size:19px;line-height:1.5;max-width:38em;margin:36px 0 0;color:var(--ink)}
.ownline .amt{font-style:normal}

/* the P&L is a ledger, not a full-width table — cap it so the figure sits a
   readable distance from its label instead of stranding across the whole
   column (and, on desktop, so a right-aligned number never lands under the
   Grace panel). */
.pnlwrap{max-width:620px}
.pnlgroup{margin-top:22px}
.pnlhead{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent);border-top:1px solid rgba(230,225,209,.22);padding-top:14px;margin-bottom:10px}
.pnlrow{display:flex;justify-content:space-between;gap:20px;padding:9px 0;border-bottom:1px solid rgba(230,225,209,.08);font-size:17px}
.pnlrow .pnl-lbl small{display:block;font-size:12px;opacity:.55;font-style:italic;margin-top:2px}
.pnlrow.pnlbold{font-weight:500}
.pnl-val.pnl-cost{color:color-mix(in srgb,var(--paper) 62%, transparent)}
.pnlnoi{position:relative;margin-top:18px;padding-top:14px;border-top:1px solid var(--ink);border-bottom:none;font-size:22px;color:var(--terra);font-weight:500}
.pnlnoi::before{content:"";position:absolute;left:0;right:0;top:-4px;height:1px;background:var(--ink)}

/* the 30-year picture — full-bleed midnight panel, the one composed dark moment */
.mnband{background:var(--midnight);width:100vw;margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);padding:84px 0 76px}
.mnband-inner{max-width:820px;margin:0 auto;padding:0 24px}
.mnover{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:rgba(232,221,198,.6);margin-bottom:16px}
.mnhead{font-family:var(--serif);font-weight:300;font-size:34px;line-height:1.3;color:var(--paper);max-width:18em}
.mnhead em{font-style:italic}
.chartwrap{margin-top:40px}
.chartwrap svg text{font-style:normal;font-family:'Cormorant Garamond',serif}
.chartwrap svg text.mn-italic{font-style:italic}
.chartwrap svg .mn-axis{letter-spacing:.14em;text-transform:uppercase;fill:rgba(232,221,198,.55)}
.chartwrap svg .mn-price{letter-spacing:.14em;text-transform:uppercase;fill:rgba(232,221,198,.75)}
.chartwrap svg .mn-mark{fill:var(--paper)}
.chartwrap svg .mn-micro{letter-spacing:.14em;text-transform:uppercase;fill:rgba(232,221,198,.55)}
.chartwrap svg .mn-tipcaps{letter-spacing:var(--ls);text-transform:uppercase;fill:rgba(232,221,198,.6)}
.chartwrap svg .mn-tipval{fill:var(--paper)}
.mncaption{text-align:right;font-style:italic;font-size:13px;color:rgba(232,221,198,.55);margin-top:16px}
@media(max-width:700px){.mnband{padding:56px 0}.mnband-inner{padding:0 22px}}

/* the management-proof band — full-bleed WARM PAPER (never a second dark
   panel; the midnight chart stays the chapter's one dark moment). Same
   full-bleed technique as .mnband, inner column pinned to the same 820px
   text column via .rt-proof-inner. Stats mirror .pgtiles' own ledger
   construction (hairline above each number) at the spec's own sizes. */
.rt-proof{background:var(--paper);color:var(--ink);width:100vw;
  margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);padding:76px 0 68px}
.rt-proof-inner{max-width:820px;margin:0 auto;padding:0 24px}
.rt-proof-over{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:rgba(230,225,209,.55)}
.rt-proof-head{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:clamp(28px,3vw,34px);
  line-height:1.25;color:var(--ink);max-width:24ch;margin-top:16px}
.rt-proof-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:44px}
.rt-proof-stats>div{border-top:1px solid rgba(230,225,209,.22);padding:18px 24px 0 0}
.rt-proof-l{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent);min-height:2.4em;line-height:1.2}
.rt-proof-n{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:clamp(34px,3vw,44px);
  line-height:1.05;color:var(--ink);font-variant-numeric:lining-nums;margin-top:6px}
.rt-proof-s{font-style:italic;font-size:14px;color:color-mix(in srgb,var(--paper) 62%, transparent);margin-top:6px;text-wrap:pretty}
.rt-proof-caveat{border-top:1px solid rgba(230,225,209,.22);padding-top:20px;margin-top:32px;
  font-style:italic;font-size:16px;line-height:1.55;color:color-mix(in srgb,var(--paper) 62%, transparent);max-width:60ch}
.rt-proof-close{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:clamp(19px,1.7vw,21px);
  line-height:1.45;color:var(--ink);margin-top:28px;max-width:46ch}
@media(max-width:700px){
  .rt-proof{padding:52px 0 48px}
  .rt-proof-inner{padding:0 22px}
  .rt-proof-stats{grid-template-columns:1fr 1fr}
}

.accordion{margin-top:36px}
.accordion summary{cursor:pointer;letter-spacing:.18em;font-size:12px;text-transform:uppercase;padding:16px 0;
  border-top:1px solid rgba(230,225,209,.22);border-bottom:1px solid rgba(230,225,209,.22);
  list-style:none;color:var(--ink)}
.accordion summary::-webkit-details-marker{display:none}
.accordion summary::marker{content:""}
.accordion summary::after{content:"+";float:right;font-family:var(--serif);font-size:16px}
.accordion[open] summary::after{content:"–"}
.accordion .methline{margin-top:22px;font-size:17px;max-width:44em;line-height:1.55}
.methrow{margin-top:18px}
.methrow .k{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}
.methrow .v{font-size:17px;color:var(--ink);margin-top:6px}
.methrow .v small{display:block;font-size:13px;opacity:.65;font-style:italic;margin-top:6px;max-width:44em}

/* ---------- furnishing v2: the styler stage ---------- */
.styler{margin-top:30px}
.styler .fstage{position:relative;border:1.5px solid rgba(230,225,209,.24);overflow:hidden;background:var(--well);border-radius:2px}
.styler .fcanvas{position:relative;aspect-ratio:16/9;overflow:hidden}
.styler .fcanvas img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .7s var(--ease)}
.styler .fcanvas img.on{opacity:1}
.styler .floadbar{position:absolute;top:0;left:0;right:0;height:3px;z-index:6;opacity:0;transition:opacity .25s;pointer-events:none;background:color-mix(in srgb,var(--paper) 20%, transparent)}
.styler .fstage.loading .floadbar{opacity:1}
.styler .floadbar i{position:absolute;top:0;bottom:0;left:-32%;width:32%;background:var(--terra);animation:fsweep 1.1s var(--ease) infinite}
@keyframes fsweep{0%{left:-32%}65%{left:100%}100%{left:100%}}
@media(prefers-reduced-motion:reduce){.styler .floadbar i{animation:none;left:0;width:100%}}
.styler .flive{position:absolute;top:13px;left:15px;display:flex;align-items:center;gap:8px;color:var(--paper);letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:500;text-shadow:0 1px 6px rgba(0,0,0,.6)}
.styler .flive i{width:7px;height:7px;border-radius:50%;background:var(--terra);animation:fpl 2.4s infinite}
@keyframes fpl{0%{box-shadow:0 0 0 0 rgba(168,90,62,.55)}70%{box-shadow:0 0 0 8px rgba(168,90,62,0)}100%{box-shadow:0 0 0 0 rgba(168,90,62,0)}}
.styler .fcap{position:absolute;left:0;right:0;bottom:0;display:flex;justify-content:space-between;flex-wrap:wrap;gap:6px 18px;padding:56px 20px 15px;background:linear-gradient(to top,rgba(10,9,6,.82),transparent);color:var(--paper)}
.styler .fcap span{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500}
.styler .fcap .r{opacity:.85}
.styler .fnoncap{font-size:14px;margin-top:12px;margin-bottom:0}

.styler .ftabs{display:flex;gap:8px;margin-top:24px;flex-wrap:wrap}
.styler .ftabs button{border:1px solid rgba(230,225,209,.28);padding:10px 18px 11px;letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;opacity:.75;transition:.2s}
.styler .ftabs button:hover{opacity:1;border-color:var(--ink)}
.styler .ftabs button.on{background:var(--ink);color:var(--cream);border-color:var(--ink);opacity:1}

.styler .froomhead{margin-top:26px;display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
.styler .froomhead .nm{font-family:var(--serif);font-size:clamp(22px,2.4vw,28px)}
.styler .froomhead .rn{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;opacity:.55}
.styler .froomnote{font-size:16px;opacity:.75;max-width:44em;margin-top:8px;line-height:1.5}

.styler .fpal{display:flex;gap:12px;margin-top:20px;flex-wrap:wrap}
.styler .fpal button{display:flex;align-items:center;gap:9px;border:1px solid rgba(230,225,209,.28);padding:9px 16px 9px 10px;border-radius:99px;font-size:13px;letter-spacing:.02em;opacity:.8;transition:.2s}
.styler .fpal button:hover{opacity:1;border-color:var(--ink)}
.styler .fpal button.on{border-color:var(--ink);background:var(--ink);color:var(--cream);opacity:1}
.styler .fsw{width:16px;height:16px;border-radius:50%;flex:none;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}
.styler .fsw.teak{background:linear-gradient(135deg,#a07c48,#6f5330)}
.styler .fsw.pale{background:linear-gradient(135deg,#e6dcc4,#c3b48f)}
.styler .fsw.dark{background:linear-gradient(135deg,#4a4b47,#23231f)}

/* ---------- configurator layout — top bar + two columns (render / room panel) ---------- */
.styler .fvbar{display:flex;flex-wrap:wrap;gap:20px 34px;align-items:center;justify-content:space-between;margin:26px 0 4px;padding:20px 0;border-top:1px solid rgba(230,225,209,.16);border-bottom:1px solid rgba(230,225,209,.16)}
.styler .fvbar .fvgrp{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.styler .fvbar .fvlab{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;color:var(--dim)}
.styler .fvbar .fpal{margin-top:0}
.styler .fvtot{text-align:right;margin-left:auto}
.styler .fvtot .k{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;color:var(--dim)}
.styler .fvtot .n{font-size:clamp(26px,3vw,31px);font-weight:300;line-height:1.15}
.styler .fvtot .tier{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;color:var(--dim)}
.styler .fcfg{display:grid;grid-template-columns:1.5fr 1fr;gap:46px;margin-top:30px;align-items:start}
@media(max-width:1000px){.styler .fcfg{grid-template-columns:1fr;gap:28px}}
.styler .fcfg .ftabs{margin-top:16px}
.styler .ftabs button.override{position:relative}
.styler .ftabs button.override::after{content:"";position:absolute;top:5px;right:6px;width:6px;height:6px;border-radius:50%;background:var(--terra)}

/* room panel (right column) */
.styler .fpanel .rhead{display:flex;align-items:baseline;justify-content:space-between;gap:14px;margin-bottom:6px}
.styler .fpanel .rhead h3{font-family:var(--serif);font-size:clamp(24px,2.6vw,30px);font-weight:300}
.styler .fpanel .rhead .rn{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;opacity:.55;white-space:nowrap}
.styler .fpanel .frp{margin:20px 0 10px}
.styler .fpanel .frp .lab{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;color:var(--dim);margin-bottom:11px}
.styler .frp-set{display:flex;gap:7px;flex-wrap:wrap}
.styler .frp-chip{display:flex;align-items:center;gap:8px;border:1px solid rgba(230,225,209,.3);padding:8px 13px 9px;letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:500;transition:.2s}
.styler .frp-chip .fsw{width:12px;height:12px}
.styler .frp-chip:hover{border-color:var(--ink)}
.styler .frp-chip.on{background:var(--ink);color:var(--cream);border-color:var(--ink)}
.styler .fdivline{height:1px;background:rgba(230,225,209,.16);margin:24px 0 4px}
.styler .fitem{padding:18px 0;border-bottom:1px solid rgba(230,225,209,.13)}
.styler .fitem .ftop{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer;user-select:none;width:100%;text-align:left}
.styler .fitem .ftop:hover .l{opacity:.75}
.styler .fitem .ftop .l{font-family:var(--serif);font-size:22px;transition:.2s}
.styler .fitem .ftop .tr{display:flex;align-items:center;gap:14px}
.styler .fitem .ftop .cur{letter-spacing:var(--ls);font-size:10px;text-transform:uppercase;font-weight:500;opacity:.55;text-align:right}
.styler .fitem .ftop .chev{width:9px;height:9px;border-right:1.4px solid rgba(230,225,209,.55);border-bottom:1.4px solid rgba(230,225,209,.55);transform:rotate(45deg) translate(-1px,-1px);transition:transform .4s var(--ease);flex:none}
.styler .fitem.open .ftop .chev{transform:rotate(225deg)}
.styler .foptwrap{overflow:hidden;max-height:0;transition:max-height .5s var(--ease)}
.styler .fitem.open .foptwrap{max-height:400px}
.styler .fopts{display:flex;flex-direction:column;gap:7px;padding-top:14px}
.styler .fopt{display:flex;align-items:center;gap:12px;border:1px solid rgba(230,225,209,.2);padding:10px 14px;transition:.2s;text-align:left;width:100%}
.styler .fopt:hover{border-color:rgba(230,225,209,.55)}
.styler .fopt.on{border-color:var(--ink);background:color-mix(in srgb,var(--ink) 5%, transparent)}
.styler .fopt .fsw{width:20px;height:20px}
.styler .fopt .fsw.none{background:repeating-linear-gradient(45deg,transparent,transparent 3px,rgba(230,225,209,.3) 3px,rgba(230,225,209,.3) 4px);box-shadow:inset 0 0 0 1px rgba(23,20,15,.3)}
.styler .fopt .nm{flex:1;font-family:var(--serif);font-size:18px;line-height:1.25}
.styler .fopt .pr{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;color:var(--dim);white-space:nowrap}
.styler .fopt.on .pr{color:var(--paper)}
.styler .fopt .tick{width:19px;height:19px;border-radius:50%;border:1.5px solid rgba(230,225,209,.3);display:flex;align-items:center;justify-content:center;font-size:11px;color:transparent;flex:none;transition:.2s}
.styler .fopt.on .tick{background:var(--ink);border-color:var(--ink);color:var(--cream)}
.styler .frnote{font-style:italic;color:var(--dim);font-size:15.5px;line-height:1.5;margin-top:18px}

/* name-your-villa prompt — the gate before the configurator opens */
.styler .fname-prompt{border-top:1px solid rgba(230,225,209,.16);border-bottom:1px solid rgba(230,225,209,.16);padding:56px 0;margin:26px 0 4px}
.styler .fnp-inner{max-width:34em}
.styler .fnp-inner .over{margin-bottom:12px}
.styler .fnp-h{font-family:var(--serif);font-size:clamp(30px,4vw,46px);font-weight:300;line-height:1.05}
.styler .fnp-sub{font-style:italic;opacity:.7;font-size:18px;line-height:1.5;margin:14px 0 30px;max-width:30em}
.styler .fnp-row{display:flex;gap:14px;flex-wrap:wrap;align-items:stretch}
.styler .fnp-row input{flex:1;min-width:240px;font-family:var(--serif);font-size:22px;background:transparent;border:none;border-bottom:1.5px solid rgba(230,225,209,.35);padding:10px 4px;color:var(--ink)}
.styler .fnp-row input::placeholder{opacity:.4}
.styler .fnp-row input:focus{outline:none;border-color:var(--ink)}
.styler .fnp-row input.err{border-color:var(--terra)}
.styler .fnp-row .btn{white-space:nowrap;align-self:center}
@media(max-width:600px){.styler .fnp-row .btn{align-self:stretch;justify-content:center}}

/* the villa name, once given — sits above the configurator */
.styler .fnamebar{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-top:26px}
.styler .fnb-l{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;font-weight:500;opacity:.55}
.styler .fnb-name{font-family:var(--serif);font-size:clamp(24px,3vw,34px);font-weight:300;line-height:1.05}
.styler .fnb-edit{letter-spacing:var(--ls);font-size:10.5px;text-transform:uppercase;font-weight:500;opacity:.5;border-bottom:1px solid transparent;transition:.2s;margin-left:2px}
.styler .fnb-edit:hover{opacity:1;border-bottom-color:var(--ink)}

/* the tuner (inside the .accordion pattern already used by the returns chapter) */
.tuner-disc{font-style:italic;font-size:15px;opacity:.65;line-height:1.5;margin:20px 0 26px;max-width:44em}
.tuner-room{margin-bottom:30px}
.tuner-room:last-child{margin-bottom:6px}
.tuner-room .trn{letter-spacing:var(--ls);font-size:11px;text-transform:uppercase;opacity:.55;margin-bottom:4px}
.tuner-room .trname{font-family:var(--serif);font-size:20px;margin-bottom:6px}
.tuner-room .trnote{font-size:15px;opacity:.65;max-width:44em;margin-bottom:16px;line-height:1.5}
.tuner-items{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:18px 24px}
.tuner-item{display:flex;flex-direction:column;gap:7px}
.tuner-item .til{letter-spacing:.02em;font-size:13px;opacity:.7;display:flex;align-items:center;gap:8px}
.tuner-item .tidot{width:11px;height:11px;border-radius:50%;flex:none;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15)}
.tuner-item select{font-family:var(--serif);font-size:16px;background:transparent;border:none;border-bottom:1px solid rgba(230,225,209,.3);padding:8px 4px;color:var(--ink);cursor:pointer}
.tuner-item select:focus{outline:none;border-color:var(--ink)}

/* "save my selections" lead capture */
.leadwrap{max-width:640px}
.leadh{font-family:var(--serif);font-weight:300;font-size:clamp(26px,3vw,34px);margin:10px 0 14px}
.leadfields{display:flex;gap:32px;flex-wrap:wrap;margin:30px 0 6px}
.fld{flex:1;min-width:220px;display:flex;flex-direction:column;gap:8px}
.fld span{letter-spacing:.18em;font-size:11px;text-transform:uppercase;color:color-mix(in srgb,var(--paper) 62%, transparent)}
.fld input{font-family:var(--serif);font-size:20px;background:transparent;border:none;border-bottom:1px solid rgba(230,225,209,.35);padding:9px 2px;color:var(--ink);min-height:22px}
.fld input:focus{outline:none;border-color:var(--terra)}
.fld.err input{border-color:var(--terra)}
.fld-warn{color:var(--terra);font-size:13px;font-style:italic;margin-top:12px;display:none}
.fld-warn.show{display:block}
.leadconfirm{font-size:19px;font-style:italic;max-width:34em;line-height:1.6}
.leadconfirm .talklink{display:inline-block;margin-top:14px;font-size:13px;font-style:normal;letter-spacing:.02em}
.welcomeback{font-size:15px;font-style:italic;opacity:.8;margin:28px 0 6px}

@keyframes fabhalo{0%{box-shadow:0 14px 40px rgba(0,0,0,.35),0 0 0 0 color-mix(in srgb,var(--terra) 55%, transparent)}
  70%{box-shadow:0 14px 40px rgba(0,0,0,.35),0 0 0 26px color-mix(in srgb,var(--terra) 0%, transparent)}
  100%{box-shadow:0 14px 40px rgba(0,0,0,.35),0 0 0 0 color-mix(in srgb,var(--terra) 0%, transparent)}}
#c-fab.pulse2{animation:fabhalo 1.1s var(--ease) 2}

@media(max-width:700px){
  .pgtiles{grid-template-columns:1fr 1fr}
  .sumcard{padding:24px 22px}
  /* scenario chips + reset link were cramping into one crowded row — give the
     reset link its own line beneath them */
  .pgreset{flex-basis:100%;margin-top:2px}
  /* the node-dot thumb reads a touch bigger on mobile — still the same
     hairline+dot instrument, just an easier target */
  .pgslide input[type=range]::-webkit-slider-thumb{width:22px;height:22px}
  .pgslide input[type=range]::-moz-range-thumb{width:22px;height:22px}

  /* styler + tuner + lead form: bigger tap targets, single columns */
  .styler .ftabs button{padding:13px 16px 14px}
  .styler .fpal button{padding:12px 18px 12px 12px;font-size:14px}
  .styler .froomhead{margin-top:22px}
  .tuner-items{grid-template-columns:1fr}
  .tuner-item select{padding:12px 4px;font-size:16px}
  .leadfields{flex-direction:column;gap:22px}
  .fld input{padding:13px 2px;font-size:17px}
}
@media(max-width:430px){
  /* v23 E2 — "US$46,486"-class values were crowding the 2x2 stat-tile
     grid's right edge on narrow phones; shrink just the number. */
  .pgtv{font-size:clamp(30px,8.4vw,40px)}
}

/* ═══ v26 · PASS 3 readability · fixes 1-12 ══════════════════════════════
   Appended at the end of the sheet on purpose: media queries carry no
   specificity of their own, so same-specificity conflicts are decided by
   source order and every rule below must sit after the rule it overrides. */

/* FIX 1 — prose measure (A1, 45 findings).
   54ch body/lead prose, 52ch .smallprint.
   No margin-inline:auto: all 91 A1 elements compute text-align:start. */
.smallprint{max-width:52ch}
.body-l,
.jstep p,
.pricenotes p,
.accordion .methline,
.styler .froomnote,
.tuner-disc,
.tuner-room .trnote,
/* .rt-hero-close is deliberately NOT a member of this group (v27).
   v23's E1 fix sizes that closing paragraph to fill the ladder column it sits
   under on the returns page, so it pairs visually with .rt-ladder.  A 54ch
   measure clamp narrows it to ~378px against a ~472px ladder and breaks that
   pairing.  pw_v23 s16 and pw_v24 s6 both assert the two widths match to <2px.
   Do not re-add it here. */
.schips-note,
p.dim,
#pg-acc-irr{max-width:54ch}
/* A1's D-23 is NOT closed by the #pg-acc-irr rule above.  D-23's evidence line
   ("the average above is the mean of thirty annual returns; ...") lives in a
   <small> CHILD, and `.methrow .v small{...;max-width:44em}` (block 1, 0,2,1)
   caps that child independently.  54ch on the parent is computed against the
   parent's 17px font (1ch=8px -> 432px); the child renders at 13px, so 432px
   still held 93 chars — measured, over the doc's own 78 bar.  1,0,1 here beats
   0,2,1.  52ch at 13px (1ch=6px -> 312px, 4.613px/char measured) = ~68 chars.
   .doorcard .chs and .plans-grid figcaption are NOT among A1's named 19 — they
   appear in the audit only as font findings (D-74, D-40/41/43), which are not
   mine and whose font-size I do not touch.  But fix 1's verify clause is global
   ("no prose element on any audited route exceeds 78 characters per line"), and
   measured they run 107 and 89.  max-width alone changes neither font-size nor
   colour, so this does not collide with D-74/D-40-43 or with fix 6.
   All five elements compute text-align start/left, so no margin-inline:auto —
   same conditional the doc sets for the rest of A1. */
#pg-acc-irr small,
.doorcard .chs{max-width:52ch}
.plans-grid figcaption{max-width:54ch}
/* 21 of the 23 <p class="lead"> carry an INLINE max-width (28em-34em =
   756-918px = 79-95 chars).  No normal-weight rule of any specificity can
   reach a style attribute, and the repeated inline strings are not unique
   enough to splice one at a time, so this is the one place !important is
   the correct tool.  The two intentionally-narrower hero leads are then
   restored at higher specificity, also !important, so they keep 26em. */
.lead{max-width:54ch!important}
#v-cover .hero .lead,
.film-mid .lead{max-width:26em!important}

/* FIX 2 — journey grid (A2 / M-01).  Was an inline style on an unclassed
   div; a media query cannot reach an inline style, so it moved to a class.
   The fractional pixel columns are not preserved: they were `1fr auto`
   computing to 153px 210.125px, 60px wider than the 335.4px content box. */
.jgrid{display:grid;grid-template-columns:1fr auto;gap:60px;align-items:start}
@media(max-width:720px){
  .jgrid{grid-template-columns:1fr;gap:34px}
  .jgrid .tree-aside{text-align:center}
}

/* FIX 3 — starved columns (A3).  X measured, see apply_v26_css.py.
   .incl stays CSS multi-column on purpose: grid would flip the list from
   column-major to row-major reading order. */
.packs{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
@media(max-width:960px){.packs{grid-template-columns:1fr}}
.incl{columns:440px;column-gap:64px}
@media(max-width:900px){.incl{columns:1}}

/* FIX 3 addendum — the price-ladder cards share one set of interior rows, so
   the price line and the first list item sit at the same y however many lines
   the title takes.  `:has(.pr)` picks out the two price ladders and leaves the
   "A rule we keep" trio alone.  row-gap:0 because a subgrid would otherwise
   inherit the parent's 26px gutter between all five rows.
   justify-self:start on the button because the source sets align-self:flex-start
   on .pick — in a column flex container that is the INLINE axis and gives the
   pill its shrink-to-fit width, but in grid align-self is the BLOCK axis, so
   without this the button would stretch the full column (measured 146.3px to
   267.4px at 390).  justify-self:start restores the measured original width. */
@supports(grid-template-rows:subgrid){
  .packs:has(.pr)>.pack{display:grid;grid-template-rows:subgrid;grid-row:span 5;row-gap:0}
  .packs:has(.pr)>.pack>.pick{justify-self:start}
}

/* FIX 4 — tap targets (A4).  Coarse pointers only: the desktop site keeps
   its delicate sizing, which is the design, not an oversight. */
:root{--tap-min:44px}
@media(pointer:coarse){
  /* the 16px info dot keeps its visual size — the hit area grows, not the dot.
     SPEC DELTA: the doc's snippet uses inset:-14px and claims "44x44 of
     touchable area".  Measured, it yields 42x42.  `*{box-sizing:border-box}`
     (block 1 L21) + `.gdot{width:16px;height:16px;border:1px ...}` (L577-580)
     means the .gdot PADDING box — which is the containing block for an
     absolutely positioned ::after — is 14x14, not 16x16.  14 + 2*14 = 42.
     getComputedStyle(el,'::after').width read back "42px" and a 0.1px-step
     elementsFromPoint sweep gave a 41.8px hittable span.
     -15px restores the doc's own binding requirement of >=44x44: 14 + 2*15 = 44. */
  /* SPEC DELTA 2: a 44x44 box is not 44x44 of TOUCHABLE area if something
     paints over it.  With the inset alone, elementFromPoint (topmost — that is
     what a tap actually hits, unlike elementsFromPoint) reached only 43x36 on
     the invest chapter and 43x33 on the path chapter: inert later siblings
     (SPAN.d, DIV.amt) painted over the bottom band of the pseudo.
     z-index:1 lifts the dot over same-context siblings and fixed invest
     (36 -> 43).  It did NOT fix path, because the dot's parent
     `.pathmiles .k` computes opacity:.72, which CREATES A STACKING CONTEXT
     and traps the dot's z-index inside it; the later sibling .amt then paints
     above the whole context.  Raising .k itself is the only way out and is
     visually inert — measured, the boxes do not overlap (.k 412.1-430,
     .amt 434-458), and both rules are inside pointer:coarse.
     After both: all 6 .gdot sites measure tapW 43 / tapH 43, i.e. the full
     44x44 box (43 = largest whole-pixel span strictly inside 44px: 22 up +
     21 down from the centre). */
  .gdot{position:relative;z-index:1}
  .pathmiles .k{position:relative;z-index:1}
  .gdot::after{content:"";position:absolute;inset:-15px}
  .footnav button,
  .talklink,
  .curchip button,
  .chip,
  .schip,
  .pack .pick,
  .styler .ftabs button,
  .styler .fpal button{min-height:var(--tap-min)}
  .nextlink{min-height:var(--tap-min);display:flex;align-items:center}
  /* 24px glyph + symmetric padding = exactly 44x44 (was 38x40). */
  .burger{padding:10px 11px}
  /* hairline track preserved exactly: 44-2*21 = 2px content box, same as
     the 30-2*14 it replaces, and background-clip:content-box is unchanged */
  .pgslide input[type=range]{height:var(--tap-min);padding:21px 0}
}

/* FIX 5 — orphan control (A5), partial by decision.  No hard <br> anywhere:
   portal widths vary continuously and a break that fixes 1440 breaks 1100. */
p,li,figcaption,blockquote{text-wrap:pretty}
h1,h2,h3,h4,.title,.nm,.trname{text-wrap:balance}

/* FIX 6 — caps off full sentences (A6).  Modifier class on the 2 sites that
   actually carry the treatment; the shared microlabel class is untouched.
   Specificity is deliberate: plain `.lowcaps` would lose to the
   ID-qualified `#v-cover .scroll-cue` and to `.miles .k`.
   font-size and colour are unchanged, so the type hierarchy still reads. */
#v-cover .scroll-cue.lowcaps,
.miles .k.lowcaps{text-transform:none;letter-spacing:.02em}

/* FIX 7 — .smallprint 14px -> 15px (A7).  "One value, everywhere."
   `.styler .fnoncap{font-size:14px}` (block 1 L837, specificity 0,2,0) outranks
   a bare `.smallprint` (0,1,0), so #styler-block>p.fnoncap.smallprint — one of
   A1's own 19 named selectors — stayed at 14px in the first build.  Measured on
   #/villa/2br-1/details/furnishing at 1440 and 390.  Matched here at equal
   specificity, later in source order, so it wins without !important. */
.smallprint{font-size:15px}
.styler .fnoncap{font-size:15px}

/* FIX 8 — invest-ledger description 13.5px -> 15px (A8). */
.bd-name .d{font-size:15px}

/* FIX 9 — .invbreak overflow (A9).  The doc's prescription (row normal,
   nowrap on the numeric span) was already true in the source; these two
   declarations restate it so it cannot regress. */
.invbreak{white-space:normal}
.bd-val{white-space:nowrap}
/* The actual 6px: .bd-row{margin:0 -6px} bleeds the hi-row background past
   the text column.  6px of inline padding on the list gives the bleed room
   inside the box, keeping the effect and losing the overflow. */
.bdlist{padding-inline:6px}

/* FIX 10 — terracotta text grounds (A10+A11).  --terra itself is untouched:
   it is correct for rules, marks and the signature. */
:root{--terracotta-deep:#949E86}  /* retired: now sage. SWV has no terracotta. */
/* .pack text is --paper, not cream: paper on #9A5138 is 4.321, still under
   the floor, so the ground AND the foreground both move. */
.pack.terra{background:var(--terracotta-deep);color:var(--cream)}
/* was an inline opacity:.7 on two sites; on the terra ground 70% cream
   composites to 3.395, so terra opts out and keeps the label at full. */
.pack .caps{opacity:.7}
.pack.terra .caps{opacity:1}
/* D-119 `.pack.terra .pick`: `.pack .pick{color:var(--paper)}` (block 1 L288-289,
   specificity 0,2,0) matches the button directly, so it beats the cream that
   `.pack.terra` sets for inheritance.  Measured 4.321 in the first build — the
   exact paper-on-#9A5138 figure.  0,3,0 here, so it wins.  The border moves with
   it or the pill reads as two different whites. */
.pack.terra .pick{color:var(--cream);border-color:var(--cream)}
.pack.terra .pick:hover,.pack.terra .pick.picked{background:var(--cream);color:var(--ink)}
.btn.terra{background:var(--terracotta-deep);border-color:var(--terracotta-deep)}
.cbtalk{border-color:var(--terracotta-deep);color:var(--terracotta-deep)}
.cbtalk:hover,.cbtalk.active{background:var(--terracotta-deep)}
.vcard .vtag{color:var(--terracotta-deep)}
.bd-total .v small{color:var(--terracotta-deep)}
/* M-23a: ink at a cumulative .92*.62 = .5704 measured 4.193 on cream. */
.vcard .vmeta div small{opacity:.7}
/* M-23c and its untagged sibling .mn-micro: paper at 55% on midnight. */
.mncaption{color:rgba(232,221,198,.75)}
.chartwrap svg .mn-micro{fill:rgba(232,221,198,.75)}

/* FIX 11 — doorcard .over (A12).  Opacity alone tops out at 4.073 on this
   ground, so the fix-10 token is used with it. */
.doorcard .over{color:var(--terracotta-deep);opacity:1}

/* FIX 12 — 55% ink -> 70% (A13). */
.rt-proof-over{color:rgba(230,225,209,.7)}
.tuner-room .trn{opacity:.7}
.pnlrow .pnl-lbl small{opacity:.7}


/* ===================== v29 ===================== */
/* v29 FIX A2 — cream masthead scrim over the hero render.  At scroll 0 the
   nav is ink on the photograph with no text-shadow (nav.on-cream,
   background:none), measured 2.81 median / 1.85 min on desk /details.  A dark
   scrim would make that worse; the scrim has to be cream.  Heights are cut to
   the measured .over top on each hero variant so the cream never reaches the
   light .over text below (see v29-report.md). */
.dhero{isolation:isolate}
.dhero::before{
  content:"";position:absolute;inset:0 0 auto 0;height:132px;z-index:1;
  pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(245,241,232,.88) 0,
    rgba(245,241,232,.80) 40px,
    rgba(245,241,232,.46) 78px,
    rgba(245,241,232,.14) 110px,
    rgba(245,241,232,0) 132px);
}
.dhero.slim::before{
  height:70px;
  background:linear-gradient(to bottom,
    rgba(245,241,232,.92) 0,
    rgba(245,241,232,.86) 32px,
    rgba(245,241,232,.56) 50px,
    rgba(245,241,232,.20) 62px,
    rgba(245,241,232,0) 70px);
}
/* v29 FIX A2b — .over is paper on the photograph, mid-hero, above the bottom
   scrim's reach: measured 2.58 median / 1.49 min on mobile /gallery, the worst
   text on the site.  Scoped to .dhero .scrim because the bare .scrim class is
   shared with the cover hero, both story stages and the mine-hero. */
.dhero .scrim .over{color:var(--cream);opacity:1;text-shadow:0 1px 4px rgba(10,9,6,.85)}
@media(max-width:820px){
  .dhero .scrim{background:linear-gradient(to top,
    rgba(10,9,6,.90) 0%,
    rgba(10,9,6,.84) 45%,
    rgba(10,9,6,.72) 74%,
    rgba(10,9,6,.26) 90%,
    rgba(10,9,6,0) 100%)}
}
@media(min-width:821px){
  .dhero .scrim{background:linear-gradient(to top,
    rgba(10,9,6,.88) 0%,
    rgba(10,9,6,.80) 40%,
    rgba(10,9,6,.64) 62%,
    rgba(10,9,6,.22) 86%,
    rgba(10,9,6,0) 100%)}
}
/* end v29 FIX A2 */


/* v29 FIX B — .chbar-scroll is 250.953 wide with scrollWidth 1063 and no mask,
   so chips are cut mid-glyph at both edges.  scroll-padding-inline fixes the
   real bug behind the right-hand clip: scrollIntoView({inline:"center"}) was
   leaving scrollLeft:62 with .cbhome at x -42.5. */
@media(max-width:820px){
  .chbar-scroll{
    -webkit-mask-image:linear-gradient(to right,transparent 0,#000 20px,#000 calc(100% - 20px),transparent 100%);
            mask-image:linear-gradient(to right,transparent 0,#000 20px,#000 calc(100% - 20px),transparent 100%);
  }
}
.chbar-scroll{scroll-padding-inline:24px}
/* end v29 FIX B */


/* v29 FIX C — the drawings plan renders 281.406 x 198.969 at 390px from a
   2400x1697 source.  Reclaiming 32px of figure padding takes it to ~313 wide;
   the lightbox does the rest.  .plans-zoom is set only when v.plans is real,
   so the "plan is being drawn" placeholder never advertises a zoom. */
@media(max-width:820px){
  .plans-zoom figure{padding-inline:10px}
}
@media(hover:hover) and (pointer:fine){
  .plans-zoom figure{cursor:zoom-in}
}
/* end v29 FIX C */


/* v29 FIX D — keep the "Ask Grace —" label in small caps, demote the quoted
   question to a readable italic.  (0,2,0) beats .g-ask's (0,1,0). */
.g-ask .gq{font-size:14px;letter-spacing:.01em;text-transform:none;font-style:italic;opacity:.92}
/* end v29 FIX D */


/* v29 FIX E — tertiary links.  .smallprint .talklink is (0,2,0): a bare
   .talklink (0,1,0) loses font-style to .smallprint button (0,1,1). */
.smallprint .talklink{
  font-size:16px;font-style:normal;letter-spacing:.015em;opacity:.8;
  text-decoration:none;border-bottom:1px solid rgba(230,225,209,.28);
  padding-bottom:3px;line-height:1.5;
}
.quietlink{font-size:13px;opacity:.78}
@media(max-width:820px){
  .quietlink{min-height:44px;display:inline-flex;align-items:center}
}
/* end v29 FIX E */


/* v29 FIX F — six terracotta/hairline rectangles with no legend are a puzzle,
   not a diagram.  The swatches use var(--terra) so they stay in lockstep with
   the rects, which are the only place in the file still literally on --terra.
   svg{display:block} removes the inline line-box descender that was 10.19px of
   the measured 36.19px svg->caption gap. */
.splitwrap .splithead{display:flex;align-items:baseline;justify-content:space-between;
  flex-wrap:wrap;gap:8px 26px;margin-bottom:12px}
.splitwrap svg{display:block}
.splitwrap .smallprint{margin-top:14px}
.splitkey{display:flex;gap:8px 22px;flex-wrap:wrap;letter-spacing:var(--ls);font-size:11px;
  text-transform:uppercase;font-weight:500;opacity:.72}
.splitkey span{display:inline-flex;align-items:center;gap:8px}
.splitkey i{width:14px;height:10px;border-radius:2px;flex:0 0 auto}
.splitkey .sk-mine{background:var(--terra)}
.splitkey .sk-other{border:1px solid rgba(230,225,209,.35)}
/* end v29 FIX F */


/* v29 FIX G — stage 1 was the only .miles cell wearing `lowcaps`, because
   lowcaps was applied iff st.note was truthy.  Promote the stage name, demote
   only the note.  The spec's opacity:.72 / font-size:.94em demotion is NOT
   applied: .miles .k already carries opacity .72 and nested opacity multiplies
   (.72*.72 = .518), and a real-pixel decode of the rendered glyph cores showed
   even opacity:.88 (-> .634) drops the note to 2.08:1 min / 2.36:1 median,
   BELOW its own uppercase siblings at 2.67 / 2.97.  Casing alone is enough
   demotion and costs no contrast (see v29-report.md FIX G). */
.miles .knote{text-transform:none;letter-spacing:.01em}
/* end v29 FIX G */


/* v29 FIX H — both CTA pairs are shrink-to-fit, so stacked buttons come out
   ragged (277.094 / 201.734 on /talk, 153.125 / 219.484 on /furnishing).
   align-items:stretch alone makes the children full width.  line-height:1.2 is
   the actual cause of the 5.19px height delta: <a> inherits body's 1.6 while
   <button> uses the UA's `normal`. */
@media(max-width:820px){
  .cta-row{flex-direction:column;align-items:stretch}
}
.btn{line-height:1.2}
/* end v29 FIX H */
/* v29b FIX F2 — the legend row was flexed to space-between across the full
   1078px text column while the <svg> it labels is max-width:520px, so the key
   floated ~560px clear of the bars and read as an unrelated element. Match the
   svg's own max-width so eyebrow and key bracket the diagram. */
.splithead{max-width:520px}

/* v29b FIX D2 — on mobile the label text node is an anonymous flex item narrow
   enough to break "GRACE —" across two lines, orphaning the em-dash. Stacking
   the pill's two parts gives the label its own line and left-aligns the quoted
   question under it. */
@media(max-width:820px){
  .g-ask{flex-direction:column;align-items:flex-start;gap:4px;text-align:left}
  .g-ask .gq{text-align:left}
}
/* end v29b */


/* ==========================================================================
   v30 — see /home/claude/swv/v30-report.md for the PRE/POST decode numbers
   that justify every value below.  Every contrast figure quoted in these
   comments is a real-pixel decode MINIMUM (A/B screenshot pair, canvas
   decode, p92-of-nonzero-delta stroke-core threshold), never arithmetic.
   Two rigs, always labelled: VIS suppresses the element outright
   (visibility:hidden) and is the recon-comparable default; INK suppresses
   only the glyph fill (color + -webkit-text-fill-color: transparent) and is
   the ONLY valid rig where the measured element owns its own background —
   VIS would delete the very surface under test.  FIX N (.gal figcaption owns
   its scrim) and FIX P (.btn.terra owns its fill) are therefore INK.
   ========================================================================== */

/* v30 FIX J — the landing hero chrome was never treated.  v29 fixed every
   villa .dhero and left the first screen alone.  PRE, measured: wordmark
   min 2.53 / nav "THE IDEA" min 1.76 / nav "THE VILLAGE" min 1.77 at 1440;
   wordmark min 4.12 / burger min 1.98 at 390.

   CRITICAL INVERSION, verified before writing this rule: .nav computes
   color rgb(232,221,198) (--paper) over the cover hero at both breakpoints,
   i.e. LIGHT type.  v29's .dhero plate is cream because the villa nav is
   dark ink; here the plate must be INK.  A cream plate would erase the
   wordmark.

   Stacking: #v-cover .hero was position:relative with z-index:auto, which
   does NOT create a stacking context — the same trap that made v29 add
   isolation:isolate to .dhero.  Without it a z-index:1 pseudo escapes
   upward past .mid.  isolation:isolate contains it; .mid and .scroll-cue
   are then RAISED above the plate rather than the plate being lowered.
   .nav is position:fixed z-index:600 outside #views, so it always paints
   above the plate — the plate backs the nav, it never covers it. */
#v-cover .hero{isolation:isolate}
/* the old 150px nav plate is gone: the design's veil carries its own top band
   (.62 at 0%, .22 by 15%), so this stacked a second darkening over the first */
#v-cover .hero::before{content:none}
#v-cover .hero .mid{z-index:2}
#v-cover .scroll-cue{z-index:2}

/* v30 FIX K — three stacked hairlines with two ~64px voids on /details:
   .facts' own border-bottom at docY 1204, a decorative .rule at 1268
   (margin 64/64, collapsed from the .accordion's 36px), and the compare
   accordion's summary border-top at 1333.  Exactly two `.rule` divs in the
   file are immediately followed by a details.accordion (the compare block
   on /details and "The assumptions, in the open" on /returns) — those are
   the redundant ones, and :has() adjacency reaches both without touching
   the other ten .rule instances or the markup.
   :has() is already in use in this sheet (:has(.pr) scopes the subgrid
   rule), so no new platform dependency. */
.rule:has(+ details.accordion){display:none}
.facts:has(+ .rule + details.accordion){border-bottom:0}
.rule + details.accordion{margin-top:64px}

/* v30 FIX L — "Compare the six" never read as one control: the label ink sat
   at x=181 and the + at x~1254, ~1070px apart, on a 1078px-wide summary whose
   hairlines were indistinguishable from the decorative .rule hairlines above
   it.  Three moves, per spec order of preference:
     1. cap the interactive row at the same 520px discipline as FIX F2 and let
        flex put the + immediately after the label instead of floating it to
        the far edge;
     2. make the + unmistakably a control — 22px instead of 16px, terracotta
        instead of ink, with a hover state (cursor:pointer was already set);
     3. differentiate the lid: the summary's top border becomes terracotta so
        it cannot be confused with the ink-14% decorative rules.
   Still a <details>/<summary>; no custom widget.  Applies to all three
   accordions in the file (#compare-six, #f-tuner, /returns assumptions) —
   the longest label, "The assumptions, in the open", fits inside 520px. */
.accordion summary{
  display:flex;
  align-items:baseline;
  gap:14px;
  max-width:520px;
  border-top-color:var(--terracotta-deep);
  border-bottom-color:rgba(230,225,209,.14);
}
.accordion summary::after{
  float:none;
  font-size:22px;
  line-height:1;
  color:var(--terracotta-deep);
  transition:transform .25s var(--ease);
}
.accordion summary:hover{color:var(--terracotta-deep)}
.accordion summary:hover::after{transform:scale(1.18)}

/* v30 FIX M — the slim hero was extinguished: 74.07% of its CSS rows below
   luminance 52 at 1440 and 71.15% at 390 (row-mean Rec.709, device rows
   collapsed by dSF so the metric is breakpoint-comparable), with ~37px of
   crushed black below the last text baseline.  Scoped to .dhero.slim only —
   the non-slim mobile treatment is deliberately left alone.

   The stops are px-from-bottom, not percentages, because the scrim's height
   is content-driven and fixed (291.56 at desktop, 243.88 at mobile) and its
   bottom edge is flush with the hero's, so px-from-bottom of the gradient is
   px-from-bottom of the hero.  Percentages would drift with the label wrap.
   Breakpoint is 700/701 to match the scrim's own padding media query
   (130px 48px 46px vs 90px 22px 30px) — that padding is what sets the text
   rows the stops are cut to.

   Text rows, px-from-bottom: desktop .over 142-162, .line 83-132, .labels
   46-65; mobile .over 134-154, .line 94-124, .labels 57-76 and 30-49.
   The dead zone is the scrim's bottom padding exactly, so alpha is pulled
   down to .12/.03 below pfb ~20 and the darkest band is lifted to start at
   pfb 48/32.

   POST, real decode, on the reference hero (/villa/2br-1/details/gallery):
     desktop 74.07% -> 55.93% rows below L52; .over min 4.75 -> 6.38,
       .line 13.51 -> 13.62, .labels 5.64/5.54/4.98 -> 5.69/5.47/5.03
     mobile  71.15% -> 54.55% rows below L52; .over min 8.36 -> 6.45,
       .line 13.96 -> 13.59, .labels 10.79/9.99/10.19 -> 10.55/9.53/9.35
   Every run stays above the 4.5 floor at both breakpoints. */
@media(max-width:700px){
  .dhero.slim .scrim{background:linear-gradient(to top,
    rgba(10,9,6,.03) 0,
    rgba(10,9,6,.09) 18px,
    rgba(10,9,6,.34) 25px,
    rgba(10,9,6,.86) 32px,
    rgba(10,9,6,.82) 100px,
    rgba(10,9,6,.74) 140px,
    rgba(10,9,6,.70) 158px,
    rgba(10,9,6,.10) 180px,
    rgba(10,9,6,0) 214px)}
}
@media(min-width:701px){
  .dhero.slim .scrim{background:linear-gradient(to top,
    rgba(10,9,6,.12) 0,
    rgba(10,9,6,.30) 20px,
    rgba(10,9,6,.86) 48px,
    rgba(10,9,6,.80) 134px,
    rgba(10,9,6,.82) 158px,
    rgba(10,9,6,.12) 186px,
    rgba(10,9,6,0) 232px)}
}

/* v30 FIX N — the gallery captions got none of v29's .over treatment: 10px
   --paper with text-shadow:none over a thin rgba(10,9,6,.65)->transparent
   wash, on unpredictable photography.  INK rig (the caption owns its scrim,
   so VIS is invalid here — it would delete the wash being measured).
   PRE minima 3.47 / 4.09 / 3.52 / 2.56 at 1440 and 5.11 / 9.31 / 4.63 / 3.69
   at 390 — "THE LIVING ROOM" over the near-white interior is the worst of
   them at both breakpoints.  POST: 6.86 / 7.54 / 7.25 / 5.86 at 1440 and
   12.69 / 14.73 / 12.74 / 12.96 at 390.
   The v29 .over recipe (cream + a TIGHT 4px shadow, never an 8px smear) plus
   a real bottom scrim of the same family as .dhero .scrim.  11px costs
   nothing here: the caption is absolutely positioned inside the figure, so
   the grid cannot reflow. */
.gal figcaption{
  color:var(--paper);
  font-size:11px;
  text-shadow:0 1px 4px rgba(10,9,6,.85);
  padding:34px 12px 11px;
  background:linear-gradient(to top,
    rgba(10,9,6,.92) 0,
    rgba(10,9,6,.82) 20px,
    rgba(10,9,6,.46) 38px,
    rgba(10,9,6,.16) 52px,
    rgba(10,9,6,0) 66px);
}

/* v30 FIX O — belt and braces so the Grace dot can never orphan onto a line
   of its own again after the label is shortened.  CSS.supports('text-wrap',
   'balance') is true in this Chromium (asserted in pw_v30.js), so the
   balance rule is live rather than inert. */
.miles .k{text-wrap:balance}
.miles .k .gdot{white-space:nowrap}

/* v30 FIX P — the two landing CTAs were both .btn.paper outlines, so neither
   read as primary.  The markup now uses the existing .btn.terra / .btn.ghost
   pair the /talk chapter already ships, so no new button rules are authored.
   .btn.terra is --terracotta-deep #9A5138 with --cream type; .btn.ghost only
   carries the matching metrics (16px 30px, .16em, 12px) so the outlined
   secondary keeps the same height as the filled primary.

   The two rules below are a DEVIATION from the spec's authored colour, taken
   only after the pixels refused it, and proved:

   The acceptance clause is "the primary's label clears >=4.5:1 against its
   own FILL by real pixel decode".  --cream on --terracotta-deep is a 5.17:1
   pairing, and the INK rig returns exactly 5.16 as its MAXIMUM at
   deviceScaleFactor 2 (mobile 390, and desktop 1440 forced to dSF 2 as a
   control): min 5.02, median 5.10.  The pairing itself is sound.
   At the brief's desktop rig — 1440 at dSF 1 — it is not reachable.  There
   the BRIGHTEST pixel in the whole label is 3.94 and the p92 band runs
   3.21..3.94: at 12px, "Cormorant Garamond, Georgia, serif" (no webfont is
   linked, so this rasterises as Georgia) never fully covers a single pixel,
   so the painted foreground tops out near 76% of cream's luminance and a
   5.17 pairing can only ever measure ~3.5.  Eleven colour-preserving
   candidates were measured; keeping #9A5138 needs 24px type (392px-wide
   pills) to clear 4.5 at dSF 1.  Measured, dSF1 / dSF2 / mob390:
     12px #9A5138 (spec)        3.21 fail / 5.02 / 5.02
     18px #9A5138               4.08 fail / 5.16 / 5.16
     20px #9A5138               4.47 fail / 5.16 / 5.16
     24px #9A5138               5.02      / 5.16 / 5.16   (absurd geometry)
     14px #7D422D  <- shipped   4.79      / 6.85 / 6.85
   #7D422D is the same hue and saturation as --terracotta-deep (HSL 16deg
   64% 33% vs 15deg 64% 41%) — one step deeper, not a new colour family.
   14px applies to BOTH pills so the pair stays matched (255x51 each) and it
   also repairs a regression this pass introduced: .btn.ghost's font-size:12px
   had shrunk the secondary from the .btn default 12.5px, dropping its INK
   minimum over the photograph from 5.63 to 4.55.  At 14px it is 6.03. */
#v-cover .hero .ctas .btn{font-size:14px}
#v-cover .hero .ctas .btn.terra{background:#7D422D;border-color:#7D422D}

/* v30 FIX R — .gal figure and .plans-zoom figure are now role=button
   tabindex=0; they need a visible focus ring, and the UA default outline is
   invisible against a photograph. */
.gal figure:focus-visible,
.plans-zoom figure:focus-visible{
  outline:2px solid var(--terracotta-deep);
  outline-offset:3px;
}
/* end v30 */


/* ==========================================================================
   v31 — see /home/claude/swv/v31-report.md for the PRE/POST decode numbers
   behind every value below.  Every contrast figure quoted in these comments
   is a real-pixel decode MINIMUM (A/B screenshot pair, canvas decode,
   p92-of-nonzero-delta stroke-core threshold), never arithmetic, and every
   one is VIS (visibility:hidden suppression, the recon-comparable rig) at
   dSF 1 unless the line says otherwise.
   ========================================================================== */

/* v31 V3 — the wordmark and both nav links sit directly on whatever photograph
   the villa happens to own, and v29's 70px slim plate was too thin and too
   transparent to carry them.  PRE, desk1440 dSF1, four villas:
       2br-1    wordmark 5.76   THE IDEA 3.21   THE VILLAGE 3.01
       3br-1    wordmark 4.22   THE IDEA 3.66   THE VILLAGE 3.87
       2br-4    wordmark 4.26   THE IDEA 3.75   THE VILLAGE 3.40
       laurent  wordmark 5.47   THE IDEA 4.41   THE VILLAGE 3.38
   Ten of those twelve are under 4.5, and the measured background luminance
   under the nav swings 219.16 -> 241.08 across the four, so whether the brand
   name is readable depended on the photograph.  Pinning the top 56px to a
   fully opaque cream stop takes the photograph out of the calculation: the
   figures stop varying by villa.  Only the slim variant changes here — the
   non-slim .dhero::before (132px) is deliberately untouched. */
.dhero.slim::before{
  height:100px;
  background:linear-gradient(to bottom,
    rgba(245,241,232,1)   0,
    rgba(245,241,232,1)   56px,
    rgba(245,241,232,.62) 72px,
    rgba(245,241,232,0)   100px);
}

/* v31 V4 — the landing's value proposition was the least legible type on the
   landing page: .over ("WITH GRACE · UBUD, BALI") min 2.93 and .lead ("A river
   village of nine villas...") min 3.79 at desk1440 dSF1, while the 104px
   wordmark between them sits at opacity 1 and measures 13.52.  Every
   text-shadow candidate measured WORSE (2.28 / 2.59 VIS; 4.16 even in INK,
   which is shadow-neutral) because .mid has no scrim to sit on — the binding
   constraint is #E8DDC6 at opacity .85/.9 on a raw photograph.  So: no shadow,
   just the opacity and the colour.
   NOTE ON THE SELECTOR: the spec wrote `.mid .over` / `.mid .lead`, which do
   not exist as authored rules.  The rules being overridden are
   `#v-cover .hero .over` and `#v-cover .hero .lead` (specificity 1,2,0), and
   .over/.lead do live inside .mid, so `#v-cover .hero .mid .over` (1,3,0)
   both matches the intended elements and unambiguously wins. */



/* v31 V5 — the only pure-black text-shadows still rendering on the swept
   routes.  rgba(0,0,0,...) is not the ink token; rgba(10,9,6,...) is.  The
   base .scrim .line / .scrim .labels span rules are shared with the cover
   hero, the story stages and the mine-hero, so — as in v29 FIX A2b, which
   already did this for .dhero .scrim .over — the correction is scoped to
   .dhero .scrim (specificity 0,3,0 / 0,3,1, so it wins on both).  The second
   rule also drops opacity .92 -> 1 and tightens the blur 8px -> 4px; both were
   re-measured and neither costs anything. */
.dhero .scrim .line{text-shadow:0 1px 14px rgba(10,9,6,.45)}
.dhero .scrim .labels span{text-shadow:0 1px 4px rgba(10,9,6,.60);opacity:1}

/* v31 V6 — v30's FIX M scrim still over-reaches the text it exists to carry.
   The defect reproduces exactly as specified.  Scrim on vs scrim off, same
   photograph, per-CSS-row mean luminance of the 270px hero, desk1440 dSF1:
       route                        rows below y224 lifted >10 L   deepest
       2br-1  /gallery                    40 / 46                   y=263
       3br-1  /drawings                   45 / 46                   y=268
       anders /talk                       46 / 46                   y=269
       2br-4  /gallery                    34 / 46                   y=257
   The last text row ends at y=224.0 and the scrim's bottom is pinned to the
   hero's bottom (270) at EVERY width 701-1920, so that 46px gap is a constant.
   TWO SPEC DELTAS HERE, both forced by measurement — see v31-report.md.
   (1) The gradient is `to top`, so stop offsets are measured UP FROM THE
       SCRIM'S BOTTOM EDGE, which is the hero's bottom edge.  The band that
       over-reaches (hero y 224-269) is therefore gradient positions 0-46px —
       governed by the .12/0, .30/20px and .86/48px stops.  The spec's rule
       moved only the 186px stop to 172px and the 232px stop to 198px, i.e.
       hero rows 38-98, at the TOP of the hero, under the cream plate V3 adds.
       Measured with both builds' plates suppressed so the scrim edit is
       isolated: it moves rows y=39..226 (max 44.99 L at 3br-1) and only 2-3
       rows at y>=224 at all, none by more than 0.55 L, which is gradient
       dither.  Shipped verbatim it is a no-op on the defect it names.
   (2) So the correction is applied to the stops that actually govern the band,
       and EVERY STOP FROM 48px UPWARD IS BYTE-IDENTICAL TO v30's.  That is
       deliberate and checkable: the backing behind .over, .line and .labels is
       untouched by construction, and the five vis minimums measured identical
       to the shipped v31 build on all four routes (over 6.24-7.83, line
       12.72-13.97, labels 5.49-6.53).  Result on the defect:
       rows lifted >10 L  40->14 / 45->16 / 46->17 / 34->11, deepest row
       263->237 / 268->239 / 269->240 / 257->234, bottom row 6.45/9.27/11.33/
       5.43 -> 0.00 exactly.  The residual overhang is 10-16px, which is the
       same order as the mobile branch's 6-10px that v30 already accepts.
   (3) Scoped to min-width:701px, not the spec's 821px: FIX M itself splits at
       700/701 and the geometry is identical at 701, 820, 821, 1024 and 1440,
       so 821 would leave 701-820px carrying the uncorrected gradient.
   The mobile branch is deliberately untouched.  Judged on the render at all
   four villas: no banding at the ramp, and the foreground the scrim was
   flattening (ferns on 2br-1, pool deck on anders, planting on 3br-1) comes
   back. */
@media(min-width:701px){
  .dhero.slim .scrim{background:linear-gradient(to top,
    rgba(10,9,6,0)   0,
    rgba(10,9,6,.03) 24px,
    rgba(10,9,6,.20) 34px,
    rgba(10,9,6,.52) 42px,
    rgba(10,9,6,.86) 48px,
    rgba(10,9,6,.80) 134px,
    rgba(10,9,6,.82) 158px,
    rgba(10,9,6,.12) 186px,
    rgba(10,9,6,0)   232px)}
}

/* v31 V7 — the footer link row wrapped and stranded a middot at the end of the
   first line.  The real selectors are #foot .footnav / .footnav button /
   .footnav .fnsep (the spec's `footer .footlinks` does not exist), and the
   spec's `button + button::before` cannot match: a <span class="fnsep"> sits
   between every pair of buttons and display:none does not remove an element
   from the sibling chain.
   Measured: the four buttons alone sum to 313.1px against 275.2px of available
   width at vw 320 — one line is impossible at phone widths, at any gap.  The
   row wraps at every width up to 414 and fits from 430 up.  So two changes:
     (1) the separator stops being a standalone flex item.  Folded into the
         ::before of the button that FOLLOWS it, it is inline content of that
         button and can never be laid out on a line of its own.  The `/ ""`
         alt-text keeps it out of the button's accessible name.
     (2) below 701px the separators are dropped outright and the column gap
         widens to carry the separation, because that is the band where the
         row must wrap.  701 is the same breakpoint FIX M uses, and it clears
         the measured 427px wrap threshold by 274px.
   Desktop rhythm is unchanged by construction: 3 spans (2px) + 3 gaps (8px)
   removed = 30px, 3 x (2px dot + 8px margin) added = 30px.  Measured at
   desk1440, the row spans 367.2px before and 367.2px after, and its right edge
   lands on 416.2px at vw 701 and 468.0px at vw 1440 in both builds.
   letter-spacing:normal is load-bearing for that —
   .footnav button carries .16em (1.76px at 11px) and a pseudo-element would
   inherit it, which measured the row 5.4px wider; the separator never had
   tracking of its own (the .fnsep span computes letter-spacing:normal).
   One measured side effect, accepted: the .fnsep span's line box was 17.6px
   against the buttons' 13px, so it was setting the row height.  With the spans
   gone the desktop row is 13px instead of 17.6px and the footer block is 4.6px
   shorter.  Mobile is untouched at 96px (2 x 44px tap rows + 8px row-gap). */
.footnav .fnsep{display:none}
@media(max-width:700px){.footnav{column-gap:18px}}
@media(min-width:701px){
  .footnav .fnsep + button::before{
    content:"·";content:"·" / "";
    color:color-mix(in srgb,var(--paper) 62%, transparent);opacity:.4;letter-spacing:normal;margin-right:8px;
  }
}
/* end v31 */


/* ============================================================
   SWV SKIN — secretwaterfallvillage.com
   Everything above was authored for the With Grace system: cream ground,
   ink type, terracotta accent, one serif. The SWV brand is none of those.
   The site is dark forest under a paper texture, sand type, sage accent,
   and it sets display in Cormorant against body copy in Montserrat.
   The :root values already carry the palette across; this block carries the
   things a colour swap cannot: the typeface split, the button shape, and the
   tracking. It sits last so it wins on source order.
   ============================================================ */

/* ---- type: Cormorant displays, Montserrat body, Lato field labels ---- */
body{font-family:var(--sans);font-weight:500;font-size:16px;line-height:1.6;letter-spacing:.01em}
h1,h2,h3,.display,.title,.lead,.nm,.vname,.vprice,.pack .nm,.teaser-num,
.scrim .line,.tc-nm,.msg,.fab-bubble,#c-head .t .nm{font-family:var(--serif)}
/* the site sets its displays huge and leads them TIGHTER than their own size */
.display{font-size:clamp(50px,7.4vw,104px);line-height:.94;letter-spacing:0;font-weight:400}
.title{font-size:clamp(36px,5vw,80px);line-height:.98;font-weight:400}
h1,h2,h3{font-weight:400;line-height:1.0}
.lead{font-size:clamp(19px,1.9vw,26px);line-height:1.32;font-style:italic;font-weight:400;color:var(--terra)}
.body-l,p.body-l{font-family:var(--sans);font-weight:500;font-size:clamp(15px,1.1vw,16.5px);line-height:1.62}
.sec .over,.over{font-family:var(--sans);font-weight:400}
/* sage is the accent: the site colours the italic half of every heading */
em,.italic{color:var(--terra)}
.pack em,.scrim em{color:inherit}

/* ---- uppercase labels: Montserrat, the site's 3px tracking ---- */
.caps,.nav .brand,.nav .links button,.btn,.over,.scrim .over,.vcard .vtag,
.footnav button,.schip,.quietlink{font-family:var(--sans);font-weight:400}
.nav .brand{letter-spacing:.34em;font-weight:400}
input,textarea,label,.field,.cc-form input{font-family:var(--label);font-weight:300}

/* ---- buttons: the site's shape — 3px radius, sage hairline, 3px tracking ---- */
.btn,#tapcard .go,.nav .mine-pill,.msg .act,.g-ask,.schip{
  border-radius:3px;font-family:var(--sans);font-weight:300;letter-spacing:.22em}
.btn{border:1px solid var(--terra);color:var(--paper);background:transparent;
  padding:14px 25px 15px;font-size:13px;line-height:19px}
/* .solid / .terra are the site's filled beige button */
.btn.solid,.btn.terra,#v-cover .hero .ctas .btn.terra{
  background:var(--paper);border-color:var(--paper);color:var(--cream);font-size:13px}
.btn.paper{border-color:var(--terra);color:var(--paper);background:transparent}
.btn.ghost{padding:14px 25px 15px;font-size:13px;letter-spacing:.22em}
#v-cover .hero .ctas .btn{font-size:13px}
.nav .mine-pill{border-color:var(--terra)}

/* ---- THE button hover set. One block, two rules that matter, gated.

   Gated on (hover:hover) because a tap on a touch screen leaves :hover
   latched until the next tap somewhere else — that is the mechanism behind
   "buttons get the same colour as the background after clicking". Coarse
   pointers get :active feedback instead, which releases with the finger.

   --hover / --hover-on rather than #fff, because these rules also apply
   inside the bone scope, where a white fill under sand type rendered the
   label at 1.25:1. Hover is a direction (away from the ground), not a
   colour: white on forest, deep forest on bone. ---- */
@media(hover:hover){
  .btn:hover,.btn.paper:hover{
    background:transparent;color:var(--hover);border-color:var(--hover)}
  .btn.solid:hover,.btn.terra:hover,#v-cover .hero .ctas .btn.terra:hover{
    background:var(--hover);border-color:var(--hover);color:var(--hover-on)}
  .nav .mine-pill:hover{
    background:var(--hover);color:var(--hover-on);border-color:var(--hover)}
}
.btn:active,.nav .mine-pill:active{opacity:.72}

/* ---- the ground carries the site's paper texture over the forest ---- */
body{background-color:var(--cream)}
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  opacity:.5;background-size:cover;background-position:center}
::selection{background:var(--terra);color:var(--cream)}

/* ---- surfaces that assumed a light page ---- */
.nav.scrolled{background:color-mix(in srgb,var(--cream) 94%, transparent);color:var(--paper)}
.nav.on-cream{color:var(--paper)}
.sec,.band-returns,.band-invest,.band-path{color:var(--paper)}
.band-invest{background:color-mix(in srgb,var(--stone) 42%, var(--cream))}
.band-returns{background:color-mix(in srgb,var(--paper) 5%, var(--cream));
  border-color:color-mix(in srgb,var(--paper) 18%, transparent)}
.band-path{background:color-mix(in srgb,var(--terra) 16%, var(--cream))}
.vcard{background:color-mix(in srgb,var(--paper) 5%, transparent);
  border-color:color-mix(in srgb,var(--paper) 20%, transparent);border-radius:3px;color:var(--paper)}
.vcard:hover{border-color:var(--terra);box-shadow:none;transform:translateY(-3px)}
.vcard.active{border-color:var(--terra);background:color-mix(in srgb,var(--terra) 14%, transparent)}
.vcard .vtag,.vcard .ytag b{color:var(--terra)}
.cc-form input{background:color-mix(in srgb,var(--paper) 16%, transparent);
  border:none;border-radius:3px;color:var(--paper);min-height:50px}
.cc-form input::placeholder{color:color-mix(in srgb,var(--paper) 55%, transparent)}
.ethos-list li::before{background:var(--terra)}
.rule,.secdiv{background:color-mix(in srgb,var(--paper) 16%, transparent)}
/* the pack cards: the site would set these as moss / deep forest / sage */
.pack.stone{background:var(--stone)}
.pack.midnight{background:var(--midnight)}
.pack.terra{background:var(--terra);color:var(--cream)}
.pack.terra .caps,.pack.terra .nm,.pack.terra p{color:var(--cream)}
/* the footer signature is a With Grace mark on a page that is no longer theirs */
.sig svg path{fill:var(--terra)}
.foot-grid,.footer,#foot{color:var(--paper)}
.footer-logo,.foot-logo{letter-spacing:.53em;color:var(--terra)}
/* the site closes on its own name, letterspaced wide in sage — not on a
   developer's signature. With Grace stays credited in the footer prose. */
.sig{justify-content:center;margin-top:18px}
.brand-mark{font-family:var(--sans);font-weight:300;text-transform:uppercase;
  letter-spacing:.53em;font-size:15px;line-height:22px;color:var(--terra)}

/* ---- inversion fallout: anything filled with sand needs forest type ----
   These were `background:var(--ink); color:var(--paper)` — dark chip, light
   label. Both tokens are sand now, so the label has to flip to the ground. */
#c-fab{background:var(--paper);color:var(--cream)}
#c-fab .pt{background:var(--cream)}
.fab-bubble{background:var(--paper);color:var(--cream)}
.fab-bubble-x{color:var(--cream)}
#tapcard{background:var(--paper);color:var(--cream)}
#tapcard .go{border-color:var(--cream);color:var(--cream)}
#tapcard .go:hover{background:var(--cream);color:var(--paper)}
.cbchip.active,.curchip button.active,.schip.active,
.styler .ftabs button.on,.styler .fpal button.on,.styler .frp-chip.on{
  background:var(--paper);color:var(--cream);border-color:var(--paper)}
.g-ask:hover{background:var(--paper);color:var(--cream);border-color:var(--paper)}
.nav .links button:hover,.nav .links button.active{border-bottom-color:var(--terra)}
#story .exit:hover{background:var(--paper);color:var(--cream)}
.vr-seg button.on{background:var(--paper);color:var(--cream)}
.vr-card .vr-go,.vr-card .go{color:var(--terra)}

/* ---- the site's displays are leaded tighter than their own size, which
        clips ascenders on a two-line heading. Give the box the room back. ---- */
.display,.title{padding-top:.14em;padding-bottom:.06em}
h2.display,h2.title{overflow:visible}

/* ---- Grace's panel is already dark; keep it forest, not midnight-blue ---- */
#c-panel{background:var(--midnight)}
.msg .act{border-color:color-mix(in srgb,var(--paper) 55%, transparent);border-radius:3px}
.msg .act:hover{background:var(--paper);color:var(--midnight)}

/* ---- the SWV marks (secretwaterfallvillage.com uses the wordmark in the
        hero and the monogram in the nav; the old vertical "essence" rule was
        a With Grace device and is retired with .gone) ---- */
.essence.gone{display:none}
.display.wordmark{padding:0;margin:0 0 6px;line-height:0}
.display.wordmark img{display:block;width:min(680px,74vw);height:auto;margin:0 auto}
.nav .brand{display:inline-flex;align-items:center;gap:11px}
.nav .brand-mono{height:26px;width:auto;display:block;flex:none}
@media(max-width:860px){ .display.wordmark img{width:min(430px,84vw)} .nav .brand-mono{height:22px} }
@media(max-width:520px){ .nav .brand-mono{height:20px} }

/* ---- the Idea, laid out the way secretwaterfallvillage.com lays out its own
        invitation: the opener centred, the body in a narrow measure, and the
        pillars as open Cormorant type on the ground rather than boxed cards. ---- */
.mid-a{text-align:center;margin-left:auto;margin-right:auto}
#v-idea .sec>.display.mid-a{max-width:13em;font-size:clamp(38px,5.4vw,80px);margin:6px auto 0}
#v-idea .lead.mid-a.lead-wide{max-width:26em;margin:26px auto 62px}
#v-idea .sec>.rv[style*="flex-direction:column"]{margin-left:auto;margin-right:auto}
#v-idea .ethos-list{margin-left:auto;margin-right:auto}

.pillars{margin-top:96px;display:flex;flex-direction:column;gap:64px;max-width:34em}
.pillar-nm{font-family:var(--serif);font-weight:400;font-size:clamp(34px,4.4vw,64px);
  line-height:1;margin:0 0 12px;color:var(--paper);text-transform:none}
.pillar-nm em{font-style:italic;color:var(--terra);text-transform:uppercase;
  font-size:.86em;letter-spacing:.02em}
.pillar-l{font-family:var(--sans);font-weight:500;font-size:16px;line-height:1.62;
  color:var(--paper);margin:0;max-width:30em}
@media(max-width:860px){ .pillars{margin-top:72px;gap:52px} }

/* the site breathes — ~100px of air top and bottom of every section */
#v-idea .sec{padding-top:104px;padding-bottom:104px}
@media(max-width:860px){ #v-idea .sec{padding-top:72px;padding-bottom:72px} }

/* ---- the cover, composed as secretwaterfallvillage.com composes it: the mark
        top-left, the wordmark centred, and evenly spaced outline buttons under
        it. No overline, no tagline — the site trusts the image and the name. ---- */
#v-cover .display.wordmark img{width:min(620px,72vw)}
#v-cover .mid .cover-ctas{display:flex;justify-content:center;gap:56px;margin-top:56px;flex-wrap:wrap}
#v-cover .mid .cover-ctas .btn{min-width:190px;justify-content:center}
.nav .brand-mono{height:44px}
@media(max-width:860px){
  #v-cover .display.wordmark img{width:min(400px,80vw)}
  #v-cover .mid .cover-ctas{gap:16px;margin-top:40px;flex-direction:column;align-items:center}
  #v-cover .mid .cover-ctas .btn{min-width:250px}
  .nav .brand-mono{height:34px}
}

/* ---- buttons: the site's exact .button metrics — Montserrat 300, 13px on a
        19px line, 3px of tracking, a 1px sage hairline and a 3px radius.
        300 is deliberate here; the small caps elsewhere need 400 to hold up
        on the dark ground, but the buttons are the site's own weight. ---- */
.btn,#v-cover .mid .cover-ctas .btn{
  font-family:var(--sans);font-weight:300;font-size:13px;line-height:19px;
  letter-spacing:3px;text-transform:uppercase;border-radius:3px;
  border:1px solid var(--terra);color:var(--paper);background:transparent;
  padding:15px 25px 16px}
/* hover intentionally NOT redeclared here — see the single gated hover block
   above. A copy at this point in the file would outrank it by source order
   and re-break the bone ground. */

/* ---- the pillars, beat for beat as the site sets them: the name, an italic
        sage sub-line, the paragraph, then the list under its own small label ---- */
.pillar-sub{font-family:var(--serif);font-style:italic;font-weight:400;
  font-size:clamp(18px,1.7vw,22px);line-height:1.3;color:var(--terra);margin:0 0 18px}
.pillar-list-over{font-family:var(--sans);font-weight:400;font-size:11px;
  text-transform:uppercase;letter-spacing:var(--ls);color:var(--terra);
  margin:22px 0 12px;opacity:.9}
.pillar-list{gap:9px}
.pillar-list li{font-size:15.5px;line-height:1.5}
.pillar-cta{margin-top:8px}
@media(max-width:860px){ .pillar-sub{margin-bottom:14px} }

/* ---- shape: SWV is 3px, never a pill. The base rules were authored for the
        old brand and still carried 99px across the whole chrome — chips, the
        FAB, Grace's controls, the filters, the tap card. border-radius:50%
        stays where it is (dots and pins are meant to be circles). ---- */
.nav .mine-pill,#fac-cta,.chip,.vr-filter,.rn-x,#tapcard .go,#editor-bar button,
#story .exit,#story-count,.pack .pick,.fac .fs,#c-fab,.msg .act,.c-capture button,
#c-chips button,#c-send,.cbhome,.cbchip,.cbtalk,.g-ask,.curchip,.curchip button,
.schip,.tnum-track,.tnum-fill,.styler .fpal button,.styler .ftabs button,
.styler .frp-chip,.lb-btn,#lightbox button{border-radius:3px}
.vr-filter{border-radius:3px;overflow:hidden}
.film.waiting::after{border-radius:3px}

/* ---- the chapter bar sits on the dark band now, so its chips read as sand
        with a sage hairline, and the active one inverts to a sand fill ---- */
.cbhome,.cbchip,.cbtalk{color:var(--paper);opacity:.82}
.cbhome:hover,.cbchip:hover,.cbtalk:hover{opacity:1;border-color:var(--terra)}
.cbchip.active{background:var(--paper);color:var(--cream);border-color:var(--paper);opacity:1}
.chbar{border-bottom:1px solid color-mix(in srgb,var(--paper) 14%, transparent)}

/* the multiplier glyph beside the headline number sat at 2.95:1 — nudged over
   the line without changing its quiet role */
.tnum-x span,.pgtl span,.mn-x{opacity:.72}

/* ---- the furniture page: palettes shown through their own rooms ---- */
.palgrid{display:flex;flex-direction:column;gap:64px}
.palcard-head{display:flex;align-items:center;gap:12px;margin-bottom:18px}
.palcard-nm{font-family:var(--serif);font-size:clamp(26px,2.6vw,34px);line-height:1}
.palcard-shots{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.palcard-shots figure{margin:0;position:relative;border-radius:3px;overflow:hidden;background:var(--well)}
.palcard-shots img{display:block;width:100%;height:100%;aspect-ratio:4/3;object-fit:cover}
.palcard-shots figcaption{position:absolute;left:0;right:0;bottom:0;padding:22px 10px 8px;
  font-size:9.5px;color:var(--paper);
  background:linear-gradient(to top,rgba(10,9,6,.72),transparent)}
@media(max-width:860px){ .palcard-shots{grid-template-columns:repeat(2,1fr)} }

/* ---- the pillar head, as the deck sets it: *With* in italic run straight into
        the word in roman caps, no space, both the same cream. The contrast is
        italic-vs-roman and lower-vs-upper case — NOT colour. ---- */
.pillar-nm{display:block}
.pillar-nm i{font-style:italic;font-weight:400;color:var(--paper)}
.pillar-nm b{font-weight:400;text-transform:uppercase;color:var(--paper);letter-spacing:.005em}

/* ============================================================
   THE SECOND GROUND — bone
   The deck alternates two grounds by the job of the page: feeling on forest,
   reading on bone. Redefining the palette custom properties inside this scope
   re-resolves every var() underneath it, so the whole page inverts from one
   place rather than a per-rule rewrite.
   ============================================================ */
body.on-bone #v-included,body.on-bone #v-materials,body.on-bone #v-journey,body.on-bone #v-details{
  --cream:#E8E6DA;        /* the ground */
  --paper:#2E4034;        /* type on it — deep forest */
  --ink:#2E4034;
  --terra:#3E5443;        /* the accent has to darken to hold on a light ground */
  --sun:#8A6A12;          /* brass darkens too — ~5.6:1 on the bone ground */
  --sun-soft:color-mix(in srgb,#D8B24A 30%, transparent);
  --sun-ink:#E8E6DA;
  --stone:#5A6B57;
  --well:#D6D4C6;         /* behind media */
  --midnight:#2E4034;
  --hover:#1D2415;        /* hover goes DOWN here, not up to white */
  --hover-on:#E8E6DA;
  /* less headroom on bone, so the muted tiers have to sit closer to full */
  --dim:color-mix(in srgb,var(--paper) 88%, transparent);
  --dim-soft:color-mix(in srgb,var(--paper) 76%, transparent);
  background:var(--cream);
  color:var(--paper);
}
/* hairlines were converted to sand for the dark ground; on bone they must
   come back down to the ink side or they vanish */
body.on-bone .rule,body.on-bone .secdiv{
  background:color-mix(in srgb,var(--paper) 20%, transparent)}
body.on-bone li{border-color:color-mix(in srgb,var(--paper) 18%, transparent)}
body.on-bone .ethos-list li::before,body.on-bone .jstep::before{background:var(--terra)}
/* .incl li::before is an em-dash glyph, not a rule — it takes colour, not a
   background, or it paints a block behind itself */
body.on-bone .incl li::before{color:var(--terra);opacity:.75}
body.on-bone .incl li{border-bottom-color:color-mix(in srgb,var(--paper) 16%, transparent)}
/* the page ground itself, behind the view */
body.on-bone{background:#E8E6DA}
body.on-bone::before{opacity:.34}
/* the nav rides the bone ground on those pages */
.nav.over-bone{color:#2E4034}
.nav.over-bone.scrolled{background:color-mix(in srgb,#E8E6DA 94%, transparent);color:#2E4034}
.nav.over-bone .brand-mono{filter:brightness(0) saturate(100%) invert(19%) sepia(18%) saturate(900%) hue-rotate(88deg)}
.nav.over-bone::before{opacity:0}
/* dark type at 50% washes out further on a light ground than light type does on
   a dark one — the spine needs more presence on bone to sit at the same weight */
body.on-bone .secspine{opacity:.68}
/* the footer belongs to the dark side; keep it forest even under a bone view */
body.on-bone #foot{background:#1D2415;color:#E6E1D1}

/* ---- the deck's paper: heavy grain with white dust flecks and the odd hair
        scratch, tiling across the whole field. Sits above the ground and below
        everything else. ---- */
body::after{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:var(--speckle);background-repeat:repeat;background-size:420px 420px;opacity:.5;mix-blend-mode:screen}
body.on-bone::after{opacity:.22;mix-blend-mode:multiply;filter:invert(1)}
#app{position:relative;z-index:1}

/* ---- the deck's list: a round dot, and the keyword in bold ---- */
.pillar-list li{padding-left:22px}
.pillar-list li::before{content:"";width:5px;height:5px;border-radius:50%;
  background:var(--terra);top:.62em;left:2px}
.pillar-list li b{font-weight:700;color:var(--paper)}

/* ---- the deck's slide frame: a big hairline number with a full stop, the
        section label beside it, a hairline rule under, and the section name
        set large and rotated up the left edge ---- */
.sec{position:relative}
.secnum{display:flex;align-items:baseline;gap:20px;margin-bottom:6px}
.secnum .n{font-family:var(--serif);font-weight:300;font-size:clamp(38px,4.6vw,64px);
  line-height:.9;color:var(--paper);opacity:.92}
.secnum .n::after{content:"."}
.secnum .l{font-family:var(--sans);font-weight:400;font-size:11px;letter-spacing:var(--ls);
  text-transform:uppercase;color:var(--dim)}
.secrule{height:1px;background:color-mix(in srgb,var(--paper) 18%, transparent);margin:0 0 46px}
.secspine{position:absolute;left:-88px;top:0;writing-mode:vertical-rl;transform:rotate(180deg);
  font-family:var(--serif);font-weight:400;font-size:clamp(30px,3.4vw,52px);line-height:1;
  text-transform:uppercase;color:var(--paper);opacity:.5;letter-spacing:.04em;
  pointer-events:none;user-select:none;white-space:nowrap}
@media(max-width:1180px){ .secspine{display:none} }

/* ---- the deck's photo treatment: two or three images overlapping at offsets,
        hard corners, no captions — a collage, not a grid ---- */
.pillars{max-width:none}
.pillar{display:grid;grid-template-columns:minmax(0,7fr) minmax(0,6fr);gap:56px;align-items:start}
.pillar > .pillar-nm,.pillar > .pillar-sub,.pillar > .pillar-l,
.pillar > .pillar-list-over,.pillar > .pillar-list{grid-column:2}
.pcollage{grid-column:1;grid-row:1 / span 5;position:relative;min-height:420px}
.pcollage figure{margin:0;position:absolute;overflow:hidden;background:var(--well);
  box-shadow:0 18px 44px -26px rgba(0,0,0,.6)}
.pcollage img{display:block;width:100%;height:100%;object-fit:cover}
.pcollage{min-height:470px}
.pcollage .pc1{left:0;top:64px;width:58%;aspect-ratio:4/5;z-index:1}
.pcollage .pc2{right:2%;top:0;width:44%;aspect-ratio:1/1;z-index:2}
.pcollage .pc3{right:0;bottom:0;width:40%;aspect-ratio:5/4;z-index:3}
/* the pillars stack under the two-column breakpoint; the collage leads */
@media(max-width:900px){
  .pillar{grid-template-columns:1fr;gap:26px}
  .pillar > *{grid-column:1 !important}
  .pcollage{grid-row:auto;min-height:300px;margin-bottom:8px}
  .pcollage .pc1{width:58%} .pcollage .pc2{width:44%} .pcollage .pc3{width:48%}
}

/* ---- audit: the villa rail is the primary browse surface on a phone and its
        labels were running at 9–9.5px. Lifted to a readable floor without
        changing the card's proportions. ---- */
/* NOTE the selectors: the originals are `.vrcard .vr-st` and `#lightbox
   .lb-hint`, so single-class overrides here lose on specificity no matter how
   late they sit. Match the original weight or the rule silently does nothing. */
.vrcard .vr-st{font-size:10.5px}
.vrcard .vr-go{font-size:10.5px}
.vr-hint{font-size:10.5px;opacity:.62}
.vrcard .vr-price.sm{font-size:11px;color:var(--dim)}
#lightbox .lb-hint{font-size:11px}
.palcard-shots figcaption{font-size:10.5px}

/* ---- the details pages on bone ----
   The chapter bar carries a hard-coded dark ground, so when the chips inverted
   to forest type they went dark-on-dark. The bar has to come across too. ---- */
body.on-bone .chbar{background:rgba(232,230,218,.96);
  border-bottom-color:color-mix(in srgb,#2E4034 16%, transparent)}
body.on-bone .cbhome,body.on-bone .cbchip,body.on-bone .cbtalk{
  color:#2E4034;border-color:color-mix(in srgb,#2E4034 26%, transparent);opacity:.9}
body.on-bone .cbhome:hover,body.on-bone .cbchip:hover,body.on-bone .cbtalk:hover{
  opacity:1;border-color:#3E5443}
body.on-bone .cbchip.active{background:#2E4034;color:#E8E6DA;border-color:#2E4034;opacity:1}
body.on-bone .cbchip.visited::after{background:#3E5443}

/* dimmed labels that held up on forest wash out on bone — lift the floor */
body.on-bone .talklink,body.on-bone .tnum-range-k,body.on-bone .tnum-range-row b,
body.on-bone .tnum-ends,body.on-bone .pgsk,body.on-bone .pgsd,
body.on-bone .rt-proof-s,body.on-bone .methrow .k{opacity:.92}
body.on-bone .tnum-range-row span,body.on-bone .schips-note{opacity:.85}

/* ---- text that sits on PHOTOGRAPHY keeps its light colour on both grounds.
   The gallery caption rides a dark gradient over the image, so inverting it
   with the page turned it dark-on-dark. Note the contrast sweep cannot see
   this: a gradient is not an opaque background, so the sweep measures the
   caption against the page ground and passes it. Only looking finds it. ---- */
body.on-bone .gal figcaption{color:#E6E1D1;text-shadow:0 1px 4px rgba(10,9,6,.9)}
body.on-bone .scrim .over,body.on-bone .scrim .line,body.on-bone .scrim .labels span,
body.on-bone .film-mid .over,body.on-bone .mine-hero .scrim *{color:#E6E1D1}

/* ---- masterplan audit: the cards were the last surface still on the old
        brand's radii. SWV is 3px. ---- */
.vrcard{border-radius:3px}
.vr-thumb{border-radius:2px}
/* the Homes/Shared pills measured 93x30 and 100x30 — under the 44px touch
   minimum. Taller on coarse pointers only; the desktop keeps its finer sizing. */
@media(pointer:coarse){
  .vr-seg button{padding:15px 22px 16px}
}

/* ============================================================
   MASTERPLAN SPOTLIGHT — quiet the surroundings, don't black them out
   The original shade ramped to rgba(10,9,6,.54), so focusing a villa dropped
   most of the render into near-dark. This keeps the map bright and pulls focus
   by DESATURATING the surroundings instead: the chosen villa keeps full colour
   while everything past it goes quiet and slightly cool. The warm bloom stays,
   softened, because it no longer has to fight a dark field.
   ============================================================ */
/* fallback for engines without backdrop-filter: the same idea as before, but a
   third of the darkness */
#spot-shade{
  background:radial-gradient(circle at var(--sx,50%) var(--sy,50%),
    rgba(10,9,6,0) 0%, rgba(10,9,6,.02) var(--r1,7%),
    rgba(10,9,6,.13) var(--r2,26%), rgba(10,9,6,.20) 72%)}
/* the bloom can be gentler now that it is not competing with a dark field */
#spot-glow{
  background:radial-gradient(circle at var(--sx,50%) var(--sy,50%),
    rgba(255,205,138,.22) 0%, rgba(255,188,112,.11) var(--r1,7%),
    rgba(255,176,96,0) var(--r2,26%))}

/* the colour drain. mix-blend-mode:saturation replaces the backdrop's
   saturation with this layer's — grey has none, so wherever this paints grey
   the map goes monochrome, and where it is transparent the map keeps its
   colour. The gradient IS the mask, so there is no mask property involved:
   backdrop-filter + mask measured as barely applying, this measures cleanly. */
#spot-desat{
  position:absolute;left:0;top:0;width:100%;height:100%;z-index:8;
  pointer-events:none;opacity:0;mix-blend-mode:saturation;
  transition:opacity .75s var(--ease);
  background:radial-gradient(circle at var(--sx,50%) var(--sy,50%),
    rgba(128,128,128,0) 0%, rgba(128,128,128,0) var(--r1,7%),
    rgba(128,128,128,.5) var(--r2,26%), rgba(128,128,128,.6) 100%)}
body.spot-on #spot-desat{opacity:1}

/* ---- the My-villa pill is the one persistent handle on a chosen villa, so it
        carries where it will take you: the villa, then the chapter left open ---- */
.nav .mine-pill{gap:0;display:inline-flex;align-items:center;white-space:nowrap}
.nav .mine-pill .mp-ch{position:relative;margin-left:9px;padding-left:10px;opacity:.8}
.nav .mine-pill .mp-ch::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:1px;height:11px;background:currentColor;opacity:.45}
.nav .mine-pill.resumable::after{content:"→";margin-left:9px;opacity:.75}
@media(max-width:700px){ .nav .mine-pill .mp-ch{display:none} }

/* ---- the resume pill sits OUTSIDE #navlinks so it survives the burger
        collapse: on a phone it is the only way back to an unfinished villa,
        and it was hidden behind the menu. ---- */
.nav{position:relative}
.nav .nav-right{display:flex;align-items:center;gap:14px;margin-left:auto}
.nav .links{margin-left:24px;order:3}
@media(min-width:961px){ .nav .nav-right{order:4} }
@media(max-width:960px){
  .nav .nav-right{gap:10px}
  .nav .mine-pill{padding:9px 14px 10px;font-size:11px}
}
/* a real touch target on coarse pointers */
@media(pointer:coarse){ .nav .mine-pill{min-height:44px;padding:11px 16px} }

/* buyer-given names can run to 40 characters; the pill truncates rather than
   pushing the burger off the bar */
.nav .mine-pill .mp-nm{max-width:16ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:700px){ .nav .mine-pill .mp-nm{max-width:12ch} }

/* ---- the configurator on bone: these labels sat at .5-.55 opacity, which held
        on the forest ground and washed out on parchment. The tick was a sand
        glyph inside a sand ring at 1:1 — invisible. ---- */
/* NOTE the depth: the originals are `.styler .fvtot .tier`, `.styler .froomhead
   .rn` and `.styler .fitem .ftop .cur` — three classes each. A two-class
   override loses on specificity however late it sits. */
body.on-bone .fnb-l{opacity:.82}
/* .fvtot .tier is off this list: it sets itself back with --dim now, which is
   already ground-aware, and stacking .82 on top of it dropped it under AA. */
body.on-bone .styler .froomhead .rn,
body.on-bone .styler .fpanel .rhead .rn,
body.on-bone .styler .fitem .ftop .cur{opacity:.82}
body.on-bone .fnb-edit{opacity:.8}
body.on-bone .fnb-edit:hover{opacity:1;border-bottom-color:var(--paper)}
body.on-bone .styler .froomnote{opacity:.9}
body.on-bone .tick{border-color:color-mix(in srgb,var(--paper) 40%, transparent);color:var(--paper)}
body.on-bone .fopt.on .tick{background:var(--paper);color:var(--cream);border-color:var(--paper)}

/* ============================================================
   MASTERPLAN — the map keeps its own light
   Anders: the render should not be dimmed, desaturated or bloomed. The pin on
   the house is the only thing that marks the chosen villa. The #spot layers
   stay in the DOM so the geometry code has something to write to, but they
   paint nothing.
   ============================================================ */
#spot-desat,#spot-shade,#spot-glow{display:none !important}

/* the pin now carries the whole highlight, so it earns a stronger mark */
html[data-alt="1"] .dot.picked .pt{
  box-shadow:0 0 0 3px var(--terra),
             0 0 0 8px color-mix(in srgb,var(--terra) 42%, transparent),
             0 0 22px 6px color-mix(in srgb,#FFCB8A 55%, transparent),
             0 2px 14px rgba(0,0,0,.55);
  transform:scale(1.18)}
html[data-alt="1"] .dot.picked{z-index:40}
.dot .pt{transition:box-shadow .35s var(--ease), transform .35s var(--ease)}

/* ============================================================
   THE RAIL IS A DRAWER
   Closed on arrival; the villas / facilities chips drop it out and put it away.
   ============================================================ */
html[data-alt="1"] body.on-map #vrail{
  display:flex;flex-direction:column;min-height:0;
  transform:translateY(112%);opacity:0;pointer-events:none;
  transition:transform .5s var(--ease), opacity .4s var(--ease)}
html[data-alt="1"] body.on-map.rail-open #vrail{
  transform:none;opacity:1;pointer-events:auto}
@media(min-width:861px){
  html[data-alt="1"] body.on-map #vrail{transform:translateX(-104%)}
  html[data-alt="1"] body.on-map.rail-open #vrail{transform:none}
}
/* the chips come back — they are the way in now */
html[data-alt="1"] body.on-map #sel-bottom{display:block}
html[data-alt="1"] body.on-map #chips-sub{display:block}
/* and the in-rail Homes/Shared pair goes: the chips already do that job */
html[data-alt="1"] .vr-filter{display:none}
/* the FAB only needs to clear the rail while the rail is out — and ONLY on the
   bottom-sheet breakpoint. Above 861px the rail is a left column and
   --vrail-h is its full height, which throws the FAB off the top of the
   screen. This is the regression CLAUDE.md warns about; it is scoped. */
html[data-alt="1"] body.on-map #c-fab{bottom:26px}
@media(max-width:860px){
  html[data-alt="1"] body.on-map.rail-open #c-fab{bottom:calc(var(--vrail-h,190px) + 12px)}
}

/* two blinks each, villas first and then facilities — never together */
@keyframes gblink2{
  0%,100%{box-shadow:0 0 0 1px color-mix(in srgb,var(--paper) 28%, transparent)}
  50%{box-shadow:0 0 0 2px var(--terra), 0 0 16px 2px color-mix(in srgb,var(--terra) 55%, transparent)}}
#chips-main.blink .gchip{animation:none}
#chips-main.blink2 .gchip[data-g="villas"]{animation:gblink2 .85s var(--ease) 2}
#chips-main.blink2 .gchip[data-g="facilities"]{animation:gblink2 .85s var(--ease) 2;animation-delay:1.7s}

/* the drawer is a bottom sheet on phones, so an open rail sat straight on top
   of the very chips that close it — the second tap never reached them */
@media(max-width:860px){
  html[data-alt="1"] body.on-map.rail-open #sel-bottom{
    bottom:calc(var(--vrail-h,190px) + 14px);z-index:40}
  html[data-alt="1"] body.on-map #sel-bottom{
    transition:bottom .5s var(--ease);z-index:40}
}

/* on desktop the drawer is a left column, so the sub-filters and the legend
   move out from under it rather than being covered */
@media(min-width:861px){
  html[data-alt="1"] body.on-map.rail-open #sel-bottom{
    padding-left:calc(var(--vrail-w,370px) + 26px);transition:padding-left .5s var(--ease)}
  html[data-alt="1"] body.on-map #sel-bottom{transition:padding-left .5s var(--ease)}
}

/* ---- the active chip was `background:var(--paper); color:var(--ink)` — a dark
        fill with a light label under the old brand. Both tokens are sand now,
        so the active Villas / Facilities / All-homes chips measured 1.00:1:
        completely invisible. It went unseen because these chips were hidden
        while cards mode had no chip UI. ---- */
.chip.active,#chips-main .gchip.active{background:var(--paper);color:var(--cream);
  border-color:var(--paper)}
/* end SWV skin */




/* ==========================================================================
   design/ split only — the same faces as the data-URI @font-face rules above,
   served from design/assets/fonts/ so a designer can open them in a type tool.
   Appended, not substituted: every rule above is untouched and still works.
   These are local files, so no network font request is introduced.
   ========================================================================== */
@font-face{font-family:'Cormorant Garamond';font-style:normal;font-weight:300;font-display:swap;src:url("assets/fonts/CormorantGaramond-300-normal.woff2") format("woff2");}
@font-face{font-family:'Cormorant Garamond';font-style:italic;font-weight:300;font-display:swap;src:url("assets/fonts/CormorantGaramond-300-italic.woff2") format("woff2");}
@font-face{font-family:'Cormorant Garamond';font-style:normal;font-weight:400;font-display:swap;src:url("assets/fonts/CormorantGaramond-400-normal.woff2") format("woff2");}
@font-face{font-family:'Cormorant Garamond';font-style:italic;font-weight:400;font-display:swap;src:url("assets/fonts/CormorantGaramond-400-italic.woff2") format("woff2");}
@font-face{font-family:'Cormorant Garamond';font-style:normal;font-weight:600;font-display:swap;src:url("assets/fonts/CormorantGaramond-600-normal.woff2") format("woff2");}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:100 900;font-display:swap;src:url("assets/fonts/Montserrat-100_900-normal.woff2") format("woff2");}
@font-face{font-family:'Lato';font-style:normal;font-weight:300;font-display:swap;src:url("assets/fonts/Lato-300-normal.woff2") format("woff2");}


/* ==========================================================================
   ask Grace — the brass button, as settled in "VillaDetails 1b" (4d).
   Replaces the dark pill + uppercase label. Brass gradient, hairline
   highlight on the top edge, a shelf underneath, and the typing dots that
   say this is a conversation. Late in the sheet so it beats the earlier
   #c-fab paint rules and the radius normalisation.
   ========================================================================== */
@font-face{font-family:'Italianno';font-style:normal;font-weight:400;font-display:swap;src:url("assets/fonts/Italianno-400-normal.woff2") format("woff2");}

#c-fab{
  display:flex;align-items:center;gap:14px;
  background:#D8B24A;border:none;border-radius:13px;padding:12px 24px 14px;
  color:#1D2415;white-space:nowrap;letter-spacing:normal;text-transform:none;
  width:auto;height:auto;place-items:normal;
  box-shadow:0 5px 16px rgba(17,21,12,.4);
  transition:transform .18s var(--ease),background .2s,box-shadow .2s}
#c-fab:hover{transform:translateY(-1px);background:#E2BF5D;
  box-shadow:0 8px 22px rgba(17,21,12,.44)}
#c-fab:active{transform:none;background:#CBA43C;box-shadow:0 4px 12px rgba(17,21,12,.4)}
.fab-lock{display:flex;align-items:baseline}
.fab-ask{font-family:'Italianno',var(--serif),cursive;font-size:36px;line-height:1;
  display:block;margin-right:8px;letter-spacing:0.05em}
.fab-name{font-family:var(--serif);font-weight:400;font-size:33px;line-height:1;display:block}
.fab-dots{display:flex;align-items:center;gap:5px;padding-left:13px;
  border-left:1px solid rgba(29,36,21,.2)}
.fab-dots i{width:6px;height:6px;border-radius:50%;background:#1D2415;display:block}
.fab-dots i:first-child{opacity:.42}
.fab-dots i:nth-child(2){opacity:.7}
/* the old kit collapsed the fab to a 52px dot below 861px; the lockup is the
   button now, so it keeps its name at every width — only the shelf tightens */


/* ==========================================================================
   NAVIGATION, mobile pass.
   Three things were fighting at 390: the 24-character wordmark, the villa
   pill and the burger all claimed the 64px bar; the burger had no handler
   at all; and the map filters sat as a third layer of chrome over the card
   rail. One system per job now — the bar names the place, the sheet
   navigates, the rail filters itself.
   ========================================================================== */

/* --- the sheet: full height, forest ground, real tap targets ------------- */
@media(max-width:960px){
  .nav .links{
    position:fixed;inset:0 0 0 auto;width:min(84vw,340px);
    background:var(--well);background-image:var(--speckle);background-size:340px;
    color:var(--paper);border-bottom:none;border-left:1px solid color-mix(in srgb,var(--paper) 16%, transparent);
    flex-direction:column;align-items:stretch;gap:0;
    padding:0 0 calc(20px + env(safe-area-inset-bottom));
    display:flex;transform:translateX(101%);transition:transform .42s var(--ease);
    box-shadow:-24px 0 60px rgba(10,9,6,.5);z-index:610;overflow-y:auto}
  .nav .links.open{transform:none}
  .sheet-head{display:flex;align-items:center;justify-content:space-between;
    padding:0 20px 0 24px;height:var(--nav-h);flex:none;
    border-bottom:1px solid color-mix(in srgb,var(--paper) 14%, transparent)}
  .sheet-head span{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:9.5px;
    text-transform:uppercase;opacity:.55}
  .sheet-x{font-size:26px;line-height:1;width:44px;height:44px;color:var(--paper);
    display:grid;place-items:center;margin-right:-10px}
  /* the villa you have open is a place to go back to, so it leads the sheet
     instead of crowding the bar */
  .sheet-resume{display:flex;flex-direction:column;align-items:flex-start;gap:3px;
    padding:16px 24px 18px;border-bottom:1px solid color-mix(in srgb,var(--paper) 14%, transparent);
    text-align:left;background:color-mix(in srgb,var(--terra) 12%, transparent)}
  .sheet-resume .sr-k{font-family:var(--sans);letter-spacing:var(--ls);font-size:8.5px;
    text-transform:uppercase;color:var(--terra)}
  .sheet-resume .sr-v{font-family:var(--serif);font-size:19px;line-height:1.15;color:var(--paper)}
  .nav .links button:not(.sheet-x):not(.sheet-resume){
    min-height:54px;padding:0 24px;display:flex;align-items:center;font-size:12px;
    border-bottom:1px solid color-mix(in srgb,var(--paper) 9%, transparent);
    border-left:2px solid transparent;text-align:left;justify-content:flex-start}
  .nav .links button.active{border-left-color:var(--terra);border-bottom-color:color-mix(in srgb,var(--paper) 9%, transparent);
    color:var(--terra);background:color-mix(in srgb,var(--paper) 5%, transparent)}
  #nav-scrim{position:fixed;inset:0;z-index:605;background:rgba(10,9,6,.6);
    backdrop-filter:blur(2px);opacity:0;pointer-events:none;transition:opacity .42s}
  #nav-scrim.on{opacity:1;pointer-events:auto}
  /* the bar names the place and opens the sheet — nothing else */
  .nav{padding:0 8px 0 18px}
  .nav .brand{font-size:10.5px;letter-spacing:.2em}
  .nav .mine-pill{display:none}
  .burger{width:44px;height:44px;display:grid;place-items:center;padding:0;font-size:22px}
}
@media(max-width:960px) and (prefers-reduced-motion:reduce){
  .nav .links{transition:none} #nav-scrim{transition:none}
}

/* --- mobile: the rail filters itself, so the map chips stand down -------- */
@media(max-width:860px){
  html[data-alt="1"] body.on-map #sel-bottom{display:none}
  html[data-alt="1"] .vr-head{justify-content:space-between;padding:0 14px 9px;gap:10px}
  html[data-alt="1"] .vr-seg{display:flex;pointer-events:auto;flex:none;
    background:color-mix(in srgb,var(--well) 62%, transparent);backdrop-filter:blur(10px);
    border:1px solid color-mix(in srgb,var(--paper) 24%, transparent);
    border-radius:99px;overflow:hidden}
  html[data-alt="1"] .vr-seg button{color:var(--dim);font-family:var(--sans);
    letter-spacing:var(--ls);font-size:9.5px;text-transform:uppercase;
    padding:9px 16px 10px;min-height:36px;transition:.25s}
  html[data-alt="1"] .vr-seg button.on{background:var(--paper);color:var(--cream);font-weight:600}
  /* the brass lockup is tall — give it the rail's clearance and its own lane */
  html[data-alt="1"] body.on-map.rail-open #c-fab{bottom:calc(var(--vrail-h,190px) + 14px)}
}
/* (the desktop rule that used to hide .vr-seg is gone with #sel-bottom — the
   segment is the only group control on every width now; see below) */


/* --- nav v2 fixes -------------------------------------------------------- */
/* the sheet's own chrome belongs to the sheet; the desktop bar has a pill */
@media(min-width:961px){
  .nav .links .sheet-head,.nav .links .sheet-resume{display:none}
}
/* a centred, full-width chip stack cannot be cleared with padding — it has to
   be bounded on the right at the FAB's edge */
@media(min-width:861px){
  html[data-alt="1"] body.on-map #sel-bottom{padding-right:0;right:270px}
}
/* the rail's real height is measured into --vrail-h; this fallback only has to
   survive the first frame, so it sits above the tallest rail we render */
@media(max-width:860px){
  html[data-alt="1"] body.on-map.rail-open #c-fab{bottom:calc(var(--vrail-h,214px) + 16px)}
  html[data-alt="1"] body.on-map.rail-open #fab-bubble{bottom:calc(var(--vrail-h,214px) + 20px)}
}


/* ==========================================================================
   The rail's segment is the only group control now — desktop as well as
   mobile. #sel-bottom (chips, bedroom sub-chips, legend) is gone from the
   markup, so its offsets and the FAB clearances it forced go with it.
   And the founders' houses read as sold, not as withheld.
   ========================================================================== */
html[data-alt="1"] .vr-seg{display:flex;pointer-events:auto;flex:none;
  background:color-mix(in srgb,var(--well) 62%, transparent);backdrop-filter:blur(10px);
  border:1px solid color-mix(in srgb,var(--paper) 24%, transparent);
  border-radius:99px;overflow:hidden}
html[data-alt="1"] .vr-seg button{color:var(--dim);font-family:var(--sans);
  letter-spacing:var(--ls);font-size:9.5px;text-transform:uppercase;
  padding:9px 16px 10px;min-height:36px;transition:.25s}
html[data-alt="1"] .vr-seg button.on{background:var(--paper);color:var(--cream);font-weight:600}
html[data-alt="1"] .vr-head{justify-content:space-between;gap:10px}

/* the private villas recede rather than inviting a click. Muting is a colour
   token, never an opacity: .62 on the card times .7 on the price landed the
   figure at .43 of the ground, which is CLAUDE.md rule (b) exactly. */
html[data-alt="1"] .vrcard.slim{color:var(--dim)}
html[data-alt="1"] .vrcard.slim .vr-thumb img{filter:grayscale(.5) brightness(.9)}
html[data-alt="1"] .vrcard.slim .vr-price{color:var(--dim);letter-spacing:var(--ls-wide)}
.vr-div span{color:var(--paper)}


/* ==========================================================================
   Only what you can buy earns a pin.
   Three near-identical dot states asked the reader to decode a legend before
   they could read the land. Available villas are marked; reserved and sold
   carry no pin at all — hovering their card still finds them on the map
   (a hollow ring plus the plot outline), which is the only time you need to
   know where a house you cannot have is standing.
   ========================================================================== */
html[data-alt="1"] .dot.reserved,html[data-alt="1"] .dot.sold{pointer-events:none}
html[data-alt="1"] .dot.reserved .pt,html[data-alt="1"] .dot.sold .pt{
  opacity:0;transform:translate(-50%,-50%) scale(.55);transition:opacity .35s,transform .35s}
html[data-alt="1"] .dot.reserved .pt::after,html[data-alt="1"] .dot.sold .pt::after{display:none}
/* found from its card: a hollow ring, never the solid available marker */
html[data-alt="1"] .dot.reserved.hovlit .pt,html[data-alt="1"] .dot.sold.hovlit .pt{
  opacity:1;width:15px;height:15px;background:transparent;
  transform:translate(-50%,-50%) scale(1);
  box-shadow:0 0 0 1.5px var(--paper) inset,0 1px 8px rgba(0,0,0,.5)}
html[data-alt="1"] .dot.reserved.hovlit .plot,html[data-alt="1"] .dot.sold.hovlit .plot{
  border-color:color-mix(in srgb,var(--paper) 62%, transparent);
  border-style:dashed;
  background:radial-gradient(circle,color-mix(in srgb,var(--paper) 10%, transparent),transparent 74%)}
/* with one pin state left, the available marker can carry full confidence */
html[data-alt="1"] .dot:not(.reserved):not(.sold):not(.amen) .pt{background:var(--terra);
  box-shadow:0 0 0 7px color-mix(in srgb,var(--terra) 26%, transparent),
             0 0 22px 4px color-mix(in srgb,var(--terra) 45%, transparent),0 1px 10px rgba(0,0,0,.5)}
html[data-alt="1"] .dot:not(.reserved):not(.sold):not(.amen) .pt::after{
  border-color:color-mix(in srgb,var(--terra) 70%, transparent)}


/* ==========================================================================
   ask Grace on mobile: the brass lockup is a desktop-scale object and sat
   badly over the card rail. On touch it becomes what a chat affordance is
   — a small round brass button with her typing dots in it, lower right.
   ========================================================================== */
@media(max-width:860px){
  #c-fab{width:50px;height:50px;padding:0;border-radius:50%;gap:0;
    display:grid;place-items:center;right:16px}
  body.on-map #c-fab{padding:0;border-radius:50%}
  #c-fab .fab-lock{display:none}
  #c-fab .fab-dots{padding-left:0;border-left:none;gap:4px}
  #c-fab .fab-dots i{width:5px;height:5px}
}


/* ==========================================================================
   MOBILE: the card rail is the pointer.
   A finger has no hover, so the carousel does the work — it snaps, and the
   card resting at the centre of the screen lights its plot on the map.
   Tapping selects for real (the .on/.picked states were baked into the
   markup before), and the map walks the chosen plot into the open band
   above the rail.
   ========================================================================== */
@media(max-width:860px){
  html[data-alt="1"] #vrail .vr-scroll{scroll-snap-type:x mandatory;scroll-padding:0 14px}
  html[data-alt="1"] .vrcard,html[data-alt="1"] .vr-mdiv{scroll-snap-align:center}
  /* the Sold divider is a column rule on desktop; in a horizontal scroller it
     has to be a stop of its own, or the sold cards arrive unannounced */
  .vr-mdiv{display:flex;align-items:center;justify-content:center;flex:0 0 auto;
    width:34px;align-self:stretch;pointer-events:none}
  .vr-mdiv span{writing-mode:vertical-rl;transform:rotate(180deg);
    font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:8.5px;
    text-transform:uppercase;color:var(--paper);opacity:.42;
    padding:10px 0;border-left:1px solid color-mix(in srgb,var(--paper) 22%, transparent);
    padding-left:11px}
  /* the centred card reads as chosen without the desktop hover lift */
  html[data-alt="1"] .vrcard.hov{transform:none;box-shadow:0 14px 34px rgba(0,0,0,.4)}
  /* No pin label on a phone. The reasoning here was "the only way to read the
     map where nothing is hovered" — but the card is directly below, naming the
     same villa in bigger type, so the label said it twice and the masterplan
     opened with a box floating over the village nobody had asked for. */
}
@media(min-width:861px){.vr-mdiv{display:none}}
/* the nav sheet and the map layout switched at different widths, leaving a
   band with a desktop drawer and a phone burger */
@media(min-width:861px) and (max-width:960px){
  .nav .links{position:static;width:auto;transform:none;flex-direction:row;
    background:none;background-image:none;border-left:none;box-shadow:none;
    padding:0;overflow:visible;display:flex}
  .nav .links .sheet-head,.nav .links .sheet-resume{display:none}
  .nav .mine-pill{display:flex}
  .burger{display:none}
  #nav-scrim{display:none}
}


/* ==========================================================================
   DESKTOP pass — the map should be readable on its own, the drawer should
   be sized for the screen it is on, and the sold plots should not cost a
   third of the scroll to walk past.
   ========================================================================== */
.hint .h-mouse{display:none}
@media(hover:hover){.hint .h-touch{display:none}.hint .h-mouse{display:inline}}

/* the tag carries the numbers now, not just a name */
.dot .tag .fx{display:flex;align-items:baseline;gap:8px;margin-top:4px;
  opacity:0;transition:opacity .3s var(--ease) .06s}
.dot .tag .fx span:first-child{font-family:var(--serif);font-size:14px;color:var(--paper)}
.dot .tag .fx span:last-child{font-family:var(--sans);letter-spacing:var(--ls);font-size:8px;
  text-transform:uppercase;color:var(--dim)}
@media(min-width:861px){
  /* the base rule hides every tag; these are the three moments it earns
     its place — pointed at from the rail, chosen, or hovered directly */
  html[data-alt="1"] .dot.hovlit .tag,
  html[data-alt="1"] .dot.picked .tag,
  html[data-alt="1"] .dot:hover .tag{display:block;opacity:1;pointer-events:none;
    transform:translate(calc(-50% + var(--tagdx,0px)),0)}
  html[data-alt="1"] .dot.hovlit .tag .nm,
  html[data-alt="1"] .dot.picked .tag .nm,
  html[data-alt="1"] .dot:hover .tag .nm{font-family:var(--serif);font-size:15px;
    letter-spacing:0;text-transform:none;font-weight:400}
  html[data-alt="1"] .dot.hovlit .tag .fx,html[data-alt="1"] .dot.picked .tag .fx{opacity:1}
  html[data-alt="1"] .dot:hover .tag .fx{opacity:1}
}
@media(max-width:860px){.dot .tag .fx{display:none}}

@media(min-width:1200px){
  /* 4 — the drawer is sized for the screen it is on, and the price is the
     largest thing in the card because it is the thing being decided */
  html[data-alt="1"] body.on-map #vrail{width:min(420px,32vw)}
  html[data-alt="1"] .vrcard .vr-nm{font-size:17px}
  html[data-alt="1"] .vrcard .vr-price{font-size:23px}
  html[data-alt="1"] .vr-thumb{flex:0 0 82px}
}

/* 5 — sold collapses to a line */
@media(min-width:861px){
  html[data-alt="1"] .vr-div{display:flex;align-items:center;gap:10px;width:100%;
    padding:14px 20px 12px;text-align:left;cursor:pointer;transition:opacity .2s}
  html[data-alt="1"] .vr-div:hover{opacity:.85}
  html[data-alt="1"] .vr-div i{font-style:normal;font-size:13px;opacity:.6;
    width:18px;height:18px;display:grid;place-items:center;flex:none;
    border:1px solid color-mix(in srgb,var(--paper) 30%, transparent);border-radius:50%;
    order:3;margin-left:0}
  html[data-alt="1"] .vr-div::after{order:2}
  html[data-alt="1"] .vrcard.slim{display:none}
  html[data-alt="1"] body.sold-open .vrcard.slim{display:flex}
}


/* ==========================================================================
   NAVIGATION — one bar, one way in, at every width.
   The bar had a wordmark, two links, a villa pill and a burger competing in
   64px. Now it holds the name and a two-rule mark; the menu comes down from
   the top as a full-width plate on the forest ground. Same behaviour on a
   phone and a desktop, so there is one thing to learn.
   ========================================================================== */
.nav{display:flex;align-items:center;justify-content:space-between;padding:0 22px}
.nav .brand{font-size:11px;letter-spacing:.24em}
.nav .mine-pill{display:none}

.burger{display:flex;flex-direction:column;justify-content:center;gap:5px;
  width:44px;height:44px;padding:0 9px;align-items:stretch;background:none;border:none;cursor:pointer}
.burger i{display:block;height:1px;background:currentColor;transform-origin:50% 50%;
  transition:transform .38s var(--ease),opacity .38s var(--ease)}
body.nav-open .burger i:first-child{transform:translateY(3px) rotate(45deg)}
body.nav-open .burger i:last-child{transform:translateY(-3px) rotate(-45deg)}

/* the plate drops from under the bar at every width */
.nav .links{
  position:fixed;left:0;right:0;top:0;width:auto;bottom:auto;
  display:block;flex-direction:column;align-items:stretch;gap:0;
  background:var(--well);background-image:var(--speckle);background-size:420px;
  color:var(--paper);border-left:none;
  border-bottom:1px solid color-mix(in srgb,var(--paper) 16%, transparent);
  padding:calc(var(--nav-h) + 34px) 0 44px;
  transform:translateY(-101%);transition:transform .5s var(--ease);
  box-shadow:0 26px 60px rgba(10,9,6,.5);z-index:600;overflow:visible}
.nav .links.open{transform:none}
.sheet-in{display:flex;flex-direction:column;gap:26px;
  max-width:1180px;margin:0 auto;padding:0 22px;width:100%}
.sheet-list{display:flex;flex-direction:column}
.nav .links .sheet-list button{display:flex;align-items:baseline;gap:18px;
  min-height:62px;padding:0;justify-content:flex-start;text-align:left;
  border-bottom:1px solid color-mix(in srgb,var(--paper) 12%, transparent);
  color:var(--paper);background:none;transition:opacity .2s,padding-left .3s var(--ease)}
.nav .links .sheet-list button:hover{padding-left:8px}
.nav .links .sheet-list button em{font-family:var(--sans);font-style:normal;
  letter-spacing:var(--ls-wide);font-size:9px;opacity:.42;width:20px;flex:none}
.nav .links .sheet-list button span{font-family:var(--serif);font-size:34px;
  font-weight:300;line-height:1.1;letter-spacing:0;text-transform:none}
.nav .links .sheet-list button.active span{color:var(--terra)}
.nav .links .sheet-list button.active em{color:var(--terra);opacity:1}
.sheet-resume{display:flex;align-items:baseline;gap:12px;padding:0 0 4px;
  background:none;border:none;text-align:left;color:var(--paper);align-self:flex-start}
.sheet-resume .sr-k{font-family:var(--sans);letter-spacing:var(--ls);font-size:8.5px;
  text-transform:uppercase;color:var(--terra)}
.sheet-resume .sr-v{font-family:var(--serif);font-size:17px;line-height:1.1}
#nav-scrim{position:fixed;inset:0;z-index:590;background:rgba(10,9,6,.55);
  opacity:0;pointer-events:none;visibility:hidden;
  transition:opacity .5s,visibility 0s linear .5s}
#nav-scrim.on{opacity:1;pointer-events:auto;visibility:visible;transition:opacity .5s}
.nav{z-index:601}
body.nav-open .nav{color:var(--paper)}

@media(max-width:860px){
  .nav{padding:0 14px 0 18px}
  .nav .links{padding:calc(var(--nav-h) + 26px) 0 34px}
  .sheet-in{gap:20px;padding:0 18px}
  .nav .links .sheet-list button{min-height:54px;gap:14px}
  .nav .links .sheet-list button span{font-size:26px}
}
@media(prefers-reduced-motion:reduce){
  .nav .links,#nav-scrim,.burger i{transition:none}
}


/* ==========================================================================
   Two angles, one arrow at a time. Showing both implied four views; there
   are two, so the arrow you can see is always the one that takes you
   somewhere new — and on the second angle it is the way back.
   ========================================================================== */
/* THESE TWO RULES USED TO STRAND YOU. The design was written for two angles
   and gated the back arrow on body.angle-2 — a class nothing in this engine
   ever adds, because the engine has THREE views and drives the arrows from
   state.angleIdx through syncAngleChrome(). So #ang-left sat at opacity:0
   forever: you could walk right and never walk back, and on the last view
   syncAngleChrome hid the right arrow too, leaving no way out at all.
   Visibility belongs to syncAngleChrome now — one owner, any number of views.
   The rest of the body.angle-2 rules below still stand: they drive the second
   pin set and the layer crossfade, which is a separate job. */
.ang-btn{transition:opacity .4s var(--ease),background .3s,border-color .3s}
.ang-btn[hidden]{display:none !important}
#angle-layers .angle-img{opacity:0;transition:opacity .7s var(--ease)}
body.angle-2 #angle-layers .angle-img{opacity:1}
/* each camera carries its own pins, surveyed against its own ground; only
   the plot footprints stay behind, since an ellipse drawn for the west
   view would lie about the land from the river */
#hotspots2{position:absolute;inset:0;opacity:0;pointer-events:none;transition:opacity .45s var(--ease)}
body.angle-2 #hotspots{opacity:0;pointer-events:none;transition:opacity .35s}
body.angle-2 #hotspots2{opacity:1;pointer-events:auto}


/* ==========================================================================
   PERFORMANCE — the map was asking the compositor for more than it could
   give: 28 blurred tag backdrops, both pin layers alive at once, and the
   idle layer still pulsing. None of it was visible work.
   ========================================================================== */
/* a near-solid plate reads the same over a photograph as a blurred one, and
   costs nothing per frame. 28 of the 31 backdrop filters on this page. */
.dot .tag{backdrop-filter:none;background:color-mix(in srgb,var(--well) 94%, transparent)}
.ang-btn{backdrop-filter:none;background:color-mix(in srgb,var(--well) 72%, transparent)}
.ang-btn:hover{background:color-mix(in srgb,var(--well) 88%, transparent)}
html[data-alt="1"] .vr-seg{backdrop-filter:none;background:color-mix(in srgb,var(--well) 88%, transparent)}
@media(max-width:860px){
  html[data-alt="1"] .vr-seg{backdrop-filter:none;background:color-mix(in srgb,var(--well) 88%, transparent)}
  #nav-scrim{backdrop-filter:none}
}

/* the hidden layer is hidden: no paint, no hit-testing, no animation */
#hotspots,#hotspots2{transition:opacity .35s var(--ease)}
body.angle-2 #hotspots,body:not(.angle-2) #hotspots2{
  opacity:0;pointer-events:none;visibility:hidden;content-visibility:hidden}
body:not(.angle-2) #hotspots,body.angle-2 #hotspots2{
  opacity:1;pointer-events:auto;visibility:visible;content-visibility:visible}
body.angle-2 #hotspots .pt::after,body:not(.angle-2) #hotspots2 .pt::after{animation:none}
/* only the plots you can still buy breathe; the rest were animating unseen */
.dot.sold .pt::after,.dot.reserved .pt::after,.dot.amen .pt::after{animation:none}
@media(prefers-reduced-motion:reduce){.dot .pt::after{animation:none}}

/* the drop-down plate inherited the old inline bar's offset and sat 24px
   short of the left edge, out of line with the bar above it */
.nav .links{margin-left:0;order:initial}


/* the back arrow was pinned to the old 370px drawer and now sits under the
   wider one */
@media(min-width:1200px){
  html[data-alt="1"] body.on-map #ang-left{left:calc(min(420px,32vw) + 18px)}
}


/* ==========================================================================
   Choosing a plot and entering it are two different intentions, so they are
   two clicks: the first brings the plot to you on the map, the second walks
   you into the house. The chosen card says so rather than leaving you to
   guess that clicking again does something new.
   ========================================================================== */
/* a narrow lane, not a second column — the card's own text keeps its width */
.vr-go-in{display:none;align-items:center;justify-content:center;align-self:stretch;
  flex:0 0 34px;width:34px;padding:0;margin:-13px -13px -13px 0;border-radius:0 3px 3px 0;
  font-size:0;color:var(--cream);background:var(--terra)}
.vr-go-in::after{content:"›";font-family:var(--serif);font-size:22px;line-height:1;margin-top:-3px}
html[data-alt="1"] .vrcard.on .vr-go-in{display:flex}
@media(max-width:860px){
  .vr-go-in{margin:-11px -11px -11px 0;flex-basis:30px;width:30px}
}


/* ==========================================================================
   WALKING INTO A VILLA — the camera pushes into the plot until the village
   fills the frame, then the villa's own pictures take over. Leaving reverses
   the same move, so you come back standing on the plot you left.
   ========================================================================== */
body.zooming #hotspots,body.zooming #hotspots2,
body.zooming #vrail,body.zooming #sel-chrome,
body.zooming .ang-btn,body.zooming #c-fab,body.zooming .nav{
  opacity:0;pointer-events:none;transition:opacity .45s var(--ease)}
body.zooming #map-wrap{pointer-events:none}

#story{position:fixed;inset:0;z-index:80;opacity:0;pointer-events:none;
  transition:opacity .6s var(--ease);background:var(--well)}
body.in-story #story{opacity:1;pointer-events:auto}
#story-scroll{position:absolute;inset:0;overflow-y:auto;overflow-x:hidden;
  scrollbar-width:none}
#story-scroll::-webkit-scrollbar{display:none}
.sslide{position:relative;height:100%;scroll-snap-align:start;overflow:hidden;
  display:flex;align-items:flex-end}
.sslide img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.sslide::after{content:"";position:absolute;left:0;right:0;bottom:0;height:62%;
  background:linear-gradient(to top,rgba(10,9,6,.88),rgba(10,9,6,.24) 58%,transparent)}
.sslide .scap{position:relative;z-index:2;color:var(--paper);
  padding:0 clamp(22px,5vw,72px) clamp(74px,9vh,110px);max-width:40em}
.sslide .sk{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:9.5px;
  text-transform:uppercase;color:var(--terra);margin-bottom:12px}
.sslide .sh{font-family:var(--serif);font-weight:300;font-size:clamp(30px,4.6vw,54px);
  line-height:1.08;margin-bottom:12px}
.sslide .scap p{font-family:var(--sans);font-size:13.5px;line-height:1.7;
  max-width:30em;opacity:.78;margin:0;text-wrap:pretty}

#story .exit{opacity:0;transition:opacity .5s var(--ease) .2s}
body.in-story #story .exit{opacity:1}
#story-cue,#story-count{opacity:0;transition:opacity .5s var(--ease)}
body.in-story #story-cue{opacity:1}
body.in-story.story-moved #story-cue{opacity:0}
body.in-story.story-moved #story-count{opacity:1}
#story-count{backdrop-filter:none;background:color-mix(in srgb,var(--well) 82%, transparent)}
#story .exit{backdrop-filter:none;background:color-mix(in srgb,var(--well) 78%, transparent)}
@media(max-width:860px){
  #story .exit{top:14px;left:14px;font-size:10.5px;padding:8px 15px 9px}
  .sslide .scap{padding-bottom:96px}
}
@media(prefers-reduced-motion:reduce){
  #story,#story .exit,#story-cue,#story-count{transition:none}
}


/* the cue and the counter sat centred, straight through the left-aligned
   caption; the caption owns the bottom-left, so they move to the corner */
body.in-story #story-cue{left:auto;right:26px;bottom:20px;transform:none;gap:9px}
body.in-story #story-count{left:auto;right:22px;bottom:22px;transform:none}
body.in-story #story-cue .caps{font-size:9.5px;letter-spacing:var(--ls-wide)}
body.in-story #story-cue .cue-line{height:34px}
.sslide{height:100dvh}
@media(max-width:860px){
  body.in-story #story-cue{right:16px;bottom:16px}
  body.in-story #story-count{right:14px;bottom:18px}
}


/* the lane rides on the card's edge instead of taking a column of its own,
   so choosing a plot never shortens its name */
html[data-alt="1"] .vrcard{position:relative}
html[data-alt="1"] .vrcard.on .vr-go-in{position:absolute;right:0;top:0;bottom:0;
  display:flex;width:32px;flex-basis:auto;margin:0;padding:0;
  background:var(--terra);color:var(--cream);border-radius:0 3px 3px 0;z-index:3}
html[data-alt="1"] .vrcard.on .vr-body{padding-right:36px}
/* in the narrow desktop band the drawer is only ~295px, so the lane has to
   give the name back its room rather than take another 36px from it */
@media(min-width:861px) and (max-width:1120px){
  html[data-alt="1"] .vrcard.on .vr-go-in{width:26px}
  html[data-alt="1"] .vrcard.on .vr-body{padding-right:28px}
  html[data-alt="1"] .vrcard.on .vr-thumb{flex-basis:56px}
}


/* the fade group was written without the kit's html[data-alt="1"] prefix, so
   the drawer's own rule out-specified it and the rail stayed opaque over a
   map pushing to 2.9x */
html[data-alt="1"] body.zooming #vrail,
html[data-alt="1"] body.zooming #hotspots,
html[data-alt="1"] body.zooming #hotspots2,
html[data-alt="1"] body.zooming #sel-chrome,
html[data-alt="1"] body.zooming .ang-btn,
html[data-alt="1"] body.zooming #c-fab,
html[data-alt="1"] body.zooming .nav{
  opacity:0;pointer-events:none;transition:opacity .45s var(--ease)}


/* .on-map.rail-open pins the drawer to opacity 1 and out-specifies a single
   .zooming class, so the fade has to be written against that same pair */
html[data-alt="1"] body.on-map.rail-open.zooming #vrail,
html[data-alt="1"] body.on-map.zooming #vrail{
  opacity:0;pointer-events:none;transition:opacity .45s var(--ease)}


/* the walk-through scrolls the way the rest of the village does: each image
   holds on a sticky stage while its caption reads over it, and you leave it
   by scrolling on — no snapping, no paging */
#story-scroll .beat{min-height:100vh;min-height:100dvh}
#story-scroll .beat .stage{position:sticky;top:0;height:100vh;height:100dvh}
#story-scroll .scap.scrim{padding:130px clamp(22px,5vw,48px) 46px}
#story-scroll .scrim .line{font-family:var(--serif);font-weight:300}
#story-scroll .scrim .labels span{text-transform:none;letter-spacing:0;
  font-family:var(--sans);font-size:13.5px;line-height:1.7;opacity:.8;max-width:32em}
@media(max-width:700px){#story-scroll .scap.scrim{padding-bottom:74px}}


/* ==========================================================================
   The walk-through scrolls the PAGE, like every other chapter of the
   village — an inner overflow box scrolls differently under a wheel and a
   thumb, and that is what felt wrong. The map stays fixed behind it.
   ========================================================================== */
body.in-story{overflow:visible;overflow-y:auto;height:auto}
#story{position:relative;inset:auto;z-index:80;background:var(--well);
  display:none;opacity:1;pointer-events:auto}
body.in-story #story{display:block}
#story-scroll{position:relative;inset:auto;overflow:visible;height:auto}
#story .exit{opacity:1}
body.in-story #map-wrap{position:fixed;inset:0;z-index:1}


/* the story is the page while it is open. The nav is sticky, so it still
   held a 64px line of flow above it — the one thing left in the document. */
body.in-story .nav{position:fixed;top:0;left:0;right:0}
body.in-story #story{margin:0}


/* ==========================================================================
   The walk-through, as it was: front, left, right — then the front again,
   pushing in until the wall gives way and you are inside looking out. The
   last beat is twice as tall so the push has room to happen.
   ========================================================================== */
#story-scroll .beat.push{min-height:200vh;min-height:200dvh}
#story-scroll .beat.push .stage img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;transform-origin:50% 46%}
#story-scroll .beat.push .px-out{transform:scale(calc(1 + var(--p,0) * 0.55));
  opacity:calc(1 - (var(--p,0) - 0.55) * 2.6)}
#story-scroll .beat.push .px-in{transform:scale(calc(1.18 - var(--p,0) * 0.18));
  opacity:calc((var(--p,0) - 0.55) * 2.6)}
#story-scroll .beat.push .scap{opacity:calc((var(--p,0) - 0.62) * 3.4)}
@media(prefers-reduced-motion:reduce){
  #story-scroll .beat.push{min-height:100vh;min-height:100dvh}
  #story-scroll .beat.push .px-out{display:none}
  #story-scroll .beat.push .px-in{transform:none;opacity:1}
  #story-scroll .beat.push .scap{opacity:1}
}


/* the closing card — the number, and the two things you can do next */
#story-scroll .story-end{background:var(--well);color:var(--paper);
  min-height:100vh;min-height:100dvh;display:flex;align-items:center}
#story-scroll .se-in{padding:0 clamp(22px,6vw,96px);max-width:56em;
  display:flex;flex-direction:column;align-items:flex-start;gap:0}
.se-k{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:10px;
  text-transform:uppercase;opacity:.55;margin-bottom:26px}
.se-h{font-family:var(--serif);font-weight:300;font-size:clamp(34px,5.4vw,68px);
  line-height:1.06;margin:0 0 26px;text-wrap:pretty}
.se-p{font-family:var(--serif);font-style:italic;font-size:clamp(16px,1.5vw,20px);
  line-height:1.5;opacity:.8;margin:0 0 40px;max-width:24em}
.se-cta{display:flex;flex-wrap:wrap;gap:12px;margin-bottom:44px}
.se-cta .btn{font-family:var(--sans);letter-spacing:var(--ls);font-size:10.5px;
  text-transform:uppercase;font-weight:500;padding:15px 26px 16px;
  background:var(--terra);color:var(--cream);border:1px solid var(--terra);
  border-radius:3px;transition:.25s}
.se-cta .btn.ghost{background:transparent;color:var(--paper);
  border-color:color-mix(in srgb,var(--paper) 40%, transparent)}
.se-cta .btn:hover{background:var(--paper);color:var(--cream);border-color:var(--paper)}
.se-next{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:10px;
  text-transform:uppercase;color:var(--paper);opacity:.6;padding:14px 0;
  border-top:1px solid color-mix(in srgb,var(--paper) 20%, transparent);
  align-self:stretch;text-align:left;transition:opacity .25s}
.se-next:hover{opacity:1}
body.in-story #c-fab{opacity:1;pointer-events:auto;z-index:96}


/* ==========================================================================
   VILLA STORY v2 — the image holds, the next one dissolves through it.
   Every frame is a fixed layer; the spacers below are the only real scroll.
   ========================================================================== */
#story-scroll .sfade{position:fixed;inset:0;z-index:1;overflow:hidden;
  background:var(--well);cursor:pointer}
#story-scroll .sfl{position:absolute;inset:0;opacity:0;will-change:opacity}
#story-scroll .sfl>img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;transform-origin:50% 46%;will-change:transform}
#story-scroll .sfl .scap.scrim{z-index:2}
#story-scroll .sspace{height:100vh;height:100dvh;pointer-events:none}
#story-scroll .story-end{position:relative;z-index:3}
/* the cue is the affordance AND the control: centred on the image, holding
   until the last frame, where there is nothing left to advance to */
body.in-story #story-cue{pointer-events:auto;cursor:pointer;border:0;background:none;
  padding:6px 14px;left:50%;right:auto;bottom:20px;transform:translateX(-50%);gap:9px;
  font-family:var(--sans);color:var(--paper)}
body.in-story #story-cue:hover .caps{opacity:1;text-decoration:underline;text-underline-offset:4px}
body.in-story.story-moved #story-cue{opacity:1}
body.in-story.sf-done #story-cue{opacity:0;pointer-events:none}
@media(max-width:860px){body.in-story #story-cue{bottom:14px}}
@media(prefers-reduced-motion:reduce){#story-scroll .sfl>img{transform:none !important}}


/* the walk-through's position, as dots on the right — the same language as
   the plot dots on the map. Visible from the first frame, unlike a counter. */
#story-dots{position:fixed;right:22px;top:50%;transform:translateY(-50%);z-index:95;
  display:none;flex-direction:column;gap:13px}
body.in-story #story-dots{display:flex}
#story-dots button{width:7px;height:7px;padding:0;border-radius:50%;border:0;cursor:pointer;
  background:color-mix(in srgb,var(--paper) 34%, transparent);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--paper) 42%, transparent), 0 1px 6px rgba(0,0,0,.5);
  transition:background .35s var(--ease),transform .35s var(--ease)}
#story-dots button:hover{background:color-mix(in srgb,var(--paper) 70%, transparent)}
#story-dots button.on{background:var(--paper);transform:scale(1.32)}
@media(max-width:860px){#story-dots{right:13px;gap:11px}}
/* the faces in between read as one line, not a full caption */
#story-scroll .scap.quiet .line{font-size:clamp(22px,3vw,34px);opacity:.94}
#story-scroll .scap.quiet{padding-bottom:64px}
@media(prefers-reduced-motion:reduce){#story-dots button{transition:none}}


/* v27 — the cue is centred now (the dot rail took the right edge), so the
   story caption has to clear the cue band, not the right corner. Cue caps
   top out at y≈770 on a 844-tall phone; 104px of padding keeps the longest
   glyph run above it. */
@media(max-width:860px){
  #story-scroll .scap.scrim,
  #story-scroll .scap.quiet{padding-bottom:104px}
}


/* ==========================================================================
   VILLA STORY — the closing card, v2.
   It sits over the last frame (which is still fixed behind it) rather than
   cutting to a flat panel; the price leads; one primary action.
   ========================================================================== */
#story-scroll .story-end{background:linear-gradient(to bottom,
    color-mix(in srgb,var(--well) 72%, transparent) 0%,
    color-mix(in srgb,var(--well) 93%, transparent) 34%,
    var(--well) 72%);
  backdrop-filter:blur(14px) saturate(.9);color:var(--paper);
  min-height:100vh;min-height:100dvh;display:flex;align-items:center}
#story-scroll .se-in{padding:clamp(70px,9vh,110px) clamp(22px,6vw,96px) 0;max-width:none;
  width:100%;display:flex;flex-direction:column;align-items:stretch;gap:0}
#story-scroll .se-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.62fr);
  gap:clamp(30px,5vw,72px);align-items:center;flex:1}
#story-scroll .se-main{display:flex;flex-direction:column;align-items:flex-start}

.se-k{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:10px;
  text-transform:uppercase;opacity:.5;margin-bottom:22px}
.se-nm{font-family:var(--sans);letter-spacing:var(--ls);font-size:11.5px;
  text-transform:uppercase;font-weight:500;opacity:.82;margin-bottom:14px}
.se-price{font-family:var(--serif);font-weight:300;font-size:clamp(46px,7.4vw,104px);
  line-height:.94;letter-spacing:-.01em;margin-bottom:14px}
.se-price.is-sold{opacity:.5}
.se-sub{font-family:var(--serif);font-style:italic;font-size:clamp(15px,1.35vw,19px);
  line-height:1.5;opacity:.72;margin-bottom:34px;max-width:26em}
.se-facts{display:flex;flex-wrap:wrap;gap:0;margin:0 0 38px;
  border-top:1px solid color-mix(in srgb,var(--paper) 18%, transparent)}
.se-facts>div{padding:16px 34px 0 0;margin-right:34px;
  border-right:1px solid color-mix(in srgb,var(--paper) 12%, transparent)}
.se-facts>div:last-child{border-right:0;margin-right:0;padding-right:0}
.se-facts dt{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:9.5px;
  text-transform:uppercase;opacity:.45;margin:0 0 7px}
.se-facts dd{margin:0;font-family:var(--serif);font-weight:300;font-size:clamp(20px,2vw,27px);line-height:1}
.se-facts dd em{font-style:normal;font-size:.62em;opacity:.55;margin-left:2px}

.se-cta{display:flex;flex-wrap:wrap;align-items:center;gap:24px;margin:0}
.se-cta .btn{font-family:var(--sans);letter-spacing:var(--ls);font-size:10.5px;
  text-transform:uppercase;font-weight:500;padding:16px 30px 17px;
  background:var(--terra);color:var(--cream);border:1px solid var(--terra);
  border-radius:3px;transition:.25s;cursor:pointer}
.se-cta .btn:hover{background:var(--paper);color:var(--cream);border-color:var(--paper)}
.se-link{font-family:var(--sans);letter-spacing:var(--ls);font-size:10.5px;
  text-transform:uppercase;font-weight:400;color:var(--paper);opacity:.62;
  background:none;border:0;padding:6px 0;cursor:pointer;
  border-bottom:1px solid color-mix(in srgb,var(--paper) 26%, transparent);transition:.25s}
.se-link:hover{opacity:1;border-bottom-color:var(--paper)}

/* the villa you just walked through stays on its own closing card */
#story-scroll .se-shot{margin:0;position:relative;aspect-ratio:4/5;overflow:hidden;
  border-radius:2px;box-shadow:0 40px 90px -40px rgba(0,0,0,.85)}
#story-scroll .se-shot img{width:100%;height:100%;object-fit:cover;display:block}

/* next villa is a footer strip, not a third equal choice */
.se-next{display:flex;align-items:baseline;justify-content:space-between;gap:18px;
  width:100%;margin-top:clamp(34px,5vh,58px);padding:20px 0 clamp(24px,4vh,36px);
  border-top:1px solid color-mix(in srgb,var(--paper) 16%, transparent);
  background:none;color:var(--paper);cursor:pointer;text-align:left;transition:.25s}
.se-next span{font-family:var(--sans);letter-spacing:var(--ls-wide);font-size:9.5px;
  text-transform:uppercase;opacity:.45}
.se-next em{font-family:var(--serif);font-style:normal;font-weight:300;
  font-size:clamp(17px,1.7vw,23px);opacity:.8}
.se-next:hover em{opacity:1}
.se-next:hover{border-top-color:color-mix(in srgb,var(--paper) 42%, transparent)}

@media(max-width:900px){
  #story-scroll .se-cols{grid-template-columns:1fr;gap:26px;align-items:start}
  #story-scroll .se-shot{aspect-ratio:16/10;order:-1}
  #story-scroll .story-end{align-items:flex-start}
  #story-scroll .se-in{padding-top:clamp(58px,8vh,84px)}
  .se-facts>div{padding-right:22px;margin-right:22px}
}


/* ==========================================================================
   VILLA DETAILS — the 1b design, on the site's own ground.
   1b's structure (image hero, spec tiles, go-deeper panel, next-chapter
   block) with the kit's terracotta rather than the exploration's gold.
   ========================================================================== */

/* the chapter header is a picture of the villa, not a line of text over bone */
.dhead.dhero{position:relative;min-height:66vh;min-height:66dvh;display:flex;
  flex-direction:column;justify-content:flex-end;padding:0;overflow:hidden;
  background:var(--well)}
.dhero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.dhero-veil{position:absolute;inset:0;background:linear-gradient(to bottom,
  rgba(10,9,6,.5) 0%,rgba(10,9,6,.12) 22%,rgba(10,9,6,.42) 52%,
  rgba(10,9,6,.8) 78%,var(--cream) 100%)}
.dhero-in{position:relative;display:flex;flex-direction:column;gap:14px;
  padding:clamp(70px,10vh,110px) clamp(22px,5vw,64px) clamp(26px,4vh,40px);max-width:60em}
.dhero-tags{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.dtag{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:var(--paper);background:color-mix(in srgb,var(--well) 80%, transparent);
  border:1px solid color-mix(in srgb,var(--paper) 22%, transparent);border-radius:3px;padding:7px 11px}
.dtag.rs{color:var(--terra);border-color:color-mix(in srgb,var(--terra) 46%, transparent)}
.dhead.dhero .dhead-line{font-family:var(--serif);font-weight:300;
  font-size:clamp(42px,7.4vw,82px);line-height:1.02;color:var(--paper);
  text-shadow:0 1px 20px rgba(10,9,6,.5);margin:0}
.dhero-price{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-top:2px}
.dhero-price .k{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:color-mix(in srgb,var(--paper) 72%, transparent)}
.dhero-price .v{font-family:var(--serif);font-weight:300;
  font-size:clamp(28px,4vw,42px);line-height:1;color:var(--terra)}
.dhero-price .a{font-family:var(--sans);font-size:10.5px;
  color:color-mix(in srgb,var(--paper) 56%, transparent)}
@media(max-width:700px){.dhead.dhero{min-height:60vh;min-height:60dvh}}

/* the specification reads as a set of tiles, one fact each */
.facts.spectiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:8px}
.facts.spectiles>div{border:1px solid color-mix(in srgb,var(--ink) 14%, transparent);
  border-radius:3px;padding:16px 16px 17px;display:flex;flex-direction:column;gap:6px;
  background:color-mix(in srgb,var(--paper) 32%, transparent)}
.facts.spectiles .k{font-family:var(--sans);font-size:9px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;opacity:.62;margin:0}
.facts.spectiles .v{font-family:var(--serif);font-weight:300;font-size:22px;line-height:1.15;margin:0}
.facts.spectiles .v.is-rs{color:var(--terra)}
.facts.spectiles .v small{font-size:14px;opacity:.7}

/* the go-deeper panel — one accented block per chapter, always Grace */
.godeep{margin-top:40px;display:flex;flex-direction:column;gap:14px;align-items:flex-start;
  border:1px solid color-mix(in srgb,var(--terra) 34%, transparent);border-radius:3px;
  padding:clamp(20px,3vw,28px);background:color-mix(in srgb,var(--terra) 5%, transparent)}
.gd-k{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:var(--terra)}
.gd-p{font-family:var(--serif);font-weight:300;font-size:21px;line-height:1.45;
  margin:0;max-width:26em;text-wrap:pretty}
.gd-p.big{font-size:clamp(21px,3vw,27px);line-height:1.35}
/* em is emphasis. Dimming it to .82 put the line at 4.34:1 and said the
   opposite of what the tag means — the italic already carries the stress. */
.gd-p em{font-style:italic}
.gd-btn{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls);
  text-transform:uppercase;font-weight:500;color:var(--cream);background:var(--terra);
  border:1px solid var(--terra);border-radius:3px;padding:15px 22px 16px;cursor:pointer;transition:.25s}
.gd-btn:hover{background:var(--ink);border-color:var(--ink);color:var(--paper)}

/* the end of a chapter is a door to the next one, not a link */
.nextblock{display:flex;flex-direction:column;gap:9px;align-items:flex-start;margin-top:26px}
.nb-k{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:var(--dim)}
.nb-h{font-family:var(--serif);font-weight:300;font-size:clamp(30px,5.4vw,44px);
  line-height:1.1;text-align:left;background:none;border:0;padding:0;cursor:pointer;
  color:inherit;transition:color .25s}
@media(hover:hover){.nb-h:hover{color:var(--hover)}}
.nb-h.as-text{cursor:default;max-width:22em;text-wrap:pretty}
.nb-p{font-family:var(--serif);font-weight:300;font-size:18px;line-height:1.55;
  color:var(--dim);margin:2px 0 6px;max-width:28em;text-wrap:pretty}
.nextblock .talklink{margin-top:10px}


/* v28 — the hero sits on a photograph, so it is dark ground no matter what
   the page around it is. On #v-details the kit flips --paper/--terra to ink
   colours for the bone ground; the hero must not inherit them. Literals. */
.dhead.dhero{background:#11150C}
.dhead.dhero .dhead-line{color:#E6E1D1}
.dtag{color:#E6E1D1;background:rgba(17,21,12,.82);border-color:rgba(230,225,209,.22)}
.dtag.rs{color:#949E86;border-color:rgba(148,158,134,.46)}
.dhero-price .k{color:rgba(230,225,209,.72)}
.dhero-price .v{color:#949E86}
.dhero-price .a{color:rgba(230,225,209,.56)}
/* and the spec tile is a light card on bone, not a 32% ink wash */
.facts.spectiles>div{background:color-mix(in srgb,#FFFFFF 46%, transparent)}
.facts.spectiles .k{opacity:.78}


/* v28.1 — the spec tile label is a label like any other on this page: full
   opacity, the kit's 11.5px, not a dimmed 9px exception. */
.facts.spectiles .k{font-size:11.5px;opacity:1}


/* ==========================================================================
   VILLA DETAILS — direction 1b, "Cinema".
   Forest ground, image-led: the render is the page and the type lives in the
   scrim. Brass carries the price and the live chapter; everything else is
   sand on forest. Supersedes the bone-ground pass above.
   ========================================================================== */
.dhead.dhero{min-height:0;height:clamp(430px,58vh,620px);background:#11150C}
.dhero-veil{background:linear-gradient(to bottom,
  rgba(17,21,12,.55) 0%,rgba(17,21,12,.08) 34%,rgba(17,21,12,.72) 74%,var(--cream) 100%)}
.dhero-top{position:absolute;top:0;left:0;right:0;z-index:2;display:flex;align-items:center;
  justify-content:space-between;gap:12px;padding:18px clamp(22px,4vw,40px)}
.dhero-mark{height:30px;width:auto;opacity:.9}
.dhero-pill{font-family:var(--sans);font-size:9px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:rgba(230,225,209,.82);
  border:1px solid rgba(230,225,209,.34);border-radius:3px;padding:7px 11px}
.dhero-in{gap:12px;padding:0 clamp(22px,4vw,40px) clamp(24px,3.4vh,34px)}
.dhero-k{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:var(--sun)}
.dhead.dhero .dhead-line{font-size:clamp(38px,6vw,64px);line-height:1.06}
.dhero-price{gap:12px;margin-top:4px}
.dhero-price .v{color:var(--sun);font-size:clamp(24px,3.2vw,34px)}

/* the three quiet plates the direction opens on */
.plates{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:0 0 30px}
.plates>div{background:var(--midnight);border:1px solid rgba(230,225,209,.1);
  border-radius:3px;padding:16px 14px 17px;display:flex;flex-direction:column;gap:6px}
.pl-k{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:rgba(230,225,209,.72)}
.pl-v{font-family:var(--serif);font-weight:300;font-size:clamp(24px,3vw,30px);line-height:1}
.pl-v small{font-size:.52em}
.pl-v.brass{color:var(--sun)}
.pl-s{font-family:var(--sans);font-size:9.5px;line-height:1.5;color:rgba(230,225,209,.58)}
@media(max-width:520px){.plates{gap:7px}.plates>div{padding:13px 11px}}

/* brass on the live chapter, sage stays the general accent */
.chbar .cbchip.active{background:var(--sun);color:#1D2415;border-color:var(--sun)}
.chbar .cbchip.active:hover{background:var(--paper);color:#1D2415;border-color:var(--paper)}

/* the go-deeper panel and the spec tiles return to forest ground */
.godeep{border-color:rgba(216,178,74,.3);background:var(--midnight)}
.gd-k{color:var(--sun)}
.gd-btn{background:var(--sun);border-color:var(--sun);color:#1D2415}
.gd-btn:hover{background:var(--paper);border-color:var(--paper);color:#1D2415}
.facts.spectiles>div{background:var(--midnight);border-color:rgba(230,225,209,.12)}
.facts.spectiles .k{color:rgba(230,225,209,.7);opacity:1;font-size:9.5px;letter-spacing:var(--ls-wide)}
.facts.spectiles .v{color:var(--paper)}
.facts.spectiles .v.is-rs{color:var(--sun)}


/* v29 — the mark is a mark, not the render: the full-bleed rule is scoped to
   the hero image only, so .dhero-mark keeps its own box. */
.dhead.dhero .dhero-mark{position:static;inset:auto;width:auto;height:30px;
  object-fit:contain;flex:none}

/* v29 — Cinema pins the chapter bar to the BOTTOM of the frame, on moss:
   the chapters are a foot to the page, not a header. */
.dhead.dhero + .chbar{position:sticky;top:auto;bottom:0;z-index:34;
  background:var(--stone);border-top:1px solid rgba(230,225,209,.12);
  border-bottom:0;padding:14px clamp(22px,4vw,40px);backdrop-filter:none}
.dhead.dhero + .chbar .chbar-scroll{gap:8px}
.dhead.dhero + .chbar .cbchip{flex:1;justify-content:center;text-align:center}
/* the last thing in a chapter must clear the pinned bar */
.dhead.dhero ~ .sec{padding-bottom:clamp(96px,14vh,140px)}


/* ==========================================================================
   THE NUMBERS, in Cinema.
   Two grounds only: forest for the page, midnight for anything that is a
   plate. Brass is reserved — the headline return, the sales price, the live
   scenario, the currency in play. Everything else is sand and sage.
   ========================================================================== */

/* the three bands stop being tinted washes and become plates, like the
   spec tiles and the opening three */
#v-details .band{background:var(--midnight);
  border:1px solid rgba(230,225,209,.1);border-radius:6px}
#v-details .band-invest,#v-details .band-returns,#v-details .band-path{
  background:var(--midnight)}
#v-details .band-path{border-color:rgba(148,158,134,.26)}

/* the proof panel was an inverted sand card — on forest that painted sand
   type on a sand ground. One ground, one direction. */
#v-details .rt-proof{background:var(--midnight);color:var(--paper);
  border-top:1px solid rgba(230,225,209,.12);border-bottom:1px solid rgba(230,225,209,.12)}
#v-details .rt-proof-head,#v-details .rt-proof-n,#v-details .rt-proof-close{color:var(--paper)}
#v-details .rt-proof-n{color:var(--sun)}

/* the 30-year chart keeps its dark moment, but has to declare an edge now
   that the page around it is dark too */
#v-details .mnband{border-top:1px solid rgba(230,225,209,.12);
  border-bottom:1px solid rgba(230,225,209,.12)}

/* the donut was mixed for a bone ground: midnight and stone vanish on
   forest. Re-cut the wheel in sand → sage → moss, brass on the margin. */
#v-details .dseg[data-seg="build"]{fill:#E6E1D1}
#v-details .dseg[data-seg="own"]{fill:#949E86}
#v-details .dseg[data-seg="shared"]{fill:#5A6B57}
#v-details .dseg[data-seg="community"]{fill:#C9B489}
#v-details .dseg[data-seg="margin"]{fill:#D8B24A}
#v-details .bd-row[data-seg="build"] .bd-sw{background:#E6E1D1 !important}
#v-details .bd-row[data-seg="own"] .bd-sw{background:#949E86 !important}
#v-details .bd-row[data-seg="shared"] .bd-sw{background:#5A6B57 !important}
#v-details .bd-row[data-seg="community"] .bd-sw{background:#C9B489 !important}
#v-details .bd-row[data-seg="margin"] .bd-sw{background:#D8B24A !important}
#v-details .dprice-v{color:var(--sun)}
/* --dim-soft is paper at 76% on bone, which lands these two at 4.48:1 against
   a 4.5 bar — under, by a rounding error's width. Both are small text, so they
   take --dim (88%) like every other small label on this ground. */
#v-details .dprice-k,#v-details .dprice-alt{color:var(--dim)}
#v-details .dhole-caps{fill:rgba(230,225,209,.62)}

/* brass, used four times and no more */
#v-details .rt-hero-num{color:var(--sun)}
#v-details .bd-total .v{color:var(--sun) !important}
#v-details .curchip button.active{background:var(--sun);color:#1D2415}
#v-details .qcompare .qc.base{border-color:rgba(216,178,74,.55);
  background:rgba(216,178,74,.07)}
#v-details .qcompare .qc.base .qc-y{color:var(--sun)}
#v-details .schip.active{background:var(--sun);color:#1D2415;border-color:var(--sun)}
#v-details .qtuned{border-left-color:var(--sun)}
#v-details .qtuned .qt-k{color:var(--sun)}
#v-details .pgtiles>div:first-child .pgtv{color:var(--sun)}

/* compare-the-six cards were a light wash — plates here like everything else */
#v-details .vcard{background:var(--midnight);border-color:rgba(230,225,209,.12)}
#v-details .vcard.active{background:rgba(216,178,74,.07);border-color:rgba(216,178,74,.5)}
#v-details .vcard .vtag,#v-details .vcard .ytag b{color:var(--sun)}

/* the founders' note is the one warm aside — sage, on the page ground */
#v-details .fnote{background:rgba(148,158,134,.07);
  border-left-color:rgba(148,158,134,.55)}
#v-details .fc-b b{color:var(--sun)}

/* the P&L and the payment path read as ledgers on forest, not cards */
#v-details .pnlwrap,#v-details .miles{color:var(--paper)}
#v-details .pathmiles .pct{color:var(--sun)}


/* ==========================================================================
   THE NUMBERS — the spine.
   The chapter is three arguments, not twenty modules: a sticky line that
   keeps the price and the live scenario in view, a numbered mark opening
   each band, and one panel holding every slider.
   ========================================================================== */
#v-details .nsticky{position:sticky;top:0;z-index:28;display:flex;align-items:baseline;
  gap:14px;flex-wrap:wrap;margin:0 0 26px;padding:13px clamp(16px,2.4vw,22px) 14px;
  background:color-mix(in srgb,var(--midnight) 94%, transparent);backdrop-filter:blur(10px);
  border:1px solid rgba(230,225,209,.12);border-radius:4px}
.ns-p{font-family:var(--serif);font-weight:300;font-size:23px;line-height:1;color:var(--sun)}
.ns-v,.ns-s{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:rgba(230,225,209,.72)}
.ns-s{color:rgba(230,225,209,.5)}
.ns-nav{display:flex;gap:6px;margin-left:auto}
.ns-nav a{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls);
  text-transform:uppercase;color:rgba(230,225,209,.72);border:1px solid rgba(230,225,209,.2);
  border-radius:3px;padding:8px 11px 9px;transition:.25s}
.ns-nav a:hover{color:#1D2415;background:var(--paper);border-color:var(--paper)}
@media(max-width:640px){.ns-nav{width:100%;margin-left:0}.ns-nav a{flex:1;text-align:center}}

/* each band opens by saying which of the three arguments it is */
.bandmark{display:flex;align-items:baseline;gap:12px;margin:0 0 26px;
  padding-bottom:14px;border-bottom:1px solid rgba(230,225,209,.14)}
.bandmark i{font-family:var(--serif);font-style:normal;font-weight:300;
  font-size:34px;line-height:1;color:var(--sun);opacity:.85}
.bandmark span{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:rgba(230,225,209,.62)}

/* every slider in one instrument, income above the exit */
.instrument{border:1px solid rgba(230,225,209,.12);border-radius:5px;
  padding:clamp(20px,2.6vw,30px);margin:6px 0 10px;
  background:color-mix(in srgb,var(--paper) 3%, transparent)}
.inst-head{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin:0 0 22px}
.instrument .pgsliders + .inst-head{margin-top:34px;padding-top:26px;
  border-top:1px solid rgba(230,225,209,.14)}
.inst-k{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:var(--sun)}
.inst-n{font-family:var(--serif);font-style:italic;font-size:16px;
  color:rgba(230,225,209,.68);max-width:44ch;text-wrap:pretty}
.instrument .pgsliders{max-width:none;margin-bottom:0}


/* v30 — rupiah is the page's currency; the dollar is a question you ask.
   The compare link is a quiet ask, not a second toggle. */
.ns-price{display:flex;flex-direction:column;gap:3px}
.ns-compare,.dhero-cmp{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls);
  text-transform:uppercase;color:rgba(230,225,209,.6);background:none;border:0;padding:0;
  cursor:pointer;border-bottom:1px solid rgba(230,225,209,.28);transition:.25s;align-self:flex-start}
.ns-compare:hover,.dhero-cmp:hover{color:var(--sun);border-bottom-color:var(--sun)}
.dhero-cmp{color:rgba(230,225,209,.66)}

/* one hero number, one paragraph carrying the rest of the ladder */
.rt-hero.one{grid-template-columns:1fr;gap:0;margin-bottom:44px}
.rt-hero.one .rt-hero-sub{max-width:52ch}
.rt-hero.one .rt-hero-sub b{font-family:var(--serif);font-weight:400;
  font-size:1.12em;color:var(--paper)}

/* the payment path closes the cost band rather than owning one of its own */
#v-details .miles.pathmiles{margin-top:22px}


/* v31 — the hero owns net yield, so the ledger row is the three things it
   does not say. Three columns, not four. */
#v-details .pgtiles{grid-template-columns:repeat(3,1fr)}
@media(max-width:760px){#v-details .pgtiles{grid-template-columns:1fr 1fr}}


/* ==========================================================================
   VILLA DETAILS — sand ground.
   The kit already owns the light-ground flip (body.on-bone #v-details) and
   its contrast compensations; the body carries it again. What follows is
   only what the kit has no rule for: the pieces this design added, and the
   two places that must stay DARK ground because they sit on a photograph.
   ========================================================================== */

/* --- over the render: dark ground, whatever the page is --- */
#v-details .dhero-k{color:#D8B24A}
#v-details .dhero-price .v{color:#D8B24A}
#v-details .dhero-price .k{color:rgba(230,225,209,.75)}
#v-details .dhero-cmp{color:rgba(230,225,209,.72);border-bottom-color:rgba(230,225,209,.4)}
#v-details .dhero-cmp:hover{color:#D8B24A;border-bottom-color:#D8B24A}
#v-details .dhero-pill{color:rgba(230,225,209,.85);border-color:rgba(230,225,209,.36)}
#v-details .dhero-veil{background:linear-gradient(to bottom,
  rgba(17,21,12,.55) 0%,rgba(17,21,12,.08) 34%,rgba(17,21,12,.72) 74%,var(--cream) 100%)}

/* --- the chapter foot stays forest: a page needs a bottom --- */
#v-details .chbar{background:#1D2415}
#v-details .chbar .cbchip,#v-details .chbar .cbhome{
  color:#E6E1D1;border-color:rgba(230,225,209,.28)}
#v-details .chbar .cbchip.active{background:#D8B24A;color:#1D2415;border-color:#D8B24A}

/* --- pieces the kit has no rule for --- */
#v-details .plates>div,#v-details .facts.spectiles>div{
  background:color-mix(in srgb,#FFFFFF 44%, transparent);
  border:1px solid color-mix(in srgb,var(--ink) 15%, transparent)}
#v-details .pl-k,#v-details .pl-s,#v-details .facts.spectiles .k{color:var(--ink);opacity:.92}
#v-details .pl-v,#v-details .facts.spectiles .v{color:var(--ink);opacity:1}
#v-details .pl-v.brass,#v-details .facts.spectiles .v.is-rs{color:var(--sun)}

#v-details .band{background:color-mix(in srgb,var(--ink) 5%, var(--cream));
  border:1px solid color-mix(in srgb,var(--ink) 12%, transparent);border-radius:6px}
#v-details .nsticky{position:sticky;top:0;z-index:28;
  background:color-mix(in srgb,var(--cream) 94%, transparent);
  border:1px solid color-mix(in srgb,var(--ink) 15%, transparent)}
#v-details .ns-p,#v-details .bandmark i,#v-details .rt-hero-num,
#v-details .pathmiles .pct,#v-details .inst-k,#v-details .qt-k{color:var(--sun)}
#v-details .ns-v,#v-details .ns-s,#v-details .ns-compare,
#v-details .bandmark span,#v-details .inst-n{color:var(--ink);opacity:.92}
#v-details .ns-nav a{color:var(--ink);opacity:.92;border-color:color-mix(in srgb,var(--ink) 26%, transparent)}
#v-details .ns-nav a:hover{background:var(--ink);color:var(--cream);opacity:1}
#v-details .bandmark{border-bottom-color:color-mix(in srgb,var(--ink) 16%, transparent)}
#v-details .instrument{border:1px solid color-mix(in srgb,var(--ink) 14%, transparent);
  background:color-mix(in srgb,#FFFFFF 34%, transparent)}
#v-details .instrument .pgsliders + .inst-head{border-top-color:color-mix(in srgb,var(--ink) 14%, transparent)}
#v-details .godeep{background:color-mix(in srgb,var(--sun) 7%, transparent);
  border:1px solid color-mix(in srgb,var(--sun) 40%, transparent)}
#v-details .gd-k{color:var(--sun)}
#v-details .gd-btn{background:var(--sun);border-color:var(--sun);color:var(--cream)}
#v-details .gd-btn:hover{background:var(--ink);border-color:var(--ink);color:var(--cream)}

/* --- the wheel, cut for paper --- */
#v-details .dseg[data-seg="build"]{fill:#2E4034}
#v-details .dseg[data-seg="own"]{fill:#5A6B57}
#v-details .dseg[data-seg="shared"]{fill:#9AA894}
#v-details .dseg[data-seg="community"]{fill:#C2B183}
#v-details .dseg[data-seg="margin"]{fill:#8A6A12}
#v-details .bd-row[data-seg="build"] .bd-sw{background:#2E4034 !important}
#v-details .bd-row[data-seg="own"] .bd-sw{background:#5A6B57 !important}
#v-details .bd-row[data-seg="shared"] .bd-sw{background:#9AA894 !important}
#v-details .bd-row[data-seg="community"] .bd-sw{background:#C2B183 !important}
#v-details .bd-row[data-seg="margin"] .bd-sw{background:#8A6A12 !important}
#v-details .dhole-caps{fill:var(--ink);fill-opacity:.7}
#v-details .bd-total .v{color:var(--sun) !important}

/* --- brass on the live scenario, and the two 1.0-ratio bugs --- */
#v-details .schip.active{background:var(--sun);color:var(--cream);border-color:var(--sun)}
#v-details .qtuned{border-left-color:var(--sun)}
#v-details .vcard .vtag,#v-details .vcard .ytag b{color:var(--sun)}
#v-details .rt-hero-num .pct{color:var(--sun)}
#v-details .styler .fopt.on .pr,#v-details .styler .fopt.on .nm{color:var(--cream)}
#v-details .fnb-edit,#v-details .vgridnote,#v-details .rn,#v-details .cur,
#v-details .nb-k,#v-details .quietlink,#v-details .gdot{opacity:1;color:var(--ink)}
#v-details .quietlink,#v-details .talklink{color:var(--terra)}
#v-details .gdot{border-color:color-mix(in srgb,var(--ink) 42%, transparent)}


/* v32 — sand ground, the leftovers.
   Four places kept a dark-ground fill or literal after the flip. */

/* compare-the-six: --midnight is ink on this ground, so the card was
   painting forest under forest text */
#v-details .vcard{background:color-mix(in srgb,var(--ink) 5%, transparent);
  border-color:color-mix(in srgb,var(--ink) 16%, transparent)}
#v-details .vcard.active{background:color-mix(in srgb,var(--sun) 8%, transparent);
  border-color:color-mix(in srgb,var(--sun) 55%, transparent)}

/* a selected furnishing option is ink-filled, so its text is cream */
#v-details .styler .fopt.on{background:var(--ink);border-color:var(--ink)}
#v-details .styler .fopt.on .nm,#v-details .styler .fopt.on .pr,
#v-details .styler .fopt.on .tick{color:var(--cream)}

/* gallery captions were never inverted */
#v-details .gal figcaption,#v-details .gal figcaption.caps,
#v-details .plans-grid figcaption{color:var(--ink);opacity:.92}

/* the conversion note is the whole point of the compare — sage was a
   dark-ground colour here */
#v-details .bd-total .v small{color:var(--terra) !important;opacity:1}

/* the dimmed label family carries its alpha in the colour, so the kit's
   opacity compensation cannot reach it — restate at a legible weight */
#v-details .schips-note,#v-details .methrow .k,#v-details .pgsk,
#v-details .pgsd,#v-details .pgtsub,#v-details .pgtl,#v-details .pnlhead,
#v-details .rt-hero-over,#v-details .rt-hero-sub,#v-details .pnl-val.pnl-cost,
#v-details .vgridnote,#v-details .pl-s{color:color-mix(in srgb,var(--ink) 86%, transparent)}
#v-details .bandmark i{color:#7A5D0F}


/* ==========================================================================
   v33 — one cause: the brass token and the kit's dim-label idiom were both
   calibrated on the dark ground, where a 62% alpha and a .7 opacity still
   read. On paper they land at 3.0–4.1:1. Fix the token and the floor once,
   inside the light-ground scope, rather than element by element.
   ========================================================================== */
body.on-bone #v-included,body.on-bone #v-materials,body.on-bone #v-journey,
body.on-bone #v-details{--sun:#6F5410;--sun-soft:color-mix(in srgb,#6F5410 22%, transparent)}

/* the dim family: one floor, both mechanisms */
#v-details .facts .sub,#v-details .fld span,#v-details .bd-name .d,
#v-details .splitkey span,#v-details .vspec,#v-details .qc-s,
#v-details .smallprint,#v-details .fnoncap,#v-details .frnote,
#v-details .mncaption,#v-details .qt-note{
  color:color-mix(in srgb,var(--ink) 86%, transparent);opacity:1}
#v-details .vcard .vmeta div small,#v-details .pnl-lbl small,
#v-details .miles .amt,#v-details .facts .v small,#v-details .facts .k,
#v-details .vcard .vmeta,#v-details .ytag small{
  opacity:1;color:color-mix(in srgb,var(--ink) 86%, transparent)}

/* text sitting ON brass takes the page ground, which is lighter than cream */
#v-details .gd-btn,#v-details .schip.active,#v-details .curchip button.active{
  color:#FBFAF4}


/* v34 — the hero no longer dissolves into paper: it darkens into the green
   chapter bar, so the render and the menu read as one head to the page. */
#v-details .dhero-veil{background:linear-gradient(to bottom,
  rgba(17,21,12,.55) 0%,rgba(17,21,12,.06) 30%,rgba(17,21,12,.62) 68%,
  rgba(29,36,21,.92) 90%,#1D2415 100%)}
#v-details .dhead.dhero + .chbar{position:sticky;top:var(--nav-h);bottom:auto;
  background:#1D2415;border-top:0;
  border-bottom:1px solid rgba(230,225,209,.14)}
#v-details .dhead.dhero ~ .sec{padding-bottom:clamp(56px,8vh,90px)}


/* v34.1 — the nav is position:relative on this page (a later .nav rule wins),
   so it scrolls away and a var(--nav-h) offset leaves an uncovered band with
   content sliding through it. The bar is the page's green head: pin it flush. */
#v-details .dhead.dhero + .chbar{top:0}


/* v35 — nothing washes the top of the render: the veil starts clear and only
   darkens where the type needs it. */
#v-details .dhero-veil{background:linear-gradient(to bottom,
  transparent 0%,transparent 34%,rgba(17,21,12,.58) 68%,
  rgba(29,36,21,.92) 90%,#1D2415 100%)}
#v-details .dhero::before,#v-details .dhead.dhero::before{display:none}
#v-details.on-sand .nav::before,#v-details .dhead.dhero .nav::before{opacity:0}


/* ==========================================================================
   v36 — four passes over the sand design.
   ========================================================================== */

/* 3 — one dark landmark in a very long sand scroll. The founders' note is
   the argument the page turns on, so it is the moment that goes forest. */
#v-details .fnote{background:#1D2415;color:#E6E1D1;border-left:0;
  border-radius:6px;padding:clamp(30px,3.6vw,52px) clamp(24px,3.2vw,46px);
  max-width:none}
#v-details .fnote .over{color:#D8B24A}
#v-details .fnote h3{color:#E6E1D1;font-size:clamp(26px,3.2vw,38px);
  font-weight:300;line-height:1.15;margin-bottom:.5em;max-width:20ch}
#v-details .fnote p{color:rgba(230,225,209,.86);max-width:56ch}
#v-details .fnote em{color:#D8B24A;font-style:italic}
#v-details .fnote .fnote-close{color:#E6E1D1;font-style:italic;
  border-top:1px solid rgba(230,225,209,.18);padding-top:20px;margin-top:24px}
#v-details .fnote .fnote-sign{color:rgba(230,225,209,.6);margin-top:18px}

/* 4 — the two numbers people actually compare on carry the row */
#v-details .facts.spectiles{grid-template-columns:repeat(6,1fr)}
#v-details .facts.spectiles>div{grid-column:span 2}
#v-details .facts.spectiles>div:nth-child(3),
#v-details .facts.spectiles>div:nth-child(4){grid-column:span 3;
  background:color-mix(in srgb,#FFFFFF 70%, transparent)}
#v-details .facts.spectiles>div:nth-child(3) .v,
#v-details .facts.spectiles>div:nth-child(4) .v{font-size:clamp(30px,3.4vw,42px)}
@media(max-width:820px){
  #v-details .facts.spectiles{grid-template-columns:repeat(2,1fr)}
  #v-details .facts.spectiles>div,
  #v-details .facts.spectiles>div:nth-child(3),
  #v-details .facts.spectiles>div:nth-child(4){grid-column:span 1}
  #v-details .facts.spectiles>div:nth-child(3),
  #v-details .facts.spectiles>div:nth-child(4){grid-column:span 2}
}

/* 5 — the gallery and the plans are really openable now */
#v-details .gal figure,#v-details .plans-grid figure{cursor:zoom-in}
#lightbox.solo .lb-p,#lightbox.solo .lb-n{display:none}
#lightbox .lb-cap{max-width:70ch;margin:0 auto;padding:0 24px}


/* v36.1 — Plot and Built span 3 of 6, so they only tile without holes if
   they lead the block. Order them first; the six equal tiles fill two
   clean rows of three behind them. */
#v-details .facts.spectiles>div:nth-child(3),
#v-details .facts.spectiles>div:nth-child(4){order:-1}


/* ==========================================================================
   v37 — one top bar, not two.
   The white nav is gone: the render carries the mark, and everything the nav
   held moves behind a two-rule burger. The green chapter bar is the only
   fixed chrome on the page.
   ========================================================================== */
#v-details .dhead.dhero{padding-top:0}
#v-details .dhero-top{padding-top:22px}
.dhero-burger{display:flex;flex-direction:column;justify-content:center;gap:6px;
  width:44px;height:44px;padding:0 0 0 21px;background:none;border:0;cursor:pointer}
.dhero-burger i{display:block;width:23px;height:1px;background:#E6E1D1;
  transition:transform .35s var(--ease),opacity .25s}
body.vd-open .dhero-burger i:first-child{transform:translateY(3.5px) rotate(45deg)}
body.vd-open .dhero-burger i:last-child{transform:translateY(-3.5px) rotate(-45deg)}

#vd-scrim{position:fixed;inset:0;z-index:640;background:rgba(10,9,6,.5);
  opacity:0;pointer-events:none;transition:opacity .4s var(--ease)}
body.vd-open #vd-scrim{opacity:1;pointer-events:auto}
#vd-menu{position:fixed;inset:0 0 auto 0;z-index:650;background:#1D2415;
  color:#E6E1D1;padding:34px clamp(22px,5vw,56px) 40px;
  display:flex;flex-direction:column;gap:26px;
  border-bottom:1px solid rgba(230,225,209,.14);
  transform:translateY(-101%);transition:transform .5s var(--ease);
  box-shadow:0 26px 60px rgba(10,9,6,.5)}
body.vd-open #vd-menu{transform:none}
.vd-resume{display:flex;flex-direction:column;gap:6px;align-items:flex-start;
  text-align:left;background:none;border:1px solid rgba(216,178,74,.4);
  border-radius:3px;padding:16px 20px 17px;cursor:pointer;transition:.25s}
.vd-resume:hover{border-color:#D8B24A;background:rgba(216,178,74,.08)}
.vd-k{font-family:var(--sans);font-size:9.5px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:#D8B24A}
.vd-v{font-family:var(--serif);font-weight:300;font-size:23px;color:#E6E1D1}
.vd-list{display:flex;flex-direction:column}
.vd-list button{display:flex;align-items:baseline;gap:18px;text-align:left;
  background:none;border:0;border-top:1px solid rgba(230,225,209,.14);
  padding:18px 0 19px;cursor:pointer;color:#E6E1D1;transition:.25s}
.vd-list button:last-child{border-bottom:1px solid rgba(230,225,209,.14)}
.vd-list button:hover{color:#D8B24A}
.vd-list em{font-family:var(--sans);font-style:normal;font-size:9.5px;
  letter-spacing:var(--ls-wide);opacity:.5;min-width:2.4em}
.vd-list span{font-family:var(--serif);font-weight:300;font-size:clamp(26px,3.4vw,38px);line-height:1}
.vd-list button.active span{color:#D8B24A}
.vd-x{position:absolute;top:26px;right:clamp(22px,5vw,56px);background:none;border:0;
  color:rgba(230,225,209,.7);font-size:17px;padding:10px;cursor:pointer;transition:.25s}
.vd-x:hover{color:#E6E1D1}


/* v38 — the currency compare is a question, not a line of copy: a small
   circled mark beside the price that says what it does on hover or tap. */
#v-details .curq{position:relative;width:19px;height:19px;padding:0;flex:none;
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--sans);font-size:10.5px;line-height:1;border-radius:50%;
  border:1px solid currentColor;background:none;cursor:pointer;
  opacity:.62;transition:opacity .25s,color .25s,border-color .25s;vertical-align:middle}
#v-details .curq:hover,#v-details .curq:focus-visible{opacity:1;color:var(--sun)}
#v-details .ns-q{color:var(--ink);margin-left:2px;align-self:center}
#v-details .dhero-q{color:#E6E1D1}
#v-details .dhero-q:hover,#v-details .dhero-q:focus-visible{color:#D8B24A}
#v-details .curq-tip{position:absolute;left:50%;bottom:calc(100% + 10px);
  transform:translate(-50%,4px);width:max-content;max-width:min(64vw,25em);
  background:#1D2415;color:#E6E1D1;border:1px solid rgba(216,178,74,.4);
  border-radius:3px;padding:10px 14px 11px;
  font-family:var(--serif);font-style:italic;font-weight:300;font-size:15.5px;
  line-height:1.4;letter-spacing:0;text-transform:none;text-align:left;
  opacity:0;pointer-events:none;transition:opacity .25s var(--ease),transform .25s var(--ease);
  box-shadow:0 16px 40px rgba(10,9,6,.45);z-index:40}
#v-details .curq:hover .curq-tip,#v-details .curq:focus-visible .curq-tip,
#v-details .curq:active .curq-tip{opacity:1;transform:translate(-50%,0)}
#v-details .ns-price{flex-direction:row;align-items:center;gap:9px}
@media(max-width:560px){#v-details .curq-tip{left:0;transform:translate(0,4px)}
  #v-details .curq:hover .curq-tip,#v-details .curq:focus-visible .curq-tip{transform:translate(0,0)}}


/* v38.1 — the marks sit at the right edge of the layout, so a left-anchored
   tip runs off the viewport (and, being laid out at opacity 0, put the page
   into horizontal scroll). Anchor it to the right edge of the button. */
#v-details .curq-tip{left:auto;right:-6px;transform:translate(0,4px)}
#v-details .curq:hover .curq-tip,#v-details .curq:focus-visible .curq-tip,
#v-details .curq:active .curq-tip{transform:translate(0,0)}
@media(max-width:560px){
  #v-details .curq-tip{left:auto;right:-6px;max-width:min(78vw,25em)}
  #v-details .curq:hover .curq-tip,#v-details .curq:focus-visible .curq-tip{transform:translate(0,0)}
}
/* and the light-ground mark carries its dimming in the colour, not opacity */
#v-details .ns-q{opacity:1;color:color-mix(in srgb,var(--ink) 86%, transparent)}
#v-details .ns-q:hover,#v-details .ns-q:focus-visible{color:var(--sun)}


/* v39 — Grace stays put: the brass lockup is fixed to the lower right on
   every chapter, above the chapter bar and clear of the menu. */
#c-fab{position:fixed;right:26px;bottom:26px;z-index:820;opacity:1;pointer-events:auto}
body.vd-open #c-fab{opacity:0;pointer-events:none}
@media(max-width:860px){#c-fab{right:16px;bottom:16px}}


/* ==========================================================================
   v40 — the three places you are asked to type.
   They read as underlines on paper, which on a sand ground is invisible as
   an affordance. Give them a real field: a white well, a ruled edge, a
   label above it and a brass focus.
   ========================================================================== */
#v-details .leadfields{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:16px;margin:22px 0 4px}
#v-details .fld{display:flex;flex-direction:column;gap:8px;cursor:text}
#v-details .fld span{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:color-mix(in srgb,var(--ink) 86%, transparent);opacity:1}
#v-details .fld input{width:100%;min-height:54px;
  background:#FFFFFF;color:var(--ink);
  border:1px solid color-mix(in srgb,var(--ink) 26%, transparent);
  border-radius:3px;padding:15px 16px 16px;
  font-family:var(--serif);font-weight:300;font-size:20px;line-height:1.2;
  outline:none;transition:border-color .2s,box-shadow .2s}
#v-details .fld input::placeholder{color:color-mix(in srgb,var(--ink) 45%, transparent);
  font-style:italic;font-size:17px}
#v-details .fld input:hover{border-color:color-mix(in srgb,var(--ink) 42%, transparent)}
#v-details .fld input:focus{border-color:var(--sun);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--sun) 18%, transparent)}
#v-details .fld-warn{font-family:var(--sans);font-size:11px;letter-spacing:.04em;
  color:#8A3A1E;margin-top:10px}

/* naming the villa is a button, not a whispered link */
#v-details .fnamebar{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
#v-details .fnb-name{font-family:var(--serif);font-weight:300;font-size:24px;color:var(--ink)}
#v-details .fnb-edit{display:inline-flex;align-items:center;gap:8px;
  font-family:var(--sans);font-size:10px;letter-spacing:var(--ls);text-transform:uppercase;
  color:var(--ink);opacity:1;background:none;cursor:pointer;
  border:1px solid color-mix(in srgb,var(--ink) 30%, transparent);border-radius:3px;
  padding:9px 14px 10px;transition:.25s}
#v-details .fnb-edit:hover{background:var(--ink);color:var(--cream);border-color:var(--ink)}
#v-details .fnb-edit i{display:block;width:11px;height:11px;flex:none;
  border:1px solid currentColor;border-radius:1px;
  border-top-color:transparent;border-right-color:transparent;transform:rotate(-45deg)}


/* v40.1 — naming the villa is the same kind of asking as the name and the
   email below it, so it is the same kind of field. */
#v-details .fnamebar{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap;
  padding:clamp(18px,2.2vw,24px);border-bottom:1px solid color-mix(in srgb,var(--ink) 14%, transparent)}
#v-details .fld-villa{flex:1 1 260px;min-width:0}
#v-details .fnb-save{min-height:54px;flex:none;
  background:var(--sun);border:1px solid var(--sun);color:#FBFAF4;
  font-family:var(--sans);font-size:10.5px;letter-spacing:var(--ls);
  text-transform:uppercase;font-weight:500;padding:0 24px;border-radius:3px;cursor:pointer;transition:.25s}
#v-details .fnb-save:hover{background:var(--ink);border-color:var(--ink)}


/* ==========================================================================
   THE IDEA — the same sand chapter as villa details.
   #v-idea joins the light-ground scope, and the pieces this design added
   (photograph hero, forest chapter bar, the founders' note as the one dark
   landmark) are shared with #v-details rather than re-typed.
   ========================================================================== */
body.on-bone #v-idea{
  --cream:#E8E6DA;--paper:#2E4034;--ink:#2E4034;--terra:#3E5443;--ghost:#5A6B57;
  --sun:#6F5410;--sun-soft:color-mix(in srgb,#6F5410 22%, transparent);--sun-ink:#E8E6DA;
  --stone:#5A6B57;--well:#D6D4C6;--midnight:#2E4034;--hover:#1D2415;--hover-on:#E8E6DA;
  /* the state tokens are NOT optional here. This block predates the base-rules
     pass and stopped at --hover, so --dim still resolved to the ROOT value —
     sand at 74% — and painted three nodes at 1.03:1 on the bone ground the
     moment the page flipped. A blank rectangle, no error. CLAUDE.md's
     inversion trap, found by the sweep it tells you to run. */
  --dim:color-mix(in srgb,var(--paper) 88%, transparent);
  --dim-soft:color-mix(in srgb,var(--paper) 76%, transparent);
  background:#E8E6DA;color:#2E4034}

/* over the render: dark ground, whatever the page is */
#v-idea .dhead.dhero{min-height:0;height:clamp(460px,66vh,720px);background:#11150C;padding:0;
  position:relative;display:flex;flex-direction:column;justify-content:flex-end;overflow:hidden}
#v-idea .dhero-veil{background:linear-gradient(to bottom,
  transparent 0%,transparent 34%,rgba(17,21,12,.58) 68%,
  rgba(29,36,21,.92) 90%,#1D2415 100%)}
#v-idea .dhero-k{color:#D8B24A}
#v-idea .dhead.dhero .dhead-line{color:#E6E1D1}
#v-idea .dhero-mark{position:static;inset:auto;width:auto;height:30px;object-fit:contain;flex:none}

/* the chapter bar is the page's green head, flush under the render */
#v-idea .chbar{position:sticky;top:0;bottom:auto;z-index:34;background:#1D2415;
  border-top:0;border-bottom:1px solid rgba(230,225,209,.14)}
#v-idea .chbar .cbchip{color:#E6E1D1;border-color:rgba(230,225,209,.28);flex:1;justify-content:center}
#v-idea .chbar .cbchip.active{background:#D8B24A;color:#1D2415;border-color:#D8B24A}

/* the founders' note is the one dark landmark in the sand scroll */
#v-idea .fnote{background:#1D2415;color:#E6E1D1;border-left:0;border-radius:6px;
  padding:clamp(30px,3.6vw,52px) clamp(24px,3.2vw,46px);max-width:none;margin-top:38px}
#v-idea .fnote .over{color:#D8B24A}
#v-idea .fnote h3{color:#E6E1D1;font-size:clamp(26px,3.2vw,38px);font-weight:300;
  line-height:1.15;margin-bottom:.5em;max-width:20ch}
#v-idea .fnote p{color:rgba(230,225,209,.86);max-width:56ch}
#v-idea .fnote .fnote-close{color:#E6E1D1;font-style:italic;
  border-top:1px solid rgba(230,225,209,.18);padding-top:20px;margin-top:24px}
#v-idea .fnote .fnote-sign{color:rgba(230,225,209,.6);margin-top:18px}

/* the three pillars keep their dark cards on the paper ground */
#v-idea .pack{color:#E6E1D1}
#v-idea .pack.stone{background:#3F4E3C}
#v-idea .pack.midnight{background:#1D2415}
#v-idea .pack.terra{background:#5A6B57;color:#F2EFE2}
#v-idea .pack .caps{color:#D8B24A;opacity:1;font-family:var(--sans);font-size:10px;
  letter-spacing:var(--ls-wide)}
#v-idea .pack .nm{color:#F2EFE2}
#v-idea .pack .pr{color:rgba(242,239,226,.82)}
#v-idea .pack li{color:rgba(242,239,226,.9)}

/* the beat between sections, and the film */
#v-idea .beat .stage img{filter:none}
#v-idea .film{border:1px solid color-mix(in srgb,var(--ink) 14%, transparent)}
#v-idea .grid2{gap:clamp(30px,4vw,56px)}
@media(max-width:820px){#v-idea .grid2{grid-template-columns:1fr}}


/* ==========================================================================
   FACILITIES — the shared ground, as a list you can read.
   The live page crams ten facilities into a translucent two-column panel
   over a render; at a glance nothing is more important than anything else.
   Here they are a numbered editorial list: one rule per entry, the name in
   the serif, one line under it, and the qualifiers as quiet tags.
   ========================================================================== */
body.on-bone #v-fac{
  --cream:#E8E6DA;--paper:#2E4034;--ink:#2E4034;--terra:#3E5443;--ghost:#5A6B57;
  --sun:#6F5410;--sun-soft:color-mix(in srgb,#6F5410 22%, transparent);--sun-ink:#E8E6DA;
  --stone:#5A6B57;--well:#D6D4C6;--midnight:#2E4034;--hover:#1D2415;--hover-on:#E8E6DA;
  /* the state tokens are NOT optional here. This block predates the base-rules
     pass and stopped at --hover, so --dim still resolved to the ROOT value —
     sand at 74% — and painted three nodes at 1.03:1 on the bone ground the
     moment the page flipped. A blank rectangle, no error. CLAUDE.md's
     inversion trap, found by the sweep it tells you to run. */
  --dim:color-mix(in srgb,var(--paper) 88%, transparent);
  --dim-soft:color-mix(in srgb,var(--paper) 76%, transparent);
  background:#E8E6DA;color:#2E4034}

/* the hero and the foot are the shared shell */
#v-fac .dhead.dhero{min-height:0;height:clamp(460px,66vh,720px);background:#11150C;padding:0;
  position:relative;display:flex;flex-direction:column;justify-content:flex-end;overflow:hidden}
#v-fac .dhero-veil{background:linear-gradient(to bottom,
  transparent 0%,transparent 34%,rgba(17,21,12,.58) 68%,
  rgba(29,36,21,.92) 90%,#1D2415 100%)}
#v-fac .dhero-k{color:#D8B24A}
#v-fac .dhead.dhero .dhead-line{color:#E6E1D1}
#v-fac .dhero-mark{position:static;inset:auto;width:auto;height:30px;object-fit:contain;flex:none}
#v-fac .chbar{position:sticky;top:0;bottom:auto;z-index:34;background:#1D2415;
  border-top:0;border-bottom:1px solid rgba(230,225,209,.14)}
#v-fac .chbar .cbchip{color:#E6E1D1;border-color:rgba(230,225,209,.28);flex:1;justify-content:center}
#v-fac .chbar .cbchip.active{background:#D8B24A;color:#1D2415;border-color:#D8B24A}

/* the list itself */
.faclist{list-style:none;margin:0;padding:0;
  column-count:2;column-gap:clamp(32px,5vw,80px)}
.faclist li{break-inside:avoid;display:flex;gap:clamp(14px,1.6vw,22px);
  padding:22px 0 24px;border-top:1px solid color-mix(in srgb,var(--ink) 14%, transparent)}
.faclist li:first-child{border-top:0;padding-top:6px}
.fac-n{font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  color:var(--sun);padding-top:.7em;min-width:2.4em;flex:none}
.fac-b h3{font-family:var(--serif);font-weight:300;font-size:clamp(23px,2.4vw,31px);
  line-height:1.1;margin:0 0 8px;color:var(--ink);
  display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.fac-b p{font-family:var(--sans);font-size:15px;line-height:1.6;margin:0;
  max-width:34ch;color:color-mix(in srgb,var(--ink) 86%, transparent);text-wrap:pretty}
.fac-tag{font-family:var(--sans);font-style:normal;font-size:9px;
  letter-spacing:var(--ls-wide);text-transform:uppercase;color:var(--sun);
  border:1px solid color-mix(in srgb,var(--sun) 42%, transparent);
  border-radius:3px;padding:5px 8px 6px;white-space:nowrap}
.fac-tag.sacred{color:var(--terra);border-color:color-mix(in srgb,var(--terra) 42%, transparent)}
@media(max-width:820px){
  .faclist{column-count:1}
  .faclist li:first-child{padding-top:14px}
}

/* the beat and the closing block match the Idea chapter */
#v-fac .grid2{gap:clamp(30px,4vw,56px)}
@media(max-width:820px){#v-fac .grid2{grid-template-columns:1fr}}


/* ==========================================================================
   v41 — one veil, sitewide. The render darkens at the top the way it darkens
   at the bottom: the mark and the burger get a ground to sit on, and no hero
   opens on a bright sky. Same curve on every page.
   ========================================================================== */
#v-details .dhero-veil,#v-idea .dhero-veil,#v-fac .dhero-veil,.dhero-veil{
  background:linear-gradient(to bottom,
    rgba(17,21,12,.62) 0%,
    rgba(17,21,12,.24) 16%,
    rgba(17,21,12,.04) 34%,
    rgba(17,21,12,.58) 68%,
    rgba(29,36,21,.92) 90%,
    #1D2415 100%)}
.cover-veil{background:
  linear-gradient(to bottom,
    rgba(10,9,6,.62) 0%,
    rgba(10,9,6,.22) 15%,
    rgba(10,9,6,.02) 34%,
    rgba(10,9,6,.06) 62%,
    rgba(10,9,6,.62) 100%),
  radial-gradient(120% 80% at 50% 58%,rgba(10,9,6,.26) 0%,rgba(10,9,6,.04) 46%,rgba(10,9,6,.34) 100%)}


/* ==========================================================================
   v41.1 — the "white fade" was never the veil: .dhero::before is a 132px
   CREAM band at z-index 1, painting over it. One dark curve for that band,
   everywhere, matching the bottom of the hero — and the v35 kill rule on
   #v-details is reinstated so all three heroes share it.
   ========================================================================== */
.dhero::before,.dhead.dhero::before,.dhero.slim::before,
#v-details .dhero::before,#v-details .dhead.dhero::before,
#v-idea .dhead.dhero::before,#v-fac .dhead.dhero::before{
  content:"";display:block;position:absolute;inset:0 0 auto 0;height:150px;
  z-index:1;pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(17,21,12,.62) 0%,rgba(17,21,12,.3) 46%,transparent 100%)}
/* the veil sits above it now, so the two curves add rather than fight */
#v-details .dhero-veil,#v-idea .dhero-veil,#v-fac .dhero-veil,.dhero-veil{z-index:2}
#v-details .dhero-top,#v-idea .dhero-top,#v-fac .dhero-top{z-index:5}
#v-details .dhero-in,#v-idea .dhero-in,#v-fac .dhero-in{position:relative;z-index:4}


/* ==========================================================================
   v42 — the masterplan joins the shared shell: mark and two-rule burger
   floating on the map, and the same forest drop-down as every other page.
   Its own .nav sheet is retired.
   ========================================================================== */
.mapnav{position:fixed;top:0;left:0;right:0;z-index:600;display:flex;
  align-items:center;justify-content:space-between;gap:20px;
  padding:20px clamp(16px,2.4vw,30px);pointer-events:none}
.mapnav>*{pointer-events:auto}
.mapnav .dhero-mark{position:static;inset:auto;width:auto;height:32px;
  object-fit:contain;opacity:.95;flex:none}
.mapnav::before{content:"";position:absolute;inset:0 0 auto 0;height:130px;
  z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,rgba(17,21,12,.62) 0%,rgba(17,21,12,.3) 46%,transparent 100%)}
body.zooming .mapnav,body.in-story .mapnav{opacity:0;pointer-events:none;transition:opacity .4s}
@media(max-width:860px){.mapnav{padding:14px 14px}.mapnav .dhero-mark{height:26px}}

/* ---- a filtered-out pin never shows its label -----------------------------
   .dot.off dims the whole pin to 16% and the tag inherits it, so sand type
   over the aerial measures 1.42:1. Two separate rules re-show a picked tag —
   one in @media(max-width:860px), one in @media(hover:hover) — so the guard
   sits here, last in the sheet and outside both, where it outranks either by
   source order at equal specificity. This is the LANDING state of #/select:
   every dot starts .off while one is already .picked, so the first thing on
   the masterplan was an unreadable ghost label. It clears on the first click,
   which is why it survives casual testing. */
html[data-alt="1"] .dot.off .tag{display:none}

/* ---- cover: the design's full-bleed picture -------------------------------
   Lifted from parts/cover.html, which carried it in a per-part <style>. Scoped
   under #v-cover so it cannot reach the other views, and the engine's own
   hooks are kept: the living WebGL layer attaches to `#v-cover .hero` and
   `#cover-img` by selector, so those two names stay even though the design
   calls them .cover and .cover-img — both sets of classes ride the same
   elements. */
#v-cover .hero{background:var(--well)}
#v-cover .cover-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
#v-cover .cover-veil{position:absolute;inset:0;background:
  radial-gradient(120% 80% at 50% 58%,rgba(10,9,6,.34) 0%,rgba(10,9,6,.06) 46%,rgba(10,9,6,.44) 100%),
  linear-gradient(to bottom,rgba(10,9,6,.34) 0%,transparent 22%,transparent 66%,rgba(10,9,6,.5) 100%)}
#v-cover .cnav{position:absolute;top:0;left:0;right:0;z-index:5;display:flex;align-items:center;
  justify-content:space-between;gap:20px;padding:22px clamp(18px,2.4vw,34px)}
#v-cover .cnav-mark{height:38px;width:auto;opacity:.95}
#v-cover .cover-in{position:absolute;inset:0;z-index:4;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:clamp(34px,5vh,62px);
  padding:0 clamp(18px,4vw,60px);text-align:center}
/* the wordmark is artwork, not type — the drawn lockup, at its own proportions */
#v-cover .wordmark{display:block;width:min(56vw,760px);height:auto;margin:0;padding:0;
  filter:drop-shadow(0 2px 40px rgba(10,9,6,.45))}
#v-cover .cover-cta{display:flex;gap:clamp(10px,1.4vw,18px);flex-wrap:wrap;justify-content:center;margin:0}
#v-cover .cover-cta a{display:inline-flex;align-items:center;justify-content:center;
  min-width:clamp(210px,20vw,280px);
  font-family:var(--sans);font-weight:300;font-size:11px;letter-spacing:var(--ls-wide);
  text-transform:uppercase;color:#E6E1D1;
  border:1px solid rgba(230,225,209,.5);border-radius:3px;
  padding:16px 26px 17px;background:rgba(17,21,12,.16);
  backdrop-filter:blur(2px);transition:.25s}
@media(hover:hover){
  #v-cover .cover-cta a:hover{background:#E6E1D1;color:#1D2415;border-color:#E6E1D1}
}
#v-cover .cover-cta a:active{opacity:.72}
@media(max-width:700px){
  #v-cover .cnav{padding:16px}
  #v-cover .cnav-mark{height:30px}
  #v-cover .wordmark{width:min(84vw,420px)}
  #v-cover .cover-cta{flex-direction:column;width:100%;max-width:320px}
  #v-cover .cover-cta a{width:100%}
}

/* ---- the cover carries no top bar ----------------------------------------
   #v-cover renders its own .cnav (mark + burger) floating on the picture, per
   the design. The shell's persistent #nav would otherwise sit above it and
   paint a second mark and a second burger. */
body.on-cover #nav{display:none}

/* The design's FAB is the "ask Grace" lockup and the three dots, nothing else.
   #c-fab .pt is the old pulsing bead; it is purely decorative — the attention
   pulse the engine actually fires is #c-fab.pulse2 (the fabhalo animation on
   the button), so hiding the bead costs no behaviour. */
#c-fab .pt{display:none}

/* ---- menu ordinals: token, not opacity -----------------------------------
   .vd-list em came in as opacity:.5 over the forest ground, which measures
   2.46:1 — the exact anti-pattern CLAUDE.md rule (b) names. --dim-soft is the
   sanctioned faintest tier and is ground-aware, so it holds the 4.5:1 floor
   here and would still hold if this menu ever opened over bone. Hover hands
   the colour back so the ordinal brightens with its label. */
#vd-menu .vd-list em{opacity:1;color:var(--dim-soft)}
@media(hover:hover){ #vd-menu .vd-list button:hover em{color:inherit} }

/* a view that paints its own mark-and-burger suppresses the shell's top bar */
body.own-chrome #nav{display:none}

/* ---- the Idea pillar cards: muting that fits the ground it sits on --------
   .pack .caps and .pack .pr arrive muted with opacity (.7 / .85). Over the
   terra card that lands at 2.83:1 and 3.32:1, because that card's ground
   (#5A6B57) only gives 4.96:1 at FULL type strength — there is no headroom to
   mute into. Darkening the ground does not rescue it either: even most of the
   way to moss, 70% muting still measures 4.39:1.

   So the hierarchy stops being carried by opacity and is carried by size,
   weight and case instead — which is what rule (b) in CLAUDE.md asks for. Each
   card gets an explicit value measured against its own ground rather than the
   page's, since --dim is computed against --paper and does not know about a
   card that paints its own background. */
#v-idea .pack .caps,#v-idea .pack .pr,#v-idea .pack ul li{opacity:1}
#v-idea .pack.terra .caps,#v-idea .pack.terra .pr,#v-idea .pack.terra ul li{color:#EAE8DB}   /* 4.64:1 on #5A6B57 */
#v-idea .pack.stone .caps,#v-idea .pack.stone .pr,#v-idea .pack.stone ul li{color:#CED0C2}   /* 5.6:1  on #3F4E3C */
#v-idea .pack.midnight .caps,#v-idea .pack.midnight .pr,#v-idea .pack.midnight ul li{color:#CED0C2}

/* ---- dark panels on the bone ground: restore the dark-ground palette -------
   The reading chapters run on bone, and body.on-bone flips the tokens so
   --paper (type) becomes deep forest. A panel that paints ITSELF dark then
   draws its text with the same flipped token: dark on dark. Measured on the
   numbers chapter, .rt-proof had 18 of 19 text nodes under 3:1 and .mnband
   14 of 15 — whole panels legible only where an <em> or a brass figure broke
   the pattern. This is the inversion trap the design's own notes warn about
   ("anything painted over a photograph must use dark-ground literals"); a dark
   panel is the same problem as a photograph.

   The background is pinned to a literal FIRST. These panels derive their own
   background from the very tokens being restored, so redefining the tokens
   without pinning turns the panel sand and moves the bug rather than fixing
   it. Everything below the pin is the base (forest) scope again. */
body.on-bone .rt-proof,
body.on-bone .mnband{background:#2E4034}
body.on-bone .fnote{background:#1D2415}
body.on-bone .rt-proof,
body.on-bone .mnband,
body.on-bone .fnote{
  --cream:#1D2415; --paper:#E6E1D1; --ink:#E6E1D1;
  --terra:#949E86; --stone:#314736; --well:#11150C; --midnight:#151A0F;
  --hover:#FFFFFF; --hover-on:#1D2415;
  --dim:color-mix(in srgb,var(--paper) 74%, transparent);
  --dim-soft:color-mix(in srgb,var(--paper) 58%, transparent);
  /* brass has a ground-specific value too: #D8B24A reads ~8.9:1 on forest,
     while the bone scope darkens it to #6F5410. Restoring the palette without
     restoring --sun left the figures in bone-brass on a dark panel — 2.24:1
     for the "5%" and 2.49:1 for "77.5%", the two numbers the panels exist to
     show. */
  --sun:#D8B24A; --sun-soft:color-mix(in srgb,#D8B24A 22%, transparent);
  color:var(--paper);
}
/* the comparison pair inside the founders' note was muted with opacity for a
   light panel; on the dark panel it needs the token tier instead */
body.on-bone .fnote .fcontrast .fc-a b,
body.on-bone .fnote .fcontrast .fc-a span,
body.on-bone .fnote .fcontrast .fc-b span,
body.on-bone .fnote .fcontrast .fc-vs{opacity:1;color:var(--dim)}

/* ---- the last of the opacity-muted text ----------------------------------
   Each of these sets itself back with opacity (.5–.85) or a low-alpha
   color-mix and lands between 3.07:1 and 4.16:1. Same rule (b) as everywhere
   else: --dim / --dim-soft are ground-aware and hold the 4.5:1 floor, and they
   now resolve correctly inside the dark panels too. */
#v-details .qcompare .qc-k,
#v-details .rt-ladder-row span.k,
#v-details .rt-hero-close,
#v-details .splitkey,                 /* the opacity is on the row, not the span */
#v-details .methrow .v small,
#v-details .mnband .mnover,
#v-details .band-returns .schips-note,
#v-mine .steps .step .n,
#v-mine .steps .step .t{opacity:1;color:var(--dim)}

/* the shell bar's burger: same mark as the hero one, but it sits on the bar
   rather than on a photograph, so its rules follow the bar's colour */
#nav .dhero-burger{padding:0;width:34px;height:34px;align-items:flex-end}
#nav .dhero-burger i{width:20px;background:currentColor}

/* ==========================================================================
   Putting the cards away.
   The rail lands open (the design ships body.on-map.rail-open) and the chips
   that used to toggle it are gone with #sel-bottom, so until now there was no
   way to see the whole masterplan. A close on the rail head, and a tab that
   brings it back.
   ========================================================================== */
#vr-close{flex:none;width:30px;height:30px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:14px;line-height:1;color:var(--dim);
  background:color-mix(in srgb,var(--well) 72%, transparent);
  border:1px solid color-mix(in srgb,var(--paper) 22%, transparent);cursor:pointer;transition:.2s}
#vr-open{position:fixed;z-index:36;display:none;align-items:center;gap:9px;
  left:14px;top:50%;transform:translateY(-50%);
  padding:13px 15px 14px;border-radius:3px;cursor:pointer;
  background:color-mix(in srgb,var(--well) 86%, transparent);backdrop-filter:blur(10px);
  border:1px solid color-mix(in srgb,var(--paper) 24%, transparent);
  color:var(--paper);font-family:var(--sans);font-size:10px;letter-spacing:var(--ls-wide);
  text-transform:uppercase}
#vr-open i{font-style:normal;font-size:15px;line-height:1;color:var(--terra)}
/* only on the map, and only once the cards are actually away */
html[data-alt="1"] body.on-map:not(.rail-open) #vr-open{display:flex}
@media(max-width:860px){
  /* on a phone the rail is a bottom sheet, so its handle belongs at the foot */
  #vr-open{left:50%;top:auto;bottom:calc(env(safe-area-inset-bottom,0px) + 16px);
    transform:translateX(-50%)}
}
@media(hover:hover){
  #vr-close:hover{color:var(--hover);border-color:var(--hover)}
  #vr-open:hover{color:var(--hover);border-color:var(--hover)}
}

/* Second press walks in. Once a home is picked its plot footprint is the hit
   area — the ring you can see IS the thing you can press, which is why it is
   the picked state that turns pointer-events back on and nothing else does.
   .dot.reserved/.sold are pointer-events:none so their pins cannot be pressed
   cold; once the rail has picked one, walking into it is allowed here too,
   exactly as its card already allows. */
html[data-alt="1"] .dot.picked{pointer-events:auto}
html[data-alt="1"] .dot.picked .plot{pointer-events:auto;cursor:pointer}

/* the reopen tab's own display:flex is appended after everything else, so the
   editing hide has to be appended after THAT or the tab sits over the map */
html[data-alt="1"] body.editing #vr-open{display:none !important}

/* A chapter bar with ONE chapter was stretching that chapter across the full
   width (.dhead.dhero + .chbar .cbchip{flex:1}), so the founders' villas
   showed what looked like a broken tab bar: a single 1,100px "01 THE VILLA".
   Stretch only when there is a row to share. */
html[data-alt="1"] .chbar.one .cbchip{flex:0 0 auto;justify-content:flex-start}
html[data-alt="1"] .chbar.one{justify-content:flex-start}

/* The rail head needs 392px to lay out at its natural size — count, segment
   and close — so on a 390 phone it is already 2px over and on a 360 it pushed
   the close clean off the screen. The count is the only part that can give:
   it shrinks and ellipsises, the controls keep their full hit area. */
html[data-alt="1"] .vr-head{flex-wrap:nowrap;overflow:hidden}
html[data-alt="1"] .vr-count{flex:0 1 auto;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
html[data-alt="1"] .vr-seg,html[data-alt="1"] #vr-close{flex:0 0 auto}
@media(max-width:400px){
  html[data-alt="1"] .vr-head{gap:8px;padding-left:12px;padding-right:12px}
  html[data-alt="1"] .vr-seg button{padding-left:12px;padding-right:12px}
}

/* ==========================================================================
   GN·01 — one capitalisation per kind of thing.
   .over is the eyebrow above a heading and is uppercased by scope
   (.sec .over, .dhead .over, .scrim .over). The facilities sheet is none of
   those, so its "Beyond your walls" was the single eyebrow on the site
   rendering in sentence case. Same element, same job, same treatment.
   The p&l's three total rows are handled in the data, not here: they were
   typed in LITERAL CAPITALS while their eleven siblings were sentence case,
   which is a shout the .pnlbold weight was already making for them.
   ========================================================================== */
#fac-sheet .over{letter-spacing:var(--ls-wide);font-size:12.5px;text-transform:uppercase;
  font-weight:500;color:var(--dim);margin-bottom:16px}

/* the mark is a link now — say so, and give the keyboard somewhere to land */
.brand-mono,.dhero-mark,.cnav-mark{cursor:pointer}
.brand-mono:focus-visible,.dhero-mark:focus-visible,.cnav-mark:focus-visible{
  outline:2px solid var(--sun);outline-offset:4px;border-radius:2px}
@media(hover:hover){
  .brand-mono:hover,.dhero-mark:hover,.cnav-mark:hover{opacity:.78;transition:opacity .2s}
}
