/* =====================================================================
   Placemark Builds - stylesheet
   Extracted from the 260730 prototype bundle and unbundled 2026-08-04.
   Sections: tokens / base / components / nav / hero / catalogue /
             gap / services / why / process / partner / contact /
             footer / responsive
   =====================================================================
   TYPE-STYLE CODES (shared language with Ayala, 2026-08-20; rendered
   reference: "260820 - Type Styles Reference.html"). When Ayala names a
   code, it maps to ALL selectors listed — change them together.
   D1 hero headline ......... .hero__h1
   D2 section heading ....... .gap__h2 .cred__h2 .partner__h2 .why__h2 .craft__h2 clamp(28px,3vw,44px) · .contact__h2 clamp(28px,4.2vw,50px) — all 900. TYPE SCALE B (Ayala 260910): was clamp(28,4vw,52); Our Craft's scale adopted sitewide
   D2b contact supporting line .contact__h2-sub 20/400, 85% Warm White (260924: was a second heading)
   D3 popup heading ......... .modal__title
   D4 module heading ........ .cmp__h3 (22-30, #2 cut) | .process__title .subhead .tool__title (20-28, #3 cut — deliberate hierarchy, resolved 260824)
   D5 band statement ........ .band__line (+.band__l2)
   E1 body emphasis 16/500 .. .hi + strong inside B1/B2 bodies — Medium, full Ink, SAME size (Ayala 260918: emphasis is weight, never size)
   E2 tagline closer 18/500 . .closer — a closing single sentence carrying "the Possibility of Place"; tagline in Cedar (--umber-text, 260925; was Evergreen). The only 18px body text. (.exist-pull + inline .statement retired 260918)
   H1 card title ............ .cat-card__name
   H2 feature title ......... RETIRED 260824 (was .case-card h3 18/500; Why It Works titles folded into H4)
   H3 phase title ........... .phase__title
   H4 ledger title 18/700 ... .icoitem h3 .wiw-case h3 (16/800 → 18 Bold, Ayala 260824 — one voice across WWB benefits, deliver triad, Why It Works). EXCEPTION 260918: .partner__certs h3 (title-only rows, no body) take the E1 voice 16/500
   H5 popup/sheet title 16 .. .mslide h4 .msheet__h (16/800 — split from H4 260824; popup + model-sheet context, not raised)
   B1 section body 16 ....... .gap__body .cred__body .why__body .contact__sub .process__sub .process__lede .cmp__lede .craft__lede (16/1.7 — TYPE SCALE B, Ayala 260910; was 17/1.75)
   B2 panel body 16 ......... .tool__lede .tool__cta p .partner__body .msheet__lede
   B3 card body 15 .......... .icoitem p .wiw-case p (was .case-card p, 260824) .mslide p .msheet__desc
   B4 compact body 14 ....... .phase__desc .cat-card__spec (13 → 14, Ayala 260820 pm)
   C1 caption 13 ............ .ctrl__hint .res__range .res__note .cmp__legend .cmp__foot .msheet__cap .exist__figcap .form-privacy .form-alt
   C3 image-caption pill 12 .. .exist-band__cap .partner__pill .why-figure__pill .lightbox__cap .xpanel__tag span
   F1 footer nav 12 ......... .footer__nav a
   C2 reveal text 12.5 ...... .phase__more p
   L1 eyebrow 12 ............ .eyebrow .eyebrow--light .res__label .ctrl__label .field label .phase__label (carries durations, promoted 260820)
   L2 sub-eyebrow 11 ........ .cat-card__type .cred__caption .res__k .process__hint .rgallery__hint .msheet__stats b
   L3 micro-label 10 ........ .phase__more-k .msheet__count
   BTN button label 12 ...... .btn-primary .btn-secondary .btn-secondary--light .btn-submit (.nav__cta 11, compact header cut)
   S1 headline stat ......... .res__big
   S2 secondary stat 19 ..... .res__v
   S3 value 14.5 ............ .ctrl__val .msheet__stats span
   ===================================================================== */
/* vietnamese */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("fonts/lexend-deca-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("fonts/lexend-deca-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("fonts/lexend-deca-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/lexend-deca-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/lexend-deca-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/lexend-deca-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/lexend-deca-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/lexend-deca-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/lexend-deca-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/lexend-deca-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/lexend-deca-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/lexend-deca-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* vietnamese */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/lexend-deca-vietnamese.woff2") format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/lexend-deca-latin-ext.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Lexend Deca';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/lexend-deca-latin.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


:root {
  --ink:         #1C1F1A;
  --charcoal:    #2C2F33;
  --forest:      #22592D;
  --forest-dark: #1A4523;
  --umber:       #9F784D;
  --stone:       #C4B99A;
  --fog:         #F2EDE6;
  --sunburst:    #D04C27;
  --sunburst-dark: #B8431F;  /* CTA hover */
  --cta:         #CB4A26;    /* 260924 (Ayala, proposal 2): "Start a Project" fill, ~2.5% deeper than Sunburst so pure White text passes AA (4.62:1); accents keep --sunburst. Playbook amendment candidate */
  --cta-text:    #FFFFFF;    /* White, not Warm White, on CTA buttons only (Warm White on Sunburst = 3.8:1, fails) */
  --celebration: #EE3124;    /* parent-brand red — error states only */
  --umber-text:  #7A5A38;    /* darker Cedar for small text on light — Cedar itself fails AA below 18px */
  --umber-bright: #C89968;   /* lighter Cedar for small text on dark surfaces */
  --white:       #FFFFFF;
  --font:        'Lexend Deca', sans-serif;
  --ease:        cubic-bezier(0.25, 0.46, 0.45, 0.94);
  /* spacing scale — spacious rhythm; section paddings snap to space-7/8 */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 48px;
  --space-6: 64px;
  --space-7: 96px;
  --space-8: 128px;
}
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; font-size: 16px; }
body { font-family: var(--font); background: var(--fog); color: var(--ink); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
img { display: block; max-width: 100%; }
a { text-decoration: none; color: inherit; }
button { cursor: pointer; font-family: var(--font); border: none; background: none; }
input, select, textarea { font-family: var(--font); }

/* Accent system (2026-08-17, Ayala): eyebrows are Evergreen on Moss
   grounds, Cedar (--umber-text) on Warm White grounds; rules stay Cedar.
   Evergreen: ~6.4:1 on Moss; Cedar text: 6.5:1 on Warm White — AA at 11px.
   Dark grounds (Contact) keep the fog-tinted .eyebrow--light. */
.eyebrow { display: block; font-size: 12px; font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: var(--forest); margin-bottom: 16px; }
.eyebrow--light { display: block; font-size: 12px; font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: rgba(242,237,230,0.62); margin-bottom: 16px; }
/* Warm White sections + fog modal panels → Cedar */
/* EYEBROW COLOUR RULE (Ayala 260910, applied to every eyebrow): Cedar
   (--umber-text) on Warm White grounds, Evergreen (--forest, the default) on
   Moss grounds. After the 260909 surface flip: Our Purpose (Warm White) →
   Cedar; Our Product (Moss) → Evergreen. Popup panels are Warm White → Cedar. */
.gap--exist .eyebrow, .modal__panel .eyebrow { color: var(--umber-text); }
.build-lt .eyebrow { color: var(--forest); }
.rule { width: 40px; height: 1px; background: var(--umber); margin-bottom: 48px; }

/* Sunburst = action moments, per Brand Playbook (confirmed 2026-08-05) */
.btn-primary { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; background: var(--cta); color: var(--cta-text); border: 1px solid var(--cta); padding: 13px 26px; border-radius: 1px; transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease); }
.btn-primary:hover { background: var(--sunburst-dark); border-color: var(--sunburst-dark); }

.btn-secondary { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; background: transparent; color: var(--ink); border: 1px solid rgba(28,31,26,0.4); padding: 13px 26px; border-radius: 1px; transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease); }
.btn-secondary:hover { background: var(--ink); color: var(--fog); border-color: var(--ink); }

/* full-strength type + stronger border: these sit over photography, where
   low-opacity text was illegible */
/* Exploration primary on imagery (Ayala 260820): Sunburst is RESERVED for
   "Start a Project" alone — amends the 260805 all-primary-CTAs-Sunburst call;
   playbook-amendment candidate. Frosted Warm White (translucent fill, fog
   text + border) — the solid fill competed with the hero headline
   (Ayala 260820 pm). */
.btn-light { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; background: rgba(242,237,230,0.18); color: var(--fog); border: 1px solid rgba(242,237,230,0.85); padding: 13px 26px; border-radius: 1px; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); transition: background 0.25s var(--ease), border-color 0.25s var(--ease); }
.btn-light:hover { background: rgba(242,237,230,0.32); border-color: var(--fog); }
.btn-secondary--light { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; background: transparent; color: var(--fog); border: 1px solid rgba(242,237,230,0.55); padding: 13px 26px; border-radius: 1px; transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease); }
.btn-secondary--light:hover { background: rgba(242,237,230,0.08); border-color: rgba(242,237,230,0.6); color: var(--fog); }

.btn-submit { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; background: var(--cta); color: var(--cta-text); border: 1px solid var(--cta); padding: 14px 28px; border-radius: 1px; transition: background 0.2s, border-color 0.2s; justify-content: center; }
.btn-submit:hover { background: var(--sunburst-dark); border-color: var(--sunburst-dark); }
.btn-submit:disabled { opacity: 0.6; cursor: not-allowed; }

/* Scoped to .js: without JavaScript every .reveal block stays fully visible,
   so crawlers and AI agents see all content. See the inline script in <head>. */
.js .reveal { opacity: 0; transform: translateY(20px); transition: opacity 0.65s var(--ease), transform 0.65s var(--ease); }
.js .reveal.visible { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: 0.08s; }
.reveal-d2 { transition-delay: 0.16s; }
.reveal-d3 { transition-delay: 0.24s; }
.reveal-d4 { transition-delay: 0.32s; }

/* NAV */
:root { --nav-h: 68px; }   /* header height; 48px on phones (Ayala 260921) */
.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 500; height: var(--nav-h); display: flex; align-items: center; justify-content: space-between; padding: 0 40px; background: rgba(28,31,26,0.96); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid rgba(255,255,255,0.05); transition: background 0.3s; }
.nav__logo { display: flex; align-items: center; text-decoration: none; transition: opacity 0.3s; }
.nav__logo-svg { height: 44px; width: auto; color: var(--fog); display: block; }
.nav__actions { display: flex; align-items: center; gap: 14px; }
.nav__cta { padding: 7px 14px; font-size: 11px; letter-spacing: 0.14em; } /* compact header cut, one step under BTN (was 9px — size-floor fix 260820) */
@media (max-width: 560px) { .nav__cta { display: none; } }
/* 260924 (Ayala, critique): fade the header button out while the contact form is on screen (class set by script.js) */
.nav .nav__cta { transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease), opacity 0.25s, visibility 0.25s; }
.nav.nav--at-contact .nav__cta { opacity: 0; visibility: hidden; }
/* padding sized so the hit area meets the 44x44px touch-target minimum */
.nav__hamburger { display: flex; flex-direction: column; gap: 5px; padding: 15px 11px; cursor: pointer; }
.nav__hamburger span { display: block; width: 22px; height: 1.5px; background: rgba(242,237,230,0.6); transition: all 0.25s; }
.nav__hamburger:hover span { background: var(--fog); }
.nav__menu { position: fixed; top: var(--nav-h); left: 0; right: 0; z-index: 499; background: rgba(28,31,26,0.98); padding: 48px 40px 56px;
  max-height: calc(100vh - var(--nav-h)); max-height: calc(100dvh - var(--nav-h)); overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;   /* the panel scrolls itself: 12 links + padding overran an iPhone 17 (Ayala 260921) */ transform: translateY(-8px); opacity: 0; pointer-events: none; transition: transform 0.3s var(--ease), opacity 0.3s; border-bottom: 1px solid rgba(255,255,255,0.06); }
.nav__menu.open { transform: none; opacity: 1; pointer-events: all; }
.nav__menu-links { list-style: none; display: flex; flex-direction: column; gap: 0; }
.nav__menu-links li { border-bottom: 1px solid rgba(255,255,255,0.06); }
.nav__menu-links a { display: block; padding: 22px 0; font-size: 15px; font-weight: 300; letter-spacing: 0.04em; color: rgba(242,237,230,0.72); text-align: center; transition: color 0.2s; }
.nav__menu-links a:hover { color: var(--fog); }
.nav__menu-links a.current { color: var(--fog); font-weight: 400; }
/* 260924 (Ayala, critique): grouped menu - About / What We Build / How We Deliver side by side on laptops and tablets,
   stacked on phones; Start a Project button at the foot. Selectors carry .nav__group to outrank the flat-list rules. */
.nav__groups { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px 56px; max-width: 960px; margin: 0 auto; }
.nav__group-label { font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(242,237,230,0.62); margin: 0 0 6px; padding-bottom: 12px; border-bottom: 1px solid rgba(242,237,230,0.1); }
.nav__group .nav__menu-links li { border-bottom: 0; }
.nav__group .nav__menu-links a { padding: 11px 0; font-size: 17px; font-weight: 300; letter-spacing: 0.02em; color: rgba(242,237,230,0.8); text-align: left; }
.nav__group .nav__menu-links a:hover, .nav__group .nav__menu-links a.current { color: var(--fog); }
.nav__group .nav__menu-links a.current { font-weight: 400; }
.nav__menu-foot { max-width: 960px; margin: 32px auto 0; display: flex; }
@media (max-width: 700px) {
  .nav__groups { grid-template-columns: 1fr; gap: 18px; }
  .nav__group .nav__menu-links a { padding: 8px 0; font-size: 16px; }
  .nav__menu-foot { margin-top: 24px; }
}
/* 260925 (Ayala, menu option A): where the header button shows (>560px) the menu is navigation only - the header
   button stays visible while the menu is open and the header turns solid (no hero strip above the panel).
   Phones (no header button) keep the button at the foot of the menu, as before. .nav--menu-open is set in script.js setMenu. */
@media (min-width: 561px) {
  .nav__menu-foot { display: none; }
  .nav.nav--menu-open, .nav.nav--over-hero.nav--menu-open { background: rgba(28,31,26,0.98); border-bottom-color: rgba(255,255,255,0.06); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
}
.nav__overlay { position: fixed; inset: 0; z-index: 498; background: rgba(0,0,0,0.45); opacity: 0; pointer-events: none; transition: opacity 0.3s; }
.nav__overlay.open { opacity: 1; pointer-events: all; }

/* HERO */
.hero { position: relative; height: 100vh; min-height: 680px; display: flex; align-items: flex-end; padding: 0 40px 80px; overflow: hidden; }
.hero__img { position: absolute; inset: 0; background-size: cover; background-position: center 45%; transition: transform 8s ease-out; }
.hero__overlay { position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(20,24,18,0.1) 0%, rgba(20,24,18,0.15) 40%, rgba(20,24,18,0.65) 72%, rgba(20,24,18,0.88) 100%); }
.hero__content { position: relative; z-index: 2; max-width: 980px; }
/* steeper slope for presence at laptop widths; 90px ceiling so full screen
   stays composed (108px broke the two-line lockup — ruled out 2026-08-05) */
.hero__h1 { font-size: clamp(40px, 7.5vw, 90px); font-weight: 500; letter-spacing: 0.03em; line-height: 1.01; color: var(--fog); margin-bottom: 24px; }
.hero__sub { font-size: 17px; font-weight: 300; line-height: 1.7; color: rgba(242,237,230,0.82); margin-bottom: 40px; max-width: 460px; }
.hero__ctas { display: flex; gap: 12px; flex-wrap: wrap; }
.hero__scroll { position: absolute; right: 40px; bottom: 40px; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.hero__scroll span { font-size: 9px; font-weight: 400; letter-spacing: 0.2em; text-transform: uppercase; color: rgba(242,237,230,0.25); writing-mode: vertical-rl; }
.hero__scroll-line { width: 1px; height: 48px; background: linear-gradient(to bottom, rgba(242,237,230,0.3), transparent); animation: scrollPulse 2.2s ease-in-out infinite; }
@keyframes scrollPulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.9; } }

/* CATALOGUE */
.catalogue { background: var(--charcoal); padding: 96px 0 0; }
.catalogue__header { padding: 0 40px 48px; }
.catalogue__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 500; letter-spacing: 0.04em; line-height: 1.04; color: var(--fog); max-width: none; }
.catalogue__right { max-width: 560px; text-align: left; margin-top: 22px; }
.catalogue__right p { font-size: 17px; font-family: 'Lexend Deca', sans-serif; font-weight: 300; line-height: 1.7; color: rgba(242,237,230,0.6); margin-bottom: 20px; }
.catalogue__row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 3px; padding: 0 40px; }
.catalogue__row:active { cursor: grabbing; }
.cat-card { min-width: 0; display: flex; flex-direction: column; background: white; }
.cat-card__img { height: 300px; overflow: hidden; position: relative; background: var(--charcoal); }
.cat-card__img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.55s var(--ease), opacity 0.3s; }
.cat-card__img::after { content: ''; position: absolute; inset: 0; background: rgba(34,89,45,0); transition: background 0.3s var(--ease); pointer-events: none; }
.cat-card:hover .cat-card__img::after { background: rgba(34,89,45,0.28); }
.cat-card:hover .cat-card__img img { transform: scale(1.04); }
.cat-bg--1 { background: linear-gradient(160deg,#2A3B2C,#141E15); }
.cat-bg--2 { background: linear-gradient(160deg,#32302A,#1A1814); }
.cat-bg--3 { background: linear-gradient(160deg,#1E2D34,#121B20); }
.cat-bg--4 { background: linear-gradient(160deg,#2C2820,#181410); }
.cat-bg--5 { background: linear-gradient(160deg,#262E28,#141A16); }
.cat-bg--6 { background: linear-gradient(160deg,#30282A,#1C1416); }
/* 260922: card tile with no render yet (The Lookout) - the gradient carries a quiet pending label */
.cat-card__pending { position: absolute; inset: 0; display: grid; place-items: center; font-size: 11px; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242,237,230,0.55); }
.cat-card__info { padding: 20px 20px 24px; }
.cat-card__type { font-size: 11px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: var(--umber-text); margin-bottom: 12px; }
.cat-card__name { font-size: 18px; font-weight: 500; letter-spacing: 0.02em; color: var(--ink); margin-bottom: 11px; }
.cat-card__spec { font-size: 14px; font-weight: 300; color: rgba(28,31,26,0.65); line-height: 1.5; }
.catalogue__footer { display: flex; justify-content: space-between; align-items: center; padding: 22px 40px; margin-top: 3px; border-top: 1px solid rgba(255,255,255,0.1); }
.catalogue__footer p { font-size: 11px; font-weight: 300; letter-spacing: 0.06em; color: rgba(242,237,230,0.62); } /* 0.4 → 0.62: contrast-floor fix 260820 */

/* SERVICES */
.services__hero { padding: 150px 40px 160px; }
.services__hero-scrim { position: absolute; inset: 0; background: linear-gradient(rgba(28,31,26,0.62), rgba(28,31,26,0.42) 480px, rgba(28,31,26,0.6)); }
.services__header { position: relative; }
.services__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 500; letter-spacing: 0.04em; line-height: 1.04; color: var(--fog); max-width: 760px; }
.services__right { max-width: 620px; padding-top: 0; margin-top: 22px; }
.services__right p { font-size: 17px; font-weight: 300; line-height: 1.75; color: rgba(242,237,230,0.85); margin-bottom: 0; }
.services__body { padding: 0 40px; margin-top: -36px; position: relative; }
.services__body .service-card { box-shadow: 0 6px 24px rgba(28,31,26,0.1); border-color: transparent; }
.service-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 12px; margin-bottom: 12px; }
.service-card { background: #fff; padding: 32px 24px 28px; border: 1px solid rgba(28,31,26,0.14); cursor: pointer; position: relative; overflow: hidden; transition: border-color 0.25s, background 0.25s; }
.service-card:hover { background: var(--forest); border-color: var(--forest); }
.service-card__num { display: block; font-size: 45px; font-weight: 700; letter-spacing: -0.02em; line-height: 1; color: #f2ede6; margin-bottom: 8px; }
.service-card:hover .service-card__num { color: rgba(242,237,230,0.2); }
.service-card__title { font-size: 17px; font-weight: 500; letter-spacing: 0.02em; color: var(--ink); margin-bottom: 10px; line-height: 1.35; }
.service-card:hover .service-card__title { color: var(--fog); }
.service-card__desc { font-size: 12px; font-weight: 300; line-height: 1.65; color: rgba(28,31,26,0.5); max-height: 0; overflow: hidden; transition: max-height 0.4s var(--ease), opacity 0.3s; opacity: 0; }
.service-card:hover .service-card__desc { max-height: 120px; opacity: 1; color: rgba(242,237,230,0.6); }

/* PROCESS */
.process { background: #E0E3DD; padding: var(--space-7) 40px; } /* rides with How We Deliver (Moss) */
/* tight to the sketch: the illustration, timeline and estimator read as one block */
.process__header { margin-bottom: 24px; }
.process__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 500; letter-spacing: 0.04em; line-height: 1.04; color: var(--ink); max-width: none; }
/* 740px keeps the intro to two lines; 680 orphaned the final word */
.process__sub { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72); max-width: 740px; text-align: left; margin-top: 22px; }
.process__track-wrap { position: relative; margin-bottom: 0; }
/* top aligns the line with the phase dots (phase icons were removed in the
   narrative-v2 restructure, 2026-08-05) */
.process__line { position: absolute; top: 7px; left: 8px; width: 80%; height: 2px; background: rgba(28,31,26,0.15); z-index: 0; }
.process__phases { display: grid; grid-template-columns: repeat(5,1fr); gap: 0; position: relative; }
.phase { padding: 0 24px 0 0; position: relative; opacity: 1; transform-origin: 8px 80px; transition: opacity 0.25s var(--ease), transform 0.25s var(--ease); }
.phase.is-dim { opacity: 0.5; }
.phase.is-active { transform: scale(1.06); }
.phase__icon { height: 54px; margin-bottom: 18px; display: flex; align-items: flex-end; }
.phase__icon svg { width: 46px; height: 46px; display: block; }
.phase__dot { width: 16px; height: 16px; border-radius: 50%; background: var(--umber); border: 2px solid var(--umber); margin-bottom: 22px; position: relative; z-index: 1; transition: background 0.25s var(--ease), border-color 0.25s var(--ease), transform 0.25s var(--ease), box-shadow 0.25s var(--ease); }
/* current phase reads Sunburst (action accent); Cedar keeps the rest */
.phase.is-active .phase__dot { transform: scale(1.28); background: var(--sunburst); border-color: var(--sunburst); box-shadow: 0 0 0 5px rgba(208,76,39,0.18); }
.phase.is-dim .phase__dot { background: #E0E3DD; border-color: rgba(28,31,26,0.35); } /* matches the Moss ground */
.phase__label { font-size: 12px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: rgba(28,31,26,0.65); margin-bottom: 10px; display: block; }
/* the phase number reads a step above its duration: weight only, kept subtle
   (Ayala 2026-08-19) */
.phase__label b { font-weight: 700; color: rgba(28,31,26,0.78); }
.phase__title { font-size: 17px; font-weight: 500; line-height: 1.3; color: var(--ink); margin-bottom: 6px; }
.phase__time { font-size: 12px; font-weight: 400; color: var(--umber-text); margin-bottom: 12px; }
.phase__desc { font-size: 14px; font-weight: 300; line-height: 1.6; color: rgba(28,31,26,0.7); }
/* Deliverable reveal (2026-08-18, Ayala) — RETIRED 260820 (Ayala: too much
   specificity for now). The markup was removed from index.html; these rules
   are kept intact so the cards can be restored verbatim (copy lives in
   Snapshot C, 260819). */
/* Treatment: thin Cedar rule above (2026-08-18, Ayala) — rhymes with the
   timeline's own line-and-dot vocabulary; no box. */
.phase__more { margin-top: 14px; padding-top: 12px;
  border-top: 1px solid rgba(159,120,77,0.45); }
.phase__more-k { display: block; font-size: 10px; font-weight: 500; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--umber-text); margin-bottom: 4px; }
.phase__more p { font-size: 12.5px; font-weight: 300; line-height: 1.55; color: rgba(28,31,26,0.74); }
/* The card's space is RESERVED at all times on multi-column layouts, so
   hovering never moves the CTA or anything below (no layout shift; the
   reveal is opacity + a small rise only). On the stacked mobile layout a
   tap expands in-flow instead: accordion growth is expected there and
   permanent reserved gaps between stacked phases would read as holes. */
.js .phase__more { visibility: hidden; opacity: 0; transform: translateY(6px);
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease),
    visibility 0s 0.35s; }
.js .phase.is-active .phase__more { visibility: visible; opacity: 1; transform: none;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), visibility 0s 0s; }
@media (max-width: 900px) {
  .js .phase__more { visibility: visible; max-height: 0; overflow: hidden;
    margin-top: 0; padding-top: 0; transform: none;
    transition: max-height 0.4s var(--ease), opacity 0.35s var(--ease); }
  .js .phase.is-active .phase__more { max-height: 300px; opacity: 1;
    margin-top: 14px; padding-top: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .js .phase__more { transition: none; }
}
/* tightened 56 → 32 (2026-08-18): the reserved reveal row already
   guarantees clearance below the tallest open card */
.process__cta { margin-top: 32px; text-align: center; }

/* WHY */
.why { background: var(--ink); padding: var(--space-7) 0 0; }
.why__intro { padding: 0 40px 32px; }
.why__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 500; letter-spacing: 0.04em; line-height: 1.04; color: var(--fog); text-align: left; margin-bottom: 0; }

.why__stats { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid rgba(242,237,230,0.08); }
.why-stat { padding: 64px 56px 60px; }
.why-stat + .why-stat { border-left: 1px solid rgba(242,237,230,0.08); }
.why-stat__head { font-family: 'Lexend Deca', sans-serif; font-size: clamp(24px, 2.4vw, 36px); font-weight: 900; letter-spacing: 0.03em; line-height: 1.15; color: var(--fog); margin-bottom: 22px; }
.why-stat__accent { color: var(--umber); }
.why-stat__sub { font-size: 15px; font-weight: 300; line-height: 1.75; color: rgba(242,237,230,0.55); max-width: 560px; margin-bottom: 40px; }
.why-bars { display: flex; flex-direction: column; gap: 16px; }
.why-bar { display: grid; grid-template-columns: 88px 1fr 130px; align-items: center; gap: 18px; }
.why-bar__label { font-size: 11px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242,237,230,0.62); } /* 0.45 → 0.62: contrast-floor fix 260820 */
.why-bar__track { position: relative; height: 8px; display: flex; align-items: stretch; }
.why-bar__fill { height: 100%; }
.why-bar__fill--site { background: rgba(242,237,230,0.28); }
.why-bar__fill--pm { background: var(--umber); }
.why-bar__risk { flex: 1; height: 100%; background: repeating-linear-gradient(135deg, rgba(242,237,230,0.28) 0 4px, transparent 4px 8px); }
.why-bar__val { font-size: 11px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(242,237,230,0.62); white-space: nowrap; }
.why-bar__val--pm { color: var(--umber); }

.why__band { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; border-top: 1px solid rgba(242,237,230,0.08); padding: 56px 40px; gap: 28px; }
.why__band-text { font-size: 17px; font-weight: 400; letter-spacing: 0.02em; color: rgba(242,237,230,0.72); line-height: 1.3; }
.why__band-text strong { color: var(--fog); font-weight: 500; }

.why__record { padding: 56px 40px 48px; background: var(--fog); }
.why__record-inner { display: flex; justify-content: space-between; align-items: flex-end; gap: 48px; }
.why__record-left { max-width: 760px; }
.why__record-num { font-size: clamp(28px, 3.5vw, 46px); font-weight: 500; letter-spacing: 0.02em; line-height: 1.02; color: var(--ink); margin-bottom: 14px; }
.why__record-label { font-size: 17px; font-weight: 300; line-height: 1.75; color: rgba(28,31,26,0.55); }

.project-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 3px; }
.project-card { position: relative; overflow: hidden; height: 300px; cursor: pointer; background: var(--charcoal); }
.project-card__img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.55s var(--ease); }
.project-card__overlay { position: absolute; inset: 0; background: linear-gradient(to top, rgba(28,31,26,0.82) 0%, rgba(28,31,26,0.2) 55%, transparent 100%); transition: background 0.3s; }
.project-card:hover .project-card__overlay { background: linear-gradient(to top, rgba(34,89,45,0.88) 0%, rgba(34,89,45,0.35) 60%, rgba(34,89,45,0.1) 100%); }
.project-card:hover .project-card__img { transform: scale(1.04); }
.project-card__info { position: absolute; bottom: 0; left: 0; right: 0; padding: 20px 20px; }
.project-card__name { font-size: 18px; font-weight: 500; letter-spacing: 0.02em; color: var(--fog); margin-bottom: 3px; }
.project-card__location { font-size: 12px; font-weight: 300; letter-spacing: 0.08em; color: rgba(242,237,230,0.72); margin-bottom: 6px; }
.project-card__specs { font-size: 12px; font-weight: 300; letter-spacing: 0.06em; color: rgba(242,237,230,0.62); }
.proj-bg--1 { background: linear-gradient(160deg,#283520,#141c10); }
.proj-bg--2 { background: linear-gradient(160deg,#302C20,#1C1810); }
.proj-bg--3 { background: linear-gradient(160deg,#1C2830,#10161A); }
.proj-bg--4 { background: linear-gradient(160deg,#28202C,#141018); }

/* .cert dot list retired 2026-08-19: certifications now use the icon-ledger
   grammar (see .partner__certs .icoitem below) */

/* CONTACT */
.contact { background: var(--charcoal); padding: var(--space-7) 40px; }
.contact__inner { max-width: 720px; margin: 0 auto; }
.contact__head { text-align: center; margin-bottom: 18px; }
.contact__h2-sub { font-size: 20px; font-weight: 400; letter-spacing: 0; line-height: 1.2; color: rgba(242,237,230,0.85); }   /* 260924 (Ayala, critique P1#2): a supporting line, one level below "Let's Build" (was a second 22-38px heading); line box kept <= the old one so no screen grows */
.contact__h2 { font-size: clamp(28px, 4.2vw, 50px); font-weight: 500; letter-spacing: 0.04em; line-height: 1.05; color: var(--fog); margin-bottom: 2px; }
.contact__sub { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(242,237,230,0.7); text-align: center; max-width: 580px; margin: 0 auto 48px; }
.contact__promises { margin-top: 44px; }
.contact__promises-head { font-size: 18px; font-weight: 500; color: var(--fog); margin-bottom: 16px; }
/* 260924 (Ayala, critique P1#2): two columns on laptops and up. Left = heading, intro and "What happens next", so the
   reassurance is read BEFORE the decision; right = the form. CSS only: the HTML order (screen readers, crawlers) is unchanged.
   Rows: auto auto 1fr packs the left column at the top while the form spans them. Section 1315 -> 862px at 1366/1920. */
@media (min-width: 1100px) {
  .contact__inner { max-width: 1160px; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); grid-template-rows: auto auto 1fr; column-gap: 80px; align-items: start; }
  .contact__head { grid-column: 1; grid-row: 1; text-align: left; margin-bottom: 20px; }
  .contact__sub { grid-column: 1; grid-row: 2; text-align: left; margin: 0 0 40px; max-width: none; }
  .contact__promises { grid-column: 1; grid-row: 3; margin-top: 0; padding-top: 28px; border-top: 1px solid rgba(242,237,230,0.14); }
  .contact__form, .contact__sent { grid-column: 2; grid-row: 1 / span 3; }
  .contact__fail { grid-column: 2; grid-row: 4; }
}
.contact__promise { display: flex; gap: 14px; align-items: flex-start; padding: 7px 0; }
.promise__dot { width: 4px; height: 4px; border-radius: 50%; background: var(--umber); margin-top: 9px; flex-shrink: 0; }
.promise__text { font-size: 17px; font-weight: 300; line-height: 1.6; color: rgba(242,237,230,0.72); }
.contact__form { display: flex; flex-direction: column; gap: 18px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(242,237,230,0.7); } /* was 9px @ 0.35 — size + contrast floor fix 260820; matches .ctrl__label grammar */
.field input, .field select, .field textarea { font-size: 14px; font-weight: 300; color: var(--fog); background: rgba(242,237,230,0.07); border: 1px solid rgba(242,237,230,0.12); border-radius: 1px; padding: 12px 14px; outline: none; transition: border-color 0.2s, background 0.2s; -webkit-appearance: none; appearance: none; }
.field input::placeholder, .field textarea::placeholder { color: rgba(242,237,230,0.2); }
/* focus border mirrors the Sunburst submit it leads to (3.0:1 on Graphite) */
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--sunburst); background: rgba(242,237,230,0.1); }
.field select { color: rgba(242,237,230,0.6); }
.field select option { background: var(--charcoal); color: var(--fog); }
.field textarea { resize: vertical; min-height: 100px; }
.contact__sent { margin-top: 8px; padding: 18px 22px; background: rgba(242,237,230,0.07); border: 1px solid rgba(242,237,230,0.15); border-radius: 1px; }
.contact__sent p { font-size: 14px; font-weight: 300; line-height: 1.65; color: rgba(242,237,230,0.75); }
.contact__sent strong { font-weight: 500; color: var(--fog); }

/* FOOTER */
.footer { background: var(--ink); padding: 52px 40px 40px; border-top: 1px solid rgba(255,255,255,0.04); }
.footer__top { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 40px; padding-bottom: 40px; border-bottom: 1px solid rgba(255,255,255,0.05); margin-bottom: 28px; }
.footer__logo-svg { height: 44px; width: auto; color: rgba(242,237,230,0.82); display: block; } /* size matches the header logo (Ayala 260819) */
.footer__nav { display: grid; grid-template-columns: repeat(3, minmax(110px, 180px)); grid-template-rows: repeat(3, auto); grid-auto-flow: column; gap: 8px 32px; }
.footer__nav a { display: inline-block; padding: 6px 0; font-size: 12px; font-weight: 400; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(242,237,230,0.62); transition: color 0.2s; }
.footer__nav a:hover { color: rgba(242,237,230,0.95); }
.footer__bottom { display: flex; justify-content: space-between; align-items: center; }
.footer__copy { font-size: 10px; font-weight: 300; letter-spacing: 0.08em; color: rgba(242,237,230,0.55); }

/* HEADING FONT — Lexend Deca throughout. (Museo Sans lives only inside the
   logo wordmark, which is outlined SVG — never loaded as a webfont.) */
.hero__h1, .catalogue__h2, .services__h2, .process__h2, .why__h2,
.contact__h2, .why__record-num,
.cred__h2, .gap__h2, .partner__h2 {
  font-family: 'Lexend Deca', sans-serif;
  font-weight: 800; /* ExtraBold per Brand Playbook (confirmed 2026-08-05) */
}
/* D2 weight made uniform (Ayala 260910): .why__h2 and .contact__h2 are declared
   above this block and were left at 800 while .gap__h2 / .cred__h2 / .partner__h2
   (declared below it) render at 900. One weight for every section heading. */
.why__h2, .contact__h2 { font-weight: 900; }


/* HERO EYEBROW */
.hero__eyebrow { font-size: 11px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: rgba(242,237,230,0.7); margin-bottom: 20px; }

/* CRED (WHO WE ARE) */
/* width matches the header's Builds logo rendered width (44px tall x its
   354.44:81.19 viewBox = 192px), per Ayala 2026-08-19 */
.cred__logo { width: 192px; height: auto; color: var(--fog); display: block; margin: 6px 0 30px; }
.cred { background: var(--ink); padding: var(--space-7) 0 0; }
.cred__inner { padding: 0 40px 56px; max-width: 1200px; }
.cred__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 900; letter-spacing: 0.04em; line-height: 1.04; color: var(--fog); margin-bottom: 22px; }
.cred__body { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(242,237,230,0.75); max-width: 860px; }
.cred__caption { font-size: 11px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: rgba(242,237,230,0.58); padding: 0 40px 16px; }

/* GAP */
/* Inverted alternation (260817 pm, Ayala): grounds start on Moss and
   alternate with Warm White. .gap = Why We Exist + How We Deliver. */
.gap { background: #E0E3DD; padding: var(--space-7) 40px; }
.gap__inner { display: block; }
.gap__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 900; letter-spacing: 0.04em; line-height: 1.04; color: var(--ink); margin-bottom: 22px; }
.gap__body { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72); max-width: 860px; }
/* 30px matches the paragraph rhythm set by .partner__body site-wide */
.gap__body + .gap__body { margin-top: 30px; }
.triad-units { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.triad__name { font-size: 20px; font-weight: 500; letter-spacing: 0.04em; color: var(--ink); margin-bottom: 8px; }
.triad__note { font-size: 15px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.55); }

/* PROCESS COVERAGE */
.process__coverage { margin-top: 44px; display: flex; flex-direction: column; gap: 22px; }
.coverage__grid { display: grid; grid-template-columns: repeat(5, 1fr); }
.coverage__seg { display: flex; flex-direction: column; gap: 9px; padding-right: 24px; }
.coverage__seg--supplier { grid-column: 4 / 5; text-align: center; }
.coverage__seg--pmb { grid-column: 1 / -1; text-align: center; }
.coverage__bar { height: 2px; background: rgba(28,31,26,0.3); position: relative; }
.coverage__bar::before, .coverage__bar::after { content: ''; position: absolute; top: -5px; width: 2px; height: 12px; background: inherit; }
.coverage__bar::before { left: 0; }
.coverage__bar::after { right: 0; }
.coverage__seg--pmb .coverage__bar { background: var(--ink); }
.coverage__label { font-size: 11px; font-weight: 500; letter-spacing: 0.14em; line-height: 1.7; text-transform: uppercase; color: rgba(28,31,26,0.7); }
.coverage__seg--pmb .coverage__label { color: var(--ink); }
.coverage__sig { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 14px; }
.coverage__logo { height: 44px; width: auto; display: block; }
.coverage__sig-rule { width: 1px; height: 44px; background: rgba(28,31,26,0.35); }
.coverage__sig .coverage__label { text-align: left; }

/* PARTNER */
.partner { position: relative; overflow: hidden; min-height: 680px; display: flex; flex-direction: column; justify-content: flex-end; padding: var(--space-8) 40px var(--space-7); }
.partner__bg { position: absolute; inset: 0; background-image: url("images/partner-background.webp"); background-size: cover; background-position: center; background-color: #2A3020; }
.partner__overlay { position: absolute; inset: 0; background: linear-gradient(105deg, rgba(28,31,26,0.88) 0%, rgba(28,31,26,0.72) 45%, rgba(28,31,26,0.3) 80%, rgba(28,31,26,0.1) 100%); }
.partner__content { position: relative; z-index: 2; max-width: 620px; }
.partner__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 900; letter-spacing: 0.04em; line-height: 1.04; color: var(--fog); margin-bottom: 22px; }
.partner__body { font-size: 16px; font-weight: 300; line-height: 1.8; color: rgba(242,237,230,0.75); margin-bottom: 30px; }
/* certifications as icon-ledger rows (Option C, 2026-08-19): heading-only
   .icoitem rows, stacked with a hairline, icons vertically centered */
.partner__certs .icoitem { padding: 12px 0; align-items: center; }
.partner__certs .icoitem h3 { margin-bottom: 0; font-size: 16px; font-weight: 500; }   /* 260918 (Ayala): title-only rows read too heavy in H4 18/700; they take the E1 voice (16/500 Ink), a skimmable list of facts rather than titles over body text */
.partner__certs .icoitem + .icoitem { border-top: 1px solid rgba(28,31,26,0.12); }
/* same text-to-CTA gap as .cred__ctas */
.partner__cta { margin-top: var(--space-4); }

/* RESPONSIVE */
@media (max-width: 900px) {
  .nav { padding: 0 24px; }
  .hero { padding: 0 24px 72px; }
  .catalogue__header { padding: 0 24px 40px; }
  .catalogue__right { text-align: left; max-width: 100%; }
  .catalogue__row { padding: 0 24px; grid-template-columns: repeat(2,1fr); }
  .cat-card__img { height: 240px; }
  .catalogue__footer { padding: 18px 24px; }
  .process, .why, .contact { padding-left: 24px; padding-right: 24px; }
    .services__hero { padding: 84px 24px 64px; }
  .services__body { padding: 0 24px; margin-top: -36px; }
  .service-grid { grid-template-columns: repeat(2,1fr); }
  .process__phases { grid-template-columns: 1fr; gap: 28px; }
  .process__line { display: none; }
  .phase { opacity: 1 !important; padding-right: 0; }
  .why__intro { padding: 0 24px 56px; }
  .why__stats { grid-template-columns: 1fr; }
  .why-stat + .why-stat { border-left: none; border-top: 1px solid rgba(242,237,230,0.08); }
  .why-stat { padding: 40px 24px; }
  .why-bar { grid-template-columns: 76px 1fr; }
  .why-bar__val { grid-column: 2; }
  .why__band { flex-direction: column; align-items: flex-start; padding: 32px 24px; gap: 24px; }
  .why__record { padding: 48px 24px 40px; }
  .why__record-inner { flex-direction: column; align-items: flex-start; gap: 28px; }
  .project-grid { grid-template-columns: repeat(2,1fr); }
  .form-row { grid-template-columns: 1fr; }
  .contact__inner { max-width: 100%; }
  .footer__top { flex-direction: column; }
  .footer__nav { grid-template-columns: 1fr 1fr; grid-template-rows: auto; grid-auto-flow: row; }   /* 260918: the desktop grid flows 12 links down 3 fixed rows; with 2 columns that spilled into two implicit columns off-screen and forced a 511px layout viewport on phones (the "390 nav overflow" bug) */
  .cred__inner { padding: 0 24px 48px; }
  .cred__caption { padding: 0 24px 14px; }
  .gap { padding: 72px 24px; }
  .gap__inner { grid-template-columns: 1fr; gap: 40px; }
  /* stacked: the shared rail hides; each box keeps its own Cedar top edge
     (set in the 900px block below) with its icon centered astride it */
  .triad-units { grid-template-columns: 1fr; }
  .triad-strip__line { display: none; }
  .coverage__grid { grid-template-columns: 1fr; }
  .coverage__seg--supplier { grid-column: 1 / -1; }
  .coverage__seg { padding-right: 0; }
  .partner { padding: 72px 24px 56px; min-height: 540px; }
}
@media (prefers-reduced-motion: reduce) {
  /* Remove movement; keep non-motion feedback (color and opacity hovers). */
  .js .reveal { opacity: 1; transform: none; transition: none; }
  .js .wwb-pane__stack img { transition: none; }
  .sketch g[id^="g"], .sketch .transient, .sketch .site-work { transition: none; }
  .hero__scroll-line { animation: none; }
  .hero__img { transition: none; }
  .nav__menu { transition: none; transform: none; }
  .cat-card:hover .cat-card__img img,
  .project-card:hover .project-card__img,
  .phase.is-active .phase__dot,
  .phase.is-active,
  .triad-unit:hover .triad__mark { transform: none; }
  .triad__mark, .triad-unit .triad__col { transition: none; }
}

/* =====================================================================
   UNBUNDLE ADDITIONS — 2026-08-04
   Styles for the semantic markup introduced when the prototype framework
   was removed, plus the accessibility fixes from the 260804 audit.
   Later in the file = these win over the equivalent rules above.
   ===================================================================== */

/* ---------- Anchor offset under the fixed nav ---------------------- */
html { scroll-padding-top: 88px; }

/* ---------- Skip link ---------------------------------------------- */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 1000;
  background: var(--fog); color: var(--ink);
  font-size: 13px; font-weight: 500; letter-spacing: 0.06em;
  padding: 12px 20px; border-radius: 1px;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 8px; }

/* ---------- Visible focus for keyboard users ----------------------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--umber);
  outline-offset: 3px;
}

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

.nowrap { white-space: nowrap; }

/* ---------- List resets for semantic lists ------------------------- */
.process__phases,
.partner__certs,
.contact__promise-list { list-style: none; margin: 0; padding: 0; }

/* ---------- Emphasis spans (were inline styles) -------------------- */
.cred__emphasis { font-weight: 400; color: rgba(242,237,230,0.85); }
.gap__emphasis  { font-weight: 400; color: rgba(28,31,26,0.85); }
.partner__emphasis { font-weight: 400; color: rgba(242,237,230,0.9); }
.process__emphasis { font-weight: 400; color: rgba(28,31,26,0.85); }

.cred__ctas { margin-top: var(--space-4); display: flex; flex-wrap: wrap; gap: 14px; }
.service-grid--last { margin-bottom: 0; }

/* ---------- Logos as <img> ----------------------------------------- */
.footer__logo-svg { opacity: 0.82; }
.promise__dot { display: block; }

/* ---------- Hamburger open state (was inline JS styles) ------------ */
.nav__hamburger.is-open span:nth-child(1) { transform: rotate(45deg) translate(4px, 4px); }
.nav__hamburger.is-open span:nth-child(2) { opacity: 0; }
.nav__hamburger.is-open span:nth-child(3) { transform: rotate(-45deg) translate(4px, -4px); }
/* ---------- Phone header (Ayala 260921, iPhone 17 test) ----------------
   68px of fixed header hid too much of a phone screen: 48px (about 30% less),
   logo 44 -> 32px, hamburger unchanged (44px touch target still fits). The logo
   stays visible over the hero photo (Ayala 260921, after the stacked hero landed). Menu panel padding
   tightens so more of the list shows before scrolling. */
@media (max-width: 600px) {
  :root { --nav-h: 48px; }
  .nav__logo-svg { height: 32px; }
  /* 260921 later (Ayala): with the stacked hero the logo stays visible over the photo; the
     earlier hide-while-transparent rule was for the old panel layout and is retired. */
  .nav__menu { padding: 20px 24px 28px; }
  .nav__menu-links a { padding: 16px 0; }
}

/* ---------- Catalogue CTA placeholder ------------------------------ */

/* =====================================================================
   FORM — audit fixes
   ===================================================================== */

/* Labels were 9px at 35% opacity: below any legible minimum and failing
   WCAG contrast on charcoal. Raised to 11px/75% in the first audit pass;
   12px per the L1 decision (260820 floor pass). */
.field label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(242,237,230,0.75);
}

.field input::placeholder,
.field textarea::placeholder { color: rgba(242,237,230,0.55); }

.form-note {
  font-size: 12px; font-weight: 300;
  color: rgba(242,237,230,0.68);
  margin-bottom: 2px;
}
/* Privacy line under the submit button (Ayala 260923): BC PIPA s.10 purpose statement at the point of
   collection. C1 caption voice; 0.68 Warm White on Graphite = 6.1:1. Stays true only while enquiry
   details are used solely to reply (no mailing list without separate consent). */
.form-privacy {
  margin-top: 12px;
  font-size: 13px; font-weight: 300; line-height: 1.5;
  color: rgba(242,237,230,0.68);
  text-wrap: pretty;
}
/* Standing email route (Ayala 260923): for people who prefer email or have plans/photos to attach
   (the form takes no files). Same C1 caption voice as the privacy line. */
.form-alt {
  margin-top: 4px;
  font-size: 13px; font-weight: 300; line-height: 1.5;
  color: rgba(242,237,230,0.68);
  text-wrap: pretty;
}
.form-alt a { color: var(--fog); text-decoration: underline; text-underline-offset: 3px; padding: 4px 0; }   /* 260924: tap area 16 → 24px tall; vertical padding on an inline link adds hit area without moving the text */

.req { color: var(--umber); font-weight: 500; }
.opt {
  font-size: 12px;   /* 10 -> 12 (260925 size floor) */ letter-spacing: 0.1em; text-transform: none;
  color: rgba(242,237,230,0.62); font-weight: 300;
}

/* Selects had appearance:none with no replacement arrow — they looked
   identical to text inputs. Arrow restored as an inline SVG background. */
.field select {
  color: var(--fog);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23F2EDE6' stroke-opacity='0.6' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 38px;
  cursor: pointer;
}

/* Error states */
/* Errors use Celebration red — distinct from Sunburst, which now means "act" */
.field input.is-invalid,
.field select.is-invalid,
.field textarea.is-invalid {
  border-color: var(--celebration);
  background: rgba(238,49,36,0.08);
}
.field__error {
  font-size: 12px;
  font-weight: 400;
  line-height: 1.5;
  color: #F9857B; /* legible tint of Celebration on charcoal */
}

.contact__sent:focus { outline: 2px solid var(--umber); outline-offset: 3px; }

/* Send failure (260923): same panel as "Sent.", error-tinted. Celebration is for error states only;
   the label uses its legible tint on Graphite, the rule carries the full red. */
.contact__fail { margin-top: 16px; padding: 16px 20px; background: rgba(238,49,36,0.08); border: 1px solid rgba(238,49,36,0.45); border-left: 3px solid var(--celebration); border-radius: 1px; }
.contact__fail p { font-size: 14px; font-weight: 300; line-height: 1.65; color: rgba(242,237,230,0.8); }
.contact__fail strong { font-weight: 500; color: #F9857B; }
.contact__fail a { color: var(--fog); text-decoration: underline; text-underline-offset: 3px; }
.contact__fail:focus { outline: 2px solid var(--umber); outline-offset: 3px; }

/* 260923 fix: .contact__form's display:flex beat the hidden attribute, so after "Sent." the form stayed
   on screen (reading "Sending…"). The hidden attribute must win for all three form states. */
.contact__form[hidden], .contact__sent[hidden], .contact__fail[hidden] { display: none; }

/* Spam trap (honeypot): never shown, never focusable; robots that fill every field reveal themselves. */
.hp { display: none !important; }

/* ---------- Footer bottom ------------------------------------------ */
.footer__top-link {
  font-size: 12px;   /* 10 -> 12 (260925 size floor) */ font-weight: 400; letter-spacing: 0.12em;
  text-transform: uppercase; color: rgba(242,237,230,0.62);
  transition: color 0.2s;
}
.footer__top-link:hover { color: rgba(242,237,230,0.95); }

/* ---------- Responsive additions ----------------------------------- */
@media (max-width: 900px) {
  html { scroll-padding-top: 80px; }
  .footer__bottom { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* =====================================================================
   NARRATIVE V2 ADDITIONS — 2026-08-05
   Styles for the restructured homepage (per the approved
   wireframe-narrative.html): S3 triad heading, S4 merged What We Build
   section, S5 case cards.
   ===================================================================== */

/* ---------- S3: triad heading --------------------------------------- */
.triad__heading { margin-top: 56px; font-size: 12px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(28,31,26,0.68); }
.triad__heading + .triad-strip { margin-top: 14px; }

/* Boxed triad — the S5 case-card treatment, light-ground variant */
.triad__col { background: rgba(28,31,26,0.04); border: 1px solid rgba(28,31,26,0.14); padding: 28px; }
.triad__name { font-size: 18px; margin-bottom: 10px; }
.triad__note { font-size: 14px; line-height: 1.7; color: rgba(28,31,26,0.72); }

/* S3 triad "shared rail" (approved 2026-08-06): one Cedar line is the
   boxes' shared top edge, overhanging both ends; each icon sits astride
   it, half above, half set into its box. Hover: icon scales, border warms.
   All CSS — content renders complete without JavaScript. */
.triad-strip { position: relative; }
.triad-strip__line { position: absolute; top: 34px; left: -22px; right: -22px; height: 0;
  border-top: 1.6px solid rgba(159,120,77,0.7); z-index: 2; }
.triad-unit { position: relative; padding-top: 34px; display: flex; flex-direction: column; }
.triad-unit__icon { position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 3; }
.triad__mark { width: 68px; height: 68px; display: block; color: var(--ink);
  padding: 0 10px; box-sizing: content-box;
  /* Plate matches the surface it covers — fog above the rail, box tint
     below. #E9E5DE is rgba(28,31,26,0.04) flattened onto --fog; if the
     boxes are ever retinted, this literal must move with them. */
  background: linear-gradient(to bottom, var(--fog) 50%, #E9E5DE 50%);
  transition: transform 0.25s ease; }
.triad-unit .triad__col { border-top: none; flex: 1; transition: border-color 0.25s ease; }
.triad-unit:hover .triad__mark { transform: scale(1.06); }
.triad-unit:hover .triad__col { border-color: rgba(159,120,77,0.6); }

/* ---------- S4: What We Build — render hero fading into models ------ */
.catalogue--wwb { padding-top: 0; }
.wwb-hero { position: relative; padding: var(--space-8) 40px var(--space-7); }
.wwb-hero__overlay { position: absolute; inset: 0; background:
  linear-gradient(to bottom, rgba(44,47,51,0) 68%, #2C2F33 100%),
  linear-gradient(105deg, rgba(28,31,26,0.88) 0%, rgba(28,31,26,0.7) 45%, rgba(28,31,26,0.3) 80%, rgba(28,31,26,0.12) 100%); }
.wwb-hero__content { position: relative; z-index: 1; max-width: 660px; }
.wwb-hero__content .catalogue__h2 { margin-bottom: 22px; }
.wwb-hero__content .partner__body { color: rgba(242,237,230,0.78); }
.wwb-models { padding: 26px 40px 18px; }
.wwb-models-label { font-size: 12px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242,237,230,0.62); }
.catalogue__footer--cta { display: flex; justify-content: center; padding: 30px 40px 56px; border-top: 1px solid rgba(255,255,255,0.1); margin-top: 3px; }

/* ---------- S6: revenue estimator ------------------------------------ */
.tool { background: rgba(28,31,26,0.04); border: 1px solid rgba(28,31,26,0.07); border-radius: 2px;
  box-shadow: 0 22px 44px -34px rgba(28,31,26,0.35); padding: 34px 34px 30px; margin-top: 56px; }
  /* edge treatment = .cmp__plate exactly (Ayala 260824): the near-invisible
     0.07 hairline + low tight shadow replace the 0.14 outline, so the two
     "instrument panels" (comparison plate, estimator) read as one family */
.tool__head { margin-bottom: 26px; }
/* Estimator type audit (Ayala 2026-08-19): every text element mapped to an
   established site role — subhead, panel body (.msheet__desc), form label
   (.field label), stat pair (.msheet__stats), caption (.msheet__cap),
   eyebrow letterspacing. Only .res__big keeps a unique scale (sanctioned). */
.tool__title { font-family: 'Lexend Deca', sans-serif; font-weight: 800; font-size: clamp(20px, 2.6vw, 28px); line-height: 1.15; color: var(--ink); margin-bottom: 10px; } /* .subhead scale */
.tool__lede { font-size: 16px; font-weight: 300; line-height: 1.72; color: rgba(28,31,26,0.72); max-width: 560px; } /* panel-body */
.tool__lede strong { font-weight: 500; color: var(--ink); }
.tool__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start; }

/* inputs */
.ctrl { margin-bottom: 24px; }
.ctrl__row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 9px; }
.ctrl__label { font-size: 12px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(28,31,26,0.7); }
.ctrl__val { font-size: 14.5px; font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; } /* stat-value */
.ctrl select { width: 100%; font-family: var(--font); font-size: 14px; font-weight: 300; color: var(--ink); background-color: #fff; border: 1px solid rgba(28,31,26,0.22); border-radius: 1px; padding: 11px 36px 11px 13px; -webkit-appearance: none; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%231C1F1A' stroke-opacity='0.6' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center; }
.ctrl input[type=range] { width: 100%; -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; }
.ctrl input[type=range]::-webkit-slider-runnable-track { height: 3px; background: rgba(28,31,26,0.2); }
.ctrl input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 17px; height: 17px; border-radius: 50%; background: var(--sunburst); margin-top: -7px; }
.ctrl input[type=range]::-moz-range-track { height: 3px; background: rgba(28,31,26,0.2); }
.ctrl input[type=range]::-moz-range-thumb { width: 17px; height: 17px; border: none; border-radius: 50%; background: var(--sunburst); }
.ctrl input[type=range]:focus-visible { outline: 2px solid var(--umber); outline-offset: 6px; }
.ctrl__hint { font-size: 13px; font-weight: 300; color: rgba(28,31,26,0.62); margin-top: 7px; line-height: 1.6; } /* caption; 260924 axe: ink 0.6 = 4.39:1 on white -> 0.62 = 4.7:1 */

/* results */
.res { background: var(--ink); padding: 30px 28px; }
.res__label { font-size: 12px; font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: rgba(242,237,230,0.62); margin-bottom: 12px; } /* eyebrow grammar */
.res__big { font-family: 'Lexend Deca', sans-serif; font-weight: 800; font-size: clamp(30px, 4.4vw, 46px); line-height: 1.05; color: var(--fog); font-variant-numeric: tabular-nums; }
.res__range { font-size: 13px; font-weight: 300; line-height: 1.6; color: rgba(242,237,230,0.62); margin-top: 8px; } /* caption */
.res__split { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 26px; padding-top: 22px; border-top: 1px solid rgba(242,237,230,0.14); }
.res__k { font-size: 11px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242,237,230,0.55); margin-bottom: 6px; } /* stat-label (.msheet__stats b) */
.res__v { font-size: 19px; font-weight: 500; color: var(--fog); font-variant-numeric: tabular-nums; } /* secondary stat-value — 19px (Ayala 260820, friend-feedback round; 260819 note named 19px the ceiling before competing with .res__big) */
.res__note { font-size: 13px; font-weight: 300; line-height: 1.6; color: rgba(242,237,230,0.6); margin-top: 22px; padding-top: 18px; border-top: 1px solid rgba(242,237,230,0.14); } /* caption */

.tool__cta { margin-top: 28px; padding-top: 24px; border-top: 1px solid rgba(28,31,26,0.14); display: flex; flex-wrap: wrap; align-items: center; gap: 18px; }
.tool__cta p { font-size: 16px; font-weight: 300; line-height: 1.72; color: rgba(28,31,26,0.72); flex: 1 1 300px; } /* panel-body */
.tool__cta strong { font-weight: 500; color: var(--ink); }

/* ---------- S6: interactive process sketch --------------------------- */
/* Hovering a phase rewinds the drawing to that stage (accumulation);
   default data-stage="5" = finished — also the no-JS / touch state. */
.sketch-stage { display: flex; justify-content: center; margin: 0 0 48px; }
.sketch-stage svg { width: min(720px, 92%); height: auto; overflow: visible; }
.sketch g[id^="g"] { transition: opacity 0.4s var(--ease), transform 0.4s var(--ease); }
.sketch[data-stage="1"] :is(#g2,#g3,#g4,#g5),
.sketch[data-stage="2"] :is(#g3,#g4,#g5),
.sketch[data-stage="3"] :is(#g4,#g5),
.sketch[data-stage="4"] #g5 { opacity: 0; transform: translateY(7px); }
/* the delivery in transit disappears once the module is installed */
.sketch .transient, .sketch .site-work { transition: opacity 0.4s var(--ease); }
.sketch[data-stage="5"] .transient { opacity: 0; }
/* site-built work painted with a unit for correct layering (e.g. the Rise's walkway
   deck under its walls) but shown only at Launch (Ayala 260914) */
.sketch:not([data-stage="5"]) .site-work { opacity: 0; }

/* ---------- S5: Why It Works — case cards ---------------------------- */
.why__cases { padding: 0 40px 64px; }
.case-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-top: 24px; }
.case-card { background: rgba(242,237,230,0.05); border: 1px solid rgba(242,237,230,0.12); padding: 30px 28px; }
/* small isometric marks, same drawing language as the process sketch but drawn
   for 48px: simplified geometry, heavier relative stroke, no texture */
.case-mark { display: block; width: 48px; height: 48px; margin-bottom: 16px; color: rgba(242,237,230,0.92); }
.case-card h3 { font-size: 18px; font-weight: 500; color: var(--fog); margin-bottom: 10px; }
.case-card p { font-size: 15px; font-weight: 300; line-height: 1.65; color: rgba(242,237,230,0.72); } /* 1.65 matches .icoitem p (Ayala 2026-08-19) */

/* ---------- 901–1100px: relax the 5-column grids --------------------- */
@media (min-width: 901px) and (max-width: 1100px) {
  .catalogue__row { grid-template-columns: repeat(3, 1fr); }
  /* (260918) the 3 + 2 phase grid is retired: below 1200px the phases run as a vertical timeline, see the phase-plate block */
}

/* ---------- Responsive ----------------------------------------------- */
@media (max-width: 900px) {
  .wwb-hero { padding: 90px 24px 90px; }
  .wwb-models { padding: 22px 24px 12px; }
  .catalogue__footer--cta { padding: 24px; }
  .why__cases { padding: 0 24px 48px; }
  .case-grid { grid-template-columns: 1fr; }
  .tool { padding: 26px 22px; }
  .tool__grid { grid-template-columns: 1fr; gap: 28px; }
  /* stacked triad: each box keeps a Cedar top edge with its icon set in */
  .triad__col { padding: 24px; }
  .triad-unit .triad__col { border-top: 1.6px solid rgba(159,120,77,0.55); }
}

/* =====================================================================
   REDESIGN PORT — 2026-08-17
   Styles for the V3 narrative structure ported from mockup-v3 (V3.21):
   hero pillars, Why We Exist grid, What We Build feature cards + gallery
   + light catalogue, integration band, Why It Works 3-card row + body,
   manufacturing-process modal. The visual pass (Phase 3) refines these.
   ===================================================================== */

/* ---------- S1: hero pillars (replace the retired subline) ---------- */
.hero__pillars { display: flex; flex-wrap: wrap; gap: 10px 26px; margin: 2px 0 40px; }
.hero__pillars span { font-size: 12px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242,237,230,0.85); }
.hero__pillars span + span::before { content: "·"; margin-right: 26px; color: var(--umber-bright); }

/* ---------- S2: Why We Exist — text + landscape figure --------------- */
.exist__grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: 60px; align-items: start; }
.exist__img img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4/4.6; }
.exist__figcap { font-size: 13px; font-weight: 300; letter-spacing: 0.06em; color: rgba(28,31,26,0.62); margin-top: 8px; }
.exist__cta { margin-top: var(--space-4); }

/* ---------- S3: What We Build — Moss ground (2026-08-17) --------------- */
/* "Paper" #FBF9F5 retired (off-palette, near-invisible against Warm White).
   Inverted alternation (260817 pm): WWB sits on Warm White between the
   Moss grounds of Why We Exist and How We Deliver. */
.build-lt { background: #E0E3DD; padding: var(--space-7) 40px; } /* Moss since 260909 (was Warm White) — see SURFACE FLIP note near .gap--exist */
.feat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 46px; }
.feat-card { background: #fff; border: 1px solid rgba(28,31,26,0.14); padding: 24px 24px 26px; }
.feat-card h3 { font-size: 16px; font-weight: 800; color: var(--forest); margin-bottom: 9px; }
.feat-card p { font-size: 14px; font-weight: 300; line-height: 1.68; color: rgba(28,31,26,0.72); }
.feat-card--wide { grid-column: 1 / -1; }
.subhead { font-family: 'Lexend Deca', sans-serif; font-size: clamp(20px, 2.6vw, 28px); font-weight: 800; line-height: 1.3; color: var(--ink); margin: 64px 0 24px; }
.gallery-fig { margin: 0; }
.gallery-fig img { width: 100%; aspect-ratio: 21/9; object-fit: cover; }
.catalogue__row--lt { padding: 0; }
.build-lt__cta { display: flex; justify-content: center; margin-top: 34px; }

/* ---------- S5: integration band ------------------------------------- */
.band { background: var(--forest); padding: 74px 40px; text-align: center; }
.band__line { font-family: 'Lexend Deca', sans-serif; font-weight: 300; font-size: clamp(19px, 2.4vw, 30px); line-height: 1.4; color: var(--fog); max-width: 980px; margin: 0 auto; }
.band__line strong { font-weight: 800; }

/* ---------- S6: belief paragraph rhythm ------------------------------- */
.cred__body--belief { margin-top: 30px; }
/* 260918: About Us now runs three body paragraphs (placemark.ca copy); same
   18px paragraph rhythm as Our Purpose, the belief line keeps its 30px lift */
.cred__body + .cred__body { margin-top: 18px; }
.cred__body + .cred__body--belief { margin-top: 30px; }
/* 260918 (Ayala): weight-only emphasis inside body copy, size and colour unchanged.
   About Us: the opening placemark.ca sentence in Medium. Our Purpose: the first
   sentence of the pull line back to Light, the rest of the pull stays Medium. */
.cred__lead { font-weight: 500; }
.exist-pull__lead { font-weight: 300; }

/* ---------- S8: Why It Works — body + three-card row ------------------ */
.why__body { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(242,237,230,0.72); max-width: 860px; margin-top: 22px; }
.case-grid--3 { grid-template-columns: repeat(3, 1fr); }
/* estimator panel: white + hairline (260817) — same card language as the
   case and catalogue cards, so it holds its edge on any light ground */
.why .tool { background: #fff; }

/* ---------- Manufacturing-process modal (CSS-only :target) ------------ */
/* No JS required: the Partnership button is a plain anchor, so the content
   is in the document for crawlers and the popup functions without script. */
.modal { position: fixed; inset: 0; z-index: 600; display: none; align-items: center; justify-content: center; padding: 28px; background: rgba(28,31,26,0.7); overscroll-behavior: contain; }
.modal:target { display: flex; }
/* scroll lock behind an open popup (house popup standard; also stops wheel
   scroll chaining to the page at the panel's ends). :has() is progressive —
   browsers without it keep today's behaviour. */
html:has(.modal:target) { overflow: hidden; }
/* ...and stays locked for a beat AFTER close: momentum-phase wheel events
   from a fast fling are non-cancelable, so the only reliable guard is a
   physical lock while the fling tail dies out (script.js toggles this). */
html.modal-settling { overflow: hidden; }
/* Scroll lock (2026-08-18): the page behind an open takeover is inert, so it
   must not scroll. :has() covers the CSS-only :target modals (works without
   JS) and the JS lightbox alike. scrollbar-gutter keeps the scrollbar's
   space reserved while locked so the layout doesn't shift (CLS). */
html { scrollbar-gutter: stable; }
body:has(.modal:target, .lightbox:not([hidden])) { overflow: hidden; }
/* One stage for every popup (2026-08-18, Ayala): the manufacturing modal
   matches the model sheets — 1440px / 94vh, same title scale, same
   retracting header bar. Top padding is 0 because the sticky bar carries
   its own (sticky pins to the scrollport's padding edge). */
.modal__panel { position: relative; background: var(--fog); max-width: 1440px; width: 100%; max-height: 94vh; overflow-y: auto; overscroll-behavior: contain; padding: 0 44px 40px; }
.modal__panel .eyebrow { margin-bottom: 10px; }
.modal__title { font-family: 'Lexend Deca', sans-serif; font-size: clamp(30px, 3.4vw, 44px); font-weight: 800; line-height: 1.15; color: var(--ink); margin-bottom: 26px; }
.modal__close { position: absolute; top: 12px; right: 16px; font-size: 24px; line-height: 1; color: rgba(28,31,26,0.62); padding: 8px 10px; }
.modal__close:hover { color: var(--ink); }
.modal__slides { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 18px; } /* 12 → 18 (Ayala 260824): clear air between the copy and the strip's scrollbar */
/* 260924 axe (scrollable-region-focusable): the strip takes keyboard focus (tabindex=0) so arrow keys scroll it;
   the ring shows for keyboard users only. */
.modal__slides:focus-visible { outline: 2px solid var(--umber); outline-offset: 4px; }
/* 48% of the 1440 stage ≈ the slide's old absolute size on the 920px panel;
   two slides in view with a peek of the third invites the sideways scroll */
.mslide { flex: 0 0 48%; scroll-snap-align: start; }
.mslide__ph { aspect-ratio: 16/9; border: 2px dashed rgba(28,31,26,0.28); background: rgba(28,31,26,0.03); display: flex; align-items: center; justify-content: center; text-align: center; padding: 12px; font-size: 12px; font-weight: 300; color: rgba(28,31,26,0.62); margin-bottom: 16px; } /* kept for future empty slots */
/* slide photos (260824: AI placeholders in, awaiting Elk Ridge photography) —
   same two modes as the ph box: 16/9 in flow, flexible grid cell on desktop */
.mslide__img { width: 100%; height: auto; aspect-ratio: 16/9; object-fit: cover; display: block; margin-bottom: 16px; } /* height:auto beats the height ATTRIBUTE (a presentational hint) so the aspect-ratio can govern */
/* slide type matches the catalogue sheets (Ayala 2026-08-19): h4 = .msheet__h
   size/weight, description = .msheet__desc size/leading */
.mslide h4 { font-size: 16px; font-weight: 800; color: var(--ink); margin-bottom: 8px; }
.mslide h4 span { color: var(--sunburst); margin-right: 8px; }
.mslide p { font-size: 15px; font-weight: 300; line-height: 1.72; color: rgba(28,31,26,0.72); }
.modal__hint { font-size: 10.5px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: rgba(28,31,26,0.62); margin-top: 14px; }
/* Manufacturing modal presence (2026-08-19, Ayala): the popup claims the
   same full 94vh stage as the model sheets — a short panel floating in
   scrim reads as discardable. The slide strip flexes to fill the height,
   photos stretching with it, so the footprint is earned by content.
   Mobile keeps natural flow (a forced 94vh panel wastes portrait space). */
/* no header bar (2026-08-19): the x floats at the content's top-right
   corner (ink flush with the 44px content edge, like the sheets' x aligns
   with the hero edge); the panel carries its own top padding again since
   no sticky bar needs the padding edge */
#mfg .modal__panel { padding-top: 34px; }
#mfg .modal__close { top: 26px; right: 44px; padding: 0 0 0 14px; font-size: 26px; z-index: 5; }
@media (min-width: 901px) {
  #mfg .modal__panel { height: 94vh; display: flex; flex-direction: column; }
  #mfg .modal__panel > :not(.modal__slides) { flex-shrink: 0; }
  /* equal boxes (2026-08-19): the strip is a 3-row grid (photo / heading /
     description) with rows SHARED across all slides — the tallest
     description sizes one common text row, so every photo box gets the
     identical height. Column flow keeps the horizontal scroll + snap. */
  #mfg .modal__slides { padding-bottom: 24px; flex: 1; min-height: 0; display: grid; grid-auto-flow: column;
    grid-auto-columns: 62%; grid-template-rows: 1fr auto auto; gap: 0 16px; }
  #mfg .mslide { display: contents; }
  #mfg .mslide__ph { aspect-ratio: auto; min-height: 0; scroll-snap-align: start; }
  /* height 100% would fill the whole 1fr row and swallow the 16px gap the
     old ph box kept (stretched divs subtract margins; explicitly-sized
     images don't) — so the photo cedes the gap from its own height */
  #mfg .mslide__img { aspect-ratio: auto; height: calc(100% - 16px); min-height: 0; margin-bottom: 0; scroll-snap-align: start; }
}
/* 260921 (Ayala): tablets in the desktop grid tier (iPad landscape, 1024) also page one full step
   at a time — no peek of the next card */
@media (min-width: 901px) and (max-width: 1100px) {
  #mfg .modal__slides { grid-auto-columns: 100%; grid-template-rows: auto auto auto; flex: none; }
  /* the desktop 1fr photo row stretched a lone column to the panel's height (880 x 995 on an iPad
     portrait); here the photo keeps the stand-ins' 4:3 and the panel sizes to its content */
  #mfg .mslide__img { height: auto; aspect-ratio: 4 / 3; margin-bottom: 16px; }
  #mfg .modal__panel { height: auto; max-height: 94vh; }
}
/* with JS the paging arrows carry the affordance — the written instruction
   is the no-JS fallback only */
.js .modal__hint { display: none; }
/* title and arrows share one bottom-aligned row, same as .cat-head */
.modal__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; margin-bottom: 26px; }
.modal__head .modal__title { margin-bottom: 0; }
.modal__head .cat-carousel__nav { margin-bottom: 0; }

/* ---------- Responsive ------------------------------------------------ */
@media (max-width: 900px) {
  .exist__grid { grid-template-columns: 1fr; gap: 36px; }
  .build-lt { padding: 72px 24px; }
  .feat-grid { grid-template-columns: 1fr; }
  .case-grid--3 { grid-template-columns: 1fr; }
  .mslide { flex-basis: 100%; }   /* 260921 (Ayala): one full step per view on phones and small tablets; the 12% peek is gone */
  /* popup panel's mobile padding lives in the ≤700px block with the model
     sheets, so the bar's negative margins always match the side padding */
}

/* =====================================================================
   HERO DESIGN PASS — 2026-08-17 (Ayala's aesthetic round 1)
   Transparent nav over the hero, clean render (no full-bleed dark mask),
   text in a contained panel per the approved art direction, smaller UVP.
   ===================================================================== */

/* Nav goes transparent while over the hero (class toggled by script.js;
   without JS the nav stays solid so it reads over every section). */
.nav.nav--over-hero { background: transparent; border-bottom-color: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }

/* The render shows clean. The only full-width shading left is a 160px top
   scrim so the transparent nav's logo and controls read over the sky. */
.hero__overlay { background: linear-gradient(to bottom, rgba(28,31,26,0.55), rgba(28,31,26,0) 160px); }

/* Text-over-image lives in a contained panel (art direction rule), not
   behind a page-wide mask. */
.hero__content { background: rgba(28,31,26,0.55); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); padding: 38px 42px; max-width: 760px; }

/* Two-line UVP at a calmer scale: still above the 52px section-heading
   ceiling for hierarchy, well under the old 90px. */
.hero__h1 { font-size: clamp(32px, 5.5vw, 68px); }

.hero__note { margin-top: 20px; font-size: 11px; font-weight: 300; line-height: 1.55; color: rgba(242,237,230,0.65); max-width: 560px; }

@media (max-width: 900px) {
  .hero__content { padding: 26px 24px; }
}

/* ---------- Two-line UVP, guaranteed (2026-08-17) -------------------- */
/* Each headline half is a no-wrap unit, the panel sizes to the headline,
   and the font scales with the viewport so the long line always fits on
   laptops and monitors. Under 560px the lines release and wrap naturally. */
.hero__content { width: fit-content; max-width: 100%; }
.hero__h1 { font-size: clamp(30px, 4.8vw, 62px); }
.hero__h1-line { white-space: nowrap; }
@media (max-width: 560px) {
  .hero__h1-line { white-space: normal; }
  .hero__h1 br { display: none; }   /* 260918: once the lines release, the forced break only made "Place," and "Launch." stand alone; the headline balances instead */
}

/* ---------- What We Build: sticky split (Option A, 2026-08-17) -------- */
/* Cards scroll in the left column; the render on the right is pinned below
   the fixed nav, so reading and seeing happen together. On small screens the
   pane sits first, then the cards, in one column. */
/* image as protagonist (260817): ~2/3 image on wide screens, easing to a
   gentler ratio on laptops so the benefit rows keep a readable measure */
.wwb-split { display: grid; grid-template-columns: 1fr 1.9fr; gap: 44px; align-items: start; margin-top: 46px; }
/* (260918) the 1fr / 1.4fr tablet grid is retired: below 1200px the split stacks instead, see the next block */
.wwb-cards { display: flex; flex-direction: column; gap: 14px; grid-column: 1; grid-row: 1; }
.wwb-pane { grid-column: 2; grid-row: 1; position: sticky; top: 92px; margin: 0; }
.wwb-pane img { width: 100%; aspect-ratio: 4/3.4; object-fit: cover; }
.wwb-pane__kicker { font-family: 'Lexend Deca', sans-serif; font-size: 17px; font-weight: 800; line-height: 1.35; color: var(--ink); margin-top: 16px; }
.feat-card--closer { margin-top: 44px; }
/* 260918 (Ayala, tablet review): stack render-over-features up to 1200px, not 900. In the
   two-column layout the pane stretches to the ledger's height; at 1024 (and 1152) the
   ledger is tall and the pane narrow, so the landscape renders were cropped to a portrait
   frame. Stacked, the pane keeps its 16:9 frame. From 1201px up the 1fr / 1.9fr split holds. */
@media (max-width: 1200px) {
  .wwb-split { grid-template-columns: 1fr; gap: 28px; }
  .wwb-pane { grid-column: 1; grid-row: 1; position: static; }
  .wwb-cards { grid-column: 1; grid-row: 2; }
}

/* ---------- What We Build: scrolling render stack (2026-08-17) -------- */
/* Without JS the three renders stack in normal flow (all content visible).
   With JS they layer in one frame and crossfade as the cards scroll past:
   cards 1-2 = winter, 3-4 = lakefront, 5-6 = forest. */
.wwb-pane__stack img { width: 100%; aspect-ratio: 16/9; object-fit: cover; }
.wwb-pane__stack img + img { margin-top: 10px; }
.js .wwb-pane__stack { position: relative; aspect-ratio: 16/9; overflow: hidden; }
.js .wwb-pane__stack img { position: absolute; inset: 0; height: 100%; margin: 0;
  opacity: 0; transition: opacity 0.55s var(--ease); }
.js .wwb-pane__stack img.is-shown { opacity: 1; }

/* ---------- What We Build: auto-rotation + lightbox (2026-08-17) ------ */
/* Slow crossfade for the rotating renders (1.2s; each holds ~3.3s full). */
.js .wwb-pane__stack img { transition: opacity 1.2s var(--ease), transform 0.55s var(--ease); }

/* Hover affordance matches the catalogue cards: gentle scale + Evergreen
   tint, plus a zoom-in cursor. Applied only once JS makes the pane clickable. */
.js .wwb-pane__stack.is-expandable { cursor: zoom-in; }
.js .wwb-pane__stack.is-expandable::after { content: ''; position: absolute; inset: 0;
  background: rgba(34,89,45,0); transition: background 0.3s var(--ease); pointer-events: none; }
.js .wwb-pane__stack.is-expandable:hover::after { background: rgba(34,89,45,0.28); }
.js .wwb-pane__stack.is-expandable:hover img.is-shown { transform: scale(1.04); }

/* Lightbox: dark room, image centered, arrows either side, zoom bottom right. */
.lightbox { position: fixed; inset: 0; z-index: 700; display: flex; align-items: center;
  justify-content: center; background: rgba(28,31,26,0.94); }
.lightbox[hidden] { display: none; }
.lightbox__frame { max-width: min(1400px, 88vw); max-height: 86vh; overflow: hidden;
  display: flex; align-items: center; justify-content: center; }
.lightbox__img { max-width: 100%; max-height: 86vh; transform-origin: center;
  transition: transform 0.25s var(--ease); touch-action: none; }
.lightbox__img.is-zoomed { cursor: grab; transition: none; }
.lightbox__img.is-zoomed:active { cursor: grabbing; }
.lightbox__close { position: absolute; top: 18px; right: 24px; font-size: 34px; line-height: 1;
  color: rgba(242,237,230,0.75); padding: 10px 14px; z-index: 1; }
.lightbox__close:hover { color: var(--fog); }
/* Full-height corridor zones (2026-08-18): the chevron stays small, but the
   whole blank band beside the image is the button (width set by JS to reach
   the image's edge; 90px floor). Clicking beside the image navigates —
   only clicks above/below it light-dismiss the viewer. */
.lightbox__nav { position: absolute; top: 0; bottom: 0; font-size: 48px;
  line-height: 1; color: rgba(242,237,230,0.75); padding: 18px 22px;
  min-width: 90px; display: flex; align-items: center; }
/* display:flex above beats the browser's own [hidden] rule — restate it so
   single-image viewers still lose their arrows */
.lightbox__nav[hidden] { display: none; }
.lightbox__nav:hover { color: var(--fog); background: rgba(242,237,230,0.05); }
.lightbox__nav--prev { left: 0; justify-content: flex-start; }
.lightbox__nav--next { right: 0; justify-content: flex-end; }
.lightbox__zoom { position: absolute; bottom: 22px; right: 24px; display: flex; gap: 8px; }
.lightbox__zoom button { width: 44px; height: 44px; font-size: 22px; line-height: 1; padding: 0;
  display: inline-flex; align-items: center; justify-content: center; color: var(--fog);
  border: 1px solid rgba(242,237,230,0.4); border-radius: 1px; } /* centred like .cat-nav__btn (260910) */
.lightbox__zoom button:hover { background: rgba(242,237,230,0.12); }
/* footer: on a pointer device the caption keeps its bottom-left pill; count and hint stay off */
.lightbox__foot { display: contents; }
.lightbox__count, .lightbox__hint { display: none; }
/* ---------- Lightbox on touch devices (Ayala 260921, iPhone 17 test) ----------
   No hover, coarse pointer: the corridor arrows had nowhere to live (the image spans
   the screen), the zoom buttons and caption pill fought for the same corner, and
   nothing answered the gestures a phone user makes. Now: the image sits above a
   footer row (caption, "2 / 8" counter), so nothing overlaps; arrows and zoom
   buttons are gone; swipe walks the set, pinch and double-tap zoom, drag pans while
   zoomed. A one-line hint sits in the footer for the first 3 s, then leaves on the
   first gesture. Tied to capability (hover/pointer), not width: an iPad in
   landscape gets this too, a laptop at the same width does not. */
.lightbox--touch { flex-direction: column; justify-content: center; padding: 56px 0 0; }
.lightbox--touch .lightbox__frame { width: 100%; max-width: none; max-height: none; touch-action: none; }
.lightbox--touch .lightbox__img { max-height: calc(100vh - 180px); max-height: calc(100dvh - 180px); }
.lightbox--touch .lightbox__nav, .lightbox--touch .lightbox__zoom { display: none; }
.lightbox--touch .lightbox__foot { display: grid; grid-template-columns: 1fr auto; column-gap: 16px; row-gap: 10px;
  width: 100%; padding: 16px 20px 0; min-height: 96px; align-content: start; }
.lightbox--touch .lightbox__cap { position: static; max-width: none; background: none; padding: 0;
  font-size: 13px; line-height: 1.5; color: rgba(242,237,230,0.82); }
.lightbox--touch .lightbox__cap[hidden] { display: block; visibility: hidden; }   /* keeps the row when a set has no caption */
.lightbox--touch .lightbox__count { display: block; font-size: 12px; letter-spacing: 0.1em; color: rgba(242,237,230,0.55); padding-top: 2px; }
.lightbox--touch .lightbox__hint { display: block; grid-column: 1 / -1; font-size: 11px; font-weight: 500; letter-spacing: 0.14em;
  text-transform: uppercase; color: rgba(242,237,230,0.5); opacity: 0; transition: opacity 0.4s; }
.lightbox--touch.is-hinting .lightbox__hint { opacity: 1; }
.lightbox--touch .lightbox__close { top: 8px; right: 12px; padding: 12px 14px; }
@media (prefers-reduced-motion: reduce) {
  /* re-assert here because the 1.2s crossfade rule above is later in the
     file than the global reduced-motion block */
  .js .wwb-pane__stack img { transition: none; }
  .js .wwb-pane__stack.is-expandable:hover img.is-shown { transform: none; }
  .lightbox__img { transition: none; }
}

/* ---------- What We Build: icon ledger + equal-height split (2026-08-17) */
/* Option C: benefits anchored by isometric marks, hairlines between items,
   no boxes. The two columns stretch to the same height: the list defines it
   and the render pane fills it (the lightbox still shows renders uncropped). */
.wwb-split { align-items: stretch; }
.wwb-pane { position: static; display: flex; flex-direction: column; }
.js .wwb-pane__stack { aspect-ratio: auto; flex: 1; min-height: 340px; }
.wwb-pane__kicker { flex: none; }
.wwb-cards { gap: 0; }
/* MARKS REMOVED SITE-WIDE (Ayala 260825): every decorative ledger drawing is
   gone — What We Build, How We Deliver triad, manufacturing certs, Why It
   Works. Only the INTERACTIVE phase sketch survives (plus the informational
   floor plans + comparison timelines). The ledgers are now pure text: one
   full-width column, flush left with their section headings, hairline
   dividers carrying the rhythm. Marked-up fallback: index-with-marks.html.
   Icon rules below are RETIRED, kept per house pattern in case marks return. */
.icoitem { display: grid; grid-template-columns: 1fr; padding: 17px 0; align-items: start; }
.wwb-cards .icoitem + .icoitem { border-top: 1px solid rgba(28,31,26,0.12); }
.wwb-cards .icoitem:first-child { padding-top: 0; }
/* Scale groups (260909): two C-style labels split the ledger into cabin-scale
   and land-scale attributes. Label sits in the eyebrow's Cedar; the second
   group opens with a hairline + air so the break reads as a change of scale. */
.wwb-cards__label { font-size: 12px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--umber-text); padding-bottom: 12px; }
.wwb-cards__label--place { margin-top: 0; padding-top: 26px; border-top: 1px solid rgba(28,31,26,0.14); } /* margin-top 30 → 0 (Ayala 260909): the rule now sits 17px under the last cabin row, the same gap as every other ledger rule; the 26px above the label keeps the group heading's air */
.wwb-cards .wwb-cards__label + .icoitem { padding-top: 0; }
.wwb-cards .icoitem:last-child { padding-bottom: 0; }
/* RETIRED 260825 (no ledger marks in the markup):
.icoitem svg { width: 44px; height: 44px; color: var(--ink); }
.wwb-cards .icoitem svg { color: rgba(28,31,26,0.75); width: 76px; height: 76px; }
   Treatment history for the traced set, if it ever returns: ink 75% general,
   composing with each icon's own per-piece depth opacities; 76px scene slot
   with strokes rebaked to ~1.5px rendered. */
.icoitem h3 { font-family: 'Lexend Deca', sans-serif; font-size: 18px; font-weight: 700; color: var(--ink); margin-bottom: 6px; } /* 16/800 → 18/700 (Ayala 260824: one ledger-title voice across WWB, triad, certs, Why It Works) */
.icoitem p { font-size: 15px; font-weight: 300; line-height: 1.65; color: rgba(28,31,26,0.72); }
.icoitem--closer { margin-top: 44px; padding-top: 26px; border-top: 1px solid rgba(28,31,26,0.14); }
@media (max-width: 1200px) {
  .js .wwb-pane__stack { aspect-ratio: 16/9; flex: none; min-height: 0; }   /* 260918: follows the 1200px stack */
}

/* ---------- Catalogue: two-up carousel (2026-08-17) ------------------- */
/* Two whole models per view; the third card starts exactly at the clipped
   edge, so nothing shows cut. Arrows (JS) page by one card; the track also
   scrolls natively, which is the no-JS path. */
.cat-carousel__nav { display: flex; justify-content: flex-end; gap: 8px; margin-bottom: 14px; }
/* One arrow button sitewide (catalogue, manufacturing popup, Our Craft). The
   chevron is drawn in CSS (a rotated 9px L in currentColor) and centred with
   flex, because the ‹ › glyphs in Lexend Deca sit low and off-centre in the
   box (Ayala 260910). The glyph stays in the HTML for no-CSS fallbacks and is
   hidden with font-size 0; the aria-label carries the name. */
.cat-nav__btn { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0; font-size: 0; line-height: 0; color: var(--ink);
  border: 1px solid rgba(28,31,26,0.35); border-radius: 1px; background: transparent;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease); }
.cat-nav__btn::before { content: ''; display: block; width: 9px; height: 9px;
  border-left: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; }
.cat-nav__btn--prev::before { transform: translateX(2px) rotate(45deg); }   /* the L's corner points left; the nudge puts the chevron's visual centre on the box centre */
.cat-nav__btn--next::before { transform: translateX(-2px) rotate(-135deg); }
/* Sunburst action accents (2026-08-17, Ayala): one rule sitewide —
   Sunburst marks "you can act here". Arrows, timeline current dot,
   in-copy link hovers, form focus. Celebration stays errors-only. */
.cat-nav__btn:hover { background: var(--sunburst); border-color: var(--sunburst); color: var(--fog); }
.cat-nav__btn:disabled { opacity: 0.3; cursor: default; background: transparent; color: var(--ink); }
.cat-track { display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 6px; }
.cat-track > .cat-card { flex: 0 0 calc((100% - 14px) / 2); scroll-snap-align: start; }
.cat-track .cat-card__img { height: auto; aspect-ratio: 16/10; }
@media (max-width: 860px) {
  .cat-track > .cat-card { flex-basis: 100%; }
}

/* ---------- Catalogue heading spacing (2026-08-17) -------------------- */
/* More air above the catalogue subhead than below it, so it reads as the
   carousel's heading rather than the benefit list's footer. */
#catalogue .subhead { margin-top: 120px; margin-bottom: 18px; }

/* ---------- Catalogue header row (2026-08-17) -------------------------- */
/* Heading and arrows share one row; the images start directly beneath, so
   the heading reads as the carousel's title. */
.cat-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px;
  margin: var(--space-6) 0 16px; }
.cat-head .subhead { margin: 0; }
.cat-head .cat-carousel__nav { margin-bottom: 0; }
@media (max-width: 860px) {
  .cat-head { margin-top: var(--space-5); }
}

/* ---------- Why We Exist: magazine interleave + parallax (2026-08-17) -- */
/* Site-wide rule for the depth effect: only full-bleed landscape imagery
   parallaxes (hero, this band, the Partnership backdrop). Contained images
   stay still; text never moves. */
.exist-intro, .exist-close { max-width: 900px; }
.exist-band { margin: 48px -40px; }
.exist-band__media { position: relative; aspect-ratio: 21/8; overflow: hidden; }
.exist-band__media img { position: absolute; left: 0; top: -180px; width: 100%;
  height: calc(100% + 360px); object-fit: cover; will-change: transform; }
.exist-band { position: relative; }
/* caption sits inside the photo, bottom-left, on a soft ink pill so it holds
   contrast over any part of the image (text-over-image stays contained) */
.exist-band__cap { position: absolute; left: 24px; bottom: 16px; padding: 6px 11px;
  font-size: 12px; font-weight: 400; letter-spacing: 0.06em;
  color: rgba(242,237,230,0.92); background: rgba(28,31,26,0.55); }
.exist-close { margin-top: 44px; } /* RETIRED 260824 — argument-first restructure; markup removed, CSS kept */
/* Why We Exist: argument first, panorama after (260824, Ayala — Option B).
   The four-step argument reads unbroken (tighter in-section paragraph
   rhythm so the full text frame fits ~660px at 1366×768); the Tobiano
   band closes the section as the proof shot. */
.gap--exist .exist-intro { max-width: 940px; }
.gap--exist .exist-intro .gap__body + .gap__body { margin-top: 18px; }
.gap--exist .exist-pull { margin-top: 26px; }
.gap--exist .exist__cta { margin-top: 28px; }
.gap--exist .exist-band { margin: 56px -40px 0; }
/* SURFACE FLIP (Ayala 260909): Our Craft landed between Our Product and Our
   Service, and the page alternates Moss / Warm White strictly. Cheapest
   re-alternation runs upstream: Our Purpose → Warm White, Our Product → Moss,
   Our Craft → Warm White, Our Service stays Moss. Everything from Our Service
   down is untouched. */
.gap--exist { background: var(--fog); }
/* .gap.gap--exist { padding-bottom: 0; }  RETIRED 260909 — the Tobiano band that was the section's bottom edge is gone (Theo 260901); the section takes the standard --space-7 bottom padding again. */ /* the band IS the section's bottom edge (Ayala 260824) — same flush pattern as the full-bleed grids in Who We Are / Why It Works. Double class: must outrank the section-rhythm rule further down */
@media (max-width: 900px) {
  .gap--exist .exist-band { margin: 40px -24px 0; }
}
.exist-pull { font-family: 'Lexend Deca', sans-serif; font-size: clamp(18px, 2.1vw, 25px);
  font-weight: 800; line-height: 1.42; color: var(--ink); margin-top: 34px; max-width: 880px; }
.exist-pull em { font-style: normal; color: var(--forest); }
/* the partner backdrop overscans so its parallax drift never exposes edges */
.partner .partner__bg.parallax__media { top: -180px; bottom: -180px; will-change: transform; }
@media (max-width: 900px) {
  .exist-band { margin: 36px -24px; }
  .exist-band__cap { padding: 10px 24px 0; }
}

/* ---------- Heading line-height fix (2026-08-17) ----------------------- */
/* 1.04 let descenders touch the line below on two-line headings ("g" over
   the "i" dot). 1.12 clears them; applied to every section heading so the
   rhythm stays consistent site-wide. */
.gap__h2, .cred__h2, .partner__h2, .why__h2, .catalogue__h2,
.process__h2, .contact__h2 { line-height: 1.12; }

/* ---------- How We Deliver: intro split (Option A, 2026-08-17) --------- */
.deliver-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 48px; align-items: stretch; }
.deliver-img { margin: 0; overflow: hidden; }
.deliver-img img { width: 100%; height: 100%; object-fit: cover; }
/* triad in-column: compact ledger rows, same language as the WWB benefits */
.deliver-triad { margin-top: 30px; }
.deliver-triad .triad__heading { margin: 0 0 4px; }
/* items use the SAME sizes as the What We Build ledger (Ayala 2026-08-19):
   one .icoitem rule set serves both sections, so they cannot drift apart.
   The photo column stretches to the text column, keeping edge alignment. */
.deliver-triad .icoitem + .icoitem { border-top: 1px solid rgba(28,31,26,0.12); }
/* 260918 (Ayala, tablet review): the text + photo grid stacks up to 1200px (was 900), the same
   rule as Our Product. In two columns at 1024 the photo was 427px wide and the callout cards
   squeezed to 154px; stacked, the photo is 944px wide and the cards read at desktop size. */
@media (max-width: 1200px) {
  .deliver-grid { grid-template-columns: 1fr; gap: 32px; }
  .deliver-img img { height: auto; aspect-ratio: 4/3; }
}

/* ---------- Section rhythm: one breathing token (2026-08-17) ----------- */
/* Consistent vertical air between sections, one knob for the whole site:
   128px between sections on desktop, 84px on small screens. The scale reads
   128 (between sections) > 64 (between sub-blocks) > 44 (heading to body)
   > 24 (paragraph to paragraph). Dark sections that end flush with a
   full-bleed grid (Who We Are, Why It Works) keep their bottom edge. */
:root { --section-y: 128px; }
@media (max-width: 900px) { :root { --section-y: 84px; } }
.gap, .process, .build-lt, .contact, .partner {
  padding-top: var(--section-y); padding-bottom: var(--section-y); }
.why, .cred { padding-top: var(--section-y); }
.band { padding-top: 96px; padding-bottom: 96px; }

/* ---------- How We Deliver ↔ Map Your Project: one section (2026-08-17) */
/* Both blocks belong to How We Deliver: the gap between them drops to the
   within-section token (64px total), and Map Your Project gets the same
   heading hierarchy as the estimator's "What could your land earn?" —
   it is an invitation, not a label. */
#how-we-deliver { padding-bottom: var(--space-6); } /* was 0; restored 260824
   (Ayala: the comparison heading sat too tight to the intro half). Seam total
   = 64 + the process half's 128 = 192px: more than the 96px module gap,
   less than a true section break (2 × 128). */
.process { padding-top: var(--space-6); }
.process__title { font-family: 'Lexend Deca', sans-serif; font-size: clamp(20px, 2.6vw, 28px);
  font-weight: 800; line-height: 1.2; color: var(--ink); } /* #3 cut (260824): one step under the comparison's .cmp__h3 */
.process__lede { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72); max-width: 740px; margin: 12px 0 36px; }
.lede-br { display: none; } /* the phases lede holds two fixed lines on desktop */
@media (min-width: 761px) { .lede-br { display: inline; } }
/* 260917: the Our Product lede breaks after "alpine ridges," (Ayala). Its first
   line is ~785px at 16px, so the break only switches on from 901px, where the
   860px column is available; below that the sentence flows naturally. */
/* .lede-br--wide (the Our Product lede split after "alpine ridges,") RETIRED
   260918: the lede now takes the ledger column's measure (see the Measure
   system block), where that first line no longer fits. */

/* ---------- Line balance (260918, Ayala) --------------------------------
   Short blocks (headings, ledes, pull lines) balance their lines with
   text-wrap: balance, so a two-line lede never pairs a full line with a
   three-word one (the Our Craft lede at 1920 read 99% / 37%). Body
   paragraphs use text-wrap: pretty, which only stops a lone last word.
   Both are progressive: browsers without them wrap exactly as before.
   Deliberate breaks (.lede-br, .lede-br--wide, the clause <br>s in the
   About and Partner headings) stay on laptop/desktop; below their
   breakpoints the text flows and balances instead of forcing a widow. */
h1, h2, h3, .craft__lede, .process__lede, .hero__sub, .statement, .exist-pull, .subhead, .band__line, .tool__lede { text-wrap: balance; }
p { text-wrap: pretty; }
/* the Partner heading's first clause is nowrap for the two-line lockup; on
   narrow phones (< 420px) it would overflow the column, so it may wrap */
@media (max-width: 420px) { .partner__h2 .nowrap { white-space: normal; } }

/* Our Craft lede (Ayala 260918): first line ends at "is carefully". That line
   needs ~640px, so the break shows only where the lede column has it: the
   stacked layout from 761px up to the 1100px grid switch, and the two-column
   layout from 1580px (column = 0.45 x (vw - 120)). In between, balance rules. */
.lede-br--craft { display: none; }
@media (min-width: 761px) and (max-width: 1100px), (min-width: 1580px) { .lede-br--craft { display: inline; } }

/* Our Product features (Ayala 260918): ONE shared right boundary, text-editor
   style, greedy wrapping. The boundary is the ledger column itself (the same
   edge the section lede now ends at; see the Measure system block), so no
   separate cap is needed. (Earlier the same day: a balance + spacer
   treatment, then a 35.8em cap set by one chosen line; both retired.) */
.wwb-cards .icoitem p { max-width: none; }

/* The comparison opens a new movement inside the arc: one full step up the
   spacing scale to the section rhythm (Ayala 260824; was space-7). */
.process { padding-top: 80px; } /* was space-8 (128): seam image→plate cut by a quarter, 192 → 144 (Ayala 260910) */

/* Laptop-height fit (2026-08-20, friend feedback): on short viewports the
   sketch + phase track must share one screen so the hover reveal and the
   drawing are visible together. The sketch shrinks and vertical air tightens;
   nothing is hidden. Targets ~768–900px-tall laptop screens (1366×768 /
   1280×800 / MacBook 1440×900 minus browser chrome). */
@media (max-height: 900px) and (min-width: 761px) {
  .process { padding-top: var(--space-4); } /* 64 → 32: gap 128 → 96 (Ayala 260910) */
  .process__header { margin-bottom: 10px; }
  .sketch-stage { margin-bottom: 20px; }
  .sketch-stage svg { width: min(470px, 62%); }
  .process__hint { margin: -10px 0 20px; }
}
/* shortest common laptops (1366×768 minus browser chrome ≈ 630–660px usable):
   the sketch compresses further so sketch + track + open reveal share one screen */
@media (max-height: 800px) and (min-width: 761px) {
  .process { padding-top: var(--space-3); } /* 48 → 24: gap 112 → 88 (Ayala 260910) */
  .process__header { margin-bottom: 8px; }
  .sketch-stage { margin-bottom: 14px; }
  .sketch-stage svg { width: min(325px, 44%); }
  .process__hint { margin: -8px 0 16px; }
}

/* ---------- Integration band: imagery + staged text (2026-08-17) ------- */
/* Option A+B: full-bleed dusk render with the site's parallax drift; the
   sentence rides a contained ink panel and assembles in stages on entry.
   Hidden states are scoped to .js so the no-JS band is complete and still;
   reduced motion gets the finished state with no transitions. */
.band { position: relative; overflow: hidden; padding: 0; }
.band__media { position: absolute; inset: -160px 0; }
.band__media img { width: 100%; height: 100%; object-fit: cover; will-change: transform; }
.band__inner { position: relative; padding: 150px 40px; display: flex; justify-content: flex-start; }
/* text sits directly on the image, left side, over the dark water; a soft
   text-shadow keeps the fog type legible across the drift */
.band__panel { text-align: left; max-width: 720px; }
.band__line { font-family: 'Lexend Deca', sans-serif; font-weight: 300;
  font-size: clamp(19px, 2.4vw, 30px); line-height: 1.4; color: var(--fog);
  text-shadow: 0 1px 22px rgba(28,31,26,0.45); }
.band__l1 { display: block; }
.band__l2 { display: block; font-weight: 800; font-size: 1.35em; margin-top: 10px; }
.band__rule { width: 72px; height: 2px; background: var(--umber); margin: 26px 0 0; }
.js .band__l1 { opacity: 0; transform: translateY(18px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.js .band__l2 { opacity: 0; transform: translateY(22px);
  transition: opacity 0.9s var(--ease) 0.55s, transform 0.9s var(--ease) 0.55s; }
.js .band__rule { width: 0; transition: width 1.1s var(--ease) 1.1s; }
.js .band.lit .band__l1, .js .band.lit .band__l2 { opacity: 1; transform: none; }
.js .band.lit .band__rule { width: 72px; }
@media (max-width: 900px) {
  .band__inner { padding: 100px 24px; }
  .band__panel { padding: 26px 24px 24px; }
}
@media (prefers-reduced-motion: reduce) {
  .js .band__l1, .js .band__l2 { opacity: 1; transform: none; transition: none; }
  .js .band__rule { width: 72px; transition: none; }
}

/* ---------- Model tech sheets (2026-08-17) ----------------------------- */
/* Catalogue cards open scrollable spec popups; prev/next anchors chain the
   five models. Same :target mechanism as the manufacturing modal. */
.cat-card__link { display: block; color: inherit; }
/* top padding lives on the sticky bar, not the panel: sticky pins to the
   scrollport's PADDING edge, so panel padding-top would make the bar stick
   28px down with content sliding through the gap */
/* Wide stage (2026-08-18, Ayala): the catalogue is the page's core, so
   the sheets get presence: 1440px, 94vh, 21:9 hero, larger title. The
   full-takeover variant was deferred to post-launch dedicated model pages.
   Panel sizing + title scale now live on the base .modal__panel /
   .modal__title rules — every popup shares the stage. */
/* HOUSE STANDARD for popup headers (2026-08-18, Ayala) — apply to every
   future popup: a slim sticky bar that RETRACTS on scroll-down (content is
   protagonist) and returns on the first scroll-up (controls one gesture
   away). JS toggles .is-tucked per scroll direction; reduced-motion users
   keep the bar always visible. Manufacturing modal migrated 2026-08-18. */
.msheet__nav { display: flex; align-items: center; gap: 18px;
  border-bottom: 1px solid rgba(28,31,26,0.12);
  position: sticky; top: 0; z-index: 5; background: var(--fog);
  margin: 0 -44px 22px; padding: 13px 44px 11px;
  transition: transform 0.3s var(--ease); }
.msheet__nav.is-tucked { transform: translateY(-110%); }
@media (prefers-reduced-motion: reduce) {
  .msheet__nav { transition: none; }
  .msheet__nav.is-tucked { transform: none; }
}
.msheet__arrow { font-size: 12px; font-weight: 500;   /* 11 -> 12 (260925 size floor) */ letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(28,31,26,0.65); padding: 6px 0; }
.msheet__arrow:hover { color: var(--sunburst-dark); }
.msheet__count { font-size: 11.5px; letter-spacing: 0.16em;   /* 10 -> 11.5 (260925 size floor) */ color: rgba(28,31,26,0.65);   /* 260924 axe: 0.45 = 2.74:1 -> 0.65 = 4.7:1 */
  position: absolute; left: 50%; transform: translateX(-50%); margin: 0; }   /* 260925 (Ayala): pinned to the bar's centre - with margin auto it centred between two arrows of different lengths and drifted sheet to sheet */
.msheet__count + .msheet__arrow { margin-left: auto; }   /* the next-arrow keeps the right edge now that the count is out of the flow */
/* top: -2px is optical, not structural: the boxes already center, but the
   x glyph's ink sits 2px below its em-box center in Lexend (measured on
   rendered pixels) — lift it so the INK centers with the labels' ink */
/* top: -2px lifts the glyph ink to the labels' optical center (measured);
   right padding is 0 so the ink sits flush on the content/photo right edge:
   the hit area lives entirely on the left, where nothing else sits */
.msheet__nav .modal__close { position: relative; top: -2px; right: auto; order: 4; margin-left: 6px; font-size: 26px; padding: 2px 0 2px 14px; }
/* a bar whose only control is the close (manufacturing modal) keeps it at
   the right edge, where every other popup puts it */
.msheet__nav .modal__close:only-child { margin-left: auto; }
/* Model sheets (260909, Ayala): the type label ("Studio · Single-Storey") was
   removed from the sheets — the lede and the stats block already carry it, and
   the catalogue card shows it before the click. .modal__title keeps its 26px. */
.msheet__lede { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72);
  max-width: 1000px; margin: -12px 0 24px; } /* 680 → 1000 (Ayala 260909): the lede must hold one line on a laptop; all five ledes are 80–91 characters */
/* Hero frame (260925, Ayala, option A "full width"): the 21:9 band (260818) cropped the roof
   and deck on every model. The frame is now the renders' native 16:9 at the column width on
   every screen, so all six show the whole file with the same framing (2400x1350/1351, never
   cropped, per 260925 rule). Option B (fit-to-screen, centred, narrower on laptops) was made
   live first and reverted the same day: Ayala weighed size + left alignment above "everything
   visible at open". The bottom of the render sits below the first screen on shorter viewports
   (1920x970: 18px; 1366x768: 126px) and comes in on scroll. */
.msheet__hero { width: 100%; aspect-ratio: 16/9; object-fit: cover; display: block; }
/* Trim above the picture (260925, Ayala): the stack from the sticky bar to the hero was 193px;
   the three gaps below step down to 16px (bar 22->16, title 26->16, lede 24->16) = 169px, so
   24px more of the render fits on the first screen. Model sheets only; the manufacturing popup
   keeps its own rhythm. */
.modal--model .msheet__nav { margin-bottom: 16px; }
.modal--model .modal__title { margin-bottom: 16px; }
.modal--model .msheet__lede { margin-bottom: 16px; }
/* stats as an open row — no grid, no boxes (Ayala 260817) */
.msheet__stats { display: flex; flex-wrap: wrap; gap: 18px 44px; margin-top: 30px; }
.msheet__stats b { display: block; font-size: 11px; font-weight: 500; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--umber-text); margin-bottom: 5px; }
.msheet__stats span { font-size: 14.5px; font-weight: 500; color: var(--ink); }
/* Phones + small tablets: the wrapping flex row packed the six stats by their own widths
   (3 unaligned columns on The Ledge; a lone Total area on a third row elsewhere). Below 900px
   they sit in a fixed 3-column grid, two rows, columns aligned; the (b)/span pair keeps its
   scale and shrinks one step on narrow phones so long values fit a ~96px column (Ayala 260921). */
@media (max-width: 900px) {
  .msheet__stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 16px; }
  .msheet__stats span { display: block; line-height: 1.3; }
}
@media (max-width: 600px) {
  /* phones 401-600: the first track takes a little more room so the longest value
     ("2 · Murphy bed") holds one line; tracks are shared by both rows, so columns align */
  .msheet__stats { grid-template-columns: 1.3fr 1fr 1fr; gap: 16px 12px; }
}
@media (max-width: 400px) {
  /* narrow phones: Lexend Deca is a wide face and three columns cannot hold "TOTAL AREA" or
     "2 · Murphy bed" on one line at 360 even a size down; two columns, three rows, full type
     size, six cells fill the grid exactly (no orphan) (Ayala 260921) */
  .msheet__stats { grid-template-columns: 1fr 1fr; gap: 16px 16px; }
}
.msheet__desc { font-size: 15px; font-weight: 300; line-height: 1.72; color: rgba(28,31,26,0.72);
  max-width: 780px; margin-top: 42px; }
/* simplified plan diagrams: a drawing, not a photograph — modest scale,
   transparent on the fog panel, left-aligned (2026-08-18, Ayala) */
.msheet__plansvg { width: 100%; max-width: 620px; height: auto; display: block;
  background: transparent; border: none; }
.msheet__h { font-family: 'Lexend Deca', sans-serif; font-size: 16px; font-weight: 800;
  color: var(--ink); margin: 44px 0 16px; }
.msheet__plan { width: 100%; border: 1px solid rgba(28,31,26,0.12); background: #fff; }
.msheet__cap { font-size: 13px; font-weight: 300; line-height: 1.6; color: rgba(28,31,26,0.62);
  margin-top: 10px; }
.msheet__gal { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.msheet__gal img { width: 100%; aspect-ratio: 16/10; object-fit: cover; }
/* Option B (2026-08-18): sheet renders open the shared lightbox */
.msheet__hero, .msheet__gal img { cursor: zoom-in; }
.msheet__gal img { transition: transform 0.3s var(--ease); }
.msheet__gal img:hover { transform: scale(1.02); }
/* 260922: a sheet whose renders have not arrived (The Lookout) uses the dashed placeholder in the
   hero slot too, at the hero's proportion so the sheet keeps its rhythm. */
.msheet__ph--hero { aspect-ratio: 21/9 !important; }
@media (max-width: 1200px) { .msheet__ph--hero { aspect-ratio: 16/9 !important; } }
.msheet__ph { aspect-ratio: 16/10; border: 2px dashed rgba(28,31,26,0.28); background: rgba(28,31,26,0.03);
  display: flex; align-items: center; justify-content: center; text-align: center; padding: 14px;
  font-size: 12.5px; font-weight: 300; line-height: 1.5; color: rgba(28,31,26,0.6); }
.msheet__cta { margin-top: 30px; padding-top: 22px; border-top: 1px solid rgba(28,31,26,0.12); }
@media (max-width: 700px) {
  .modal__panel { padding: 0 20px 30px; }
  #mfg .modal__panel { padding-top: 30px; }
  #mfg .modal__close { right: 20px; top: 20px; }
  /* Manufacturing popup on phones (Ayala 260921, iPhone 17): the 30px title wrapped to three
     lines beside the arrows and pushed the strip down; the photos ran at 88% width under
     15px copy. Now: title one line at 22px across the full width; the arrows join the close
     in a top-right control cluster (36px on phones, still tappable); photo full width at the
     stand-ins' own 4:3, so it is the largest thing on screen; step title 14px, copy 13.5px
     (the caption tier, C-scale), still legible. */
  #mfg .modal__panel { padding-top: 34px; padding-bottom: 22px; }
  #mfg .modal__panel .eyebrow { margin-bottom: 22px; }   /* r4: the arrow cluster sits on the eyebrow line and needs 12px+ clear of the title */
  #mfg .modal__head { display: block; margin-bottom: 22px; }   /* 260921 r3: the top cluster read cramped against the title while the foot had spare air */
  #mfg .modal__slides { padding-bottom: 6px; }
  #mfg .modal__title { font-size: 22px; line-height: 1.2; }
  #mfg .cat-carousel__nav { position: absolute; top: 26px; right: 50px; gap: 6px; }
  #mfg .modal__close { top: 27px; }
  #mfg .cat-carousel__nav .cat-nav__btn { width: 32px; height: 32px; }
  #mfg .mslide__img { aspect-ratio: 4/3; margin-bottom: 12px; }
  #mfg .mslide h4 { font-size: 14px; margin-bottom: 6px; }
  #mfg .mslide p { font-size: 13.5px; line-height: 1.6; }
  .msheet__nav { margin: 0 -20px 20px; padding: 11px 20px 9px; }
  .msheet__gal { grid-template-columns: 1fr; }
  .msheet__arrow { font-size: 11px; }   /* 10 -> 11 (260925) */
  /* top bar holds one line on phones: arrows and counter never wrap (Ayala 260921 capture at 360) */
  .msheet__nav { gap: 12px; }
  .msheet__arrow, .msheet__count { white-space: nowrap; }
  /* 260925 (Ayala): arrows drop "The" on phones (.msheet__the is the wrapped word) so the pinned counter clears
     the longest name from 371px up; below that the counter goes back IN FLOW (pinned, "Lookout" still collided by 10px at 360) */
  .msheet__the { display: none; }
}
@media (max-width: 370px) {
  .msheet__count { position: static; transform: none; margin: 0 auto; }
  .msheet__count + .msheet__arrow { margin-left: 0; }
}
@media (max-width: 400px) {
  .msheet__arrow { letter-spacing: 0.08em; }
  .msheet__count { letter-spacing: 0.1em; }
  .msheet__nav .modal__close { padding-left: 8px; }
}

/* ---------- Map Your Project: hover invitation (2026-08-17) ------------ */
.process__hint { text-align: center; font-size: 11px; font-weight: 500; letter-spacing: 0.16em;
  text-transform: uppercase; color: rgba(28,31,26,0.55); margin: -22px 0 36px; }
.process__hint svg { vertical-align: -3px; margin-right: 7px; display: inline-block; }
/* 260921 (Ayala): touch devices cannot hover, so the hint reads "Tap each phase..." there. 260922 (Ayala):
   the tablet tier (<=1200px, the vertical list) drops "Hover or" by width too - tablets are tactile whether
   or not the browser reports hover:none. Capability query kept for touch laptops. Desktop/laptop keeps the
   full sentence. The source text stays whole for crawlers; the style is uppercase so the capital needs no change. */
@media (hover: none), (max-width: 1200px) { .process__hint .hint-hover { display: none; } }
.phase { cursor: pointer; }

/* Hint-icon attention pulse (Ayala 260820: soft pulse, amplified — the
   sampler's 1.16× read as too subtle). script.js adds .hint-attention once
   the self-demo has ended or been interrupted; from then on it pulses
   CONTINUOUSLY while no phase is active, and rests (.hint-paused, set by
   script.js) while the visitor hovers, taps or focuses a phase (Ayala 260915;
   was four breaths then stop). Reduced-motion visitors never receive the class
   (the demo is skipped), and the media rule below is belt and braces. */
@keyframes hint-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.42); opacity: 0.6; }
}
.process__hint.hint-attention svg { animation: hint-pulse 1.6s ease-in-out infinite; transform-origin: center; }
.process__hint.hint-attention.hint-paused svg { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .process__hint.hint-attention svg { animation: none; }
}

/* ---------- How We Deliver: comparison module (2026-08-20, Ayala) ------- */
/* Option 1 dual timeline: conventional site build vs Placemark. Opens the
   Map Your Project section. All colours are palette values or alpha washes
   of them — no new hex tints (the 260820 solid ramp was retired same day:
   too heavy against the drawing language). Legend/foot ink at 0.65 per the
   contrast scale. */
.cmp { margin: 0 0 var(--space-7); } /* opens the section (Ayala 260820 pm); full width + left-anchored, like the phase track */
.cmp__foot { margin-bottom: 0; }
.cmp__head { margin-bottom: 40px; } /* now the plate's first child (Ayala 260910): heading + lede sit on the sheet with the timelines, so the unit reads as one */
.cmp__h3 { font-family: 'Lexend Deca', sans-serif; font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 800; line-height: 1.15; color: var(--ink); margin-bottom: 14px; } /* = .process__title scale */
.cmp__lede { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72); max-width: 980px; } /* = .process__sub scale; measure 740 → 980 (260910) so the four-beat lede holds three to four lines inside the plate and the frame */
/* Comparison in the phase track's line + dot grammar (ported 260824 from
   the narrative draft). One meaning per mark: hollow 2px-outline node = a
   beginning · filled 10px dot = a stage · 20px outlined circle with a chunky
   2.5px drawn check = an inspection gate (replaces the dot, sits on the line)
   · 16px haloed dot = the destination. Conventional row = ink/cedar; the
   Placemark row is the only Evergreen line. */
/* Depth (Option A, approved 260824): the instrument rides a contained Warm
   White plate. A bounded surface reads as a sheet laid ON the Moss ground —
   an object, not a ground change — so it cannot read as a section boundary
   (the rejected full-bleed swap did). Hairline edge + one low, tight shadow
   lift it without gloss; chips are fog-filled to match the plate. */
/* Plate fill (Ayala 260910): Warm White at 30% over WHITE — a near-white with a
   slight warm cast (#FBFAF8), so the plate reads as one sheet, warm, yet distinct
   from the Warm White sections. Composited to a solid colour on purpose: the
   Moss ground must not show through. Not a playbook colour — flag as a
   Directional-tier candidate ("plate white"). Hollow markers share the fill. */
.cmp__plate{--plate-solid:#FBFAF8;background:#FBFAF8;border:1px solid rgba(28,31,26,0.07);border-radius:2px;
  padding:46px 50px 40px;box-shadow:0 22px 44px -34px rgba(28,31,26,0.35)}
/* Desktop: the subheading runs inline after the name, joined by an interpunct drawn
   in CSS so the mark can be dropped where the line stacks (Ayala 260921). */
/* 260921 r4: the check is an SVG path centred in the ring's box (a rotated CSS "L" has an
   off-centre visual mass, as the deliver-card gates found earlier). Same box as ::before. */
.lspacer{flex:34}
/* ---------- Comparison timelines, VERTICAL below 900px (260918, Ayala) ----
   A horizontal timeline is a landscape instrument: at 768 it overran the plate
   by 74px and on phones it hid half its steps behind a sideways scroll with no
   hint. Below 900px each row becomes a vertical list: the 2px line runs down
   the left, the same node grammar sits on it (hollow start, filled stage,
   checked gate, haloed destination), step text to the right. The Placemark
   row's two parallel lanes flatten into one sequence (its label already says
   "factory + land in parallel"). Markup unchanged; desktop untouched. The
   260824 swipe canvas (overflow-x scroller, min-width 640) is retired. */
@media (max-width: 900px) {
  /* seam photo -> comparison plate = 48px, the same air as plate -> phase plate below it
     (Ayala 260921: the two gaps must match on phones and tablets). Was 44 + 24 = 68. */
  #how-we-deliver { padding-bottom: 24px; }
  .process { padding-top: 24px; }
      /* row header stacks (Ayala 260918): name on its own line, the measure beneath it as a
     subtitle; side by side the two fought for the same 300px and read as clutter */
      /* subheading on its own line under the name, no interpunct (Ayala 260921): inline it
     broke mid-phrase ("factory + land / in parallel") and the dot became a stray mark */
          /* 260922 (Ayala): the LEFT EDGE of the widest marker sits on the content edge, level with the h3 - the markers
     used to hang left of it. Line centres share one x (11px in): conventional 3px line -> margin 9.5 (centre 9.5 + 1.5),
     Placemark 4px line -> margin 9 (centre 9 + 2); its 22px gate then starts at 11 - 11 = 0. Widths shrink to match.
     Declared after the ranking block's vertical rules would be simpler, but this tier runs first in the file, so
     the same values are repeated in TIMELINES RANKED (vertical) to keep the cascade honest. */
        .lspacer { display: none; }
      /* r4: markers centred on the 2px line (x = -1) and on the first text line (y ~ 9.5) */
                    }
@media (max-width: 760px) { .cmp__plate { padding: 22px 24px 20px; } }
/* Laptop-height fit: the plate (+86px) and the enlarged step/sub type
   (260824) pushed the framed moment (heading + lede + plate) past the
   ~660px usable at 1366×768. On short laptops the AIR tightens — plate
   padding, row gaps, line-to-text padding — never the type: the sizes
   were raised for legibility and must hold exactly where laptops look.
   Same tier as the sketch/track compression above. */
@media (max-height: 800px) and (min-width: 761px) {
  .cmp__head { margin-bottom: 22px; }
  .cmp__plate { padding: 22px 36px 20px; }
        }

/* ---------- Who We Are: Warm White ground ------------------------------ */
/* Ayala: Placemark never uses black backgrounds; parent site is light.
   Ground history: Ink → Moss (260817 am) → Warm White (260817 pm, ground
   re-sequence: Moss/Mud read as value-twins, so grounds must alternate
   warm ↔ green-grey; Mud retired from the page, Moss stays — playbook
   amendment now Moss only). */
.cred { background: var(--fog); }
.cred .eyebrow { color: var(--umber-text); } /* Warm White ground → Cedar */
.cred__h2 { color: var(--ink); }
.cred__body { color: rgba(28,31,26,0.74); }
.cred__emphasis { color: rgba(28,31,26,0.9); font-weight: 500; }
.cred__caption { color: rgba(28,31,26,0.64); }   /* 260924 axe: 0.62 = 4.46:1 -> 0.64 = 4.7:1 */

/* ---------- Who We Are: expanding project panels (2026-08-17) ---------- */
/* Full-bleed, four full-height panels; the hovered (or keyboard-focused)
   panel widens to ~3x while the others compress. Touch: first tap expands
   (browser hover emulation), second follows the link. Without JS or hover:
   four equal panels. */
.xpanels { display: flex; gap: 6px; height: 66vh; min-height: 420px; }
.xpanels a { position: relative; flex: 1; overflow: hidden; transition: flex 0.7s var(--ease); }
.xpanels a:hover, .xpanels a:focus-visible { flex: 3.2; }
.xpanels img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.7s var(--ease); }
/* Collapsed panels show a narrow slice: aim each photo so the slice frames
   the project's built structures, not empty landscape (Ayala 2026-08-19).
   Percentages target the structures' horizontal position in each photo. */
.xpanels img[src*="predator"] { object-position: 30% 50%; }   /* resort buildings left of centre */
.xpanels img[src*="britannia"] { object-position: 32% 50%; }  /* pool + village left of centre */
.xpanels img[src*="bear-mountain"] { object-position: 66% 50%; } /* hotel right of centre */
.xpanels a:hover img { transform: scale(1.03); }
.xpanel__tag { position: absolute; left: 16px; bottom: 14px; background: rgba(28,31,26,0.55);
  padding: 7px 12px; max-width: calc(100% - 32px); }
.xpanel__tag b { display: block; font-size: 14px; font-weight: 800; color: rgba(242,237,230,0.95);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xpanel__tag span { font-size: 12px; font-weight: 300; letter-spacing: 0.08em;
  color: rgba(242,237,230,0.90); white-space: nowrap; }   /* 260924 (Ayala, A): 0.78 -> 0.90, worst spot over the photos 4.1 -> 5.0:1 */
@media (max-width: 860px) {
  .xpanels { flex-direction: column; height: auto; }
  .xpanels a { height: 200px; flex: none; }
  .xpanels a:hover { flex: none; }
}
@media (prefers-reduced-motion: reduce) {
  .xpanels a, .xpanels img { transition: none; }
  .xpanels a:hover img { transform: none; }
}

/* ---------- Partnership: clean bleed split on Mud (2026-08-17) ---------- */
/* Replaces the masked full-bleed background. Text left (heading stays on the
   page's left rail), photograph clean at full section height, bleeding off
   the right edge. Mud ground = parent palette, playbook-amendment list. */
/* Mud #E3DED8 → Moss #E0E3DD (260817 ground re-sequence, Ayala) */
.partner { background: #E0E3DD; min-height: 0; display: block;
  padding: var(--section-y) 40px; overflow: visible; }
.partner__grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 48px; align-items: stretch; }
.partner__content { position: static; max-width: none; padding: 0;
  display: flex; flex-direction: column; justify-content: center; }
.partner .eyebrow { color: var(--forest); }
.partner__h2 { color: var(--ink); }
.partner__body { color: rgba(28,31,26,0.74); }
.partner__emphasis { color: rgba(28,31,26,0.9); font-weight: 500; }
.partner .cert span { color: var(--ink); }
.partner__img { position: relative; overflow: hidden; margin: 0; }
.partner__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.partner__pill { position: absolute; left: 16px; bottom: 14px; background: rgba(28,31,26,0.55);
  color: rgba(242,237,230,0.92); font-size: 12px; font-weight: 400; letter-spacing: 0.06em;
  padding: 6px 11px; }
/* The factory-bay photo is a landscape instrument: side by side at 1024 the 1fr column
   cropped it to a near-portrait slot (Ayala 260921, tablet review). Below 1200 the section
   stacks, as Our Product and How We Deliver already do; the photo keeps the 2.4:1 band
   proportion Ayala approved at 768 (720 x 300). Below 900 the fixed 300px band remains. */
@media (max-width: 1200px) {
  .partner__grid { grid-template-columns: 1fr; gap: 32px; }
  .partner__img { position: relative; height: auto; aspect-ratio: 2.4 / 1; }
}
@media (max-width: 900px) {
  .partner { padding: var(--section-y) 24px; }
  .partner__img { height: 300px; aspect-ratio: auto; }
}

/* ---------- Partnership: hierarchy (2026-08-17, amended 2026-08-19) ----- */
/* 260817: certifications led by scale. 260819 (Ayala): they now use the
   icon-ledger grammar instead — weight comes from the icon marks, not from
   type scale. The partnered note stays at 18px/medium. */
.partner .partner__emphasis { display: inline-block; font-size: 18px;
  font-weight: 500; line-height: 1.6; color: var(--ink); }

/* ---------- Partnership: column aligned to the photo (2026-08-17) ------ */
/* Eyebrow sits above the grid; inside it, the heading's top edge and the
   button's bottom edge lock to the photo's edges (button pushed down with
   margin-top auto). Text rhythm normalized: 24px between text blocks. */
.partner__eyebrow { margin-bottom: 18px; }
.partner__content { justify-content: flex-start; }
.partner .partner__body { margin-bottom: 24px; }
.partner__certs { margin: 4px 0 36px; }
.partner .partner__cta { margin-top: auto; }
@media (max-width: 1200px) {
  .partner .partner__cta { margin-top: 8px; }   /* stacked: the button follows the certs, not the photo edge */
}

/* ---------- How We Deliver: column aligned to the photo (2026-08-17) --- */
/* Same treatment as Partnership: eyebrow above the grid so the heading's top
   edge meets the photo's top; the last triad line meets the photo's bottom
   (its trailing padding removed so the text baseline sits at the edge). */
.deliver__eyebrow { margin-bottom: 18px; }
.deliver-triad .icoitem:last-child { padding-bottom: 0; }

/* ---------- Shared statement style (2026-08-17) ------------------------ */
/* The Partnership note's treatment, promoted to a site-wide tier: 18px,
   medium, full ink. Used for the section-level statement lines. */
.statement { font-size: 18px; font-weight: 500; line-height: 1.6; color: var(--ink); }
/* Evergreen emphasis inside copy is reserved for Possibility of Place
   moments only (Ayala, 2026-08-19): the Why We Exist pull-quote and the
   Who We Are belief line. Do not use it for other emphasis. */
.statement em { font-style: normal; color: var(--forest); }
p.statement { margin-top: 24px; max-width: 820px; }
/* Why We Exist close joins the same tier; its Evergreen ending stays. */
.exist-pull { font-size: 18px; font-weight: 500; line-height: 1.6; color: var(--ink);
  margin-top: 24px; max-width: 820px; }

/* ---------- Catalogue names in the pull-line style (2026-08-17) -------- */
/* The former Why We Exist close treatment (ExtraBold, up to 25px), applied
   to the model names on the catalogue cards. */
.cat-card__name { font-family: 'Lexend Deca', sans-serif; font-size: clamp(17px, 1.7vw, 21px);
  font-weight: 800; line-height: 1.15; color: var(--ink); margin-bottom: 9px; }

/* statement tier on dark ground: fog instead of ink (Why It Works) */
.why .statement { color: var(--fog); }

/* ---------- Why It Works: into the light (Option B+, 2026-08-17) ------- */
/* Ink ground retired (the page's last heavy block). White illustrated
   columns with the marks enlarged, one content-width render between the
   columns and the estimator. Ground: paper → Moss (260817 am) → Warm White
   (260817 pm ground re-sequence, Ayala). */
.why { background: var(--fog); padding-bottom: var(--section-y); }
.why .eyebrow--light { color: var(--umber-text); } /* Warm White ground → Cedar */
.why__h2 { color: var(--ink); }
.why__body { color: rgba(28,31,26,0.72); }
.why .statement { color: var(--ink); }
.why__cases { padding-bottom: 0; }
.why .case-card { background: #fff; border: 1px solid rgba(28,31,26,0.12); }
.why .case-card h3 { color: var(--ink); }
.why .case-card p { color: rgba(28,31,26,0.72); }
.why .case-mark { color: var(--ink); width: 72px; height: 72px; margin-bottom: 20px; }

/* ---------- Why It Works: one-viewport restructure (260824, Ayala) ------ */
/* The three reasons become a ledger column on the LEFT (the What We Build
   benefits grammar: icon · H2 title · B3 body, hairline dividers, no boxes);
   the estimator rides the RIGHT with its result panel gone HORIZONTAL so the
   whole answer reads in one glance beside the sliders that drive it. The
   disclaimer + sanctioned Start a Project close the section full-width.
   All type on documented rungs — only air is tuned, incl. the short-laptop
   tier below. The boxed .case-card / .case-grid--3 / .tool__cta styles above
   are RETIRED from this section (CSS kept). */
.wiw-wrap { padding: 0 40px; }
.wiw-grid { display: grid; grid-template-columns: 1fr 1.15fr; gap: 56px; align-items: start; }
.wiw-intro .why__h2 { margin-bottom: 0; }
.wiw-intro .why__body { margin-top: 18px; }
.wiw-cases { margin-top: 30px; }
.wiw-case { display: flex; padding: 18px 0; } /* gap dropped 260825 — no mark to space from */
.wiw-case + .wiw-case { border-top: 1px solid rgba(28,31,26,0.12); }
/* RETIRED 260825: .wiw-case svg { width: 44px; height: 44px; flex: none; color: var(--ink); } */
.wiw-case h3 { font-family: 'Lexend Deca', sans-serif; font-size: 18px; font-weight: 700; color: var(--ink); margin: 0 0 6px; }   /* H4 ledger-title voice (18/700 unified, Ayala 260824; was H2 18/500) */
.wiw-case p { font-size: 15px; font-weight: 300; line-height: 1.65; color: rgba(28,31,26,0.72); margin: 0; } /* B3 rung */
.wiw-grid .tool { margin-top: 0; padding: 24px 28px 22px; }
.wiw-grid .tool__head { margin-bottom: 18px; }
.wiw-grid .tool__grid { display: block; }       /* controls stack above the result */
.wiw-grid .ctrl { margin-bottom: 14px; }
.wiw-selpair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.wiw-selpair .ctrl { margin-bottom: 14px; }
/* result panel horizontal: secondary stats ride BESIDE the revenue figure */
.wiw-grid .res { margin-top: 18px; padding: 20px 24px; display: grid;
  grid-template-columns: 1fr auto; column-gap: 32px;
  grid-template-areas: "label label" "big split" "range split" "note note"; }
.wiw-grid .res__label { grid-area: label; margin-bottom: 10px; }
.wiw-grid .res__big { grid-area: big; }
.wiw-grid .res__range { grid-area: range; margin-top: 6px; }
.wiw-grid .res__split { grid-area: split; margin: 0; padding: 0 0 0 28px; border-top: 0;
  border-left: 1px solid rgba(242,237,230,0.14); align-self: center; gap: 8px 24px; }
.wiw-grid .res__note { grid-area: note; margin-top: 12px; padding-top: 12px; }
/* Estimator-only layout (260909): one column, tool full width, controls beside result. */
.wiw-solo { max-width: 1120px; }
.wiw-solo .why__body { margin-top: 18px; max-width: 760px; }
.wiw-solo .why__body strong { font-weight: 500; color: var(--ink); }
.wiw-solo .tool { margin-top: 28px; padding: 28px 32px 26px; }
.wiw-solo .tool__grid { gap: 48px; }
.wiw-wrap .wiw-cta { max-width: 1120px; } /* same measure as .wiw-solo so the closing hairline aligns with the panel */
.wiw-cta { margin-top: 36px; padding-top: 24px; border-top: 1px solid rgba(28,31,26,0.14);
  display: flex; flex-wrap: wrap; align-items: center; gap: 18px; }
.wiw-cta p { font-size: 16px; font-weight: 300; line-height: 1.72; color: rgba(28,31,26,0.72); flex: 1 1 300px; margin: 0; } /* B2 rung */
.wiw-cta strong { font-weight: 500; color: var(--ink); }
@media (max-width: 980px) {
  .wiw-grid { grid-template-columns: 1fr; gap: 40px; }
}
@media (max-width: 900px) {
  .wiw-wrap { padding: 0 24px; }
}
@media (max-width: 760px) {
  /* narrow screens: the result re-stacks so the figure keeps its room */
  .wiw-grid .res { display: block; }
  .wiw-grid .res__split { border-left: 0; border-top: 1px solid rgba(242,237,230,0.14);
    padding: 14px 0 0; margin-top: 16px; }
}
/* SHORT-LAPTOP AIR TIER: on ~768px-tall screens the air tightens — paddings,
   row gaps, margins — and the type never moves. Frame (heading → result)
   measures ~658px at 1366×768. Same tier boundary as the sketch/track and
   comparison-plate compressions. */
@media (max-height: 800px) and (min-width: 761px) {
  .why { padding-top: var(--space-5); }
  .wiw-intro .why__body { margin-top: 12px; }
  .wiw-cases { margin-top: 14px; }
  .wiw-case { padding: 10px 0; }
  .wiw-grid .tool { padding: 18px 24px 16px; }
  .wiw-grid .tool__head { margin-bottom: 12px; }
  .wiw-grid .ctrl { margin-bottom: 9px; }
  .wiw-selpair .ctrl { margin-bottom: 9px; }
  .wiw-grid .ctrl__hint { margin-top: 3px; }
  .wiw-grid .ctrl__row { margin-bottom: 6px; }
  .wiw-grid .res { margin-top: 10px; padding: 13px 20px; }
  .wiw-grid .res__label { margin-bottom: 5px; }
  .wiw-grid .res__note { margin-top: 7px; padding-top: 7px; }
  .wiw-cta { margin-top: 22px; padding-top: 14px; }
}

.why-figure { margin: 44px 0 0; position: relative; }
.why-figure img { width: 100%; aspect-ratio: 21/9; object-fit: cover; }
.why-figure__pill { position: absolute; left: 16px; bottom: 14px; background: rgba(28,31,26,0.55);
  color: rgba(242,237,230,0.92); font-size: 12px; font-weight: 400; letter-spacing: 0.06em;
  padding: 6px 11px; }

/* ---------- Hero framing on phones and tablets (260921, Ayala) ---------------
   The static hero (hero-cabin-2, 16:9) is cropped by height on a portrait screen and
   'center' kept the sunset and lost the cabin, which sits in the right 49-93% of the
   frame. Anchored at 88% the window shows the cabin's facade and deck on a 390 phone
   (image 65-89%) and the whole cabin on a 768 tablet (51-93%). `.hero #heroBg` outranks
   the generated `.hero__img` rule in the intro tail, so a re-port cannot undo it. */
/* phones, small tablets, and ANY portrait touch screen (an iPad Pro at 1024 wide is still
   cropped by height and lost half the cabin when centred) */
@media (max-width: 900px), ((hover: none) and (pointer: coarse) and (orientation: portrait)) {
  .hero #heroBg { background-position: 88% 50%; }
}

/* ---------- Stacked hero on phones (260921, Ayala: option C) ----------------------
   On a phone the desktop panel (Ink 55% + blur, sized by its content) became a slab over
   the lower 45% of the screen and the cabin behind it. Under 600px the hero is two
   surfaces in sequence: the photo in a 54vh box at the top (cabin anchored at 88%), then
   the copy on solid Ink beneath, no box, no blur; the photo fades into the Ink at the
   seam. Same copy and type sizes. Tablets (768+) keep the desktop panel. The id
   selectors outrank the generated hero rules in the intro tail, so a re-port keeps this.
   The first button is filled Warm White (primary), the second outlined (secondary). */
@media (max-width: 600px) {
  #home.hero { height: auto; min-height: 0; display: block; padding: 0; background: var(--ink); }
  #home #heroBg { position: relative; inset: auto; height: 54vh; height: 54dvh; min-height: 300px; transform: none !important; }
  #home .hero__overlay { top: 0; bottom: auto; height: 54vh; height: 54dvh; min-height: 300px;
    background: linear-gradient(to bottom, rgba(28,31,26,0.5) 0, rgba(28,31,26,0) 22%, rgba(28,31,26,0) 78%, var(--ink) 100%); }
  #home .hero__content { position: relative; width: auto; max-width: none; background: none;
    -webkit-backdrop-filter: none; backdrop-filter: none; padding: 20px 24px 40px; margin: 0; }
  #home .hero__ctas .btn-light { background: var(--fog); color: var(--ink); border-color: var(--fog); }
}

/* ---------- Phases as a swipe-through strip on PHONES (260921, Ayala) -----------------
   On a phone the vertical list put phases 4-5 two screens below the sketch, so the "place
   taking shape" feedback was off-screen when tapped. Under 600px the five phases become a
   native scroll-snap strip: one card in view with a 24px peek of the next, the sketch pinned
   above it (its stage = the visible card), five progress dots (passed = Cedar, current =
   Celebration) between the site's arrow pair. Works without JS (the script only syncs the
   sketch, dots and arrows). Tablets and desktop keep the list/row. Landscape phones fall in
   the tablet tier for now (go-live checklist). Selectors carry .phase-plate so they outrank
   the <=1200px vertical-list rules that come later in the file. */
.hint-swipe { display: none; }
.phase-swipe-nav { display: none; }   /* built by JS; shown only by the phone rule below */
@media (max-width: 600px) {
  .process__hint .hint-hover, .process__hint .hint-tap { display: none; }
  .process__hint .hint-swipe { display: inline; }
  .phase-plate .process__phases { display: flex; grid-template-columns: none; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory;
    margin: 0 -24px; padding: 4px 48px 6px 24px; scroll-padding-left: 24px; scrollbar-width: none;   /* right padding = inset + peek so the LAST card can align to the inset too */ -webkit-overflow-scrolling: touch; touch-action: pan-x pan-y; }
  .phase-plate .process__phases::-webkit-scrollbar { display: none; }
  .phase-plate .process__phases .phase { flex: 0 0 calc(100vw - 60px); scroll-snap-align: start;   /* viewport-based: 24 inset + card + 24 peek + 12 gap; with the 48px right padding the last card aligns to the inset too */ display: block; padding: 18px 18px 20px;
    border: 1px solid rgba(242,237,230,0.14); border-radius: 2px; opacity: 1 !important; transform: none !important; transition: border-color 0.3s; }
  .phase-plate .process__phases .phase.is-active { border-color: rgba(200,153,104,0.55); }
  .phase-plate .process__phases .phase::before, .phase-plate .process__phases .phase__dot { display: none; }
  .phase-plate .process__phases .phase__label { margin-bottom: 8px; }
  .phase-plate .process__phases .phase__more { display: none; }   /* the reveal text has no hover on a phone; the card carries the essentials */
  .phase-swipe-nav { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 0; }
  .process .phase-plate .process__cta { margin-top: 32px; }
}
.phase-swipe-dots { display: flex; gap: 6px; }
.phase-swipe-dot { width: 24px; height: 24px; padding: 0; border: 0; background: transparent; position: relative; cursor: pointer; }
.phase-swipe-dot::before { content: ''; position: absolute; left: 7px; top: 7px; width: 10px; height: 10px; border-radius: 50%; border: 2px solid rgba(242,237,230,0.5); transition: all 0.25s; }
.phase-swipe-dot.is-past::before { background: var(--umber-bright); border-color: var(--umber-bright); }
.phase-swipe-dot[aria-current="true"]::before { background: var(--sunburst); border-color: var(--sunburst); box-shadow: 0 0 0 4px rgba(208,76,39,0.22); transform: scale(1.15); }
.phase-swipe-nav .cat-nav__btn { color: var(--fog); border-color: rgba(242,237,230,0.55); width: 40px; height: 40px; }
.phase-swipe-nav .cat-nav__btn:disabled { opacity: 0.3; background: transparent; color: var(--fog); }
.phase-swipe-dot:focus-visible, .phase-swipe-nav .cat-nav__btn:focus-visible { outline: 2px solid var(--fog); outline-offset: 2px; }

/* ---------- Gallery: drifting render rows (2026-08-17) ----------------- */
/* Two marquee rows at uneven heights, opposite directions; hover pauses;
   click opens the shared lightbox. The track holds two copies of its set
   (margins, not gap, so the -50% loop is seamless). Reduced motion: rows
   stand still and scroll natively. */
.rgallery { background: #E0E3DD; padding: var(--section-y) 0; } /* Moss — distinct from Why It Works (Warm White) */
.rgallery__head { padding: 0 40px; margin-bottom: 36px; }
.rg-row { overflow: hidden; }
.rg-row + .rg-row { margin-top: 10px; }
.rg-track { display: flex; width: max-content; animation: rgScroll 130s linear infinite; }   /* 260921: row 1 grew 6 -> 10 images (hero set added); 80 s * 10/6 keeps the same drift speed */
.rg-row--rev .rg-track { animation-duration: 95s; }   /* 260921 r3: same direction as row 1 (opposite drift beside a paused row read as restless) */
.rg-row:hover .rg-track { animation-play-state: paused; }
.rg-track img { height: 420px; width: auto; display: block; margin-right: 12px; cursor: zoom-in;
  transition: transform 0.3s var(--ease); }
.rg-track img:hover { transform: scale(1.02); }
/* Side arrows (260921, Ayala; placemark.ca pattern, r3): the two rows are one object —
   .rg-rows wraps both, one arrow pair sits at the block's mid-height, hovering anywhere
   pauses both rows, and both drift the same way at one speed. The button is the site's one
   arrow, recoloured for a photo surface: Warm White chevron on a soft Ink chip. Quiet until
   the block is hovered, then full; Sunburst on hover like every other arrow. */
.rg-rows { position: relative; }
.rg-row__btn { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  color: var(--fog); background: rgba(28,31,26,0.42); border-color: rgba(242,237,230,0.55);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0.72; transition: opacity 0.2s, background 0.2s, border-color 0.2s; cursor: pointer; }
.rg-row__btn--prev { left: 20px; }
.rg-row__btn--next { right: 20px; }
.rg-rows:hover .rg-row__btn, .rg-row__btn:focus-visible { opacity: 1; }
.rg-row__btn:hover { background: var(--sunburst); border-color: var(--sunburst); }
.rg-row__btn:focus-visible { outline: 2px solid var(--fog); outline-offset: 2px; }
@media (max-width: 900px) { .rg-row__btn { opacity: 1; } .rg-row__btn--prev { left: 12px; } .rg-row__btn--next { right: 12px; } }
.rg-row--rev .rg-track img { height: 330px; }
@keyframes rgScroll { to { transform: translateX(-50%); } }
/* the hint shows only where it informs (Ayala 2026-08-19): hover-capable
   devices get the zoom-in cursor as the affordance; touch devices, which
   have no hover cue, keep the written invitation */
.rgallery__hint { text-align: center; font-size: 11px; font-weight: 500; letter-spacing: 0.16em;
  text-transform: uppercase; color: rgba(28,31,26,0.55); margin-top: 30px; }
@media (hover: hover) and (pointer: fine) {
  .rgallery__hint { display: none; }
}
@media (max-width: 900px) {
  .rgallery__head { padding: 0 24px; }
  .rg-track img { height: 240px; }
  .rg-row--rev .rg-track img { height: 190px; }
}
@media (prefers-reduced-motion: reduce) {
  .rg-track { animation: none; }
  .rg-row { overflow-x: auto; }
  .rg-track img:hover { transform: none; }
}

/* lightbox caption: bottom-left footnote pill (2026-08-17) */
.lightbox__cap { position: absolute; left: 24px; bottom: 22px; background: rgba(28,31,26,0.6);
  color: rgba(242,237,230,0.92); font-size: 12px; font-weight: 400; letter-spacing: 0.06em;
  padding: 7px 12px; max-width: 70vw; }


/* ====================================================================
   YOUR INVESTMENT — banner layout (Option 7, ported 260909)
   Appended after every .why rule so .invest padding wins on equal
   specificity. Source of truth for the decision trail:
   1 Website Prototype/260909/260909 - Your Investment Option 7 (banner).html
   ==================================================================== */
/* Option 7 — banner (Ayala 260909). The render was extended to 3:1 by
   outpainting (forest only, right side) so the whole image runs edge to edge
   at its native proportion, no crop, no scrim. The full estimator card floats
   on the forest third at the right, inside the site's 40px margin. */
.invest { background: var(--fog); padding: var(--space-7) 0 56px; }
.invest__intro { padding: 0 40px; }
.invest__intro .why__body { margin-top: 18px; max-width: 800px; }
.invest__intro .why__body strong { font-weight: 500; color: var(--ink); }

.invest__stage { position: relative; margin-top: 36px; }
/* Equal insets (Ayala 260909): the band is at least the card's height + 80px,
   so the card sits 40px from the picture's top, bottom and right edges. When
   that makes the band taller than 3:1 the image crops from the LEFT (object-
   position 80%), so on laptops the hot-tub cabin at the far left takes the cut
   while the firepit, lawn and the completed cabin stay clear of the card. */
.invest__band { position: relative; margin: 0; width: 100%; aspect-ratio: 3 / 1; min-height: var(--invest-band-min, 0px); overflow: hidden; background: var(--charcoal); }
.invest__band > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 80% 50%; display: block; }
.invest__hint { position: absolute; left: 40px; top: 20px; background: rgba(242,237,230,0.92); color: rgba(28,31,26,0.72); font-size: 11px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; padding: 6px 10px; border-radius: 2px; }
.invest__pill { position: absolute; left: 40px; bottom: 20px; background: rgba(28,31,26,0.66); color: var(--fog); font-size: 12px; font-weight: 500; letter-spacing: 0.06em; padding: 7px 12px; border-radius: 2px; }
.invest__pill b { font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; margin-right: 6px; color: var(--umber-bright); }

/* The card: floats on the right third, vertically centred on the band; it may
   stand a few px proud of the band's top and bottom edges, which reads as a
   card placed on the picture rather than fitted into it. */
.invest__card { position: absolute; right: 40px; top: 50%; transform: translateY(-50%); z-index: 2; width: min(46%, 700px); background: #fff; padding: 30px 34px 28px; border: 1px solid rgba(28,31,26,0.07); border-radius: 2px; box-shadow: 0 24px 48px -20px rgba(28,31,26,0.5), 0 2px 6px rgba(28,31,26,0.12); }
.invest__card .tool__head { margin-bottom: 18px; }
.invest__card .ctrl { margin-bottom: 14px; }
.invest__card .wiw-selpair .ctrl { margin-bottom: 14px; }
.invest__card .ctrl__hint { margin-top: 7px; }
.invest__card .res { margin-top: 18px; padding: 22px 26px; display: grid; grid-template-columns: 1fr auto; grid-template-areas: "label label" "big split" "range split"; column-gap: 22px; align-items: center; }
.invest__card .res__label { grid-area: label; margin-bottom: 10px; }
.invest__card .res__big { grid-area: big; }
.invest__card .res__range { grid-area: range; margin-top: 6px; }
.invest__card .res__split { grid-area: split; margin: 0; padding: 0 0 0 28px; border-top: 0; border-left: 1px solid rgba(242,237,230,0.14); }

/* Closing row: disclaimer + CTA, full width on Warm White (live grammar). */
.invest__cta { margin: 96px 40px 0; padding-top: 24px; border-top: 1px solid rgba(28,31,26,0.14); display: flex; flex-wrap: wrap; align-items: center; gap: 18px 40px; }
.invest__cta p { flex: 1 1 420px; font-size: 16px; font-weight: 300; line-height: 1.72; color: rgba(28,31,26,0.72); margin: 0; }
.invest__cta strong { font-weight: 500; color: var(--ink); }

@media (min-width: 1101px) and (max-width: 1500px) {
  /* laptops only: keep the lede clear of the card's column */
  .invest__intro .why__body { max-width: min(800px, 48%); }
  .invest__stage { margin-top: 48px; }
}
@media (max-width: 1100px) {
  .invest__band { aspect-ratio: 16 / 10; }
  .invest__band > img { object-position: 30% 60%; }   /* the original scene is the left ~60% of the 3:1 image */
  .invest__card { position: static; transform: none; width: auto; margin: 24px 40px 0; box-shadow: 0 22px 44px -34px rgba(28,31,26,0.35); }
  .invest__cta { margin-top: 48px; }
}
@media (max-width: 900px) {
  .invest { padding: 48px 0 40px; }
  .invest__intro { padding-left: 24px; padding-right: 24px; }
  .invest__cta { margin-left: 24px; margin-right: 24px; }
  .invest__stage { margin-top: 24px; }
  .invest__hint { left: 14px; top: 12px; }
  .invest__pill { left: 14px; bottom: 12px; }
  .invest__card { margin: 24px 24px 0; }
  .invest__card .wiw-selpair { grid-template-columns: 1fr; gap: 0; }
  .invest__card .res { display: block; }
  .invest__card .res__split { border-left: 0; border-top: 1px solid rgba(242,237,230,0.14); padding: 16px 0 0; margin-top: 16px; }
}

/* Image guard (Ayala 260909): no drag-to-desktop; the context menu is blocked
   in script.js (setupImageGuard). Screenshots and devtools are not, and
   cannot be, prevented. Selection stays enabled everywhere else. */
img { -webkit-user-drag: none; user-drag: none; }

/* ---------- S3b: Our Craft (new 260909; layout Option 7 ported 260910) ----------
   Warm White ground between Our Product (Moss) and Our Service (Moss) — the
   page alternates strictly (see SURFACE FLIP near .gap--exist). One-frame
   header on the left (eyebrow · D2 heading · B1 lede · the catalogue's arrow
   pair); on the right one fixed-height row of tiles that scrolls sideways:
   photographs (no caption pills — Ayala 260910), and Moss text tiles (H4 title · B3-ish
   body) carrying the three themes. Vertically the section fits a laptop frame
   (short-laptop air tier below); horizontally the cut-off tile at the right
   edge is the affordance, the arrows repeat it for mouse users. Text as
   tiles, not as the bolded ledger, so the section reads differently from
   Our Product / Our Service. Cedar (--umber-text) on the eyebrow as in Our
   Product. */
.craft { background: var(--fog); padding: var(--section-y) 40px; }
.craft .eyebrow { color: var(--umber-text); }
.craft__row { display: grid; grid-template-columns: minmax(340px, 0.9fr) 1.1fr; gap: 40px; align-items: stretch; } /* 0.8/1.2 → 0.9/1.1 (260910): room for the two-line heading at laptop widths */
.craft__head { display: flex; flex-direction: column; justify-content: center; }
.craft__h2 { font-size: clamp(28px, 3vw, 44px); font-weight: 900; letter-spacing: 0.04em; line-height: 1.12; color: var(--ink); margin-bottom: 18px; } /* line-height 1.12 = the sitewide D2 fix of 2026-08-17 (was 1.04 here by mistake; corrected 260910) */ /* 3.4vw → 3.1vw (260910): keeps the two-line heading on two lines in the ~500px column at 1366 */
.craft__lede { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72); }
.craft__nav { justify-content: flex-start; margin: 28px 0 0; }
.craft__strip { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory; margin-right: -40px; padding-right: 40px; scrollbar-width: none; }
.craft__strip::-webkit-scrollbar { display: none; }
.craft-tile { position: relative; flex: 0 0 auto; height: 460px; margin: 0; overflow: hidden; scroll-snap-align: start; background: rgba(28,31,26,0.05); }
.craft-tile--port { width: 330px; }
.craft-tile--land { width: 520px; }
.craft-tile img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 0.55s var(--ease); }
.craft-tile img[src*="team-drawings"] { object-position: 50% 18%; }   /* 260921 r4 (Ayala): frame from near the top so her eyes stay in, most of the plan still shows */
/* Photos open the shared lightbox (Ayala 260910): same affordance as the Our
   Product renders — zoom-in cursor, Evergreen tint, gentle scale — applied
   only once JS has wired the click (setupCraftStrip). */
.js .craft-tile.is-expandable { cursor: zoom-in; }
.js .craft-tile.is-expandable::after { content: ''; position: absolute; inset: 0; background: rgba(34,89,45,0); transition: background 0.3s var(--ease); pointer-events: none; }
.js .craft-tile.is-expandable:hover::after, .js .craft-tile.is-expandable:focus-visible::after { background: rgba(34,89,45,0.28); }
.js .craft-tile.is-expandable:hover img { transform: scale(1.04); }
.js .craft-tile.is-expandable:focus-visible { outline: 2px solid var(--forest); outline-offset: 2px; }
.craft-tile--txt { width: 300px; background: #E0E3DD; padding: 22px 22px 20px; display: flex; flex-direction: column; justify-content: flex-end; }
.craft-tile--txt h3 { font-family: 'Lexend Deca', sans-serif; font-size: 17px; font-weight: 700; color: var(--ink); margin: 0 0 6px; }
.craft-tile--txt p { font-size: 14px; font-weight: 300; line-height: 1.55; color: rgba(28,31,26,0.72); margin: 0; }
/* Short-laptop air tier (site pattern): ~768px-tall screens tighten padding and tile height; type stays. */
@media (max-height: 800px) and (min-width: 1101px) {
  .craft { padding-top: var(--space-5); padding-bottom: var(--space-5); }
  .craft-tile { height: 420px; }
}
@media (max-width: 1100px) {
  .craft__row { grid-template-columns: 1fr; gap: 32px; }
  .craft__head { display: block; }
  .craft__strip { margin-left: -40px; padding-left: 40px; scroll-padding-left: 40px; }   /* 260921 r3: snap to the inset, not the screen edge */
}
@media (max-width: 900px) {
  .craft { padding-left: 24px; padding-right: 24px; }
  .craft__strip { margin-left: -24px; padding-left: 24px; margin-right: -24px; padding-right: 24px; scroll-padding-left: 24px; }
  .craft-tile { height: 340px; }
  .craft-tile--port { width: 250px; }
  .craft-tile--land { width: 400px; }
  .craft-tile--txt { width: 260px; }
}
@media (max-width: 600px) {
  /* 260921 r3 (Ayala): one whole tile per view; the arrows then always land on a complete
     photo or text card. Tile width = the strip's visible width between its 24px insets. */
  .craft-tile--port, .craft-tile--land, .craft-tile--txt { width: calc(100vw - 48px); }
}

/* ---------- Our Service: "arrives complete" callouts on the crane photo (260910) ----------
   Two grouped cards (factory list from the module's roof, site list from the foundation
   frame). Frosted: translucent warm near-white (#FBFAF8 family) + backdrop blur, hairline
   light edge, no shadow, no row dividers — the photo reads through. Marker vocabulary =
   the comparison's: outlined Evergreen check-gate for factory items, Cedar dot for site
   items. Leaders: fog line over a soft ink underlay so they hold on any part of the photo. */
.deliver-img { position: relative; }
.deliver-callouts { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.deliver-lead { fill: none; stroke: rgba(242,237,230,0.95); stroke-width: 1.5; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.deliver-lead--shadow { stroke: rgba(28,31,26,0.45); stroke-width: 3.5; }
.deliver-anchor { position: absolute; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 50%; background: var(--fog); box-shadow: 0 0 0 1.5px rgba(28,31,26,0.55), 0 0 0 3px rgba(242,237,230,0.6); pointer-events: none; } /* ~30% smaller (Ayala 260910) */
.deliver-card { position: absolute; width: 36%; box-sizing: border-box; /* % so the leader ends (40% / 60%) always meet the card edge */ background: rgba(251,250,248,0.58);
  -webkit-backdrop-filter: blur(14px) saturate(1.1); backdrop-filter: blur(14px) saturate(1.1);
  border: 1px solid rgba(251,250,248,0.55); border-radius: 2px; padding: 8px 10px 6px; }
@supports not (backdrop-filter: blur(1px)) { .deliver-card { background: rgba(251,250,248,0.82); } }
.deliver-card--factory { left: 4%; }
.deliver-card--site { right: 4%; }
.deliver-card__h { font-size: 12.5px;   /* 11.5 -> 12.5 (260925 size floor) */ font-weight: 600; letter-spacing: 0.04em; color: var(--ink); margin: 0 0 4px; padding-bottom: 4px; border-bottom: 1.5px solid rgba(34,89,45,0.7); }
.deliver-card--site .deliver-card__h { border-color: rgba(159,120,77,0.75); }   /* 260922 (Ayala, on the iPhone): heading colour matched to the factory card (full Ink); only the rule colour differs now */
.deliver-card ul { list-style: none; margin: 0; padding: 0; }
.deliver-card li { display: flex; align-items: center; gap: 7px; font-size: 12px;   /* 11.5 -> 12 (260925); 12.5 wrapped "Electrical + plumbing, tested" at 1366 */ font-weight: 400; line-height: 1.25; color: rgba(28,31,26,0.86); padding: 3px 0; }
.deliver-card__gate { position: relative; flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--forest); }
/* check drawn as an SVG path centred in the ring's 10px interior (a rotated CSS "L" has an
   off-centre visual mass — Ayala 260910) */
.deliver-card__gate::after { content: ''; position: absolute; inset: 0;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><path d='M2.4 5.3 L4.3 7.1 L7.8 3.2' fill='none' stroke='%2322592D' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 100% 100% no-repeat; }
.deliver-card__dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--umber); margin: 0 3.5px; } /* 9 → 7px (~25% smaller, Ayala 260910); margin keeps the text column aligned with the gates above */
/* Callouts stay on the photo down to 600px (was 900: a generic mobile cutoff that was never
   measured). At 768 the photo is 720px wide, wider than on a 1366 laptop (582px), so the cards
   (36% = 259px) read better there than on desktop. Below 600px the photo is under 550px, the
   cards would drop under 200px, and the lists move beneath the photo (Ayala 260918). */
@media (max-width: 600px) {
  .deliver-callouts, .deliver-anchor { display: none; }
  .deliver-card { position: static; width: auto; margin: 12px 0 0; }
}

/* ---------- Your project, phase by phase: Ink plate (260911) ----------
   Boxed like .cmp__plate, on Ink (var(--ink)) with Warm White lines and type —
   the page's one deliberate dark break (Ayala: parked 260909, approved 260911).
   Type tints follow the dark-surface scale (body 0.72, captions 0.62); Cedar
   becomes --umber-bright; Sunburst stays for the active phase and the CTA. The
   sketch (inline SVG, unchanged) is inverted by attribute selectors: Ink strokes
   → Warm White, Warm White fills → Ink, Cedar → umber-bright, Evergreen lifted.
   The sketch is ~25% smaller per laptop tier and the air is scaled with it so
   the whole plate frames in one screen (874 @1080-tall, 784 @900, 694 @768).
   Gap to the comparison plate halved: .cmp margin-bottom 96 → 48. */
.cmp { margin-bottom: var(--space-5); }
.phase-plate { background: var(--ink); border-radius: 2px; padding: 46px 50px 44px; box-shadow: 0 22px 44px -34px rgba(28,31,26,0.45); }
.phase-plate .process__header { margin-bottom: 16px; }
.phase-plate .sketch-stage svg { width: min(648px, 84%); }   /* +20% (Ayala 260915) */
.phase-plate .sketch-stage { margin-bottom: 28px; }
.phase-plate .process__lede { margin-bottom: 20px; color: rgba(242,237,230,0.72); }
.phase-plate .process__hint { margin-bottom: 22px; color: rgba(242,237,230,0.62); }
.phase-plate .process__hint svg { stroke: var(--umber-bright); }
.phase-plate .process__cta { margin-top: 24px; }
.phase-plate .process__title { color: var(--fog); }
.phase-plate .process__line { background: rgba(242,237,230,0.22); }
.phase-plate .phase__label { color: rgba(242,237,230,0.62); }
.phase-plate .phase__label b { color: rgba(242,237,230,0.82); }
.phase-plate .phase__title { color: var(--fog); }
.phase-plate .phase__time { color: var(--umber-bright); }
.phase-plate .phase__desc { color: rgba(242,237,230,0.72); }
.phase-plate .phase__more { border-top-color: rgba(242,237,230,0.14); }
.phase-plate .phase__more-k { color: var(--umber-bright); }
.phase-plate .phase__more p { color: rgba(242,237,230,0.74); }
.phase-plate .phase.is-dim .phase__dot { background: var(--ink); border-color: rgba(242,237,230,0.35); }
.phase-plate .sketch [stroke="#1C1F1A"] { stroke: var(--fog); }
.phase-plate .sketch [fill="#F2EDE6"] { fill: var(--ink); }
.phase-plate .sketch [stroke="#7A5A38"] { stroke: var(--umber-bright); }
.phase-plate .sketch [fill="#7A5A38"] { fill: var(--umber-bright); }
.phase-plate .sketch [stroke="#22592D"] { stroke: #6FA97B; }
.phase-plate .sketch [fill="#22592D"] { fill: #6FA97B; }
@media (max-width: 900px) { .phase-plate { padding: 28px 24px 30px; margin: 0 -24px; border-radius: 0; } }
/* ---------- Phases as a VERTICAL timeline below 1200px (260918, Ayala) -----
   The five-column row needs ~1100px to hold five descriptions side by side;
   between 901 and 1200 it fell into a 3 + 2 grid that reads as neither a
   timeline (the line of time breaks) nor a list (the second row looks like
   leftovers, with the CTA under the orphan). Below 1200px the phases run as one
   vertical sequence: a 2px line down the left, the phase dot on it, label /
   title / description to the right, the same grammar as the comparison plate
   above it. The sketch, the hover/tap lighting and the reveal text are
   unchanged. Later in the file than the 900px rules on purpose. */
@media (max-width: 1200px) {
  .process__phases { grid-template-columns: 1fr; gap: 0; position: relative; }
  .process__line { display: none; }
  /* 260922 (found on the tablet capture): the active card's scale(1.06) is a row-layout effect; on a full-width
     list item it pushed the card 21px past the plate edge at 768 and clipped the description. No scale here. */
  .phase.is-active { transform: none; }
  /* the line is drawn per phase, from its dot down to the next dot, so it closes
     on the last circle instead of running past it (Ayala 260918) */
  .phase::before { content: ''; position: absolute; left: 7px; top: 8px; bottom: 0; width: 2px; background: rgba(28,31,26,0.2); }
  .phase:last-child::before { display: none; }
  .phase-plate .phase::before { background: rgba(242,237,230,0.22); }
  .phase:last-child .phase__dot { box-shadow: 0 0 0 5px rgba(159,120,77,0.22); }   /* destination halo, as on the comparison timeline */
  .phase-plate .phase:last-child .phase__dot { box-shadow: 0 0 0 5px rgba(200,153,104,0.22); }
  .phase { display: grid; grid-template-columns: 16px 1fr; column-gap: 22px; padding: 0 0 30px; opacity: 1 !important; transform-origin: 8px 8px; }
  .phase:last-child { padding-bottom: 0; }
  .phase > * { grid-column: 2; }
  .phase__dot { grid-column: 1; grid-row: 1 / span 6; margin: 1px 0 0; }
  .phase__label { margin-bottom: 8px; }
  .process .phase-plate .process__cta { margin-top: 44px; }   /* the CTA clears the last description by more than the 30px phase rhythm (Ayala 260918: read as tight at 18-24px); extra specificity so the laptop-height rule (max-height 800px: 18px) cannot undercut it on 1024x768 tablets */
}

/* ---------- Tablet + phone footer and section rhythm (260918, Ayala) --------
   Footer: stacked under 900px, the nav grid sat at the start of a column flex
   container and shrank to its content (two 145px columns, empty right half).
   It now fills the width: three columns to 601px, two below. The copyright row
   stays on one line down to 601px. Sections: every section below 900px runs
   84px / 84px; Your Investment was the one outlier at 48 / 40. */
@media (max-width: 900px) {
  .footer__top { align-items: stretch; }
  .footer__nav { width: 100%; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; grid-auto-flow: row; column-gap: 24px; }
  .footer__bottom { flex-direction: row; align-items: center; gap: 16px; }
  .invest { padding: 84px 0 84px; }
}
@media (max-width: 600px) {
  .footer__nav { grid-template-columns: repeat(2, 1fr); }
  .footer__nav a { font-size: 11px; letter-spacing: 0.08em; }   /* "Map Your Project" wrapped in a 155px column at 12px/0.12em; no nowrap: at 320px it must be allowed to wrap rather than overflow */
  .footer__bottom { flex-direction: column; align-items: flex-start; gap: 12px; }
}

@media (max-height: 900px) and (min-width: 761px) {
  .phase-plate { padding-top: 30px; padding-bottom: 30px; }
  .phase-plate .sketch-stage svg { width: min(420px, 56%); }   /* +20% (Ayala 260915) */
  .phase-plate .sketch-stage { margin-bottom: 16px; }
  .phase-plate .process__hint { margin: -8px 0 14px; }
  .phase-plate .process__cta { margin-top: 18px; }
}
@media (max-height: 800px) and (min-width: 761px) {
  .phase-plate { padding-top: 22px; padding-bottom: 22px; }
  .phase-plate .sketch-stage svg { width: min(294px, 40%); }   /* +20% (Ayala 260915) */
  .phase-plate .sketch-stage { margin-bottom: 10px; }
  .phase-plate .process__hint { margin: -6px 0 12px; }
  .phase-plate .process__cta { margin-top: 14px; }
}

/* ---------- Measure system (260918, Ayala) ------------------------------
   One rule for text-block width, so paragraphs within a section share an
   edge and ledes across sections match. --measure (860px, ~105 characters
   at 16px Light, the width Our Purpose and Our Service already used) is the
   standalone single-column measure; every full-width text block takes it.
   Blocks that sit inside a grid column take the column instead (Our Craft
   lede, Partner body). Before this block: 860 / 820 / 800 / 740 / 980 /
   uncapped, section by section. Sits late in the file on purpose: it must
   follow the older per-section widths it replaces. */
:root { --measure: 860px; }
.gap__body, .cred__body, .why__body, .invest__intro .why__body, .exist-pull, p.statement,
.process__lede, .process__sub, .cmp__lede, .partner__body, .craft__lede { max-width: var(--measure); }
/* Our Product: the lede heads a 1fr / 1.9fr grid (gap 44px). Its right edge
   is the render pane's LEFT edge (column 1 + the gap), the line Ayala drew:
   at 1920 that is 658px, two full lines; column 1 alone (614px) left the
   word "four-bedrooms." orphaned on a third line. The six features below end
   at the column edge, 44px inside that. Stacked (<= 900px): full width. */
#what-we-build .gap__body { max-width: calc((100% - 44px) / 2.9 + 44px); }
@media (max-width: 1200px) { #what-we-build .gap__body { max-width: var(--measure); } }   /* stacked below 1200px: the lede takes the standard measure like every other section */

/* ---------- Body emphasis system (260918, Ayala) ------------------------
   Skimmers should catch the key messages from the emphasised fragments
   alone, so emphasis has to mean one thing everywhere:
   B1  section body ....... 16px / Light 300 / Ink 72% (one size sitewide)
   E1  body emphasis ...... same size, Medium 500, full Ink (.hi, and any
                            strong inside a body paragraph). Never a size change.
   E2  tagline closer ..... the ONE exception: a closing paragraph that is a
                            single sentence carrying "the Possibility of Place"
                            may sit at 18px Medium with the tagline in Evergreen
                            (.closer). Nothing else takes 18px. (Closers went Cedar 260925.)
   Normalised here: the 18px Our Purpose pull, the inline 18px .statement in
   How We Deliver and About, and the 74% Ink on About / Partner bodies.
   Late in the file on purpose: overrides the older per-block rules. */
.gap__body, .cred__body, .why__body, .partner__body, .craft__lede, .cmp__lede, .process__lede, .contact__sub { font-size: 16px; font-weight: 300; }
.cred__body, .partner__body { color: rgba(28,31,26,0.72); }
.hi, .gap__body strong, .cred__body strong, .why__body strong, .partner__body strong, .craft__lede strong, .cmp__lede strong,
.gap__body .statement, .cred__body .statement { font-size: inherit; line-height: inherit; font-weight: 500; font-style: normal; color: var(--ink); }
.process__lede strong, .process__lede .hi, .contact__sub strong, .contact__sub .hi { color: var(--fog); }   /* E1 on the dark plates */
.closer { font-size: 18px; font-weight: 500; line-height: 1.6; color: var(--ink); margin-top: 26px; max-width: var(--measure); }
.closer em { font-style: normal; color: var(--umber-text); }   /* 260925 (Ayala): the two tagline closers go Cedar (light-ground Cedar #7A5A38, raw Cedar fails AA at 18px/500); Evergreen leaves in-copy emphasis */
.cred__body--belief, .cred__body + .cred__body--belief { margin-top: 26px; }   /* closing single-sentence emphasis gets the same lift as .closer */

/* ---------- Phone refinements (260918, Ayala's tablet + mobile review) ----
   1. Buttons never wrap on phones: one rule for every .btn-* so they stay
      consistent. Under 400px the side padding drops 26 -> 20px and tracking
      0.16 -> 0.14em ("Explore How We Deliver" needed 267px in a 264px panel
      at 360); under 340px the label steps down to 11px.
   2. Hero pillars stack as a list with the site's 4px bullet (the .promise__dot
      vocabulary, Cedar-bright on the dark panel) instead of the inline "·"
      separators, which landed at the start of wrapped lines.
   3. Our Product -> catalogue gap cut by a third on phones (168 -> ~112px). */
@media (max-width: 400px) {
  .btn-primary, .btn-secondary, .btn-light, .btn-secondary--light, .btn-submit { padding-left: 20px; padding-right: 20px; letter-spacing: 0.14em; }
  /* no white-space: nowrap here: "Explore our Manufacturing Process" (33 characters) cannot fit a
     312px column and a nowrap button widened the layout viewport to 381px at 360 */
}
@media (max-width: 340px) {
  .btn-primary, .btn-secondary, .btn-light, .btn-secondary--light, .btn-submit { font-size: 11px; }
}
@media (max-width: 900px) {
  .hero__pillars { flex-direction: column; gap: 10px; }
  .hero__pillars span { display: flex; align-items: center; }
  .hero__pillars span::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: var(--umber-bright); margin: 0 12px 0 0; flex-shrink: 0; }
  .hero__pillars span + span::before { content: ''; margin-right: 12px; }
}
/* 260918: the tighter features -> catalogue gap (168 -> 112px) applies wherever Our Product is stacked, i.e. up to 1200px (Ayala: tablet 1024 should match tablet 768) */
@media (max-width: 1200px) {
  .cat-head, #catalogue .subhead { margin-top: 56px; }
}


/* ================= OUR SERVICE RESTRUCTURE (Ayala 260922: Option G structure + G2 strength) =================
   One heading and one lede for the section; three numbered exhibits (01 the crane photo, 02 the
   timelines, 03 the phases). The comparison plate is retired: the instrument sits on the Moss ground
   and is strengthened for it. The Ink phases plate is the only container in the arc (its 260911
   intent). Sheets: "1 Website Prototype/260922/260922 - Our Service Options (round 2).html" and
   "(round 3).html"; measured arc at 1366x768: 3.3 -> 2.3 screens. Contrast on Moss: conventional line
   1.9:1 at 30% ink (failed WCAG 1.4.11 non-text 3:1 even on the old plate) -> 3.05:1 at 50%;
   Evergreen line 6.4:1; Cedar markers 3.1:1 (filled solid, never hollow, on this ground).
   Marker grammar amendment: an inspection gate is now a SOLID disc with a Warm White check
   (was a hollow ring with a Cedar/Evergreen check) - one meaning per mark still holds. */

/* exhibit labels - L2 sub-eyebrow scale; number in Cedar (umber-bright on the Ink plate) */
.ex-label { font-size: 12px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(28,31,26,0.62); margin: 0 0 12px; }
.ex-label b { font-weight: 600; color: var(--umber-text); margin-right: 12px; }
.ex { min-width: 0; }
.ex .ex-label { margin-bottom: 10px; }
.cmp__head { margin-bottom: 32px; }
.cmp__head--label .cmp__label { margin-bottom: 0; }
.phase-plate .ex-label { color: rgba(242,237,230,0.62); margin-bottom: 8px; }
.phase-plate .ex-label b { color: var(--umber-bright); }
.phase-plate .process__header { margin-bottom: 24px; }

/* one unit: photo -> timelines = 48px, timelines -> phases plate = 48px (.cmp margin, 260911) */
@media (min-width: 901px) { #how-we-deliver { padding-bottom: 0; } #map-your-project { padding-top: 48px; } }

/* the crane photo at 16:9 on desktop so the row ends where the 54-word lede ends (was 4:3 stretched to
   the triad's height); the callouts are in % of the figure and follow the crop */
@media (min-width: 901px) { .deliver-grid { align-items: start; } .deliver-img img { height: auto; aspect-ratio: 16/9; object-position: 50% 45%; } }

/* plate retired: no surface, no inset; anything that took the plate fill takes the ground */
.cmp__plate { --plate-solid: #E0E3DD; background: transparent; border: 0; border-radius: 0; padding: 0; box-shadow: none; }

/* strength, all widths: solid markers, Warm White checks, soft shadow under each marker */

/* strength, HORIZONTAL (>900): line 2 -> 3px moves its centre from 1 to 1.5px, so every marker top
   shifts +0.5 (top = 1.5 - outer/2; border-box maths as the 260921 plate fix). Stage dot 10 -> 12px. */

/* strength, VERTICAL (<=900): the line runs down the left; centre x moves 1 -> 1.5px, so lefts shift +0.5.
   Stage dot 12px: x = 1.5 - 6, y = 9.5 - 6 (first text line centre ~9.5, as the 260918 rule). */


/* ================= OUR SERVICE STACKED (Ayala 260922 pm: Option H1, photo after the timelines) =================
   Fixed-measure text beside fluid media scales asymmetrically (at 1920 the 16:9 photo was twice the lede's
   height and the column ended in air). Now nothing sits beside anything: heading + lede at the measure,
   01 timelines, 02 the crane photo full width at 2.4:1 with its callouts, 03 the phases plate. Arc at
   1366x768: 2.3 -> ~2.8 screens (the photo's height), still under the 3.3 of the pre-restructure page. */
/* 260922 (Ayala): the crane photo shows the FOUNDATION PLATFORM - 2:1 pinned to the bottom edge keeps both the roof
   peak and the platform (2.4:1 could hold one or the other). Applies wherever the callouts ride on the photo
   (>600px); below 600 the photo is 4:3 and the lists drop beneath it. Cards widened to 26% with larger type now
   that the photo is full width; leaders end at the card edges (4 + 26 = 30% / 100 - 4 - 26 = 70%). */
@media (min-width: 601px) {
  .ex--wide .deliver-img img { height: auto; aspect-ratio: 2/1; object-position: 50% 100%; }
  .ex--wide .deliver-card { width: 26%; padding: 12px 14px 10px; }
  .ex--wide .deliver-card__h { font-size: 13px; margin-bottom: 6px; padding-bottom: 6px; }
  .ex--wide .deliver-card li { font-size: 13px; line-height: 1.3; padding: 4px 0; gap: 9px; }
}
@media (min-width: 901px) {
  .deliver-grid { grid-template-columns: 1fr; gap: 0; }
  .ex--wide { margin: 0 0 var(--space-5); }                                   /* photo -> phases plate = 48, the arc's within-unit token */
}
@media (max-width: 900px) { .ex--wide { margin: 0 0 40px; } }

/* 260928 cleanup: the retired .lcmp/.lbar/.lseg/.llanes timeline rules were removed (copy in Archive/260928 - site cleanup). */
/* ================= TIMELINES RANKED (Ayala 260922 pm: Option J3, lighter tail) =================
   Two rows drawn with one weight read as equals; colour alone says "different", not "better". The
   conventional row steps back, the Placemark row steps forward, and a dashed Evergreen guide from the
   Placemark finish "trims" the conventional row: its LINE fades beyond the guide, its TEXT stays AA.
   GEOMETRY CORRECTION: pseudo-elements are border-box (global rule, line 202) and are positioned from
   the segment's padding edge, i.e. below the line's own border. Horizontal: top = L/2 - L - S/2.
   The 260922 morning values (-10.5 / -6.5 / -4.5 / -8.5 on a 3px line) were 1px low; Ayala saw it. */

/* conventional row: quiet baseline. Line 3px at 50% ink (3.05:1), markers grey at 50% (3.05:1),
   labels ink 80% (7.4:1), subs 75% (6.3:1) - the tail fade below leaves them >= 4.5:1. */

/* vertical rows (<=900): the same ranking in weight and type; no guide (rows are stacked, not parallel).
   left = L/2 - L - S/2; tops centre on the first text line (~9.5px). */


/* ================= TIMELINES RANKED, REVISION 2 (Ayala 260922 pm, annotated screenshot) =================
   1. Subheadings: the exhibit labels (12px uppercase + 01/02/03) were too light to register against the
      page's hierarchy. "Modular vs. Conventional" and "Arrives Complete" are module headings again
      (.cmp__h3, D4 rung: 22-30px / 800); no numbers; the "03" label on the phases plate is gone.
   2. Guide: no text. The dashed line hangs from the conventional line down to the Placemark line, at the
      x of the "Open to guests" marker (the marker is 20px, right: -1px on a 58%-wide bar -> its centre
      sits 9px inside the bar's right edge; the 2px dashed border is centred with a further -1px).
      Height = the conventional bar's own height + the gap to the Placemark line (row margin 56 + the
      Placemark row label block 56) - measured to land on the Placemark line's centre.
   3. No tail fade: the conventional row keeps one colour and one opacity along its whole length. */
.ex__h3 { margin-bottom: 18px; }


/* 260922 (Ayala): "Measured in years" read like a step label ("Open to guests") - same size, weight and colour.
   Upper case, chip-sized and chip-spaced, so it pairs with the Evergreen "Measured in months" chip below it:
   same type, no box, colour and weight unchanged. */

/* ================= PHOTO BESIDE THE LEDE (Ayala 260922 pm) =================
   The crane photo returns to the grid's right column at its NATURAL 3:2 aspect (Ayala's edited crop shows the
   platform, so no CSS crop and no object-position). The lede is vertically centred beside it (the Sketch Mock
   layout she chose). Supersedes the STACKED photo block and the 16:9 / 2:1 crops above; .ex--wide is unused. */
@media (min-width: 901px) {
  .deliver-grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 56px; align-items: center; }
  .ex--side .deliver-img img { height: auto; aspect-ratio: auto; object-position: 50% 50%; }
}
.ex--side { margin: 0; }
.ex--side .deliver-img img { height: auto; aspect-ratio: auto; }   /* every width where the callouts ride the photo (>600) uses the picture's own frame */
@media (max-width: 600px) { .ex--side .deliver-img img { aspect-ratio: 4/3; object-fit: cover; } }
.deliver-cap { font-size: 13px; font-weight: 300; line-height: 1.55; color: rgba(28,31,26,0.62); margin-top: 10px; }
@media (max-width: 900px) { .ex--side { margin-top: 28px; } }
/* ---------- Hero gallery (260917, Ayala) -----------------------------
   After the intro (or at once when it does not play) the four hero photos
   become a manual gallery: arrows + dots at the lower right, swipe on touch,
   a click on the photo opens the shared lightbox. Gated behind html.hero-gal,
   which script.js adds, so the no-JS hero stays one static photo. The
   parallax moves every layer through --hero-py (set on .hero by script.js),
   so a flipped photo sits exactly where the previous one was. Keep this
   block ABOVE the HERO INTRO marker: the port rewrites everything below it. */
.hero__img { transform: translateY(var(--hero-py, 0px)); }
html.hero-gal .hero .hero__img--intro { display: block; }
html.hero-gal .hero .hero__img { opacity: 0; transition: opacity 0.9s ease; }
html.hero-gal .hero .hero__img.is-gal-active { opacity: 1; }
html.hero-gal .hero .hero__img--i1 { transform: translateY(var(--hero-py, 0px)) scale(1.04); }
@media (max-width: 900px) { html.hero-gal .hero .hero__img--i1 { transform: translateY(var(--hero-py, 0px)); } }
html.hero-gal .hero { cursor: zoom-in; }
html.hero-gal .hero__content, html.hero-gal .hero__scroll, html.hero-gal .hero__gal { cursor: auto; }
/* Controls follow the sitewide arrow button (.cat-nav__btn: 44px square,
   hairline border, CSS chevron, Sunburst on hover), recoloured Warm White
   for the photo (Ayala 260917: "consistent with the other arrows"). Dots use
   the same hairline: an outlined circle that fills when current. */
.hero__gal { position: absolute; right: 40px; bottom: 40px; z-index: 3; display: flex; align-items: center; gap: 8px;
  opacity: 0; transition: opacity 0.6s ease 0.3s; }   /* right: 40px = the nav gutter, so the next arrow shares the hamburger's right edge (Ayala 260917) */
html.hero-gal .hero__gal { opacity: 1; }
.hero__gal[hidden] { display: none; }
.hero__gal .cat-nav__btn { color: var(--fog); border-color: rgba(242,237,230,0.55); cursor: pointer; }
.hero__gal .cat-nav__btn:hover { background: var(--sunburst); border-color: var(--sunburst); color: var(--fog); }
.hero__gal-dots { display: flex; align-items: center; height: 44px; padding: 0 6px; }
.hero__gal-dot { position: relative; width: 24px; height: 24px; padding: 0; border: 0; background: transparent; cursor: pointer; }
.hero__gal-dot::before { content: ''; position: absolute; left: 7px; top: 7px; width: 8px; height: 8px; border-radius: 50%;
  border: 1px solid rgba(242,237,230,0.7); background: transparent; transition: background 0.2s var(--ease), border-color 0.2s var(--ease); }
.hero__gal-dot:hover::before { background: rgba(242,237,230,0.45); border-color: var(--fog); }
.hero__gal-dot[aria-current="true"]::before { background: var(--fog); border-color: var(--fog); }
.hero__gal .cat-nav__btn:focus-visible, .hero__gal-dot:focus-visible { outline: 2px solid var(--fog); outline-offset: 2px; }
@media (max-width: 900px) {
  .hero__gal { right: 24px; bottom: auto; top: 84px; }   /* 24px = the mobile nav gutter (hamburger's right edge) */
  .hero__gal-btn { display: none; }
  .hero__gal-dot { width: 32px; height: 32px; }          /* 260918: touch target 32px (dot itself stays 8px) */
  .hero__gal-dot::before { left: 12px; top: 12px; }
}

/* =====================================================================
   HERO INTRO (ported 260921, Option 2: intro, photo hero).
   Source of truth: 1 Website Prototype\260916\260916 - Hero Intro Animation Prototype v2 (elevation).html and the builder that wrote it;
   re-run the builder and port_hero_intro.py rather than editing here.
   ===================================================================== */
:root {
  --i-ease: cubic-bezier(0.33, 0, 0.2, 1);       /* calm in-out, no overshoot */
  --iw: min(640px, 86vw);                         /* one width drives sketch AND logo, so their ratio holds at every viewport */
  --i-mark: 0.8s;     /* logomark fade-in */
  --i-lockup: 1.3s;   /* cabins out, mark scales down into its slot; the wordmark fades over the last 0.7 s */
  --i-tohead: 1.2s;   /* logo travels to the header */
  --i-photo: 2.0s;    /* hero photo 1 fades in full-bleed under the lockup (260921; was at tohead, 260916) */
  --i-xfade: 2.0s;    /* photo 1 -> photo 2 cross-fade (260916) */
  --i-content: 0.9s;  /* hero content fade */
}

/* HERO CSS (carried in block 3) - v2 260916: photo hero, four photos in the intro, slots: Cabin_Hero_4 -> 1 -> 3 -> 2 */
.hero { height: 84vh; min-height: 600px; background: var(--ink); }
.hero__img, .hero__overlay { display: block; }
.hero__img { background-image: url("images/hero-cabin-2.webp"); background-position: center 55%; }
/* the intro-only photos: hidden (and never fetched) for no-JS / reduced-motion */
.hero__img--intro { display: none; }
.hero__img--i1 { background-image: url("images/hero-cabin-4.webp"); background-position: center 100%; }  /* SLOT 1 = CAD Hero 1 render (260922, expanded plate cut to Ayala's red frame, 2:1 bottom-anchored: position 100% shows her exact frame in a 2.44:1 window and ~15% more sky on 16:9). The old scale(1.04) from the left edge was tuned for the stock photo and pushed the right cabin off the frame - removed 260922 pm; cabins now sit x 57-96 %, y 65-73 % of a 2.44:1 hero (her yellow box). Was Cabin_Hero_4 stock at 33%: Ayala's frame - peaks with little sky, lake below the cabins, picture nudged 4% right so the first cabin clears the text panel (the partial 4th cabin at the edge crops) */
.hero__img--i2 { background-image: url("images/hero-cabin-1.webp"); background-position: center; }  /* SLOT 2 = Cabin_Hero_1 (alpine valley, 2.2:1): nearly the hero's own proportions - full height shows, ~4% width trims evenly (Ayala's mockup) */
/* Text must not cover the cabins (Ayala 260916). The hero photos put the cabins in the right 45% of the frame,
   and at laptop widths the 62px headline made the text panel ~67% of the viewport, so it overlapped them.
   The headline now scales with the viewport (3.4vw) and only reaches 62px from ~1824px wide; at 1366 it is
   46px and the panel ~50% wide, clearing the cabins with room to spare. Two-line UVP still holds (nowrap lines). */
.hero__h1 { font-size: clamp(28px, 2.75vw, 54px); }   /* HERO PANEL B (Ayala 260922 pm): was 3.4vw/62. The panel must END before x 48 % - the first cabin of the Hero 1 render, and the static hero's deck sits at 50 % - so every hero image reads uncovered (clearance sheet 260922). */
@media (min-width: 901px) {
  .hero__content { padding: 30px 34px; }                                             /* was 38/42 */
  .hero__pillars { margin: 0 0 30px; gap: 8px 14px; }                                  /* was 2/40, 10/26 */
  .hero__pillars span { letter-spacing: 0.14em; }                                      /* was 0.18em */
  .hero__pillars span + span::before { margin-right: 14px; }
  .hero__ctas a { padding-left: 18px; padding-right: 18px; }                            /* hero only; the site button stays 26px. At 1366 the CTA row set the panel width */
}
.hero__img--i3 { background-image: url("images/hero-cabin-3.webp"); background-position: center top; }  /* SLOT 3 = Cabin_Hero_3 (winter lake, 16:9): anchored top so the peak clears the header; the foreground snow crops */
@media (max-width: 900px) { .hero__img--i1 { transform: none; background-position: center; } }
html.has-intro .hero__img--intro { display: block; }
@media (max-width: 900px) { .hero { height: 100vh; min-height: 640px; } }
/* while the intro plays, mask the section that peeks in below the shorter hero; it lifts
   with the content reveal so the page below simply appears as the hero settles */
html.has-intro .intro::after { content: ''; position: fixed; left: 0; right: 0; bottom: 0;
  top: max(84vh, 600px); background: var(--ink); transition: opacity 0.9s var(--i-ease); }
html.is-content .intro::after { opacity: 0; }
/* photos and scrim stay hidden behind the Ink intro until the logo leaves for the header.
   is-tohead: photo 1 + scrim fade in (--i-photo).  is-content: text panel fades in over photo 1.
   is-photo3 (after the text is fully in): photo 1 fades out while photo 3 fades in (--i-xfade,
   both at once), under the text.  is-photo4 (after a hold): 3 out, 4 in.  is-photo2 (after a hold): 4 out, 2 in. */
html.has-intro .hero__img, html.has-intro .hero__overlay { opacity: 0; }
html.has-intro .hero__img--i1, html.has-intro .hero__overlay { transition: opacity var(--i-photo) var(--i-ease); }
html.has-intro .hero__img--i2, html.has-intro .hero__img--i3, html.has-intro #heroBg { transition: opacity var(--i-xfade) var(--i-ease); }
html.is-lockup .hero__img--i1, html.is-lockup .hero__overlay { opacity: 1; }   /* 260921: photo in at the lockup beat (was tohead) */
html.is-photo3 .hero__img--i1 { opacity: 0; transition-duration: var(--i-xfade); }
html.is-photo3 .hero__img--i2 { opacity: 1; }
html.is-photo4 .hero__img--i2 { opacity: 0; }
html.is-photo4 .hero__img--i3 { opacity: 1; }
html.is-photo2 .hero__img--i3 { opacity: 0; }
html.is-photo2 #heroBg { opacity: 1; }
html.has-intro .hero__content { opacity: 0; transition: opacity var(--i-content) var(--i-ease); }
html.is-content .hero__content { opacity: 1; }

/* ---- overlay scaffolding: transparent, above the header, never blocks input ---- */
.intro { display: none; }
html.has-intro .intro { display: block; position: fixed; inset: 0; z-index: 600; pointer-events: none; }

/* ---- scene 1: the two cabins sketch themselves in elevation.  Lines are stored with
   pathLength=1 so a 1→0 dash offset draws each stroke; per-line start (--d) and duration
   (--t) come from the generator at constant pen speed, in drawing order.
   non-scaling-stroke keeps every line crisp at any size. ---- */
.intro__cabins { position: fixed; left: 50%; top: 50%; width: var(--iw); height: auto; color: var(--fog);
  transform: translate(-49.70%, -48.87%);     /* puts the logomark anchor at the viewport centre */
  transition: opacity var(--i-lockup) var(--i-ease); }
.intro__cabins .s { vector-effect: non-scaling-stroke; stroke-dasharray: 1; stroke-dashoffset: 1; }
.intro__cabins .s1 { stroke-width: 1.9; }  /* 260918: ~12% heavier than the 260916 weights (1.7/1.6/1.15/1) so the pencil grain has something to bite into */
.intro__cabins .s2 { stroke-width: 1.8; }
.intro__cabins .s3 { stroke-width: 1.3; }
.intro__cabins .s4, .intro__cabins .s5 { stroke-width: 1.15; }
html.is-sketch .intro__cabins .s { animation: introDraw var(--t) linear var(--d) both; }
@keyframes introDraw { to { stroke-dashoffset: 0; } }

/* ---- scenes 2–4: one SVG, official path data.  Mark phase: the svg is
   scaled about the mark's own centre and shifted so that centre sits at the
   viewport centre, between the cabins.  Lockup phase: transform releases to
   none — the mark eases into its slot while the wordmark fades in and the
   whole logo is centred. ---- */
.intro__logo { position: fixed; left: 50%; top: 50%; width: var(--iw); transform: translate(-50%, -50%); }
.intro__logo svg { display: block; width: 100%; height: auto; fill: var(--fog);
  transform-origin: 61.77% 50%;                                 /* the mark's centre within the logo */
  transform: translateX(-11.77%) scale(2.203);
  transition: transform var(--i-lockup) var(--i-ease); }
.intro__logo .lg-mark { opacity: 0; transition: opacity var(--i-mark) var(--i-ease); }
.intro__logo .lg-word { opacity: 0; transition: opacity 0.7s cubic-bezier(0.4, 0, 0.6, 1) 0.6s; }
html.is-mark .lg-mark { opacity: 1; }
html.is-lockup .intro__cabins { opacity: 0; }
html.is-lockup .intro__logo svg { transform: none; }
html.is-lockup .lg-word { opacity: 1; }

/* ---- scene 5: FLIP to the header (inline transform set by JS from the real
   header logo's rect) ---- */
html.is-tohead .intro__logo { transition: transform var(--i-tohead) var(--i-ease); transform-origin: 0 0; }
html.is-landed .intro__logo { visibility: hidden; }
html.has-intro .nav__logo-svg { opacity: 0; }
html.is-landed .nav__logo-svg { opacity: 1; }

/* ---- scene 6: hero content — opacity-led, 6px lift, staggered UVP → pillars → CTAs ---- */
html.has-intro .hero__h1, html.has-intro .hero__pillars, html.has-intro .hero__ctas, html.has-intro .hero__scroll {
  opacity: 0; transform: translateY(6px);
  transition: opacity var(--i-content) var(--i-ease), transform var(--i-content) var(--i-ease); }
html.is-content .hero__h1, html.is-content .hero__pillars, html.is-content .hero__ctas, html.is-content .hero__scroll { opacity: 1; transform: none; }
html.is-content .hero__pillars { transition-delay: 0.35s; }
html.is-content .hero__ctas { transition-delay: 0.7s; }
html.is-content .hero__scroll { transition-delay: 1s; }

@media (prefers-reduced-motion: reduce) {
  html.has-intro .intro { display: none; }
  html.has-intro .nav__logo-svg, html.has-intro .hero__h1, html.has-intro .hero__pillars,
  html.has-intro .hero__ctas, html.has-intro .hero__scroll, html.has-intro .hero__content,
  html.has-intro .hero__img, html.has-intro .hero__overlay { opacity: 1 !important; transform: none !important; transition: none !important; }
}


/* ================= TIMELINE v2 (Ayala's sketch, 260925) =================
   Supersedes every .lcmp / .lbar / .lseg / .llanes rule above: that markup left index.html on 260925, so those
   rules are dead (sweep candidate; left in place so this pass touches one block). What Ayala decided:
   Placemark Builds first, Conventional Site Build second (as the heading reads) - Title Case - one 16px circle
   for every step, 8px start dot - the Placemark line is HALF the conventional line from 1600px up, and a little
   longer on laptops so the labels breathe (57% at 1366-1599, 60% at 1280-1365; "balance over an exact half") -
   the "Complete in Half the Time" chip sits on its own line under the name (never beside it), ending where the
   Placemark line ends, 14px under the name and 22px above the first marker - checks on Built + Certified in
   Factory and Occupancy Approvals only - Site Preparation runs Built -> Transported, its two circles exactly on
   those two (slots are exact % of the line: flex 0 0 N%, so padding never shifts a circle) - labels start on
   the LEFT edge of their circle; both "Open to Guests" end on the RIGHT edge of theirs (on large screens the
   one-line label hangs left of its slot via a flex-end item, which stays in flow) - the dashed Evergreen guide
   drops from under the Placemark "Open to Guests" to just past the conventional line - no footnote (Paul + Theo).
   Marker maths as before: pseudo-elements are border-box and sit below the line's own border, so
   top = L/2 - L - S/2 (3px line, 16px circle: -9.5; 4px: -10). Below 900px the same lists stack vertically
   (line down the left, Site Preparation in sequence), the phone treatment Ayala kept. */
.tl { display: grid; grid-template-columns: minmax(0, 1fr); --tl-in: 4px; --tl-out: 13px; --tl-conv: calc(100% - var(--tl-in) - var(--tl-out)); --tl-half: 0.5; --tl-ours: calc(var(--tl-conv) * var(--tl-half)); --ground: #E0E3DD; }
.tl ol { list-style: none; margin: 0; padding: 0; }
.tl__head { grid-column: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 14px; margin: 0 0 26px; }
.tl__head p { margin: 0; }
.tl__name { font-size: 15px; font-weight: 500; letter-spacing: 0.02em; color: rgba(28,31,26,0.78); }
.tl__head--ours { grid-row: 1; margin-bottom: 32px; }   /* chip -> marker top = 32 - 10 = 22px of air */
.tl__head--ours .tl__name { font-size: 17px; font-weight: 700; color: var(--ink); }
.tl__name-sub { font-weight: 300; color: rgba(28,31,26,0.65); }
.tl__name-sub::before { content: "· "; }
.tl__tag { background: var(--forest); color: var(--fog); font-size: 12px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; padding: 5px 12px 4px; border-radius: 2px; white-space: nowrap; }
.tl__track { grid-column: 1; position: relative; }
.tl__track--ours { grid-row: 2; }
.tl__head--conv { grid-row: 3; }
.tl__track--conv { grid-row: 4; }
.tl__step { position: relative; min-width: 0; font-size: 13.5px; font-weight: 400; line-height: 1.35; color: rgba(28,31,26,0.8); }
.tl__t, .tl__sub { display: block; text-wrap: balance; }
.tl__sub { font-size: 12.5px; font-weight: 300; line-height: 1.45; margin-top: 4px; color: rgba(28,31,26,0.75); }
.tl__step::before { content: ""; position: absolute; width: 16px; height: 16px; border-radius: 50%; background: #7E817C; z-index: 2; }   /* ink 50% on Moss, opaque */
.tl__step--start::before { width: 8px; height: 8px; }
.tl__step--end { font-weight: 500; }
.tl__step--end::before { background: #74776E; box-shadow: 0 0 0 5px #C9CBC6; }   /* ink 55% + halo ink 12%, composited on Moss */
.tl__track--ours .tl__step { font-size: 15.5px; font-weight: 600; color: var(--forest-dark); }
.tl__track--ours .tl__sub { font-size: 13px; font-weight: 400; color: rgba(26,69,35,0.78); }
.tl__track--ours .tl__step::before { background: var(--forest); box-shadow: 0 0 0 2px var(--fog), 0 2px 4px rgba(28,31,26,0.3); }
.tl__track--ours .tl__step--start::before { box-shadow: none; }
.tl__track--ours .tl__step--end { font-size: 16px; font-weight: 700; }
.tl__track--ours .tl__step--end::before { box-shadow: 0 0 0 7px #B6C5B6, 0 3px 6px rgba(28,31,26,0.3); }   /* halo = Evergreen 22% on Moss, opaque */
.tl__track--ours .tl__step--insp::after { content: ""; position: absolute; width: 16px; height: 16px; background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><path d='M2.4 5.3 L4.3 7.1 L7.8 3.2' fill='none' stroke='%23F2EDE6' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 100% 100% no-repeat; z-index: 3; }   /* Warm White check over the same 16px circle */

/* HORIZONTAL (>900): two rows on one grid, the Placemark row first */
@media (min-width: 901px) {
  .tl__head--ours { width: calc(var(--tl-in) + var(--tl-ours) + 15px); }   /* +15 = the end marker's 8px overhang + 7px halo: the chip ends on the halo's edge */
  .tl__tag { align-self: flex-end; }
  .tl__track { margin-left: var(--tl-in); }
  .tl__track--ours { width: var(--tl-ours); margin-bottom: 56px; }
  .tl__track--conv { width: var(--tl-conv); }
  .tl__line, .tl__lane { display: flex; width: 100%; }
  .tl__step { padding: 16px 20px 0 0; border-top: 3px solid rgba(28,31,26,0.5); box-shadow: inset 0 1px 0 rgba(255,255,255,0.55); }   /* hairline of light under the line lifts it off the ground */
  .tl__t, .tl__sub { margin-left: -8px; }   /* text starts on the circle's left edge */
  .tl__step::before { left: -8px; top: -9.5px; }
  .tl__step--start { padding: 0; }
  .tl__step--start::before { left: -4px; top: -5.5px; }
  .tl__step--tight { padding-right: 0; }
  .tl__step--greedy .tl__t { text-wrap: wrap; }   /* "with Servicing / Connections", never an orphaned "with" */
  .tl__step--end { padding: 16px 0 0 8px; text-align: right; }
  .tl__step--end .tl__t { margin: 0 -8px 0 0; background: var(--ground); position: relative; z-index: 2; padding-bottom: 10px; }   /* ends on the circle's right edge; covers the guide */
  .tl__step--end::before { left: auto; right: -8px; }
  .tl__track--ours .tl__step { border-top: 4px solid var(--forest); box-shadow: inset 0 1px 0 rgba(255,255,255,0.35); }
  .tl__track--ours .tl__step::before { top: -10px; }
  .tl__track--ours .tl__step--start { padding: 0; }
  .tl__track--ours .tl__step--start::before { top: -6px; }
  .tl__track--ours .tl__step--insp::after { left: -8px; top: -10px; }
  .tl .tl__lane { margin: 28px 0 0 27.06%; width: 21.2%; }   /* start = 4.46 + 22.6 (the Built circle); width = the Built slot (to the Transported circle) */
  .tl__step--lane { padding-right: 0; }
  .tl__step--lane::after { content: ""; position: absolute; right: -8px; top: -10px; width: 16px; height: 16px; border-radius: 50%; background: var(--forest); box-shadow: 0 0 0 2px var(--fog), 0 2px 4px rgba(28,31,26,0.3); z-index: 2; }
  .tl__guide { grid-row: 2 / 4; grid-column: 1; justify-self: start; align-self: stretch; width: 0; border-left: 2px dashed rgba(34,89,45,0.75); margin: 2px 0 -12px calc(var(--tl-in) + var(--tl-ours) - 1px); z-index: 1; pointer-events: none; }
}
/* large screens: the one-line "Open to Guests" hangs LEFT of its slot (a flex item overflowing with flex-end goes left, in flow) */
@media (min-width: 1800px) {
  .tl__track--ours .tl__step:nth-child(3) { flex-basis: 18.5% !important; }
  .tl__track--ours .tl__step:nth-child(6) { flex-basis: 13.54% !important; }
  .tl .tl__lane { width: 18.5%; }
  .tl__keep { white-space: nowrap; }
  .tl__step--end .tl__t { display: flex; justify-content: flex-end; white-space: nowrap; }
}
/* laptops: the Placemark line stretches past half and its type steps down one rung so the labels breathe */
@media (min-width: 901px) and (max-width: 1599px) {
  .tl { --tl-half: 0.57; }
  .tl__track--ours .tl__step { font-size: 14px; }
  .tl__track--ours .tl__step--end { font-size: 14.5px; }
  .tl__track--ours .tl__sub { font-size: 12.5px; }
  .tl__track--ours .tl__step:nth-child(2) { flex-basis: 21.1% !important; }
  .tl__track--ours .tl__step:nth-child(3) { flex-basis: 19.7% !important; }
  .tl__track--ours .tl__step:nth-child(4) { flex-basis: 31.6% !important; }
  .tl .tl__lane { margin-left: 25.56%; width: 19.7%; }
}
@media (min-width: 901px) and (max-width: 1365px) {
  .tl { --tl-half: 0.6; }
  .tl__track--ours .tl__step { font-size: 13.5px; }
  .tl__track--ours .tl__step--end { font-size: 14px; }
  .tl__track--ours .tl__step:nth-child(2) { flex-basis: 20.6% !important; }
  .tl__track--ours .tl__step:nth-child(3) { flex-basis: 19.6% !important; }
  .tl__track--ours .tl__step:nth-child(4) { flex-basis: 32.2% !important; }
  .tl .tl__lane { margin-left: 25.06%; width: 19.6%; }
  .tl__track--conv .tl__step:nth-child(5) .tl__t { max-width: 6.5em; }   /* Plumbing / + Electrical on two lines: one line sat 14px from Insulation */
}
@media (min-width: 901px) and (max-height: 800px) { .tl__step, .tl__step--end { padding-top: 12px; } }   /* laptop-height fit, as the old rows */

/* VERTICAL (<=900): each row a list down the left edge; the same node grammar; Site Preparation in sequence
   after Built + Certified (the name already says "Factory + Land in Parallel"); no guide (rows stacked, not parallel).
   left = L/2 - L - S/2 (3px line, 16px: -9.5; 4px: -10); tops centre on the first text line (~9.5px). */
@media (max-width: 900px) {
  .tl__head { gap: 10px; margin-bottom: 22px; }
  .tl__name-sub { display: block; margin-top: 2px; font-size: 14px; line-height: 1.4; }
  .tl__name-sub::before { content: none; }
  .tl__tag { font-size: 11.5px; padding: 5px 10px 4px; }
  .tl__track { display: flex; flex-direction: column; }
  .tl__line, .tl__lane { display: contents; }
  .tl__step { flex: none !important; }   /* the inline slot widths (flex 0 0 N%) would become HEIGHTS in a column */
  .tl__track--ours { margin-left: 6px; margin-bottom: 40px; }    /* the circle's left edge on the content edge */
  .tl__track--conv { margin-left: 6.5px; }
  .tl__step { border-left: 3px solid rgba(28,31,26,0.5); box-shadow: inset 1px 0 0 rgba(255,255,255,0.55); padding: 0 0 20px 22px; font-size: 14px; }
  .tl__track--ours .tl__step { border-left: 4px solid var(--forest); box-shadow: inset 1px 0 0 rgba(255,255,255,0.35); font-size: 15px; }
  .tl__step::before { left: -9.5px; top: 1.5px; }
  .tl__track--ours .tl__step::before, .tl__track--ours .tl__step--insp::after { left: -10px; top: 1.5px; }
  .tl__step--start { height: 20px; padding: 0; }
  .tl__step--start::before { left: -5.5px; top: 0; }
  .tl__track--ours .tl__step--start::before { left: -6px; }
  .tl__step--end, .tl__track--ours .tl__step--end { border-left-color: transparent; box-shadow: none; padding-bottom: 0; }
  .tl__track--ours .tl__step--end { font-size: 15px; }
  .tl__track--ours .tl__line .tl__step:nth-child(n+4) { order: 2; }   /* Transported, Occupancy Approvals, Open to Guests follow the lane */
  .tl__lane .tl__step { order: 1; }
  .tl__guide { display: none; }
}

/* 260925 (critique small fixes): the crane callout cards grow with the photo on large screens but their text did not */
@media (min-width: 1600px) {
  .deliver-card { padding: 10px 12px 8px; }
  .deliver-card__h { font-size: 13.5px; margin-bottom: 6px; padding-bottom: 6px; }
  .deliver-card li { font-size: 13px; line-height: 1.3; padding: 4px 0; gap: 9px; }
}

/* ================= PHASES: LEDE + GROUPS (260925, Ayala) =================
   The plate gets its lede back, and the two companies are named over their phases. Composition chosen after a
   busy first draft: on laptops the heading + lede sit LEFT and the sketch RIGHT (440px, where the laptop-fit tiers
   had squeezed it to 294px), the hint becomes the sketch's caption, and the group row carries only the company
   names in Cedar (--umber-bright on Ink: raw Cedar fails AA below 18px). Each group line runs from its first
   phase to the centre of its LAST dot (Ayala: "end in alignment with the last circle", all sizes). Below 900px
   the row is hidden; stacked screens carry no company caption (the per-phase .phase__group captions were removed 260925, "too busy").
   Cost: +104px on the plate at 1366x768 (the lede), so the plate no longer frames in one laptop screen - Ayala
   accepted that 260925. No second button: the lede's "Placemark Design" link goes to About Us. */
.phase-plate .process__lede { margin: 12px 0 0; }
.lede-link { color: var(--fog); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; padding: 4px 0; transition: color 0.2s; }   /* 24px tap height, as .form-alt a */
.lede-link:hover { color: var(--sunburst); }
.process__groups { display: grid; grid-template-columns: repeat(5, 1fr); margin: 0 0 22px; }
.process__group { margin: 0; padding: 0 0 9px; border-bottom: 1px solid rgba(200,153,104,0.6); font-size: 12px; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; color: var(--umber-bright); line-height: 1.3; }
.process__group--design { grid-column: 1 / span 2; margin-right: 28px; }   /* 260925 (Ayala): runs to just short of the Builds line - a 28px break, not a gap back to dot 2 */
.process__group--build { grid-column: 3 / span 3; margin-right: calc(33.333% - 8px); }   /* ends on dot 5's centre */
@media (min-width: 901px) {
  .phase-plate { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); column-gap: 48px; row-gap: 0; align-items: center; }
  .phase-plate .process__header { grid-column: 1; grid-row: 1; margin: 0; }
  .phase-plate .sketch-stage { grid-column: 2; grid-row: 1; margin: 0; }
  .phase-plate .sketch-stage svg { width: min(440px, 100%); }   /* outranks the laptop-height tiers above by order */
  .phase-plate .process__hint { grid-column: 2; grid-row: 2; margin: 6px 0 0; align-self: start; }
  .phase-plate .process__groups { grid-column: 1 / -1; grid-row: 3; margin-top: 36px; }
  .phase-plate .process__track-wrap { grid-column: 1 / -1; grid-row: 4; }
  .phase-plate .process__cta { grid-column: 1 / -1; grid-row: 5; margin-bottom: 37px; }   /* 260925 (Ayala): the sketch SVG carries 37px of blank space above its first stroke (measured), so the plate's top air reads 37px deeper than its padding; the button gets the same 37px below so the two ends match at every height tier */
}
/* the phases stack into one column from 1200px down (rule above, 260918): the spanning row goes with them.
   260925 (Ayala): no per-phase company caption on stacked screens either - it made the phone cards "too busy". */
@media (max-width: 1200px) { .process__groups { display: none; } }

/* 260928 PRIVACY NOTICE popup (Ayala): house :target modal, text-width panel */
.form-privacy a, .footer__legal { color: inherit; text-decoration: underline; text-underline-offset: 3px; padding: 4px 0; }
.form-privacy a:hover { color: var(--fog); }
.footer__legal:hover { color: rgba(242,237,230,0.95); }
.modal--privacy .modal__panel { max-width: 760px; max-height: 86vh; }
.legal__bar-label { font-size: 12px; font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; color: var(--forest); padding: 6px 0; }
.modal--privacy .msheet__nav .modal__close { margin-left: auto; }
.modal--privacy .modal__title { font-size: clamp(28px, 2.6vw, 36px); margin-bottom: 8px; }
.legal .legal__date { font-size: 13px; font-weight: 400; color: rgba(28,31,26,0.65); margin: 0 0 24px; }
.legal .legal__intro { margin: 0 0 8px; }   /* B1 like the rest: 18px is reserved for .closer */
.legal h4 { font-family: 'Lexend Deca', sans-serif; font-size: 18px; font-weight: 800; line-height: 1.3; color: var(--ink);
  margin: 28px 0 10px; padding-top: 22px; border-top: 1px solid rgba(28,31,26,0.14); }
.legal p, .legal li { font-size: 16px; font-weight: 300; line-height: 1.7; color: rgba(28,31,26,0.72); }   /* B1 */
.legal p { margin: 0 0 12px; }
.legal ul { margin: 0 0 12px; padding-left: 20px; list-style: disc; }
.legal li { margin-bottom: 8px; }
.legal b { font-weight: 500; color: var(--ink); }   /* E1 emphasis: Medium + full Ink */
.legal a:not(.modal__close) { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.legal a:not(.modal__close):hover { color: var(--forest); }
.legal__contact { margin-top: 28px; padding: 20px 24px; background: #fff; }
.legal__contact p { margin: 0; }
@media (max-width: 600px) {
  .modal--privacy .modal__panel { max-height: 90vh; }
  .legal__contact { padding: 18px 18px; }
}

/* 260928 pm PARTNER PHOTO framing (Ayala): Elk Ridge crane-set photo, one crop.
   Horizontal 45% keeps the crane + module in the portrait laptop frames (1201-1649);
   the wide bands (tablets, >=2100) sit high so the crane tip, module and truck cab stay in. */
.partner__img img { object-position: 45% 50%; }
@media (min-width: 480px) and (max-width: 1200px) { .partner__img img { object-position: 50% 45%; } }   /* full-frame band */
@media (min-width: 2100px) { .partner__img img { object-position: 45% 85%; } }   /* full-frame band */

/* 260928 MANUFACTURING POPUP, TEXT-ONLY (Ayala): photos removed until Elk Ridge's arrive.
   Each step becomes a text card with a hairline top rule; the panel sizes to its content
   instead of the 94vh photo stage. Paging: 3 cards per view >1100, 2 at 901-1100, 1 below. */
#mfg.modal--nophoto .mslide { border-top: 1px solid rgba(28,31,26,0.16); padding-top: 18px; }
@media (min-width: 901px) {
  #mfg.modal--nophoto .modal__panel { height: auto; max-height: 94vh; }
  #mfg.modal--nophoto .modal__slides { display: flex; flex: none; gap: 16px; grid-auto-columns: unset; grid-template-rows: none; padding-bottom: 8px; }
  #mfg.modal--nophoto .mslide { display: block; flex: 0 0 calc((100% - 32px) / 3); scroll-snap-align: start; }
}
@media (min-width: 901px) and (max-width: 1100px) {
  #mfg.modal--nophoto .mslide { flex-basis: calc((100% - 16px) / 2); }
}
