/* ==========================================================================
   Double Diamond — walkthrough revisions, v16 (2026-08-18)

   RELOCATED TO <head>. This file is now pulled in by a <link> at the end of
   the SITE-LEVEL head custom code (Project settings > Custom code > Head),
   i.e. after the compiled webflow.shared css and after the site head <style>
   block. It used to be loaded by a one-line <link> inside an HtmlEmbed at the
   END of <body> on 11 pages, which meant it arrived after first paint and
   every page visibly re-styled — the flash Matt reported.

   CASCADE NOTE — why every selector below starts with `html body`:
   from <head> this file no longer wins by document order against the pages'
   in-<body> `<style>` embeds. Each selector therefore carries an `html body`
   prefix, adding two ELEMENT units of specificity (same pattern as the
   `html .site-header ...` rules already in the site head code). Two element
   units are enough to win the equal-specificity ties that the old
   end-of-body placement used to win by position, and — because element units
   can never outrank a class or an ID — they cannot flip a rule that already
   beat this file on class/ID specificity. No `!important` anywhere.

   Verified with a computed-style diff of EVERY element on 11 pages x 2
   viewports (390 / 1440), v15-at-end-of-body vs v16-in-head: zero
   differences. Asset URLs are content-hashed and immutable — a change means
   a new upload + repointing the <link> in the site head code.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TYPE SCALE — body copy floor is 14pt (18.7px), everything up from there.
   Audience skews older; readability over delicacy.
   -------------------------------------------------------------------------- */
html body{font-size:clamp(18.7px,1.35vw,20px);line-height:1.458}

/* Body copy, cards, forms, footer, modal prose */
html body .contact-intro,html body .proc-text p,html body .feature-list p,html body .about-col p,html body .diff-blurb p,
html body .service-body p,html body .about-grid>div>p,html body .wwb-copy p,html body .faq-a p,html body .folio-body p,
html body .about-creds-p,html body .modal-foot,html body .duo-sub,html body .process-intro,html body .ba-note,
html body .footer-tag,html body .footer-nav a,html body .footer-contact address,
html body .scope-card-text,html body .cert-desc,html body .dd-gallery-caption{
  font-size:1.19rem;line-height:1.44
}
html body .field input,html body .field textarea,html body .contact-form .w-input,html body .contact-form .w-select{
  font-size:1.15rem
}

/* Lead / intro paragraphs, and the homepage hero subtitle */
html body .philosophy .lead,html body .wwb-copy .lead,html body .modal-lead,html body .hero-lede{
  font-size:clamp(1.32rem,1.75vw,1.6rem);line-height:1.35
}
html body .hero-lede{max-width:52ch}

/* Eyebrows — bigger, and tighter to the title they introduce.
   2026-08-18 (v21): eyebrow→heading gap halved site-wide per Matt ("every
   single eyebrow"), EXCEPT the Home "Home builder" and About "Meet The
   Owner" eyebrows, which already carry their own dedicated, more-specific
   overrides elsewhere (`.about-grid>div>p.eyebrow` and `.eyebrow.tight-gap`
   in the page embeds) and are unaffected by this base-class change. */
html body .eyebrow{font-size:.88rem;letter-spacing:.2em;margin-bottom:.25rem}
html body .hero .eyebrow{font-size:.95rem;margin-bottom:.3125rem}
html body .modal-head .eyebrow,html body .dd-gallery-eyebrow{margin-bottom:.225rem}
/* Footer column labels (h4) — embed sets margin-bottom:.6rem with no shared
   counterpart before now; add one here so all pages get the halved gap from
   a single edit instead of touching each page's own <style> block. */
html body .footer-inner h4{margin-bottom:.3rem}

/* 2026-08-18 (v22) — MARGIN-COLLAPSE FIX for the eyebrow halving above.
   In normal block flow, an eyebrow's margin-bottom collapses with the
   following heading's own margin-top (Webflow's default h1/h2/h3/h4 all
   carry a base margin-top from the compiled reset) — the LARGER of the two
   wins, not the sum. Measured live: Home's hero eyebrow→H1 gap was 10px
   both before and after halving margin-bottom (7.2px→3.6px), because H1's
   own 10px margin-top was already the dominant side of the collapse even
   pre-edit. Same for section-head eyebrow→H2 pairs (Home "Difference",
   About "Our Philosophy"/"Commitment to Quality", Contact's eyebrows): H2's
   native 20px margin-top was masking the eyebrow's margin-bottom the whole
   time. Fix: zero the following heading's margin-top ONLY when it is
   immediately preceded by an eyebrow (adjacent-sibling combinator — no
   other heading anywhere on the site is touched).
   2026-08-18 (v23) — REVERTED the v22 attempt to also retarget
   `.eyebrow`'s margin-bottom to .625rem for heading-following contexts:
   that number was reverse-engineered from ONE pattern (Home "Difference" /
   About "Our Philosophy"/"Commitment to Quality", all originally 20px)
   and, once applied site-wide, made Contact's three section-head eyebrows
   WORSE, not better — their originals were 24px/8px/8px (a different,
   smaller baseline, confirmed live pre-edit), so bumping them to 10px
   made two of the three gaps LARGER than before. `.eyebrow` keeps its
   plain .25rem from above for every heading-following context now; that
   under-shoots "exactly half" for the 20px-original contexts (cuts them
   further than 50%) but is never larger than the original anywhere,
   which matters more given Matt's complaint was always "too much gap",
   never "too little". */
html body .eyebrow + h1,
html body .eyebrow + h2,
html body .eyebrow + h3,
html body .eyebrow + h4{margin-top:0}
/* The hero H1 specifically didn't respond to the rule above — measured live:
   `.hero-title.reveal{margin-top:10px}` (native combo class, compiled css)
   has 2 classes, which outranks the 1-class `.eyebrow + h1` selector (element
   count doesn't help there since class count is compared first). Add the
   extra class so this rule wins on its own terms (2 classes + 3 elements
   beats 2 classes + 0 elements) without touching the hero's page embeds. */
html body .eyebrow + h1.hero-title{margin-top:0}

/* Same collapse issue for the About Awards/Affiliations eyebrows: native
   `.award-rows` / `.affil-row` both carry margin-top:1.1rem (17.6px),
   which was already beating `.about-creds-h`'s margin-bottom before this
   pass. Half of the true 17.6px gap = 8.8px. `.about-creds-h` itself is a
   native Webflow class (edited directly via data_style_tool to .55rem,
   not here) — only the collapse-causing margin-top needs zeroing here. */
html body .about-creds-h + .award-rows,
html body .about-creds-h + .affil-row{margin-top:0}

/* Small uppercase labels / specs / captions.
   ⚠ Everything in this list must actually BE a small uppercase label — the
   rule sets one flat size and letter-spacing, so anything else gets crushed.
   Two were wrong and have been removed: `.swatch-label` (the hero gallery's
   "Interiors"/"Exteriors" — EB Garamond display type at 33.6px, shrunk to
   13.76px with 0.15em tracking bolted on) and `.ba-grip` (the before/after
   drag handle glyph, 17.6px). Both are back on the template's own sizes.
   Check the rendered size before adding a selector here. */
html body .about-col h4,html body .about-creds-h,html body .footer-inner h4,html body .proc-num,html body .project-card-loc,
html body .folio-meta,html body .folio-cat,html body .dd-gallery-eyebrow,html body .dd-gallery-count,
html body .hero-swatches-label,html body .duo-cue,html body .link-arrow,html body .ba-tag,
html body .project-spec dt,html body .field label,html body .about-cap span,
html body .about-cap-span,html body .pull-quote cite,html body .gallery-quote,html body .form-status,
html body .folio-panel .project-spec>div>div:first-child,
html body .project-card-body::after,html body .service-body::after{
  font-size:.86rem;letter-spacing:.15em
}

/* Buttons and navigation */
html body .btn{font-size:.95rem}
html body .nav-item>a,html body .nav-cta,html body .nav>a,html body .site-header .nav .nav-link,
html body #primaryNav .nav-item>a,html body #primaryNav .nav-cta{font-size:1.04rem}
html body .nav-sub a,html body .site-header .nav .nav-sub a{font-size:1rem}

/* Headings — up a step to keep the hierarchy after the body-copy lift */
html body .section-head h2,html body .services .section-head h2{font-size:clamp(2.3rem,4.4vw,3.6rem)}
html body .featured .section-head h2{font-size:clamp(1.2rem,2.6vw,1.85rem)}
html body .faq-q{font-size:clamp(1.28rem,2vw,1.62rem)}
html body .feature-list h3,html body .scope-card-title,html body .cert-title{font-size:clamp(1.28rem,1.9vw,1.6rem)}
html body .diff-head{font-size:clamp(1.34rem,1.9vw,1.72rem)}
html body .wwb-regions li{font-size:1.2rem}
html body .about-heading,html body .about-commit-title,html body .ct-faq-q{font-size:clamp(1.7rem,2.9vw,2.4rem)}

/* --------------------------------------------------------------------------
   2. TEXT WRAPPING — pretty for prose, balance for display type.
   -------------------------------------------------------------------------- */
html body p,html body li,html body dd,html body dt,html body figcaption,html body blockquote,html body address,html body .contact-intro,html body .modal-lead,html body .lead{
  text-wrap:pretty
}
html body h1,html body h2,html body h3,html body h4,html body .hero-title,html body .duo-title,html body .section-head h2,html body .about-phil-title,
html body .project-card-name,html body .folio-title,html body .contact-panel h2{
  text-wrap:balance
}

/* --------------------------------------------------------------------------
   3. CTA SECTION — heading was capped at 18ch and broke three lines early.
   -------------------------------------------------------------------------- */
html body .contact-panel h2{max-width:none;font-size:clamp(1.9rem,3vw,2.7rem);line-height:1.12}
html body .contact-intro{max-width:60ch}

/* --------------------------------------------------------------------------
   4. MODAL ALIGNMENT BUG
   `.container.modal-content` is a native Webflow class set to a 1fr 1fr grid,
   which pushed the whole feature list into the left column and stranded the
   short closing note top-right. Make it a single column; let the feature list
   itself do the two-column split, and only when there is room for it.
   Also: `.modal-lead` sits OUTSIDE the container, so it rendered flush to the
   viewport edge instead of on the gutter.
   -------------------------------------------------------------------------- */
html body .container.modal-content{display:block}
html body .modal-body .feature-list{
  grid-template-columns:repeat(auto-fit,minmax(min(100%,26rem),1fr));
  column-gap:clamp(28px,3.5vw,64px);
  max-width:none
}
/* The lead matches `.container` exactly — same width, same gutters — and spans
   the content width like the feature list beneath it.
   ⚠ It previously capped its measure with
   `padding-right:max(var(--gutter),calc(100% - 72ch))`. That percentage
   resolves against `.modal-body` (i.e. the viewport), NOT the paragraph, so
   once the viewport passed roughly 2300px the padding grew larger than the
   element's own max-width and crushed the text column to nothing — one word
   per line. Measured content width: 1053px at 1440, 512px at 1990, 0px at
   2560 and 3440. Never cap a measure with a percentage of an ancestor. */
html body .modal-body>.modal-lead{
  box-sizing:border-box;width:100%;max-width:var(--content);margin-inline:auto;
  padding-inline:var(--gutter)
}
html body .modal-foot{max-width:72ch;margin-top:clamp(36px,4vw,60px)}

/* --------------------------------------------------------------------------
   5. FEATURE LIST — white icons in navy discs, icon on the title's line,
   tighter text block.
   -------------------------------------------------------------------------- */
html body .feature-list li{padding:1rem 0;gap:0 1rem}

/* One source of truth for the title size, so the marker beside it can be
   centred on the title's own first line at every width instead of being
   nudged with a hardcoded margin. */
html body .feature-list{--fl-title:clamp(1.28rem,1.9vw,1.6rem);--fl-line:1.2}
html body .feature-list h3{
  font-size:var(--fl-title);line-height:var(--fl-line);
  margin-top:0;margin-bottom:.2rem
}
/* ⚠ margin-top:0 above is load-bearing. The <h3> was inheriting Webflow's
   default 20px heading margin, which pushed every title down while its bullet
   — positioned with a fixed margin-top — stayed put, so the marker sat about
   22px above the text it belonged to. Same root cause as §19. It was never a
   stray line break or a padding problem. */
html body .feature-list .feature-dot{
  margin-top:calc((var(--fl-title) * var(--fl-line) - .6rem) / 2)
}
html body .feature-list .feature-icon{
  width:2.75rem;height:2.75rem;padding:.45rem;box-sizing:border-box;
  background:#0f1a23;border-radius:50%;
  margin-top:calc((var(--fl-title) * var(--fl-line) - 2.75rem) / 2)
}
html body .feature-list p{margin:0;max-width:56ch;line-height:1.35}

/* --------------------------------------------------------------------------
   6. "WHERE WE BUILD" MAP — replace the flat white veil with a left-to-right
   off-white gradient so the copy is readable without the text-shadow hack,
   and give the band 20% more padding, matched top and bottom.
   -------------------------------------------------------------------------- */
html body .wwb::after{
  background:linear-gradient(90deg,
    rgba(238,242,246,.97) 0%,
    rgba(238,242,246,.95) 30%,
    rgba(238,242,246,.72) 48%,
    rgba(238,242,246,.28) 66%,
    rgba(238,242,246,0) 80%)
}
html body .wwb-content .section-head h2,html body .wwb-copy{text-shadow:none}
html body main>section.wwb{padding-block:clamp(38px,4.8vw,70px)}

/* --------------------------------------------------------------------------
   7. PROJECT CARDS — the dark plate behind the caption had a hard top edge.
   Fade it out above the text instead, and tighten/enlarge the caption.
   -------------------------------------------------------------------------- */
html body .project-card-body{
  background:linear-gradient(to top,
    rgba(9,16,22,.9) 0%,rgba(9,16,22,.82) 38%,
    rgba(9,16,22,.5) 68%,rgba(9,16,22,0) 100%);
  padding:clamp(56px,8vw,110px) clamp(20px,2.6vw,34px) clamp(18px,2.4vw,30px);
  gap:.2rem
}
html body .project-card:hover .project-card-body{
  background:linear-gradient(to top,
    rgba(9,16,22,.95) 0%,rgba(9,16,22,.88) 38%,
    rgba(9,16,22,.56) 68%,rgba(9,16,22,0) 100%)
}
html body .project-card-name{font-size:clamp(1.55rem,2.5vw,2.15rem);line-height:1.1}
html body .project-card-loc{margin-top:.1rem}
html body .project-card-body::after{margin-top:.6rem}

/* Same hard-edged plate on the homepage service cards and duo panels */
html body .service-body{
  background:linear-gradient(to top,
    rgba(9,16,22,.9) 0%,rgba(9,16,22,.8) 40%,
    rgba(9,16,22,.45) 72%,rgba(9,16,22,0) 100%);
  padding-top:clamp(48px,7vw,92px)
}
html body .service-card:hover .service-body{
  background:linear-gradient(to top,
    rgba(9,16,22,.95) 0%,rgba(9,16,22,.88) 40%,
    rgba(9,16,22,.52) 72%,rgba(9,16,22,0) 100%)
}
html body .duo-inner{
  background:linear-gradient(to top,
    rgba(9,16,22,.86) 0%,rgba(9,16,22,.76) 45%,
    rgba(9,16,22,.4) 75%,rgba(9,16,22,0) 100%);
  padding-top:clamp(56px,7vw,104px)
}
html body .duo-panel:hover .duo-inner{
  background:linear-gradient(to top,
    rgba(9,16,22,.92) 0%,rgba(9,16,22,.84) 45%,
    rgba(9,16,22,.48) 75%,rgba(9,16,22,0) 100%)
}

/* --------------------------------------------------------------------------
   8. ONE-LINE HEADLINE — "We build fewer homes, better." was capped at 16ch.
   -------------------------------------------------------------------------- */
html body .about-phil-title{max-width:none;white-space:nowrap}
@media (max-width:640px){html body .about-phil-title{white-space:normal}}

/* --------------------------------------------------------------------------
   9. AWARDS / AFFILIATIONS — bigger logos, awards laid out one per row with
   their citation beside them, affiliation logos on a shared centre line.
   -------------------------------------------------------------------------- */
html body .cred-logo-row{gap:1.6rem 2rem;align-items:center;margin-top:1rem}
html body .cred-logo-affil{height:52px;width:auto;object-fit:contain}
html body .cred-logo-award{height:78px;width:auto;object-fit:contain}

html body .award-rows{display:grid;gap:1.5rem;margin-top:1.1rem}
html body .award-row{
  display:grid;grid-template-columns:96px 1fr;gap:1.4rem;align-items:center
}
html body .award-row img{width:96px;height:78px;object-fit:contain;object-position:left center}
html body .award-row p{margin:0;color:var(--muted);font-size:1.12rem;line-height:1.35}
html body .award-row strong{display:block;color:var(--ink);font-family:var(--serif);
  font-weight:500;font-size:1.3rem;line-height:1.2;margin-bottom:.15rem}
html body .affil-row{display:flex;flex-wrap:wrap;align-items:center;gap:1.6rem 2.2rem;margin-top:1.1rem}
html body .affil-row img{height:52px;width:auto;object-fit:contain;display:block}
@media (max-width:560px){
  html body .award-row{grid-template-columns:72px 1fr;gap:1rem}
  html body .award-row img{width:72px;height:60px}
}


/* ==========================================================================
   PART 2 — per-page layout work from the same walkthrough.
   ========================================================================== */

/* 10. HOMEPAGE "DIFFERENCE" ACCORDION
   It used to start level with the eyebrow; it should start level with the
   title. The offset is the eyebrow's own line box plus the h2's collapsed
   20px top margin. Only applies while the section is two columns. */
html body .philosophy-grid > .diff-list{padding-top:calc(.88rem * 1.62 + 20px)}
@media (max-width:991px){html body .philosophy-grid > .diff-list{padding-top:0}}

/* 11. PLAN IDEAS CARDS — the square-footage line was wrapping "SQ / FT". */
html body .plan-size{white-space:nowrap;font-size:1.4rem}
html body .plan-size small{font-size:.74rem;letter-spacing:.1em;white-space:nowrap}
html body .plan-dl{font-size:.78rem;letter-spacing:.1em;white-space:nowrap}

/* 12. PROJECT GALLERY — REMOVED 2026-08-18 (v14). This !important block
   existed only to beat Projects Template's own page-level "Before </body>"
   custom code, which forced height:auto on .dd-gallery-feature-img (see the
   v13 comment this replaces). That page code was fixed at source the same
   day — it now sets its own fixed box size in JS and lets native
   .dd-gallery-feature-img (absolute/100%/100%/object-fit:cover) govern
   directly — so the counter-rule has nothing left to fight and is gone.
   The gallery is now 100% native, no !important anywhere. Verified live
   post-removal (feature photo still crops to fill its box on all
   breakpoints). */

html body .about-statement .about-cite{
  font-family:var(--sans);font-size:.95rem;letter-spacing:.16em;
  text-transform:uppercase;margin-top:1.6rem
}

/* 14. ABOUT US — story section now leads with Todd's portrait, and carries a
   swappable placeholder image (native Image element, class about-story-media)
   at the foot of the section. */
html body .container.about-story-grid{
  grid-template-columns:minmax(0,.8fr) minmax(0,1fr) minmax(0,1.4fr);
  align-items:start
}
html body .about-story-grid .about-owner-media{max-width:none}
@media (max-width:991px){
  html body .container.about-story-grid{grid-template-columns:1fr}
}

/* 15. ABOUT US — owner section.
   2026-08-18 (v24): REVERTED the single-column collapse below per Matt —
   the Designer's intended layout is two columns: portrait left (300px,
   matching `.about-owner-media`'s own max-width so the image isn't
   stretched into a wider track), eyebrow/heading/copy/timeline right in
   the remaining space. Single-column fallback kept for mobile only. The
   portrait is `position:relative` (not sticky), so there is nothing to
   reconsider there when it sits in its own column again. */
html body .container.about-owner-grid{grid-template-columns:300px minmax(0,1fr);justify-items:start}
html body .about-owner-copy{max-width:72ch}
@media (max-width:767px){
  html body .container.about-owner-grid{grid-template-columns:minmax(0,1fr)}
}
/* 2026-08-18 (v25) — the two-column layout above didn't actually render
   side-by-side: Webflow's own compiled CSS pins a per-instance grid-child
   placement via a generated #w-node-… ID selector (ID specificity always
   beats any class chain, so this can't be reached from `.about-owner-copy`
   itself) — `#w-node-…ae7-815ec4b1{grid-column:span 2/span 2}`, left over
   from when this container was 3 columns (media spans col 1, copy spanned
   cols 2-3). With only 2 columns now, copy demanding 2 tracks starting at
   col 1 collides with media (col 1), so the engine bumps copy to row 2 —
   the exact stacking bug this pass exists to fix. It also explains the
   mobile symptom: with `grid-auto-columns:1fr` inherited from the generic
   `.container` base rule, that span-2 demand was silently creating an
   IMPLICIT second column even under the single-column mobile override
   above, rendering as two equal auto-sized tracks instead of one.
   Fixed by re-targeting the SAME generated ID from this later-loading
   stylesheet: equal specificity (both are single ID selectors), later
   source order wins — no !important needed. Matches the media node's own
   span (already `span 1/span 1`, untouched). */
#w-node-_7651298a-cb01-c565-5bef-182d45768ae7-815ec4b1{grid-column:span 1 / span 1}

/* 16. Two labels the template pins with !important, both too small for this
   audience: the header's "Get a Quote" button (11.8px) and the hero gallery
   eyebrow, "View our Gallery" (12.2px). Matching !important is the only way
   past them.
   ⚠ `.swatch-label` was in the second selector below and must not be — that is
   the big EB Garamond "Interiors"/"Exteriors" display type beside the eyebrow,
   not a small label. It was pinned to .86rem, taking it from 33.6px to 13.76px
   and collapsing the swatch bar from 60.8px tall to 41px. The eyebrow beside it
   still gets the intended lift. */
html body .nav-cta,html body .nav-cta-1,html body .nav-cta-1-2{font-size:.95rem !important}
html body .hero-swatches>span,html body .hero-swatches-label{font-size:.86rem !important}

/* 17. Award citations sit alongside body copy, so hold the same floor. */
html body .award-text{font-size:1.19rem}

/* 18. CTA CONTACT FORM (#contactForm — the band that closes nine pages).
   The markup is identical everywhere, but only Home and Projects Template
   carry the .contact-form class on the <form> itself, so on the other seven
   pages the form was a plain block: no spacing between rows at all, and the
   Submit button sat flush against the message box.
   Row spacing is set on the rows here rather than as a container gap, so the
   empty Turnstile slot that sits between the message field and the button
   contributes nothing while it renders at zero height — and still spaces
   correctly if it ever draws a real widget. */
html body #contactForm{display:grid;row-gap:0}
html body #contactForm .w-input{margin-bottom:0}
html body #contactForm>.field-row+.field-row,
html body #contactForm>.field-row+.field,
html body #contactForm>.form-status{margin-top:.85rem}
html body #contactForm>input[type="submit"]{margin-top:calc(.85rem + 5px)}

/* Each label carried its whole 5px of spacing on the bottom, which read as
   the label belonging to the field above it rather than below. Swapped, so
   the gap sits above the label and each one sits tight to its own input. */
html body #contactForm label{margin-top:5px;margin-bottom:0}

/* 19. WHERE WE BUILD / REMODEL map section — the section's padding-block is a
   single symmetric clamp, but the block still rendered top-heavy: the <h2> is
   the first thing in it and carries Webflow's base 20px heading margin-top,
   which stacks on the padding with nothing equivalent below the region list.
   Measured 89.1px above the heading vs 69.1px below the list at 1440px, on all
   four pages that use this section. Zeroed so the padding is what decides. */
html body .wwb .section-head h2{margin-top:0}

/* 20. AFFILIATIONS — the five logos wrap onto two lines (3 + 2, or 4 + 1 at
   some widths) inside a flex row that was left-aligned, so the two lines sat
   on different axes: measured centres 1065px and 818px at 1440. Centred, so
   both lines share one centre line under the heading. */
html body .affil-row{justify-content:center}


/* ==========================================================================
   Double Diamond — cursor-follower rollout, 2026-08-18 (v14)

   v13 gave four new interaction groups (nav/footer links, gallery thumbs +
   swatches, FAQ accordion rows, form fields) their own STATIC OS cursor
   images (cursor:url() PNGs) that mimicked the site's real animated
   follower (a `#cursor` div that grows to a 104px navy circle with a
   centered white uppercase label — see .folio-bar's data-cursor="View").
   That was a deliberate workaround at the time: this stylesheet's own
   authorization didn't cover per-page elements/scripts, so it couldn't add
   real data-cursor attributes or touch the FAQ toggle script.

   This pass has that authorization (site-level custom code), so the four
   static cursor:url() sections (old §21–23: Open/Close, View, Go) are
   REMOVED here. The real behavior now lives in the site-level footer custom
   code: it tags the same elements with real data-cursor attributes AND
   drives the #cursor follower directly for them (delegated hover listener —
   necessary because each page's own follower script binds its
   mouseenter/mouseleave listeners to a one-time querySelectorAll snapshot
   taken before the site-level code runs, confirmed live via Playwright).
   See that footer script's own header comment for the full explanation.

   What's left below (old §24, renumbered) is the one static rule that was
   never part of the cursor-mimicry work — a defensive text-cursor pin for
   form fields — plus a new corrective rule for submit/button fields, which
   inherited an I-beam from the template's own bare
   `body.has-cursor input,textarea{cursor:text}` rule.
   ========================================================================== */

@media (pointer:fine){

/* 24. FORM TEXT ENTRY — confirm the I-beam wins over any inherited/forced
   pointer. body.has-cursor already sets a bare input/textarea rule to
   cursor:text (confirmed live: an email field already computes cursor:text
   with no override needed), so nothing here was actually forcing pointer.
   Kept anyway, scoped to the specific field classes, as a defensive pin so a
   more specific template rule can never reassert pointer on a text field. */
html body.has-cursor .field input,
html body.has-cursor .field textarea,
html body.has-cursor .contact-form .w-input,
html body.has-cursor .contact-form .w-select,
html body.has-cursor .cta-field-text,
html body.has-cursor input[type="text"],
html body.has-cursor input[type="email"],
html body.has-cursor input[type="tel"],
html body.has-cursor textarea{
  cursor:text
}

/* 25. SUBMIT / BUTTON FIELDS — 2026-08-18 (v14). The template's bare
   `body.has-cursor input,textarea{cursor:text}` rule (site-level footer
   custom code) also matches `<input type="submit">`, so every CTA/contact
   form's Send button computed an I-beam instead of behaving like the rest
   of the follower system (which hides the native cursor on links/buttons
   entirely). This selector is more specific than the bare `input` rule it
   corrects (a type attribute + a class beats a bare tag), so it wins on
   specificity alone — no !important needed regardless of load order. */
html body.has-cursor input[type="submit"],
html body.has-cursor input[type="button"],
html body.has-cursor .btn[type="submit"]{
  cursor:none
}

}


/* --------------------------------------------------------------------------
   HERO PHOTO FALLBACK — 2026-08-18 (ghost-text fix)
   The hero headline / lede / buttons are white and reveal-animate in right
   away, but `.hero-media` had no background of its own, so until the hero
   photo decoded that white text sat on the page's light `--bone` ground and
   was effectively invisible on cold or throttled loads. Give the photo's own
   container the site ink so the text is legible from first paint. The <img>
   is a child of .hero-media and paints on top of this, and the .hero-scrim
   gradient is untouched. Applied here rather than on `.hero` itself because
   `.hero-media` is `z-index:-1` — a background on the section would paint
   OVER the photo and hide it.
   -------------------------------------------------------------------------- */
html body .hero-media{background-color:var(--ink,#0f1a23)}

/* --------------------------------------------------------------------------
   NEWSREADER SELF-HOSTED @FONT-FACE — added 2026-08-18
   Restores the hero-title font. .hero-title.reveal (compiled stylesheet)
   sets font-family: Newsreader with no matching @font-face, which was
   silently falling back to a generic serif after the Google Fonts
   webfont.js loader (site-level head) was removed. Self-hosted here as
   latin-subset woff2, font-display:block per no-FOUC policy, uploaded as
   Webflow assets (CDN serves Access-Control-Allow-Origin: * — verified,
   safe for cross-origin @font-face). Weight 500 is confirmed used by
   .hero-title.reveal on all three hero pages (home, custom-home-building,
   green-building-practices); weight 400 included as a safety-net normal
   weight, currently unused but cheap to keep available. No italic used
   anywhere for Newsreader on this site.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Newsreader';
  src: url('https://cdn.prod.website-files.com/6a21a975b966dcfe00ef004e/6a84ae45bda5772db1487538_newsreader-500-normal-latin.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: 'Newsreader';
  src: url('https://cdn.prod.website-files.com/6a21a975b966dcfe00ef004e/6a84ae45bda5772db1487522_newsreader-400-normal-latin.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

/* ==========================================================================
   CLS FIX — pinned-scroll hero track height, added 2026-08-18 (v18)

   Measured via Playwright PerformanceObserver('layout-shift') against the
   live site: Custom Home Building, Renovations & Additions and Green
   Building Practices each showed a single dominant layout-shift entry of
   ~0.09-0.13 (desktop, both throttled and unthrottled — i.e. NOT a
   network-timing artifact) whose source was the `::before` pseudo-element of
   `.hero-inner` (and, by the same mechanism, `.hero-media` on Home).

   ROOT CAUSE: each of those three pages carries its own page-level custom
   code (invisible to this connector — not a Designer-canvas HtmlEmbed and
   not present in either page's freeform head/footer code, confirmed via
   data_element_tool query_elements, get_all_elements, and
   data_scripts_tool get_page_freeform_code) implementing a pinned "foggy
   glass" scroll effect: `.hero-pin{position:relative}` starts at its
   natural (~1 viewport) content height, and a small inline script adds
   `.hero-pin-on` — which sets `height:175svh` — the moment the page loads
   (gated only by `prefers-reduced-motion`, not by any user interaction or
   scroll). That JS class-add happens shortly AFTER first paint, so every
   page using this pattern paints once at the natural height, then
   immediately grows by ~75svh — a real, measured layout shift, not merely a
   visual one.

   FIX: reserve the SAME final height from the very first (render-blocking)
   paint by targeting the base `.hero-pin` class — already present in the
   static HTML before any script runs — under the identical
   `prefers-reduced-motion` gate the script itself checks
   (`matchMedia('(prefers-reduced-motion:reduce)')`). This does not change
   behavior for either motion preference; it only removes the JS-timing gap
   between "painted small" and "grown tall". The page's own `.hero-pin-on`
   rule (which this connector cannot reach to edit or remove) still applies
   once the script adds that class — same value, so it is now a harmless
   no-op, not a fix in itself. `.hero-pin` was NOT reachable as a native
   Webflow style, a page-embed, or page/site freeform code (see above), so
   per the fix hierarchy this shared-stylesheet rule is the layer of last
   resort, used here because the source is genuinely unreachable, not as a
   substitute for a reachable fix. No `!important`: these are new selectors,
   not overrides of an existing rule, so ordinary specificity is enough.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference){
  html body .hero-pin{height:175svh}
  html body .hero-pin > .hero--center{position:sticky;top:0;height:100svh;min-height:0}
}

/* ==========================================================================
   CLS FIX FOLLOW-UP — hero content alignment jump, added 2026-08-18 (v19)

   Even with the v18 height fix (.hero-pin reserves 175svh / 100svh from
   first paint, verified with a frame-by-frame getBoundingClientRect trace —
   .hero--center's own box is 900px tall and stable from frame 1), a second,
   independent single-frame shift of the SAME order of magnitude (~0.10-0.11
   CLS) remained on Custom Home Building, Renovations & Additions and Green
   Building Practices. Traced it frame-by-frame: `.hero-inner` (height
   constant throughout, ~412px) sits at top:244px on the very first rendered
   frame — vertically CENTERED in the 900px `.hero--center` box, i.e.
   `justify-content:center`, `.hero--center`'s base style before any script
   runs (confirmed via getComputedStyle on the first frame the element
   exists: justifyContent "center", classList "hero hero--center", no
   "hero-reveal" yet) — then one frame later jumps to top:440px once the
   same inline script adds the `hero-reveal` class, which is what actually
   carries `justify-content:flex-end` + `padding-bottom:var(--band-pad)`
   (both confirmed live in that page's own invisible custom code, same
   unreachable source as the height rule above). 900-412-48(padding) = 440,
   matching exactly.

   Same fix shape as v18: reserve the POST-script alignment from first paint
   under the identical `prefers-reduced-motion` gate the script itself uses,
   so there is no frame where the content sits centered before jumping to
   the bottom-aligned "banner on the hero's bottom edge" position. band-pad
   is the same `clamp(24px,4vw,48px)` value the page's own hero-reveal rule
   uses (confirmed: computed padding-bottom was 48px at 1440 width both
   before and after this fix). Still last-resort (source unreachable via
   this connector — see v18 comment above for the full search), still no
   `!important` (new selectors, not overriding an existing one).
   ========================================================================== */
@media (prefers-reduced-motion: no-preference){
  html body .hero-pin > .hero--center{
    justify-content:flex-end;
    padding-bottom:clamp(24px,4vw,48px)
  }
}

/* ==========================================================================
   CLS FIX — Home hero Interiors/Exteriors swatch bar, added 2026-08-18 (v20)

   Measured via Playwright PerformanceObserver('layout-shift') + a
   frame-by-frame getBoundingClientRect trace against the live Home page:
   `.hero-swatch-bar` rendered at 149.39px tall on its first painted frame,
   then at 100.16px one animation frame later (~20-40ms) — no DOM mutation,
   no class change, only a computed-style change: `.hero-swatches`'s own
   padding-block went from 19.8px (the base rule's
   `clamp(0.9rem,2.2vh,1.6rem)`, i.e. 2.2vh resolving against a 900px
   viewport) to 8.8px, which is not a value that clamp expression can
   produce at all — it can only come from a DIFFERENT, later rule. Traced to
   a `!important` override living in a later page-level custom-code block
   (`.hero-swatches{padding-block:.55rem!important}` plus tightened
   `.swatch`/`.w-button` padding) — the intended final design, but it lands
   after the hero has already painted with the base clamp() value, so the
   page visibly (and measurably) shrinks the swatch bar a moment after
   first paint. Same class of bug as the CTA mosaic (v17) and hero-pin
   (v18/v19) fixes above: a correct value that arrives one document-order
   step too late for CLS purposes.

   Fix: apply the SAME final values from first paint via this
   render-blocking, head-loaded stylesheet, so there is no frame where the
   swatch bar is taller than its intended size. Not gated by
   prefers-reduced-motion (unlike the hero-pin fixes) — this isn't a motion
   effect, just a static sizing value the page settles on regardless of
   motion preference. `!important` is deliberately mirrored here: the later
   page-embed rule also uses it, so unlike the hero-pin case (new
   selectors, no existing rule to out-rank) this one straight-up needs to
   win the SAME cascade fight from an earlier position in the document.
   Per the fix hierarchy this is a last resort: `.hero-swatches` is a native
   Webflow style (verified via data_style_tool query_styles) whose base
   value is the correct-shaped clamp() this page wants everywhere BUT here,
   so fixing the shared native style would regress every other page that
   uses default padding — the override has to stay page-scoped, and since
   editing the page's own late-loading embed is outside this connector's
   reach for the reasons documented in the v18 comment above, matching it
   here is the only way to make it win from frame 1.
   ========================================================================== */
html body .hero-swatches{padding-block:.55rem !important}
html body .hero-swatches .swatch,
html body .hero-swatches .w-button{
  padding:.3rem .3rem !important;
  min-height:0 !important
}
