/* Melaragno Services — Quiet Confidence homepage (dark-native system)
   Standalone stylesheet: concepts/ archive keeps using common.css untouched. */

/* The display serif is the identity. It was previously a bare system stack
   ("Iowan Old Style", Palatino Linotype, Georgia), which meant only Apple
   visitors ever saw the intended face — Windows fell back to Palatino
   Linotype and Android to Georgia, both materially different. Source Serif 4
   is an open (OFL) humanist serif in the same register, self-hosted as a
   latin-subset variable woff2 so it ships to everyone. font-display: swap
   keeps it off the critical path; the old stack remains the fallback. */
@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("fonts/source-serif-4-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Source Serif 4";
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("fonts/source-serif-4-latin-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Neutrals */
  --bg: #121310;
  --surface-1: #1b1d18;
  --surface-2: #23261f;
  --ink: #f2efe8;
  --muted: #b8b4a8;
  --line: rgba(242, 239, 232, 0.14);
  --line-strong: rgba(242, 239, 232, 0.28);

  /* Light proof section */
  --paper: #ece7dc;
  --paper-ink: #161713;
  --paper-muted: #5d594e;

  /* Accent — quiet rosewood pink (white text ≈ 5.9:1) */
  --accent: #b0356a;
  --accent-hover: #c14079;
  --accent-tint: #e0578f;
  /* Photo-safe tint of the accent, for text set over imagery. See .hero h1 em. */
  --accent-hero: #f2a8c4;
  --accent-soft: rgba(224, 87, 143, 0.13);
  /* Section-ground washes. Previously six hand-typed alphas (.05 .055 .09
     .10 .12 .14) across home.css and page.css doing one job at values nobody
     chose twice. Two steps is the whole vocabulary. */
  --accent-wash: rgba(224, 87, 143, 0.06);
  --accent-wash-strong: rgba(224, 87, 143, 0.12);

  /* Type */
  --font-display:
    "Source Serif 4", "Iowan Old Style", "Palatino Linotype", Palatino,
    Georgia, serif;
  --font-body:
    ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial,
    sans-serif;
  --fs-h1: clamp(2.9rem, 6.5vw, 5.4rem);
  --fs-h2: clamp(2rem, 4.2vw, 3.3rem);
  --fs-quote: clamp(1.7rem, 3.6vw, 2.9rem);
  --fs-body: 1.05rem;

  /* Rhythm */
  --space-section: clamp(4.5rem, 9vw, 7.5rem);

  /* Shape + elevation */
  --radius-card: 14px;
  --radius-field: 8px;
  --radius-pill: 999px;
  --shadow-1: 0 8px 24px rgba(0, 0, 0, 0.35);
  --shadow-2: 0 18px 50px rgba(0, 0, 0, 0.5);
  --glow-accent: 0 10px 30px rgba(176, 53, 106, 0.32);

  /* Motion */
  --dur-fast: 160ms;
  --dur-mid: 260ms;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

* {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img {
  display: block;
  max-width: 100%;
}
a {
  color: inherit;
}
button,
input,
select,
textarea {
  font: inherit;
}
a,
button {
  touch-action: manipulation;
}

.wrap {
  width: min(1180px, calc(100% - 40px));
  margin-inline: auto;
}

.skip {
  position: fixed;
  left: 12px;
  top: -60px;
  z-index: 99;
  background: #fff;
  color: #111;
  padding: 12px 16px;
  border-radius: var(--radius-field);
}
.skip:focus {
  top: 12px;
}

:focus-visible {
  outline: 3px solid #ffbf47;
  outline-offset: 3px;
}

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 40;
  padding: 12px 0;
  color: #fff;
  background: linear-gradient(rgba(0, 0, 0, 0.55), transparent);
  transition:
    background var(--dur-mid) var(--ease),
    box-shadow var(--dur-mid) var(--ease),
    padding var(--dur-mid) var(--ease);
}
.site-header.scrolled {
  background: rgba(18, 19, 16, 0.88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow:
    0 1px 0 var(--line),
    var(--shadow-1);
  padding: 10px 0;
}
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
}
.brand {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 2vw, 2rem);
  line-height: 0.95;
  font-weight: 700;
  letter-spacing: 0;
  text-decoration: none;
  transition: font-size var(--dur-mid) var(--ease);
}
.brand span {
  color: var(--accent-tint);
}
.brand-logo {
  display: inline-flex;
  width: 154px;
  height: 60px;
  flex: 0 0 auto;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 7px;
  background: #fff;
}
.brand-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.site-header.scrolled .brand-logo {
  width: 142px;
  height: 55px;
}
.footer-logo,
.site-header.scrolled .footer-logo {
  width: 180px;
  height: 70px;
}
.site-header.scrolled .brand {
  font-size: 1.6rem;
}
.navlinks {
  display: flex;
  align-items: center;
  gap: 26px;
}
.navlinks a {
  text-decoration: none;
  font-weight: 600;
  font-size: 0.92rem;
  opacity: 0.92;
  transition: opacity var(--dur-fast) var(--ease);
}
.navlinks a:hover {
  opacity: 1;
}
.navlinks a:not(.button)::after {
  content: "";
  display: block;
  height: 1px;
  margin-top: 2px;
  background: var(--accent-tint);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-mid) var(--ease);
}
.navlinks a:not(.button):hover::after {
  transform: scaleX(1);
}
.navlinks a[aria-current="page"]::after {
  transform: scaleX(1);
}

.mobile-toggle {
  display: none;
  color: #fff;
  background: rgba(18, 19, 16, 0.6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-field);
  min-width: 48px;
  min-height: 48px;
  cursor: pointer;
}

/* ---------- Buttons ---------- */
.button {
  display: inline-flex;
  min-height: 52px;
  align-items: center;
  justify-content: center;
  padding: 0 26px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  text-decoration: none;
  font-weight: 700;
  cursor: pointer;
  color: inherit;
  background: transparent;
  transition:
    transform var(--dur-fast) var(--ease),
    box-shadow var(--dur-mid) var(--ease),
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.button:hover {
  transform: translateY(-2px);
  border-color: var(--ink);
}
.button:active {
  transform: translateY(0);
}
.button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.button.primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  box-shadow: var(--glow-accent);
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--muted);
  margin: 0 0 14px;
}

.section {
  padding: var(--space-section) 0;
}

/* This band measured 421px tall against 240px of padding — 57% air, the one
   section on the page with room to do real work and nothing in it. The uniform
   --space-section is right for content-dense bands and wrong here; this one
   gets its own reduced rhythm, and the county list below gives it a payload. */
.area-summary {
  padding: clamp(3.25rem, 6vw, 5rem) 0;
  border-block: 1px solid var(--line);
  background:
    linear-gradient(110deg, var(--accent-wash-strong), transparent 48%),
    var(--bg);
}
.area-summary .section-split {
  align-items: start;
}
.county-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  margin: 30px 0 0;
  padding: 0;
  list-style: none;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
}
.county-strip li {
  background: var(--surface-1);
  padding: 18px 20px;
}
.county-strip .county-name {
  display: block;
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.1;
}
.county-strip .county-count {
  display: block;
  margin-top: 6px;
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---------- Work in motion (video) ---------- */
.filmstrip {
  border-block: 1px solid var(--line);
  background:
    linear-gradient(200deg, var(--accent-wash), transparent 46%),
    var(--surface-1);
}
.film-group {
  margin-top: clamp(40px, 6vw, 68px);
  padding-top: 28px;
  border-top: 1px solid var(--line);
}
.film-group-heading {
  display: grid;
  grid-template-columns: minmax(180px, 0.42fr) minmax(280px, 0.58fr);
  gap: clamp(24px, 5vw, 64px);
  align-items: baseline;
  max-width: 820px;
}
.film-group-heading h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.5vw, 2rem);
  font-weight: 400;
  line-height: 1.1;
}
.film-group-heading p {
  margin: 0;
  color: var(--muted);
  font-size: 0.95rem;
}
.film-row {
  display: grid;
  align-items: start;
  gap: clamp(18px, 2.4vw, 28px);
  margin-top: clamp(20px, 2.6vw, 32px);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}
/* Was capped at 820px in a 1180px wrap — left-aligned, ~360px of empty
   space to the right. This group has exactly one card; let it fill the
   row like every other wide card on the page instead of an artificial cap. */
.film-row.is-feature-row {
  grid-template-columns: minmax(0, 1fr);
}
.film-row.is-tall-row {
  grid-template-columns: repeat(2, minmax(230px, 320px));
  justify-content: center;
  align-items: stretch;
}
.film-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--line);
  border-top: 2px solid var(--accent);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-1);
}
.film-card video {
  display: block;
  width: 100%;
  height: auto;
  background: #000;
  object-fit: cover;
}
.film-card.is-wide video {
  aspect-ratio: 16 / 9;
}
.film-card.is-tall video {
  aspect-ratio: 9 / 16;
}
.film-card.focus-active video {
  object-position: 50% 50%;
}
.film-card.focus-protection video {
  object-position: 50% 52%;
}
.film-card.focus-interior video {
  object-position: 50% 50%;
}
.film-card.focus-truck video {
  object-position: 50% 48%;
}
.film-card.focus-snow video {
  object-position: 50% 46%;
}
.film-meta {
  flex: 1;
  padding: 16px 20px 20px;
}
.film-meta h4 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.3rem;
  line-height: 1.15;
  margin: 8px 0 6px;
}
.film-meta p {
  margin: 0;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.55;
}
.film-kicker {
  display: block;
  color: var(--accent-tint);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* The hero photograph is a real client property and gets no credit for it.
   Labelling media as a real job is the cheapest available answer to the
   "is this stock?" reflex every contractor site fights. Desktop only —
   at phone widths it competes with the footage itself. */
/* No backdrop-filter here. A blurred layer positioned directly over a
   <video> element is a known WebKit compositing problem — Safari can fail
   to paint the video (and its native controls) underneath a blur layer
   stacked on top of it. This tag only ever sits over the poster/first
   frame, not moving content, so a solid chip reads just as clearly without
   the blur and doesn't risk the video's own render layer. */
.media-tag {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  max-width: 60%;
  padding: 9px 14px;
  border-radius: var(--radius-field);
  background: rgba(15, 16, 13, 0.92);
  border: 1px solid var(--line-strong);
  font-size: 0.8rem;
  line-height: 1.35;
}
.media-tag span {
  display: block;
  color: var(--accent-tint);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.film-provenance {
  margin: 28px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.85rem;
  max-width: 70ch;
}

.section-split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, 0.85fr);
  gap: clamp(36px, 7vw, 84px);
  align-items: center;
}

.section-split h2 {
  margin-bottom: 0;
}

.section-split p {
  color: var(--muted);
}
.section h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h2);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 22px;
  text-wrap: balance;
}
.section-lede {
  max-width: 620px;
  color: var(--muted);
  margin: 0 0 40px;
}

/* ---------- Hero ---------- */
.hero {
  /* The 640px floor keeps the composition complete on short desktop screens,
     while 92svh gives taller screens a fuller cinematic hero and leaves only a
     narrow next-section cue at the fold. */
  min-height: max(640px, 92svh);
  display: grid;
  align-items: end;
  position: relative;
  background-color: var(--bg);
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  /* Frame cut from the drone flyover in #in-motion — the same finished roof
     the visitor sees moving further down the page. Replaces the old angled
     aerial (hero-aerial-1600.jpg, 270KB served to every viewport). */
  background-image: url("hero-drone-1600.jpg");
}
@supports (
  background-image: image-set(url("hero-drone-1600.avif") type("image/avif"))
) {
  .hero {
    background-image: image-set(
      url("hero-drone-1600.avif") type("image/avif"),
      url("hero-drone-1600.jpg") type("image/jpeg")
    );
  }
}
/* A 16:9 frame cropped to a 390px-wide portrait viewport throws away most of
   its pixels and upscales the rest. The mobile variant is cut portrait from
   the same frame — 77KB AVIF against the 270KB every phone used to download. */
@media (max-width: 760px) {
  .hero {
    background-image: url("hero-drone-760.jpg");
  }
  @supports (
    background-image: image-set(url("hero-drone-760.avif") type("image/avif"))
  ) {
    .hero {
      background-image: image-set(
        url("hero-drone-760.avif") type("image/avif"),
        url("hero-drone-760.jpg") type("image/jpeg")
      );
    }
  }
}

.hero-media,
.hero-scrim {
  position: absolute;
  inset: 0;
}
.hero-media {
  z-index: 0;
  overflow: hidden;
}
.hero-video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  background: transparent;
  transition: opacity 420ms var(--ease);
}
.hero.is-video-playing .hero-video {
  opacity: 1;
}
.hero.is-poster-only .hero-video {
  display: none;
}
/* The 0%/46% vertical stops were sampled against every frame of the looping
   hero video (not just the poster), text glyph extents measured via
   Range.getClientRects() rather than each paragraph's full block width.
   The eyebrow and tagline both dipped below their WCAG minimum for a few
   frames around the drone's pan across bright siding (worst observed:
   eyebrow 3.93:1 vs 4.5 needed, tagline 2.63:1 vs 3.0). These two stops
   raised from .24/.10 clear every sampled frame with margin (worst case
   now 4.84:1 and 3.18:1) without visibly flattening the footage — verify
   any future scrim change the same way, against playback, not a still. */
.hero-scrim {
  z-index: 1;
  background:
    linear-gradient(
      180deg,
      rgba(0, 0, 0, 0.4) 0%,
      rgba(0, 0, 0, 0.2) 46%,
      rgba(18, 19, 16, 0.9) 100%
    ),
    linear-gradient(
      90deg,
      rgba(0, 0, 0, 0.72) 0%,
      rgba(0, 0, 0, 0.3) 56%,
      rgba(0, 0, 0, 0.04) 84%
    );
  pointer-events: none;
}
/* Always rendered — not just a failure fallback — per WCAG 2.2.2. Icon-only
   so a permanent control doesn't compete with the hero copy; aria-label
   carries the full "Play/Pause background video" state for AT users. */
.hero-video-play {
  position: absolute;
  right: 22px;
  bottom: 22px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(242, 239, 232, 0.58);
  border-radius: 50%;
  color: var(--ink);
  background: rgba(18, 19, 16, 0.72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.hero-video-play:hover {
  background: rgba(18, 19, 16, 0.88);
  border-color: var(--ink);
}
.hero-video-play [data-hero-play-icon] {
  transform: translateX(1px);
}
.hero-video-play[aria-pressed="true"] [data-hero-play-icon] {
  transform: none;
  font-size: 0.75rem;
  letter-spacing: 1px;
}
.hero-content {
  position: relative;
  z-index: 2;
  /* Trimmed from 150/90. The hero is taller than its own min-height because the
     content drives it, so the padding is what actually decides how much of the
     services grid clears the fold. Still clears the ~72px fixed header. */
  padding: 128px 0 72px;
}
.hero .eyebrow {
  color: rgba(242, 239, 232, 0.85);
}
.hero h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--fs-h1);
  line-height: 1.02;
  letter-spacing: -0.02em;
  max-width: 820px;
  margin: 10px 0 4px;
  text-wrap: balance;
}
.hero-tagline {
  max-width: 760px;
  margin: 0 0 22px;
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 4.4vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  font-style: italic;
  color: var(--accent-hero);
  text-wrap: balance;
}
.hero-sub {
  font-size: 1.13rem;
  max-width: 580px;
  margin: 0;
  color: rgba(242, 239, 232, 0.92);
}
.actions {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  /* The 26px bottom margin used to live here for the hero, where .glass-proof
     follows — everywhere else it was dead space that page.css zeroed out in
     six separate rules. When six consumers patch a base rule, the base rule is
     wrong. It now belongs to the hero, which is the only place that wants it. */
  margin: 30px 0 0;
}
.hero .actions {
  margin-bottom: 26px;
}

/* The 0.28 line token is fine for dividers on flat dark ground, but the hero's
   ghost button sits on photography: sampled around its outline, 100% of points
   fell below the 3:1 that WCAG 1.4.11 requires for a control boundary, and it
   visibly dissolved against the white clapboard. It now carries its own
   backdrop instead of borrowing the photo's. */
.hero .button:not(.primary) {
  border-color: rgba(242, 239, 232, 0.5);
  background: rgba(18, 19, 16, 0.38);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.hero .button:not(.primary):hover {
  border-color: var(--ink);
  background: rgba(18, 19, 16, 0.55);
}

.glass-proof {
  display: inline-flex;
  gap: 10px 26px;
  flex-wrap: wrap;
  align-items: center;
  background: rgba(18, 19, 16, 0.55);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 14px 26px;
  font-size: 0.92rem;
  font-weight: 600;
}
.glass-proof a {
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  /* Was a 21px-tall inline link — and it is the fold's only route to
     independent verification, for an audience skewing older. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.glass-proof .stars {
  color: #f2bd48;
  letter-spacing: 0.08em;
  margin-right: 6px;
}
.glass-proof .sep {
  opacity: 0.35;
}

.scroll-cue {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin-top: 22px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: rgba(242, 239, 232, 0.75);
  transition: color var(--dur-fast) var(--ease);
}
.scroll-cue:hover {
  color: var(--ink);
}
.scroll-cue svg {
  transition: transform var(--dur-mid) var(--ease);
}
.scroll-cue:hover svg {
  transform: translateY(3px);
}

/* ---------- Service cards ---------- */
.cards {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
}
.cards .card {
  grid-column: span 2;
}
.card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  text-decoration: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
  transition:
    transform var(--dur-mid) var(--ease),
    border-color var(--dur-mid) var(--ease),
    box-shadow var(--dur-mid) var(--ease);
}
.card:hover {
  transform: translateY(-4px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-1);
}
.card img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-bottom: 1px solid var(--line);
  filter: saturate(0.85) contrast(1.04);
  transition:
    transform 500ms var(--ease),
    filter var(--dur-mid) var(--ease);
}
.card:hover img {
  transform: scale(1.035);
  filter: saturate(1) contrast(1.04);
}
.card-image-exterior {
  object-position: 50% 12%;
}
.card-image-window {
  object-position: 50% 38%;
}
.card-image-gutters {
  object-position: 50% 68%;
}
.card-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: 24px 22px;
}
.card-kicker {
  color: var(--accent-tint);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
/* One card-heading rule. .step h3 previously rendered 17.3px sans (it omitted
   --font-display) and .storm-card h3 had no rule at all, so it fell through to
   the UA default at 19.7px sans — both outranked visually by .owner-identity
   strong (20.8px serif) and .worklist strong (18.4px serif). Real headings
   were reading as sub-body text while bold body text read as headings. */
.card h3,
.step h3,
.storm-card h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.4rem;
  line-height: 1.15;
  margin: 10px 0;
}
.card p {
  margin: 0;
  color: var(--muted);
  font-size: 0.98rem;
}
.card-link {
  display: inline-block;
  margin-top: auto;
  padding-top: 20px;
  color: var(--ink);
  font-size: 0.86rem;
  font-weight: 700;
}

/* ---------- Work / chapters ---------- */
.chapters {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: center;
}
.chapters img {
  width: 100%;
  height: 610px;
  object-fit: cover;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-2);
}
.worklist {
  list-style: none;
  margin: 26px 0 30px;
  padding: 0;
  display: grid;
  gap: 0;
}
.worklist li {
  padding: 16px 0;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 4px;
}
.worklist li:last-child {
  border-bottom: 1px solid var(--line);
}
.worklist strong {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.15rem;
}
.worklist span {
  color: var(--muted);
  font-size: 0.96rem;
}
.text-link {
  font-weight: 700;
  text-underline-offset: 5px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-fast) var(--ease);
}
.text-link:hover {
  color: var(--accent-tint);
}

/* ---------- Storm band ---------- */
.storm {
  background: var(--surface-1);
  border-block: 1px solid var(--line);
}
.storm-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 70px;
  align-items: start;
}
.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}
.checklist li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.checklist svg {
  flex: none;
  margin-top: 4px;
  color: var(--accent-tint);
}
.storm-card {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 30px;
  box-shadow: var(--shadow-1);
}
.storm-card p {
  color: var(--muted);
}

/* ---------- Process ---------- */
.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  counter-reset: step;
}
.step {
  counter-increment: step;
  position: relative;
  padding: 30px 26px 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
}
.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-display);
  font-size: 2.4rem;
  line-height: 1;
  color: var(--accent-tint);
  display: block;
  margin-bottom: 16px;
}
.step h3 {
  margin: 0 0 8px;
}
.step p {
  margin: 0;
  color: var(--muted);
  font-size: 0.97rem;
}

/* ---------- Owner band ---------- */
/* #process and #owner both measured #121310, so the only thing separating them
   was a 1px line with 240px of unbroken dark between the last process card and
   the owner block — read as a page break, not a section change. A 5% accent
   wash on near-black is imperceptible; --surface-1 gives it a real ground. */
.owner {
  border-top: 1px solid var(--line);
  background:
    linear-gradient(135deg, var(--accent-wash), transparent 42%),
    var(--surface-1);
}
.owner-profile {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 70px;
  align-items: center;
}
.owner-media {
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-1);
  box-shadow: var(--shadow-2);
}
.owner-media img {
  width: 100%;
  height: auto;
  aspect-ratio: 28 / 15;
  object-fit: cover;
  object-position: center;
  filter: saturate(0.9) contrast(1.04);
}
.owner-media figcaption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 18px 20px;
  border-top: 1px solid var(--line);
}
.owner-identity {
  display: grid;
  gap: 1px;
}
.owner-identity strong {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 400;
}
.owner-identity span,
.owner-media figcaption a,
.owner-family-caption {
  color: var(--muted);
  font-size: 0.78rem;
}
.owner-media figcaption a {
  text-align: right;
  text-underline-offset: 4px;
}
.owner-family-caption {
  text-align: right;
}
.owner-story h2 {
  max-width: 540px;
}
.owner-story > p:not(.eyebrow) {
  max-width: 590px;
  color: var(--muted);
}
.owner-story > p.owner-lede {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2vw, 1.65rem);
  line-height: 1.35;
}
.owner-actions {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  margin-top: 30px;
}
.cred-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
.cred-list li {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.97rem;
}
.cred-list > li > span:first-child {
  color: var(--muted);
}
.cred-list > li > span:last-child {
  font-weight: 700;
  text-align: right;
}
.cred-list .manufacturer-credentials {
  display: grid;
  gap: 8px;
}
.credential-stack {
  display: grid;
  gap: 5px;
  justify-items: end;
  text-align: right;
}
.credential-stack > span,
.credential-stack a {
  color: var(--ink);
}
.credential-stack a {
  display: inline-grid;
  gap: 2px;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent-tint) 72%, transparent);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.credential-stack a:hover,
.credential-stack a:focus-visible {
  color: var(--accent-tint);
}
.cred-list .credential-stack .credential-link-note {
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.35;
  text-align: inherit;
  text-decoration: none;
}
.owner-credentials {
  grid-template-columns: repeat(3, 1fr);
  gap: 0 30px;
  margin-top: 54px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

/* ---------- Reviews (light) ---------- */
.reviews {
  background: var(--paper);
  color: var(--paper-ink);
}
.reviews .eyebrow {
  color: var(--paper-muted);
}
.review-heading {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 32px;
  align-items: end;
  margin-bottom: 38px;
}
.review-heading h2 {
  max-width: 760px;
  margin-bottom: 0;
}
.review-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.review-card {
  min-height: 260px;
  display: flex;
  flex-direction: column;
  padding: 22px;
  border: 1px solid rgba(22, 23, 19, 0.13);
  border-radius: var(--radius-card);
  background: rgba(255, 255, 255, 0.5);
  box-shadow: 0 14px 40px rgba(22, 23, 19, 0.055);
}
.review-card::before {
  content: "";
  width: 36px;
  height: 2px;
  margin-bottom: 18px;
  background: #b7892f;
}
.review-card-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
  align-items: center;
}
.review-avatar {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--paper-ink);
  color: var(--paper);
  font-weight: 800;
  font-size: 0.74rem;
  letter-spacing: 0.05em;
}
.review-person {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.review-card-head strong {
  font-size: 0.94rem;
}
.review-card-head a,
.review-card-head div span {
  color: var(--paper-muted);
  font-size: 0.75rem;
  line-height: 1.35;
}
/* --pink is a common.css token and common.css is the concepts archive, which
   production never loads. The undefined var made this outline shorthand
   invalid at computed-value time, so all three longhands reset and
   outline-style became none — and because this selector out-specifies the
   global :focus-visible, these six review links had no focus indicator at
   all (WCAG 2.4.7). --accent is the on-paper accent and clears 5.89:1 here. */
.review-card-head a:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
.review-card-meta {
  min-height: 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(22, 23, 19, 0.11);
  color: var(--paper-muted);
  font-size: 0.75rem;
  line-height: 1.35;
}
.review-card-meta time {
  text-align: right;
}
.review-stars {
  /* Was #a87308, which measured 3.33:1 on the #ece7dc review card and failed
     WCAG AA. The rating is conveyed by text characters, so it is held to the
     4.5:1 body-text threshold rather than the 3:1 graphics one. #845b05 is
     4.89:1 and still reads as gold. */
  color: #845b05;
  font-size: 0.86rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.review-card blockquote {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.12rem, 1.5vw, 1.34rem);
  line-height: 1.32;
  letter-spacing: -0.01em;
  margin: 22px 0 4px;
}
.reviews .button.dark {
  background: var(--paper-ink);
  border-color: var(--paper-ink);
  color: var(--paper);
}
.reviews .button.dark:hover {
  box-shadow: 0 12px 30px rgba(22, 23, 19, 0.25);
}

/* ---------- FAQ ---------- */
.faq-list {
  display: grid;
  gap: 0;
  max-width: 860px;
}
.faq-list details {
  border-top: 1px solid var(--line);
}
.faq-list details:last-child {
  border-bottom: 1px solid var(--line);
}
.faq-list summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  align-items: center;
  padding: 22px 4px;
  font-weight: 700;
  font-size: 1.05rem;
  transition: color var(--dur-fast) var(--ease);
}
.faq-list summary::-webkit-details-marker {
  display: none;
}
.faq-list summary:hover {
  color: var(--accent-tint);
}
.faq-list summary .indicator {
  flex: none;
  width: 28px;
  height: 28px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-weight: 400;
  transition:
    transform var(--dur-mid) var(--ease),
    background var(--dur-fast) var(--ease);
}
.faq-list details[open] summary .indicator {
  transform: rotate(45deg);
  background: var(--accent-soft);
  border-color: var(--accent-tint);
}
.faq-list details p {
  margin: 0 0 24px;
  padding: 0 44px 0 4px;
  color: var(--muted);
  max-width: 720px;
}

/* ---------- Quote / form ---------- */
.quote-zone {
  background: var(--surface-1);
  border-top: 1px solid var(--line);
}
.quote-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: 70px;
  align-items: start;
}
.quote-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.quote-form label {
  font-weight: 700;
  font-size: 0.86rem;
}
.quote-form input,
.quote-form select,
.quote-form textarea {
  width: 100%;
  min-height: 52px;
  margin-top: 6px;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-field);
  background: var(--bg);
  color: var(--ink);
  transition:
    border-color var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}
.quote-form input:focus,
.quote-form select:focus,
.quote-form textarea:focus {
  border-color: var(--accent-tint);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}
.quote-form textarea {
  min-height: 120px;
  resize: vertical;
}
.quote-form .full {
  grid-column: 1 / -1;
}
.form-status {
  min-height: 24px;
  font-weight: 700;
  color: var(--accent-tint);
}
.form-note {
  margin: 0;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.55;
}
.form-honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.quote-alt {
  color: var(--muted);
  font-size: 0.95rem;
}
.quote-alt a {
  font-weight: 700;
  color: var(--ink);
}
/* Four fields were `required` with nothing saying so — the only signal was
   native validation firing after a failed submit. The two optional fields
   were already labelled, so the asterisk completes a pattern that was
   half-built. Marks are aria-hidden; the inputs keep their own `required`. */
.form-legend {
  margin: 0 0 4px;
  color: var(--muted);
  font-size: 0.85rem;
}
.req {
  color: var(--accent-tint);
  font-weight: 700;
}

/* ---------- Footer ---------- */
/* The 110px bottom padding was call-bar clearance, but .call-bar is
   display:none until the 760px breakpoint — so every desktop page carried
   110px of unexplained empty space below the footer. Clearance now lives
   with the call bar. */
.site-footer {
  padding: 64px 0;
  border-top: 1px solid var(--line);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: 40px;
  margin-bottom: 44px;
}
.footer-grid h3 {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  margin: 0 0 16px;
}
.footer-grid ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
  font-size: 0.96rem;
}
.footer-grid a {
  text-decoration: none;
}
.footer-grid a:hover {
  text-decoration: underline;
  text-underline-offset: 4px;
}
.footer-brand p {
  color: var(--muted);
  max-width: 300px;
  margin: 12px 0 0;
  font-size: 0.96rem;
}
.footer-bottom {
  border-top: 1px solid var(--line);
  padding-top: 24px;
  color: var(--muted);
  font-size: 0.85rem;
}

/* ---------- Sticky mobile call bar ---------- */
.call-bar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 50;
  display: none;
  align-items: center;
  gap: 12px;
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: rgba(18, 19, 16, 0.92);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--line);
  transform: translateY(110%);
  transition: transform var(--dur-mid) var(--ease);
}
.call-bar.visible {
  transform: translateY(0);
}
.call-bar .button {
  flex: 1;
  min-height: 48px;
}
.call-bar .text-link {
  flex: none;
  font-size: 0.9rem;
}

/* ---------- Reveal ---------- */
.js .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 600ms var(--ease),
    transform 600ms var(--ease);
}
.js .reveal.in {
  opacity: 1;
  transform: none;
}

/* ---------- Responsive ---------- */

/* Short desktop viewports: 1280x800, 1366x768 and the 13-14" laptop sizes.
   The constraint here is height, not width, so this is keyed to height —
   at 1280x800 the hero measured 815px against an 800px viewport and the
   services grid sat just under the fold, which is the exact problem the
   hero-height work was meant to solve.

   Tall viewports (900px+) never enter this block and keep their own tuning.
   Reducing the display size by viewport height is the same idea as the
   existing clamp() on --fs-h1, keyed to the axis that actually binds. */
@media (min-width: 981px) and (max-height: 860px) {
  .hero-content {
    /* 112 rather than 96: at 96 the eyebrow cleared the fixed header by only
       12px and read as crowding it. 112 keeps ~28px and still leaves the
       services grid well clear of the fold. */
    padding: 112px 0 52px;
  }
  .hero h1 {
    font-size: clamp(2.6rem, 5.4vw, 4.2rem);
    margin: 8px 0 2px;
  }
  .hero-tagline {
    margin-bottom: 18px;
    font-size: clamp(2rem, 4vw, 3.35rem);
  }
  .scroll-cue {
    margin-top: 20px;
  }
}

/* Nav collapsed to a hamburger at 1060px, which caught iPad landscape and
   several common laptop widths — five links, a phone number and one button
   that fit comfortably. The compression rule below already existed to handle
   tight-but-workable widths; it now covers 901–1240 instead of 1061–1240, and
   the hamburger starts at 900. */
@media (min-width: 901px) and (max-width: 1240px) {
  .navlinks {
    gap: 18px;
  }
  .navlinks a {
    font-size: 0.88rem;
  }
  .navlinks .button {
    padding-inline: 20px;
  }
}
@media (max-width: 1060px) {
  .review-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 900px) {
  .mobile-toggle {
    display: block;
  }
  .navlinks {
    display: none;
    position: absolute;
    top: 72px;
    left: 14px;
    right: 14px;
    max-height: calc(100dvh - 88px);
    overflow-y: auto;
    background: rgba(18, 19, 16, 0.97);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-2);
    padding: 18px;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
  }
  .navlinks.open {
    display: flex;
  }
  .navlinks a {
    padding: 12px 6px;
  }
  .navlinks .button {
    width: 100%;
    margin-top: 10px;
  }
}
@media (max-width: 980px) {
  .review-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .cards {
    grid-template-columns: 1fr 1fr;
  }
  .cards .card {
    grid-column: auto;
  }
  .steps {
    grid-template-columns: 1fr;
  }
  .chapters,
  .storm-grid,
  .owner-profile,
  .quote-grid,
  .section-split {
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .owner-credentials {
    grid-template-columns: 1fr 1fr;
  }
  .chapters img {
    height: 420px;
  }
  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 760px) {
  /* Small-label floor — see the matching block in page.css. The service card
     kickers ("Roofing", "Emergency response", "Drainage") were the worst
     offenders at 11.2px. Mobile only; the desktop scale is untouched. */
  .eyebrow,
  .card-kicker,
  .story-meta dt,
  .review-card-meta,
  .review-stars {
    font-size: 0.8125rem;
  }

  .brand-logo,
  .site-header.scrolled .brand-logo {
    width: 126px;
    height: 49px;
  }
  .wrap {
    width: min(1180px, calc(100% - 32px));
  }
  .brand {
    font-size: 1.55rem;
  }
  .site-header.scrolled .brand {
    font-size: 1.55rem;
  }
  .mobile-toggle {
    display: block;
  }
  .navlinks {
    display: none;
    position: absolute;
    top: 68px;
    left: 14px;
    right: 14px;
    background: #17181422;
    background: rgba(18, 19, 16, 0.97);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-2);
    padding: 18px;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
  }
  .navlinks.open {
    display: flex;
  }
  .navlinks a {
    padding: 12px 6px;
  }
  .navlinks .button {
    width: 100%;
    margin-top: 10px;
  }

  .hero {
    min-height: 100svh;
  }
  .hero-scrim {
    background:
      linear-gradient(
        180deg,
        rgba(0, 0, 0, 0.16) 0%,
        rgba(0, 0, 0, 0.1) 34%,
        rgba(0, 0, 0, 0.66) 64%,
        rgba(18, 19, 16, 0.96) 100%
      ),
      linear-gradient(
        90deg,
        rgba(0, 0, 0, 0.56) 0%,
        rgba(0, 0, 0, 0.12) 76%,
        transparent 100%
      );
  }
  .hero-content {
    padding: 96px 0 28px;
  }
  .hero-content > div {
    max-width: 350px;
  }
  .hero .eyebrow,
  .hero-tagline,
  .hero-secondary,
  .glass-proof .hero-credential,
  .glass-proof .sep,
  .scroll-cue {
    display: none;
  }
  .hero h1 {
    max-width: 330px;
    margin: 0 0 14px;
    font-size: clamp(2.45rem, 10.8vw, 2.8rem);
    line-height: 0.98;
  }
  .hero-sub {
    max-width: 330px;
    font-size: 1rem;
    line-height: 1.45;
  }
  .hero .actions {
    margin: 18px 0 14px;
  }
  .actions .button {
    width: 100%;
  }
  .glass-proof {
    padding: 3px 14px;
    border-radius: var(--radius-pill);
    font-size: 0.8rem;
    gap: 0;
  }
  .hero-video-play {
    right: 16px;
    bottom: 16px;
    max-width: 154px;
  }

  .cards {
    grid-template-columns: 1fr;
  }
  .cards .card,
  .cards .card:last-child:nth-child(odd) {
    grid-column: auto;
  }
  .chapters img {
    height: 340px;
  }
  .chapters > div:last-child {
    order: -1;
  }
  .review-heading {
    grid-template-columns: 1fr;
  }
  .review-grid {
    grid-template-columns: 1fr;
  }
  .owner-media figcaption {
    align-items: flex-start;
    flex-direction: column;
    gap: 10px;
  }
  .owner-media figcaption a {
    text-align: left;
  }
  .owner-family-caption {
    text-align: left;
  }
  .credential-stack {
    justify-items: start;
    text-align: left;
  }
  .owner-actions .button {
    width: 100%;
  }
  .owner-credentials {
    grid-template-columns: 1fr;
    margin-top: 40px;
  }
  .review-heading {
    align-items: start;
  }
  .review-heading .button {
    width: 100%;
  }
  .review-card {
    min-height: 260px;
  }
  .quote-form {
    grid-template-columns: 1fr;
  }
  .quote-form .full {
    grid-column: auto;
  }
  .footer-grid {
    grid-template-columns: 1fr;
  }
  .call-bar {
    display: flex;
  }
  /* Clearance belongs here, with the bar it clears. */
  .site-footer {
    padding-bottom: 110px;
  }
  .media-tag {
    display: none;
  }
  .film-group-heading,
  .film-row.is-feature-row,
  .film-row.is-tall-row {
    grid-template-columns: 1fr;
  }
  .film-row.is-tall-row {
    width: 100%;
    justify-content: center;
    justify-items: center;
  }
  .film-group-heading {
    gap: 8px;
  }
  /* A 9:16 clip at full phone width is ~690px tall and swallows the screen. */
  .film-card.is-tall {
    max-width: min(78vw, 330px);
    margin-inline: auto;
  }
}

@media (max-width: 760px) and (min-height: 760px) {
  .hero {
    min-height: calc(100svh - 64px);
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
    animation: none !important;
    transition: none !important;
  }
  .js .reveal {
    opacity: 1;
    transform: none;
  }
}

/* Project stories (section is scaffolded in index.html, disabled until
   David's photos + approvals arrive; these rules are inert until then).
   Story cards inherit .cards/.card layout across all breakpoints. */
.story-meta {
  margin: 0;
  display: grid;
  gap: 2px;
}
.story-meta dt {
  color: var(--accent-tint);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-top: 10px;
}
.story-meta dd {
  margin: 0;
  color: var(--muted);
  font-size: 0.98rem;
}
