/* ==========================================================================
   CLEAR PATH GROUND WORKS — DESIGN SYSTEM
   ---------------------------------------------------------------------------
   Brand palette (fixed, supplied by client):
     Charcoal    #1E1E1E
     Bronze      #B07D3C
     Olive Green #6B7A46
     Warm White  #F7F6F2

   Type: Barlow Condensed (headings) / Montserrat (body). Self-hosted, see
   css/fonts.css.

   ---------------------------------------------------------------------------
   CONTRAST NOTE — why bronze is not used as body text on light backgrounds
   ---------------------------------------------------------------------------
   Measured WCAG ratios for the supplied palette:

     Bronze #B07D3C on Charcoal #1E1E1E .......... 4.69:1  -> AA normal text OK
     Bronze #B07D3C on Warm White #F7F6F2 ........ 3.28:1  -> LARGE TEXT ONLY
     Olive  #6B7A46 on Warm White #F7F6F2 ........ 4.26:1  -> fails AA normal

   So on dark surfaces bronze is free to carry text of any size, but on light
   surfaces it is restricted to display-size headings, rules, icons and fills.
   Anywhere a bronze-coloured link or small label sits on white, the darkened
   --bronze-ink (#8E6230, 4.93:1) is substituted instead. Olive is treated as a
   fill/rule colour only, with --olive-ink (#55603A) for the rare text use.
   None of the four brand colours were altered — these are additional shades
   derived from bronze/olive purely to keep text legible.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /* --- Brand, exactly as supplied ---------------------------------------- */
  --charcoal:    #1E1E1E;
  --bronze:      #B07D3C;
  --olive:       #6B7A46;
  --warm-white:  #F7F6F2;

  /* --- Derived neutrals --------------------------------------------------- */
  --char-950: #141414;
  --char-900: #1A1A1A;
  --char-850: #1E1E1E;
  --char-800: #242424;
  --char-700: #2E2E2E;
  --char-600: #3A3A3A;
  --char-500: #4E4E4C;

  --paper:     #FFFFFF;
  --paper-alt: #F7F6F2;
  --paper-dim: #EFEDE6;

  --ink:        #1E1E1E;
  --ink-body:   #3A3A36;   /* 11.1:1 on warm white */
  --ink-muted:  #6A6A62;   /* 5.2:1  on warm white */

  /* --- Accent shades derived for legibility (see contrast note) ---------- */
  --bronze-ink:   #8E6230;  /* bronze darkened for text on light   4.93:1 */
  --bronze-lift:  #C89355;  /* bronze lightened for hover on dark        */
  --bronze-glow:  rgba(176, 125, 60, 0.16);
  --olive-ink:    #55603A;
  --olive-lift:   #7E8E55;

  /* --- Hairlines ---------------------------------------------------------- */
  --rule-dark:  rgba(247, 246, 242, 0.14);
  --rule-light: rgba(30, 30, 30, 0.12);
  --rule-bronze: rgba(176, 125, 60, 0.38);

  /* --- Type -------------------------------------------------------------- */
  --font-head: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
  --font-body: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Fluid display scale. clamp() keeps headings proportional from 360px to
     1440px without a stack of breakpoints. */
  --t-display: clamp(2.75rem, 1.4rem + 5.9vw, 6.25rem);
  --t-h1:      clamp(2.25rem, 1.3rem + 4.2vw, 4.5rem);
  --t-h2:      clamp(1.85rem, 1.25rem + 2.6vw, 3.25rem);
  --t-h3:      clamp(1.35rem, 1.1rem + 1.1vw, 1.85rem);
  --t-h4:      clamp(1.1rem, 1rem + 0.5vw, 1.3rem);
  --t-lead:    clamp(1.02rem, 0.97rem + 0.28vw, 1.19rem);
  --t-body:    1rem;
  --t-small:   0.875rem;
  --t-micro:   0.75rem;

  /* --- Space -------------------------------------------------------------- */
  --shell:      1240px;
  --shell-narrow: 900px;
  --gutter:     clamp(1.25rem, 0.8rem + 2vw, 2.5rem);
  --section-y:  clamp(4rem, 2.5rem + 6vw, 8rem);
  --section-y-sm: clamp(3rem, 2rem + 4vw, 5.5rem);

  /* --- Motion ------------------------------------------------------------- */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.45s;

  /* Tall enough to clear the 64px logo badge with real breathing room. */
  --header-h: 92px;
  /* Live height of .stormbar, kept in sync by an inline script right after it
     in the markup (pre-paint) and by js/main.js thereafter (post-load, on
     resize/wrap changes). .header reads this so it always sits below the bar
     instead of the two occupying the same pixels — see the note on .header. */
  --stormbar-h: 0px;
  --shadow-card: 0 1px 2px rgba(30,30,30,.05), 0 12px 32px -12px rgba(30,30,30,.18);
  --shadow-lift: 0 2px 4px rgba(30,30,30,.06), 0 28px 56px -20px rgba(30,30,30,.30);
}

@media (max-width: 900px) {
  :root { --header-h: 72px; }
}

/* ==========================================================================
   2. RESET / BASE
   ========================================================================== */

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

* { margin: 0; }

/* The UA stylesheet implements [hidden] as `display: none`, which ANY author
   `display` declaration silently outranks. Several components here set an
   explicit display on an element that also toggles [hidden] (.brand__fallback
   being the one that bit: the logo and its type-lockup fallback both rendered,
   widening the header until the burger was pushed off-screen on phones).
   This makes the attribute authoritative, as its semantics imply. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.7;
  color: var(--ink-body);
  background: var(--warm-white);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

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

input, button, textarea, select { font: inherit; color: inherit; }

a { color: var(--bronze-ink); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--bronze); }

/* Visible, brand-coloured focus ring on every interactive element. Uses
   :focus-visible so mouse users never see it but keyboard users always do. */
:focus-visible {
  outline: 3px solid var(--bronze);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--bronze); color: #fff; }

.skip-link {
  position: absolute;
  left: 1rem;
  top: -100px;
  z-index: 999;
  /* --bronze-ink, not --bronze — same 3.59:1 white-text failure as .btn,
     fixed the same way. Notable here specifically: this is a keyboard-
     accessibility feature, so a contrast failure on it is doubly wrong. */
  background: var(--bronze-ink);
  color: #fff;
  padding: 0.75rem 1.25rem;
  font-family: var(--font-head);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 1rem; color: #fff; }

.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;
}

/* ==========================================================================
   3. TYPOGRAPHY
   ========================================================================== */

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4 {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
}

.h1, h1 { font-size: var(--t-h1); }
.h2, h2 { font-size: var(--t-h2); }
.h3, h3 { font-size: var(--t-h3); line-height: 1.12; }
.h4, h4 { font-size: var(--t-h4); line-height: 1.2; letter-spacing: 0.02em; }

.display {
  font-size: var(--t-display);
  line-height: 0.94;
  letter-spacing: -0.005em;
}

p { text-wrap: pretty; }
p + p { margin-top: 1.1em; }

.lead {
  font-size: var(--t-lead);
  line-height: 1.65;
  color: var(--ink-body);
}

.on-dark { color: var(--warm-white); }
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4 { color: var(--warm-white); }
.on-dark p { color: rgba(247, 246, 242, 0.82); }
.on-dark a { color: var(--bronze); }
.on-dark a:hover { color: var(--bronze-lift); }

/* Headings inherit --ink (charcoal) by default, which is invisible against
   .section--dark's charcoal background unless every heading is individually
   wrapped in .on-dark or hand-colored. That dependency was missed on six
   headings across the site (contrast audit found them rendering charcoal-on-
   charcoal — literally blank space where a heading should be, e.g. "Where We
   Work" on the homepage). Making dark sections self-contained for their own
   headings removes the failure mode instead of just patching each instance. */
.section--dark h1, .section--dark h2, .section--dark h3, .section--dark h4 {
  color: var(--warm-white);
}

/* --- Eyebrow: the small numbered label above section headings.
       Reads like a survey station marker — part of the "ground works" motif. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-head);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bronze-ink);
  margin-bottom: 1.1rem;
}
.on-dark .eyebrow, .eyebrow--light { color: var(--bronze); }

.eyebrow::before {
  content: "";
  width: 34px;
  height: 2px;
  background: currentColor;
  flex: none;
}
.eyebrow--center { justify-content: center; }

/* --- Section heading block ---------------------------------------------- */
.section-head { max-width: 62ch; margin-bottom: clamp(2.25rem, 1.5rem + 2vw, 3.5rem); }
.section-head--center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head p { margin-top: 1.15rem; font-size: var(--t-lead); }

/* ==========================================================================
   4. LAYOUT
   ========================================================================== */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.shell--narrow { max-width: var(--shell-narrow); }

.section { padding-block: var(--section-y); position: relative; }
.section--sm { padding-block: var(--section-y-sm); }
.section--flush-top { padding-top: 0; }

.section--dark { background: var(--charcoal); color: var(--warm-white); }
.section--paper { background: var(--paper); }
.section--alt { background: var(--paper-alt); }
.section--dim { background: var(--paper-dim); }

/* Hairline that separates stacked light sections without a heavy border. */
.section--ruled { border-top: 1px solid var(--rule-light); }

.grid { display: grid; gap: clamp(1.25rem, 0.9rem + 1.4vw, 2rem); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1000px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); }
}

/* Split: text column + media column, reversible. */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 1rem + 4vw, 5rem);
  align-items: center;
}
.split--reverse > :first-child { order: 2; }
@media (max-width: 900px) {
  .split { grid-template-columns: minmax(0, 1fr); }
  .split--reverse > :first-child { order: 0; }
}

/* Pins the media column in place while the other column scrolls past beside
   it — used by the "How It Runs" process section so the photo stays put as
   the visitor scrolls through the four steps. align-self: start is required
   because .split's default align-items: center stretches grid children to
   the row's full height, which would leave nothing for `sticky` to travel
   within (a sticky element can't move inside a box it's already stretched
   to fill). Off below 900px, where the two columns stack and there is no
   side-by-side scroll relationship left to preserve. */
.split--sticky-media > :first-child {
  align-self: start;
  position: sticky;
  top: calc(var(--header-h) + 2rem);
}
@media (max-width: 900px) {
  .split--sticky-media > :first-child { position: static; }
}

/* ==========================================================================
   5. BUTTONS
   ========================================================================== */

.btn {
  /* Matches .btn--primary's fix below: --bronze-ink, not --bronze, so a
     button that ends up with no modifier class still carries accessible
     white text instead of silently reintroducing the 3.59:1 failure. */
  --btn-bg: var(--bronze-ink);
  --btn-fg: #fff;
  --btn-bd: var(--bronze-ink);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.95rem 1.9rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 2px solid var(--btn-bd);
  border-radius: 2px;
  font-family: var(--font-head);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.28s var(--ease),
              border-color 0.28s var(--ease),
              color 0.28s var(--ease),
              transform 0.28s var(--ease),
              box-shadow 0.28s var(--ease);
}

.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 24px -10px rgba(176, 125, 60, 0.55);
  color: var(--btn-fg);
}
.btn:active { transform: translateY(0); }

/* Resting state uses --bronze-ink, not the brand's literal --bronze, for the
   button FILL specifically. White text on raw --bronze (#B07D3C) measures
   3.59:1 — confirmed by the WCAG relative-luminance formula, not a rounding
   artifact — which fails the 4.5:1 minimum for normal-size text, on every
   primary CTA sitewide ("Request a Free Estimate", "Call 941-699-6992", every
   "Free Estimate" button). White on --bronze-ink (#8E6230) measures 5.33:1,
   comfortably clearing it. Hover swaps to the brighter, literal --bronze —
   the button now lightens on hover instead of darkening, which reads as more
   "alive" as an interaction anyway. --bronze itself is untouched everywhere
   else (rules, icons, numbers, borders); only what a primary button's fill
   resolves to changed. */
.btn--primary { --btn-bg: var(--bronze-ink); --btn-fg: #fff; --btn-bd: var(--bronze-ink); }
.btn--primary:hover { --btn-bg: var(--bronze); --btn-bd: var(--bronze); }

/* Outline on light surfaces */
.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  --btn-bd: rgba(30, 30, 30, 0.28);
}
.btn--ghost:hover {
  --btn-bg: var(--charcoal);
  --btn-fg: var(--warm-white);
  --btn-bd: var(--charcoal);
  box-shadow: 0 12px 24px -10px rgba(30, 30, 30, 0.45);
}

/* Outline on dark surfaces */
.btn--ghost-light {
  --btn-bg: transparent;
  --btn-fg: var(--warm-white);
  --btn-bd: rgba(247, 246, 242, 0.42);
}
.btn--ghost-light:hover {
  --btn-bg: var(--warm-white);
  --btn-fg: var(--charcoal);
  --btn-bd: var(--warm-white);
  box-shadow: 0 12px 24px -10px rgba(0, 0, 0, 0.5);
}

.btn--olive { --btn-bg: var(--olive); --btn-fg: #fff; --btn-bd: var(--olive); }
.btn--olive:hover { --btn-bg: var(--olive-ink); --btn-bd: var(--olive-ink); box-shadow: 0 12px 24px -10px rgba(107,122,70,.55); }

.btn--sm { padding: 0.7rem 1.25rem; font-size: 0.9375rem; letter-spacing: 0.08em; }
.btn--lg { padding: 1.15rem 2.4rem; font-size: 1.15rem; }

/* .btn is white-space:nowrap everywhere else in the system — deliberately,
   since a button label breaking mid-word looks broken. The one long-label
   CTA ("Call 941-699-6992 for Emergency Response") overflowed the viewport
   on phones as a result, so large buttons specifically are allowed to wrap
   below 480px, where a two-line centered button reads as a considered
   choice rather than a bug. Small/default buttons keep single-line text. */
@media (max-width: 480px) {
  .btn--lg { white-space: normal; text-align: center; line-height: 1.25; }
}
.btn--block { width: 100%; }

.btn__icon { width: 1.05em; height: 1.05em; flex: none; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  align-items: center;
}
.btn-row--center { justify-content: center; }

/* Text link with an animated bronze underline. */
.link-cut {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-head);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--bronze-ink);
  padding-bottom: 0.3rem;
  background-image: linear-gradient(var(--bronze), var(--bronze));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 2px;
  transition: background-size 0.35s var(--ease), color 0.28s var(--ease), gap 0.28s var(--ease);
}
.link-cut:hover { gap: 0.85rem; color: var(--bronze); }
.on-dark .link-cut { color: var(--bronze); }
.on-dark .link-cut:hover { color: var(--bronze-lift); }
.link-cut svg { width: 0.95em; height: 0.95em; }

/* ==========================================================================
   6. HEADER
   ---------------------------------------------------------------------------
   Sits transparent over the hero on every page, then condenses to solid
   charcoal once the user scrolls past the hero (js/main.js toggles .is-stuck).

   `top` reads --stormbar-h rather than being pinned to 0. .header is
   position:fixed (removed from flow) and .stormbar is a normal in-flow
   element directly above it, so a hard-coded top:0 puts the header on top of
   — literally overlapping — the storm bar for as long as the bar is still on
   screen, since .header's z-index (100) simply paints over it. js/main.js
   narrows this offset by the scroll distance each frame, so the header sits
   below the bar at the top of the page and glides up flush with it exactly
   as the bar scrolls away, instead of the two ever sharing the same pixels.
   ========================================================================== */

.header {
  position: fixed;
  top: var(--stormbar-h, 0px);
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 0.35s var(--ease),
              border-color 0.35s var(--ease),
              box-shadow 0.35s var(--ease),
              height 0.35s var(--ease);
}

.header::before {
  /* Scrim so white nav text stays readable over bright hero photography
     before the header goes solid. */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(20,20,20,.78), rgba(20,20,20,0));
  opacity: 1;
  transition: opacity 0.35s var(--ease);
  pointer-events: none;
}

.header.is-stuck {
  background: var(--char-950);
  border-bottom-color: var(--rule-dark);
  box-shadow: 0 10px 30px -18px rgba(0,0,0,.9);
}
.header.is-stuck::before { opacity: 0; }

.header__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  width: 100%;
  position: relative;
  z-index: 1;
}

/* --- Brand lockup --------------------------------------------------------
   .brand__logo is the client's approved artwork (images/Logo.png), used
   exactly as supplied — only its height is constrained, width follows the
   file's own 362:231 aspect ratio. It is never recoloured, cropped or redrawn.

   The supplied logo is a PICTORIAL badge with no company name in it, so the
   .brand__wordmark type lockup sits permanently beside it rather than acting
   as a fallback — without it a visitor could not read who the company is. The
   image carries alt="" because the wordmark next to it already states the name;
   announcing it twice would just be noise for screen-reader users.
   ------------------------------------------------------------------------ */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
  text-decoration: none;
  margin-right: auto;
  flex: none;
}

/* The badge is nearly square (362x231), so it earns a little more height than a
   horizontal wordmark would — at 44px tall the illustrated scene turns to mush. */
.brand__logo {
  /* 4.4vw reaches the 64px ceiling at ~1440px, the most common desktop width,
     so the badge is at full size where most visitors see it. */
  height: clamp(48px, 4.4vw, 64px);
  width: auto;
  display: block;
  flex: none;
  transition: height 0.35s var(--ease);
}
.header.is-stuck .brand__logo { height: clamp(42px, 3.2vw, 54px); }

.brand__wordmark {
  display: flex;
  flex-direction: column;
  line-height: 1;
  font-family: var(--font-head);
  text-transform: uppercase;
  color: var(--warm-white);
}
.brand__wordmark-name {
  font-size: clamp(1.25rem, 1rem + 0.75vw, 1.65rem);
  font-weight: 700;
  letter-spacing: 0.05em;
  white-space: nowrap;
}
.brand__wordmark-sub {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.32rem;
  font-size: clamp(0.6rem, 0.54rem + 0.2vw, 0.72rem);
  font-weight: 600;
  letter-spacing: 0.28em;
  color: var(--bronze);
  white-space: nowrap;
}
.brand__wordmark-sub::before {
  content: "";
  width: 18px;
  height: 2px;
  background: var(--bronze);
  flex: none;
}

/* --- Primary nav --------------------------------------------------------- */
.nav { display: block; }
.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 0.3rem + 1.5vw, 2.1rem);
  list-style: none;
  padding: 0;
  margin: 0;
}

.nav__link {
  position: relative;
  display: block;
  padding: 0.4rem 0;
  font-family: var(--font-head);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: rgba(247, 246, 242, 0.9);
  white-space: nowrap;
  transition: color 0.25s var(--ease);
}

/* The bronze "cut line" that wipes in under a nav item — the same blade-path
   motif used for section rules and link underlines. */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: var(--bronze);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}
.nav__link:hover { color: #fff; }
.nav__link:hover::after { transform: scaleX(1); }

.nav__link.is-current { color: #fff; }
.nav__link.is-current::after { transform: scaleX(1); }

.header__actions {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex: none;
}

.header__phone {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-head);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-decoration: none;
  color: var(--warm-white);
  white-space: nowrap;
  transition: color 0.25s var(--ease);
}
.header__phone:hover { color: var(--bronze); }
.header__phone svg { width: 1.05em; height: 1.05em; color: var(--bronze); flex: none; }

/* --- Burger -------------------------------------------------------------- */
.burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 46px;
  height: 46px;
  padding: 0 9px;
  background: transparent;
  border: 1px solid rgba(247,246,242,.3);
  border-radius: 2px;
  cursor: pointer;
  flex: none;
}
.burger__bar {
  display: block;
  height: 2px;
  width: 100%;
  background: var(--warm-white);
  transition: transform 0.35s var(--ease), opacity 0.2s var(--ease);
}
.burger.is-open .burger__bar:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.burger.is-open .burger__bar:nth-child(2) { opacity: 0; }
.burger.is-open .burger__bar:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/* Header breakpoints are set by measured fit, not by round numbers.
   The full lockup is brand + 5 nav items + phone + CTA button, and none of
   those can wrap. Measured against the 1240px shell it stops fitting below
   ~1140px, so the drawer takes over there — a tablet in landscape (1024px)
   correctly gets the burger rather than a nav that overflows the viewport. */
@media (max-width: 1260px) {
  .header__phone span { display: none; }
}
@media (max-width: 1140px) {
  .nav { display: none; }
  .burger { display: flex; }
  .header__actions .btn { display: none; }
}

/* At 320px the shell leaves 280px of content width. Logo (201) + gap (24) +
   phone icon (19) + gap (24) + burger (46) = 314, which pushed the burger off
   the screen entirely — the menu became untappable. The phone icon is the
   redundant one here: the storm bar directly above the header already shows
   the number, and the drawer repeats it. Dropping it plus a slightly smaller
   logo brings the row to 252px, inside 280 with room to spare. */
@media (max-width: 520px) {
  .header__actions { display: none; }
  .brand__logo { height: 42px; }
  .header.is-stuck .brand__logo { height: 38px; }
}

/* Below ~380px even the wordmark will not fit beside the badge. The badge is
   the client's actual artwork, so the type lockup is what gives way — the page
   <title>, the hero and the footer all still carry the company name. */
@media (max-width: 379px) {
  .brand__wordmark { display: none; }
  .brand__logo { height: 46px; }
}

/* --- Mobile drawer ------------------------------------------------------- */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: var(--char-950);
  padding: calc(var(--header-h) + 2rem) var(--gutter) 2.5rem;
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-12px);
  /* visibility is stepped, not eased: 0s with a delay equal to the fade means
     it flips to hidden only AFTER the panel has faded out. On open (below) the
     delay is 0s so it becomes visible immediately — without that, the panel is
     still computed `hidden` when JS calls focus(), and a hidden element
     silently refuses focus, stranding keyboard users on the page behind. */
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), visibility 0s linear 0.35s;
}
.drawer.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease), visibility 0s linear 0s;
}

.drawer__list { list-style: none; padding: 0; margin: 0 0 2rem; }
.drawer__list li { border-bottom: 1px solid var(--rule-dark); }

.drawer__link {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1.05rem 0;
  font-family: var(--font-head);
  font-size: 1.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--warm-white);
  transition: color 0.25s var(--ease), padding-left 0.25s var(--ease);
}
.drawer__link:hover, .drawer__link.is-current { color: var(--bronze); padding-left: 0.5rem; }
.drawer__link::before {
  content: attr(data-num);
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  color: var(--bronze);
  flex: none;
}

.drawer__foot { display: grid; gap: 0.9rem; }
.drawer__phone {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-head);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--warm-white);
  text-decoration: none;
}
.drawer__phone svg { width: 1em; height: 1em; color: var(--bronze); }

body.is-locked { overflow: hidden; }

/* ==========================================================================
   7. HERO
   ========================================================================== */

.hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(92vh, 900px);
  padding-top: calc(var(--header-h) + clamp(3rem, 6vw, 6rem));
  padding-bottom: clamp(3.5rem, 2rem + 5vw, 7rem);
  background: var(--char-950);
  overflow: hidden;
  isolation: isolate;
}

.hero--compact {
  min-height: min(66vh, 620px);
  align-items: center;
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Two-stop scrim: a strong charcoal wash from the left for text legibility,
   plus a bottom fade so the section below joins seamlessly. Kept as a
   pseudo-element pair rather than one gradient so each can be tuned per page. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(100deg,
      rgba(15, 15, 15, 0.94) 0%,
      rgba(18, 18, 18, 0.82) 34%,
      rgba(20, 20, 20, 0.45) 62%,
      rgba(20, 20, 20, 0.30) 100%),
    linear-gradient(to top, rgba(15, 15, 15, 0.85) 0%, rgba(15, 15, 15, 0) 45%);
}

.hero__inner { position: relative; width: 100%; }
.hero__content { max-width: 44rem; }

.hero__title {
  font-size: var(--t-display);
  line-height: 0.92;
  color: var(--warm-white);
  letter-spacing: -0.003em;
}
.hero__title em {
  display: block;
  font-style: normal;
  color: var(--bronze);
}

.hero__tagline {
  margin-top: 1.4rem;
  font-family: var(--font-head);
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.6rem);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(247, 246, 242, 0.88);
}

.hero__text {
  margin-top: 1.35rem;
  max-width: 46ch;
  font-size: var(--t-lead);
  color: rgba(247, 246, 242, 0.8);
}

.hero__actions { margin-top: 2.25rem; }

/* Trust strip pinned to the bottom of the hero. */
.hero__strip {
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4.5rem);
  padding-top: 1.6rem;
  border-top: 1px solid var(--rule-dark);
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.25rem, 0.5rem + 2.5vw, 3.25rem);
}
.hero__strip-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-head);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(247, 246, 242, 0.9);
}
.hero__strip-item svg { width: 1.35em; height: 1.35em; color: var(--bronze); flex: none; }

/* Page hero (inner pages) */
.hero--page .hero__content { max-width: 52rem; }
.hero--page .hero__title { font-size: var(--t-h1); line-height: 1; }

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
  list-style: none;
  padding: 0;
  margin: 0 0 1.4rem;
  font-family: var(--font-head);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(247, 246, 242, 0.6);
}
.breadcrumb a { color: var(--bronze); text-decoration: none; }
.breadcrumb a:hover { color: var(--bronze-lift); text-decoration: underline; }
.breadcrumb li::after { content: "/"; margin-left: 0.55rem; color: rgba(247,246,242,.3); }
.breadcrumb li:last-child::after { content: none; }

/* ==========================================================================
   8. EMERGENCY / STORM BAR
   ---------------------------------------------------------------------------
   Thin olive band directly under the header on every page. Storm response is
   the client's highest-urgency offer, so it gets a permanent slot rather than
   living only in the nav.
   ========================================================================== */

.stormbar {
  position: relative;
  z-index: 90;
  background: var(--olive);
  color: #fff;
}
.stormbar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.4rem 1.1rem;
  padding-block: 0.7rem;
  text-align: center;
}
.stormbar__label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-head);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.stormbar__label svg { width: 1.1em; height: 1.1em; flex: none; }
/* Solid white, not translucent: at 14px, rgba(255,255,255,.92) over the olive
   background measured 4.24:1 — just under the 4.5:1 AA minimum for normal-size
   text. Solid white clears it, matching the label and link beside it, which
   were already solid for the same reason. */
.stormbar__text { font-size: var(--t-small); color: #fff; }
.stormbar__link {
  font-family: var(--font-head);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #fff;
  text-decoration: none;
  border-bottom: 2px solid rgba(255,255,255,.55);
  padding-bottom: 1px;
  transition: border-color 0.25s var(--ease);
}
.stormbar__link:hover { color: #fff; border-bottom-color: #fff; }

/* ==========================================================================
   9. CARDS
   ========================================================================== */

/* --- Service card: photo + copy, bronze cut-line on hover ---------------- */
.svc {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--rule-light);
  border-radius: 3px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease), border-color 0.4s var(--ease);
}
.svc:hover { transform: translateY(-6px); box-shadow: var(--shadow-lift); border-color: var(--rule-bronze); }

.svc__media { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--char-800); }
.svc__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease-out);
}
.svc:hover .svc__media img { transform: scale(1.055); }

/* Bronze rule that wipes across the base of the image on hover. */
.svc__media::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 4px;
  background: var(--bronze);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease);
}
.svc:hover .svc__media::after { transform: scaleX(1); }

.svc__num {
  position: absolute;
  top: 0; left: 0;
  padding: 0.5rem 0.85rem;
  background: rgba(20,20,20,.82);
  color: var(--bronze);
  font-family: var(--font-head);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.18em;
}

.svc__body { display: flex; flex-direction: column; flex: 1; padding: 1.65rem 1.5rem 1.75rem; }
.svc__title { font-size: var(--t-h3); margin-bottom: 0.7rem; }
.svc__text { font-size: 0.9375rem; line-height: 1.7; color: var(--ink-body); }
.svc__list {
  margin: 1.1rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.45rem;
}
.svc__list li {
  position: relative;
  padding-left: 1.4rem;
  font-size: 0.875rem;
  color: var(--ink-muted);
}
.svc__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.62em;
  width: 8px; height: 2px;
  background: var(--bronze);
}
.svc__foot { margin-top: auto; padding-top: 1.4rem; }

/* --- Icon card ----------------------------------------------------------- */
.icard {
  padding: clamp(1.5rem, 1.1rem + 1.2vw, 2.15rem);
  background: var(--paper);
  border: 1px solid var(--rule-light);
  border-radius: 3px;
  border-top: 3px solid var(--bronze);
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.icard:hover { transform: translateY(-5px); box-shadow: var(--shadow-lift); }
.icard--dark {
  background: var(--char-800);
  border-color: var(--rule-dark);
  border-top-color: var(--bronze);
  color: rgba(247,246,242,.8);
}
.icard--dark .icard__title { color: var(--warm-white); }

.icard__icon {
  width: 46px; height: 46px;
  margin-bottom: 1.15rem;
  color: var(--bronze);
}
.icard__icon svg { width: 100%; height: 100%; }
.icard__title { font-size: var(--t-h4); margin-bottom: 0.6rem; }
.icard__text { font-size: 0.9375rem; line-height: 1.7; }

/* --- Stats --------------------------------------------------------------- */
.stat { text-align: center; padding: 0.5rem; }
.stat__num {
  font-family: var(--font-head);
  font-size: clamp(2.75rem, 1.9rem + 3.4vw, 4.5rem);
  font-weight: 700;
  line-height: 1;
  color: var(--bronze);
  letter-spacing: -0.01em;
}
.stat__label {
  margin-top: 0.65rem;
  font-family: var(--font-head);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(247, 246, 242, 0.72);
}
.section--paper .stat__label, .section--alt .stat__label { color: var(--ink-muted); }

/* --- Process steps ------------------------------------------------------- */
.steps { counter-reset: step; display: grid; gap: 0; }
.step {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(1.25rem, 0.8rem + 1.6vw, 2.25rem);
  padding: clamp(1.6rem, 1.2rem + 1.2vw, 2.4rem) 0;
  border-top: 1px solid var(--rule-light);
}
.step:last-child { border-bottom: 1px solid var(--rule-light); }
.on-dark .step, .section--dark .step { border-color: var(--rule-dark); }

.step__num {
  font-family: var(--font-head);
  font-size: clamp(2.1rem, 1.6rem + 1.9vw, 3.1rem);
  font-weight: 700;
  line-height: 1;
  color: var(--bronze);
  min-width: 2.6ch;
  letter-spacing: 0.02em;
}
.step__title { font-size: var(--t-h3); margin-bottom: 0.55rem; }
.step__text { font-size: 0.9688rem; line-height: 1.75; max-width: 62ch; }

/* --- Scroll-linked steps ---------------------------------------------------
   Opt-in via .steps--scrolly (in the HTML) + .is-scrolly (added by JS only
   once js/main.js confirms IntersectionObserver is available and the visitor
   hasn't asked for reduced motion — see scrollySteps() in main.js). Scoped to
   that pairing rather than .step generally, so the plain step lists on the
   About and Contact pages are untouched. Without .is-scrolly every step
   simply renders at full opacity, so nothing depends on JS to be readable.
   ---------------------------------------------------------------------- */
.is-scrolly .step {
  padding-left: 1.15rem;
  opacity: 0.42;
  transition: opacity 0.45s var(--ease);
}
.is-scrolly .step__num { color: var(--ink-muted); transition: color 0.45s var(--ease); }

.is-scrolly .step::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3rem;
  bottom: 0.3rem;
  width: 3px;
  background: var(--bronze);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.45s var(--ease);
}

.is-scrolly .step.is-active { opacity: 1; }
.is-scrolly .step.is-active .step__num { color: var(--bronze); }
.is-scrolly .step.is-active::before { transform: scaleY(1); }

/* --- Checklist ----------------------------------------------------------- */
.checks { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.85rem; }
.checks li {
  position: relative;
  padding-left: 2.1rem;
  font-size: 0.9688rem;
  line-height: 1.65;
}
.checks li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.28em;
  width: 1.25rem; height: 1.25rem;
  border: 2px solid var(--bronze);
  border-radius: 2px;
}
.checks li::after {
  content: "";
  position: absolute;
  left: 0.4rem; top: 0.5em;
  width: 0.42rem; height: 0.72rem;
  border-right: 2px solid var(--bronze);
  border-bottom: 2px solid var(--bronze);
  transform: rotate(42deg);
}

/* --- Chip list -------------------------------------------------------------
   Non-interactive pill tags — used for "Who We Serve", the Southwest Florida
   condition list, and the Service Areas roll call. Deliberately not built on
   .filter (which is a clickable gallery control with hover/active states);
   these never do anything when clicked, so they aren't buttons. */
.chips { display: flex; flex-wrap: wrap; gap: 0.6rem; list-style: none; padding: 0; margin: 0; }
.chips--center { justify-content: center; }

.chip {
  padding: 0.55rem 1.1rem;
  background: var(--paper);
  border: 1px solid var(--rule-bronze);
  border-radius: 2px;
  font-family: var(--font-head);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink);
  white-space: nowrap;
}
.section--alt .chip { background: var(--paper); }
.chip--dark {
  background: transparent;
  border-color: rgba(176, 125, 60, 0.45);
  color: var(--warm-white);
}

/* --- Team ------------------------------------------------------------------
   No headshots were supplied. Rather than illustrate a named real person with
   a stand-in stock photo — which would misrepresent who they are — each card
   uses an initials badge in the brand's numbered-marker style (the same
   treatment as .step__num / .svc__num) until real photography is provided. */
.team { display: grid; gap: clamp(1.5rem, 1rem + 2vw, 2.5rem); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 720px) { .team { grid-template-columns: minmax(0, 1fr); } }

.team-card {
  padding: clamp(1.75rem, 1.3rem + 1.8vw, 2.5rem);
  background: var(--paper);
  border: 1px solid var(--rule-light);
  border-top: 3px solid var(--bronze);
  border-radius: 3px;
  box-shadow: var(--shadow-card);
}

.team-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 76px;
  height: 76px;
  margin-bottom: 1.25rem;
  background: var(--charcoal);
  color: var(--bronze);
  border: 1px solid var(--rule-bronze);
  border-radius: 50%;
  font-family: var(--font-head);
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* .team-card { background: var(--paper) } — always a light card, including
   when the section around it is .section--dark (About page). Scoped under
   .team-card specifically so its specificity (2 classes + type) beats the
   .section--dark h1-h4 rule (1 class + type), which would otherwise turn
   this white-on-white and invisible against the card's own light background. */
.team-card .team-name {
  color: var(--ink);
  font-family: var(--font-head);
  font-size: var(--t-h3);
  text-transform: uppercase;
  line-height: 1.1;
}
.team-role {
  margin-top: 0.35rem;
  font-family: var(--font-head);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bronze-ink);
}
.team-bio { margin-top: 1rem; font-size: 0.9375rem; line-height: 1.75; color: var(--ink-body); }

/* --- Review placeholder cards ----------------------------------------------
   No testimonials were supplied. A dashed border and explicitly muted star
   row (outline, not filled/coloured) keep these from reading as real
   5-star reviews at a glance — they are a marked slot, not a claim. */
.review-card {
  padding: clamp(1.5rem, 1.1rem + 1.4vw, 2.15rem);
  background: var(--paper-alt);
  border: 1px dashed rgba(30, 30, 30, 0.22);
  border-radius: 3px;
  text-align: center;
}
.review-card__stars { display: flex; justify-content: center; gap: 0.3rem; margin-bottom: 1rem; }
.review-card__stars svg { width: 1.15rem; height: 1.15rem; fill: none; stroke: var(--ink-muted); stroke-width: 1.4; }
.review-card__text { font-size: 0.9688rem; font-style: italic; color: var(--ink-muted); }
.review-card__name {
  margin-top: 0.85rem;
  font-family: var(--font-head);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* --- Project cards -----------------------------------------------------
   The Projects & Gallery template: a photo (still filterable/lightboxable,
   same as .shot) plus a labelled metadata block. Real jobs don't have
   photography or details yet, so every field defaults to an explicit
   "To be added" rather than a blank — a blank could read as an oversight,
   this reads as a placeholder waiting on real data. */
.project-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--paper);
  border: 1px solid var(--rule-light);
  border-radius: 3px;
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.project-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); }

.project-card__media {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--char-800);
  border: 0;
  padding: 0;
  cursor: pointer;
}
.project-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease-out);
}
.project-card:hover .project-card__media img { transform: scale(1.06); }

.project-card__category {
  position: absolute;
  top: 0; left: 0;
  padding: 0.5rem 0.85rem;
  background: rgba(20, 20, 20, 0.82);
  color: var(--bronze);
  font-family: var(--font-head);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.project-card__body { padding: 1.4rem 1.5rem 1.6rem; }
.project-card__title { font-size: var(--t-h4); margin-bottom: 1rem; }

.project-card__meta { margin: 0; display: grid; gap: 0.55rem; }
.project-card__meta > div { display: grid; grid-template-columns: 7.5rem 1fr; gap: 0.5rem; align-items: baseline; }
.project-card__meta dt {
  margin: 0;
  font-family: var(--font-head);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.project-card__meta dd { margin: 0; font-size: 0.8438rem; color: var(--ink-body); }
.project-card__meta dd.is-tbd { color: var(--ink-muted); font-style: italic; }

/* Empty-state card for a category with no photography or projects logged
   yet — deliberately distinct from a populated card, not a smaller version
   of one, so it never looks like a broken or forgotten tile. */
.project-card--empty {
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(2.5rem, 2rem + 2vw, 3.5rem) 1.5rem;
  background: var(--paper-alt);
  border: 1px dashed rgba(30, 30, 30, 0.22);
  box-shadow: none;
}
.project-card--empty:hover { transform: none; box-shadow: none; }
.project-card--empty__icon { width: 40px; height: 40px; margin: 0 auto 1rem; color: var(--ink-muted); }
.project-card--empty__icon svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.4; }
.project-card--empty__title {
  font-family: var(--font-head);
  font-size: var(--t-h4);
  text-transform: uppercase;
  color: var(--ink);
}
.project-card--empty__text { margin-top: 0.6rem; font-size: 0.875rem; color: var(--ink-muted); max-width: 32ch; }

/* ==========================================================================
   10. MEDIA FRAMES
   ========================================================================== */

/* Image with an offset bronze rule behind it — the "surveyed edge" motif. */
.frame { position: relative; }
.frame::before {
  content: "";
  position: absolute;
  inset: auto -14px -14px auto;
  width: 62%;
  height: 62%;
  border-right: 3px solid var(--bronze);
  border-bottom: 3px solid var(--bronze);
  z-index: 0;
}
.frame img {
  position: relative;
  z-index: 1;
  width: 100%;
  border-radius: 3px;
  box-shadow: var(--shadow-card);
}
.frame--flip::before { inset: -14px auto auto -14px; border: none; border-left: 3px solid var(--bronze); border-top: 3px solid var(--bronze); }

@media (max-width: 640px) {
  .frame::before { display: none; }
}

/* ==========================================================================
   11. GALLERY
   ========================================================================== */

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: clamp(0.85rem, 0.6rem + 1vw, 1.35rem);
}

.shot {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 3px;
  background: var(--char-800);
  aspect-ratio: 4 / 3;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  width: 100%;
}
.shot img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.75s var(--ease-out), filter 0.5s var(--ease);
}
.shot:hover img { transform: scale(1.07); filter: brightness(0.72); }

.shot__cap {
  position: absolute;
  inset: auto 0 0 0;
  padding: 1.5rem 1.15rem 1.05rem;
  background: linear-gradient(to top, rgba(15,15,15,.9), rgba(15,15,15,0));
  color: var(--warm-white);
  transform: translateY(6px);
  opacity: 0;
  transition: transform 0.4s var(--ease), opacity 0.4s var(--ease);
}
.shot:hover .shot__cap, .shot:focus-visible .shot__cap { transform: none; opacity: 1; }

.shot__title {
  font-family: var(--font-head);
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  line-height: 1.15;
}
.shot__meta {
  margin-top: 0.28rem;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bronze);
}

/* Tag filter buttons */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  margin-bottom: clamp(1.75rem, 1.2rem + 1.6vw, 2.75rem);
}
.filter {
  padding: 0.6rem 1.15rem;
  background: transparent;
  border: 1px solid var(--rule-light);
  border-radius: 2px;
  font-family: var(--font-head);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  cursor: pointer;
  /* Explicit property list, never `all` — see the note on .lightbox__close. */
  transition: background-color 0.28s var(--ease),
              border-color 0.28s var(--ease),
              color 0.28s var(--ease);
}
.filter:hover { border-color: var(--bronze); color: var(--bronze-ink); }
.filter.is-active {
  background: var(--charcoal);
  border-color: var(--charcoal);
  color: var(--warm-white);
}

/* --- Lightbox ------------------------------------------------------------ */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(12, 12, 12, 0.94);
  opacity: 0;
  visibility: hidden;
  /* Same stepped-visibility pattern as .drawer — see the note there. */
  transition: opacity 0.3s var(--ease), visibility 0s linear 0.3s;
}
.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s var(--ease), visibility 0s linear 0s;
}
.lightbox__fig { margin: 0; max-width: min(1100px, 100%); max-height: 100%; }
.lightbox__img {
  width: 100%;
  max-height: 78vh;
  object-fit: contain;
  border-radius: 3px;
}
.lightbox__cap {
  margin-top: 1rem;
  text-align: center;
  font-family: var(--font-head);
  font-size: 1.15rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--warm-white);
}
.lightbox__close {
  position: absolute;
  top: clamp(0.75rem, 2vw, 1.5rem);
  right: clamp(0.75rem, 2vw, 1.5rem);
  width: 48px; height: 48px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid rgba(247,246,242,.35);
  border-radius: 2px;
  color: var(--warm-white);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  /* Must NOT be `transition: all`. The shorthand includes `visibility`, and
     this button inherits visibility from .lightbox — so `all` made the button
     spend 0.25s still computed as hidden after the dialog opened, and a hidden
     element cannot take focus(). That silently broke keyboard access to the
     close button. Transition only what actually needs animating. */
  transition: background-color 0.25s var(--ease),
              border-color 0.25s var(--ease),
              color 0.25s var(--ease);
}
.lightbox__close:hover { background: var(--bronze); border-color: var(--bronze); }

/* ==========================================================================
   12. CTA BANDS
   ========================================================================== */

.cta {
  position: relative;
  overflow: hidden;
  background: var(--charcoal);
  color: var(--warm-white);
  isolation: isolate;
}
.cta__media { position: absolute; inset: 0; z-index: -2; }
.cta__media img { width: 100%; height: 100%; object-fit: cover; }
.cta__scrim {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(95deg, rgba(15,15,15,.95) 0%, rgba(18,18,18,.86) 45%, rgba(20,20,20,.55) 100%);
}
.cta__inner { max-width: 46rem; padding-block: clamp(3.5rem, 2.2rem + 4.5vw, 6.5rem); }
.cta__title { font-size: var(--t-h2); color: var(--warm-white); }
.cta__text { margin-top: 1.15rem; font-size: var(--t-lead); color: rgba(247,246,242,.82); }
.cta__actions { margin-top: 2rem; }

/* ==========================================================================
   13. FORMS
   ========================================================================== */

.form-card {
  background: var(--paper);
  border: 1px solid var(--rule-light);
  border-top: 4px solid var(--bronze);
  border-radius: 3px;
  padding: clamp(1.5rem, 1.1rem + 1.8vw, 2.75rem);
  box-shadow: var(--shadow-card);
}

/* Emergency storm callout beside the estimate form on the home page's
   Contact section — olive, not bronze, so it reads as a distinct "this one
   is different" block rather than a second copy of the form card, matching
   the storm bar's color language used for every other emergency touchpoint. */
.form-card--emergency {
  border-top-color: var(--olive);
  background: var(--paper-alt);
}

.field-grid { display: grid; gap: 1.15rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field-grid > .field--full { grid-column: 1 / -1; }
@media (max-width: 640px) { .field-grid { grid-template-columns: minmax(0, 1fr); } }

/* min-width: 0 defeats the grid blowout. Grid items default to
   `min-width: auto`, which means they refuse to shrink below the intrinsic
   width of their content — and <input>/<select> carry a default intrinsic
   width (roughly `size=20`) regardless of `width: 100%`. Without this, the
   form pushed the whole page ~5px wider than a 375px viewport. */
.field { display: flex; flex-direction: column; gap: 0.42rem; min-width: 0; }
.field-grid > *, .choices > * { min-width: 0; }
.field input, .field select, .field textarea { min-width: 0; }

.field label,
.fieldset__legend {
  font-family: var(--font-head);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink);
}
.field .req { color: var(--bronze-ink); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--warm-white);
  border: 1px solid rgba(30,30,30,.18);
  border-radius: 2px;
  font-size: 0.9688rem;
  color: var(--ink);
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.field textarea { min-height: 150px; resize: vertical; }

.field input::placeholder, .field textarea::placeholder { color: #9A9A92; }

.field input:hover, .field select:hover, .field textarea:hover { border-color: rgba(30,30,30,.34); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  background: var(--paper);
  border-color: var(--bronze);
  box-shadow: 0 0 0 3px var(--bronze-glow);
}
/* Keep the keyboard ring for users who tab in. */
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 3px solid var(--bronze);
  outline-offset: 2px;
}

.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%231E1E1E' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 12px;
  padding-right: 2.6rem;
}

.field__hint { font-size: 0.8125rem; color: var(--ink-muted); }

.fieldset { border: 0; padding: 0; margin: 0; }
.fieldset__legend { padding: 0; margin-bottom: 0.7rem; }

/* min(190px, 100%) so the track never demands more width than the container
   has, which would otherwise overflow on narrow phones. */
.choices { display: grid; gap: 0.55rem; grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr)); }
.choice {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  background: var(--warm-white);
  border: 1px solid rgba(30,30,30,.18);
  border-radius: 2px;
  font-size: 0.9062rem;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.choice:hover { border-color: var(--bronze); }
.choice input { width: 1.05rem; height: 1.05rem; accent-color: var(--bronze); flex: none; }
.choice:has(input:checked) { border-color: var(--bronze); background: #FBF7F1; }

/* Netlify honeypot — visually hidden but reachable by bots. */
.hp { position: absolute; left: -9999px; opacity: 0; height: 0; overflow: hidden; }

/* --- Contact detail list ------------------------------------------------- */
.detail { display: grid; gap: 1.5rem; }
.detail__item { display: grid; grid-template-columns: auto minmax(0,1fr); gap: 1rem; align-items: start; }
.detail__icon {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: var(--bronze);
  color: #fff;
  border-radius: 2px;
  flex: none;
}
.detail__icon svg { width: 20px; height: 20px; }
.detail__label {
  font-family: var(--font-head);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bronze);
  margin-bottom: 0.15rem;
}
/* Same unbreakable-email reasoning as .footer__contact a. */
.detail__value { font-size: 1.0625rem; line-height: 1.5; color: var(--warm-white); overflow-wrap: anywhere; }
.detail__value a { color: var(--warm-white); text-decoration: none; }
.detail__value a:hover { color: var(--bronze); }
.section--paper .detail__value, .section--alt .detail__value { color: var(--ink); }
/* .detail was originally built for a dark contact-info band; --bronze on
   warm-white/paper (3.59:1) fails AA there, same failure mode as the
   .btn--primary fix above. --bronze-ink is the light-background-safe shade
   already used everywhere else this pairing comes up (.eyebrow, links). */
.section--paper .detail__label, .section--alt .detail__label { color: var(--bronze-ink); }
.section--paper .detail__value a, .section--alt .detail__value a { color: var(--ink); }

/* ==========================================================================
   14. FAQ / ACCORDION
   ========================================================================== */

.faq { border-top: 1px solid var(--rule-light); }
.faq__item { border-bottom: 1px solid var(--rule-light); }

.faq__q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  padding: 1.35rem 0;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
  font-family: var(--font-head);
  font-size: clamp(1.15rem, 1.05rem + 0.45vw, 1.4rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
  transition: color 0.25s var(--ease);
}
.faq__q:hover { color: var(--bronze-ink); }

.faq__sign { position: relative; width: 18px; height: 18px; flex: none; }
.faq__sign::before, .faq__sign::after {
  content: "";
  position: absolute;
  background: var(--bronze);
  transition: transform 0.35s var(--ease);
}
.faq__sign::before { inset: 8px 0 auto 0; height: 2px; }
.faq__sign::after  { inset: 0 auto 0 8px; width: 2px; }
.faq__q[aria-expanded="true"] .faq__sign::after { transform: scaleY(0); }

/* Height animation via grid-template-rows so no JS measurement is needed. */
.faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s var(--ease);
}
.faq__item.is-open .faq__a { grid-template-rows: 1fr; }
.faq__a > div { overflow: hidden; }
.faq__a p { padding-bottom: 1.5rem; max-width: 72ch; font-size: 0.9688rem; }

/* ==========================================================================
   15. FOOTER
   ========================================================================== */

.footer { background: var(--char-950); color: rgba(247,246,242,.72); }

.footer__top {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.3fr;
  gap: clamp(2rem, 1.2rem + 3vw, 3.5rem);
  padding-block: clamp(3rem, 2rem + 3.5vw, 5rem);
}
@media (max-width: 980px) { .footer__top { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 560px) { .footer__top { grid-template-columns: minmax(0,1fr); } }

/* Larger here than in the header: the footer has the room, and the badge's
   illustrated detail is the strongest brand asset on the page. */
.footer__logo { height: 104px; width: auto; margin-bottom: 1rem; }

.footer__wordmark {
  display: flex;
  flex-direction: column;
  line-height: 1;
  font-family: var(--font-head);
  text-transform: uppercase;
  color: var(--warm-white);
  margin-bottom: 1.15rem;
}
.footer__wordmark-name { font-size: 1.55rem; font-weight: 700; letter-spacing: 0.05em; }
.footer__wordmark-sub {
  display: flex; align-items: center; gap: 0.5rem; margin-top: 0.35rem;
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.28em; color: var(--bronze);
}
.footer__wordmark-sub::before { content: ""; width: 18px; height: 2px; background: var(--bronze); flex: none; }
.footer__blurb { font-size: 0.9375rem; line-height: 1.75; max-width: 34ch; }

.footer__tagline {
  margin-top: 1.1rem;
  font-family: var(--font-head);
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--bronze);
}

.footer__title {
  font-family: var(--font-head);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--warm-white);
  margin-bottom: 1.15rem;
  padding-bottom: 0.65rem;
  border-bottom: 2px solid var(--bronze);
  display: inline-block;
}

.footer__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }
.footer__list a {
  font-size: 0.9375rem;
  color: rgba(247,246,242,.72);
  text-decoration: none;
  transition: color 0.25s var(--ease), padding-left 0.25s var(--ease);
}
.footer__list a:hover { color: var(--bronze); padding-left: 0.28rem; }

.footer__contact { display: grid; gap: 0.9rem; font-size: 0.9375rem; }
.footer__contact-row { display: grid; grid-template-columns: auto minmax(0,1fr); gap: 0.7rem; align-items: start; }
.footer__contact-row svg { width: 1.05rem; height: 1.05rem; color: var(--bronze); margin-top: 0.32rem; flex: none; }
.footer__contact a {
  color: rgba(247,246,242,.85);
  text-decoration: none;
  /* An email address is a single unbreakable token. At 320px the 30-character
     address is wider than its grid column and pushed the page sideways, so it
     is allowed to break mid-word rather than overflow. */
  overflow-wrap: anywhere;
}
.footer__contact a:hover { color: var(--bronze); }

.footer__cta { margin-top: 1.4rem; }

.footer__bottom {
  border-top: 1px solid var(--rule-dark);
  padding-block: 1.6rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.85rem 1.5rem;
  font-size: 0.8125rem;
}
.footer__legal { display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem; }
.footer__legal a { color: rgba(247,246,242,.6); text-decoration: none; }
.footer__legal a:hover { color: var(--bronze); }

.footer__credit { color: rgba(247,246,242,.55); }
.footer__credit a {
  color: var(--bronze);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease);
}
.footer__credit a:hover { border-bottom-color: var(--bronze); }

/* ==========================================================================
   16. SCROLL REVEAL
   ---------------------------------------------------------------------------
   Scoped to html.js so the page renders fully visible when scripting is off.
   ========================================================================== */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* Stagger children of a revealed group. */
.js [data-reveal-group] > * {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}
.js [data-reveal-group].is-in > * { opacity: 1; transform: none; }
.js [data-reveal-group].is-in > *:nth-child(1) { transition-delay: 0s; }
.js [data-reveal-group].is-in > *:nth-child(2) { transition-delay: .08s; }
.js [data-reveal-group].is-in > *:nth-child(3) { transition-delay: .16s; }
.js [data-reveal-group].is-in > *:nth-child(4) { transition-delay: .24s; }
.js [data-reveal-group].is-in > *:nth-child(5) { transition-delay: .32s; }
.js [data-reveal-group].is-in > *:nth-child(6) { transition-delay: .40s; }
.js [data-reveal-group].is-in > *:nth-child(7) { transition-delay: .48s; }
.js [data-reveal-group].is-in > *:nth-child(8) { transition-delay: .56s; }

/* ==========================================================================
   17. UTILITIES
   ========================================================================== */

.u-center { text-align: center; }
.u-mt-0 { margin-top: 0; }
.u-mt-1 { margin-top: 1rem; }
.u-mt-2 { margin-top: 2rem; }
.u-mt-3 { margin-top: 3rem; }
.u-mb-2 { margin-top: 0; margin-bottom: 2rem; }
.u-maxw { max-width: 62ch; }

/* Bronze rule used as a standalone divider. */
.rule-cut {
  width: 68px;
  height: 3px;
  background: var(--bronze);
  border: 0;
  margin: 0 0 1.5rem;
}
.rule-cut--center { margin-inline: auto; }

/* ==========================================================================
   18. MOTION & PRINT
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Reveal elements must not stay invisible if their transition is nulled. */
  .js [data-reveal],
  .js [data-reveal-group] > * { opacity: 1 !important; transform: none !important; }
  .btn:hover, .svc:hover, .icard:hover { transform: none; }
}

@media print {
  .header, .drawer, .stormbar, .burger, .lightbox, .cta, .footer__cta { display: none !important; }
  body { background: #fff; color: #000; }
  .hero { min-height: auto; padding-top: 2rem; }
  .hero__media, .hero__scrim { display: none; }
  .hero__title, .hero__tagline, .hero__text { color: #000 !important; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; }
}
