/* =============================================================================
   THE ROOTS SADAHALLI — "Datum"
   Bespoke stylesheet for sites/the-roots-sadahalli. SVAM Realty
   (SRK Infra Projects Private Limited), 100 row villas at Sadahalli.

   DESIGN INTENT
   A measured, structural, all-sans record sheet. The whole evidence base of
   this project is filings and dimensions, so the page is built like a filing:
   flush-left display type, a numbered section index, hairline rules instead of
   shadows, square corners everywhere, tabular numerals wherever a number
   appears, and wide data tables that break out past the reading measure while
   the prose stays in a 44rem column. Nothing decorative carries meaning.

   PALETTE
   The nine canonical brand tokens below are copied verbatim from
   builders/svam-realty/svam-realty.json -> branding.colors. No aliases, no
   raw colour literals outside :root, tints and translucency via color-mix over
   those nine. --state-success / --state-error are the one sanctioned
   exception, for form validation only.

   THE TERTIARY TRAP, READ THIS BEFORE EDITING
   On this builder --brand-tertiary is 0xF3FAFF, a near-WHITE pale blue — not a
   deep blue like most of the fleet. It is a GROUND on light bands and an INK
   on dark bands. It can never be ink on a light band (1.05:1 on white).
   Likewise --dark-tertiary 0xd8d8d8 is a light grey: hairline on light,
   ink on dark, never ink on light (1.43:1 on white).

   CONTRAST LEDGER (computed, sRGB, WCAG 2.1)
     0x171717 on 0xffffff 17.93 | on 0xF3FAFF 17.01 | on 0xf8f8f8 16.88
     0x4a4a4a on 0xffffff  8.86 | on 0xF3FAFF  8.41
     0x18547C on 0xffffff  8.08 | on 0xF3FAFF  7.67   <- all accent TEXT on light
     0x237CB6 on 0xffffff  4.54 | on 0xF3FAFF  4.30   <- RULES AND FILLS ONLY,
                                                      never small text on light
     0xffffff on 0x171717 17.93 | 0xF3FAFF on 0x171717 17.01
     0xd8d8d8 on 0x171717 12.58 | on 0x18547C 5.67    <- muted ink on dark
     0xffffff on 0x18547C  8.08 | 0xF3FAFF on 0x18547C 7.67
     mix(--brand-primary 55%, --light-secondary) = 0x86b7d7 on 0x171717 8.34
     mix(--light-secondary 62%, transparent) over 0x171717 = 0xa7a7a7, 7.45
     mix(--light-secondary 55%, transparent) over 0x171717 = 0x979797, 6.14
   Every figure quoted in a comment below comes from that ledger.

   FONTS
   Pure system stack. No @font-face, no external font URL, no bytes on the
   wire. The theme's voice is scale, tracking, weight and rhythm, not a face.
============================================================================= */

/* ── 1. TOKENS ───────────────────────────────────────────────────────────── */

:root {
  /* The nine canonical brand tokens — builders/svam-realty/svam-realty.json */
  --brand-primary:   #237CB6;
  --brand-secondary: #18547C;
  --brand-tertiary:  #F3FAFF;
  --dark-primary:    #171717;
  --dark-secondary:  #4a4a4a;
  --dark-tertiary:   #d8d8d8;
  --light-primary:   #f8f8f8;
  --light-secondary: #ffffff;
  --light-tertiary:  #eeeeee;

  /* Form validation only. Folding these into the brand hue costs the form its
     red/green affordance, which is an accessibility regression. */
  --state-success: #166534;
  --state-error:   #991b1b;

  /* Non-colour knobs. */
  --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
               "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
               "Liberation Mono", monospace;

  --radius: 0;                                 /* square corners, throughout */
  --hair:   1px;                               /* the only rule weight but 2px */
  --shell:  1160px;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --rhythm: clamp(3rem, 6.5vw, 5rem);
  --measure: 44rem;
  --navh:   66px;


  /* Aliases for the generated related-projects block, which reads
     --font-body / --font-headline / --font-display. Without these it
     falls back to Georgia and breaks the page's type. */
  --font-body: var(--font-sans);
  --font-display: var(--font-sans);
  --font-headline: var(--font-sans);
}

/* ── 2. RESET ────────────────────────────────────────────────────────────── */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

/* Colour is set ONCE, on body. No global `p {}` / `strong {}` colour rule
   exists anywhere in this sheet — that is the single most repeated bug in this
   fleet (a global dark ink on <strong> renders ~1.3:1 inside a dark band).
   Ink is set on the container that owns the ground, and inline elements
   inherit it. */
body {
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.68;
  color: var(--dark-primary);
  background: var(--light-secondary);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* This page is full of unbreakable 37-character strings — RERA ids, the
     BIAAPA commencement-certificate number, PIDs. At 360px one of them ran
     16px past the hero, where overflow:hidden simply cut the digits off.
     break-word only ever splits a word that cannot otherwise fit. */
  overflow-wrap: break-word;
  /* NO overflow-x:hidden here. It would make <body> a scroll container and
     silently break position:sticky on #nav. Sideways bleed is prevented at
     source instead: every wide child (.table-wrap, .gallery-grid, .plan-grid)
     scrolls or wraps inside its own box. */
}

img { max-width: 100%; height: auto; display: block; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button { background: none; border: 0; font: inherit; color: inherit; cursor: pointer; }
input, select, textarea { font: inherit; color: inherit; }
table { border-collapse: collapse; }
address { font-style: normal; }
strong { font-weight: 700; }        /* weight only — colour is NEVER set here */
em { font-style: italic; }
p:empty { display: none; }          /* .closing-cta ships an empty <p> */

/* Focus is visible on every ground this sheet paints. Light grounds get
   --brand-primary (4.54:1 on white, 4.30:1 on the pale-blue band — both clear
   the 3:1 non-text minimum); dark grounds are overridden per band below. */
:focus-visible {
  outline: 2px solid var(--brand-primary);
  outline-offset: 3px;
}

/* ── 3. TYPE ─────────────────────────────────────────────────────────────── */

h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.022em;          /* tight display tracking = the Datum voice */
  text-wrap: balance;
}
h1 { font-size: clamp(2.05rem, 5.2vw, 3.3rem); }
h2 { font-size: clamp(1.5rem, 3.1vw, 2.15rem); }
h3 { font-size: clamp(1.1rem, 1.9vw, 1.3rem); line-height: 1.3; letter-spacing: -0.012em; }
h4 { font-size: 1.02rem; line-height: 1.35; letter-spacing: -0.008em; }

code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  padding: 0.1em 0.36em;
  /* A 7% near-black tint on white = 0xefefef; body ink on it is 15.59:1.
     Every <code> on this site is a RERA / sanction number inside light
     prose — there is no <code> in any dark band. */
  background: color-mix(in srgb, var(--dark-primary) 7%, var(--light-secondary));
  border: var(--hair) solid var(--dark-tertiary);
  word-break: break-word;            /* RERA ids are 37 unbroken characters */
}

/* Micro-label: 800 weight, wide tracking, uppercase. Used for the section
   index, table heads, stat labels and footer column heads — the sheet's
   recurring structural mark. */
.section-label {
  font-size: 0.71rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--brand-secondary);     /* 8.08:1 on white — brand-primary would
                                        be 4.30 on the pale band, too thin for
                                        11px text, so the SECONDARY carries it */
}

.section-title {
  margin-top: 0.7rem;
  color: var(--dark-primary);
  max-width: 24ch;
}

/* The "gold divider" of the generated markup is a plain 2px brand rule here —
   no gradient, no gold. It is the section mark, nothing more. */
.gold-divider {
  width: 56px;
  height: 2px;
  background: var(--brand-primary);
  margin-top: 1rem;
}

/* ── 4. LAYOUT PRIMITIVES ────────────────────────────────────────────────── */

/* `.container` is a bare max-width box: it is used both inside .prose-inner
   (where it is already inside the shell and must not inset again) and as the
   direct child of #contact (which supplies its own padding-inline). */
.container {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
}

#main-content { display: block; }

/* Anchored section ids must clear the sticky nav. */
#hero, #faq, #contact, [id^="section-"] {
  scroll-margin-top: calc(var(--navh) + 14px);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 2000;
}
.skip-link:focus {
  left: 0;
  padding: 0.8rem 1.3rem;
  background: var(--dark-primary);
  color: var(--light-secondary);     /* 17.93:1 */
  font-weight: 650;
  outline: 2px solid var(--brand-tertiary);
  outline-offset: -6px;
}

/* ── 5. NAVIGATION ───────────────────────────────────────────────────────── */

#nav {
  position: sticky;
  top: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: var(--navh);
  padding-inline: var(--gutter);
  background: var(--light-secondary);
  /* A rule, not a shadow. The scrolled state changes the rule's COLOUR, never
     its height, so the nav cannot shift layout mid-scroll. */
  border-bottom: var(--hair) solid var(--dark-tertiary);
  transition: border-color 0.18s ease;
}
#nav.scrolled { border-bottom: 2px solid var(--brand-primary); margin-bottom: -1px; }

.nav-logo {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-right: auto;
  min-width: 0;
}

.brand-logo-img {
  width: 40px;
  height: 40px;
  border-radius: var(--radius);
  flex: 0 0 auto;
}

/* NOT a flex container. A flex parent discards the whitespace text node
   between the two spans, and Chrome's accessible-name computation then reads
   the lockup as "SVAM RealtyThe Roots Sadahalli". Block children keep that
   text node in the DOM and the name keeps its space. */
.brand-text { display: block; line-height: 1.12; min-width: 0; }
.brand-developer {
  display: block;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-secondary);     /* 8.08:1 on the white nav */
}
.brand-project {
  display: block;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.012em;
  color: var(--dark-primary);        /* 17.93:1 */
}

.nav-links { display: none; }        /* mobile-first: shown at >1024 (§16) */
.nav-links a {
  display: inline-block;
  padding: 0.3rem 0;
  font-size: 0.85rem;
  font-weight: 550;
  color: var(--dark-secondary);      /* 8.86:1 on white */
  border-bottom: 2px solid transparent;
}
.nav-links a:hover,
.nav-links a:focus-visible {
  color: var(--brand-secondary);     /* 8.08:1 — the hover state is DARKER than
                                        the rest state, never lighter */
  border-bottom-color: var(--brand-primary);
}

.nav-cta {
  display: none;                     /* shown at >=520px (§16) */
  padding: 0.58rem 1.1rem;
  font-size: 0.83rem;
  font-weight: 650;
  letter-spacing: 0.01em;
  background: var(--brand-secondary);
  color: var(--light-secondary);     /* 8.08:1 */
  border-radius: var(--radius);
}
.nav-cta:hover,
.nav-cta:focus-visible { background: var(--dark-primary); }  /* 17.93:1 */

.hamburger {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 42px;
  height: 36px;
  padding: 9px 8px;
  flex: 0 0 auto;
  /* 4.54:1 border — a ghost control needs a 3:1 boundary to be perceivable. */
  border: var(--hair) solid var(--brand-primary);
  border-radius: var(--radius);
}
.hamburger span {
  display: block;
  height: 2px;
  background: var(--dark-primary);
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.hamburger:hover { background: var(--brand-tertiary); }   /* bars stay 17.01:1 */
.hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger.open span:nth-child(2) { opacity: 0; }
.hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

#mobile-menu {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1500;
  flex-direction: column;
  padding: calc(var(--navh) + 0.5rem) var(--gutter) 2rem;
  background: var(--light-secondary);
  overflow-y: auto;
  overscroll-behavior: contain;
}
#mobile-menu.open { display: flex; }
#mobile-menu a {
  padding: 0.95rem 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--dark-primary);        /* 17.93:1 */
  border-bottom: var(--hair) solid var(--dark-tertiary);
}
#mobile-menu a:hover,
#mobile-menu a:focus-visible { color: var(--brand-secondary); }

.menu-close {
  position: absolute;
  top: 0.8rem;
  right: var(--gutter);
  width: 40px;
  height: 40px;
  font-size: 1.7rem;
  line-height: 1;
  color: var(--dark-primary);
  border: var(--hair) solid var(--brand-primary);
  border-radius: var(--radius);
}
.menu-close:hover { background: var(--brand-tertiary); }

/* Selector raised to (1,1,1) on purpose: `#mobile-menu a` is (1,0,1) and would
   otherwise repaint this CTA near-black on brand blue — 2.22:1. Specificity,
   not !important. */
#mobile-menu .menu-cta {
  margin-top: 1.4rem;
  padding: 0.85rem 1.2rem;
  text-align: center;
  font-weight: 650;
  background: var(--brand-secondary);
  color: var(--light-secondary);     /* 8.08:1 */
  border-bottom: 0;
}
#mobile-menu .menu-cta:hover,
#mobile-menu .menu-cta:focus-visible {
  background: var(--dark-primary);   /* 17.93:1 */
  color: var(--light-secondary);
}

/* ── 6. BUTTONS ──────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  padding: 0.76rem 1.5rem;
  border: 1.5px solid transparent;
  border-radius: var(--radius);
  font-size: 0.88rem;
  font-weight: 650;
  letter-spacing: 0.015em;
  line-height: 1.25;
  text-align: center;
  transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

/* Primary. Named "gold" by the generator; it is the brand blue here. */
.btn-gold {
  background: var(--brand-secondary);
  border-color: var(--brand-secondary);
  color: var(--light-secondary);     /* 8.08:1 */
}
.btn-gold:hover,
.btn-gold:focus-visible {
  background: var(--dark-primary);
  border-color: var(--dark-primary);
  color: var(--light-secondary);     /* 17.93:1 — hover gains contrast */
}

/* Ghost for DARK grounds (hero, page hero). */
.btn-outline {
  color: var(--light-secondary);
  border-color: color-mix(in srgb, var(--light-secondary) 55%, transparent);
}                                    /* 0x979797 over 0x171717 = 6.14:1 boundary */
.btn-outline:hover,
.btn-outline:focus-visible {
  border-color: var(--light-secondary);
  background: color-mix(in srgb, var(--light-secondary) 12%, transparent);
  color: var(--light-secondary);     /* white on the composited 0x333 = 12.63:1 */
}

/* Ghost for LIGHT grounds (prose .cta-row). The border is --brand-primary, not
   --dark-tertiary: a 0xd8d8d8 boundary is 1.43:1 on white and fails the 3:1
   non-text minimum — that is how this fleet once shipped an invisible button. */
.btn-outline-dark {
  color: var(--brand-secondary);     /* 8.08:1 white / 7.67:1 pale band */
  border-color: var(--brand-primary);/* 4.54:1 / 4.30:1 boundary */
}
.btn-outline-dark:hover,
.btn-outline-dark:focus-visible {
  background: var(--brand-secondary);
  border-color: var(--brand-secondary);
  color: var(--light-secondary);     /* 8.08:1 */
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* ── 7. HOME HERO (dark band) ────────────────────────────────────────────── */

#hero {
  position: relative;
  background: var(--dark-primary);
  color: var(--dark-tertiary);       /* 12.58:1 — the band's INHERITED ink, so
                                        <strong>, <em> and every unstyled child
                                        inherit a light colour, never a dark one */
  overflow: hidden;
}
.hero-bg { position: absolute; inset: 0; z-index: 0; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; }

/* z-index 1 puts the scrim ABOVE the image (z-index 0), not under it. A scrim
   that paints under its image is a silent, validator-invisible fleet bug. */
.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Worst case — a fully white photograph under the 80% stop — composites to
     0x454545: white 9.59:1, --dark-tertiary 6.73:1. Both clear AA. */
  background: linear-gradient(
    100deg,
    color-mix(in srgb, var(--dark-primary) 93%, transparent) 0%,
    color-mix(in srgb, var(--dark-primary) 80%, transparent) 52%,
    color-mix(in srgb, var(--dark-primary) 34%, transparent) 100%
  );
}

.hero-content {
  position: relative;
  z-index: 2;
  width: min(var(--shell), 100% - 2 * var(--gutter));
  margin-inline: auto;
  padding-block: clamp(2.75rem, 7vw, 5.25rem);
}

.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1.1rem;
  font-size: 0.71rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* --brand-primary is only 3.95:1 on this ground and this is 11px text; the
     lifted mix is 0x86b7d7 = 8.34:1 and still reads as the brand hue. */
  color: color-mix(in srgb, var(--brand-primary) 55%, var(--light-secondary));
}
.hero-badge::before {
  content: "";
  width: 30px;
  height: 2px;
  background: var(--brand-primary);
  flex: 0 0 auto;
}

.hero-title {
  color: var(--light-secondary);     /* 17.93:1 */
  max-width: 18ch;
}

.hero-sub {
  margin-top: 1rem;
  max-width: 62ch;
  font-size: 1.02rem;
  color: var(--dark-tertiary);       /* 12.58:1 */
}
/* Emphasis on a dark band must go BRIGHTER than its surroundings, never
   darker. This is the donor theme's live bug, inverted. */
.hero-sub strong { color: var(--light-secondary); }

.hero-btns {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.7rem;
}

/* The stat strip is a hairline grid. The rules are drawn on the CELLS
   (right + bottom, with the container supplying top + left), never as gaps over
   a container background: auto-fit collapses empty COLUMNS but not the empty
   cells of a short last row, and a container fill paints those as a phantom
   block. Cell-drawn rules simply stop where the content stops. */
.hero-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  margin-top: 1.9rem;
  border-top: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
  border-left: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
}
.hero-stat {
  padding: 0.85rem 0.9rem;
  border-right: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
  border-bottom: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
  font-size: 0.83rem;
  font-weight: 600;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
  color: var(--light-secondary);
  /* 72% near-black over the scrim: even the white-photo worst case composites
     to about 0x242424, where white is ~15.9:1. */
  background: color-mix(in srgb, var(--dark-primary) 72%, transparent);
}

/* ── 8. SUBPAGE HERO (dark band) ─────────────────────────────────────────── */

.page-hero {
  background: var(--dark-primary);
  color: var(--dark-tertiary);       /* band ink, inherited by every child */
  border-bottom: 3px solid var(--brand-primary);
}
.page-hero-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: clamp(1.5rem, 4vw, 3rem);
  width: min(var(--shell), 100% - 2 * var(--gutter));
  margin-inline: auto;
  padding-block: clamp(2.5rem, 5.5vw, 4rem);
}
/* The text column. flex, not grid: 404.html has no .page-hero-image and the
   column must then take the full width rather than sit in a dead half. */
.page-hero-inner > div:not(.page-hero-image) {
  flex: 1 1 min(100%, 34rem);
  min-width: 0;
}
.page-hero h1 { color: var(--light-secondary); max-width: 22ch; }

.lead {
  margin-top: 0.9rem;
  max-width: 66ch;
  font-size: 1.02rem;
  color: var(--dark-tertiary);       /* 12.58:1 */
}
.lead strong { color: var(--light-secondary); }

.page-hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.page-hero-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  margin-top: 1.8rem;
  border-top: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
  border-left: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
}
.page-hero-stat {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.9rem;
  border-right: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
  border-bottom: var(--hair) solid color-mix(in srgb, var(--light-secondary) 32%, transparent);
}
.num {
  font-size: clamp(1.05rem, 2.2vw, 1.4rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  color: var(--light-secondary);     /* 17.93:1 */
}
.lbl {
  font-size: 0.69rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  line-height: 1.35;
  color: var(--dark-tertiary);       /* 12.58:1 */
}

.page-hero-image { flex: 0 1 340px; min-width: 0; }
.page-hero-image img {
  width: 100%;
  /* The source files are 720px square. Capping at 360 keeps them from being
     upscaled into a wide column, which reads as blur. */
  max-width: 360px;
  border: 1px solid color-mix(in srgb, var(--light-secondary) 30%, transparent);
}

/* The updated stamp appears only inside the two dark heroes in this build; the
   light-ground value is kept as the base so a future placement cannot inherit
   an invisible colour. */
.page-updated {
  margin-top: 0.75rem;
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--dark-secondary);      /* 8.86:1 if it ever lands on white */
}
#hero .page-updated,
.page-hero .page-updated { color: var(--dark-tertiary); }  /* 12.58:1 */
.page-updated time { font-weight: 650; }

/* Focus rings inside the dark bands: --brand-primary is 3.95:1 there, so the
   pale tertiary carries the ring instead (17.01:1). */
#hero :focus-visible,
.page-hero :focus-visible,
.closing-cta :focus-visible,
#contact .contact-info :focus-visible,
#footer :focus-visible {
  outline-color: var(--brand-tertiary);
}

/* Primary CTA inverts on every dark band: a white block on near-black, or on
   the blue closing band. (0,2,0) beats .btn-gold's (0,1,0). */
#hero .btn-gold,
.page-hero .btn-gold,
.closing-cta .btn-gold {
  background: var(--light-secondary);
  border-color: var(--light-secondary);
  color: var(--dark-primary);        /* 17.93:1 ink, 17.93:1 / 8.08:1 boundary */
}
#hero .btn-gold:hover,
#hero .btn-gold:focus-visible,
.page-hero .btn-gold:hover,
.page-hero .btn-gold:focus-visible,
.closing-cta .btn-gold:hover,
.closing-cta .btn-gold:focus-visible {
  background: var(--brand-tertiary);
  border-color: var(--brand-tertiary);
  color: var(--brand-secondary);     /* 7.67:1 ink; 17.01:1 / 7.67:1 boundary */
}

/* ── 9. PROSE SECTIONS + THE NUMBERED INDEX ──────────────────────────────── */

main { counter-reset: datum; }

.prose-section {
  counter-increment: datum;
  padding-block: var(--rhythm);
  /* Band separation is carried by a rule, not by a fill: the two grounds are
     only 1.05:1 apart by design, and the hairline is what makes the structure
     legible. */
  border-top: var(--hair) solid var(--dark-tertiary);
}
.bg-white { background: var(--light-secondary); }
.bg-light { background: var(--brand-tertiary); }   /* 0xF3FAFF pale blue paper */

.prose-inner {
  width: min(var(--shell), 100% - 2 * var(--gutter));
  margin-inline: auto;
  color: var(--dark-secondary);      /* 8.86:1 white / 8.41:1 pale band */
}

/* The section index. A leading-zero counter over a short brand rule, flush
   left above the heading — the sheet's signature mark. Set in
   --brand-secondary (8.08 / 7.67), never --brand-primary, which is 4.30:1 on
   the pale band and far too thin for an 11px numeral. */
.prose-inner::before {
  content: counter(datum, decimal-leading-zero);
  display: block;
  width: 2.5rem;
  margin-bottom: 1.4rem;
  padding-bottom: 0.5rem;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  font-variant-numeric: tabular-nums;
  color: var(--brand-secondary);
  border-bottom: 2px solid var(--brand-primary);
}

.prose-inner > * + * { margin-top: 1.05rem; }
.prose-inner h2 { color: var(--dark-primary); }
.prose-inner h3,
.prose-inner h4 { color: var(--dark-primary); }
.prose-inner > h3 { margin-top: 2.1rem; }
.prose-inner > h4 { margin-top: 1.7rem; }

/* Emphasis inside light prose. This is the ONLY place <strong> is given a
   colour in the whole sheet, and its ground is guaranteed light. */
.prose-inner strong { color: var(--dark-primary); }   /* 17.93 / 17.01 */
.prose-inner em { color: inherit; }

.prose-inner a:not(.btn) {
  color: var(--brand-secondary);     /* 8.08:1 / 7.67:1 */
  text-decoration: underline;
  text-underline-offset: 0.16em;
  text-decoration-thickness: 1px;
}
.prose-inner a:not(.btn):hover,
.prose-inner a:not(.btn):focus-visible {
  color: var(--dark-primary);        /* 17.93:1 — hover darkens */
  text-decoration-thickness: 2px;
}

/* Lists: a 6px brand tick instead of a bullet — a mark, not an ornament. */
.prose-inner ul > li {
  position: relative;
  padding-left: 1.35rem;
  margin-top: 0.5rem;
}
.prose-inner ul > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 8px;
  height: 2px;
  background: var(--brand-primary);
}
.prose-inner ol { counter-reset: prose-ol; }
.prose-inner ol > li {
  position: relative;
  counter-increment: prose-ol;
  padding-left: 2rem;
  margin-top: 0.6rem;
}
.prose-inner ol > li::before {
  content: counter(prose-ol, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.08em;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--brand-secondary);     /* 8.08:1 / 7.67:1 */
}

.prose-inner blockquote {
  border-left: 3px solid var(--brand-primary);
  padding: 0.3rem 0 0.3rem 1.2rem;
  color: var(--dark-primary);        /* 17.93 / 17.01 */
  font-size: 1.04rem;
}

/* Reading measure. Text is capped and stays FLUSH LEFT — it is never centred,
   which is what lets the tables and grids below run the full shell width and
   gives the page its left datum line. Tables, figures and grids are
   deliberately excluded from the cap. */
.wide { --measure: 44rem; }
.prose-inner.wide > p,
.prose-inner.wide > ul,
.prose-inner.wide > ol,
.prose-inner.wide > blockquote,
.prose-inner.wide > h2,
.prose-inner.wide > h3,
.prose-inner.wide > h4 { max-width: var(--measure); }

/* Full-width children need their own breathing room; (0,2,0) beats the
   (0,1,1) stack rule above. */
.prose-inner > .table-wrap,
.prose-inner > .gallery-grid,
.prose-inner > .plan-grid,
.prose-inner > .content-figure,
.prose-inner > .cta-row { margin-top: 1.75rem; }
.prose-inner > hr { margin-block: 2.2rem; }

hr {
  border: 0;
  height: var(--hair);
  background: var(--dark-tertiary);  /* visible on white and on 0xF3FAFF alike */
}

/* ── 10. DATA TABLES ─────────────────────────────────────────────────────── */

/* Wide tables scroll inside their own box. The page body never scrolls
   sideways, at 360px or anywhere else. */
.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-bottom: var(--hair) solid var(--dark-tertiary);
}

.data-table {
  width: 100%;
  min-width: 34rem;                  /* below this the columns collapse to
                                        unreadable slivers — scroll instead */
  font-size: 0.93rem;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
}
.data-table th,
.data-table td {
  text-align: left;
  vertical-align: top;
  padding: 0.7rem 0.9rem;
  border-bottom: var(--hair) solid var(--dark-tertiary);
}
.data-table thead th {
  font-size: 0.69rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--brand-secondary);     /* 8.08:1 / 7.67:1 */
  border-bottom: 2px solid var(--brand-primary);
}
.data-table tbody td { color: var(--dark-secondary); }       /* 8.86 / 8.41 */
.data-table tbody th { color: var(--dark-primary); font-weight: 650; }
.data-table tbody td:first-child {
  color: var(--dark-primary);        /* the key column carries full weight */
  font-weight: 650;
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table strong { color: var(--dark-primary); }
/* A <strong> inside a header cell is (0,1,1) and would otherwise repaint the
   head's micro-label ink near-black. Both pass AA; this is consistency. */
.data-table thead th strong { color: inherit; }
.data-table a {
  color: var(--brand-secondary);
  text-decoration: underline;
  text-underline-offset: 0.16em;
}
.data-table tbody tr:hover { background: color-mix(in srgb, var(--brand-primary) 7%, transparent); }

/* ── 11. FIGURES, PLANS, GALLERY ─────────────────────────────────────────── */

.content-figure,
.plan-figure { margin: 0; }
.content-figure img,
.plan-figure img {
  width: 100%;
  border: var(--hair) solid var(--dark-tertiary);
  background: var(--light-secondary);
}
.content-figure { max-width: 720px; }   /* source renders are 720px wide */
.content-figure figcaption,
.plan-figure figcaption {
  margin-top: 0.7rem;
  font-size: 0.84rem;
  line-height: 1.6;
  color: var(--dark-secondary);      /* 8.86 / 8.41 */
}

.plan-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.25rem, 3vw, 2rem);
}

/* 300px minimum, so the 9 images land as a clean 3 x 3 at the full shell and
   a ~386px cell is asked to show a 1200px source rather than a ~289px cell
   showing the same file — four-up here was a 4x oversample. */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  border-top: var(--hair) solid var(--dark-tertiary);
  border-left: var(--hair) solid var(--dark-tertiary);
}
.gallery-item {
  position: relative;
  background: var(--light-tertiary);
  cursor: pointer;
  overflow: hidden;
  border-right: var(--hair) solid var(--dark-tertiary);
  border-bottom: var(--hair) solid var(--dark-tertiary);
}
.gallery-item img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 0.35s ease;
}
.gallery-item:hover img { transform: scale(1.03); }
.gallery-item-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--dark-primary) 58%, transparent);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.gallery-item:hover .gallery-item-overlay,
.gallery-item:focus-visible .gallery-item-overlay,
.gallery-item:focus-within .gallery-item-overlay { opacity: 1; }
.gallery-zoom-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border: 1.5px solid var(--light-secondary);
  color: var(--light-secondary);     /* icon on a 58% scrim: >=9:1 worst case */
}
/* The generated SVGs carry no fill/stroke attributes at all — without this
   they paint as solid black blobs. */
.gallery-zoom-icon svg,
.contact-detail-icon svg,
.faq-q svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── 12. FAQ (light band) ────────────────────────────────────────────────── */

#faq {
  padding-block: var(--rhythm);
  background: var(--light-secondary);
  border-top: var(--hair) solid var(--dark-tertiary);
}
.faq-inner {
  width: min(var(--shell), 100% - 2 * var(--gutter));
  margin-inline: auto;
}
.faq-header { margin-bottom: 2rem; }
#faq-heading { max-width: 28ch; }

.faq-list { border-top: 2px solid var(--brand-primary); }
.faq-item { border-bottom: var(--hair) solid var(--dark-tertiary); }

.faq-q {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.2rem;
  width: 100%;
  padding: 1.05rem 0;
  text-align: left;
  font-size: 1rem;
  font-weight: 650;
  line-height: 1.45;
  color: var(--dark-primary);        /* 17.93:1 */
}
.faq-q:hover,
.faq-q:focus-visible { color: var(--brand-secondary); }      /* 8.08:1 */
.faq-q svg {
  flex: 0 0 auto;
  margin-top: 0.28em;
  stroke: var(--brand-primary);      /* 4.54:1 — clears the 3:1 icon minimum */
  transition: transform 0.2s ease;
}
.faq-item.open .faq-q svg { transform: rotate(180deg); }

/* display:none rather than a 0fr grid: `fr` interpolation is not universally
   supported and where it is missing the answer never opens at all. Hiding it
   outright also keeps the collapsed answers out of the screen-reader tree,
   which matches the aria-expanded state the script sets. */
.faq-a { display: none; }
.faq-item.open .faq-a {
  display: block;
  padding-bottom: 1.3rem;
}
.faq-a p { color: var(--dark-secondary); max-width: 76ch; }  /* 8.86:1 */
.faq-a p + p { margin-top: 0.9rem; }
.faq-a strong { color: var(--dark-primary); }                /* light ground */
.faq-a a {
  color: var(--brand-secondary);
  text-decoration: underline;
  text-underline-offset: 0.16em;
}
.faq-a a:hover { color: var(--dark-primary); }
.faq-a .table-wrap { margin-top: 1.1rem; }

/* ── 13. CLOSING CTA (the one saturated band) ────────────────────────────── */

.closing-cta {
  padding-block: clamp(2.5rem, 5.5vw, 4rem);
  background: var(--brand-secondary);
  color: var(--brand-tertiary);      /* 7.67:1 band ink, inherited by children */
}
.closing-cta-inner {
  width: min(var(--shell), 100% - 2 * var(--gutter));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;           /* flush left, like everything else */
  gap: 1.5rem;
}
.closing-cta h2 {
  color: var(--light-secondary);     /* 8.08:1 */
  max-width: 26ch;
}
.closing-cta strong { color: var(--light-secondary); }

/* ── 14. CONTACT (dark band + white form card) ───────────────────────────── */

#contact {
  padding-block: var(--rhythm);
  padding-inline: var(--gutter);
  background: var(--dark-primary);
}
.contact-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: start;
}

/* Everything in this column sits on near-black. Ink is set on the column and
   inherited; nothing here may carry a dark colour. */
.contact-info { color: var(--dark-tertiary); }               /* 12.58:1 */
.contact-info .section-label {
  color: color-mix(in srgb, var(--brand-primary) 55%, var(--light-secondary));
}                                                            /* 0x86b7d7, 8.34:1 */
.contact-info .section-title { color: var(--light-secondary); }  /* 17.93:1 */
.contact-info .gold-divider {
  background: color-mix(in srgb, var(--brand-primary) 55%, var(--light-secondary));
}                                    /* the raw brand blue is 3.95:1 here */
.contact-info p { margin-top: 1.1rem; }
.contact-info strong { color: var(--light-secondary); }      /* brighter, never darker */
.contact-info ul { margin-top: 1rem; }
.contact-info li {
  position: relative;
  padding-left: 1.35rem;
  margin-top: 0.5rem;
}
.contact-info li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 8px;
  height: 2px;
  background: color-mix(in srgb, var(--brand-primary) 55%, var(--light-secondary));
}
.contact-info a {
  color: var(--brand-tertiary);      /* 17.01:1 */
  text-decoration: underline;
  text-underline-offset: 0.16em;
}

.contact-detail {
  display: grid;
  gap: 1rem;
  margin-top: 1.8rem;
  padding-top: 1.5rem;
  border-top: var(--hair) solid color-mix(in srgb, var(--light-secondary) 26%, transparent);
}
.contact-detail-item { display: flex; align-items: flex-start; gap: 0.9rem; }
.contact-detail-icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border: var(--hair) solid color-mix(in srgb, var(--light-secondary) 40%, transparent);
  color: color-mix(in srgb, var(--brand-primary) 55%, var(--light-secondary));
}                                    /* 8.34:1 icon stroke, 3:1 minimum is icons */
.contact-detail-text {
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--dark-tertiary);       /* 12.58:1 */
}
.contact-detail-text strong {
  display: block;                    /* the markup runs the label straight into
                                        the value with no separator element */
  font-size: 0.71rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--light-secondary);
  margin-bottom: 0.2rem;
}

/* ── 15. FORM ────────────────────────────────────────────────────────────── */

.form-card {
  background: var(--light-secondary);
  color: var(--dark-primary);        /* the card resets ink to the light scale */
  border-top: 3px solid var(--brand-primary);
  padding: clamp(1.3rem, 3vw, 1.9rem);
}
#contact-form { display: block; }
.form-row { display: grid; grid-template-columns: 1fr; gap: 0.9rem; }
.form-group {
  display: flex;
  flex-direction: column;
  margin-bottom: 0.9rem;
}
.form-group label {
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--dark-primary);        /* 17.93:1 */
  margin-bottom: 0.4rem;
}
.form-group input,
.form-group textarea {
  width: 100%;
  padding: 0.72rem 0.85rem;
  font-size: 0.94rem;
  background: var(--light-secondary);
  color: var(--dark-primary);
  border-radius: var(--radius);
  /* A 50/50 near-black-to-light-tertiary mix is 0x838383, 3.6:1 on white —
     a form control's boundary needs 3:1 and --dark-tertiary would be 1.43:1. */
  border: var(--hair) solid color-mix(in srgb, var(--dark-primary) 50%, var(--light-tertiary));
}
.form-group input::placeholder,
.form-group textarea::placeholder { color: var(--dark-secondary); }  /* 8.86:1 */
.form-group textarea { min-height: 110px; resize: vertical; }
.form-group input:focus-visible,
.form-group textarea:focus-visible {
  border-color: var(--brand-primary);
  outline: 2px solid var(--brand-primary);
  outline-offset: 1px;
}
.form-group input.error,
.form-group textarea.error { border-color: var(--state-error); }

/* The generator ships the error copy as visible text; the script reveals it by
   adding .show. Without this rule every field would ship its error permanently
   on screen. */
.field-error {
  display: none;
  margin-top: 0.35rem;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--state-error);         /* 8.31:1 on white */
}
.field-error.show { display: block; }

.form-submit {
  width: 100%;
  padding: 0.85rem 1.5rem;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  border-radius: var(--radius);
  background: var(--brand-secondary);
  color: var(--light-secondary);     /* 8.08:1 */
  transition: background-color 0.16s ease;
}
.form-submit:hover:not(:disabled),
.form-submit:focus-visible:not(:disabled) { background: var(--dark-primary); }  /* 17.93:1 */
.form-submit:disabled {
  background: var(--dark-secondary); /* white on 0x4a4a4a = 8.86:1 — a disabled
                                        control is exempt, but there is no
                                        reason to ship it illegible */
  cursor: not-allowed;
}

.form-status {
  margin-top: 1rem;
  padding: 0.75rem 0.9rem;
  font-size: 0.88rem;
  line-height: 1.5;
  border: var(--hair) solid;
}
.form-status[hidden] { display: none; }
.form-status.success {
  color: var(--state-success);       /* 6.14:1 on its own 10% tint */
  background: color-mix(in srgb, var(--state-success) 10%, var(--light-secondary));
  border-color: color-mix(in srgb, var(--state-success) 40%, transparent);
}
.form-status.error {
  color: var(--state-error);         /* 7.24:1 on its own 8% tint */
  background: color-mix(in srgb, var(--state-error) 8%, var(--light-secondary));
  border-color: color-mix(in srgb, var(--state-error) 40%, transparent);
}

/* ── 16. FOOTER (dark band) ──────────────────────────────────────────────── */

#footer {
  background: var(--dark-primary);
  color: var(--dark-tertiary);       /* 12.58:1 band ink — inherited by the
                                        disclaimer <p>s, which is exactly why
                                        this sheet sets no global p colour */
  border-top: 3px solid var(--brand-primary);
  padding-block: clamp(2.75rem, 5vw, 4rem) 1.6rem;
  font-size: 0.92rem;
}
.footer-inner,
.footer-disclaimer,
.footer-copy {
  width: min(var(--shell), 100% - 2 * var(--gutter));
  margin-inline: auto;
}
.footer-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(1.75rem, 4vw, 3rem);
}
.footer-brand { max-width: 46ch; }
.footer-logo { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 1rem; }
/* --brand-secondary is 2.22:1 on near-black. Lift the developer line toward
   white until it clears AA and still reads as the brand hue: 0x86b7d7, 8.34:1. */
.footer-logo .brand-developer {
  color: color-mix(in srgb, var(--brand-primary) 55%, var(--light-secondary));
  font-size: 11px;
}
.footer-logo .brand-project { color: var(--light-secondary); font-size: 1.05rem; }
.footer-tagline { color: var(--dark-tertiary); line-height: 1.6; }   /* 12.58:1 */
.footer-about-text {
  margin-top: 0.9rem;
  font-size: 0.82rem;
  line-height: 1.6;
  color: color-mix(in srgb, var(--light-secondary) 62%, transparent);
}                                    /* composites to 0xa7a7a7 = 7.45:1 */

.footer-col-title {
  font-size: 0.71rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--light-secondary);     /* 17.93:1 */
  padding-bottom: 0.6rem;
  margin-bottom: 0.9rem;
  border-bottom: var(--hair) solid color-mix(in srgb, var(--light-secondary) 26%, transparent);
}
.footer-col li { margin-bottom: 0.5rem; }
.footer-col a { color: var(--dark-tertiary); font-size: 0.9rem; }    /* 12.58:1 */
.footer-col a:hover,
.footer-col a:focus-visible {
  color: var(--light-secondary);     /* 17.93:1 — hover gains contrast */
  text-decoration: underline;
  text-underline-offset: 0.16em;
}
.footer-col address { font-size: 0.9rem; line-height: 1.6; color: var(--dark-tertiary); }

.footer-disclaimer {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: 1.4rem;
  border-top: var(--hair) solid color-mix(in srgb, var(--light-secondary) 20%, transparent);
  font-size: 0.78rem;
  line-height: 1.65;
  color: color-mix(in srgb, var(--light-secondary) 62%, transparent);  /* 7.45:1 */
}
.footer-disclaimer p + p { margin-top: 0.8rem; }

.footer-copy {
  margin-top: 1.4rem;
  padding-top: 1.2rem;
  border-top: var(--hair) solid color-mix(in srgb, var(--light-secondary) 20%, transparent);
  font-size: 0.8rem;
  color: var(--dark-tertiary);       /* 12.58:1 */
}

/* ── 17. RUNTIME COMPONENTS (injected by js/script.js) ───────────────────── */

/* Gallery lightbox. */
#lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1800;
  padding: clamp(1rem, 4vw, 3rem);
  background: color-mix(in srgb, var(--dark-primary) 92%, transparent);
  align-items: center;
  justify-content: center;
}
#lightbox.open { display: flex; }
.lightbox-img {
  max-width: min(100%, 1100px);
  max-height: 78vh;
  object-fit: contain;
  margin-inline: auto;
  border: var(--hair) solid color-mix(in srgb, var(--light-secondary) 30%, transparent);
}
.lightbox-close,
.lightbox-prev,
.lightbox-next {
  position: absolute;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  font-size: 1.7rem;
  line-height: 1;
  color: var(--light-secondary);     /* >=17:1 on the 92% scrim */
  border: var(--hair) solid color-mix(in srgb, var(--light-secondary) 55%, transparent);
}
.lightbox-close { top: 1rem; right: 1rem; }
.lightbox-prev  { left: 1rem;  top: 50%; transform: translateY(-50%); }
.lightbox-next  { right: 1rem; top: 50%; transform: translateY(-50%); }
.lightbox-close:hover,
.lightbox-prev:hover,
.lightbox-next:hover { background: color-mix(in srgb, var(--light-secondary) 16%, transparent); }
.lightbox-caption {
  position: absolute;
  left: 50%;
  bottom: 1.2rem;
  transform: translateX(-50%);
  width: min(100% - 2rem, 62rem);
  text-align: center;
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--dark-tertiary);       /* 11.6:1 on the 92% scrim */
}

/* Contact modal (fleet rollout — tooling/add-contact-modal.mjs builds this
   markup at runtime). The dialog element itself carries the scrim and fills
   the viewport: ::backdrop could not resolve custom properties before Chrome
   122, and the script closes the modal on clicks that land on the dialog
   itself, which only works if the dialog is larger than its panel. */
.cm-modal {
  display: none;
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  margin: 0;
  padding: 1rem;
  border: 0;
  overflow: auto;
  overscroll-behavior: contain;
  background: color-mix(in srgb, var(--dark-primary) 72%, transparent);
}
.cm-modal[open] { display: grid; place-items: center; }
.cm-modal::backdrop { background: color-mix(in srgb, var(--dark-primary) 40%, transparent); }

.cm-modal__panel {
  position: relative;
  width: min(100%, 28rem);
  padding: 1.6rem;
  background: var(--light-secondary);
  color: var(--dark-primary);        /* 17.93:1 */
  border-top: 3px solid var(--brand-primary);
  font-family: inherit;
}
.cm-modal__title {
  margin: 0 0 1.2rem;
  padding-right: 2.5rem;
  font-size: 1.15rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.018em;
  color: var(--dark-primary);
}
.cm-modal__close {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--dark-primary);        /* 17.93:1 */
  border: var(--hair) solid var(--brand-primary);   /* 4.54:1 boundary */
}
.cm-modal__close:hover { background: var(--brand-tertiary); }
.cm-form { display: grid; gap: 0.9rem; }
.cm-form__field { display: flex; flex-direction: column; gap: 0.35rem; text-align: left; }
.cm-form__field label {
  font-size: 0.73rem;
  font-weight: 800;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--dark-primary);
}
.cm-form input,
.cm-form textarea {
  width: 100%;
  min-width: 0;
  font: inherit;
  padding: 0.62rem 0.75rem;
  color: var(--dark-primary);
  background: var(--light-secondary);
  border-radius: var(--radius);
  border: var(--hair) solid color-mix(in srgb, var(--dark-primary) 50%, var(--light-tertiary));
}
.cm-form input:focus-visible,
.cm-form textarea:focus-visible {
  border-color: var(--brand-primary);
  outline: 2px solid var(--brand-primary);
  outline-offset: 1px;
}
.cm-form textarea { min-height: 5.5rem; resize: vertical; }
.cm-form__submit {
  padding: 0.78rem 1.5rem;
  font: inherit;
  font-weight: 700;
  border-radius: var(--radius);
  background: var(--brand-secondary);
  color: var(--light-secondary);     /* 8.08:1 */
}
.cm-form__submit:hover,
.cm-form__submit:focus-visible { background: var(--dark-primary); }
.cm-form__status { font-size: 0.86rem; line-height: 1.5; }
.cm-form__status.success { color: var(--state-success); }    /* 7.13:1 on white */
.cm-form__status.error { color: var(--state-error); }        /* 8.31:1 on white */
.cm-form__hint {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.55;
  color: var(--dark-secondary);      /* 8.86:1 on the white panel */
}
.cm-form__hint a { color: var(--brand-secondary); text-decoration: underline; }

body.has-modal-open { overflow: hidden; }

/* Scroll reveal, if a future build emits it. */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.5s ease, transform 0.5s ease; }
.reveal.visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .gallery-item img,
  .faq-q svg,
  .btn,
  .nav-cta,
  .form-submit { transition: none; }
  .gallery-item:hover img { transform: none; }
}

/* ── 18. ID CONTRACT ─────────────────────────────────────────────────────── */
/* The page generator emits 30 ids as well as 82 classes, and every one of them
   is answered somewhere in this sheet. The handful below are the ids whose
   VISUAL styling lives on a class: they are given real but deliberately
   non-conflicting declarations here, because an id is (1,0,0) and would
   otherwise out-rank the state classes that do the actual work — an
   `#name-err { display: none }` would have beaten `.field-error.show` and the
   form would never have shown a validation message at all. */

#hamburger,
#mobile-menu-close { -webkit-tap-highlight-color: transparent; }

#name, #phone, #email, #message { max-width: 100%; }
#name-err, #phone-err, #email-err { max-width: 44ch; }
#form-message { max-width: 100%; }

/* Anchor targets. The scroll-margin is set once in §4 via [id^="section-"];
   these are named so the contract is legible rather than inferred. */
#section-overview,
#section-location,
#section-master-plan,
#section-floor-plans,
#section-plot-options,
#section-gallery,
#section-amenities,
#section-pricing,
#section-reviews,
#section-builder,
#section-cta { display: block; }

/* ── 19. RESPONSIVE ──────────────────────────────────────────────────────── */
/* Mobile-first. Breakpoints 520 / 600 / 768 / 900 / 1024. */

@media (max-width: 519px) {
  /* Stacked, full-width CTAs read better than two half-width pills. */
  .cta-row .btn,
  .hero-btns .btn,
  .page-hero-ctas .btn { flex: 1 1 100%; }
}

@media (min-width: 520px) {
  .nav-cta { display: inline-block; }
}

@media (min-width: 600px) {
  .form-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .contact-detail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 768px) {
  .plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero-title { max-width: 16ch; }
}

@media (min-width: 900px) {
  .contact-inner { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
  .contact-detail { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: minmax(0, 1.8fr) repeat(3, minmax(0, 1fr)); }
  /* At this width the section index can step out into the left margin, which
     is the whole point of a datum line. */
  .prose-inner { position: relative; }
}

/* The fleet standard is "nav collapses at 1024"; written mobile-first that is
   the complement, min-width 1025. */
@media (min-width: 1025px) {
  .nav-links {
    display: flex;
    align-items: center;
    gap: clamp(0.7rem, 1.5vw, 1.3rem);
  }
  .hamburger { display: none; }
  #mobile-menu.open { display: none; }   /* a resize past the breakpoint must
                                            not strand an open drawer */
}


/* ------------------------------------------------------------------ *
 * Inline links on the dark surfaces.
 *
 * tooling/rewire-sister-links-by-relevance.mjs injects an editorial sentence
 * into the page-head lead of most subpages — its skip regex is
 * /(?<!page-)\bhero\b|…/, and the negative lookbehind means `page-hero` does
 * NOT match, so the head is not skipped. That is the fleet's majority
 * behaviour (embassy-riverine 8/11, urbanrise-gattahalli 8/11,
 * nambiar-kannamangala 8/12 all carry one there).
 *
 * Without this rule the anchor inherits the lead's own --dark-tertiary with
 * text-decoration:none, so it is pixel-identical to the prose around it: a
 * link no sighted user can find. --light-secondary on --dark-primary is
 * 17.93:1, and reads brighter than the surrounding --dark-tertiary (12.58:1),
 * so the affordance is carried by weight AND underline, never by hue alone.
 * ------------------------------------------------------------------ */
.page-hero .lead a:not(.btn),
.footer-about-text a:not(.btn),
.footer-disclaimer a:not(.btn) {
  color: var(--light-secondary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
}
.page-hero .lead a:not(.btn):hover,
.page-hero .lead a:not(.btn):focus-visible,
.footer-about-text a:not(.btn):hover,
.footer-about-text a:not(.btn):focus-visible,
.footer-disclaimer a:not(.btn):hover,
.footer-disclaimer a:not(.btn):focus-visible {
  color: var(--brand-tertiary);          /* #F3FAFF on #171717 = 17.0:1 */
  text-decoration-thickness: 2px;
}
