@font-face{font-family:'EB Garamond';font-style:normal;font-weight:400;font-display:swap;src:url(../fonts/ebgaramond-400-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'EB Garamond';font-style:normal;font-weight:500;font-display:swap;src:url(../fonts/ebgaramond-500-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:300;font-display:swap;src:url(../fonts/montserrat-300-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Montserrat';font-style:normal;font-weight:600;font-display:swap;src:url(../fonts/montserrat-600-latin.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

/* ============================================================
   SANUREI
   Brand (colour, type, logo) is taken from the brochure PDF.
   Motion + scaling model is taken from _work/reference-spec.md.

   Scaling: the ROOT font size is a vw value and every token is in
   rem, so the page scales as one object. The breakpoint ladder is
   tuned so 1rem lands at 20px at each breakpoint's own width — that
   ladder is what stops type going illegible, so there is no clamp().
   ============================================================ */

:root{
  --fsize: 1.0416667vw;              /* 1rem = 15px @1440 · 20px @1920 */

  /* colour — sampled from the brochure, not guessed */
  --cream:        #F3EEE3;
  --cream-2:      #EAE3D5;
  --cream-warm:   #EBD8C7;           /* the warmer cream used for headings on green */
  --ink:          #4F3C27;           /* brochure sets headings AND body in this one brown */
  --ink-soft:     #776552;   /* darkened to clear WCAG AA (4.80:1) on cream */
  --green:        #0D4D2F;
  --green-mid:    #10653E;
  --green-deep:   #07361F;
  --green-night:  #04220F;
  --on-green:     #F3EEE3;
  --on-green-soft:#C3D3C6;
  --hair-cream:   rgba(79,60,39,.20);
  --hair-green:   rgba(243,238,227,.22);

  /* type families */
  --serif: 'EB Garamond', 'Iowan Old Style', Georgia, 'Times New Roman', serif;
  --sans:  'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --jp:    'Hiragino Sans', 'Hiragino Kaku Gothic ProN', 'Yu Gothic', 'Noto Sans JP', Meiryo, var(--sans);

  /* type scale — desktop. px comments are @1440 */
  --t-hero:    9.5rem;   /* 142.5 */
  --t-display: 6rem;     /* 90    */
  --t-quote:   3.9rem;   /* 58.5  */
  --t-h3:      2.3rem;   /* 34.5  */
  --t-lead:    1.85rem;  /* 27.75 */
  --t-body:    1.117rem; /* 16.75 */
  --t-small:   .85rem;   /* 12.75 */
  --t-label:   .75rem;   /* 11.25 */

  /* display type is set solid or tighter; body stays loose */
  --lh-hero: .92; --lh-display: .98; --lh-quote: 1.08; --lh-h3: 1.22;
  --lh-lead: 1.36; --lh-body: 1.8;

  /* space */
  --pad:  1.65rem;       /* 24.75 */
  --gap:  1.5rem;        /* 22.5  */
  --sec:  12rem;         /* 180   */
  --sec-s: 6rem;         /* 90    */

  /* footprint of the floating sound control — anything that must stay clear of
     it derives from these, so moving or resizing the control moves the rest */
  --snd-size:  2.9rem;
  --snd-inset: calc(var(--pad) + env(safe-area-inset-bottom, 0px));
  --hero-foot-pb: 2.8rem;

  /* easing — GSAP curves the reference uses, as cubic-beziers */
  --e-out:  cubic-bezier(.16,1,.30,1);      /* power3.out  — every entrance */
  --e-out2: cubic-bezier(.22,.61,.36,1);    /* power2.out  — settles */
  --e-io:   cubic-bezier(.65,0,.35,1);      /* power2.inOut— hover swaps */
  --e-io3:  cubic-bezier(.87,0,.13,1);      /* power3.inOut— big wipes */
  --e-in:   cubic-bezier(.70,0,.84,0);      /* power3.in   — exits */
  --e-back: cubic-bezier(.34,1.56,.64,1);   /* back.out    — cursor */

  /* duration bands: UI .25–.33 · content .5–.65 · big objects 1–1.25 */
  --d-ui: .33s; --d-enter: .65s; --d-big: 1.25s;
}

/* the ladder: 1rem === 20px at each breakpoint's own width */
@media (max-width:1024px){ :root{ --fsize:1.953125vw   } }
@media (max-width: 768px){ :root{ --fsize:2.6041667vw  } }
@media (max-width: 576px){ :root{ --fsize:3.4722222vw  } }
@media (max-width: 468px){ :root{ --fsize:4.2735043vw  } }
@media (max-width: 375px){ :root{ --fsize:5.3333333vw  } }

/* tablet — tokens re-declared on top of the new rem */
@media (max-width:1024px){
  :root{
    --t-hero:5.4rem; --t-display:3.6rem; --t-quote:2.5rem; --t-h3:1.6rem;
    --t-lead:1.3rem; --t-body:.87rem; --t-small:.7rem; --t-label:.62rem;
    --pad:1.4rem; --gap:1.1rem; --sec:6.5rem; --sec-s:3.6rem;
  }
}
/* mobile — the hero drops hard while body copy gets BIGGER, as the reference does */
@media (max-width:768px){
  :root{
    --t-hero:2.8rem; --t-display:2.15rem; --t-quote:1.55rem; --t-h3:1.25rem;
    --t-lead:1.05rem; --t-body:.85rem; --t-small:.7rem; --t-label:.6rem;
    --lh-hero:1; --lh-display:1.06; --lh-quote:1.2;
    --pad:.75rem; --gap:.75rem; --sec:5rem; --sec-s:2.5rem;
  }
}

*,*::before,*::after{ box-sizing:border-box }
html{ font-size:var(--fsize); -webkit-text-size-adjust:100% }
body{
  margin:0; background:var(--cream); color:var(--ink);
  font-family:var(--sans); font-weight:300;
  font-size:var(--t-body); line-height:var(--lh-body);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
}
img,svg,video{ display:block; max-width:100% }
h1,h2,h3,h4,p,figure,blockquote,dl,dd{ margin:0 }
ul,ol{ margin:0; padding:0; list-style:none }
a{ color:inherit; text-decoration:none }
::selection{ background:var(--green-mid); color:var(--cream) }

/* ---------- layout — no max-width anywhere, per the reference ---------- */
.wrap{ padding-inline:var(--pad) }
.section{ position:relative; padding-block:var(--sec) }
.section--s{ padding-block:var(--sec-s) }
.grid{ display:grid; grid-template-columns:repeat(12,1fr); gap:var(--gap) }
@media (max-width:950px){ .grid{ grid-template-columns:repeat(4,1fr) } }

/* a section seam that never shows a hairline gap between colour blocks */
.t-cream,.t-green,.t-green-deep,.t-night{ box-shadow:0 -1px 0 currentColor }
.t-cream{ background:var(--cream);      color:var(--ink);      box-shadow:0 -1px 0 var(--cream) }
.t-green{ background:var(--green);      color:var(--on-green); box-shadow:0 -1px 0 var(--green) }
.t-green-deep{ background:var(--green-deep); color:var(--on-green); box-shadow:0 -1px 0 var(--green-deep) }
.t-night{ background:var(--green-night); color:var(--on-green); box-shadow:0 -1px 0 var(--green-night) }

.stack-s > * + *{ margin-top:1.6rem }
.stack   > * + *{ margin-top:3rem }
.stack-l > * + *{ margin-top:6rem }

.cols2{ display:grid; gap:var(--gap); grid-template-columns:1fr }
@media (min-width:760px){ .cols2{ grid-template-columns:1fr 1fr; gap:calc(var(--gap) * 2) } }

.split{ display:grid; gap:calc(var(--gap) * 2); grid-template-columns:1fr }
@media (min-width:951px){
  .split{ grid-template-columns:repeat(12,1fr); gap:var(--gap); align-items:start }
  .split__head{ grid-column:1 / 6 }
  .split__body{ grid-column:7 / 13 }
  .split--wide .split__head{ grid-column:1 / 7 }
  .split--wide .split__body{ grid-column:8 / 13 }
}

/* ---------- type ---------- */
.eyebrow{
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.2em; text-transform:uppercase; line-height:1; color:var(--ink-soft);
}
.t-green .eyebrow,.t-green-deep .eyebrow,.t-night .eyebrow{ color:var(--on-green-soft) }
.eyebrow span{ margin-right:.9em; opacity:.7 }

/* Two lines at every width, never three. The break itself is a <br> in the
   source; this cap stops the longer line wrapping again on a narrow screen.
   "JAPANESE DESIGN" measures 8.31em in this face at this letter-spacing, so it
   needs the viewport's usable width / 8.31 — about 11.1vw. 10.5vw leaves a
   margin for font fallback and only binds below ~430px, where the ladder's
   2.8rem was over three times too wide. */
.hero__h1{ font-family:var(--serif); font-weight:400;
  font-size:min(var(--t-hero), 10.5vw);
  line-height:var(--lh-hero); letter-spacing:-.007em; text-transform:uppercase }
.hln{ display:block }
.h2{ font-family:var(--serif); font-weight:400; font-size:var(--t-display);
  line-height:var(--lh-display); letter-spacing:-.012em; text-wrap:balance }
.h3{ font-family:var(--serif); font-weight:500; font-size:var(--t-h3);
  line-height:var(--lh-h3); letter-spacing:-.005em }
.lead{ font-family:var(--serif); font-weight:400; font-size:var(--t-lead);
  line-height:var(--lh-lead) }
.quote{ font-family:var(--serif); font-weight:400; font-size:var(--t-quote);
  line-height:var(--lh-quote); letter-spacing:-.012em; text-wrap:balance }
.body{ max-width:46ch }
.small{ font-size:var(--t-small); line-height:1.75; color:var(--ink-soft) }
.t-green .small,.t-green-deep .small,.t-night .small{ color:var(--on-green-soft) }
.label{ font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.13em; text-transform:uppercase; line-height:1.4 }
.jp{ font-family:var(--jp); font-weight:400; letter-spacing:.14em }
.rule{ height:1px; background:var(--hair-cream); border:0 }
.t-green .rule,.t-green-deep .rule,.t-night .rule{ background:var(--hair-green) }

/* ---------- logo — alpha mask of the brochure logo, recoloured by currentColor ---------- */
.logo{ display:block; background-color:currentColor;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center;  mask-position:center;
  -webkit-mask-size:contain;     mask-size:contain }
.logo--lockup{ -webkit-mask-image:url(../img/logo-lockup.webp); mask-image:url(../img/logo-lockup.webp); aspect-ratio:682/720 }
.logo--mark{   -webkit-mask-image:url(../img/logo-mark.webp);   mask-image:url(../img/logo-mark.webp);   aspect-ratio:440/385 }

/* ---------- media + the one parallax primitive ----------
   Spec: image is 115% of its frame and travels DOWN 15% of the
   frame height across its pass. JS writes the px translate. */
.media{ position:relative; overflow:hidden; background:var(--cream-2) }
.t-green .media,.t-green-deep .media,.t-night .media{ background:var(--green-deep) }
.media__inner{ position:absolute; inset:0; height:108%; will-change:transform }
.media img{ width:100%; height:100%; object-fit:cover }
/* flat artwork (the map): shown whole, so the frame matches the source aspect,
   the inner fills it exactly and nothing travels inside it */
.media--flat{ background:transparent }
.media--flat .media__inner{ height:100% }

.media__cap{ margin-top:1rem; font-size:var(--t-label); letter-spacing:.11em;
  text-transform:uppercase; font-weight:600; color:var(--ink-soft) }
.t-green .media__cap,.t-night .media__cap{ color:var(--on-green-soft) }

.r-16x9{ aspect-ratio:16/9 } .r-8x5{ aspect-ratio:8/5 } .r-4x3{ aspect-ratio:4/3 }
.r-3x2{ aspect-ratio:3/2 }
.r-1x1{ aspect-ratio:1/1 }   .r-3x4{ aspect-ratio:3/4 } .r-2x3{ aspect-ratio:2/3 }

/* full-bleed image with an overlaid line of copy */
.scene{ position:relative; overflow:hidden; min-height:88svh; display:grid }
.scene__bg{ position:absolute; inset:0; height:108%; will-change:transform }
.scene__bg img{ width:100%; height:100%; object-fit:cover }
.scene::after{ content:''; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to top,rgba(7,54,31,.80) 0%,rgba(7,54,31,.34) 40%,rgba(7,54,31,.04) 72%,transparent 100%) }
.scene__body{ position:relative; z-index:2; align-self:end;
  padding:var(--pad); padding-bottom:var(--sec-s); color:var(--cream) }

/* ---------- header ---------- */
.hdr{
  position:fixed; inset:0 0 auto; z-index:60;
  display:flex; align-items:center; justify-content:space-between; gap:var(--gap);
  padding:1.4rem var(--pad); color:var(--cream);
  transition:transform var(--d-big) var(--e-out), color .5s var(--e-io);
}
.hdr[data-hidden="true"]{ transform:translate3d(0,-115%,0) }
.hdr[data-theme="cream"]{ color:var(--ink) }
/* over a photograph, neither ink nor flat cream is reliable — lift the mark off
   the image with a soft halo so it reads against wood, stone or a bright window */
.hdr[data-theme="media"]{ color:var(--cream) }
.hdr[data-theme="media"] .hdr__logo{
  filter:drop-shadow(0 1px 2px rgba(4,34,15,.42)) drop-shadow(0 2px 14px rgba(4,34,15,.34));
}
.hdr[data-theme="media"] .hdr__cta{
  border-color:rgba(243,238,227,.7);
  text-shadow:0 1px 10px rgba(4,34,15,.5);
  backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px);
}
.hdr[data-theme="media"] .hdr__cta:hover span{ color:var(--green); text-shadow:none }
.hdr__logo{ width:4.48rem; transition:opacity .5s var(--e-io), filter .5s var(--e-io) }
.hdr[data-atop="true"] .hdr__logo{ opacity:0; pointer-events:none }
.hdr__cta{
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.16em; text-transform:uppercase;
  padding:.9em 1.7em; border:1px solid currentColor; border-radius:100px;
  position:relative; overflow:hidden; isolation:isolate;
}
.hdr__cta::before{ content:''; position:absolute; inset:0; z-index:-1; background:currentColor;
  transform:scaleY(0); transform-origin:50% 100%; transition:transform .5s var(--e-io) }
.hdr__cta:hover::before{ transform:scaleY(1) }
.hdr__cta span{ transition:color .5s var(--e-io) }
.hdr__cta:hover span{ color:var(--green) }
.hdr[data-theme="cream"] .hdr__cta:hover span{ color:var(--cream) }

.prog{ position:fixed; left:0; top:0; height:2px; width:100%; z-index:70;
  transform:scaleX(0); transform-origin:0 50%; background:var(--cream-warm);
  opacity:.5; pointer-events:none }

/* ---------- hero ---------- */
.hero{ position:relative; height:100svh; min-height:34rem; overflow:hidden;
  background:var(--green-deep); color:var(--cream); display:grid; grid-template-rows:1fr auto }
.hero__bg{ position:absolute; inset:0; height:108%; z-index:0; will-change:transform }
.hero__bg img{ width:100%; height:100%; object-fit:cover }
.hero__veil{ position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(to bottom,rgba(4,34,15,.50) 0%,rgba(4,34,15,.10) 30%,rgba(7,54,31,.26) 62%,rgba(7,54,31,.88) 100%) }
/* darken only where the type sits, so the render itself stays clear */
.hero__mid{ position:relative; z-index:2; align-self:center; padding-inline:var(--pad);
  text-align:center; isolation:isolate }
.hero__mid::before{ content:''; position:absolute; inset:-18% -8%; z-index:-1; pointer-events:none;
  background:radial-gradient(64% 70% at 50% 54%,rgba(4,34,15,.74) 0%,rgba(4,34,15,.44) 50%,rgba(4,34,15,.12) 74%,transparent 86%) }
.hero__logo{ width:8.5rem; margin:0 auto 2.6rem }
@media (max-width:768px){ .hero__logo{ width:6.2rem; margin-bottom:2rem } }
.hero__sub{ margin:2.2rem auto 0; max-width:44ch; font-size:var(--t-body);
  line-height:1.8; color:rgba(243,238,227,.94) }
.hero__foot{ position:relative; z-index:2; padding:0 var(--pad) var(--hero-foot-pb);
  display:flex; align-items:flex-end; justify-content:space-between; gap:var(--gap) }
.hero__tag{ font-family:var(--serif); font-size:var(--t-h3); line-height:1.24 }
.cue{ display:flex; align-items:center; gap:.9em; font-size:var(--t-label);
  letter-spacing:.2em; text-transform:uppercase; font-weight:600; opacity:.9;
  /* Taken out of flow and anchored to the hero's bottom edge so it clears the
     fixed sound control, which shares this corner. The hero is a fixed-height
     grid, so anything that grows .hero__foot overflows it and gets clipped
     instead of moving the cue — absolute positioning sidesteps that entirely
     and leaves the tagline where it was. Offsets derive from the control's own
     tokens, so this tracks --pad and the iOS safe area. */
  position:absolute; z-index:2; right:var(--pad);
  bottom:calc(var(--snd-inset) + var(--snd-size) + 1rem) }
/* The cue fades in with the rest of the hero but must not slide, or its
   entrance offset would dip it into the sound control before it settles. */
.cue[data-rise],
html.m-scrub .cue[data-rise]{ transform:none }
.cue__line{ position:relative; display:block; width:1px; height:3.6rem;
  background:rgba(243,238,227,.35); overflow:hidden }
.cue__line::after{ content:''; position:absolute; inset:0; background:var(--cream-warm);
  transform:translateY(-100%); animation:cue 2.4s var(--e-io) infinite }
@keyframes cue{ 0%{transform:translateY(-100%)} 45%,100%{transform:translateY(100%)} }
@media (max-width:768px){ .hero__foot{ flex-direction:column; align-items:flex-start; gap:1.4rem } .cue{ display:none } }

/* ---------- lists ---------- */
.deflist__row{ display:grid; gap:var(--gap); grid-template-columns:1fr;
  padding-block:2.2rem; border-top:1px solid var(--hair-cream) }
.t-green .deflist__row,.t-green-deep .deflist__row,.t-night .deflist__row{ border-color:var(--hair-green) }
.deflist__row:last-child{ border-bottom:1px solid var(--hair-cream) }
.t-green .deflist__row:last-child{ border-bottom-color:var(--hair-green) }
@media (min-width:760px){ .deflist__row{ grid-template-columns:minmax(9rem,3fr) 7fr; align-items:baseline } }
.deflist__term{ font-family:var(--sans); font-weight:600; font-size:var(--t-small);
  letter-spacing:.09em; text-transform:uppercase; line-height:1.5 }
.deflist__def{ max-width:52ch }

/* min() keeps the floor from exceeding the container on narrow screens, which
   would otherwise force overflow now that the type is larger */
.facts{ display:grid; gap:3rem var(--gap);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,17.5rem),1fr)) }
.fact{ border-top:1px solid var(--hair-cream); padding-top:1.2rem }
.t-green .fact{ border-color:var(--hair-green) }
.fact__label{ font-weight:600; font-size:var(--t-label); letter-spacing:.15em;
  text-transform:uppercase; color:var(--ink-soft) }
.t-green .fact__label{ color:var(--on-green-soft) }
.fact__name{ margin-top:.9em; font-size:calc(var(--t-body) * 1.5); line-height:1.3 }
/* the travel time is the point of this grid, so it is set at twice the small
   size and the figure itself is lifted into the display serif — the same
   treatment the ROI number gets, so the two read as a family */
.fact__time{ margin-top:.5em; font-size:calc(var(--t-small) * 2);
  color:var(--ink-soft); line-height:1.25 }
.t-green .fact__time{ color:var(--on-green-soft) }
.fact__time b{ font-family:var(--serif); font-weight:400; font-size:1.4em;
  letter-spacing:-.01em; color:var(--ink) }
.t-green .fact__time b{ color:var(--on-green) }

.triad{ display:grid; gap:var(--gap); grid-template-columns:1fr }
@media (min-width:820px){ .triad{ grid-template-columns:repeat(3,1fr) } }
.triad__item{ font-family:var(--serif); font-size:var(--t-h3); line-height:1.3 }

/* ---------- the name: equation ---------- */
.equation{ display:flex; flex-wrap:wrap; align-items:baseline; justify-content:center;
  gap:.5em 1.2em; font-family:var(--serif); font-size:var(--t-display); line-height:1.1 }
.equation__op{ opacity:.45; font-size:.55em }
.pron{ margin-top:2.6rem; text-align:center }
.pron__inner{ display:inline-flex; align-items:center; gap:2rem }
.pron__paren{ font-family:var(--serif); font-size:var(--t-quote); line-height:1; opacity:.4 }
.pron__jp{ display:block; font-family:var(--jp); font-size:var(--t-lead); letter-spacing:.24em }
.pron__say{ margin-top:.6em; font-size:var(--t-small) }

/* ---------- collection: specs + floor plans ---------- */
.specs{ display:grid; gap:var(--gap); grid-template-columns:1fr }
@media (min-width:700px){ .specs{ grid-template-columns:1fr 1fr } }
.spec{ display:flex; gap:.9em; align-items:flex-start; line-height:1.6 }
.spec::before{ content:''; flex:0 0 auto; width:1em; height:.875em; margin-top:.5em;
  background-color:currentColor; opacity:.5;
  -webkit-mask:url(../img/logo-mark.webp) center/contain no-repeat;
          mask:url(../img/logo-mark.webp) center/contain no-repeat }
.plan__title{ font-family:var(--sans); font-weight:600;
  font-size:calc(var(--t-small) * 1.3);   /* +30% */
  letter-spacing:.1em; text-transform:uppercase; line-height:1.35 }
/* land and building sizes: a labelled pair under the villa name. The label takes
   the same small caps as .fact__label, and the figure the display serif, so the
   sizes, the travel times and the ROI number all read as one family. */
.plan__dims{ margin-top:1.2rem; display:grid; gap:1.1rem }
@media (min-width:951px){ .plan__dims{ gap:1.4rem } }
.plan__label{ font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.15em; text-transform:uppercase; color:var(--ink-soft) }
.t-green .plan__label{ color:var(--on-green-soft) }
.plan__size{ margin-top:.45em; font-family:var(--serif); font-weight:400;
  font-size:calc(var(--t-small) * 2); line-height:1.2; letter-spacing:-.01em }
.plan__size sup{ font-size:.55em; vertical-align:super }
.plan__set{ margin-top:1.6rem; display:grid; gap:var(--gap); grid-template-columns:1fr 1fr }
.plan__fig figcaption{ margin-top:.9em; font-size:var(--t-label); letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-soft) }
.plan__fig .media{ background:transparent }
.plan__fig .media__inner{ position:static; height:auto }
.plan__fig img{ height:auto; object-fit:contain }

/* ---------- home: teasers to the other four pages ----------
   The whole card is the link. The underline uses the same origin-flip as
   .contact__person so every text link on the site behaves identically. */
.teasers{ display:grid; gap:calc(var(--gap) * 2); grid-template-columns:1fr }
@media (min-width:760px){ .teasers{ grid-template-columns:1fr 1fr } }
.teaser a{ display:block; color:inherit }
.teaser__t{ margin-top:1.6rem }
.teaser__d{ margin-top:.9rem; max-width:38ch; color:var(--ink-soft) }
.teaser__go{ display:inline-block; position:relative; margin-top:1.6rem; padding-bottom:.3em;
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.16em; text-transform:uppercase }
.teaser__go::after{ content:''; position:absolute; left:0; bottom:0; width:100%; height:1px;
  background:currentColor; opacity:.35; transform:scaleX(1); transform-origin:0 50%;
  transition:transform .5s var(--e-io) }
.teaser a:hover .teaser__go::after{ transform:scaleX(0); transform-origin:100% 50% }

/* ---------- gallery ---------- */
.gal{ display:grid; gap:calc(var(--gap) * 1.5); grid-template-columns:1fr; margin-top:1.6rem }
@media (min-width:760px){ .gal{ grid-template-columns:1fr 1fr } }
.gal__room{ margin-top:6rem; color:var(--ink-soft) }
.t-green .gal__room{ color:var(--on-green-soft) }

/* ---------- investment stat ---------- */
.stat{ display:grid; gap:var(--gap); grid-template-columns:1fr; align-items:baseline }
@media (min-width:860px){ .stat{ grid-template-columns:minmax(14rem,4fr) 8fr } }
.stat__label{ font-family:var(--serif); font-size:var(--t-display); line-height:1.05 }
.stat__value{ display:block; font-family:var(--serif); font-weight:400;
  font-size:var(--t-hero); line-height:.86; letter-spacing:-.03em; color:var(--cream-warm) }
.stat__value sup{ font-size:.26em; vertical-align:super; opacity:.75; margin-left:.06em }
.note{ border-top:1px solid var(--hair-green); padding-top:1.4rem }
.note__t{ font-weight:600; font-size:var(--t-small); letter-spacing:.16em; text-transform:uppercase }
.note__b{ margin-top:1em; font-size:var(--t-small); line-height:1.8;
  color:var(--on-green-soft); max-width:76ch }

/* ---------- closing ---------- */
.closing{ position:relative; overflow:hidden }
.closing__glow{ position:absolute; left:50%; top:46%; translate:-50% -50%; z-index:0;
  width:min(94vw,52rem); aspect-ratio:440/385; background-color:rgba(243,238,227,.055);
  -webkit-mask:url(../img/logo-mark.webp) center/contain no-repeat;
          mask:url(../img/logo-mark.webp) center/contain no-repeat; will-change:transform }
.closing__in{ position:relative; z-index:2 }
.marks{ display:grid; gap:4rem; margin-block:7rem; font-family:var(--serif);
  font-size:var(--t-h3); letter-spacing:.09em; text-transform:uppercase; line-height:1 }
.marks li:nth-child(1){ justify-self:start }
.marks li:nth-child(2){ justify-self:end; text-align:right }
.marks li:nth-child(3){ justify-self:start; margin-left:8vw }
.marks li:nth-child(4){ justify-self:end; text-align:right; margin-right:3vw }

/* A slow idle drift. Unlike the scroll reveals this has no hidden start state
   and never touches opacity, so it cannot strand the text the way the old
   reveal did at the foot of the page. transform only: compositor work, no
   layout, no paint, nothing on the main thread per frame.
   Amplitudes are in em so the drift stays proportional to the type across the
   breakpoint ladder — 0.2em lands on ~7px at the desktop --t-h3 of 34.5px. */
.marks li > span{
  display:inline-block;
  animation:markDrift var(--dur) ease-in-out var(--del) infinite;
}
/* negative delays start each line mid-cycle, so the four are already out of
   phase on the very first frame instead of setting off together */
.marks li:nth-child(1) > span{ --dur:11s;   --del:0s;    --ay:.200em; --ax:.116em }
.marks li:nth-child(2) > span{ --dur:9.5s;  --del:-2.2s; --ay:.174em; --ax:.087em }
.marks li:nth-child(3) > span{ --dur:13s;   --del:-5.1s; --ay:.232em; --ax:.116em }
.marks li:nth-child(4) > span{ --dur:10.5s; --del:-7.4s; --ay:.174em; --ax:.145em }

@keyframes markDrift{
  0%  { transform:translate3d(0,0,0) }
  25% { transform:translate3d(calc(var(--ax) *  .6), calc(var(--ay) * -1),   0) }
  50% { transform:translate3d(calc(var(--ax) * -1),  calc(var(--ay) * -.35), 0) }
  75% { transform:translate3d(calc(var(--ax) * -.4), calc(var(--ay) *  .8),  0) }
  100%{ transform:translate3d(0,0,0) }
}
/* JS only ever pauses; with no attribute at all the marks simply keep floating,
   so a JS failure can never leave them hidden */
.marks[data-drift="idle"] li > span{ animation-play-state:paused }

.contact{ display:grid; gap:var(--gap); grid-template-columns:1fr; align-items:end }
@media (min-width:951px){ .contact{ grid-template-columns:repeat(3,1fr) } }
.contact__tag{ font-family:var(--serif); font-size:var(--t-h3); line-height:1.24 }
.contact__ask{ color:var(--on-green-soft) }
.contact__people{ display:grid; gap:1.6em; justify-items:start }
@media (min-width:951px){ .contact__people{ justify-items:end } }
.contact__row{ display:flex; align-items:center; flex-wrap:wrap; gap:.6em 1.1em }
@media (min-width:951px){ .contact__row{ justify-content:flex-end } }

/* Same button language as the header CTA: hairline pill, letterspaced caps,
   fill sweeping up from the base on hover. Monochrome on purpose — WhatsApp
   green against the brand green would fight. */
.wa{
  display:inline-flex; align-items:center; gap:.6em;
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.16em; text-transform:uppercase; white-space:nowrap;
  padding:.8em 1.4em; border:1px solid currentColor; border-radius:100px;
  position:relative; overflow:hidden; isolation:isolate;
}
.wa::before{ content:''; position:absolute; inset:0; z-index:-1; background:currentColor;
  transform:scaleY(0); transform-origin:50% 100%; transition:transform .5s var(--e-io) }
.wa:hover::before{ transform:scaleY(1) }
.wa span,.wa__ico{ transition:color .5s var(--e-io), fill .5s var(--e-io) }
.wa:hover span,.wa:hover .wa__ico{ color:var(--green-night); fill:var(--green-night) }
.wa__ico{ width:1.15em; height:1.15em; flex:0 0 auto }
.contact__person{ position:relative; padding-bottom:.2em; font-size:var(--t-body) }
.contact__person b{ font-weight:600; margin-right:.5em }
.contact__person::after{ content:''; position:absolute; left:0; bottom:0; width:100%; height:1px;
  background:currentColor; opacity:.35; transform:scaleX(0); transform-origin:100% 50%;
  transition:transform .5s var(--e-io) }
.contact__person:hover::after{ transform:scaleX(1); transform-origin:0 50% }

.foot{ border-top:1px solid var(--hair-green); margin-top:6rem; padding-top:1.8rem;
  display:flex; flex-wrap:wrap; gap:1.2em 2.4em; justify-content:space-between;
  font-size:var(--t-label); letter-spacing:.1em; text-transform:uppercase;
  color:var(--on-green-soft) }

/* ============================================================
   MOTION — numbers taken from _work/reference-spec.md S3/S4/S14
   Every reveal is one-shot and driven by JS toggling [data-in].
   ============================================================ */

/* masked line reveal — JS wraps each visual line in .ln > .ln__i. stagger 90ms */
.ln{ display:block; overflow:hidden; padding-bottom:.08em; margin-bottom:-.08em }
.ln__i{ display:block; transform:translate3d(0,110%,0); will-change:transform;
  transition:transform 1s var(--e-out); transition-delay:var(--d,0ms) }
[data-in] .ln__i{ transform:translate3d(0,0,0) }

/* char reveal — alternating from above/below, 25ms stagger. hero only */
.ch{ display:inline-block; overflow:hidden; vertical-align:top }
.ch__i{ display:inline-block; transform:translate3d(0,var(--from,110%),0); will-change:transform;
  transition:transform .9s var(--e-out); transition-delay:var(--d,0ms) }
[data-in] .ch__i{ transform:translate3d(0,0,0) }

/* image reveal — clip wipe 1.2s + frame lift 1.5s, both power3.out */
/* the wipe alone carries the reveal — .media's transform belongs to the frame
   drift in site.js, so nothing here may touch it */
[data-reveal]{ clip-path:inset(100% 0 0 0);
  transition:clip-path 1.2s var(--e-out); transition-delay:var(--d,0ms) }
[data-reveal][data-in]{ clip-path:inset(0 0 0 0) }

/* copy reveal — the reference ramps paragraphs from opacity .2, not from 0 */
[data-rise]{ opacity:.2; transform:translate3d(0,1.6rem,0); will-change:transform,opacity;
  transition:opacity var(--d-enter) var(--e-out), transform var(--d-enter) var(--e-out);
  transition-delay:var(--d,0ms) }
[data-rise][data-in]{ opacity:1; transform:none }

[data-draw]{ transform:scaleX(0); transform-origin:0 50%;
  transition:transform 1s var(--e-io3); transition-delay:var(--d,0ms) }
[data-draw][data-in]{ transform:scaleX(1) }

/* ---------- preloader ---------- */
.pre{ position:fixed; inset:0; z-index:200; display:grid; place-items:center;
  background:var(--green-deep); color:var(--cream-warm);
  transition:opacity .8s var(--e-out), visibility .8s }
.pre__logo{ width:7rem; opacity:0; transform:translate3d(0,.8rem,0);
  transition:opacity 1s var(--e-out), transform 1s var(--e-out) }
.pre[data-ready] .pre__logo{ opacity:1; transform:none }
.pre__bar{ position:absolute; left:50%; bottom:5rem; translate:-50% 0;
  width:min(14rem,42vw); height:1px; background:rgba(243,238,227,.2); overflow:hidden }
.pre__bar i{ position:absolute; inset:0; background:var(--cream-warm);
  transform:scaleX(var(--p,0)); transform-origin:0 50%; transition:transform .45s var(--e-out) }
.pre[data-done]{ opacity:0; visibility:hidden; pointer-events:none }
html[data-loading] body{ overflow:hidden }

/* ---------- cursor — 11px dot, expands on interactive, back.out ---------- */
.cur{ position:fixed; left:0; top:0; z-index:150; pointer-events:none;
  width:11px; height:11px; margin:-5.5px 0 0 -5.5px; border-radius:50%;
  background:var(--cream); mix-blend-mode:difference; opacity:0; will-change:transform;
  transition:width .25s var(--e-back), height .25s var(--e-back),
             margin .25s var(--e-back), opacity var(--d-ui) }
.cur[data-on]{ opacity:1 }
.cur[data-big]{ width:88px; height:88px; margin:-44px 0 0 -44px }
@media (hover:none),(pointer:coarse){ .cur{ display:none } }

/* ---------- accessibility ---------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{ animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important }
  .ln__i,.ch__i{ transform:none }
  [data-rise]{ opacity:1; transform:none }
  [data-reveal]{ clip-path:none; transform:none }
  [data-draw]{ transform:none }
  .media__inner,.scene__bg,.hero__bg{ height:100%; transform:none !important }
  .cur,.pre{ display:none }
}
:focus-visible{ outline:2px solid var(--cream-warm); outline-offset:4px; border-radius:2px }
.t-cream :focus-visible{ outline-color:var(--ink) }
.sr{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap; border:0 }
.wd{ display:inline-block; white-space:nowrap }

/* ============================================================
   MOBILE — scroll-driven motion (<=950px)
   Desktop reveals fire once on entry; on a phone that reads as dead
   space between triggers. Here every element is driven continuously
   by its own --p (0..1), written once per frame by site.js, so each
   scrolled pixel moves something. .m-scrub is only added after the
   first pass, so a JS failure falls back to the desktop reveals.
   ============================================================ */
@media (max-width:950px){
  /* deeper travel needs more overflow to travel through */
  .media__inner{ height:114% }
  .scene__bg,.hero__bg{ height:114% }

  /* scenes run long and pin their caption while the image keeps moving */
  .scene{ display:block; min-height:0; height:152svh }
  .scene__body{ position:sticky; bottom:0; margin-top:84svh; padding-bottom:13svh }
  .scene::after{ background:linear-gradient(to top,
    rgba(7,54,31,.86) 0%,rgba(7,54,31,.44) 34%,rgba(7,54,31,.08) 62%,transparent 100%) }
}

/* lines rise on scroll, each one trailing the last */
html.m-scrub .ln__i{
  --lp:clamp(0,calc((var(--p,0) - var(--i,0) * .085) / .46),1);
  transform:translate3d(0,calc((1 - var(--lp)) * 118%),0);
  transition:none;
}
/* copy ramps in rather than snapping */
html.m-scrub [data-rise]{
  opacity:calc(.1 + var(--p,0) * .9);
  transform:translate3d(0,calc((1 - var(--p,0)) * 2.6rem),0);
  transition:none;
}
/* images wipe open as they cross the screen */
html.m-scrub [data-reveal]{
  clip-path:inset(calc((1 - var(--p,0)) * 100%) 0 0 0);
  transition:none;
}
/* the closing marks drift in from alternating edges */
html.m-scrub .marks li{
  transform:translate3d(calc((1 - var(--p,0)) * var(--dir,-1) * 14vw),0,0);
  transition:none;
}
html.m-scrub .marks li:nth-child(even){ --dir:1 }

@media (prefers-reduced-motion:reduce){
  html.m-scrub .ln__i,html.m-scrub [data-rise],
  html.m-scrub [data-reveal],html.m-scrub .marks li{
    transform:none !important; opacity:1 !important; clip-path:none !important;
  }
}

/* the hero lets go as you leave it */
html.m-scrub .hero__mid{
  opacity:var(--p,1);
  transform:translate3d(0,calc((1 - var(--p,1)) * -4.5rem),0);
  transition:none;
}
html.m-scrub .hero__foot{ opacity:var(--p,1); transition:none }
@media (prefers-reduced-motion:reduce){
  html.m-scrub .hero__mid,html.m-scrub .hero__foot{ opacity:1 !important; transform:none !important }
}

/* ============================================================
   CLOSING SECTION — never animated, unconditionally readable
   This is the last screen, so there is no scroll left to drive a
   reveal to completion; anything that waited on one would strand
   the CTA and the phone numbers half-visible. Nothing in here may
   depend on JS to be legible.
   ============================================================ */
.closing [data-rise],
.closing [data-reveal],
.closing [data-draw],
.closing .ln__i,
.closing .ch__i,
.closing .marks li,
html.m-scrub .closing [data-rise],
html.m-scrub .closing [data-reveal],
html.m-scrub .closing .ln__i,
html.m-scrub .closing .marks li{
  opacity:1 !important;
  transform:none !important;
  clip-path:none !important;
  transition:none !important;
}
.closing__glow{ transform:none !important }

/* ============================================================
   AMBIENT SOUND TOGGLE
   A speaker that gains its waves when playing and wears a cross
   when muted. Small and quiet, but unmistakably an audio control.
   ============================================================ */
.snd{
  position:fixed; right:var(--pad); z-index:80;
  /* viewport-fit=cover is set, so keep clear of the iOS home indicator */
  bottom:var(--snd-inset);
  /* a 2.9rem box with a 100px radius is still a circle, so the collapsed
     state is identical to the plain icon button */
  width:auto; min-width:var(--snd-size); height:var(--snd-size);
  /* .75rem keeps the collapsed content narrower than min-width, so the
     circle stays a circle rather than a slight oval */
  padding:0 .75rem; border-radius:100px;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  color:var(--cream); background:rgba(7,54,31,.36);
  border:1px solid rgba(243,238,227,.36);
  -webkit-backdrop-filter:blur(8px) saturate(1.1); backdrop-filter:blur(8px) saturate(1.1);
  opacity:0; transform:translate3d(0,10px,0) scale(.92);
  transition:opacity .7s var(--e-out), transform .7s var(--e-out),
             background-color .4s var(--e-io), border-color .4s var(--e-io);
}
.snd[data-ready]{ opacity:1; transform:none }
.snd:hover{ background:rgba(7,54,31,.62); border-color:rgba(243,238,227,.6) }
.snd__ico{ width:1.25rem; height:1.25rem; display:block; overflow:visible; flex:0 0 auto }

/* the label announces itself, then gets out of the way after a few seconds.
   max-width rather than grid-template-columns: same motion, no support caveat,
   and the pill is position:fixed so nothing else reflows. */
.snd__label{
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.13em; text-transform:uppercase; white-space:nowrap;
  max-width:0; margin-left:0; opacity:0; overflow:hidden;
  transition:max-width .5s var(--e-out), margin-left .5s var(--e-out),
             opacity .34s var(--e-io);
}
.snd[data-expanded] .snd__label{ max-width:12rem; margin-left:.6rem; opacity:1 }

/* muted: no waves, cross showing */
.snd__w{ opacity:0; transform:translateX(-2px); transform-origin:8px 12px;
  transition:opacity .35s var(--e-io), transform .45s var(--e-out) }
.snd__x{ opacity:.95; transition:opacity .3s var(--e-io) }

/* playing: waves in, cross out, outer wave breathing so it reads as live */
.snd[aria-pressed="true"] .snd__w{ opacity:1; transform:none }
.snd[aria-pressed="true"] .snd__w2{ transition-delay:.07s; animation:wave 2.6s var(--e-io) infinite }
.snd[aria-pressed="true"] .snd__x{ opacity:0 }
@keyframes wave{ 0%,100%{ opacity:.5 } 50%{ opacity:1 } }

@media (prefers-reduced-motion:reduce){
  .marks li > span{ animation:none }
  .snd__w2{ animation:none !important }
  /* don't slide the label in and out — just leave it readable */
  .snd__label{ max-width:12rem; margin-left:.6rem; opacity:1; transition:none }
}

/* ============================================================
   CHAPTER INDICATOR + JUMP MENU
   The pill bookends the bottom edge opposite the sound control and
   shares its inset tokens. Button language matches .hdr__cta / .wa.
   ============================================================ */
.chap{
  position:fixed; left:var(--pad); bottom:var(--snd-inset); z-index:80;
  /* positioning context for the "Menu" label stacked on top of the chapter */
  display:inline-flex; align-items:center; justify-content:center;
  height:var(--snd-size); min-width:var(--snd-size); padding:0 1.15em;
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.16em; text-transform:uppercase; white-space:nowrap;
  color:var(--cream); background:rgba(7,54,31,.36);
  border:1px solid rgba(243,238,227,.36); border-radius:100px;
  -webkit-backdrop-filter:blur(8px) saturate(1.1); backdrop-filter:blur(8px) saturate(1.1);
  cursor:pointer; opacity:0; transform:translate3d(0,10px,0) scale(.92);
  transition:opacity .7s var(--e-out), transform .7s var(--e-out),
             background-color .4s var(--e-io), border-color .4s var(--e-io);
}
.chap[data-ready]{ opacity:1; transform:none }
.chap[data-atop="true"]{ opacity:0; pointer-events:none }   /* silent over the hero */
.chap:hover{ background:rgba(7,54,31,.62); border-color:rgba(243,238,227,.6) }
@media (max-width:768px){ .chap{ padding:0 1em } }

/* ---------- zoom badge ----------
   Same chip as .snd and .chap — translucent deep green, cream hairline,
   backdrop blur — so the three floating controls read as one family. Always
   visible, on every device: there is no hover on touch, and an affordance
   nobody can see is not an affordance. */
.zoom{
  position:absolute; inset:0; z-index:2; display:block; width:100%; height:100%;
  padding:0; border:0; background:none; cursor:zoom-in; -webkit-appearance:none;
}
.zoom__chip{
  position:absolute; right:.8rem; bottom:.8rem;
  display:grid; place-items:center; width:2.4rem; height:2.4rem;
  color:var(--cream); background:rgba(7,54,31,.36);
  border:1px solid rgba(243,238,227,.36); border-radius:100px;
  -webkit-backdrop-filter:blur(8px) saturate(1.1); backdrop-filter:blur(8px) saturate(1.1);
  transition:background-color .4s var(--e-io), border-color .4s var(--e-io),
             transform .4s var(--e-out);
}
.zoom__chip svg{ width:58%; height:58% }
@media (hover:hover){
  .zoom:hover .zoom__chip{ background:rgba(7,54,31,.62); border-color:rgba(243,238,227,.6);
    transform:scale(1.06) }
}
.zoom:focus-visible{ outline:2px solid var(--cream); outline-offset:-4px }
/* floor plans sit on cream with no photograph behind the chip, so the same
   translucency would leave it floating on nothing — ground it instead */
.plan__fig .zoom__chip{ background:rgba(7,54,31,.82); border-color:rgba(7,54,31,.28) }
@media (max-width:768px){
  .zoom__chip{ right:.55rem; bottom:.55rem; width:2rem; height:2rem }
}

/* ---------- lightbox ---------- */
/* The site's own controls step aside while the viewer is open. Focus is trapped
   inside the dialog, so they are unreachable anyway, and the header CTA and the
   chapter pill both sit in corners the image wants. */
html[data-lb] .hdr,
html[data-lb] .chap,
html[data-lb] .snd,
html[data-lb] .prog{ opacity:0; pointer-events:none; transition:opacity .3s var(--e-io) }
.lb{ position:fixed; inset:0; z-index:120; display:grid;
  opacity:0; transition:opacity .42s var(--e-io) }
.lb[hidden]{ display:none }
.lb[data-open]{ opacity:1 }
/* Opaque, not a scrim: this is a viewer, and at 6% bleed the cream chrome and
   the display type behind it were still legible enough to compete with the
   render. --lb-dim is what fades it back out under a swipe-to-dismiss. */
.lb__bg{ position:absolute; inset:0; background:var(--green-night);
  opacity:var(--lb-dim, 1) }
.lb__stage{
  position:relative; z-index:1; place-self:center; display:grid; place-items:center;
  width:100%; height:100%; padding:clamp(1rem, 4vw, 4rem);
  touch-action:none; overflow:hidden; cursor:zoom-in;
}
.lb[data-zoomed="true"] .lb__stage{ cursor:grab }
.lb[data-zoomed="true"] .lb__stage:active{ cursor:grabbing }
.lb[data-drag="true"] .lb__stage{ transition:none }
.lb__img{
  max-width:100%; max-height:100%; width:auto; height:auto; object-fit:contain;
  transform-origin:center; will-change:transform; user-select:none; -webkit-user-drag:none;
}
/* the page-resolution frame is showing while the full-size file decodes */
.lb[data-busy="true"] .lb__img{ filter:blur(.4px) }

.lb__cap,.lb__count{
  position:absolute; z-index:2; font-family:var(--sans); font-size:var(--t-label);
  letter-spacing:.11em; text-transform:uppercase; color:var(--on-green-soft);
  pointer-events:none;
}
.lb__cap{ left:0; right:0; bottom:1.5rem; padding-inline:6rem; text-align:center;
  line-height:1.5; max-height:4.5em; overflow:hidden }
.lb__count{ left:0; right:0; top:1.6rem; text-align:center; font-variant-numeric:tabular-nums }

.lb__x,.lb__nav{
  position:absolute; z-index:3; display:grid; place-items:center;
  width:var(--snd-size); height:var(--snd-size); padding:0;
  color:var(--cream); background:rgba(7,54,31,.36);
  border:1px solid rgba(243,238,227,.36); border-radius:100px; cursor:pointer;
  -webkit-backdrop-filter:blur(8px) saturate(1.1); backdrop-filter:blur(8px) saturate(1.1);
  transition:background-color .4s var(--e-io), border-color .4s var(--e-io);
}
.lb__x:hover,.lb__nav:hover{ background:rgba(7,54,31,.72); border-color:rgba(243,238,227,.62) }
.lb__x{ top:var(--pad); right:var(--pad) }
.lb__x span{ position:absolute; width:42%; height:1px; background:currentColor }
.lb__x span:first-child{ transform:rotate(45deg) }
.lb__x span:last-child{ transform:rotate(-45deg) }
.lb__nav{ top:50%; margin-top:calc(var(--snd-size) / -2) }
.lb__nav svg{ width:44%; height:44% }
.lb__nav--prev{ left:var(--pad) }
.lb__nav--next{ right:var(--pad) }
/* panning with a finger must not be interrupted by an arrow under the thumb */
@media (max-width:768px){
  .lb__nav{ display:none }
  .lb__cap{ padding-inline:1.5rem; bottom:calc(var(--snd-inset) + 2.6rem) }
}
@media (prefers-reduced-motion:reduce){
  .lb,.lb__img,.zoom__chip{ transition:none !important }
}

/* ---------- fullscreen menu ---------- */
.menu{ position:fixed; inset:0; z-index:100; display:grid }
.menu[hidden]{ display:none }
.menu__bg{
  position:absolute; inset:0 0 0 auto; width:0; background:var(--green-night);
  transition:width .75s var(--e-out2);
}
.menu[data-open] .menu__bg{ width:100% }
.menu__in{
  position:relative; z-index:2; align-self:center;
  padding:var(--sec-s) var(--pad); color:var(--cream);
  max-height:100svh; overflow-y:auto; overscroll-behavior:contain;
}
.menu__eyebrow,.menu__item,.menu__cta{
  opacity:0; transform:translate3d(0,105%,0);
  transition:opacity .5s var(--e-out), transform .85s var(--e-out);
  transition-delay:calc(var(--i,0) * 55ms + 260ms);
}
.menu[data-open] .menu__eyebrow,
.menu[data-open] .menu__item,
.menu[data-open] .menu__cta{ opacity:1; transform:none }
.menu__eyebrow{ font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.2em; text-transform:uppercase; color:var(--on-green-soft);
  margin-bottom:2rem }
.menu__list{ display:grid; gap:.15em }
.menu__item a{ display:flex; align-items:baseline; gap:1.1em;
  padding:.18em 0; transition:opacity .4s var(--e-io) }
.menu__n{ font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.14em; opacity:.5; font-variant-numeric:tabular-nums; flex:0 0 auto }
.menu__name{ font-family:var(--serif); font-size:var(--t-h3); line-height:1.14;
  transition:transform .5s var(--e-out) }
/* the page you are already on: the mark is the dot, not a colour change, so the
   list keeps reading as one block of type */
.menu__item a[aria-current]{ opacity:1 }
.menu__item a[aria-current] .menu__name::after{ content:'\00b7'; margin-left:.4em; opacity:.55 }
@media (hover:hover){
  .menu__list:hover .menu__item a{ opacity:.45 }
  .menu__list .menu__item a:hover{ opacity:1 }
  .menu__item a:hover .menu__name{ transform:translateX(.35em) }
}
.menu__cta{ display:inline-flex; margin-top:2.6rem;
  font-family:var(--sans); font-weight:600; font-size:var(--t-label);
  letter-spacing:.16em; text-transform:uppercase;
  padding:.9em 1.7em; border:1px solid currentColor; border-radius:100px;
  position:relative; overflow:hidden; isolation:isolate }
.menu__cta::before{ content:''; position:absolute; inset:0; z-index:-1;
  background:currentColor; transform:scaleY(0); transform-origin:50% 100%;
  transition:transform .5s var(--e-io) }
.menu__cta:hover::before{ transform:scaleY(1) }
.menu__cta span{ transition:color .5s var(--e-io) }
.menu__cta:hover span{ color:var(--green-night) }

.menu__close{
  position:absolute; z-index:3; top:var(--pad); right:var(--pad);
  width:var(--snd-size); height:var(--snd-size); padding:0; cursor:pointer;
  background:none; border:1px solid rgba(243,238,227,.36); border-radius:50%;
  color:var(--cream); opacity:0;
  transition:opacity .4s var(--e-out) .4s, border-color .4s var(--e-io);
}
.menu[data-open] .menu__close{ opacity:1 }
.menu__close:hover{ border-color:var(--cream) }
.menu__close span{ position:absolute; left:50%; top:50%; width:1rem; height:1px;
  background:currentColor; transform-origin:50% 50% }
.menu__close span:first-child{ transform:translate(-50%,-50%) rotate(45deg) }
.menu__close span:last-child{ transform:translate(-50%,-50%) rotate(-45deg) }

html[data-menu] body,
html[data-lb] body{ overflow:hidden }

@media (prefers-reduced-motion:reduce){
  .menu__bg{ transition:none }
  .menu[data-open] .menu__bg{ width:100% }
  .menu__eyebrow,.menu__item,.menu__cta{ transition:none; transition-delay:0s }
}
