/* ==========================================================================
   Rick Ross Exteriors — design system
   Palette pulled from Rick's own job photos: charcoal architectural shingle,
   Lowcountry siding, pine, and the crimson from the eagle wordmark.
   Textures are all CSS/SVG — no image requests, nothing to go stale.
   ========================================================================== */

:root {
  /* --- ink & ground ------------------------------------------------- */
  --ink:        #14202b;   /* near-black slate, from the shingle shadow */
  --ink-2:      #22323f;
  --ink-3:      #46596a;
  --muted:      #6d7f8d;
  --line:       #d8dee3;
  --line-soft:  #e8edf0;
  --paper:      #ffffff;
  --paper-2:    #f6f7f5;   /* warm off-white, siding */
  --paper-3:    #eceeea;

  /* --- brand -------------------------------------------------------- */
  /* Carmine, not fire-engine. There is blue in it, so it sits with the
     graphite instead of shouting over it. Rick's mark keeps its own red. */
  --crimson:    #9e1a26;
  --crimson-d:  #7a111b;
  --crimson-lt: #b3232f;
  --graphite:   #3c4a55;   /* weathered-wood shingle */
  --graphite-d: #2a343d;
  --pine:       #24402f;   /* Lowcountry green */
  --copper:     #a8622c;   /* brick / cedar accent */
  --sand:       #d9cdb8;

  /* --- type --------------------------------------------------------- */
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --serif: "Lora", Georgia, "Times New Roman", serif;

  /* fluid scale — mobile first, no media query needed to grow */
  --t-xs:   0.78rem;
  --t-sm:   0.9rem;
  --t-base: clamp(1rem, 0.97rem + 0.15vw, 1.075rem);
  --t-lg:   clamp(1.14rem, 1.05rem + 0.4vw, 1.35rem);
  --t-xl:   clamp(1.45rem, 1.25rem + 0.9vw, 2rem);
  --t-2xl:  clamp(1.85rem, 1.45rem + 1.8vw, 2.9rem);
  --t-3xl:  clamp(2.3rem, 1.6rem + 3.1vw, 4.15rem);

  /* --- space -------------------------------------------------------- */
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --wrap:   1180px;
  --wrap-narrow: 760px;
  --sect:   clamp(3.25rem, 8vw, 6.5rem);

  --r-sm: 4px;
  --r:    8px;
  --r-lg: 14px;

  --shadow-1: 0 1px 2px rgba(20,32,43,.06), 0 2px 8px rgba(20,32,43,.05);
  --shadow-2: 0 2px 6px rgba(20,32,43,.07), 0 12px 32px rgba(20,32,43,.10);
  --shadow-3: 0 4px 12px rgba(20,32,43,.10), 0 24px 60px rgba(20,32,43,.16);

  --header-h: 62px;
  --callbar-h: 56px;
}

/* ==========================================================================
   TEXTURES
   Four surfaces, each tied to something real on a roof.
   Kept under ~2% opacity contrast so they read as material, not pattern.
   ========================================================================== */

/* 1. GRANULE — the mineral surface of an architectural shingle.
      Fractal noise, desaturated, very low alpha. Used on dark sections. */
.tx-granule { position: relative; isolation: isolate; }
.tx-granule::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: .32;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  mix-blend-mode: overlay;
}

/* 2. COURSE — the horizontal rhythm of shingle courses, offset every other
      row the way a real roof is staggered. Drawn, not photographed. */
.tx-course { position: relative; isolation: isolate; }
.tx-course::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: .5;
  background-image:
    repeating-linear-gradient(
      to bottom,
      transparent 0 33px,
      rgba(255,255,255,.045) 33px 34px,
      rgba(0,0,0,.09) 34px 36px
    ),
    repeating-linear-gradient(
      to right,
      transparent 0 88px,
      rgba(0,0,0,.05) 88px 89px
    );
  background-size: auto, 88px 72px;
}

/* 3. SEAM — standing seam metal. Vertical ribs with a highlight on the
      leading edge, like light down a panel. */
.tx-seam { position: relative; isolation: isolate; }
.tx-seam::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: .55;
  background-image: repeating-linear-gradient(
    to right,
    rgba(255,255,255,.00) 0 60px,
    rgba(255,255,255,.07) 60px 62px,
    rgba(0,0,0,.10) 62px 65px,
    rgba(255,255,255,.03) 65px 68px,
    rgba(255,255,255,.00) 68px 128px
  );
}

/* 4. KRAFT — the carbon-copy proposal pad Rick has used for forty years.
      Warm paper tooth + a faint ruled grid. Used behind the 13-point scope. */
.tx-kraft { position: relative; isolation: isolate; background-color: var(--paper-2); }
.tx-kraft::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none;
  opacity: .55;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23p)' opacity='.4'/%3E%3C/svg%3E"),
    repeating-linear-gradient(to bottom, transparent 0 27px, rgba(20,32,43,.045) 27px 28px);
}

/* Hairline that reads like a drip edge — used to cap dark sections. */
.edge-drip { position: relative; }
.edge-drip::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: linear-gradient(to bottom,
    rgba(255,255,255,.22) 0 1px,
    rgba(0,0,0,.28) 1px 3px);
}

/* ==========================================================================
   BASE
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Painted as well as <body>: anything outside the body box — the scrollbar
     gutter, overscroll, an embedding host's ground — shows through <html>,
     and on a dark host that reads as a black strip down the edge. */
  background: var(--paper);
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-base);
  line-height: 1.62;
  color: var(--ink-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

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

h1, h2, h3, h4 {
  margin: 0 0 .5em;
  color: var(--ink);
  line-height: 1.12;
  letter-spacing: -0.02em;
  font-weight: 700;
  text-wrap: balance;
}
h1 { font-size: var(--t-3xl); letter-spacing: -0.032em; }
h2 { font-size: var(--t-2xl); letter-spacing: -0.026em; }
h3 { font-size: var(--t-xl); }
h4 { font-size: var(--t-lg); }

p { margin: 0 0 1.1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

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

:focus-visible {
  outline: 3px solid var(--crimson);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: #fff; padding: .8rem 1.2rem; z-index: 999;
}
.skip:focus { left: .5rem; top: .5rem; }

/* ==========================================================================
   LAYOUT
   ========================================================================== */

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

.section { padding-block: var(--sect); }
.section-tight { padding-block: clamp(2.25rem, 5vw, 3.75rem); }

.section-dark { background: var(--ink); color: #cfd8de; }
.section-dark h1, .section-dark h2, .section-dark h3, .section-dark h4 { color: #fff; }

.section-graphite { background: var(--graphite); color: #d7dee3; }
.section-graphite h2, .section-graphite h3 { color: #fff; }

.eyebrow {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--crimson);
  margin: 0 0 .9rem;
}
.section-dark .eyebrow, .section-graphite .eyebrow { color: #e8919a; }

.lede { font-size: var(--t-lg); color: var(--ink-3); max-width: 62ch; }
.section-dark .lede, .section-graphite .lede { color: #b6c2cb; }

/* ==========================================================================
   BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .55rem;
  min-height: 52px;
  padding: .85rem 1.5rem;
  font: inherit; font-weight: 650; font-size: var(--t-base);
  letter-spacing: -.005em;
  border: 1.5px solid transparent;
  border-radius: var(--r);
  cursor: pointer;
  text-decoration: none;
  transition: transform .14s ease, box-shadow .18s ease, background-color .18s ease;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--crimson); color: #fff; border-color: var(--crimson);
  box-shadow: var(--shadow-1);
}
.btn-primary:hover { background: var(--crimson-d); border-color: var(--crimson-d); color: #fff; box-shadow: var(--shadow-2); }

.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--ink-3); color: var(--ink); background: rgba(20,32,43,.03); }

.btn-on-dark { background: rgba(255,255,255,.09); color: #fff; border-color: rgba(255,255,255,.34); backdrop-filter: blur(6px); }
.btn-on-dark:hover { background: rgba(255,255,255,.17); color: #fff; border-color: rgba(255,255,255,.55); }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }

/* ==========================================================================
   HEADER
   ========================================================================== */

.header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255,255,255,.94);
  backdrop-filter: saturate(150%) blur(12px);
  border-bottom: 1px solid var(--line-soft);
}
.header-inner {
  display: flex; align-items: center; gap: 1rem;
  min-height: var(--header-h);
}
.brand { display: flex; align-items: center; gap: .7rem; text-decoration: none; margin-right: auto; }
.brand img { height: 34px; width: auto; }
.brand-text { display: flex; flex-direction: column; line-height: 1.05; }
.brand-name { font-weight: 800; font-size: 1.02rem; color: var(--ink); letter-spacing: -.03em; }
.brand-sub { font-size: .66rem; letter-spacing: .16em; text-transform: uppercase; color: var(--muted); font-weight: 600; }

.nav { display: none; }
@media (min-width: 1000px) {
  .nav { display: flex; align-items: center; gap: .3rem; }
  .nav a {
    padding: .5rem .72rem; border-radius: var(--r-sm);
    font-size: .92rem; font-weight: 550; color: var(--ink-2); text-decoration: none;
  }
  .nav a:hover { background: var(--paper-3); color: var(--ink); }
  .nav a[aria-current="page"] { color: var(--crimson); font-weight: 700; }
  .nav .btn { margin-left: .5rem; min-height: 42px; padding: .5rem 1.05rem; font-size: .92rem; }
}

.header-phone {
  display: inline-flex; align-items: center; gap: .45rem;
  font-weight: 750; color: var(--ink); text-decoration: none;
  font-size: .95rem; white-space: nowrap;
}
.header-phone:hover { color: var(--crimson); }
@media (max-width: 480px) { .header-phone span.label { display: none; } }

.menu-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: #fff; cursor: pointer;
}
@media (min-width: 1000px) { .menu-btn { display: none; } }

.mobile-nav { display: none; border-top: 1px solid var(--line-soft); background: #fff; }
.mobile-nav.open { display: block; }
.mobile-nav a {
  display: block; padding: .95rem var(--gutter);
  border-bottom: 1px solid var(--line-soft);
  color: var(--ink); text-decoration: none; font-weight: 600;
}
.mobile-nav a:last-child { border-bottom: 0; }
@media (min-width: 1000px) { .mobile-nav { display: none !important; } }

/* Fixed tap-to-call bar, phones only. A homeowner is standing in the yard. */
.callbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  display: grid; grid-template-columns: 1fr 1fr;
  background: var(--ink);
  box-shadow: 0 -2px 18px rgba(20,32,43,.22);
  padding-bottom: env(safe-area-inset-bottom);
}
.callbar a {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: var(--callbar-h);
  color: #fff; text-decoration: none; font-weight: 700; font-size: .96rem;
}
.callbar a + a { background: var(--crimson); }
@media (min-width: 1000px) { .callbar { display: none; } }
@media (max-width: 999px) { body { padding-bottom: var(--callbar-h); } }

/* ==========================================================================
   HERO
   ========================================================================== */

.hero {
  position: relative;
  background: var(--ink);
  color: #fff;
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; z-index: 0; }
/* Photos are real jobs now, not placeholder crops — let them read.
   The scrim is weighted left so the headline keeps contrast while the
   right half of the roof stays visible. */
.hero-media img {
  width: 100%; height: 100%; object-fit: cover;
  object-position: 50% 42%;          /* favour the roofline over the lawn */
  opacity: .74;
}
.hero-media::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(to right,
      rgba(12,20,28,.90) 0%,
      rgba(12,20,28,.70) 40%,
      rgba(12,20,28,.30) 74%,
      rgba(12,20,28,.16) 100%),
    linear-gradient(to top, rgba(12,20,28,.86) 0%, transparent 52%);
}
/* On phones the text sits over the whole frame, so darken evenly instead. */
@media (max-width: 780px) {
  .hero-media img { opacity: .62; }
  .hero-media::after {
    background:
      linear-gradient(to bottom, rgba(12,20,28,.72) 0%, rgba(12,20,28,.55) 40%, rgba(12,20,28,.88) 100%);
  }
}
/* fallback when no photo has been dropped in yet */
.hero-media.is-empty {
  background:
    radial-gradient(120% 90% at 15% 0%, #2c3a46 0%, transparent 60%),
    linear-gradient(160deg, #1b2833 0%, #131e28 55%, #0e161e 100%);
}

.hero-inner {
  position: relative; z-index: 2;
  padding-block: clamp(3.5rem, 11vw, 8rem);
  max-width: 40rem;
}
.hero h1 { color: #fff; margin-bottom: .55em; }
.hero-sub { font-size: var(--t-lg); color: #c6d1d9; margin-bottom: 1.9rem; max-width: 34rem; }
.hero .btn-row { margin-bottom: 1.6rem; }

.hero-caption {
  position: absolute; right: var(--gutter); bottom: 1.1rem; z-index: 3;
  font-size: var(--t-xs); color: rgba(255,255,255,.62);
  letter-spacing: .04em;
}
@media (max-width: 780px) { .hero-caption { display: none; } }

/* ==========================================================================
   TRUST BAR
   ========================================================================== */

.trustbar { background: var(--graphite); color: #fff; }
.trustbar ul {
  display: flex; flex-wrap: wrap; gap: .55rem 1.9rem;
  list-style: none; margin: 0; padding-block: .95rem;
  font-size: var(--t-sm); font-weight: 600; letter-spacing: .01em;
}
.trustbar li { display: flex; align-items: center; gap: .5rem; color: #e3e9ed; }
.trustbar li::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--crimson); flex: none;
}

/* ==========================================================================
   CARDS / GRIDS
   ========================================================================== */

.grid { display: grid; gap: clamp(1rem, 2.4vw, 1.6rem); }
.grid-3 { grid-template-columns: 1fr; }
.grid-2 { grid-template-columns: 1fr; }
@media (min-width: 700px)  { .grid-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px)  { .grid-3 { grid-template-columns: repeat(3, 1fr); } }

.card {
  position: relative;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 3vw, 2rem);
  overflow: hidden;
  transition: transform .18s ease, box-shadow .2s ease, border-color .2s ease;
}
.card:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: #c6cfd6; }
.card h3 { margin-bottom: .45rem; }
.card p { color: var(--ink-3); font-size: var(--t-sm); margin-bottom: 1rem; }
.card-link { font-weight: 700; font-size: var(--t-sm); text-decoration: none; display: inline-flex; gap: .35rem; align-items: center; }
.card-link::after { content: "→"; transition: transform .16s ease; }
.card:hover .card-link::after { transform: translateX(3px); }

/* a 4px colored cap on each card, tinted per service */
.card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: var(--graphite);
}
.card[data-texture="shingle"]::before { background: var(--graphite); }
.card[data-texture="water"]::before   { background: #2f6f8f; }
.card[data-texture="paper"]::before   { background: var(--copper); }

/* ==========================================================================
   THE 13-POINT SCOPE — the money block. Reads like his paper pad.
   ========================================================================== */

.scope { position: relative; }
.scope-head { max-width: 46rem; margin-bottom: clamp(2rem, 5vw, 3rem); }
.scope-system {
  display: inline-block;
  font-family: var(--serif); font-style: italic;
  font-size: var(--t-lg); color: var(--ink);
  border-bottom: 2px solid var(--crimson);
  padding-bottom: .2rem; margin-top: .4rem;
}

.scope-list { list-style: none; margin: 0; padding: 0; counter-reset: pt; display: grid; gap: 0; }
@media (min-width: 860px) { .scope-list { grid-template-columns: 1fr 1fr; column-gap: clamp(2rem, 4vw, 3.5rem); } }

.scope-item {
  counter-increment: pt;
  display: grid; grid-template-columns: 2.6rem 1fr; gap: 1rem;
  padding: 1.15rem 0;
  border-bottom: 1px solid rgba(20,32,43,.11);
}
.scope-item::before {
  content: counter(pt, decimal-leading-zero);
  font-variant-numeric: tabular-nums;
  font-weight: 800; font-size: .82rem; letter-spacing: .04em;
  color: var(--crimson);
  padding-top: .28rem;
}
.scope-item h4 { margin: 0 0 .2rem; font-size: var(--t-base); font-weight: 700; }
.scope-item p { margin: 0; font-size: var(--t-sm); color: var(--ink-3); }

/* ==========================================================================
   VALUES / FAITH BLOCK
   ========================================================================== */

.values-list { list-style: none; margin: 2rem 0 0; padding: 0; display: grid; gap: 1.35rem; }
.values-list li { padding-left: 1.4rem; border-left: 3px solid rgba(184,32,42,.5); }
.values-list strong { display: block; color: #fff; font-weight: 700; margin-bottom: .15rem; }
.values-list span { color: #adbac4; font-size: var(--t-sm); }

.verse {
  font-family: var(--serif); font-style: italic;
  font-size: var(--t-lg); line-height: 1.55;
  color: #c9d3da;
  border-left: 3px solid var(--crimson);
  padding-left: 1.35rem;
  margin: 2rem 0 0;
  max-width: 44ch;
}
.verse cite { display: block; font-style: normal; font-family: var(--sans); font-size: var(--t-sm); color: var(--muted); margin-top: .7rem; letter-spacing: .05em; }

/* ==========================================================================
   STEPS (insurance claims)
   ========================================================================== */

.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; counter-reset: st; }
.step {
  counter-increment: st;
  display: grid; grid-template-columns: auto 1fr; gap: 1.25rem;
  padding: 1.5rem 0;
  border-top: 1px solid var(--line);
}
.step:last-child { border-bottom: 1px solid var(--line); }
.step-n {
  width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--ink); color: #fff;
  font-weight: 800; font-size: .95rem;
  flex: none;
}
.step h4 { margin-bottom: .2rem; }
.step p { margin: 0; color: var(--ink-3); font-size: var(--t-sm); }

/* ==========================================================================
   GALLERY
   ========================================================================== */

.gallery { display: grid; gap: .6rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .gallery { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .gallery { grid-template-columns: repeat(3, 1fr); } }
.shot {
  position: relative; overflow: hidden; border-radius: var(--r);
  background: var(--paper-3); aspect-ratio: 4 / 3;
}
.shot img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s cubic-bezier(.2,.7,.3,1); }
.shot:hover img { transform: scale(1.035); }
.shot figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 1.6rem .9rem .75rem;
  background: linear-gradient(to top, rgba(12,20,28,.82), transparent);
  color: #fff; font-size: var(--t-xs); font-weight: 600; letter-spacing: .02em;
}
.gallery-empty {
  border: 1.5px dashed var(--line);
  border-radius: var(--r-lg);
  padding: clamp(2rem, 6vw, 3.5rem);
  text-align: center;
  color: var(--muted);
  font-size: var(--t-sm);
}

/* ==========================================================================
   FORM
   ========================================================================== */

.form-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  box-shadow: var(--shadow-2);
}
.field { margin-bottom: 1.15rem; }
.field label { display: block; font-weight: 650; font-size: var(--t-sm); margin-bottom: .4rem; color: var(--ink); }
.field .req { color: var(--crimson); }
.field input, .field textarea, .field select {
  width: 100%;
  min-height: 50px;
  padding: .8rem .9rem;
  font: inherit; font-size: 16px; /* never trigger iOS zoom */
  color: var(--ink);
  background: var(--paper-2);
  border: 1.5px solid var(--line);
  border-radius: var(--r);
  transition: border-color .15s ease, background-color .15s ease;
}
.field textarea { min-height: 128px; resize: vertical; line-height: 1.55; }
.field input:focus, .field textarea:focus {
  background: #fff; border-color: var(--ink-3); outline: none;
  box-shadow: 0 0 0 3px rgba(184,32,42,.14);
}
.field input:user-invalid, .field textarea:user-invalid { border-color: var(--crimson); }

.radio-row { display: flex; flex-wrap: wrap; gap: .5rem; }
.radio-chip { position: relative; }
.radio-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.radio-chip span {
  display: inline-flex; align-items: center;
  min-height: 46px; padding: .5rem 1.1rem;
  border: 1.5px solid var(--line); border-radius: 999px;
  background: var(--paper-2); cursor: pointer;
  font-size: var(--t-sm); font-weight: 600;
  transition: all .15s ease;
}
.radio-chip input:checked + span { background: var(--ink); color: #fff; border-color: var(--ink); }
.radio-chip input:focus-visible + span { outline: 3px solid var(--crimson); outline-offset: 2px; }

.form-note { font-size: var(--t-xs); color: var(--muted); margin-top: .9rem; }
.form-status { margin-top: 1rem; padding: .95rem 1.1rem; border-radius: var(--r); font-size: var(--t-sm); display: none; }
.form-status.show { display: block; }
.form-status.ok  { background: #eaf4ee; color: #1c5433; border: 1px solid #bcdcc7; }
.form-status.err { background: #fbeced; color: #8f171f; border: 1px solid #f0c4c7; }

/* ==========================================================================
   CTA STRIP
   ========================================================================== */

.cta-strip { background: var(--crimson); color: #fff; }
.cta-strip h2 { color: #fff; margin-bottom: .35em; }
.cta-strip p { color: rgba(255,255,255,.9); max-width: 46ch; }
.cta-strip .btn-ghost { color: #fff; border-color: rgba(255,255,255,.5); }
.cta-strip .btn-ghost:hover { background: rgba(255,255,255,.12); color: #fff; }
.cta-strip .btn-primary { background: #fff; color: var(--crimson); border-color: #fff; }
.cta-strip .btn-primary:hover { background: #f4f4f4; color: var(--crimson-d); }

/* ==========================================================================
   FOOTER
   ========================================================================== */

.footer { background: var(--ink); color: #93a3af; font-size: var(--t-sm); }
.footer a { color: #cdd7df; text-decoration: none; }
.footer a:hover { color: #fff; text-decoration: underline; }
.footer-grid { display: grid; gap: 2.25rem; padding-block: clamp(2.5rem, 6vw, 4rem); }
@media (min-width: 800px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr; gap: 3rem; } }
.footer h4 { color: #fff; font-size: var(--t-sm); letter-spacing: .1em; text-transform: uppercase; margin-bottom: 1rem; }
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.footer-brand img { height: 40px; margin-bottom: 1rem; }
.footer-verse {
  font-family: var(--serif); font-style: italic; color: #8fa0ac;
  border-top: 1px solid rgba(255,255,255,.11);
  padding-block: 1.4rem;
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; justify-content: space-between;
  font-size: var(--t-xs);
}

/* ==========================================================================
   MOTION — entrance only, respects reduced-motion via the global rule above
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  .reveal { opacity: 0; transform: translateY(14px); transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.3,1); }
  .reveal.in { opacity: 1; transform: none; }
}

/* ==========================================================================
   PRINT
   ========================================================================== */

@media print {
  .header, .callbar, .mobile-nav, .cta-strip, .hero-media { display: none !important; }
  body { color: #000; }
  a::after { content: " (" attr(href) ")"; font-size: .8em; }
}

/* ==========================================================================
   ── ELEVATION PASS ────────────────────────────────────────────────────────
   The devices below are what make this read as a roofing site specifically
   rather than a generic contractor template: a pitch line borrowed from a
   roof profile, a course-stagger reveal, and display type with real weight.
   ========================================================================== */

:root {
  --display: "Archivo", "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  --pitch: 3.2vw;              /* rise of the roofline dividers */
  --t-hero: clamp(2.6rem, 1.4rem + 5.4vw, 5.6rem);
}

/* --- DISPLAY TYPE -------------------------------------------------------
   Archivo at 800 with tight tracking. Reads structural, not decorative. */
h1, h2, .display {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.04;
}
h1 { font-size: var(--t-hero); }
.hero h1 { letter-spacing: -0.042em; }

/* An accent line the color of the wordmark, set under section headings. */
.rule-accent { display: block; width: 54px; height: 4px; background: var(--crimson); border-radius: 2px; margin-bottom: 1.4rem; }

/* --- ROOFLINE DIVIDERS --------------------------------------------------
   A section can carry a pitch on its top edge, bottom edge, or both. The
   angle is shallow — a 4/12 pitch, the same as most of the roofs he builds.
   Implemented with clip-path so it costs nothing and scales with viewport. */
.pitch-top    { clip-path: polygon(0 var(--pitch), 50% 0, 100% var(--pitch), 100% 100%, 0 100%); margin-top: calc(var(--pitch) * -1); padding-top: calc(var(--sect) + var(--pitch)); }
.pitch-bottom { clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--pitch)), 50% 100%, 0 calc(100% - var(--pitch))); padding-bottom: calc(var(--sect) + var(--pitch)); }
.pitch-rake   { clip-path: polygon(0 var(--pitch), 100% 0, 100% 100%, 0 100%); margin-top: calc(var(--pitch) * -1); padding-top: calc(var(--sect) + var(--pitch)); }
@media (max-width: 600px) { :root { --pitch: 5vw; } }

/* --- SCROLL-AWARE HEADER ------------------------------------------------ */
.header { transition: box-shadow .25s ease, background-color .25s ease; }
.header.scrolled { box-shadow: 0 1px 0 var(--line), 0 6px 24px rgba(20,32,43,.07); }
.header.scrolled .brand-sub { opacity: 0; transform: translateY(-4px); }
.brand-sub { transition: opacity .22s ease, transform .22s ease; }

/* --- HERO, REWORKED -----------------------------------------------------
   Slow ken-burns drift on the photo, a hairline grid over it for structure,
   and the headline set on a scrim so it stays legible on any image. */
.hero { min-height: clamp(520px, 82svh, 860px); display: flex; align-items: center; }
.hero-media img {
  opacity: .58;
  animation: drift 26s ease-in-out infinite alternate;
  transform-origin: 58% 40%;
}
@keyframes drift { from { transform: scale(1.06); } to { transform: scale(1.14); } }
@media (prefers-reduced-motion: reduce) { .hero-media img { animation: none; transform: scale(1.06); } }

.hero-media::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background-image:
    repeating-linear-gradient(to right, rgba(255,255,255,.05) 0 1px, transparent 1px 12.5%);
  opacity: .5;
}
.hero-inner { max-width: 46rem; }
.hero h1 { text-shadow: 0 2px 30px rgba(8,14,20,.45); }
.hero-sub { color: #d3dce2; }

/* A thin credential strip pinned to the bottom of the hero on wide screens */
.hero-creds {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  border-top: 1px solid rgba(255,255,255,.14);
  backdrop-filter: blur(8px);
  background: rgba(12,20,28,.34);
}
.hero-creds ul {
  display: flex; gap: 2.4rem; list-style: none; margin: 0; padding: .9rem 0;
  font-size: var(--t-xs); letter-spacing: .1em; text-transform: uppercase;
  font-weight: 700; color: rgba(255,255,255,.82);
}
@media (max-width: 900px) { .hero-creds { display: none; } }

/* --- STAT BAND ----------------------------------------------------------
   Three numbers that do the arguing: years, scope points, warranty. */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
.stat { padding: clamp(1.5rem, 4vw, 2.75rem) clamp(.75rem, 2vw, 1.5rem); text-align: center; position: relative; }
.stat + .stat::before { content: ""; position: absolute; left: 0; top: 22%; bottom: 22%; width: 1px; background: rgba(255,255,255,.16); }
.stat-n {
  display: block; font-family: var(--display); font-weight: 800;
  font-size: clamp(2.2rem, 1.2rem + 3.6vw, 4rem); line-height: 1;
  color: #fff; letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
}
.stat-l { display: block; margin-top: .55rem; font-size: var(--t-xs); letter-spacing: .11em; text-transform: uppercase; font-weight: 700; color: #93a8b6; }
@media (max-width: 560px) { .stat-l { letter-spacing: .06em; font-size: .68rem; } }

/* --- SCOPE, AS A SHOWPIECE ---------------------------------------------- */
.scope-item { transition: background-color .18s ease, padding-left .18s ease; padding-left: .5rem; margin-left: -.5rem; border-radius: 4px; }
.scope-item:hover { background: rgba(184,32,42,.045); }
.scope-item h4 { transition: color .18s ease; }
.scope-item:hover h4 { color: var(--crimson-d); }

/* Staggered reveal — rows come in like courses going on. */
@media (prefers-reduced-motion: no-preference) {
  .scope-list .reveal { transition-delay: calc(var(--i, 0) * 42ms); }
}

/* --- CARDS, DEEPER ------------------------------------------------------ */
.card { background: linear-gradient(180deg, #fff 0%, #fcfdfd 100%); }
.card::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(80% 60% at 50% 0%, rgba(184,32,42,.06), transparent 70%);
  transition: opacity .25s ease;
}
.card:hover::after { opacity: 1; }
.card:hover { box-shadow: var(--shadow-3); }

/* --- BEFORE / AFTER SLIDER --------------------------------------------- */
.ba { position: relative; overflow: hidden; border-radius: var(--r-lg); aspect-ratio: 3 / 2; background: var(--paper-3); touch-action: pan-y; }
.ba img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ba .after { clip-path: inset(0 0 0 var(--split, 50%)); }
.ba-handle {
  position: absolute; top: 0; bottom: 0; left: var(--split, 50%);
  width: 2px; background: #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.2);
  transform: translateX(-1px); cursor: ew-resize;
}
.ba-handle::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 44px; height: 44px;
  transform: translate(-50%,-50%); border-radius: 50%;
  background: #fff; box-shadow: 0 2px 12px rgba(0,0,0,.3);
}
.ba-tag {
  position: absolute; top: .75rem; padding: .3rem .7rem; border-radius: 999px;
  font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  background: rgba(12,20,28,.72); color: #fff; backdrop-filter: blur(4px);
}
.ba-tag.l { left: .75rem; } .ba-tag.r { right: .75rem; }

/* --- GALLERY, RICHER ---------------------------------------------------- */
.gallery { gap: .75rem; }
.shot { border-radius: var(--r-lg); }
.shot::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(20,32,43,.09);
  border-radius: inherit;
}
@media (min-width: 1000px) {
  .gallery .shot:first-child { grid-column: span 2; grid-row: span 2; aspect-ratio: 16 / 11; }
}

/* --- MARQUEE OF TOWNS --------------------------------------------------- */
.towns { overflow: hidden; border-block: 1px solid var(--line); padding-block: 1.1rem; }
.towns-track {
  display: flex; gap: 2.5rem; width: max-content;
  font-family: var(--display); font-weight: 700; font-size: var(--t-lg);
  color: var(--ink-3); letter-spacing: -.02em;
  animation: slide 46s linear infinite;
}
.towns-track span::after { content: "·"; margin-left: 2.5rem; color: var(--crimson); }
@keyframes slide { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .towns-track { animation: none; } }
.towns:hover .towns-track { animation-play-state: paused; }

/* --- FORM, SHARPER ------------------------------------------------------ */
.form-card { background: linear-gradient(180deg,#fff, #fbfcfc); }
.form-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--crimson), var(--crimson-d));
}
.form-card { position: relative; overflow: hidden; }

/* --- BRAND LOCKUP -------------------------------------------------------
   The logo is a hand-drawn scan, 2.7:1, with the company name inside it.
   So it is never paired with a repeated wordmark — it just runs as large as
   the header allows, with the locality set small beside it. */
.brand-logo { height: 34px; width: auto; }
@media (min-width: 700px) { .brand-logo { height: 42px; } }
.brand-rule { width: 1px; align-self: stretch; background: var(--line); margin-inline: .15rem; }
.brand .brand-sub { font-size: .6rem; line-height: 1.3; letter-spacing: .1em; }
@media (max-width: 420px) { .brand-rule, .brand .brand-text { display: none; } }

/* Vector-traced knockout for dark ground — no plate needed. */
.footer-logo { height: 52px; width: auto; margin-bottom: 1.1rem; }

/* Quiet maker's credit — home page only. */
.colophon {
  border-top: 1px solid rgba(255,255,255,.07);
  padding-block: .85rem 1.1rem;
  text-align: center;
}
.colophon a {
  font-size: .66rem; letter-spacing: .13em; text-transform: uppercase;
  color: #56656f; text-decoration: none; font-weight: 600;
}
.colophon a:hover { color: #93a3af; text-decoration: none; }

/* ==========================================================================
   RESPONSIVE HARDENING
   Findings from scripts/rwd.js across 9 viewports, portrait and landscape.
   Nothing here is cosmetic — each rule fixes a measured failure.
   ========================================================================== */

/* 1. Nothing under ~11.5px anywhere. 9.6px locality text was unreadable. */
.brand .brand-sub { font-size: .7rem; line-height: 1.25; letter-spacing: .07em; }
.stat-l { font-size: .72rem; }
@media (max-width: 560px) { .stat-l { font-size: .7rem; letter-spacing: .05em; } }
.colophon a { font-size: .7rem; }
.hero-creds ul { font-size: .72rem; }
.trustbar ul { font-size: .82rem; }

/* 2. Tap targets. Anything a thumb aims at gets 44px of height on touch. */
@media (max-width: 999px) {
  a[href^="tel:"] {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .footer ul a, .mobile-nav a {
    display: flex; align-items: center; min-height: 44px;
  }
  .card-link { min-height: 44px; align-items: center; }
  .footer-verse a, .colophon a { min-height: 44px; display: inline-flex; align-items: center; }
  /* standalone "read more" style links in body copy */
  .wrap > p > a:not(.btn) { display: inline-block; padding-block: .55rem; }
}

/* 3. Landscape phones are short. Stop the hero eating the whole screen. */
@media (max-height: 480px) and (orientation: landscape) {
  .hero { min-height: 0; }
  .hero-inner { padding-block: 2.25rem; }
  .hero h1 { font-size: clamp(1.6rem, 4.2vw, 2.4rem); }
  .hero-sub { font-size: 1rem; margin-bottom: 1.1rem; }
  .hero-creds { display: none; }
  .section { padding-block: 2.5rem; }
}

/* 4. Very narrow phones (320–360). Keep the header from crowding. */
@media (max-width: 370px) {
  .brand-logo { height: 30px; }
  .brand-rule, .brand .brand-text { display: none; }
  .header-phone .label { display: none; }
  .stats { grid-template-columns: 1fr; }
  .stat + .stat::before { top: 0; bottom: auto; left: 18%; right: 18%; width: auto; height: 1px; }
  .stat { padding-block: 1.15rem; }
}

/* 5. The hero photo scales for the drift; clip it to the section so it can
      never contribute to document width. */
.hero, .hero-media { overflow: hidden; }
.hero-media img { will-change: transform; }

/* 6. Tablet portrait: three service cards are cramped at 768. Go two-up. */
@media (min-width: 700px) and (max-width: 899px) {
  .grid-3 { grid-template-columns: 1fr 1fr; }
  .grid-3 > :last-child { grid-column: 1 / -1; }
}

/* 7. Form on small screens — full-width controls, comfortable chips. */
@media (max-width: 560px) {
  .radio-chip span { min-height: 48px; padding-inline: 1.25rem; }
  .form-card { padding-inline: 1.15rem; }
  .btn { width: 100%; }
  .btn-row { flex-direction: column; align-items: stretch; }
  .hero .btn-row { gap: .6rem; }
}

/* 8. Wide screens — stop line lengths running long. */
@media (min-width: 1600px) { :root { --wrap: 1280px; } }

/* --- audit round 2 ------------------------------------------------------
   The logo already carries the company name, so on phones the locality line
   is redundant crowding — it stays in the trust bar and the footer. */
@media (max-width: 760px) { .brand-rule, .brand .brand-text { display: none; } }
.stat-l { font-size: .75rem; }
@media (max-width: 560px) { .stat-l { font-size: .74rem; } }
/* standalone links that sit directly in a .wrap, not inside a paragraph */
@media (max-width: 999px) {
  .wrap > a:not(.btn) { display: inline-flex; align-items: center; min-height: 44px; }
}

/* Locality line shows only from 760px up, so it must be legible there. */
.brand .brand-sub { font-size: .78rem; line-height: 1.3; }

/* --- HEADER FIT ---------------------------------------------------------
   Seven nav items, a CTA and a phone number need real room. Below 1180px
   the hamburger does the job; nothing is ever allowed to wrap to two lines. */
.nav { display: none; }
@media (min-width: 1180px) { .nav { display: flex; } }
@media (max-width: 1179px) { .menu-btn { display: inline-flex; } }
@media (min-width: 1180px) { .menu-btn { display: none; } }
.nav a, .header-phone, .brand .brand-sub { white-space: nowrap; }
.nav a { padding-inline: .6rem; font-size: .9rem; }
.nav .btn { white-space: nowrap; }
/* the locality line only when there is genuinely space for it */
.brand .brand-text { display: none; }
@media (min-width: 1340px) { .brand .brand-text { display: flex; } .brand-rule { display: block; } }
@media (max-width: 1339px) { .brand-rule { display: none; } }

/* ==========================================================================
   REVIEWS
   We don't buy leads and we don't buy reviews — so the site has to ask well.
   ========================================================================== */

.stars { color: #d9a406; letter-spacing: .12em; font-size: 1.05rem; display: block; margin-bottom: .9rem; }
.stars-off { color: var(--line); }

.review {
  margin: 0;
  background: linear-gradient(180deg, #fff, #fbfcfc);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(1.35rem, 3vw, 1.85rem);
  position: relative;
}
.review::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: var(--crimson); border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.review blockquote {
  margin: 0 0 1.1rem; font-size: var(--t-base); line-height: 1.6; color: var(--ink-2);
}
.review blockquote::before { content: "\\201C"; }
.review blockquote::after  { content: "\\201D"; }
.review figcaption { display: grid; gap: .12rem; font-size: var(--t-sm); }
.review figcaption strong { color: var(--ink); font-weight: 700; }
.review figcaption span { color: var(--muted); }
.review-src { font-size: var(--t-xs); letter-spacing: .06em; text-transform: uppercase; }

/* the /review/ landing page — one job, one button */
.btn-lg { min-height: 62px; font-size: var(--t-lg); padding-inline: 2rem; }
.review-cta {
  margin: 2.5rem 0;
  padding: clamp(1.5rem, 4vw, 2.5rem);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.review-alt {
  margin-top: 2.5rem; padding-top: 2rem;
  border-top: 1px solid var(--line);
}
.review-alt p { color: var(--ink-3); max-width: 46ch; margin-inline: auto; }

/* ==========================================================================
   ── V2 — TEXTURE, CUTAWAY, LIVING MARK ───────────────────────────────────
   Everything below supersedes the first-pass texture block. The originals
   were tuned against low-resolution placeholder crops and ended up at a
   volume nobody could actually see. These are meant to be noticed.
   ========================================================================== */

:root {
  --tex-strength: 1;
  --ease-out: cubic-bezier(.16,1,.3,1);
  --ease-soft: cubic-bezier(.4,0,.2,1);
}

/* ── 1. GRANULE ──────────────────────────────────────────────────────────
   The mineral face of an architectural shingle. Two turbulence fields at
   different frequencies, one tight and one loose, so it reads as crushed
   rock rather than TV static. */
.tx-granule { position: relative; isolation: isolate; }
.tx-granule::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 .82 0 0 0 0 .85 0 0 0 0 .88 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='h'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.22' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .28 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3C/svg%3E");
  opacity: calc(.5 * var(--tex-strength));
  mix-blend-mode: overlay;
}

/* ── 2. SHINGLE ──────────────────────────────────────────────────────────
   Staggered courses with a real shadow line under each butt edge, and the
   vertical keyway offset every other row. This one you can see from across
   the room, which is the point. */
.tx-shingle { position: relative; isolation: isolate; background-color: var(--sand, #f4f1ec); }
.tx-shingle::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    /* butt-edge shadow, one per course */
    repeating-linear-gradient(to bottom,
      transparent 0 62px,
      rgba(20,32,43,.09) 62px 63px,
      rgba(20,32,43,.035) 63px 70px,
      transparent 70px 72px),
    /* keyways, offset by half a tab on alternating courses */
    repeating-linear-gradient(to right,
      transparent 0 94px,
      rgba(20,32,43,.055) 94px 96px,
      transparent 96px 190px);
  background-size: 100% 72px, 190px 144px;
  opacity: calc(.9 * var(--tex-strength));
}
.tx-shingle::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: repeating-linear-gradient(to right,
      transparent 0 94px, rgba(20,32,43,.055) 94px 96px, transparent 96px 190px);
  background-size: 190px 144px;
  background-position: 95px 72px;
  opacity: calc(.9 * var(--tex-strength));
}

/* ── 3. SEAM ─────────────────────────────────────────────────────────────
   Standing-seam metal: ribs at a real pitch with a specular band that
   travels once when the strip scrolls into view. */
.tx-seam { position: relative; isolation: isolate; overflow: hidden; }
.tx-seam::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: repeating-linear-gradient(to right,
    rgba(255,255,255,.045) 0 1px,
    rgba(255,255,255,.11)  1px 3px,
    rgba(255,255,255,.03)  3px 5px,
    transparent            5px 58px,
    rgba(0,0,0,.16)       58px 61px,
    transparent           61px 64px);
  opacity: calc(1 * var(--tex-strength));
}
.tx-seam::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 42%; z-index: -1;
  pointer-events: none; left: -45%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.13) 46%, transparent);
  transform: skewX(-14deg);
}
.tx-seam.is-lit::after { animation: seam-sweep 2.1s var(--ease-soft) .15s 1 both; }
@keyframes seam-sweep { to { left: 118%; } }

/* ── 4. BLUEPRINT ────────────────────────────────────────────────────────
   Spec-sheet ground for the cutaway. Fine grid, heavier every fifth line,
   and a faint vignette so the drawing sits in the middle of a drafting
   sheet rather than floating on a flat field. */
.tx-blueprint {
  position: relative; isolation: isolate;
  background-color: #101a23;
  color: #e6edf3;
}
.tx-blueprint::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    linear-gradient(rgba(120,160,190,.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(120,160,190,.07) 1px, transparent 1px),
    linear-gradient(rgba(120,160,190,.14) 1px, transparent 1px),
    linear-gradient(90deg, rgba(120,160,190,.14) 1px, transparent 1px),
    radial-gradient(120% 90% at 50% 40%, transparent 45%, rgba(6,11,16,.6) 100%);
  background-size: 22px 22px, 22px 22px, 110px 110px, 110px 110px, 100% 100%;
  opacity: calc(1 * var(--tex-strength));
}
.tx-blueprint h2, .tx-blueprint .lede { color: #f2f6f9; }
.tx-blueprint .lede { color: #b6c6d2; }

/* ── 5. KRAFT ────────────────────────────────────────────────────────────
   His carbon-copy proposal pad: paper tooth, ruled lines, and the warm
   yellow cast of the second sheet. */
.tx-kraft { position: relative; isolation: isolate; background-color: #f7f3e9; }
.tx-kraft::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='k'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.7' numOctaves='4'/%3E%3CfeColorMatrix values='0 0 0 0 .45 0 0 0 0 .38 0 0 0 0 .26 0 0 0 .3 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23k)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(to bottom, transparent 0 31px, rgba(20,32,43,.07) 31px 32px);
  opacity: calc(1 * var(--tex-strength));
}

/* ==========================================================================
   THE CUTAWAY
   ========================================================================== */

.section-spec { color: #e6edf3; }
.section-spec .eyebrow { color: #ff6b6b; }
.scope-head { max-width: 46rem; }
.scope-foot { margin-top: 2.4rem; }

.cutaway { margin: 2.8rem 0 0; }
.cutaway-stage {
  position: relative;
  aspect-ratio: 1000 / 640;
  border: 1px solid rgba(160,190,210,.16);
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 24px 60px -30px rgba(0,0,0,.9);
}
.cutaway-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.d-house { fill: #101c25; stroke: rgba(150,185,210,.22); stroke-width: 1; }
.d-ground { stroke: rgba(180,205,220,.3); stroke-width: 1; stroke-dasharray: 3 5; }

.d-layers polygon, .d-layers path, .d-layers rect { transition: opacity .3s var(--ease-soft), filter .3s var(--ease-soft); }
.d-rafter { fill: #46382a; stroke: #6b573c; stroke-width: 1; }
.d-deck   { fill: #c08f57; stroke: #e0b57f; stroke-width: 1.2; }
.d-ice    { fill: #14343f; stroke: #45c6d8; stroke-width: 1.4; }
.d-under  { fill: #35708e; stroke: #7cc6e2; stroke-width: 1.2; }
.d-start  { fill: #6d5030; stroke: #b08a55; stroke-width: 1.2; }
.d-shing  { stroke: #55636f; stroke-width: 1; }
.d-tab    { stroke: rgba(255,255,255,.16); stroke-width: 1.2; }
.d-nail   { fill: #ffd166; stroke: #b8202a; stroke-width: 1; }
.d-drip   { fill: none; stroke: #cfd9e2; stroke-width: 3.4; stroke-linejoin: round; }
.d-ridge  { fill: #3b4854; stroke: #7d8b97; stroke-width: 1.4; }
.d-vent-air path { stroke: #6fd3c4; stroke-width: 2; stroke-linecap: round; fill: none; opacity: .75; }
.d-boot path { fill: #2b3742; stroke: #8d9aa6; stroke-width: 1.4; }
.d-boot rect { fill: #4b5864; stroke: #8d9aa6; stroke-width: 1.2; }
.d-flash path { fill: #cfd9e2; stroke: #98a6b2; stroke-width: 1; }

.d-wall { fill: #273542; stroke: rgba(180,205,220,.3); stroke-width: 1; }
.d-tarp { fill: #2e6b52; stroke: #4c9b78; stroke-width: 1.2; }
.d-sweep { stroke: #b8202a; stroke-width: 4; stroke-linecap: round; fill: none; }
.d-seal { fill: rgba(184,32,42,.18); stroke: #e0555f; stroke-width: 1.6; }
.d-hot { fill: rgba(255,255,255,.05); stroke: rgba(255,255,255,.22); stroke-width: 1; }

/* Lift the active layer rather than dimming the other twelve — dimming made
   the whole drawing murky and you lost the thing the diagram is for, which is
   seeing how the layers sit together. */
.cutaway .d-layers > *,
.cutaway .d-around > * { opacity: .88; }
.cutaway .d-layers > [data-layer].is-active,
.cutaway .d-around > [data-layer].is-active {
  opacity: 1;
  filter: drop-shadow(0 0 2px rgba(255,255,255,.55)) drop-shadow(0 0 11px rgba(255,107,107,.5));
}
.cutaway .d-layers > [data-layer].is-active polygon,
.cutaway .d-layers > [data-layer].is-active path { stroke-width: 2; }

/* pins */
.cutaway-pins { position: absolute; inset: 0; }
.pin {
  position: absolute; left: var(--x); top: var(--y);
  transform: translate(-50%,-50%);
  display: flex; align-items: center; gap: .5rem;
  min-height: 34px; padding: 0;
  background: none; border: 0; cursor: pointer; color: #fff;
  font: inherit;
}
.pin > span {
  display: grid; place-items: center;
  width: 30px; height: 30px; flex: none;
  border-radius: 50%;
  background: #b8202a; color: #fff;
  font-family: var(--display); font-weight: 800; font-size: 13px; line-height: 1;
  border: 2px solid rgba(255,255,255,.85);
  box-shadow: 0 3px 12px rgba(0,0,0,.5);
  transition: transform .25s var(--ease-out), background .25s;
}
.pin > em {
  font-style: normal; font-size: 12.5px; letter-spacing: .01em; white-space: nowrap;
  background: rgba(9,15,21,.92); padding: .32rem .6rem; border-radius: 2px;
  opacity: 0; transform: translateX(-6px); pointer-events: none;
  transition: opacity .25s, transform .25s var(--ease-out);
  border: 1px solid rgba(255,255,255,.14);
}
.pin:hover > span, .pin:focus-visible > span { transform: scale(1.22); background: #d9333d; }
.pin:hover > em, .pin:focus-visible > em, .pin.is-on > em { opacity: 1; transform: none; }
.pin.is-on > span { background: #fff; color: #b8202a; transform: scale(1.22); }
.pin:focus-visible { outline: 2px solid #fff; outline-offset: 6px; border-radius: 4px; }

/* the reading panel */
.cutaway-panel {
  position: relative;
  margin-top: 1.6rem; padding: 1.5rem 1.6rem 1.4rem;
  background: rgba(255,255,255,.045);
  border: 1px solid rgba(160,190,210,.16);
  border-left: 3px solid #b8202a;
  border-radius: 2px;
  min-height: 9.5rem;
}
.cut-item { display: none; }
.cut-item.is-on { display: block; animation: cut-in .4s var(--ease-out) both; }
@keyframes cut-in { from { opacity: 0; transform: translateY(6px); } }
.cut-num {
  display: block; font-family: var(--display); font-weight: 800;
  font-size: 12px; letter-spacing: .18em; color: #ff6b6b; margin-bottom: .4rem;
}
.cutaway-panel h3 { font-size: clamp(1.15rem, .9rem + .7vw, 1.5rem); margin-bottom: .45rem; color: #fff; }
.cutaway-panel p { color: #b6c6d2; max-width: 52ch; margin: 0; }
.cutaway-hint {
  position: absolute; right: 1.2rem; bottom: .9rem;
  font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(182,198,210,.5); margin: 0;
}

@media (max-width: 860px) {
  .pin > em { display: none; }
  .pin > span { width: 26px; height: 26px; font-size: 12px; }
  .cutaway-hint { position: static; margin-top: .9rem; }
  .cutaway-panel { min-height: 0; }
}
@media (max-width: 560px) {
  .cutaway-stage { aspect-ratio: 1000 / 700; }
  .pin > span { width: 24px; height: 24px; font-size: 11px; border-width: 1.5px; }
}

/* ==========================================================================
   CREED + STEP RAIL — the two sections that used to be text slabs
   ========================================================================== */

.creed-grid { display: grid; gap: 2.4rem; }
@media (min-width: 900px) { .creed-grid { grid-template-columns: 1fr 1.05fr; gap: 4rem; align-items: start; } }
.creed-list { list-style: none; margin: 0; padding: 0; counter-reset: creed; }
.creed-list li {
  counter-increment: creed;
  display: grid; grid-template-columns: auto 1fr; gap: .2rem 1rem;
  padding: 1.15rem 0; border-top: 1px solid rgba(20,32,43,.13);
}
.creed-list li:last-child { border-bottom: 1px solid rgba(20,32,43,.13); }
.creed-list li::before {
  content: counter(creed, decimal-leading-zero);
  grid-row: 1 / span 2;
  font-family: var(--display); font-weight: 800; font-size: 13px;
  color: var(--crimson); letter-spacing: .08em; padding-top: .28rem;
}
.creed-list strong { font-family: var(--display); font-weight: 700; font-size: 1.02rem; line-height: 1.35; }
.creed-list span { color: var(--graphite); font-size: .95rem; line-height: 1.6; }

.steprail { list-style: none; margin: 2.6rem 0 0; padding: 0; display: grid; gap: 0; counter-reset: step; }
@media (min-width: 900px) { .steprail { grid-template-columns: repeat(5, 1fr); } }
.steprail li {
  position: relative; padding: 1.5rem 1.3rem 1.5rem 0;
  border-top: 2px solid rgba(255,255,255,.14);
}
@media (min-width: 900px) { .steprail li { padding-right: 1.6rem; } }
.steprail li::after {
  content: ""; position: absolute; top: -2px; left: 0; height: 2px; width: 0;
  background: var(--crimson);
  transition: width .8s var(--ease-out);
}
.steprail li.in::after { width: 100%; }
.steprail-n {
  display: block; font-family: var(--display); font-weight: 800;
  font-size: 2.2rem; line-height: 1; color: rgba(255,255,255,.22); margin-bottom: .6rem;
}
.steprail strong { display: block; font-family: var(--display); font-size: 1rem; margin-bottom: .4rem; color: #fff; }
.steprail-b { display: block; font-size: .9rem; line-height: 1.6; color: #97a8b5; }

/* ==========================================================================
   THE LIVING MARK
   Isaiah 40:31 is on the logo, so on load the eagle does the one thing the
   verse says it does. Once, on arrival, and never again.
   ========================================================================== */

.mark { position: relative; display: block; aspect-ratio: 2351 / 760; width: 100%; }
.mark-eagle {
  position: absolute; left: 0; top: 3.88%;
  width: 40.88%; height: 96.12%;
  background-color: var(--mark-ink, #14202b);
  -webkit-mask: url("/assets/eagle-mask-480.png") no-repeat left center / contain;
          mask: url("/assets/eagle-mask-480.png") no-repeat left center / contain;
}
.mark-wm { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.mark-wm .lg-rule { transform-box: fill-box; transform-origin: 50% 50%; }

@media (prefers-reduced-motion: no-preference) {
  .mark-eagle { animation: mark-lift 1.15s var(--ease-out) .05s both; }
  .mark-wm .lg-rule { animation: mark-rule .5s var(--ease-out) .34s both; }
  .mark-wm .lg-rick  { animation: mark-word .62s var(--ease-out) .42s both; }
  .mark-wm .lg-ext   { animation: mark-word .62s var(--ease-out) .5s both; }
  .mark-wm .lg-llc   { animation: mark-word .62s var(--ease-out) .58s both; }
  .mark-wm .lg-verse { animation: mark-word .7s  var(--ease-out) .66s both; }
}
@keyframes mark-lift {
  from { opacity: 0; transform: translateY(9%) scale(.965); }
  to   { opacity: 1; transform: none; }
}
@keyframes mark-rule { from { opacity: 0; transform: scaleY(0); } to { opacity: 1; transform: none; } }
@keyframes mark-word {
  from { opacity: 0; transform: translateX(-9px); }
  to   { opacity: 1; transform: none; }
}

/* a two-pixel lift when you point at his name */
.brand .mark-eagle { transition: transform .5s var(--ease-out); }
@media (hover: hover) { .brand:hover .mark-eagle { transform: translateY(-2.5px); } }

/* header + footer sizing for the composed mark */
.brand .mark { width: 172px; }
/* At header size the full engraving silts up — this variant has the white
   feather lines opened out so they survive the downscale. */
.brand .mark-eagle {
  -webkit-mask-image: url("/assets/eagle-mask-sm-320.png");
          mask-image: url("/assets/eagle-mask-sm-320.png");
}
@media (max-width: 999px) { .brand .mark { width: 146px; } }
@media (max-width: 370px) { .brand .mark { width: 126px; } }
.footer-brand .mark { width: 200px; --mark-ink: #fff; }
.footer-brand .mark-eagle {
  -webkit-mask-image: url("/assets/eagle-mask-320.png");
          mask-image: url("/assets/eagle-mask-320.png");
}

/* ==========================================================================
   2026 POLISH — depth, balance, and scroll-driven reveal where supported
   ========================================================================== */

h1, h2, .lede { text-wrap: balance; }
.cutaway-panel p, .steprail-b, .creed-list span { text-wrap: pretty; }

.card {
  box-shadow:
    0 1px 2px rgba(20,32,43,.05),
    0 8px 24px -12px rgba(20,32,43,.18);
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease-out);
}
@media (hover: hover) {
  .card:hover {
    transform: translateY(-3px);
    box-shadow: 0 2px 4px rgba(20,32,43,.06), 0 20px 44px -18px rgba(20,32,43,.3);
  }
}

/* the thin line that tracks reading progress down the hero */
.hero-scrolling { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: rgba(255,255,255,.1); }
.hero-scrolling span { display: block; height: 100%; width: 0; background: var(--crimson); }

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-scrolling span {
      width: 100%;
      transform-origin: 0 50%;
      animation: hero-progress linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 100vh;
    }
    @keyframes hero-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  }
}

/* Pins need a real thumb target — the visible dot stays small, the hit area
   does not. The audit caught these at 34px. */
.pin { min-width: 44px; min-height: 44px; justify-content: flex-start; padding-left: 7px; }
.pin::before { content: ""; position: absolute; inset: 0; }
@media (max-width: 860px) { .pin { padding-left: 9px; } .pin > span { width: 28px; height: 28px; font-size: 12.5px; } }
@media (max-width: 560px) { .pin > span { width: 26px; height: 26px; font-size: 12px; } }
.d-rib { stroke: #8a7050; stroke-width: 2.2; opacity: .85; }

/* ── 6. SCRIM ────────────────────────────────────────────────────────────
   The woven face of synthetic underlayment — the Atlas Summit 60 that goes
   on every one of his roofs, and point three of the thirteen. Two weaves at
   different frequencies: the fine thread count, and the coarser reinforcing
   bundles that run through it. Then one chalk line snapped across the whole
   band at the angle a roofer would actually pull it.

   A roofer will recognise this ground immediately. Everyone else just reads
   it as a material rather than a blank white box, which is the job. */
.tx-scrim { position: relative; isolation: isolate; overflow: hidden; background-color: #fbfaf7; }
.tx-scrim::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    /* fine weave — warp */
    repeating-linear-gradient(90deg,
      rgba(20,32,43,.055) 0 1px, transparent 1px 7px),
    /* fine weave — weft, offset so the crossings alternate */
    repeating-linear-gradient(0deg,
      rgba(20,32,43,.045) 0 1px, transparent 1px 7px),
    /* reinforcing bundles, every fifth thread, slightly heavier */
    repeating-linear-gradient(90deg,
      rgba(20,32,43,.075) 0 2px, transparent 2px 35px),
    repeating-linear-gradient(0deg,
      rgba(20,32,43,.06) 0 2px, transparent 2px 35px),
    /* the warm pull of a resin-coated sheet under raking light */
    linear-gradient(102deg, rgba(168,98,44,.05), transparent 38%, rgba(60,74,85,.05));
  background-position: 0 0, 3px 3px, 0 0, 0 0, 0 0;
}
/* the snapped chalk line */
.tx-scrim::after {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  left: -12%; right: -12%; top: 30%; height: 2px;
  transform: rotate(-2.4deg);
  background: repeating-linear-gradient(90deg,
    rgba(43,108,176,.30) 0 26px,
    rgba(43,108,176,.13) 26px 33px,
    rgba(43,108,176,.30) 33px 54px,
    transparent 54px 57px);
  filter: blur(.35px);
  opacity: .75;
}
@media (max-width: 700px) {
  .tx-scrim::before { background-size: auto, auto, auto, auto, auto; }
  .tx-scrim::after { top: 22%; }
}

/* The cards sit on the scrim, so they need to read as laid *on* it —
   a hair more lift and a warm hairline rather than a cool grey one. */
.tx-scrim .card {
  border-color: rgba(20,32,43,.11);
  box-shadow:
    0 1px 2px rgba(20,32,43,.06),
    0 10px 28px -14px rgba(20,32,43,.26);
}

/* ==========================================================================
   THE MAIN MARK — the footer lockup
   The header mark is small and functional. This is the one that gets to be
   the signature: it arrives when you reach it, not when the page loads, and
   it takes its time. One light pass travels the wordmark the way a low sun
   crosses a standing seam, then it settles and stays still.
   ========================================================================== */

.footer-brand .mark { width: min(300px, 78%); }

@media (prefers-reduced-motion: no-preference) {
  /* Hold the whole lockup until it's actually on screen — the header copy
     already animated on load, and repeating that down here would read cheap. */
  .footer-brand .mark-eagle,
  .footer-brand .lg-rule,
  .footer-brand .lg-rick,
  .footer-brand .lg-ext,
  .footer-brand .lg-llc,
  .footer-brand .lg-verse { animation: none; opacity: 0; }

  .footer-brand .mark.in .mark-eagle {
    animation: mark-rise 1.5s var(--ease-out) both;
  }
  .footer-brand .mark.in .lg-rule  { animation: mark-rule .7s var(--ease-out) .5s both; }
  .footer-brand .mark.in .lg-rick  { animation: mark-set .9s var(--ease-out) .62s both; }
  .footer-brand .mark.in .lg-ext   { animation: mark-set .9s var(--ease-out) .74s both; }
  .footer-brand .mark.in .lg-llc   { animation: mark-set .9s var(--ease-out) .86s both; }
  .footer-brand .mark.in .lg-verse { animation: mark-set 1.1s var(--ease-out) 1s both; }

  /* (The first light pass lived here as .mark.in::after. It was unmasked and
     .mark doesn't clip, so translateX parked it to the right of the lockup as
     a visible grey band on the dark footer. The masked .mark-flash below
     replaced it.) */
}

/* A longer, slower lift than the header's — it has the room for it. */
@keyframes mark-rise {
  from { opacity: 0; transform: translateY(15%) scale(.94); filter: blur(3px); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: none; filter: none; }
}
@keyframes mark-set {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}
/* Pointing at it lifts the eagle and warms the rule — quiet, but it's alive. */
.footer-brand .mark .lg-rule { transition: fill .45s var(--ease-soft); }
@media (hover: hover) {
  .footer-brand .mark:hover .mark-eagle { transform: translateY(-4px); }
  .footer-brand .mark:hover .lg-rule { fill: #ff6b6b; }
}

/* ── cutaway v2: lit slabs instead of flat bands ─────────────────────────── */
.d-slab .f-top { stroke: rgba(255,255,255,.16); stroke-width: 1; }
.d-slab .f-cut { stroke: rgba(0,0,0,.45); stroke-width: 1; }
.d-slab .f-end { fill: rgba(0,0,0,.34); stroke: rgba(255,255,255,.08); stroke-width: 1; }
.d-rib  { stroke: #7a6144; stroke-width: 2.4; opacity: .7; }
.d-strand, .d-grain { pointer-events: none; }
.d-grain { mix-blend-mode: overlay; opacity: .4; }
.d-strand { mix-blend-mode: overlay; opacity: .55; }
.d-sunlit { pointer-events: none; }
.d-course { stroke: rgba(0,0,0,.4); stroke-width: 1.6; }
.d-nail { fill: #ffcf5c; stroke: #7a1219; stroke-width: 1.2; }
.d-drip { fill: none; stroke: #e2ebf2; stroke-width: 4; stroke-linejoin: round; stroke-linecap: round; }
.d-ridge .f-top { fill: #55636f; stroke: #9aa8b4; stroke-width: 1.2; }
.d-ridge .f-cut { fill: #2b3742; stroke: #7c8a96; stroke-width: 1.2; }
.d-boot path { fill: #313e4a; stroke: #a3b0bc; stroke-width: 1.6; }
.d-boot rect { fill: #5a6875; stroke: #a3b0bc; stroke-width: 1.4; }
.d-flash path { fill: #e2ebf2; stroke: #9dabb7; stroke-width: 1.1; }
.d-wall { fill: #1c2732; stroke: rgba(180,205,220,.4); stroke-width: 1.2; }

/* the three that happen around the job — these were too faint to find */
.d-tarp { fill: rgba(46,107,82,.75); stroke: none; }
.d-tarp-fold { fill: none; stroke: #63c79b; stroke-width: 2.4; }
.d-sweep { stroke: #e0555f; stroke-width: 5; stroke-linecap: round; fill: none; }
.d-sweep-arc { fill: none; stroke: rgba(224,85,95,.45); stroke-width: 2; stroke-dasharray: 4 6; }
.d-seal { fill: rgba(184,32,42,.22); stroke: #e0555f; stroke-width: 2; }
.d-seal-in { fill: none; stroke: rgba(224,85,95,.5); stroke-width: 1; stroke-dasharray: 3 4; }
.d-seal-t {
  fill: #ffd9dc; font-family: var(--display); font-weight: 800; font-size: 22px;
  letter-spacing: .02em;
}

/* ==========================================================================
   THE FLASH
   Same move as the Stafford Consulting nav brand: one slow left-to-right
   glint, then rest. Here it crosses the whole lockup at once — eagle, rule
   and wordmark — because this mark is one object, not a tile handing off to
   a word.

   A moving light band on the child, an alpha mask of the whole lockup on the
   parent, so light only ever falls on the ink. One cached PNG and no
   duplicated path data.

   (The band is moved with a transform, not background-position: percentage
   background-position is measured against container-minus-image, so once the
   gradient is wider than its box the percentages run backwards.)
   ========================================================================== */

.mark-flash {
  position: absolute; inset: 0; pointer-events: none; overflow: hidden;
  -webkit-mask: url("/assets/logo-mask-480.png") no-repeat center / 100% 100%;
          mask: url("/assets/logo-mask-480.png") no-repeat center / 100% 100%;
}
.mark-flash::before {
  content: ""; position: absolute; top: -30%; bottom: -30%;
  left: 0; width: 34%;
  /* A hard specular core with a crimson spark running just ahead of it —
     the brand colour leading the light. Wide soft sweeps disappear against
     dark ink; this reads as a flash. */
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(184,32,42,.55) 26%,
    rgba(255,255,255,1) 47%,
    rgba(255,255,255,1) 55%,
    rgba(255,236,238,.5) 68%,
    transparent 100%);
  /* No mix-blend-mode here. Blending the band with the page backdrop let it
     paint outside the mask — a grey smear beside the wordmark on the dark
     footer. The band reads fine composited normally. */
  transform: translateX(-160%) skewX(-16deg);
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  /* Header: once the build-in has settled, then every nine seconds. Slow
     enough to be a detail you catch rather than a thing that nags. */
  .brand .mark-flash::before { animation: mark-flash 9s linear 1.6s infinite both; }
  /* Footer: same beat, started when the lockup arrives. */
  .footer-brand .mark.in .mark-flash::before { animation: mark-flash 9s linear 3.2s infinite both; }
}

@keyframes mark-flash {
  0%   { transform: translateX(-190%) skewX(-16deg); opacity: 0; }
  2%   { opacity: 1; }
  21%  { transform: translateX(360%) skewX(-16deg); opacity: 1; }
  23%  { transform: translateX(360%) skewX(-16deg); opacity: 0; }
  100% { transform: translateX(360%) skewX(-16deg); opacity: 0; }
}

/* Point at it and it flashes on demand rather than on the clock. */
@media (hover: hover) {
  .brand:hover .mark-flash::before,
  .footer-brand .mark:hover .mark-flash::before {
    animation: mark-flash 2.6s linear 0s 1 both;
  }
}

/* The footer mark is large and reversed out of a dark ground, so it takes a
   warmer pass — a low sun crossing metal rather than a white spark. */
.footer-brand .mark-flash {
  -webkit-mask-image: url("/assets/logo-mask-960.png");
          mask-image: url("/assets/logo-mask-960.png");
}
.footer-brand .mark-flash::before {
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,138,96,.5) 26%,
    rgba(255,248,236,1) 47%,
    rgba(255,248,236,1) 55%,
    rgba(255,206,160,.5) 68%,
    transparent 100%);
}

/* ── Mark up a third, across the top ──────────────────────────────────────
   172 -> 229px. The lockup is 3.09:1, so it grows to ~74px tall and the
   header grows with it rather than cropping the mark. */
.brand .mark { width: 229px; }
@media (max-width: 1339px) { .brand .mark { width: 210px; } }
@media (max-width: 999px)  { .brand .mark { width: 195px; } }
@media (max-width: 560px)  { .brand .mark { width: 176px; } }
@media (max-width: 370px)  { .brand .mark { width: 152px; } }

.header-inner { min-height: max(var(--header-h), 84px); }
@media (max-width: 999px) { .header-inner { min-height: max(var(--header-h), 76px); } }

/* ==========================================================================
   THE SEAL IN THE SKY
   The upper right of the hero was a quadrant of empty sky and bare branches.

   The eagle was the obvious thing to put there — his mark is an eagle and the
   verse on his logo is Isaiah 40:31 — but the artwork bleeds off all four
   edges, so blown up it is a rectangle of magnified feather texture with a
   hard edge, not a bird. Same constraint that stopped it becoming a badge.

   So the sky gets the promise instead: the fifteen-year warranty, struck as a
   seal. It is the one thing he offers that nobody around here matches, it is
   already a motif further down the page, and a struck circle in open sky is a
   composition that has worked for a hundred years. Thin rings and no fill, so
   it reads as a seal rather than a sticker.
   ========================================================================== */

.hero-seal {
  position: absolute; z-index: 1; pointer-events: none;
  top: clamp(4.5rem, 11vh, 8rem);
  right: clamp(2rem, 7vw, 8rem);
  width: clamp(140px, 15vw, 208px);
  height: auto;
  transform: rotate(-7deg);
  opacity: .46;
  overflow: visible;
}
.seal-ring { fill: none; stroke: #fff; stroke-width: 1.1; }
.seal-ring-2 { stroke-dasharray: 2 7; stroke-width: 1; opacity: .8; }
.seal-arc {
  fill: #fff; font-family: var(--display); font-weight: 700;
  font-size: 13.5px; letter-spacing: .26em;
}
.seal-n {
  fill: #fff; font-family: var(--display); font-weight: 800;
  font-size: 62px; letter-spacing: -.03em;
}
.seal-yr {
  fill: #fff; font-family: var(--display); font-weight: 700;
  font-size: 15px; letter-spacing: .34em; opacity: .85;
}
.seal-rule { stroke: var(--crimson); stroke-width: 3; }

/* It arrives with the headline rather than sitting there from the first
   frame — struck onto the sky, then still. */
@media (prefers-reduced-motion: no-preference) {
  .hero-seal { animation: seal-strike 1.1s cubic-bezier(.2,.9,.25,1) .55s both; }
}
@keyframes seal-strike {
  from { opacity: 0; transform: rotate(-7deg) scale(1.16); }
  to   { opacity: .46; transform: rotate(-7deg) scale(1); }
}

/* Below the desktop breakpoint the headline owns the frame and the seal would
   only sit behind type. */
@media (max-width: 1099px) { .hero-seal { display: none; } }
@media (max-height: 620px) { .hero-seal { display: none; } }

/* ==========================================================================
   ── SECTION SURFACES ─────────────────────────────────────────────────────
   A flat fill across a full-width band reads as cheap no matter how good the
   colour is — the eye needs something to catch on. Each band below gets a
   surface drawn from the trade itself: suede, a snapped chalk line, mineral
   granule, a survey plat. All of them are CSS; nothing here is an image.
   ========================================================================== */

/* ── SUEDE ───────────────────────────────────────────────────────────────
   A napped surface, not a colour swatch. Three things make nap read: very
   fine anisotropic noise (the fibres lie one way), a broad soft sheen where
   the light falls, and a darker fall-off at the far edge. Brush a real piece
   of suede and the pile changes tone — that is the effect here. */
.tx-suede {
  position: relative; isolation: isolate;
  background-color: var(--crimson);
  /* Deeper overall, and the highlight pulled right back — at .15 it blew out
     into pink and the whole band read as a gradient rather than a surface. */
  background-image:
    radial-gradient(150% 120% at 30% -25%, rgba(255,255,255,.07), transparent 52%),
    linear-gradient(165deg, #96202b 0%, #85161f 45%, #6b0f17 100%),
    radial-gradient(120% 100% at 50% 50%, transparent 58%, rgba(0,0,0,.22));
}
.tx-suede::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  /* the pile: stretched noise, so the grain runs in one direction */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='s'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.15 .42' numOctaves='4'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .9 0 0 0 0 .88 0 0 0 .34 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23s)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='t'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.14 .045' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .2 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23t)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
  opacity: 1;
}
/* the brushed pass — where a hand has run across the nap */
.tx-suede::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(104deg,
    transparent 22%, rgba(255,255,255,.045) 40%,
    rgba(255,255,255,.075) 50%, rgba(255,255,255,.03) 60%, transparent 78%);
}
.cta-strip.tx-suede { color: #fff; }
.cta-strip .btn-ghost { border-color: rgba(255,255,255,.55); color: #fff; }
.cta-strip .btn-primary { background: #fff; color: var(--crimson-d); }

/* ── CHALK ───────────────────────────────────────────────────────────────
   The blue lines a roofer snaps on bare decking before the first course goes
   down. Loose, slightly off-square, and faded — chalk does not sit in a neat
   grid, so neither does this. Under the job photos, which is exactly where
   chalk lines belong. */
.tx-chalk { position: relative; isolation: isolate; overflow: hidden; background-color: #f7f8f9; }
.tx-chalk::before {
  content: ""; position: absolute; inset: -10%; z-index: -1; pointer-events: none;
  background-image:
    repeating-linear-gradient(91.4deg, rgba(43,108,176,.11) 0 1.5px, transparent 1.5px 168px),
    repeating-linear-gradient(.7deg,  rgba(43,108,176,.09) 0 1.5px, transparent 1.5px 196px),
    repeating-linear-gradient(90.6deg, rgba(43,108,176,.05) 0 1px,  transparent 1px 56px);
  filter: blur(.3px);
}
.tx-chalk::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(90% 70% at 50% 40%, transparent 55%, rgba(20,32,43,.045));
}

/* ── MINERAL ─────────────────────────────────────────────────────────────
   Shingle granules seen in daylight rather than in shadow: the same crushed
   rock as tx-granule, but pale, so the reviews block reads as a light stone
   field instead of a white void. */
.tx-mineral { position: relative; isolation: isolate; background-color: #f4f2ef; }
.tx-mineral::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 .32 0 0 0 0 .34 0 0 0 0 .36 0 0 0 .34 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E"),
    radial-gradient(130% 100% at 50% 0%, rgba(255,255,255,.85), transparent 62%);
  opacity: .8;
}

/* ── PLAT ────────────────────────────────────────────────────────────────
   The service-area band, set like a plat map margin: a fine survey grid,
   hairline rules top and bottom, and tick marks at a regular interval. */
.tx-plat { position: relative; isolation: isolate; background-color: #16222d; overflow: hidden; }
.tx-plat::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    linear-gradient(rgba(140,180,205,.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(140,180,205,.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(140,180,205,.18) 1px, transparent 1px);
  background-size: 14px 14px, 14px 14px, 112px 100%;
}

/* ── The service-area band, rebuilt ───────────────────────────────────────
   It was a row of grey words sliding past. Now it reads like the margin of a
   plat map: hairline rules with survey ticks, town names letterspaced in
   small caps, a crimson lozenge between each, and the edges dissolved so the
   towns arrive out of the dark instead of being chopped off by the frame.

   St. Stephen is marked differently because that is where he actually is. */

.towns {
  position: relative; overflow: hidden; border: 0;
  padding-block: 1.9rem;
  --edge: 13%;
  -webkit-mask: linear-gradient(90deg, transparent, #000 var(--edge), #000 calc(100% - var(--edge)), transparent);
          mask: linear-gradient(90deg, transparent, #000 var(--edge), #000 calc(100% - var(--edge)), transparent);
}
.towns-rule {
  position: relative; height: 9px;
  background-image:
    linear-gradient(rgba(190,215,232,.34) 1px, transparent 1px),
    repeating-linear-gradient(90deg, rgba(190,215,232,.34) 0 1px, transparent 1px 28px);
  background-size: 100% 1px, 28px 9px;
  background-repeat: no-repeat, repeat-x;
  background-position: 0 0, 0 0;
}
.towns-rule:last-child { transform: scaleY(-1); }

.towns-track {
  display: flex; align-items: center; gap: 0; width: max-content;
  margin-block: 1.15rem;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1rem, .72rem + .7vw, 1.32rem);
  letter-spacing: .13em; text-transform: uppercase;
  color: #a9bccb;
  animation: slide 62s linear infinite;
}
.towns-track span { padding-inline: 1.5rem; white-space: nowrap; }
.towns-track span::after {
  content: ""; display: inline-block; vertical-align: middle;
  width: 5px; height: 5px; margin-left: 3rem;
  background: var(--crimson-lt); transform: rotate(45deg);
  margin-right: -1.5rem;
}
/* the home town */
.towns-track span.is-home {
  color: #fff;
  position: relative;
}
.towns-track span.is-home::before {
  content: ""; position: absolute; left: .55rem; top: 50%;
  width: 7px; height: 7px; margin-top: -3.5px; border-radius: 50%;
  background: var(--crimson-lt);
  box-shadow: 0 0 0 4px rgba(158,26,38,.3);
}
.towns-track span.is-home { padding-left: 2rem; }

@keyframes slide { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .towns-track { animation: none; } }
.towns:hover .towns-track { animation-play-state: paused; }

/* the section that holds it goes dark so the plat ground reads */
.section-tight:has(> .towns) { background: #16222d; color: #c3d1db; }
.section-tight:has(> .towns) .eyebrow { color: #ff7a83; }
.section-tight:has(> .towns) a { color: #fff; }

/* ── The footer gets a ground too ─────────────────────────────────────────
   Flat #14202b under everything else made the bottom of the page fall off a
   cliff. Same crushed-rock tooth as the dark bands above, plus a standing
   seam running down through it, so the page ends on a material rather than
   on a void. */
.footer {
  position: relative; isolation: isolate; overflow: hidden;
  background: linear-gradient(180deg, #16232e 0%, #101b24 55%, #0c151c 100%);
}
.footer::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 .75 0 0 0 0 .8 0 0 0 0 .85 0 0 0 .3 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.035) 0 1px,
      transparent 1px 3px,
      transparent 3px 92px,
      rgba(0,0,0,.22) 92px 94px,
      transparent 94px 96px);
  mix-blend-mode: overlay;
  opacity: .55;
}
/* a hairline of the brand red where the page ends */
.footer::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; z-index: -1;
  background: linear-gradient(90deg, var(--crimson-d), var(--crimson-lt) 40%, var(--crimson-d));
}
