/* ============================================================
   Phillip Smith General Contractor — shared stylesheet
   Used by: index, process, portfolio, about, contact, careers, project
   (thank-you.html stays self-contained — its nav/footer diverge)
   Page-specific styles live in each page's inline <style> block,
   which loads AFTER this file and wins ties.
   ============================================================ */

:root {
  --canvas: #F8F8F8;
  --ink: #1A1A1A;
  --ink-60: rgba(26,26,26,.62);
  --ink-30: rgba(26,26,26,.28);
  --accent: #4682B4;
  --accent-deep: #2E5A80;
  --nautilus: #57A0D3;
  --serif: 'Lora', Georgia, serif;
  --sans: 'DM Sans', -apple-system, sans-serif;
  --gutter: clamp(20px, 5vw, 72px);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html.no-lenis { scroll-behavior: smooth; }
body { background: var(--canvas); color: var(--ink); font-family: var(--sans); font-size: 16px; line-height: 1.65; -webkit-font-smoothing: antialiased; overflow-x: hidden; }
img { display: block; width: 100%; height: 100%; object-fit: cover; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--accent); color: #fff; }
/* keyboard focus ring — box-shadow respects radius, never clips (WCAG 2.4.7; base.css pattern) */
:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--canvas), 0 0 0 4px var(--accent); }

/* ---------- type ---------- */
h1, h2, h3, .serif { font-family: var(--serif); font-weight: 500; letter-spacing: .01em; }
.eyebrow { font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase; color: var(--accent); margin-bottom: 22px; }
.eyebrow.on-dark { color: rgba(255,255,255,.85); }
.section-head { font-size: clamp(30px, 4.4vw, 54px); line-height: 1.12; letter-spacing: .015em; max-width: 18em; }
.section-head em { font-style: italic; letter-spacing: 0; }
.section-sub { font-size: 17px; color: var(--ink-60); max-width: 34em; margin-top: 18px; }

/* ---------------------------------------------------------------------------
   S-03 / H-16 / H-18 — even copy distribution.
   Headings balance their lines instead of dumping a short orphan on the last
   row; body copy avoids leaving a single word stranded. Purely a line-breaking
   change: no font sizes move, which their feedback explicitly required
   ("don't solve by increasing text size"). Degrades to today's behaviour on
   engines without text-wrap support.
--------------------------------------------------------------------------- */
h1, h2, h3, h4,
.section-head, .banner h1, .final-cta h2, .hero-sub, .banner-sub,
.section-sub, .why-close, .close-line, .text-line {
  text-wrap: balance;
}
p, li, blockquote, figcaption, cite, dd { text-wrap: pretty; }

/* Centered narrative copy on the interior pages had no measure at all, so it
   ran the full container width — the "avoid long single-line strings of copy"
   half of S-03. Cap the measure, keep it centred, balance the breaks. */
.bridge .copy p, .bridge .sub,
.sb-head .intro p,
.cr .inner p,
.text-line {
  max-width: 34em;
  margin-left: auto;
  margin-right: auto;
  text-wrap: balance;
}

/* ---------- buttons ---------- */
.btn { display: inline-block; font-family: var(--sans); font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; padding: 17px 34px; border: 1px solid currentColor; transition: background .35s cubic-bezier(.22,1,.36,1), color .35s cubic-bezier(.22,1,.36,1), border-color .35s; cursor: pointer; }
.btn-solid { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-solid:hover { background: var(--accent-deep); border-color: var(--accent-deep); }
.btn-ghost-light { color: #fff; border-color: rgba(255,255,255,.6); }
.btn-ghost-light:hover { background: #fff; color: var(--ink); border-color: #fff; }
.btn-ghost-dark, .btn-ghost { color: var(--ink); border-color: var(--ink-30); }
.btn-ghost-dark:hover, .btn-ghost:hover { border-color: var(--ink); background: var(--ink); color: #fff; }
.text-link { font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; border-bottom: 1px solid var(--ink-30); padding-bottom: 6px; transition: border-color .3s, color .3s; }
.text-link:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- nav (transparent over hero/banner, solid on scroll) ---------- */
nav#nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 0 var(--gutter); height: 84px; transition: background .4s, box-shadow .4s, height .4s; }
nav.scrolled { background: rgba(248,248,248,.92); backdrop-filter: blur(14px); height: 66px; box-shadow: 0 1px 0 rgba(26,26,26,.08); }
nav.scrolled .nav-logo, nav.scrolled .nav-links a, nav.scrolled .nav-meta { color: var(--ink); }
nav.scrolled .nav-cta { border-color: var(--ink); color: var(--ink); }
nav.scrolled .nav-cta:hover { background: var(--ink); color: #fff; }
.nav-logo { color: #fff; line-height: 1.15; transition: color .4s; display: flex; align-items: center; gap: 12px; }
.nav-logo .mark { width: 42px; height: 42px; object-fit: contain; flex: 0 0 auto; transition: width .4s, height .4s; }
/* Nov 11 (client): single-file lockup (psgcweblogo.svg) replaces the icon + typed text.
   The supplied artwork is dark ink only, so it is whitened while the nav sits over the hero
   and restored to full colour once the nav goes solid. Same trick the footer affiliation
   logos already use. If a white master is supplied later, drop the filters. */
/* Two states because the supplied lockup is dark-ink only and the nav sits over the hero
   photograph before it goes solid. psgcweblogo-white.svg is DERIVED from the supplied file,
   not drawn: the wordmark paths (x > 112 in the viewBox, i.e. everything right of the mark)
   are set to #fff, and the mark drops its two blue fills so the white spiral strokes already
   in the artwork read as line art — which is what the previous white lockup did. Replace both
   files if an official reversed master arrives. A CSS filter was tried first and rejected:
   brightness(0) invert(1) flattens the mark into a solid white disc. */
.nav-logo .brandlogo { width: auto; height: 46px; display: block; flex: 0 0 auto;
  transition: height .4s, opacity .4s; }
.nav-logo .brandlogo-dark { position: absolute; opacity: 0; pointer-events: none; }
nav.scrolled .nav-logo .brandlogo-light { opacity: 0; }
nav.scrolled .nav-logo .brandlogo-dark { position: static; opacity: 1; }
nav.scrolled .nav-logo .brandlogo { height: 38px; }
.nav-logo { position: relative; }
.foot-logo .foot-brandlogo { width: auto; height: 56px; margin-bottom: 20px; }
@media (max-width: 760px) {
  .nav-logo .brandlogo { height: 38px; }
  nav.scrolled .nav-logo .brandlogo { height: 32px; }
}
nav.scrolled .nav-logo .mark { width: 34px; height: 34px; }
.nav-logo .name { font-family: var(--serif); font-size: 19px; font-weight: 600; letter-spacing: .06em; }
.nav-logo .sub { font-size: 8.5px; font-weight: 700; letter-spacing: .34em; text-transform: uppercase; opacity: .75; }
.nav-links { display: flex; gap: clamp(16px, 2.2vw, 34px); align-items: center; }
.nav-links a { color: #fff; font-size: 12px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; transition: color .4s, opacity .3s; white-space: nowrap; }
.nav-links a:hover { opacity: .6; }
/* N-02 — REVERTED Aug 30 (Jack). The lowercase tab read as a typo beside the
   other capitalised tabs. Their instruction contradicts itself — the item says
   'nav tab', the note says 'site-wide' — and it came from meeting notes rather
   than the written feedback doc, so it goes back to Abby before we re-apply.
   To restore: text-transform: lowercase; letter-spacing: .14em; on that link. */

/* A-03 — Our Team now lives under About Us. Hover or keyboard-focus opens the
   panel; no JS, so it survives the mobile overlay build (which clones the
   anchors flat and indents the sub-item). */
.nav-group { position: relative; display: inline-flex; align-items: center; }
.nav-sub { position: absolute; top: 100%; left: 50%; transform: translate(-50%, 6px);
  background: #fff; box-shadow: 0 16px 40px rgba(15,25,35,.16); border: 1px solid rgba(26,26,26,.06);
  padding: 8px 4px; min-width: 150px; opacity: 0; visibility: hidden;
  transition: opacity .22s, transform .22s, visibility .22s; z-index: 60; }
.nav-group:hover .nav-sub, .nav-group:focus-within .nav-sub {
  opacity: 1; visibility: visible; transform: translate(-50%, 0); }
/* parent must not read as dimmed while its own panel is open */
.nav-group:hover > a, .nav-group:focus-within > a { opacity: 1; }
.nav-sub a, nav.scrolled .nav-sub a { display: block; padding: 9px 16px; color: var(--ink); white-space: nowrap; }
.nav-sub a:hover { opacity: 1; background: rgba(26,26,26,.05); }
.nav-sub a[aria-current="page"] { font-weight: 700; }
@media (max-width: 900px) { .nav-group { display: none; } }
@media (prefers-reduced-motion: reduce) { .nav-sub { transition: none; } }
/* the mobile overlay gets the same two items, the second indented */
.mnav a.nav-sub-item { padding-left: 26px; opacity: .82; }

/* H-10 — the filled Portfolio button read as an active state rather than a
   link. Hovering Start Your Build now moves the fill across, so both hero
   CTAs read as choices rather than one looking pre-selected (Lori's note). */
/* white fill for buttons sitting on a photo — hero and the closing CTA */
.btn-portfolio { background: #fff; color: var(--ink); border-color: #fff;
  transition: background .3s, color .3s, border-color .3s; }
.btn-portfolio:hover { background: #fff; color: var(--ink); border-color: #fff; }
/* Oct 7 feedback: the closing CTA row had the same "both buttons highlighted at once"
   problem the hero already solved — hovering Portfolio left Start the Conversation
   still filled white. Same de-emphasis now applies to the bottom row. */
.hero-ctas:has(.btn-ghost-light:hover) .btn-portfolio,
.final-cta .row:has(.btn-ghost-light:hover) .btn-portfolio {
  background: transparent; color: #fff; border-color: rgba(255,255,255,.6); }
.hero-ctas .btn-portfolio:hover,
.final-cta .row .btn-portfolio:hover { background: #fff; color: var(--ink); border-color: #fff; }

/* P-10 — homepage bottom now carries the same two-button row as Our Process */
.final-cta .row { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; margin-top: 34px; }

/* ---------------------------------------------------------------------------
   X-08 — mobile pass.
--------------------------------------------------------------------------- */

/* 1. Header. Logo + full-text CTA + burger do not fit across a 360-390px bar:
   the logo wrapped onto four lines and the burger was pushed past the right
   edge. Below 560px the CTA lives in the menu instead (the overlay builder
   already clones it as .mnav-cta), leaving a clean logo-left / burger-right
   bar — the "logo behavior" half of this item. */
@media (max-width: 560px) {
  .nav-links .nav-cta { display: none; }
  .nav-logo .name { white-space: nowrap; }
  .nav-logo .sub { white-space: nowrap; }
  .nav-burger { margin-left: 0; }
}

/* 2. Tap targets. Footer links, bio toggles and the lightbox close button were
   14-22px tall — under the 44px minimum on touch. Padding only; no type
   scaling, per the S-03 constraint. */
@media (max-width: 760px) {
  .foot-grid ul li a, .foot-naut {
    display: inline-flex; align-items: center; min-height: 44px;
    /* short labels like "Blog" were only 26px wide — widen the HIT box
       without moving anything visually */
    padding-inline-end: 14px; margin-inline-end: -14px;
  }
  a[href^="mailto:"], a[href^="tel:"], .crumb a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .foot-social { gap: 22px; }
  .foot-social .soc { padding: 11px; margin: -11px; }
  .bio-more { min-height: 44px; display: inline-flex; align-items: center; }
  a.mail { display: inline-flex; align-items: center; min-height: 44px; }
}
.lb-close { min-width: 44px; min-height: 44px; }

/* shared scroll cue — used by any hero that fills the fold */
/* Jack, Aug 30 — the hero now fills the whole fold, so a visitor needs
   something telling them there is more below. Centred down arrow, gentle
   bob, doubles as a link to the first step. */
.cue { position: absolute; left: 50%; transform: translateX(-50%); bottom: clamp(22px, 4vh, 44px);
  z-index: 3; display: flex; flex-direction: column; align-items: center; gap: 9px;
  color: rgba(255,255,255,.82); text-decoration: none; padding: 10px 16px;
  transition: color .3s, transform .3s; }
.cue:hover { color: #fff; }
.cue .cue-label { font-size: 9.5px; font-weight: 700; letter-spacing: .28em; text-transform: uppercase; }
.cue svg { display: block; animation: cueBob 2.1s cubic-bezier(.45,0,.55,1) infinite; }
@keyframes cueBob { 0%,100% { transform: translateY(0); opacity: .8 } 50% { transform: translateY(7px); opacity: 1 } }
.cue:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; border-radius: 4px; }
/* on a paper opener the cue sits on canvas, not on a photo */
body.light-top .cue { color: var(--ink-60); }
body.light-top .cue:hover { color: var(--ink); }
body.flat .cue svg { animation: none; }
@media (prefers-reduced-motion: reduce) { .cue svg { animation: none; } }
@media (max-height: 620px) { .cue { display: none; } }

/* ---------------------------------------------------------------------------
   H-19 / N-01 — INTERIOR PAGE OPENER (Option A, Jack's pick Aug 26).
   Replaces the repeating photo band. Type-led on paper with the photograph
   held to one side. What makes each page read as COMPOSED rather than as a
   template with new words dropped in: its own index, its own deck sentence,
   and its own section links, all on the fold.
   Currently applied to about.html only — pending Jack's look.
--------------------------------------------------------------------------- */
body.light-top nav { background: rgba(248,248,248,.92); box-shadow: 0 1px 0 rgba(26,26,26,.08); }
body.light-top .nav-logo, body.light-top .nav-links a, body.light-top .nav-meta { color: var(--ink); }
body.light-top .nav-cta { border-color: var(--ink); color: var(--ink); }
body.light-top .nav-cta:hover { background: var(--ink); color: #fff; }
body.light-top .nav-burger span { background: var(--ink); }
body.light-top.mnav-open .nav-burger span { background: #fff; }

/* OPTION A — the editorial opener (Jack's pick, kept Aug 30).
   Type-led on paper with the photograph held to one side. Sized to own the
   WHOLE fold: nothing else on the page sits above it. What stops each page
   reading as the shared band is its own index, deck sentence and section
   links — those change per page, the layout does not. */
.opener { position: relative; height: 100svh; min-height: 560px; display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr); }
.op-txt { padding: clamp(104px, 13vh, 152px) clamp(28px, 3.4vw, 56px) clamp(78px, 11vh, 118px) var(--gutter);
  display: flex; flex-direction: column; justify-content: center; }
.op-eyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .26em; text-transform: uppercase;
  color: var(--accent); margin: 0 0 13px; }
.opener h1 { font-family: var(--serif); font-size: clamp(38px, 5.2vw, 72px); line-height: 1.07;
  font-weight: 400; letter-spacing: -.005em; text-wrap: balance; }
.opener h1 em { font-style: italic; font-weight: 400; }
.op-deck { font-family: var(--serif); font-size: clamp(17px, 1.5vw, 20px); line-height: 1.55;
  font-weight: 400; color: var(--ink-60); max-width: 31ch; margin-top: 20px; text-wrap: pretty; }
.op-rule { width: 68px; height: 1px; background: var(--ink-30); margin-top: 28px; }
.op-jump { display: flex; flex-wrap: wrap; gap: 12px 26px; margin-top: 24px; }
.op-jump a { font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-60); padding-bottom: 3px; border-bottom: 1px solid transparent;
  transition: color .3s, border-color .3s; }
.op-jump a:hover { color: var(--ink); border-bottom-color: var(--accent); }
.op-pic { position: relative; overflow: hidden; background: #E9E7E2; }
.op-pic img { width: 100%; height: 100%; object-fit: cover; }
/* the cue belongs under the text column, not centred across the split */
.opener .cue { left: var(--gutter); transform: none; align-items: flex-start; padding-left: 0; }

.op-eyebrow, .opener h1, .op-deck, .op-rule, .op-jump {
  opacity: 0; animation: fadeUp .95s cubic-bezier(.22,1,.36,1) forwards; }
.op-eyebrow { animation-delay: .06s; } .opener h1 { animation-delay: .12s; }
.op-deck { animation-delay: .22s; } .op-rule { animation-delay: .3s; } .op-jump { animation-delay: .36s; }
body.flat .op-eyebrow, body.flat .opener h1,
body.flat .op-deck, body.flat .op-rule, body.flat .op-jump { animation: none; opacity: 1; }

@media (max-width: 860px) {
  /* photo on top, copy below — still exactly one viewport, photo takes the slack */
  .opener { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(160px, 1fr) auto; }
  .op-pic { order: -1; }
  .op-txt { padding: clamp(26px, 5vw, 40px) var(--gutter) clamp(122px, 21vw, 146px); justify-content: flex-start; }
  .op-jump { gap: 0 24px; }
  .op-jump a { display: inline-flex; align-items: center; min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .op-eyebrow, .opener h1, .op-deck, .op-rule, .op-jump { animation: none; opacity: 1; }
}
.nav-links a.active { border-bottom: 1px solid currentColor; padding-bottom: 4px; }
.nav-cta { font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; padding: 11px 22px; border: 1px solid rgba(255,255,255,.7); color: #fff; transition: all .35s; }
.nav-cta:hover { background: #fff; color: var(--ink); }
.nav-meta { display: none; color: #fff; font-size: 10px; letter-spacing: .18em; text-transform: uppercase; opacity: .75; transition: color .4s; }
@media (min-width: 1200px) { .nav-meta { display: block; } }
@media (max-width: 900px) { .nav-links a:not(.nav-cta) { display: none; } }

/* ---------- mobile menu (≤900px only — button + overlay injected by site.js;
     desktop nav rules above are untouched, burger is display:none by default) ---------- */
.nav-burger { display: none; background: none; border: 0; padding: 10px; margin-left: 14px; cursor: pointer; z-index: 130; }
.nav-burger span { display: block; width: 24px; height: 2px; background: #fff; transition: transform .35s cubic-bezier(.22,1,.36,1), opacity .25s, background .4s; }
.nav-burger span + span { margin-top: 6px; }
nav.scrolled .nav-burger span { background: var(--ink); }
body.mnav-open .nav-burger span { background: #fff; }
body.mnav-open .nav-burger span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
body.mnav-open .nav-burger span:nth-child(2) { opacity: 0; }
body.mnav-open .nav-burger span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }
.mnav { position: fixed; inset: 0; z-index: 120; background: #0D161F; display: flex; flex-direction: column; justify-content: center; padding: 0 var(--gutter); visibility: hidden; opacity: 0; transition: opacity .4s, visibility 0s .4s; }
body.mnav-open .mnav { visibility: visible; opacity: 1; transition: opacity .4s; }
.mnav a { color: #fff; font-family: var(--serif); font-size: clamp(28px, 7vw, 40px); line-height: 1.3; padding: 10px 0; opacity: 0; transform: translateY(14px); transition: opacity .5s, transform .5s cubic-bezier(.22,1,.36,1); }
body.mnav-open .mnav a { opacity: 1; transform: none; }
.mnav a:nth-child(2) { transition-delay: .05s; } .mnav a:nth-child(3) { transition-delay: .1s; }
.mnav a:nth-child(4) { transition-delay: .15s; } .mnav a:nth-child(5) { transition-delay: .2s; }
.mnav a:nth-child(6) { transition-delay: .25s; } .mnav a:nth-child(7) { transition-delay: .3s; }
.mnav a:nth-child(8) { transition-delay: .35s; }
.mnav a.active { color: var(--nautilus); }
.mnav .mnav-cta { font-family: var(--sans); font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; border: 1px solid rgba(255,255,255,.7); padding: 15px 28px; margin-top: 28px; align-self: flex-start; }
body.mnav-open { overflow: hidden; }
/* while open: lift nav above the overlay so logo + X stay visible, in white */
body.mnav-open nav { z-index: 130; background: transparent; box-shadow: none; backdrop-filter: none; }
body.mnav-open .nav-logo, body.mnav-open nav.scrolled .nav-logo { color: #fff; }
body.mnav-open .nav-links { visibility: hidden; }
@media (max-width: 900px) { .nav-burger { display: block; } }
@media (prefers-reduced-motion: reduce) { .nav-burger span, .mnav, .mnav a { transition: none; } }

/* ---------- page banner (interior pages; index hero is page-local)
     height/min-height set per page in its inline block ---------- */
.banner { position: relative; height: 62svh; min-height: 440px; display: flex; align-items: flex-end; overflow: hidden; }
.banner-media { position: absolute; inset: -8% 0; z-index: 0; will-change: transform; }
.banner-media::after { content: ''; position: absolute; inset: 0; background: linear-gradient(97deg, rgba(13,22,31,.82) 0%, rgba(13,22,31,.55) 40%, rgba(13,22,31,.2) 70%), linear-gradient(to bottom, rgba(13,22,31,.3) 0%, rgba(13,22,31,.1) 45%, rgba(13,22,31,.72) 100%); }
.banner-inner { position: relative; z-index: 1; width: 100%; padding: 0 var(--gutter) clamp(48px, 8vh, 90px); color: #fff; }
.banner-eyebrow { font-size: 11px; font-weight: 700; letter-spacing: .3em; text-transform: uppercase; color: rgba(255,255,255,.85); margin-bottom: 24px; text-shadow: 0 1px 12px rgba(13,22,31,.7); opacity: 0; animation: fadeUp 1s .05s cubic-bezier(.22,1,.36,1) forwards; }
.banner-eyebrow::before { content: ''; display: inline-block; width: 44px; height: 1px; background: rgba(255,255,255,.6); vertical-align: middle; margin-right: 16px; }
.banner h1 { font-size: clamp(34px, 5vw, 68px); line-height: 1.14; font-weight: 400; max-width: 13em; text-shadow: 0 2px 30px rgba(13,22,31,.65), 0 1px 6px rgba(13,22,31,.4); }
.banner h1 .line { display: block; overflow: hidden; padding-bottom: .16em; margin-bottom: -.16em; padding-right: .1em; }
.banner h1 .line span { display: block; transform: translateY(110%); animation: lineUp 1.1s cubic-bezier(.22,1,.36,1) forwards; }
.banner h1 .line:nth-child(2) span { animation-delay: .12s; }
.banner h1 em { font-style: italic; font-weight: 400; }
@keyframes lineUp { to { transform: translateY(0); } }
.banner-sub { font-size: clamp(15px, 1.6vw, 18px); max-width: 32em; margin-top: 24px; color: #fff; text-shadow: 0 1px 18px rgba(13,22,31,.75); opacity: 0; animation: fadeUp 1s .5s cubic-bezier(.22,1,.36,1) forwards; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: translateY(0); } }

/* ---------- sections (index/contact/careers override padding per page) ---------- */
section { padding: clamp(80px, 11vw, 150px) var(--gutter); }

/* ---------- testimonial band ---------- */
.testimonial-band { position: relative; color: #fff; text-align: center; overflow: hidden; padding: clamp(110px, 15vw, 200px) var(--gutter); }
.testimonial-band .band-media { position: absolute; inset: -10% 0; z-index: 0; will-change: transform; }
.testimonial-band .band-media::after { content: ''; position: absolute; inset: 0; background: rgba(18,28,38,.72); }
.testimonial-band .inner { position: relative; z-index: 1; max-width: 880px; margin: 0 auto; }
.testimonial-band blockquote { font-family: var(--serif); font-size: clamp(24px, 3.4vw, 42px); line-height: 1.35; font-weight: 400; }
.testimonial-band blockquote em { font-style: italic; }
.testimonial-band cite { display: block; font-style: normal; font-size: 11px; font-weight: 700; letter-spacing: .24em; text-transform: uppercase; margin-top: 34px; color: rgba(255,255,255,.8); }

/* ---------- final cta ---------- */
.final-cta { text-align: center; padding: clamp(110px, 14vw, 190px) var(--gutter); }
.final-cta h2 { font-size: clamp(32px, 5vw, 64px); line-height: 1.1; max-width: 14em; margin: 0 auto; }
.final-cta p { max-width: 36em; margin: 26px auto 0; color: var(--ink-60); font-size: 17px; }
.final-cta .btn { margin-top: 44px; }

/* ---------- footer ---------- */
footer { background: var(--ink); color: rgba(255,255,255,.75); padding: clamp(64px, 8vw, 100px) var(--gutter) 40px; font-size: 13.5px; }
/* Oct 21: the Clients column was removed (approved Oct 12) — three columns now,
   Explore widened so the longer link list still sits on one tidy run. */
.foot-grid { display: grid; grid-template-columns: 1.8fr 1.5fr 1.4fr; gap: 44px; }
.foot-logo .name { font-family: var(--serif); font-size: 21px; font-weight: 600; letter-spacing: .06em; color: #fff; }
.foot-logo .sub { font-size: 8.5px; font-weight: 700; letter-spacing: .34em; text-transform: uppercase; opacity: .65; }
.foot-logo p { margin-top: 18px; max-width: 24em; }
/* H-13 — the footer lockup is a link home */
.foot-home { display: block; text-decoration: none; color: inherit; }
.foot-home:hover .name { opacity: .82; }
/* Association memberships (Abby Oct 1 tracker; resized + NAHB added Oct 2 —
   both deliberately smaller than the Phillip Smith lockup). affil-light =
   white artwork, greyed directly; affil-dark = dark artwork, inverted to the
   same light grey so it reads on the dark footer. */
.foot-affil { margin-top: 26px; display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
.foot-affil img { display: block; width: auto; opacity: .55; }
.foot-affil .affil-light { height: 28px; filter: grayscale(1); }
.foot-affil .affil-dark { height: 52px; filter: grayscale(1) invert(1) brightness(1.15); }
/* H-21 / F-01 — social marks sit greyed back and come forward on hover */
.foot-social { display: flex; align-items: center; gap: 16px; margin-top: 20px; }
.foot-social .soc { display: inline-flex; color: rgba(255,255,255,.45); transition: color .3s, transform .3s; }
.foot-social .soc:hover { color: #fff; transform: translateY(-2px); }
.foot-social .soc:focus-visible { outline: 2px solid rgba(255,255,255,.7); outline-offset: 4px; border-radius: 3px; }
/* F-02 — the footer Nautilus entry IS the outbound link, arrow and all
   (Jack, Aug 30: one line, not two). */
.foot-naut { white-space: nowrap; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (hover: none) { .foot-social .soc:hover { transform: none; } }
@media (prefers-reduced-motion: reduce) { .foot-social .soc { transition: none; } }
footer h4 { font-size: 10.5px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase; color: #fff; margin-bottom: 18px; }
footer li { list-style: none; margin-bottom: 10px; }
footer a:hover { color: #fff; }
.foot-bottom { border-top: 1px solid rgba(255,255,255,.14); margin-top: clamp(48px, 6vw, 72px); padding-top: 28px; display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; font-size: 11.5px; opacity: .65; }
@media (max-width: 900px) { .foot-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .foot-grid { grid-template-columns: 1fr; } }

/* ---------- form controls (contact + careers; .form-card look is per-page) ---------- */
form { margin-top: 32px; }
.frow { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
@media (max-width: 560px) { .frow { grid-template-columns: 1fr; gap: 0; } }
.field { margin-bottom: 26px; }
label { display: block; font-size: 10.5px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-60); margin-bottom: 8px; }
label .req { color: var(--accent); }
input, select, textarea { width: 100%; font-family: var(--sans); font-size: 15.5px; color: var(--ink); background: transparent; border: 0; border-bottom: 1px solid rgba(26,26,26,.22); padding: 10px 2px; border-radius: 0; transition: border-color .3s; -webkit-appearance: none; appearance: none; }
select { cursor: pointer; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%231A1A1A' stroke-width='1.4'/></svg>"); background-repeat: no-repeat; background-position: right 4px center; padding-right: 22px; }
textarea { min-height: 100px; resize: vertical; line-height: 1.6; }
input:focus, select:focus, textarea:focus { outline: none; border-bottom-color: var(--accent); }
input::placeholder, textarea::placeholder { color: var(--ink-30); }
.form-card .fhead { font-family: var(--serif); font-size: clamp(21px, 2.2vw, 27px); }
.form-card .fsub { font-size: 14px; color: var(--ink-60); margin-top: 8px; }
.form-card .btn { width: 100%; margin-top: 8px; }
/* honeypot — visually gone, still in the DOM for bots */
.hp-field { display: none !important; }
/* submit-failure fallback line (hidden unless the AJAX post fails) */
.form-err { display: none; text-align: center; font-size: 13.5px; color: #C0392B; margin-top: 16px; }
.form-err a { color: inherit; border-bottom: 1px solid currentColor; }
/* success state (careers uses in-card state; contact redirects to thank-you) */
.sent { display: none; text-align: center; padding: clamp(40px, 6vw, 80px) 0; }
.sent .serif { font-size: clamp(24px, 2.6vw, 32px); }
.sent p { color: var(--ink-60); margin-top: 14px; }
.form-card.is-sent form, .form-card.is-sent .fhead, .form-card.is-sent .fsub { display: none; }
.form-card.is-sent .sent { display: block; }

/* ---------- reveal on scroll ---------- */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .9s cubic-bezier(.22,1,.36,1), transform .9s cubic-bezier(.22,1,.36,1); }
.reveal.in { opacity: 1; transform: translateY(0); }
.reveal.d1 { transition-delay: .08s; } .reveal.d2 { transition-delay: .16s; } .reveal.d3 { transition-delay: .24s; } .reveal.d4 { transition-delay: .32s; }
/* big shadowed cards fade without moving — moving a large shadow repaints every frame */
.reveal.fade-only { transform: none !important; }

/* ---------- wipe reveal ----------
   Safari-safe: observe the WRAPPER (.reveal.wipe-box), clip the inner .wipe.
   Photo develops in with a directional clip-path wipe + scale settle. */
.reveal.wipe-box { opacity: 1; transform: none; }
.wipe-box { overflow: hidden; }
.wipe-box .wipe { height: 100%; clip-path: inset(0 100% 0 0); transform: scale(1.12); transition: clip-path 1.15s cubic-bezier(.22,1,.36,1), transform 1.45s cubic-bezier(.22,1,.36,1); }
.wipe-box.wipe-r .wipe { clip-path: inset(0 0 0 100%); }
.wipe-box.in .wipe { clip-path: inset(0 0 0 0); transform: none; }
.wipe-box.d1 .wipe { transition-delay: .08s; } .wipe-box.d2 .wipe { transition-delay: .16s; }

/* ---------- review mode (#flat): static render for full-page screenshots
     (flat banner/hero HEIGHTS are per-page) ---------- */
body.flat .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
body.flat .wipe-box .wipe { clip-path: inset(0 0 0 0) !important; transform: none !important; transition: none !important; }
body.flat .banner h1 .line span { animation: none; transform: none; }
body.flat .banner-sub, body.flat .banner-eyebrow { animation: none; opacity: 1; }

/* ---------- prefers-reduced-motion: everything lands instantly (WCAG 2.3.3 / QA rule 4)
     JS side: site.js skips Lenis, parallax, and count-up under the same query ---------- */
@media (prefers-reduced-motion: reduce) {
  html.no-lenis { scroll-behavior: auto; }
  .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
  .wipe-box .wipe { clip-path: inset(0 0 0 0) !important; transform: none !important; transition: none !important; }
  .banner h1 .line span { animation: none; transform: none; }
  .banner-sub, .banner-eyebrow { animation: none; opacity: 1; }
  .banner-media, .testimonial-band .band-media { will-change: auto; }
  .btn, .text-link, .nav-cta, nav, .nav-logo, .nav-logo .mark, .nav-links a { transition: none; }
}
