@charset "utf-8";
/* ==========================================================================
   ESTATE 108 — site.css
   Single stylesheet for the whole site. No frameworks, no build step,
   no @import, no second stylesheet.

   ###  THE GROUND IS CREAM.  GREEN IS PUNCTUATION.  ###

   The client rejected the previous all-green build ("looks very green").
   The relationship is now inverted, exactly like the Aavana brochure:
   ivory pages, deep-green headings, gold hairlines.

     CREAM  #F7F2E8   the page. Every section is cream unless told otherwise.
     GREEN  #16382B   the hero overlay, the footer, at most one or two
                      accent bands per page, headings and primary buttons.
     GOLD   #EBA126   ornament only. NEVER text on cream (1.95:1).

   As a rough target no more than ~25-30% of a page's vertical run is green.
   Only `.section--deep`, `.cta-band`, `.hero` and `.site-footer` are green.

   TWO HARD RULES BAKED INTO THIS FILE — do not override them in a page:

   1.  GOLD IS NEVER TEXT ON CREAM.  #EBA126 on #F7F2E8 is 1.95:1. Gold on
       cream is allowed only as a hairline, an ornament or a gradient stop.
       A gold-looking LABEL on cream uses --gold-deep (#84611F, 4.75:1) at
       >= 16px / 600 weight. Gold as text is allowed ONLY on green.

   2.  A CARD CANNOT BE DEFINED BY ITS FILL.  Ivory on cream is 1.08:1 and
       cream-deep on cream is 1.10:1 — invisible. Every card or raised panel
       carries BOTH a 1px border (--line) AND the two-layer card shadow.
       On hover the shadow lifts and the border darkens to --line-strong.

   Other standing rules
   - No #000 and no pure-black shadow anywhere. The darkest value on the
     site is --green-900 / --ink. Shadows are rgba(20,32,26,a).
   - Motion animates transform and opacity ONLY. Never width/height/top/
     left/margin — they reflow and cost CLS.
   - prefers-reduced-motion: reduce kills all of it. Hard requirement.
   - :focus-visible is a --gold-deep outline. Never remove it.
   - Touch targets are >= 44px. Hover effects are guarded behind
     @media (hover: hover) and (pointer: fine) so a tap never sticks.

   SECTION INDEX
     01  Tokens
     02  Reset & base
     03  Typography primitives
     04  Layout: container, section, rule
     05  Motion primitives: reveal, stagger
     06  Buttons
     07  Header, brand lockup, nav, dropdowns
     08  Mobile toggle & overlay menu
     09  Hero slider
     10  Project grid & cards
     11  Principles
     12  Press strip
     13  CTA band, contact grid, form
     14  FAQ, prose, tables, disclaimer, RERA
     15  Breadcrumbs, page hero, project tabs/body/nav
     16  Aavana components: price band, gallery, amenities, plans, payments
     17  Lightbox
     18  Footer
     19  Cookie banner
     20  Paper / ivory section variant
     21  Responsive
     22  Reduced motion
     23  Print
   ========================================================================== */


/* ==========================================================================
   01  TOKENS
   ========================================================================== */

:root {

  /* --- The cream ground (measured against --ink at 15.04:1) ------------- */
  --cream:      #F7F2E8;   /* PAGE GROUND — background of every page        */
  --cream-deep: #EFE7D8;   /* alternating section band, subtle              */
  --ivory:      #FDFBF6;   /* cards and raised surfaces                     */

  /* --- The green accent scale ------------------------------------------ */
  --green-900: #012D20;    /* footer, deepest bands                         */
  --green-800: #06402F;    /* THE BRAND GREEN — hero overlay, bands, h2     */
  --green-700: #0C5540;    /* hover on green, rules                         */
  --green-600: #1B6B52;    /* muted green text on cream (6.54:1)            */

  /* --- Ink ------------------------------------------------------------- */
  --ink:   #14201A;        /* body text on cream (15.04:1)                  */
  --muted: #5A6B61;        /* secondary text on cream (5.07:1)              */

  /* --- Gold — ORNAMENT ONLY on cream ----------------------------------- */
  --gold:      #EBA126;    /* 1.95:1 on cream. Decoration and green only.   */
  --gold-deep: #84611F;    /* 5.07 cream · 4.61 cream-deep · 5.47 ivory — AA */
  --gold-hi:   #FCEEA4;    /* metallic highlight stop                       */
  --aavana-gold: #D0B470;  /* Aavana's own brand gold, sampled from the supplied
                              artwork. 5.86:1 on green-800 — the page-hero surface
                              it is actually used on — and 7.47:1 on green-900.  */
  --gold-ramp:   linear-gradient(90deg, #946F1F 0%, #EBA126 52%, #FCEEA4 100%);
  --gold-ramp-v: linear-gradient(180deg, #FCEEA4 0%, #EBA126 48%, #946F1F 100%);

  /* --- Semantic surfaces ----------------------------------------------- */
  --bg:         var(--cream);
  --bg-band:    var(--cream-deep);
  --surface:    var(--ivory);
  --bg-deep:    var(--green-800);
  --bg-deepest: var(--green-900);

  --text:   var(--ink);
  --text-2: #33443B;       /* ~11:1 on cream — sub-headings, strong body    */
  --text-3: var(--muted);
  --accent: var(--green-800);

  /* --- Text ON green (verified) ---------------------------------------- */
  --on-green:    var(--cream);            /* 13.73 on 900 · 11.51 on 800    */
  --on-green-2:  rgba(247, 242, 232, .80);
  --on-green-3:  rgba(247, 242, 232, .62);
  --on-green-gold: var(--gold);           /* 7.05 on 900 · 5.91 on 800      */

  /* --- Hairlines -------------------------------------------------------- */
  --line:        rgba(20, 32, 26, .12);   /* the required card border       */
  --line-strong: rgba(20, 32, 26, .20);   /* the required hover border      */
  --line-soft:   rgba(20, 32, 26, .07);
  --line-gold:   rgba(148, 111, 31, .34); /* decorative hairline on cream   */
  --line-on-green:      rgba(247, 242, 232, .16);
  --line-on-green-soft: rgba(247, 242, 232, .09);

  /* --- Shadows (never pure black) --------------------------------------- */
  --shadow-card:       0 1px 2px rgba(20, 32, 26, .04), 0 8px 24px rgba(20, 32, 26, .06);
  --shadow-card-hover: 0 2px 6px rgba(20, 32, 26, .07), 0 18px 44px rgba(20, 32, 26, .12);
  --shadow-header:     0 1px 2px rgba(20, 32, 26, .04), 0 6px 20px rgba(20, 32, 26, .06);
  --shadow-pop:        0 24px 70px rgba(20, 32, 26, .22);
  --shadow-on-green:   0 18px 48px rgba(6, 18, 13, .38);

  /* --- ONE family, three jobs -------------------------------------------
     DISPLAY : Jost 300, UPPERCASE, letter-spacing .015em. The client asked for
               headings in the UI face, so display and UI are now the same
               family and differ only by size, weight and tracking.
     BODY    : Jost 400, 16-18px, line-height 1.65
     LABELS  : Jost 500, UPPERCASE, 11-13px, letter-spacing .22em
     --font-display, --font-ui and --font-text all resolve to Jost; they stay
     separate tokens so the three jobs can diverge again later.
     Cormorant Garamond, Tenor Sans and Barlow have been REMOVED. Do not
     reintroduce them, and do not add a second family to the fonts request. */
  /* The display ROLE is kept, but it now resolves to Jost — the client asked
     for headings in the UI face. Repointing the token switches every heading
     rule at once instead of editing each one. Cormorant is no longer loaded. */
  --font-display: "Jost", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-ui:      "Jost", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-text:    "Jost", "Helvetica Neue", Helvetica, Arial, sans-serif;
  /* Serif, for the price figure only — the client wants that one number set
     in the old display face rather than in Jost. */
  --font-price:   "Cormorant Garamond", Georgia, "Times New Roman", serif;

  /* --- Fluid type scale -------------------------------------------------
     Display sizes are Jost, so they run large with tight leading.     */
  --fs-micro: 11px;                                  /* .eyebrow small      */
  --fs-label: clamp(11px, .2vw + 10px, 13px);        /* Jost micro-labels   */
  --fs-xs:    clamp(12px, .3vw + 11px, 13px);
  --fs-sm:    clamp(13px, .35vw + 12px, 15px);
  --fs-base:  clamp(16px, .45vw + 15px, 18px);       /* body — 16px floor   */
  --fs-md:    clamp(17px, .6vw + 15px, 20px);
  --fs-lg:    clamp(20px, 1vw + 17px, 25px);         /* .lede               */
  --fs-xl:    clamp(18px, 2.2vw + 9.5px, 31.9px);       /* h3 / card titles    */
  --fs-2xl:   clamp(19.9px, 3.0vw + 7.9px, 41.9px);       /* h2 / section heads  */
  --fs-3xl:   clamp(25.9px, 4.4vw + 7.9px, 61.9px);       /* .display / h1       */
  --fs-4xl:   clamp(29.9px, 5.6vw + 7.9px, 75.9px);       /* hero display        */
  --fs-num:   clamp(40px, 3.4vw + 26px, 68px);       /* .principle-num      */

  /* --- Tracking --------------------------------------------------------- */
  --track-micro:   .22em;   /* Jost eyebrows                 */
  --track-label:   .18em;   /* Jost nav / chips              */
  --track-btn:     .16em;
  --track-display: .015em;  /* uppercase Jost needs only a little air */

  /* --- Line heights ----------------------------------------------------- */
  --lh-display: 1.1;        /* uppercase Jost sets tighter than a serif */
  --lh-tight:  1.08;
  --lh-snug:   1.22;
  --lh-normal: 1.55;
  --lh-body:   1.65;
  --lh-loose:  1.75;

  /* --- Spacing ---------------------------------------------------------- */
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;  --sp-5: 24px;
  --sp-6: 32px;  --sp-7: 48px;  --sp-8: 64px;  --sp-9: 96px;  --sp-10: 128px;
  --sp-section: clamp(64px, 7.5vw, 120px);
  --sp-gutter:  clamp(16px, 4vw, 32px);   /* >= 16px side gutter at 320px   */
  --container:  1280px;
  --header-h:   76px;

  /* --- Radii ------------------------------------------------------------ */
  --r-0: 0px; --r-1: 2px; --r-2: 4px; --r-3: 10px; --r-4: 16px; --r-pill: 999px;

  /* ======================================================================
     MOTION TOKENS — one rhythm across the whole site.
     Exit transitions run at ~65% of their enter duration.
     ====================================================================== */
  --ease-out: cubic-bezier(.22, .61, .36, 1);   /* entering / revealing     */
  --ease-in:  cubic-bezier(.55, .06, .68, .19); /* exiting                  */
  --ease-io:  cubic-bezier(.65, .05, .36, 1);   /* crossfade, sticky header */

  --t-fast:  180ms;
  --t-base:  260ms;
  --t-slow:  420ms;
  --t-slide: 900ms;
  --t-slide-out: 585ms;    /* 65% of --t-slide */
  --t-base-out:  170ms;    /* 65% of --t-base  */

  --kenburns: 7s;
  --reveal-delay: 0ms;     /* set per element by site.js                    */
  --stagger-step: 45ms;
}


/* ==========================================================================
   02  RESET & BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchor targets must clear the sticky header. */
  scroll-padding-top: calc(var(--header-h) + 16px);
  background: var(--bg);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
}

/* Display type: UPPERCASE Jost. Garamond, .02em tracking, 1.08 leading,
   weight 400-500. h4/h5/h6 opt back out below. */
h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-display);
  /* 300, not 400: a geometric sans set in caps at display size reads much
     heavier than the serif it replaced. */
  font-weight: 300;
  color: var(--green-800);
  letter-spacing: var(--track-display);
  line-height: var(--lh-tight);
  text-transform: uppercase;
  text-wrap: balance;
}

h1 { font-size: var(--fs-3xl); line-height: var(--lh-display); }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-md); font-family: var(--font-text); font-weight: 500; letter-spacing: 0; text-transform: none; line-height: var(--lh-snug); color: var(--text-2); }
h5, h6 {
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  line-height: var(--lh-snug);
  color: var(--green-600);
  font-weight: 500;
}

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

a { color: inherit; text-decoration: none; }

img, svg, video, picture { display: block; max-width: 100%; }
img { height: auto; }

ul, ol { margin: 0; padding: 0; }
li { list-style: none; }

button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

table { border-collapse: collapse; width: 100%; }

hr {
  border: 0;
  height: 1px;
  background: var(--line);
  margin: var(--sp-7) 0;
}

::selection { background: rgba(22, 56, 43, .90); color: var(--cream); }

/* Focus. Never remove — :focus-visible only, so a mouse click is quiet. */
:focus { outline: none; }
:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 3px;
  border-radius: var(--r-1);
}
/* On a green surface the gold-deep ring is too dark — brighten it. */
.site-footer :focus-visible,
.cta-band :focus-visible,
.section--deep :focus-visible,
.hero :focus-visible,
.page-hero :focus-visible,
.lightbox :focus-visible {
  outline-color: var(--gold);
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: -100px; left: var(--sp-4);
  z-index: 200;
  background: var(--green-800);
  color: var(--cream);
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  padding: 14px 22px;
  border-radius: var(--r-2);
  box-shadow: var(--shadow-pop);
  transition: transform var(--t-base) var(--ease-out);
}
.skip-link:focus-visible { top: 12px; }


/* ==========================================================================
   03  TYPOGRAPHY PRIMITIVES
   Jost = display, micro-labels AND body. Formerly Cormorant Garamond = display.
   ========================================================================== */

.eyebrow,
.section-label,
.status-chip,
.project-meta__more,
.nav-item,
.btn,
.mobile-menu__group-label,
.footer-brands__label,
.project-nav__label,
.img-caption,
.project-tab,
.hero-dots,
.amenity,
.press-logo {
  font-family: var(--font-ui);
}

/* Jost, uppercase, 11-13px, .22em, 500. On cream an eyebrow that must read
   as gold uses .section-label (--gold-deep); --gold is never text on cream. */
.eyebrow {
  display: block;
  font-size: var(--fs-label);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  color: var(--green-600);
  margin: 0 0 var(--sp-3);
}
.eyebrow--muted { color: var(--muted); }

/* A gold-LOOKING label on cream: gold-deep, >=16px, 600. Never --gold. */
.section-label {
  display: inline-block;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--gold-deep);
  margin: 0 0 var(--sp-4);
}

/* Aavana banner lockup. Deliberately NOT the serif from the client's mock-up:
   they asked to keep the site's own face, so this is Jost throughout and the
   hierarchy is carried by size, tracking and colour instead of a type switch. */
.upcoming-tagline {
  margin: var(--sp-2) 0 var(--sp-3);
  font-family: var(--font-ui);
  font-size: clamp(14px, .5vw + 12px, 18px);
  font-weight: 400;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
}
.section-label--place {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 0;
  color: var(--muted);
}
.section-label--place::after {
  content: "";
  width: clamp(40px, 8vw, 96px);
  height: 1px;
  background: var(--gold);
  opacity: .8;
}

.display {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--fs-3xl);
  line-height: var(--lh-display);
  letter-spacing: var(--track-display);
  text-transform: uppercase;
  color: var(--green-800);
  margin: 0 0 var(--sp-5);
}
.display span { display: block; }
.display em { font-style: italic; font-weight: 400; }

.lede {
  font-size: var(--fs-lg);
  line-height: 1.5;
  color: var(--text-2);
  font-weight: 300;
  max-width: 62ch;
  margin: 0 0 var(--sp-5);
}

/* Anything sitting on a green band flips its text colours. */
.section--deep,
.cta-band,
.site-footer,
.hero-slide__content,
.page-hero { color: var(--on-green); }

.section--deep h1, .section--deep h2, .section--deep h3,
.cta-band h1, .cta-band h2, .cta-band h3,
.site-footer h2, .site-footer h3,
.hero-slide__content .display,
.page-hero h1, .page-hero h2 { color: var(--cream); }

.section--deep .lede,
.cta-band .lede,
.hero-slide__content .lede,
.page-hero .lede { color: var(--on-green-2); }

.section--deep .eyebrow,
.cta-band .eyebrow,
.hero-slide__content .eyebrow,
.page-hero .eyebrow { color: var(--gold); }        /* gold on green = legal */

.section--deep .section-label,
.cta-band .section-label,
.page-hero .section-label { color: var(--gold); }


/* ==========================================================================
   04  LAYOUT
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-gutter);
}
.container--narrow { max-width: 820px; }

.section {
  padding-block: var(--sp-section);
  position: relative;
}
.section--tight { padding-block: clamp(40px, 5vw, 72px); }

/* The subtle alternating cream band. Still cream — not a green band. */
.section--band {
  background: var(--cream-deep);
  border-block: 1px solid var(--line-soft);
}

/* THE GREEN ACCENT BAND. At most one of these mid-page; the enquiry band
   and the footer close every page in green, which is the intended rhythm. */
.section--deep {
  background: var(--green-800);
  color: var(--on-green);
}
.section--deep::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: var(--gold-ramp);
  opacity: .85;
}

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-6);
  margin-bottom: clamp(32px, 4vw, 64px);
}
/* Both columns share the row. Without a flex basis the heading column
   collapses to its min-content width, so a short heading like "Speak to us"
   wrapped mid-phrase while the lede beside it took all the space. */
.section-head > div {
  flex: 1 1 0;
  min-width: 0;
  max-width: 70ch;
}
.section-head > div:only-child { flex: 1 1 100%; }
.section-head h2 { margin-bottom: var(--sp-3); }
.section-head .lede { margin-bottom: 0; }
/* Consecutive ledes in one head (the home contact block runs two) need a
   gap; the rule above zeroes it for the single-lede case. */
.section-head .lede + .lede { margin-top: var(--sp-4); }

/* Three-part tagline closing the Aavana block. The pipes are decoration, so
   they are aria-hidden in the markup and tinted gold here. */
.lede-tagline {
  margin: var(--sp-4) 0 0;
  font-family: var(--font-ui);
  font-size: clamp(13px, .4vw + 11px, 16px);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  line-height: 1.7;
  color: var(--green-800);
}
.lede-tagline span { color: var(--gold-deep); margin: 0 6px; }

/* Project pages put the label, heading and lede as DIRECT children of
   .section-head rather than wrapping them in columns the way the home and
   about pages do. In the flex row above that meant `space-between` pinned the
   label hard left and shoved the heading right (Amenities' heading started
   830px from its label), `align-items: flex-end` bottom-aligned a 21px label
   against a 112px heading, and with no flex-basis the heading collapsed
   toward min-content — "A closer look" stacked three words deep in a 216px
   column. So: a direct label takes its own row, and the heading and lede
   share the row beneath it. The `>` scoping leaves the div-based heads on
   home/about completely untouched. */
.section-head:has(> .eyebrow),
.section-head:has(> .section-label) {
  flex-wrap: wrap;
  justify-content: flex-start;
  row-gap: var(--sp-3);
}
.section-head > .eyebrow,
.section-head > .section-label {
  flex: 0 0 100%;
  margin-bottom: 0;
}
.section-head > h2 {
  flex: 1 1 26ch;
  min-width: 0;
  max-width: 70ch;
  margin-bottom: 0;
}
.section-head > .lede {
  flex: 1 1 22ch;
  min-width: 0;
  max-width: 70ch;
}

/* Project pages run the overview prose straight into the "what was
   delivered" block, and the RERA line straight into the disclaimer, with
   0px between them. */
.prose + .reveal,
.prose + [data-reveal] { margin-top: clamp(28px, 3.2vw, 48px); }
.rera-line + .disclaimer { margin-top: var(--sp-4); }
.pull-quote + .prose { margin-top: clamp(28px, 3.2vw, 48px); }
.prose + .rera-line { margin-top: clamp(24px, 2.6vw, 40px); }

.rule {
  height: 1px;
  background: var(--line);
  border: 0;
  margin: var(--sp-6) 0;
}
/* Gold as a hairline on cream is permitted — it carries no information. */
.rule--gold {
  height: 2px;
  background: var(--gold-ramp);
  opacity: .8;
}
.rule--short { width: 72px; margin-inline: 0; }

/* Wide things get their own scroller. The page body never scrolls sideways. */
.table-scroll,
.scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
/* The caption used to butt straight up against the prose above it. */
.table-scroll {
  margin-inline: calc(var(--sp-gutter) * -1);
  padding-inline: var(--sp-gutter);
  margin-top: clamp(28px, 3.2vw, 48px);
}


/* ==========================================================================
   05  MOTION PRIMITIVES — reveal + stagger
   Transform and opacity only. Space is reserved by the element itself, so a
   reveal never shifts layout.
   ========================================================================== */

/* CONTENT IS VISIBLE BY DEFAULT. The hidden starting state is gated behind
   `.js-on`, which site.js writes onto <html> as its very first statement. If
   the script is blocked, fails to parse, or never arrives, no rule below ever
   matches and every [data-reveal] element simply renders — there is no window
   in which the page is blank. Do not remove the `.js-on` prefix. */
.js-on [data-reveal],
.js-on .reveal {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity   var(--t-slow) var(--ease-out) var(--reveal-delay),
    transform var(--t-slow) var(--ease-out) var(--reveal-delay);
  will-change: opacity, transform;
}
.js-on [data-reveal].is-revealed,
.js-on .reveal.is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}

/* A CSS-only stagger for groups whose children are not individually
   observed. Capped at six so a long grid does not crawl. */
.stagger > * { transition-delay: 0ms; }
.stagger > *:nth-child(2) { transition-delay: calc(var(--stagger-step) * 1); }
.stagger > *:nth-child(3) { transition-delay: calc(var(--stagger-step) * 2); }
.stagger > *:nth-child(4) { transition-delay: calc(var(--stagger-step) * 3); }
.stagger > *:nth-child(5) { transition-delay: calc(var(--stagger-step) * 4); }
.stagger > *:nth-child(6) { transition-delay: calc(var(--stagger-step) * 5); }
.stagger > *:nth-child(n + 7) { transition-delay: calc(var(--stagger-step) * 6); }


/* ==========================================================================
   06  BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 48px;                 /* >= 44px touch target */
  padding: 14px 30px;
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--track-btn);
  line-height: 1;
  border-radius: var(--r-2);
  border: 1px solid transparent;
  cursor: pointer;
  text-align: center;
  transition:
    background-color var(--t-fast) var(--ease-out),
    border-color     var(--t-fast) var(--ease-out),
    color            var(--t-fast) var(--ease-out),
    box-shadow       var(--t-fast) var(--ease-out),
    transform        var(--t-fast) var(--ease-out);
}
.btn:active { transform: scale(.985); }

.btn-primary {
  background: var(--green-800);
  color: var(--cream);
  border-color: var(--green-800);
  box-shadow: 0 1px 2px rgba(20, 32, 26, .10);
}
.btn-ghost {
  background: transparent;
  color: var(--green-800);
  border-color: var(--line-strong);
}
.btn-sm { min-height: 44px; padding: 11px 22px; font-size: var(--fs-xs); }

/* Ghost buttons sitting on a green band invert. */
.section--deep .btn-ghost,
.cta-band .btn-ghost,
.hero-slide__actions .btn-ghost,
.hero-brand__actions .btn-ghost,
.page-hero .btn-ghost,
.site-footer .btn-ghost {
  color: var(--cream);
  border-color: var(--line-on-green);
}
.section--deep .btn-primary,
.cta-band .btn-primary,
.hero-slide__actions .btn-primary,
.hero-brand__actions .btn-primary,
.page-hero .btn-primary {
  background: var(--cream);
  color: var(--green-900);
  border-color: var(--cream);
}

.btn[disabled] { opacity: .55; cursor: not-allowed; transform: none; }

@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover {
    background: var(--green-700);
    border-color: var(--green-700);
    transform: translateY(-1px);
    box-shadow: 0 4px 14px rgba(20, 32, 26, .16);
  }
  .btn-ghost:hover {
    color: var(--green-800);
    border-color: var(--green-800);
    background: rgba(22, 56, 43, .06);
    transform: translateY(-1px);
  }
  .section--deep .btn-ghost:hover,
  .cta-band .btn-ghost:hover,
  .hero-slide__actions .btn-ghost:hover,
  .page-hero .btn-ghost:hover {
    background: rgba(247, 242, 232, .10);
    border-color: var(--cream);
    color: var(--cream);
  }
  .section--deep .btn-primary:hover,
  .cta-band .btn-primary:hover,
  .hero-slide__actions .btn-primary:hover,
  .page-hero .btn-primary:hover {
    background: var(--gold-hi);
    border-color: var(--gold-hi);
    color: var(--green-900);
  }
  .btn[disabled]:hover { transform: none; box-shadow: none; }
}


/* ==========================================================================
   07  HEADER · BRAND LOCKUP · NAV
   Transparent over the hero, then cream with a hairline once scrolled.
   Only background-color, border and shadow change — never height.
   ========================================================================== */

.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    background-color var(--t-base) var(--ease-io),
    border-color     var(--t-base) var(--ease-io),
    box-shadow       var(--t-base) var(--ease-io);
}
.site-header > .container {
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
}

.site-header.is-scrolled,
.has-solid-header .site-header {
  background: var(--cream);
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-header);
}

/* --- Two-logo lockup, sized by HEIGHT (the two ratios differ) ---------- */
.brand-lockup {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.6vw, 20px);
  flex: 0 0 auto;
}
.brand-lockup a { display: flex; align-items: center; }
.brand-lockup img { width: auto; display: block; }

.brand-lockup__primary { height: clamp(38px, 4.6vw, 56px); }
.brand-lockup__partner { height: clamp(15px, 1.8vw, 20px); opacity: .92; }

.brand-lockup__divider {
  width: 1px;
  align-self: stretch;
  margin-block: 12px;
  background: var(--line);
  transition: background-color var(--t-base) var(--ease-io);
}

/* One Estate 108 mark in every header state. The previous build swapped a
   light and a dark copy with display:none; any page that shipped only one
   copy lost its logo entirely, which is the bug the client reported. The
   swap is deliberately gone — the metallic mark reads on cream and on green. */
.brand-lockup__primary { display: block; }
.brand-lockup__divider { display: none; }
.mobile-menu__head .brand-lockup__primary { display: block; height: 34px; }

/* --- Desktop navigation ------------------------------------------------ */
.nav {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 32px);
}
.nav ul.nav-list {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.8vw, 30px);
}

.nav-item {
  position: relative;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--cream);
  background: none;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease-out);
}
.site-header.is-scrolled .nav-item,
.has-solid-header .nav-item { color: var(--green-800); }

/* A gold-ramp underline that grows from the left. Decorative only. */
.nav-item::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 12px;
  height: 2px;
  background: var(--gold-ramp);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--t-base) var(--ease-out);
}
.nav-item.is-active::after,
.nav-item[aria-expanded="true"]::after { transform: scaleX(1); }

/* Dropdown carets */
.nav-item[aria-haspopup="true"] { padding-right: 16px; }
.nav-item[aria-haspopup="true"]::before {
  content: "";
  position: absolute;
  right: 0; top: 50%;
  width: 6px; height: 6px;
  margin-top: -5px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--t-fast) var(--ease-out);
}
.nav-item[aria-expanded="true"]::before { transform: rotate(-135deg); margin-top: -2px; }

.nav-dropdown { position: relative; }

.nav-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: -20px;
  min-width: 290px;
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card-hover);
  padding: var(--sp-3);
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -8px, 0);
  transition:
    opacity    var(--t-base-out) var(--ease-in),
    transform  var(--t-base-out) var(--ease-in),
    visibility 0s linear var(--t-base-out);
}
.nav-panel::before {
  content: "";
  position: absolute;
  inset-inline: var(--sp-3);
  top: 0;
  height: 2px;
  background: var(--gold-ramp);
  border-radius: var(--r-pill);
  opacity: .8;
}
.nav-panel.is-open {
  opacity: 1;
  visibility: visible;
  transform: translate3d(0, 0, 0);
  transition:
    opacity    var(--t-base) var(--ease-out),
    transform  var(--t-base) var(--ease-out),
    visibility 0s;
}
.nav-panel a {
  display: block;
  padding: 12px 14px;
  border-radius: var(--r-2);
  min-height: 44px;
  transition: background-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
/* NOT scoped to .nav-panel: the mobile menu renders the same markup inside
   .mobile-menu__sub, where the ancestor selector never matched — so the name
   and location spans stayed inline and ran together as "Aagar HillsRishikesh".
   The BEM class already namespaces these; the extra ancestor only broke them. */
.nav-panel__name {
  display: block;
  font-family: var(--font-display);
  font-size: 21px;
  line-height: 1.2;
  color: var(--green-800);
}
.nav-panel__meta {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--muted);
  margin-top: 3px;
}
.nav-panel__empty {
  display: block;
  padding: 12px 14px;
  font-size: var(--fs-sm);
  color: var(--muted);
}

@media (hover: hover) and (pointer: fine) {
  .nav-item:hover { color: var(--green-700); }
  .site-header:not(.is-scrolled) .nav-item:hover { color: var(--gold-hi); }
  .has-solid-header .site-header:not(.is-scrolled) .nav-item:hover { color: var(--green-700); }
  .nav-item:hover::after { transform: scaleX(1); }
  .nav-dropdown:hover .nav-panel {
    opacity: 1;
    visibility: visible;
    transform: translate3d(0, 0, 0);
    transition:
      opacity   var(--t-base) var(--ease-out),
      transform var(--t-base) var(--ease-out),
      visibility 0s;
  }
  .nav-panel a:hover { background: var(--cream-deep); transform: translateX(3px); }
}


/* ==========================================================================
   08  MOBILE TOGGLE & OVERLAY MENU
   ========================================================================== */

.mobile-toggle {
  display: none;
  width: 48px; height: 48px;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  border-radius: var(--r-2);
  transition: background-color var(--t-fast) var(--ease-out);
}
.mobile-toggle span {
  display: block;
  width: 24px; height: 2px;
  background: var(--cream);
  border-radius: 2px;
  transition: transform var(--t-base) var(--ease-out),
              opacity   var(--t-fast) var(--ease-out),
              background-color var(--t-base) var(--ease-io);
}
.site-header.is-scrolled .mobile-toggle span,
.has-solid-header .mobile-toggle span,
.mobile-menu .mobile-toggle span { background: var(--green-800); }

.mobile-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.mobile-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(.4); }
.mobile-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--cream);
  display: flex;
  flex-direction: column;
  padding: var(--sp-4) 0 var(--sp-6);
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -12px, 0);
  transition:
    opacity    var(--t-base-out) var(--ease-in),
    transform  var(--t-base-out) var(--ease-in),
    visibility 0s linear var(--t-base-out);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.mobile-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: translate3d(0, 0, 0);
  transition:
    opacity    var(--t-base) var(--ease-out),
    transform  var(--t-base) var(--ease-out),
    visibility 0s;
}
.mobile-menu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: 0 var(--sp-gutter) var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.mobile-menu__body {
  flex: 1 1 auto;
  padding: var(--sp-6) var(--sp-gutter);
  display: flex;
  flex-direction: column;
}
.mobile-menu__foot {
  padding: var(--sp-5) var(--sp-gutter) 0;
  border-top: 1px solid var(--line);
}
.mobile-menu ul { margin-bottom: var(--sp-6); }
.mobile-menu li + li { border-top: 1px solid var(--line-soft); }
.mobile-menu a {
  display: block;
  padding: 14px 0;
  min-height: 48px;
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1.25;
  color: var(--green-800);
  transition: color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.mobile-menu__group-label {
  display: block;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  color: var(--gold-deep);
  font-weight: 600;
  margin-bottom: var(--sp-2);
}
.mobile-menu__sub a { font-size: 22px; }
.mobile-menu__sub .nav-panel__meta { margin-top: 0; }
.mobile-menu .btn { width: 100%; margin-top: var(--sp-3); }

body.menu-open { overflow: hidden; }

@media (hover: hover) and (pointer: fine) {
  .mobile-toggle:hover { background: rgba(20, 32, 26, .06); }
  .mobile-menu a:hover { color: var(--green-600); transform: translateX(4px); }
}


/* ==========================================================================
   09  HERO SLIDER
   Slides are stacked and crossfaded. The active slide's image runs a slow
   Ken Burns so the picture is always gently alive. Opacity + transform only.
   ========================================================================== */

.hero {
  position: relative;
  min-height: min(86vh, 860px);
  display: flex;
  align-items: stretch;
  background: var(--green-900);
  overflow: hidden;
  isolation: isolate;
}
/* Slides are stacked in ONE grid cell rather than absolutely positioned, so
   the tallest caption sets the hero's height instead of overflowing it. */
.hero-slider {
  position: relative;
  width: 100%;
  min-height: inherit;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: stretch;
}

.hero-slide {
  grid-area: 1 / 1;
  position: relative;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  opacity: 0;
  pointer-events: none;
  /* Exit runs at 65% of the enter duration. */
  transition: opacity var(--t-slide-out) var(--ease-io);
  z-index: 1;
}
.hero-slide.is-active {
  opacity: 1;
  pointer-events: auto;
  z-index: 2;
  transition: opacity var(--t-slide) var(--ease-io);
}
.hero-slide > img,
.hero-slide picture,
.hero-slide picture > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.hero-slide.is-active > img,
.hero-slide.is-active picture > img {
  animation: kenburns var(--kenburns) linear forwards;
}
@keyframes kenburns {
  from { transform: scale(1); }
  to   { transform: scale(1.06); }
}

/* The green overlay. This is the hero's green — it is meant to be here. */
.hero-slide::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(180deg, rgba(14, 42, 32, .62) 0%, rgba(14, 42, 32, .28) 34%, rgba(14, 42, 32, .88) 100%),
    linear-gradient(90deg, rgba(22, 56, 43, .72) 0%, rgba(22, 56, 43, .18) 62%, rgba(22, 56, 43, 0) 100%);
}

.hero-slide__content {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding: calc(var(--header-h) + clamp(24px, 6vh, 64px)) var(--sp-gutter) clamp(56px, 9vh, 128px);
}
.hero-slide__content .display {
  color: var(--cream);
  /* The page display scale is too loud over a photograph — at 18ch the hero
     headline ran to five lines and swamped the image. */
  font-size: clamp(2rem, 4.4vw, 3.9rem);
  line-height: 1.04;
  max-width: 24ch;
  text-shadow: 0 2px 30px rgba(6, 18, 13, .35);
}
.hero-slide__content .lede { max-width: 56ch; color: var(--on-green-2); }

.hero-slide__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

/* Caption staggering: eyebrow 0 · headline 60 · lede 120 · CTAs 180ms */
.hero-slide.is-active .eyebrow,
.hero-slide.is-active .display,
.hero-slide.is-active .lede,
.hero-slide.is-active .hero-slide__actions {
  animation: heroRise var(--t-slow) var(--ease-out) both;
}
.hero-slide.is-active .eyebrow            { animation-delay: 0ms; }
.hero-slide.is-active .display            { animation-delay: 60ms; }
.hero-slide.is-active .lede               { animation-delay: 120ms; }
.hero-slide.is-active .hero-slide__actions{ animation-delay: 180ms; }
@keyframes heroRise {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ==========================================================================
   HERO BRAND BANNER
   The Estate 108 lockup centred, the two group marks flanking it, over the
   slider running as ambient background. The stock hero overlay is weighted
   to the left for left-aligned slide copy; a centred lockup needs a
   symmetrical one, so it is replaced here.
   ========================================================================== */
.hero--brand .hero-slide::after {
  /* Deliberately light: the client wants the render to read, not a green wash.
     This no longer carries the text contrast on its own — the pool behind the
     lockup below does that — so it only keeps the header and the dots legible
     and stops the brightest slides blowing out at the edges. */
  background:
    linear-gradient(180deg,
      rgba(14, 42, 32, .40) 0%,
      rgba(14, 42, 32, .14) 30%,
      rgba(14, 42, 32, .10) 55%,
      rgba(14, 42, 32, .58) 100%);
}

/* A soft pool sized to the lockup, so the copy keeps its contrast while the
   rest of the render stays bright. isolation:isolate keeps the -1 inside this
   element's own stacking context — without it the pool would drop behind the
   slide image entirely and do nothing. */
.hero-brand__center {
  position: relative;
  isolation: isolate;
}
.hero-brand__center::before {
  content: "";
  position: absolute;
  /* Taller than the lockup and centred a little high: the gold eyebrow sits at
     the TOP of this block, and a pool centred on the block left it at 3.2:1
     while the lede in the middle sat at 11.7:1. Extending the ellipse upward
     brings the eyebrow into the core of the gradient. */
  inset: -30% -18%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(62% 64% at 50% 52%,
    rgba(4, 22, 16, .82) 0%,
    rgba(4, 22, 16, .66) 48%,
    rgba(4, 22, 16, .30) 76%,
    rgba(4, 22, 16, 0) 100%);
}

.hero-brand {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-items: center;
  gap: clamp(20px, 4vw, 72px);
  /* Tighter than before: the flanking marks are gone, so the banner no
     longer needs room for a three-part lockup. */
  padding: calc(var(--header-h) + clamp(16px, 4vh, 40px)) var(--sp-gutter) clamp(56px, 8vh, 96px);
  text-align: center;
  /* Let swipe/drag reach the slider everywhere except on the lockup itself. */
  pointer-events: none;
}
.hero-brand > * { pointer-events: auto; }

.hero-brand__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 46ch;
}
.hero-brand__center .eyebrow {
  margin-bottom: var(--sp-4);
  /* Gold, not the inherited .eyebrow green: measured against the real render,
     --green-600 came out at 1.16:1 here, i.e. invisible. Brand gold clears AA
     only because the scrim below holds this band dark — the colour and that
     top gradient stop are a pair. Don't lighten one without rechecking. */
  color: var(--gold);
  text-shadow: 0 1px 14px rgba(6, 18, 13, .85), 0 0 28px rgba(6, 18, 13, .6);
}

.hero-brand__center {
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 46ch;
}

/* The figures carry a touch more air than the letters so "108" does not read
   tighter than the word above it. */


.hero-brand__center .lede {
  margin: var(--sp-5) 0 0;
  max-width: 46ch;
  color: var(--on-green-2);
}

.hero-brand__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}

/* Entrance: the banner's lines rise in sequence. */
.hero-brand__center > * {
  animation: heroRise var(--t-slow) var(--ease-out) both;
}
.hero-brand__center .eyebrow        { animation-delay: 60ms; }
.hero-brand__center .lede           { animation-delay: 190ms; }
.hero-brand__actions                { animation-delay: 250ms; }

/* Dots stay clickable above the banner layer. */
.hero--brand .hero-dots { z-index: 4; }

@media (max-width: 860px) {
  .hero-brand { align-content: center; row-gap: clamp(30px, 6vh, 60px); }
}

/* Image honesty label. Sits over any image, always legible. */
.img-caption {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 3;
  background: rgba(14, 42, 32, .82);
  color: var(--cream);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  padding: 6px 10px;
  border-radius: var(--r-pill);
  pointer-events: none;
}

/* --- Dots: each is a progress bar ------------------------------------- */
.hero-dots {
  position: absolute;
  left: 50%;
  bottom: clamp(24px, 4vh, 44px);
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  gap: var(--sp-3);
}
.hero-dots button {
  position: relative;
  width: 56px;
  height: 44px;                 /* 44px touch target, 2px visible rule */
  display: flex;
  align-items: center;
  overflow: hidden;
}
.hero-dots button::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: rgba(247, 242, 232, .34);
}
.hero-dots button::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: var(--gold-ramp);
  transform: scaleX(0);
  transform-origin: left center;
}
.hero-dots button[aria-current="true"]::after {
  animation: dotFill 6s linear forwards;
}
.hero.is-paused .hero-dots button[aria-current="true"]::after {
  animation-play-state: paused;
}
@keyframes dotFill {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* --- Arrows ------------------------------------------------------------ */
.hero-arrow {
  position: absolute;
  top: 50%;
  z-index: 5;
  width: 52px; height: 52px;
  margin-top: -26px;
  border: 1px solid var(--line-on-green);
  border-radius: 50%;
  background: rgba(14, 42, 32, .34);
  transition: background-color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.hero-arrow--prev { left: clamp(10px, 2.4vw, 32px); }
.hero-arrow--next { right: clamp(10px, 2.4vw, 32px); }
.hero-arrow::before {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 10px; height: 10px;
  border-top: 1px solid var(--cream);
  border-right: 1px solid var(--cream);
}
.hero-arrow--next::before { transform: translate(-70%, -50%) rotate(45deg); }
.hero-arrow--prev::before { transform: translate(-30%, -50%) rotate(-135deg); }
.hero-arrow:active { transform: scale(.94); }

@media (hover: hover) and (pointer: fine) {
  .hero-arrow:hover {
    background: rgba(22, 56, 43, .72);
    border-color: var(--gold);
    transform: scale(1.05);
  }
  .hero-dots button:hover::after { transform: scaleX(.35); }
  .hero-dots button[aria-current="true"]:hover::after { transform: none; }
}


/* ==========================================================================
   10  PROJECT GRID & CARDS
   A card on cream is 1.08:1 against the page. It is defined by its border
   and its shadow, never by its fill.
   ========================================================================== */

.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: clamp(20px, 2.4vw, 36px);
}
.project-grid--single { grid-template-columns: minmax(0, 1fr); }

.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--ivory);
  border: 1px solid var(--line);           /* REQUIRED */
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);          /* REQUIRED */
  overflow: hidden;
  transition:
    transform    var(--t-fast) var(--ease-out),
    box-shadow   var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out);
}
.project-card:focus-within {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-card-hover);
}
.project-card:active { transform: scale(.985); }

.project-media {
  position: relative;
  aspect-ratio: 4 / 3;                     /* space reserved — no CLS */
  overflow: hidden;                        /* only the picture moves */
  background: var(--cream-deep);
}
/* A <picture> wrapper must fill the frame, or the img's height:100% has
   nothing to resolve against and the card collapses. */
.project-media picture {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.project-media img,
.project-media svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease-out);
}
.project-media::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 44%;
  background: linear-gradient(180deg, rgba(14, 42, 32, 0), rgba(14, 42, 32, .34));
  pointer-events: none;
}

/* --- Card slider: three times of day, crossfaded ------------------------
   Slides stack in the same frame; only opacity animates, so nothing reflows
   and the 4/3 aspect-ratio above keeps the space reserved (no CLS). */
.card-slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity 900ms var(--ease-out);
  will-change: opacity;
}
.card-slide[aria-hidden="true"] { visibility: hidden; transition: opacity 900ms var(--ease-out), visibility 0s linear 900ms; }
.card-slide.is-active { opacity: 1; visibility: visible; transition: opacity 900ms var(--ease-out), visibility 0s; }
.card-slide img { position: absolute; inset: 0; }

/* The label and the honesty caption are decoration: they must not punch dead
   holes through the stretched whole-tile link (see .project-card :has rule). */
.card-slide__label {
  position: absolute;
  left: 14px; bottom: 14px;
  z-index: 3;
  pointer-events: none;
  background: rgba(14, 42, 32, .82);
  color: var(--cream);
  font-family: var(--font-ui);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  padding: 6px 10px;
  border-radius: var(--r-pill);
}

/* Dots ARE interactive, so they sit above the stretched link's z-index 1. */
.card-slider__dots {
  position: absolute;
  top: 14px; right: 14px;
  z-index: 4;
  display: flex;
  gap: 8px;
}
.card-slider__dots button {
  width: 26px; height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: none;
  border: 0;
  cursor: pointer;
}
.card-slider__dots button::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgba(247, 242, 232, .55);
  box-shadow: 0 0 0 1px rgba(14, 42, 32, .35);
  transition: background-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.card-slider__dots button[aria-selected="true"]::before {
  background: var(--gold);
  transform: scale(1.35);
}
.card-slider__dots button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* The card's hover zoom would fight a crossfade mid-transition. */
.card-slider img { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .card-slide { transition: none; }
}

.project-meta {
  padding: clamp(20px, 2.2vw, 30px);
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
.project-meta .eyebrow { margin-bottom: var(--sp-2); }
/* h3 inherits --fs-xl (42px at desktop), which is a section-heading size, not
   a card size: in a ~320px card a four-word title wrapped to two lines. */
.project-meta h3 {
  margin-bottom: var(--sp-3);
  font-size: clamp(21px, 1.0vw + 17px, 28px);
  line-height: 1.2;
}
.project-meta h3 a {
  display: inline;
  background-image: var(--gold-ramp);
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size var(--t-base) var(--ease-out);
}
.project-meta p { color: var(--muted); font-size: var(--fs-sm); margin-bottom: var(--sp-5); }

.project-meta__foot {
  margin-top: auto;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-soft);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.project-meta__more {
  position: relative;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-700);
  padding-right: 26px;
}
.project-meta__more::after {
  content: "";
  position: absolute;
  right: 0; top: 50%;
  width: 16px; height: 1px;
  background: currentColor;
  transform-origin: left center;
  transition: transform var(--t-base) var(--ease-out);
}

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  padding: 6px 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--cream);
  color: var(--green-700);
  white-space: nowrap;
}
.status-chip::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--gold-deep);
}
.status-chip.is-upcoming { color: var(--green-700); border-color: var(--line-gold); }
.status-chip.is-upcoming::before { background: var(--gold-deep); }
.status-chip.is-complete { color: var(--muted); }
.status-chip.is-complete::before { background: var(--muted); }

/* The chip that sits ON the image needs a dark plate to stay legible. */
.project-media .status-chip,
.page-hero .status-chip {
  position: absolute;
  top: 14px; left: 14px;
  z-index: 3;
  background: rgba(14, 42, 32, .84);
  border-color: var(--line-on-green);
  color: var(--cream);
}
.project-media .status-chip.is-upcoming::before,
.page-hero .status-chip.is-upcoming::before { background: var(--gold); }
.project-media .status-chip.is-complete::before,
.page-hero .status-chip.is-complete::before { background: rgba(247, 242, 232, .7); }
/* Static + inline-flex left the chip taller than its line box, so the h1
   below started 9px inside it and the capitals grazed the chip's edge.
   Block-level with its own margin gives it a real row. */
.page-hero .status-chip {
  position: static;
  display: flex;
  width: fit-content;
  margin-bottom: var(--sp-5);
}

@media (hover: hover) and (pointer: fine) {
  .project-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card-hover);
    border-color: var(--line-strong);
  }
  .project-card:hover .project-media img,
  .project-card:hover .project-media svg { transform: scale(1.05); }
  .project-card:hover .project-meta__more::after { transform: scaleX(1.5); }
  .project-meta h3 a:hover { background-size: 100% 1px; }
}


/* ==========================================================================
   11  PRINCIPLES
   ========================================================================== */

.principles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(24px, 3vw, 56px);
}
.principle {
  padding-top: var(--sp-5);
  border-top: 2px solid var(--line-on-green);
}
.principle h3 { font-size: var(--fs-xl); margin-bottom: var(--sp-3); }
.principle p { font-size: var(--fs-sm); line-height: var(--lh-loose); }

.principle-num {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-num);
  line-height: 1;
  font-weight: 300;
  margin-bottom: var(--sp-4);
  background: var(--gold-ramp-v);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* On a green band the principles invert; on cream they use ink rules. */
.section--deep .principle { border-top-color: var(--line-on-green); }
.section--deep .principle h3 { color: var(--cream); }
.section--deep .principle p { color: var(--on-green-2); }
.section:not(.section--deep) .principle { border-top-color: var(--line); }
.section:not(.section--deep) .principle p { color: var(--muted); }


/* ==========================================================================
   12  PRESS STRIP
   ========================================================================== */

.press-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 4vw, 64px);
}
.press-logo {
  display: block;
  opacity: .62;
  filter: saturate(0);
  transition: opacity var(--t-base) var(--ease-out),
              filter  var(--t-base) var(--ease-out),
              transform var(--t-base) var(--ease-out);
}
.press-logo img,
.press-logo svg { height: 34px; width: auto; }

@media (hover: hover) and (pointer: fine) {
  .press-logo:hover { opacity: 1; filter: none; transform: translateY(-2px); }
}


/* ==========================================================================
   13  CTA BAND · CONTACT GRID · FORM
   ========================================================================== */

/* One of the page's permitted green bands. */
.cta-band {
  position: relative;
  background: var(--green-900);
  color: var(--on-green);
  padding-block: clamp(56px, 7vw, 104px);
  overflow: hidden;
}
.cta-band::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: var(--gold-ramp);
}
.cta-band .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(24px, 4vw, 64px);
  flex-wrap: wrap;
}
.cta-band__text { max-width: 60ch; }
.cta-band__text h2 { color: var(--cream); margin-bottom: var(--sp-3); }
.cta-band__text .lede { color: var(--on-green-2); margin-bottom: 0; }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.cta-band__direct {
  margin-top: var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--on-green-2);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
}
.cta-band__direct a {
  border-bottom: 1px solid var(--line-on-green);
  padding-bottom: 2px;
  transition: color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
}

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, .9fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
}
.contact-grid__aside {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  padding: clamp(22px, 2.6vw, 36px);
}
/* This used to be knocked down to --fs-xl: at the old 52px section size an h2
   wrapped "Call, write or visit" across three lines inside the card. After four
   rounds of heading reductions --fs-2xl is 41.9px, which wraps to two lines and
   does not overflow, so the aside now matches every other section heading. */
.contact-grid__aside dl { margin: 0; }
.contact-grid__aside dt {
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--gold-deep);
  font-weight: 600;
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line-soft);
}
.contact-grid__aside dt:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.contact-grid__aside dd {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-sm);
  color: var(--text-2);
  line-height: var(--lh-normal);
}
.contact-grid__aside dd a { border-bottom: 1px solid var(--line-gold); padding-bottom: 1px; }

/* --- Form -------------------------------------------------------------- */
.form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-5);
}
.form > .form-success { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field--full { grid-column: 1 / -1; }
.field label {
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-600);
}
.field label .req { color: var(--gold-deep); font-weight: 700; }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 48px;
  padding: 13px 16px;
  background: var(--ivory);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-2);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--fs-base);
  transition: border-color var(--t-fast) var(--ease-out),
              box-shadow   var(--t-fast) var(--ease-out),
              background-color var(--t-fast) var(--ease-out);
}
.field textarea { min-height: 140px; resize: vertical; line-height: var(--lh-normal); }
.field select { appearance: none; cursor: pointer; padding-right: 42px;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--green-700) 50%),
    linear-gradient(135deg, var(--green-700) 50%, transparent 50%);
  background-position: calc(100% - 22px) 22px, calc(100% - 16px) 22px;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.field select option { color: var(--ink); background: var(--ivory); }
.field input::placeholder,
.field textarea::placeholder { color: var(--muted); opacity: 1; }

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  border-color: var(--green-700);
  box-shadow: 0 0 0 3px rgba(22, 56, 43, .10);
}
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] { border-color: #9B2C1E; }

.field-error {
  display: none;
  font-size: var(--fs-xs);
  color: #8E2718;                  /* 6.3:1 on cream */
  padding-left: 18px;
  position: relative;
}
.field-error.is-visible { display: block; }
.field-error::before {
  content: "!";
  position: absolute;
  left: 0; top: 0;
  font-weight: 700;
}

.consent-row {
  grid-column: 1 / -1;
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  background: var(--cream-deep);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--sp-4);
}
.consent-row input[type="checkbox"] {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  margin-top: 2px;
  accent-color: var(--green-800);
  cursor: pointer;
}
.consent-row label { font-size: var(--fs-sm); color: var(--text-2); line-height: var(--lh-normal); cursor: pointer; }
.consent-row a { border-bottom: 1px solid var(--line-gold); }
.consent-row .field-error { margin-top: var(--sp-2); }

.form-actions {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-4);
}

.form-success {
  display: none;
  background: var(--ivory);
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold-deep);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  padding: clamp(22px, 2.6vw, 36px);
}
.form-success.is-visible { display: block; }
.form-success h3 { margin-bottom: var(--sp-3); }
.form-success p { color: var(--text-2); margin-bottom: 0; }

.honeypot {
  position: absolute !important;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

@media (hover: hover) and (pointer: fine) {
  .cta-band__direct a:hover { color: var(--gold); border-color: var(--gold); }
  .contact-grid__aside dd a:hover { color: var(--green-700); border-color: var(--green-700); }
  .field input:hover,
  .field select:hover,
  .field textarea:hover { border-color: var(--green-600); }
}


/* ==========================================================================
   14  FAQ · PROSE · TABLES · DISCLAIMER · RERA
   ========================================================================== */

.faq { display: flex; flex-direction: column; gap: var(--sp-3); }

.faq-item {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: border-color var(--t-fast) var(--ease-out),
              box-shadow   var(--t-fast) var(--ease-out);
}
.faq-item > summary {
  position: relative;
  list-style: none;
  cursor: pointer;
  padding: clamp(16px, 2vw, 22px) 56px clamp(16px, 2vw, 22px) clamp(16px, 2vw, 26px);
  min-height: 56px;
  font-family: var(--font-display);
  font-size: clamp(19px, 1.1vw + 15px, 25px);
  line-height: 1.3;
  color: var(--green-800);
  transition: background-color var(--t-fast) var(--ease-out);
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::marker { content: ""; }
.faq-item > summary::after {
  content: "";
  position: absolute;
  right: 24px; top: 50%;
  width: 11px; height: 11px;
  margin-top: -8px;
  border-right: 1px solid var(--green-700);
  border-bottom: 1px solid var(--green-700);
  transform: rotate(45deg);
  transition: transform var(--t-base) var(--ease-out);
}
.faq-item[open] > summary::after { transform: rotate(-135deg); margin-top: -3px; }
.faq-item > div,
.faq-item > p {
  padding: 0 clamp(16px, 2vw, 26px) clamp(18px, 2vw, 26px);
  color: var(--text-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-loose);
  max-width: 78ch;
}
.faq-item > div > p:last-child { margin-bottom: 0; }

/* --- Prose ------------------------------------------------------------- */
.prose { max-width: 74ch; color: var(--text); }
.prose > * + * { margin-top: var(--sp-4); }
.prose h2 { font-size: var(--fs-2xl); margin-top: var(--sp-7); }
.prose h3 { font-size: var(--fs-xl); margin-top: var(--sp-6); }
.prose h4 { margin-top: var(--sp-5); }
.prose h2, .prose h3, .prose h4 { margin-bottom: var(--sp-3); }
.prose p { line-height: var(--lh-loose); }
.prose strong { font-weight: 600; color: var(--green-800); }
.prose a {
  color: var(--green-700);
  border-bottom: 1px solid var(--line-gold);
  padding-bottom: 1px;
  transition: color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
}
.prose ul, .prose ol { margin-left: 0; }
.prose li + li { margin-top: var(--sp-2); }
.prose ul li,
.prose ol li { position: relative; padding-left: 26px; line-height: var(--lh-loose); }
.prose ul li::before {
  content: "";
  position: absolute;
  left: 2px; top: .68em;
  width: 8px; height: 1px;
  background: var(--gold-deep);
}
.prose ol { counter-reset: prose-ol; }
.prose ol li { counter-increment: prose-ol; }
.prose ol li::before {
  content: counter(prose-ol, decimal-leading-zero);
  position: absolute;
  left: 0; top: .1em;
  font-family: var(--font-ui);
  font-size: 11px;
  letter-spacing: .08em;
  color: var(--gold-deep);
}
.prose blockquote {
  margin: var(--sp-6) 0;
  padding: var(--sp-4) var(--sp-5);
  border-left: 2px solid var(--gold-deep);
  background: var(--cream-deep);
  border-radius: 0 var(--r-3) var(--r-3) 0;
  font-family: var(--font-display);
  font-size: var(--fs-md);
  color: var(--green-800);
}
.prose dl dt { font-weight: 600; color: var(--green-800); margin-top: var(--sp-4); }
.prose dl dd { margin: var(--sp-1) 0 0; color: var(--text-2); }

/* --- Tables: spec / connectivity / payment ----------------------------- */
.spec-table,
.connectivity-table,
.payment-table {
  width: 100%;
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  font-size: var(--fs-sm);
}
.spec-table caption,
.connectivity-table caption,
.payment-table caption {
  caption-side: top;
  text-align: left;
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--muted);
  padding-bottom: var(--sp-4);
  line-height: 1.5;
}
.spec-table th,
.connectivity-table th,
.payment-table th {
  text-align: left;
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  font-weight: 400;
  color: var(--cream);
  background: var(--green-800);
  padding: 14px 18px;
  white-space: nowrap;
}
.spec-table td,
.connectivity-table td,
.payment-table td {
  padding: 14px 18px;
  border-top: 1px solid var(--line-soft);
  color: var(--text-2);
  vertical-align: top;
}
.spec-table tbody tr:first-child td,
.connectivity-table tbody tr:first-child td,
.payment-table tbody tr:first-child td { border-top: 0; }
.spec-table td:first-child,
.connectivity-table td:first-child,
.payment-table td:first-child {
  color: var(--green-800);
  font-weight: 500;
  white-space: nowrap;
}
.spec-table td:last-child { color: var(--text-2); }
.connectivity-table td:last-child,
.payment-table td:last-child {
  font-family: var(--font-ui);
  font-size: var(--fs-xs);
  letter-spacing: .06em;
  color: var(--green-700);
  white-space: nowrap;
}
.spec-table tbody tr,
.connectivity-table tbody tr,
.payment-table tbody tr { transition: background-color var(--t-fast) var(--ease-out); }

@media (hover: hover) and (pointer: fine) {
  .prose a:hover { color: var(--green-800); border-color: var(--green-700); }
  .faq-item:hover { border-color: var(--line-strong); box-shadow: var(--shadow-card-hover); }
  .faq-item > summary:hover { background: var(--cream-deep); }
  .spec-table tbody tr:hover,
  .connectivity-table tbody tr:hover,
  .payment-table tbody tr:hover { background: var(--cream-deep); }
}

/* --- Disclaimer & RERA -------------------------------------------------- */
.disclaimer {
  background: var(--cream-deep);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: clamp(20px, 2.4vw, 32px);
  font-size: var(--fs-xs);
  line-height: var(--lh-loose);
  color: var(--muted);
}
.disclaimer h3 {
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-600);
  margin-bottom: var(--sp-3);
}
.disclaimer p + p { margin-top: var(--sp-3); }

.rera-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  background: var(--ivory);
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold-deep);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  font-size: var(--fs-xs);
  color: var(--text-2);
}
.rera-line strong {
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-600);
}
.rera-line a { border-bottom: 1px solid var(--line-gold); padding-bottom: 1px; }


/* ==========================================================================
   15  BREADCRUMBS · PAGE HERO · PROJECT TABS / BODY / NAV
   ========================================================================== */

.breadcrumbs { font-size: var(--fs-xs); color: var(--muted); }
.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.breadcrumbs li { display: flex; align-items: center; gap: var(--sp-2); }
.breadcrumbs li + li::before { content: "/"; color: var(--line-strong); }
.breadcrumbs a { transition: color var(--t-fast) var(--ease-out); }
.breadcrumbs [aria-current="page"] { color: var(--green-700); }

/* The project page's own hero. It IS a green band — it is the page's one. */
.page-hero {
  position: relative;
  padding-top: calc(var(--header-h) + clamp(40px, 6vw, 88px));
  padding-bottom: clamp(40px, 6vw, 88px);
  background: var(--green-800);
  color: var(--on-green);
  overflow: hidden;
  isolation: isolate;
}
.page-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 2px;
  background: var(--gold-ramp);
  opacity: .7;
}
.page-hero .breadcrumbs { color: var(--on-green-3); margin-bottom: var(--sp-5); }
.page-hero .breadcrumbs li + li::before { color: var(--line-on-green); }
.page-hero .breadcrumbs [aria-current="page"] { color: var(--gold); }
.page-hero h1 { color: var(--cream); margin-bottom: var(--sp-4); }
.page-hero .lede { color: var(--on-green-2); }
.page-hero__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-4);
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  /* Gold, at the client's request: these are the details a visitor acts on
     (phone, email, hours), so they get the accent rather than the muted
     cream the rest of the hero uses. */
  color: var(--gold);
}
.page-hero__meta a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.page-hero__meta a:hover,
.page-hero__meta a:focus-visible { color: var(--gold-hi); }


.project-tabs-wrap {
  position: sticky;
  top: var(--header-h);
  z-index: 40;
  background: var(--cream);
  border-bottom: 1px solid var(--line);
}
.project-tabs {
  display: flex;
  gap: clamp(8px, 2vw, 32px);
  overflow-x: auto;
  scrollbar-width: none;
}
.project-tabs::-webkit-scrollbar { display: none; }
.project-tab {
  position: relative;
  /* 2px of side padding left the "All" tab 27px wide. The underline is drawn
     edge to edge on this box, so padding widens the rule with it. */
  padding: 20px 10px;
  min-width: 48px;
  min-height: 48px;
  white-space: nowrap;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--muted);
  transition: color var(--t-fast) var(--ease-out);
}
.project-tab::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--gold-ramp);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--t-base) var(--ease-out);
}
.project-tab.is-active { color: var(--green-800); }
.project-tab.is-active::after { transform: scaleX(1); }

.project-body {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, .8fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
}
.project-body > aside {
  position: sticky;
  top: calc(var(--header-h) + 72px);
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  padding: clamp(20px, 2.4vw, 32px);
}
.project-body__panel[hidden] { display: none; }
.project-body__panel > * + * { margin-top: var(--sp-5); }
.project-body__actions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}
.project-body__actions .btn { width: 100%; }

.project-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1px;
  background: var(--line);
  border-block: 1px solid var(--line);
}
.project-nav a {
  display: block;
  background: var(--cream);
  padding: clamp(24px, 3vw, 44px) var(--sp-gutter);
  transition: background-color var(--t-base) var(--ease-out);
}
.project-nav__label {
  display: block;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  color: var(--muted);
  margin-bottom: var(--sp-2);
}
.project-nav__name {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  color: var(--green-800);
  transition: transform var(--t-base) var(--ease-out);
}
.project-nav a:last-child { text-align: right; }

@media (hover: hover) and (pointer: fine) {
  .breadcrumbs a:hover { color: var(--green-700); }
  .page-hero .breadcrumbs a:hover { color: var(--gold); }
  .project-tab:hover { color: var(--green-700); }
  .project-tab:hover::after { transform: scaleX(.5); }
  .project-nav a:hover { background: var(--cream-deep); }
  .project-nav a:hover .project-nav__name { transform: translateX(6px); }
  .project-nav a:last-child:hover .project-nav__name { transform: translateX(-6px); }
}


/* ==========================================================================
   16  AAVANA COMPONENTS
   price band · gallery · figure captions · amenities · plan & payment tabs
   ========================================================================== */

/* --- Price band: cream panel, gold hairline, never gold TEXT ----------- */
.price-band {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-4) var(--sp-6);
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  padding: clamp(20px, 2.6vw, 34px);
  position: relative;
  overflow: hidden;
}
.price-band::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 3px;
  background: var(--gold-ramp);
}
.price-band .eyebrow { margin-bottom: var(--sp-1); }
/* Matches the section-heading treatment exactly — same family, 300 weight,
   uppercase, same tracking and line-height — so the price reads as a heading
   rather than as a differently-styled one-off. `lining-nums` keeps the
   figures aligned; Jost's defaults are fine but this is load-bearing on a
   price, so it is stated rather than assumed. */
.price-band strong {
  display: block;
  /* Serif, matching the client's reference. Old-style figures are Cormorant's
     default and are what that reference shows — so unlike the rest of the site
     (where lining-nums is forced to stop "108" rendering as "1o8") this one
     keeps them on purpose. No uppercase: the serif reads as itself. */
  font-family: var(--font-price);
  font-weight: 500;
  font-size: clamp(29.3px, 3.4vw + 10.3px, 55.3px);
  line-height: 1.05;
  letter-spacing: .005em;
  text-transform: none;
  font-variant-numeric: oldstyle-nums;
  color: var(--green-800);
}
.price-band small {
  display: block;
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--muted);
  max-width: 46ch;
}

/* --- Contact rows (home contact block) ---------------------------------
   Icons are decorative (aria-hidden) and the label carries the meaning, so
   the ring may use the bright --gold. The glyph uses --gold-deep: --gold is
   1.95:1 on cream and a 20px mark in it reads washed out. */
.contact-rows {
  list-style: none;
  margin: clamp(28px, 3.4vw, 48px) 0 0;
  padding: 0;
  display: grid;
  gap: clamp(20px, 2.4vw, 32px);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.contact-row {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
}
.contact-row__icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  border: 1px solid var(--gold);
  border-radius: 50%;
  color: var(--gold-deep);
}
.contact-row__icon svg { width: 20px; height: 20px; fill: currentColor; display: block; }
.contact-row__body { min-width: 0; }
.contact-row__label {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--gold-deep);
  margin-bottom: 4px;
}
.contact-row__body a,
.contact-row__body p { font-size: var(--fs-base); margin: 0; }
.contact-row__body a { text-decoration: underline; text-underline-offset: 3px; }
.contact-row__body a:hover { color: var(--green-600); }
.contact-row__hours {
  display: block;
  margin-top: 6px;
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--muted);
}

/* --- Gallery ----------------------------------------------------------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: clamp(14px, 1.8vw, 26px);
}
.gallery--wide { grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); }

.gallery-item {
  position: relative;
  margin: 0;
  background: var(--ivory);
  border: 1px solid var(--line);          /* REQUIRED — ivory on cream is 1.08 */
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: transform   var(--t-fast) var(--ease-out),
              box-shadow  var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
}
.gallery-item > button,
.gallery-item > a {
  display: block;
  width: 100%;
  position: relative;
  overflow: hidden;                        /* only the picture scales */
  cursor: zoom-in;
}
.gallery-item img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform var(--t-slow) var(--ease-out);
}
.gallery-item--fixed img,
.gallery-item--cover img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.gallery-item:active { transform: scale(.99); }

/* Honest captions. Every interior render carries one. */
.figure-caption {
  display: block;
  padding: 12px clamp(12px, 1.4vw, 18px) 14px;
  font-family: var(--font-text);
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--muted);
  border-top: 1px solid var(--line-soft);
  background: var(--ivory);
}
.figure-caption strong {
  display: block;
  font-family: var(--font-ui);
  font-weight: 400;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-600);
  margin-bottom: 4px;
}

/* --- Amenities --------------------------------------------------------- */
.amenity-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(212px, 1fr));
  gap: var(--sp-3);
}
.amenity {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 56px;
  padding: 14px 18px;
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-700);
  transition: transform    var(--t-fast) var(--ease-out),
              box-shadow   var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
}
.amenity::before {
  content: "";
  flex: 0 0 auto;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--gold-ramp);
}

/* --- Plan / payment tab switcher --------------------------------------- */
.plan-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-5);
  padding: 6px;
  background: var(--cream-deep);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.plan-tabs::-webkit-scrollbar { display: none; }
.plan-tabs button {
  min-height: 44px;
  padding: 11px 22px;
  border-radius: var(--r-pill);
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--green-700);
  white-space: nowrap;
  transition: background-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.plan-tabs button[aria-selected="true"],
.plan-tabs button.is-active {
  background: var(--green-800);
  color: var(--cream);
}
.plan-tabs button:active { transform: scale(.97); }

.payment-table td:first-child { white-space: normal; max-width: 34ch; }
.payment-table tfoot td {
  border-top: 1px solid var(--line);
  font-size: var(--fs-xs);
  color: var(--muted);
  white-space: normal;
}

@media (hover: hover) and (pointer: fine) {
  .gallery-item:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card-hover);
    border-color: var(--line-strong);
  }
  .gallery-item:hover img { transform: scale(1.05); }
  .amenity:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-card-hover);
    border-color: var(--line-strong);
  }
  .plan-tabs button:hover { background: rgba(22, 56, 43, .08); }
  .plan-tabs button[aria-selected="true"]:hover,
  .plan-tabs button.is-active:hover { background: var(--green-700); }
}


/* ==========================================================================
   17  LIGHTBOX  (no library — see site.js)
   ========================================================================== */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 56px);
  background: rgba(14, 42, 32, .94);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-base-out) var(--ease-in),
              visibility 0s linear var(--t-base-out);
}
.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--t-base) var(--ease-out), visibility 0s;
}
.lightbox__figure {
  margin: 0;
  max-width: min(1200px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  transform: scale(.98);
  transition: transform var(--t-base) var(--ease-out);
}
.lightbox.is-open .lightbox__figure { transform: scale(1); }
.lightbox__img {
  max-width: 100%;
  max-height: 76vh;
  width: auto;
  height: auto;
  margin-inline: auto;
  border-radius: var(--r-2);
  box-shadow: var(--shadow-on-green);
  background: var(--green-900);
}
.lightbox__caption {
  color: var(--on-green-2);
  font-size: var(--fs-xs);
  text-align: center;
  max-width: 72ch;
  margin-inline: auto;
}
.lightbox__close,
.lightbox__nav {
  position: absolute;
  width: 48px; height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-on-green);
  border-radius: 50%;
  background: rgba(22, 56, 43, .6);
  color: var(--cream);
  font-size: 20px;
  line-height: 1;
  transition: background-color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.lightbox__close { top: clamp(12px, 2vw, 24px); right: clamp(12px, 2vw, 24px); }
.lightbox__nav--prev { left: clamp(8px, 2vw, 24px); top: 50%; margin-top: -24px; }
.lightbox__nav--next { right: clamp(8px, 2vw, 24px); top: 50%; margin-top: -24px; }
.lightbox__close:active,
.lightbox__nav:active { transform: scale(.94); }
body.lightbox-open { overflow: hidden; }

@media (hover: hover) and (pointer: fine) {
  .lightbox__close:hover,
  .lightbox__nav:hover { background: var(--green-700); border-color: var(--gold); }
}


/* ==========================================================================
   18  FOOTER — the site's deepest green, and its largest green area
   ========================================================================== */

.site-footer {
  background: var(--green-900);
  color: var(--on-green-2);
  padding-block: clamp(48px, 6vw, 88px) var(--sp-6);
  font-size: var(--fs-sm);
}

.footer-brands {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(14px, 2.4vw, 32px);
  padding-bottom: var(--sp-6);
  margin-bottom: var(--sp-7);
  border-bottom: 1px solid var(--line-on-green);
}
.footer-brands__label {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  color: var(--on-green-3);
  width: 100%;
  margin-bottom: var(--sp-2);
}
.footer-brands img { width: auto; }
.footer-brands .footer-brands__primary { height: clamp(40px, 4.4vw, 56px); }
/* Stanley's mark is a wide wordmark (3.73:1) against Estate 108's stacked
   lockup (2.59:1), so matching them by height alone leaves Stanley looking
   undersized. Sized up until the two cap-heights read as equal. Both are the
   metallic gold renders — the white Stanley mark clashed beside gold. */
.footer-brands .footer-brands__partner { height: clamp(24px, 2.7vw, 32px); opacity: 1; }

.footer-cols {
  display: grid;
  grid-template-columns: 1.4fr .8fr .8fr 1.2fr;
  gap: clamp(24px, 3vw, 56px);
  margin-bottom: var(--sp-7);
}
.footer-cols h2,
.footer-cols h3 {
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  font-weight: 400;
  color: var(--gold);                 /* gold on green-900 = 7.05:1 */
  margin-bottom: var(--sp-4);
}
.footer-cols p { color: var(--on-green-2); font-size: var(--fs-sm); line-height: var(--lh-loose); }
.footer-cols li + li { margin-top: var(--sp-3); }
.footer-cols a { transition: color var(--t-fast) var(--ease-out); }
.footer-cols address {
  font-style: normal;
  color: var(--on-green-2);
  line-height: var(--lh-loose);
  font-size: var(--fs-sm);
}
.footer-cols address strong { color: var(--cream); font-weight: 600; }
.footer-cols address a { border-bottom: 1px solid var(--line-on-green); }

.social { display: flex; gap: var(--sp-3); }
.social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid var(--line-on-green);
  border-radius: 50%;
  transition: background-color var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              transform var(--t-fast) var(--ease-out);
}
.social svg { width: 18px; height: 18px; fill: var(--cream); }

.legal-line {
  border-top: 1px solid var(--line-on-green);
  padding-top: var(--sp-6);
  font-size: var(--fs-xs);
  color: var(--on-green-3);
  line-height: var(--lh-loose);
}
.legal-line p { margin-bottom: var(--sp-3); max-width: 100ch; }
.legal-line__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  margin: var(--sp-5) 0;
}
.legal-line__links a {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  transition: color var(--t-fast) var(--ease-out);
}
.legal-line__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-on-green-soft);
}
/* Build credit — deliberately quiet, and it must not out-shout the client's
   own copyright sitting beside it. */
.legal-line__credit a {
  color: var(--on-green-2);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--t-fast) var(--ease-out);
}
.legal-line__credit a:hover,
.legal-line__credit a:focus-visible { color: var(--gold); }

/* The footer's RERA line sits on green, so it inverts. */
.site-footer .rera-line {
  background: rgba(247, 242, 232, .05);
  border-color: var(--line-on-green);
  border-left-color: var(--gold);
  box-shadow: none;
  color: var(--on-green-2);
  margin-bottom: var(--sp-6);
}
.site-footer .rera-line strong { color: var(--gold); }
.site-footer .rera-line a { border-bottom-color: var(--line-on-green); }

@media (hover: hover) and (pointer: fine) {
  .footer-cols a:hover,
  .legal-line__links a:hover { color: var(--gold); }
  .social a:hover { background: var(--green-700); border-color: var(--gold); transform: translateY(-2px); }
}


/* ==========================================================================
   19  COOKIE BANNER
   Both buttons carry equal visual weight. This must not become a dark
   pattern: same size, same shape, min-width 190px on both.
   ========================================================================== */

.cookie-banner {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 250;
  background: var(--ivory);
  border-top: 1px solid var(--line);
  box-shadow: 0 -8px 40px rgba(20, 32, 26, .12);
  transform: translate3d(0, 110%, 0);
  /* visibility, not just transform: a translated-away banner still holds its
     three controls in the tab order while aria-hidden="true" hides it from the
     a11y tree — a keyboard user tabs into buttons a screen reader denies exist.
     The 0s delay fires after the slide-out so the animation is still seen. */
  visibility: hidden;
  transition: transform var(--t-slow) var(--ease-out),
              visibility 0s linear var(--t-slow);
}
.cookie-banner.is-open {
  transform: translate3d(0, 0, 0);
  visibility: visible;
  transition: transform var(--t-slow) var(--ease-out), visibility 0s;
}
.cookie-banner .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
  padding-block: var(--sp-5);
}
.cookie-banner__text { flex: 1 1 420px; }
.cookie-banner h2 {
  font-family: var(--font-ui);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--track-micro);
  color: var(--green-600);
  margin-bottom: var(--sp-2);
}
.cookie-banner p { font-size: var(--fs-xs); color: var(--text-2); line-height: var(--lh-loose); margin: 0; }
.cookie-banner a { border-bottom: 1px solid var(--line-gold); }
.cookie-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.cookie-actions .btn { min-width: 190px; }

@media (hover: hover) and (pointer: fine) {
  .cookie-banner a:hover { color: var(--green-700); border-color: var(--green-700); }
}


/* ==========================================================================
   20  PAPER / IVORY SECTION VARIANT
   Legal pages and long-read panels. The whole site is already light, so
   .section-paper is now simply a raised ivory sheet on the cream ground —
   and, being a panel, it obeys the border + shadow rule.
   ========================================================================== */

.section-paper {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--shadow-card);
  padding: clamp(24px, 3.4vw, 56px);
  color: var(--ink);
}
.section-paper h2, .section-paper h3 { color: var(--green-800); }
.section-paper h5, .section-paper h6 { color: var(--green-600); }
.section-paper .principle-num { background: var(--gold-ramp-v); -webkit-background-clip: text; background-clip: text; color: transparent; }
.section-paper .rule { background: var(--line); }
.section-paper .faq-item { background: var(--cream); }
.section-paper .disclaimer { background: var(--cream); }
.section-paper .spec-table,
.section-paper .connectivity-table,
.section-paper .payment-table { background: var(--cream); }
.section-paper ::selection { background: rgba(22, 56, 43, .9); color: var(--cream); }


/* ==========================================================================
   21  RESPONSIVE
   Nothing below 320px may scroll sideways. Side gutters stay >= 16px.
   ========================================================================== */

@media (max-width: 1080px) {
  .footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .project-body { grid-template-columns: minmax(0, 1fr); }
  .project-body > aside { position: static; }
}

@media (max-width: 960px) {
  .contact-grid { grid-template-columns: minmax(0, 1fr); }
  .section-head { flex-direction: column; align-items: flex-start; gap: var(--sp-4); }
}

@media (max-width: 860px) {
  :root { --header-h: 64px; }
  .nav { display: none; }
  .mobile-toggle { display: flex; }
  .hero { min-height: min(78vh, 720px); }
  .hero-arrow { display: none; }
}

@media (max-width: 768px) {
  .form { grid-template-columns: minmax(0, 1fr); }
  .cta-band .container { flex-direction: column; align-items: flex-start; }
  .cta-band__actions .btn { flex: 1 1 auto; }
  .project-nav a:last-child { text-align: left; }
  .gallery { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
  .gallery--wide { grid-template-columns: minmax(0, 1fr); }
  .price-band { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 560px) {
  .footer-cols { grid-template-columns: minmax(0, 1fr); }
  .project-grid { grid-template-columns: minmax(0, 1fr); }
  .amenity-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
  .cookie-actions { width: 100%; }
  .cookie-actions .btn { flex: 1 1 100%; min-width: 0; }
  .hero-dots button { width: 40px; }
}

@media (max-width: 400px) {
  .btn { padding-inline: 20px; }
  .hero-slide__content .display { max-width: 100%; }
  .footer-brands { gap: var(--sp-4); }
  .table-scroll { margin-inline: calc(var(--sp-gutter) * -1); }
}


/* ==========================================================================
   22  REDUCED MOTION — a hard requirement, not a nicety.
   Every duration collapses, Ken Burns stops, autoplay is disabled in JS,
   smooth scrolling is off, and every reveal is simply visible.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal],
  [data-reveal].is-revealed,
  .reveal,
  .reveal.is-revealed {
    opacity: 1 !important;
    transform: none !important;
  }

  .hero-slide.is-active > img,
  .hero-slide.is-active picture > img { animation: none !important; transform: none !important; }

  .hero-dots button[aria-current="true"]::after { animation: none !important; transform: scaleX(1); }

  .hero-slide.is-active .eyebrow,
  .hero-slide.is-active .display,
  .hero-slide.is-active .lede,
  .hero-slide.is-active .hero-slide__actions { animation: none !important; opacity: 1; transform: none; }

  .project-card:hover,
  .gallery-item:hover,
  .amenity:hover,
  .btn:hover { transform: none !important; }
}


/* ==========================================================================
   23  PRINT — legal pages must print cleanly on white.
   ========================================================================== */

@media print {
  :root { --header-h: 0px; }

  html, body { background: #fff; color: #000; font-size: 11pt; }

  .site-header,
  .mobile-menu,
  .cookie-banner,
  .hero-arrow,
  .hero-dots,
  .project-tabs-wrap,
  .cta-band,
  .project-nav,
  .lightbox,
  .skip-link,
  .social,
  .press-strip { display: none !important; }

  .site-footer { background: #fff; color: #000; border-top: 1pt solid #000; }
  .site-footer h2, .site-footer h3, .site-footer .rera-line strong { color: #000; }
  .site-footer .rera-line { background: #fff; border-color: #000; }

  .section, .section--band, .section--deep, .section-paper, .page-hero {
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
    border: 0;
    padding-block: 12pt;
  }
  .section--deep *, .page-hero * { color: #000 !important; }

  h1, h2, h3, h4, h5, h6 { color: #000; page-break-after: avoid; }
  p, li, tr, .faq-item { page-break-inside: avoid; }

  .faq-item, .disclaimer, .rera-line, .spec-table, .connectivity-table,
  .payment-table, .gallery-item, .project-card, .price-band {
    box-shadow: none !important;
    border: 1pt solid #999 !important;
    background: #fff !important;
  }
  .spec-table th, .connectivity-table th, .payment-table th {
    background: #eee !important;
    color: #000 !important;
  }

  .faq-item > div, .faq-item > p { display: block !important; }
  [data-reveal], .reveal { opacity: 1 !important; transform: none !important; }

  a { color: #000; text-decoration: underline; }
  .prose a::after { content: " (" attr(href) ")"; font-size: 9pt; color: #444; }
}

/* ==========================================================================
   ENQUIRY BAND
   A second, shorter copy of the lead form that sits directly above the footer
   on every page, so a visitor never has to navigate to /contact to make
   contact. site.js binds every form[data-form="enquiry"], so this one is wired
   automatically and fires the same generate_lead conversion. The full form on
   /contact stays as it is; this band is deliberately not rendered there, to
   avoid two identical forms competing on one page.
   Sits on green so it reads as a deliberate break before the footer.
   ========================================================================== */
.enquiry-band {
  background: var(--green-800);
  color: var(--cream);
  padding-block: clamp(48px, 7vw, 88px);
  border-top: 1px solid var(--line-on-green);
}
/* 46ch is the right measure for this band's copy, but as a flex ROW two
   columns then split it into ~23ch each and the heading sat in a 232px box.
   One column keeps the measure and gives the heading its full width. */
.enquiry-band .section-head {
  max-width: 46ch;
  margin-bottom: var(--sp-6);
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
}
.enquiry-band .section-head > div { flex: 0 0 auto; max-width: 100%; }
.enquiry-band h2 { color: var(--cream); }
.enquiry-band .eyebrow { color: var(--gold); }
.enquiry-band .lede { color: var(--on-green-2); }

.enquiry-band .field label { color: var(--on-green-2); }
.enquiry-band .field label .req { color: var(--gold); }
.enquiry-band .field input,
.enquiry-band .field select,
.enquiry-band .field textarea {
  background: rgba(250, 247, 232, .06);
  border-color: var(--line-on-green);
  color: var(--cream);
}
.enquiry-band .field input::placeholder,
.enquiry-band .field textarea::placeholder { color: rgba(250, 247, 232, .45); }
.enquiry-band .field input:focus,
.enquiry-band .field select:focus,
.enquiry-band .field textarea:focus {
  background: rgba(250, 247, 232, .1);
  border-color: var(--gold);
}
/* The select's own option list is drawn by the OS, so it needs readable
   colours of its own rather than inheriting the translucent field. */
.enquiry-band .field select option { background: var(--green-900); color: var(--cream); }

.enquiry-band .consent-row {
  color: var(--on-green-2);
  /* .consent-row is filled --cream-deep for the light form on /contact. Inside
     the green band that fill stayed, putting near-white label text on cream at
     about 1.3:1. Clear it and use a translucent light wash instead. */
  background: rgba(247, 242, 232, .07);
  border-color: var(--line-on-green);
}
.enquiry-band .consent-row a { color: var(--gold); }
.enquiry-band .field-error { color: #FFB4A8; }
.enquiry-band .btn-primary {
  background: var(--cream);
  color: var(--green-900);
  border-color: var(--cream);
}
.enquiry-band .btn-primary:hover { background: var(--gold-hi); border-color: var(--gold-hi); }
.enquiry-band .form-success { color: var(--cream); border-color: var(--gold); }

.enquiry-band__alt {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line-on-green);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  align-items: center;
  font-size: var(--fs-sm);
  color: var(--on-green-2);
}
.enquiry-band__alt a { color: var(--cream); text-decoration: underline; text-underline-offset: 3px; }
.enquiry-band__alt a:hover { color: var(--gold); }

/* ==========================================================================
   PROJECT PAGE HERO — image behind the title
   The plain .page-hero is a flat green band. Project pages carry a render
   behind the title instead, so they need the image taken out of flow and a
   scrim over it: cream text on an unmodified photograph is not reliably
   readable, and the scrim is what keeps the contrast honest at AA.
   ========================================================================== */
.page-hero--project {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  min-height: clamp(360px, 58vh, 640px);
  /* Kept as the fallback if the render fails to load — the image is layered
     ABOVE it rather than behind. A negative z-index on the image did not
     reliably paint over this background once `isolation` created a stacking
     context, so the layers are explicit and positive instead. */
  background: var(--green-800);
}
.page-hero--project .page-hero__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.page-hero--project::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Cream over the lightest stone in these renders needs roughly .80 alpha of
     green-900 to clear 4.5:1, and the text block sits across the lower half,
     so the band under it is near-opaque. */
  background: linear-gradient(180deg,
              rgba(1, 45, 32, .42) 0%,
              rgba(1, 45, 32, .68) 38%,
              rgba(1, 45, 32, .90) 68%,
              rgba(1, 45, 32, .97) 100%);
}
.page-hero--project > .container {
  position: relative;
  z-index: 2;
  width: 100%;
}
.page-hero--project .page-hero__loc {
  font-family: var(--font-ui);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  font-size: var(--fs-label);
  color: var(--on-green-2);
  margin: var(--sp-5) 0 var(--sp-3);
}
.img-caption--hero {
  position: absolute;
  right: var(--sp-gutter);
  bottom: var(--sp-4);
  z-index: 2;
}

/* Two-up gallery for wide elevation renders — at three-up a 16:9 elevation is
   too small to read the architecture. */
.gallery--two { grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); }

/* ==========================================================================
   WHOLE-TILE CLICK TARGET
   The card title is the one real link; this stretches its hit area over the
   whole card. Deliberately NOT a wrapping <a> or a JS click handler on the
   article: one link keeps the accessibility tree and the crawl honest, the
   link text stays the project name rather than the whole card's text, and
   middle-click / cmd-click / "open in new tab" all still behave.

   Scoped with :has() to cards that actually contain a project link —
   featured.html reuses .project-card for press items that are not clickable,
   and they must not get a pointer cursor or a stretched hit area.
   ========================================================================== */
.project-card:has(h3 a[href^="/projects/"]) { position: relative; }
.project-card:has(h3 a[href^="/projects/"]) h3 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}
/* Keep the focus ring on the card, not on the few words of the title. */
.project-card:has(h3 a[href^="/projects/"]):focus-within {
  outline: 2px solid var(--gold-deep);
  outline-offset: 3px;
}
.project-card:has(h3 a[href^="/projects/"]) h3 a:focus-visible { outline: none; }
/* The chip and the caption are decorative labels, not separate targets. They
   paint above the image (z-index 3) but must not intercept the pointer, or
   they punch a dead hole through the stretched tile link. */
.project-card .status-chip,
.project-card .img-caption { pointer-events: none; }

@media (hover: hover) and (pointer: fine) {
  .project-card:has(h3 a[href^="/projects/"]) { cursor: pointer; }
}

/* ==========================================================================
   SPLIT-TEXT HEADLINE REVEAL
   The signature effect on the client's other site (GSAP SplitText): display
   headlines resolve character by character from below a mask. Rebuilt here in
   plain CSS + a few lines of JS rather than loading GSAP + ScrollTrigger +
   SplitText + Lenis — roughly 150KB of library on a page whose Core Web Vitals
   feed an ad Quality Score.

   The mask is the point: each character sits inside an overflow:hidden span and
   rises into it, so the letters appear to be revealed rather than to fade.
   ========================================================================== */
.split-line {
  display: block;
  overflow: hidden;
  /* A descender clipped by overflow:hidden looks like a rendering bug, so the
     line box is opened up and pulled back by the same amount. */
  padding-block: 0.12em;
  margin-block: -0.12em;
}

/* Characters are grouped into words. Without the word wrapper each character is
   an independent inline-block, so the heading's min-content width collapses to
   one letter and a flex or grid column shrinks it to a character per line. */
.split-word {
  display: inline-block;
  white-space: nowrap;
}

/* Selectors are `.split-word > .split-char`, not `.split-char` alone: the base
   rule `.display span { display: block }` is one class plus one element, which
   outranks a single class — a bare `.split-char` lost and every character
   became a full-width block. */
.split-word > .split-char {
  display: inline-block;
  white-space: pre;
  transform: translateY(105%);
  opacity: 0;
  will-change: transform, opacity;
}
.js-on .split-ready .split-word > .split-char {
  transition:
    transform var(--t-slow) var(--ease-out),
    opacity   var(--t-base) linear;
  transition-delay: var(--char-delay, 0ms);
}
.split-ready.is-revealed .split-word > .split-char,
html:not(.js-on) .split-word > .split-char {
  transform: translateY(0);
  opacity: 1;
}

/* Scroll-linked parallax on project and hero media. Small on purpose — the
   reference site's is subtle, and a large offset reads as drift. */
.parallax-media { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  .split-word > .split-char {
    transform: none !important;
    opacity: 1 !important;
    transition: none !important;
  }
  .parallax-media { transform: none !important; }
}

/* Lining figures wherever the display face carries a number. Kept from the
   Cormorant era (its old-style figures rendered the brand name as "1o8") and
   still correct for Jost, whose default figures are lining anyway. */
.display,
h1, h2, h3,
.principle-num,
.page-hero__loc {
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1, "onum" 0;
}

/* ==========================================================================
   PULL QUOTE
   Used for the founding-team statement on the About page. Set in the display
   face, but lighter and italic so it reads as speech rather than as another
   section heading competing with the h2 above it.
   ========================================================================== */
.pull-quote {
  margin: clamp(40px, 6vw, 72px) 0 0;
  padding-left: clamp(20px, 3vw, 40px);
  border-left: 2px solid var(--gold);
  max-width: 34ch;
}
.pull-quote blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(1.4rem, 2.4vw, 2.1rem);
  line-height: 1.32;
  color: var(--green-800);
  text-transform: none;      /* the display face is uppercase by default */
  letter-spacing: 0;
}
.pull-quote figcaption {
  margin-top: var(--sp-4);
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
  color: var(--muted);
}
.pull-quote figcaption strong {
  display: block;
  color: var(--green-700);
  font-weight: 500;
}
.section--deep .pull-quote blockquote { color: var(--cream); }
.section--deep .pull-quote figcaption strong { color: var(--gold); }

/* The honesty label that trails a gallery caption ("Artist's impression.").
   Set apart from the descriptive half of the caption so a reader can tell the
   difference between what the picture shows and what the picture *is*. */
.img-caption-inline {
  display: inline;
  color: var(--green-600);
  font-style: italic;
  white-space: nowrap;
}

/* A row of buttons outside the .cta-band context (project pages use it under
   the enquire heading). Mirrors .cta-band__actions so the two read alike. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

/* Checked list for "what was delivered". No emoji, no icon font — a drawn
   mark so it scales with the text and inherits colour. */
.tick-list {
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
  display: grid;
  gap: var(--sp-3);
}
.tick-list li {
  position: relative;
  padding-left: 1.9em;
  line-height: var(--lh-normal);
}
.tick-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 0.62em;
  height: 0.34em;
  border-left: 1.5px solid var(--gold-deep);
  border-bottom: 1.5px solid var(--gold-deep);
  transform: rotate(-45deg);
}
.section--band .tick-list li::before,
.section--deep .tick-list li::before { border-color: var(--gold); }

/* --- Enquiry band corrections ------------------------------------------
   .field is a flex column, so a button inside a .field--full stretched to the
   full grid width (1216px on desktop) and read as a banner rather than a
   control. Pin it to its own width and align it to the start of the form.
   The consent label also needs the checkbox on the first text line rather
   than stacked above it. */
.enquiry-band .form__submit {
  align-items: flex-start;
}
.enquiry-band .form__submit .btn {
  width: auto;
  min-width: 220px;
  justify-content: center;
}
.enquiry-band .consent-row > label {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  cursor: pointer;
  line-height: var(--lh-normal);
}
.enquiry-band .consent-row input[type="checkbox"] {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 0.15em;
  accent-color: var(--gold);
}

/* The Aavana project page uses the development's own wordmark as its h1.
   Sized by width so the mark keeps its 2.08:1 proportion, with the same
   optical weight as the display type it replaces. */
.project-wordmark {
  margin: 0 0 var(--sp-4);
  line-height: 1;
}
.project-wordmark img {
  display: block;
  width: clamp(160px, 20vw, 265px);
  height: auto;
}

/* Brand tagline that sits under the wordmark as part of the lockup, set as
   live text rather than baked into the PNG so it stays crisp and selectable.
   Serif, to match the tagline in the brand artwork. The pipes are decoration:
   hidden from assistive tech so the line reads "Live Invest Belong". */
.project-wordmark + .wordmark-tagline {
  margin: calc(var(--sp-2) * -1) 0 var(--sp-5);
  font-family: var(--font-price);
  /* Sized to sit inside the mark's width, as it does in the brand artwork,
     rather than out-measuring the wordmark it belongs to. */
  font-size: clamp(13px, .75vw + 9.5px, 17px);
  font-weight: 400;
  letter-spacing: .06em;
  color: var(--aavana-gold);               /* matches the mark · 5.86:1 on the green-800 hero: AA */
  width: clamp(160px, 20vw, 265px);        /* exactly the mark's width */
  text-align: center;
}
.wordmark-tagline span {
  padding-inline: .3em;
  color: rgba(208, 180, 112, .5);
}

/* ==========================================================================
   FULL-BLEED MAP (contact page)
   Full width by design — the client asked for the map to run edge to edge.
   The facade is what ships; the Google iframe replaces it only on request.
   ========================================================================== */
.map-band {
  background: var(--cream-deep);
  padding-block: clamp(48px, 7vw, 88px) 0;
  border-top: 1px solid var(--line);
}
.map-band .section-head { margin-bottom: clamp(28px, 4vw, 48px); }

.map-frame {
  position: relative;
  width: 100%;
  /* Tall enough to be usable, capped so it never swallows a short screen. */
  height: clamp(340px, 62vh, 620px);
  background: var(--green-900);
  overflow: hidden;
}
.map-frame iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
.map-frame__facade {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding: var(--sp-6) var(--sp-gutter);
  text-align: center;
  color: var(--on-green-2);
  /* A hint of the coastline so the panel reads as a map, not an error state. */
  background:
    radial-gradient(120% 90% at 30% 20%, rgba(12, 85, 64, .55) 0%, transparent 60%),
    radial-gradient(90% 80% at 80% 90%, rgba(138, 101, 32, .30) 0%, transparent 60%),
    var(--green-900);
}
.map-frame__note { max-width: 46ch; margin: 0; font-size: var(--fs-sm); }
.map-frame__alt { margin: 0; font-size: var(--fs-sm); }
.map-frame__alt a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }
.map-frame__addr {
  margin: 0;
  font-style: normal;
  font-size: var(--fs-sm);
  color: var(--cream);
  line-height: var(--lh-normal);
}
