/* ============================================================================
   BLACK WIDOW SEALCOATING

   Register: work-truck posture with a credentialed backbone. Light dominant,
   two dark bands used as scroll punctuation rather than as the default, one
   brand color in a small number of strong placements.

   The palette is the spider. Asphalt black, fresh-concrete paper, hourglass
   red. It is the black and red Grant already uses, made deliberate.

   Square corners everywhere. Nothing this trade does is soft, and rounded
   cards read as a software company. --radius is 0 on purpose; do not "fix" it.

   WebKit's base.css consumes: --action --bord --bord-soft --font-body
   --font-display --gutter --ink --paper --radius --section-pad
   --section-pad-tight --wrap. Those are a contract. Everything else below is
   ours.
   ========================================================================= */

/* Fonts are self-hosted and declared inline in App.razor's <head>.
   The @import that lived here was invisible to the preload scanner and made
   a 4-hop chain; fonts were not requested until ~1.8s and the swap caused
   the site's only CWV failure (CLS 0.122 on /service-area/). */

:root {
  /* --- the contract base.css reads ------------------------------------- */
  --ink:              #16181C;
  --paper:            #F4F2EF;
  --action:           #B9121B;
  --bord:             rgba(22, 24, 28, 0.16);
  --bord-soft:        rgba(22, 24, 28, 0.08);
  --radius:           0;
  --wrap:             1180px;
  /* A single container width for every band is the strongest structural tell of
     a template: the left and right edges never move for six thousand pixels of
     scrolling. Every premium peer measured runs three or four. This is the
     first of them. See research/16-design-research.md section 2.2. */
  --wrap-wide:        1440px;
  /* Running text wants ~65 characters. At 1180px and 17px it runs about 140,
     which is the single biggest readability failure on the site and a two-line
     fix. Prose bands opt into this. */
  --wrap-text:        42rem;
  --gutter:           clamp(1.15rem, 4vw, 3rem);
  /* 8.5rem was chased out of a "premium rhythm is 96-160px" note and it was the
     wrong reading. That range is the padding INSIDE a band, and applying it top
     and bottom to sixteen adjacent bands put 272px of empty paper at every
     boundary. On screen it did not read as luxury, it read as a page that had
     run out of things to say: the eye crosses two hundred pixels of nothing and
     arrives at a heading with no momentum.

     Premium sites are DENSER than design tutorials suggest. Three steps now,
     picked per band rather than one applied to all: --lg for the two bands that
     carry the argument, the default for most, --tight after a photograph, which
     has already supplied the breath. */
  --section-pad-lg:   clamp(4.5rem, 7vw, 7rem);
  --section-pad:      clamp(3.25rem, 5vw, 5rem);
  --section-pad-tight: clamp(2rem, 3.5vw, 3rem);
  --font-display:     "Archivo", "Arial Narrow", Helvetica, sans-serif;
  --font-body:        "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

  /* --- ours ------------------------------------------------------------ */
  --surface:          #FFFFFF;
  --surface-2:        #EAE7E2;
  --ink-2:            #3A3E45;
  --steel:            #6B6B70;   /* neutral, warmed a touch toward the red */
  --action-deep:      #8E0D14;
  --gold:             #D99414;   /* star ratings only, never brand */

  /* GEOMETRY AND ELEVATION, one dial each (PA-33).

     Before this, the hs- layer carried 8 hand-typed radius values and ~14
     near-duplicate shadows; three of them were the same shadow spelled with
     different alphas. Meanwhile the WebKit-consumed controls were already
     square via --radius:0, so the page mixed square controls with 6-8px
     cards, which is exactly the "styled HTML, not components" tell.

     The register at the top of this file says square corners everywhere and
     it was right; the rounding was drift. Both tokens resolve to 0 today.
     They stay separate so cards and controls can be dialed independently if
     the register ever changes; change them HERE, never at a call site. */
  --radius-card:      0;         /* cards, panels, media containers */
  --radius-ctl:       0;         /* buttons, chips, thumbs, icon squares */

  /* Elevation ladder, three steps plus one chip shadow. Pick the step, never
     write a bespoke shadow. 1 = resting lift on paper. 2 = floating card on
     paper. 3 = floating card on a dark or photographic ground. chip = small
     control sitting on a photo. */
  --shadow-1:         0 1px 2px rgba(22,24,28,.06), 0 2px 10px rgba(22,24,28,.05);
  --shadow-2:         0 12px 30px rgba(22,24,28,.08);
  --shadow-3:         0 24px 60px rgba(0,0,0,.5);
  --shadow-chip:      0 6px 18px rgba(0,0,0,.25);

  /* One focus ring. Two alphas existed (.14 light card, .28 dark card); one
     value reads on both grounds. */
  --focus-ring:       0 0 0 3px rgba(185,18,27,.22);

  /* THE THIRD ROLE, and the thing the palette was missing.

     West Shore Home works because ground, action and accent are three separate
     colours doing three separate jobs. Here red was all three at once, so there
     was nothing left to signal "expensive" with that did not also mean "click
     me". The measured fix is a third hue used six or seven times on the whole
     page and never on a control.

     Not gold: navy-and-gold is a remodelling register and this trade is diesel
     and frost. This is the yellow of a fresh lane line, which is already in
     half the photographs on this site, on the cones, the hi-vis, the kettle and
     the striping itself. It is the trade's own marking-out colour rather than a
     brand colour we invented, which is why it can carry structure without
     reading as decoration.

     ALLOWED: the lead rule on a band head, the proof-band stage tab, the rule
     over the dark spec band. Roughly six placements.
     NEVER: a button, body text, a link, a border on a card, a bullet. */
  --line:             #E8B10A;
  --good:             #1F7A46;   /* open status, verdict Fix */
  --warn:             #B0730A;   /* verdict Maybe */
  --dark-bg:          #16181C;
  --dark-ink:         #F4F2EF;
  --dark-ink-2:       #A9ADB4;
  --dark-bord:        rgba(244, 242, 239, 0.16);
  --hatch:            rgba(22, 24, 28, 0.07);
  /* Popover shadow: dropdown panels and the scrolled header, elements that
     float OVER content rather than sitting in it. Part of the PA-33 ladder
     with --shadow-1/2/3 above; the old --shadow hairline folded into
     --shadow-1. */
  --shadow-pop:       0 24px 48px -30px rgba(22,24,28,.6);

  /* ASPHALT, AS A GROUND.

     The page ran paper / white / paper / white, and the three light grounds
     (#F4F2EF, #FFFFFF, #EAE7E2) are close enough that the band rhythm was
     nearly invisible.

     This is Grant's own asphalt background off blackwidowsealcoating.com,
     1920x1280 of real aggregate with real cracks in it, resized and dropped to
     a quality it can afford because it never appears without a scrim over it.

     Written down because two wrong answers came first and both are the obvious
     thing to reach for. A CSS gradient is AI slop flag 7 and would have read as
     an agent trying to make a flat band look designed. Then a texture tile
     GENERATED from one of the job photos, which failed twice: mirroring it to
     kill the seam introduced bilateral symmetry, and the eye finds symmetry
     instantly, so the page filled with little butterflies. Retargeting it at a
     better crop then produced a tile whose source, measured, contained almost
     no aggregate at all: lot-sealed-institutional is a car park photographed
     from fifty feet at 1400px, about four pixels per stone.

     Wayne stopped it: "just take an asphalt background like he had on his
     website". He was right, and the lesson generalises. The client had already
     solved this, and an hour went into synthesising a worse version of a file
     that was sitting on his own home page. Look at what the client already has
     before building anything that represents them. */
  --tex-asphalt:      url("/assets/black-widow-sealcoating/asphalt-bg.jpg");
}

/* Dark mode is deliberately NOT implemented. The audience is a homeowner in a
   driveway and a property manager on a laptop, the register is light-dominant
   by doctrine, and a half-considered dark theme on a contractor site reads as
   a template. Everything below paints its own ground explicitly, so the page
   holds regardless of what the browser prefers. */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, .display {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.06;
  text-wrap: balance;
  margin: 0;
}

/* Archivo carries a width axis and every heading was pinned to 112%, so there
   was no width contrast on the page at all. Big statements go near-normal and
   let size do the work; small heads go expanded, which reads engineered at a
   size where it can be seen. Tracking scales with size because it is an optical
   correction, not a style. */
h1 { font-size: clamp(2.6rem, 6.2vw, 4.75rem); font-weight: 800; font-stretch: 96%;  letter-spacing: -0.032em; }
h2 { font-size: clamp(1.9rem, 4vw,   3rem);    font-stretch: 108%; letter-spacing: -0.024em; }
h3 { font-size: clamp(1.12rem, 1.8vw, 1.35rem); font-stretch: 118%; letter-spacing: -0.010em; }
h4 { font-stretch: 118%; letter-spacing: -0.008em; }

p { margin: 0 0 1rem; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

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

/* WebKit's base.css sets `.wrap { width: min(100% - 2*gutter, var(--wrap)) }`,
   a WIDTH, and a max-width cannot override a width. The two variants below were
   written as max-width and did nothing at all: both bands opted into
   --wrap-wide and both kept rendering at 1180. The width had to be restated in
   the same form to win.

   Worth remembering the next time a token appears to be ignored: check what
   PROPERTY the shared sheet used before assuming a specificity problem. */
.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.wrap--wide { width: min(100% - 2 * var(--gutter), var(--wrap-wide)); max-width: var(--wrap-wide); }
.wrap--text { width: min(100% - 2 * var(--gutter), var(--wrap-text)); max-width: var(--wrap-text); }

/* Prose measure, applied where paragraphs are read rather than scanned. The
   band-head intro and the prose blocks are the two that run long. */
.band-head p, .prose p, .prose li { max-width: var(--wrap-text); }

a:focus-visible, button:focus-visible, summary:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--action);
  outline-offset: 3px;
}

/* Long unbroken strings are the classic narrow-viewport overflow: an email
   address or a URL has no space to wrap at, so it pushes the document wider
   than the screen. This is cheaper than chasing each one. */
a, p, li, td, dd, .nap-email, .leadform__legal { overflow-wrap: anywhere; }
.hdr-phone, .mobar a, .btn { overflow-wrap: normal; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-body); font-weight: 700; font-size: 1rem;
  padding: .95rem 1.5rem;
  border: 2px solid transparent; border-radius: var(--radius);
  text-decoration: none; cursor: pointer; text-align: center; white-space: nowrap;
  transition: background-color .14s ease, color .14s ease, border-color .14s ease;
}
.btn--primary { background: var(--action); color: #fff; }
.btn--primary:hover { background: var(--action-deep); color: #fff; }
.btn--ink { background: var(--ink); color: var(--paper); }
.btn--ink:hover { background: var(--ink-2); }
.btn--ghost { border-color: currentColor; background: transparent; }
.btn--ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn--lg { font-size: 1.05rem; padding: 1.1rem 1.9rem; }
/* The ghost button over a photograph. .btn--ghost fills with --ink on hover,
   which on a dark hero means it disappears into the scrim. */
.btn--onshot { border-color: rgba(244,242,239,.55); color: var(--dark-ink); background: transparent; }
.btn--onshot:hover { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.btn--block { display: flex; width: 100%; }

/* Two buttons side by side, with the second falling under the first on a narrow
   screen. The obvious version, margin-left on the second one, is a trap: when it
   wraps, that margin still counts toward the parent's scroll width, so the page
   gains a two-pixel horizontal scrollbar that no visible element accounts for.
   Gap on a flex container does not do that. */
.btn-row { display: flex; flex-wrap: wrap; gap: .6rem; }

/* white-space: nowrap above keeps "Call (715) 450-9897" from breaking after
   "Call" on an ordinary screen, which is what it is for. On a 320px phone it
   stops being a nicety: a label like "Text photos to (715) 450-9897" is then
   two pixels wider than the viewport and the whole document scrolls sideways
   because of it. Below 360px a wrapped button is the lesser evil. */
@media (max-width: 360px) {
  .btn { white-space: normal; }
}

/* -------------------------------------------------------- eyebrow + mark */

/* Tracking runs the other way on caps: the smaller it is, the more it needs.
   This is the widest thing on the page, at eleven pixels. */
.eyebrow {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-size: .7rem; font-weight: 700; font-stretch: 125%;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--steel);
  margin: 0 0 1.1rem;
}
/* At 125% width and .16em tracking these run long, and a phone is 342px of
   content. Without flex-wrap the row simply overflowed its own container; with
   it, a long label breaks under the rule rather than beside it. Tightening the
   tracking keeps most of them on one line, which is what the rule is for. */
@media (max-width: 520px) {
  .eyebrow { letter-spacing: .11em; font-stretch: 118%; }
  .band-head .eyebrow::before, .eyebrow--ruled::before { width: 20px; }
}
.eyebrow--light { color: var(--dark-ink-2); }
.hourglass { width: 11px; height: 11px; flex: none; color: var(--action); }

/* ----------------------------------------------------------------- header */

/* Topbar on Clear View's chip pattern: icon-led utility facts on ink.
   The open pill's green dot reads as live status. */
.topbar { background: var(--ink); color: var(--paper); font-size: .8rem; }
.topbar .wrap { display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: .4rem 1.6rem; padding-block: .5rem; }
.topbar__chip { display: inline-flex; align-items: center; gap: .5em;
  color: rgba(244,242,239,.85); font-weight: 600; }
.topbar__chip svg { opacity: .65; flex: none; }
a.topbar__chip { text-decoration: none; color: #fff; }
a.topbar__chip:hover { color: #fff; text-decoration: underline; text-underline-offset: .25em; }
.topbar__chip--phone { font-weight: 700; }
.topbar__chip--phone svg { opacity: .9; }
.openpill { display: inline-flex; align-items: center; gap: .45em; font-weight: 700; }
.openpill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #3FB950; box-shadow: 0 0 6px rgba(63,185,80,.7); }
.openpill--closed::before { background: var(--steel); box-shadow: none; }
/* Phones keep the live state and the number; the location chip yields. */
@media (max-width: 560px) { .topbar__chip--loc { display: none; } }

.site-header {
  position: sticky; top: 0; z-index: 40;
  background: var(--surface);
  border-bottom: 1px solid var(--bord);
  box-shadow: var(--shadow-1);
}
.site-header .wrap { display: flex; align-items: center; gap: 1.1rem; padding-block: .8rem; }

.brand { display: flex; align-items: center; gap: .65rem; text-decoration: none; margin-right: auto; }
/* The client's own lettering, shipped as artwork rather than reset in a
   webfont. It is a heavy sign-shop italic and there is no free face that
   matches it; approximating a logo is worse than using it. Height-driven so
   the header row governs, and the intrinsic width/height on the tag reserves
   the space so nothing jumps while it loads. */
.brand__logo { height: 56px; width: auto; flex: none; }
/* .brand__mark and .brand__txt went with the wordmark they belonged to. They
   set an Archivo lockup that stood in for a logo we did not have; we have his
   now. orphan-classes finds markup with no rule behind it and cannot see the
   reverse, so dead rules have to be removed by hand or they accumulate. */

.hdr-rating { display: flex; align-items: center; gap: .45rem; font-size: .86rem; font-weight: 600; white-space: nowrap; }
.stars { color: var(--gold); letter-spacing: .04em; }

.hdr-phone {
  font-family: var(--font-display); font-weight: 800; font-stretch: 108%;
  font-size: 1.3rem; text-decoration: none; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

.site-nav { display: flex; align-items: center; gap: 1.1rem; font-size: .93rem; font-weight: 600; }
.site-nav a { text-decoration: none; white-space: nowrap; }

/* ------------------------------------------------------- services dropdown */

/* CSS only. Opens on :hover and on :focus-within, so it works for a mouse, for
   a keyboard, and with JavaScript broken. The header is the last component on
   a site that should depend on a script having loaded.

   The panel is positioned against .site-header rather than the item, because
   the header is the sticky, overflow-visible ancestor and nine two-line rows
   are wider than the word "Services". */
.navdrop { position: relative; }
.navdrop__top { display: inline-flex; align-items: center; gap: .38rem; }
.navdrop__chev { width: 10px; height: 7px; flex: none; transition: transform .16s ease; }
.navdrop:hover .navdrop__chev, .navdrop:focus-within .navdrop__chev { transform: rotate(180deg); }

.navdrop__panel {
  position: absolute; top: 100%; left: -1rem; z-index: 45;
  /* An absolutely positioned box with no width shrink-to-fits, and shrink-to-fit
     is capped by the containing block, which here is the 71px-wide "Services"
     item. Without this the three-column grid was squeezed into 139px and ran
     1,646px down the page. width: max-content lets it be as wide as its
     content; max-width keeps it inside the viewport at 1200px, the narrowest
     width this nav is shown at. */
  width: max-content; max-width: min(48rem, calc(100vw - 4rem));
  /* The gap between the item and the panel is a dead zone the pointer crosses.
     Padding on the panel rather than a margin keeps it hoverable the whole way
     down, which is the difference between a menu and a menu that closes on
     you. */
  padding-top: .85rem;
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .14s ease, transform .14s ease, visibility 0s linear .14s;
}
.navdrop:hover .navdrop__panel,
.navdrop:focus-within .navdrop__panel {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity .14s ease, transform .14s ease, visibility 0s;
}
.navdrop__grid {
  display: grid; grid-template-columns: repeat(3, minmax(0, 15rem));
  background: var(--surface); border: 1px solid var(--bord);
  box-shadow: var(--shadow-pop);
  padding: .4rem;
}
.navdrop__grid a {
  display: block; padding: .7rem .85rem; white-space: normal;
  border: 1px solid transparent;
}
.navdrop__grid a:hover, .navdrop__grid a:focus-visible { background: var(--paper); }
.navdrop__grid b { display: block; font-family: var(--font-display); font-stretch: 112%; font-size: .95rem; }
.navdrop__grid span {
  display: block; margin-top: .2rem; font-size: .8rem; font-weight: 500;
  line-height: 1.35; color: var(--steel);
  /* Two lines of blurb, so nine rows stay a scannable block rather than nine
     paragraphs. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.navdrop__all {
  display: block; background: var(--ink); color: var(--paper);
  padding: .7rem .95rem; font-size: .85rem; font-weight: 700;
  border: 1px solid var(--ink); border-top: 0;
}
.navdrop__all:hover { background: var(--ink-2); color: var(--paper); }
/* The nav's generic underline-on-hover would fire on all ten links inside the
   panel at once, since the panel is only open while the parent is hovered. */
.site-nav .navdrop__panel a:hover { text-decoration: none; }
@media (prefers-reduced-motion: reduce) {
  .navdrop__panel { transition: none; }
  .navdrop__chev { transition: none; }
}
/* Hover is a promise of an action, not an action. Premium sites signal it with
   the weight of a rule rather than a change of hue. */
.site-nav a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: .28em; text-decoration-thickness: 2px; }

/* THREE BREAKPOINTS THAT HAVE TO AGREE, AND DID NOT.

   The nav hid at 1200px, the hamburger appeared at 1080px, and the sticky
   bottom bar appeared at 640px. So:

     1081-1200px  no nav, NO HAMBURGER, no CTA. Wordmark and a phone number.
                  An iPad Pro 11 in landscape is 1194px and landed here.
     641-1200px   no CTA button anywhere in the page chrome.

   The comment below used to read "the sticky bottom bar carries this action on
   small screens". It did not; it started 560px lower. That comment is exactly
   how the gap survived review: it described an intent nobody checked.

   Now the hamburger appears at the same width the nav disappears, and the
   header CTA survives until the sticky bar takes over. There is no width at
   which a visitor cannot both navigate and convert.

   PA-21 moved the handoff from 1200 to 1020: 1200-and-under includes
   ordinary small laptops, which were getting a hamburger beside an acre of
   empty header. The nav tightens first, then hands off. The hamburger rule
   below MUST keep the same 1020 width. */
@media (max-width: 1200px) {
  .site-nav { gap: .7rem; font-size: .88rem; }
  .hdr-rating { display: none; }
  /* The three-column dropdown panel overflows the viewport once the nav
     survives below 1200 (it anchors under Services, the leftmost item);
     two columns keep it inside with room to spare. */
  .navdrop__grid { grid-template-columns: repeat(2, minmax(0, 15rem)); }
}
@media (max-width: 1020px) {
  .site-nav { display: none; }
}
@media (max-width: 620px) {
  /* Below this the wordmark, phone and CTA cannot share a row, and the sticky
     bar is showing, so the header CTA stands down. */
  .site-header .wrap > .btn { display: none; }
}
@media (max-width: 620px) {
  .site-header .wrap { gap: .65rem; }
  .hdr-phone { font-size: 1.08rem; }
}
/* The wordmark scales rather than shedding parts. When the header was set type
   the tagline could be dropped at 520 and the name at 430, leaving the mark
   alone; artwork cannot be taken apart that way, and it does not need to be.
   At 34px the lockup is still the thing on his truck, which is the whole point
   of using it. */
@media (max-width: 520px) {
  .brand__logo { height: 44px; }
  .hdr-phone { font-size: 1rem; }
  .mnav-toggle { width: 40px; height: 40px; }
  .mnav-toggle span, .mnav-toggle span::before, .mnav-toggle span::after { left: 9px; width: 22px; }
  .mnav-toggle span { top: 19px; }
}
@media (max-width: 430px) {
  .brand__logo { height: 38px; }
  .site-header .wrap { gap: .5rem; }
}

/* ------------------------------------------------------------- mobile nav */
/* Class contract with the shared mobilenav.js. State classes land on <body>. */

.mnav-toggle {
  display: none; width: 44px; height: 44px; flex: none;
  background: transparent; border: 1px solid var(--bord); border-radius: var(--radius);
  cursor: pointer; position: relative;
}
/* STRIPE-GRADE DRAWER (PA-34). The shared mobilenav.js contract is
   unchanged; everything here is presentation. Four moves make the feel:
   the hamburger morphs to an X, the backdrop blurs in, the sheet
   decelerates in on a spring-ish curve and leaves faster than it arrived,
   and the links stagger up as the sheet lands. Exit transitions live on
   the base selectors, entrance transitions on the body.mnav-open state,
   so the two directions get different curves. */
.mnav-toggle span, .mnav-toggle span::before, .mnav-toggle span::after {
  content: ""; position: absolute; left: 11px; width: 22px; height: 2px;
  background: var(--ink);
  transition: transform .28s cubic-bezier(.4,0,.2,1), top .28s cubic-bezier(.4,0,.2,1),
              background .12s ease .1s;
}
.mnav-toggle span { top: 21px; }
.mnav-toggle span::before { top: -7px; left: 0; }
.mnav-toggle span::after { top: 7px; left: 0; }
body.mnav-open .mnav-toggle span { background: transparent; transition-delay: 0s; }
body.mnav-open .mnav-toggle span::before { top: 0; transform: rotate(45deg); }
body.mnav-open .mnav-toggle span::after { top: 0; transform: rotate(-45deg); }

.mnav { position: fixed; inset: 0; z-index: 60; visibility: hidden; overflow: hidden; }
.mnav__backdrop {
  position: absolute; inset: 0; background: rgba(10,11,13,.5);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .24s ease;
}
.mnav__panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(420px, 100vw);
  background: var(--surface); padding: 5rem 1.6rem calc(1.6rem + env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
  transform: translateX(48px); opacity: 0;
  transition: transform .24s cubic-bezier(.4,0,1,1), opacity .18s ease;
  overflow-y: auto; box-shadow: var(--shadow-pop);
}
/* Grouped sheet (Wayne, 2026-08-25): section labels, a two-column
   service grid, compact rows without the hairline wall, and the asks as
   buttons pinned at the bottom of the sheet. */
.mnav__label {
  margin: 1.6rem 0 .5rem; font-family: var(--font-display); font-weight: 600;
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase; color: var(--steel);
  display: flex; align-items: center; gap: .55rem;
}
.mnav__label::before { content: ""; flex: none; width: 20px; height: 3px; background: var(--action); }
.mnav__label:first-child { margin-top: 0; }
.mnav__grid { display: grid; grid-template-columns: 1fr 1fr; gap: .1rem .9rem; }
.mnav__link {
  padding: .55rem 0; text-decoration: none; font-weight: 600; font-size: 1rem;
  color: var(--ink);
}
.mnav__link--all { color: var(--action); }
.mnav__ctas { margin-top: auto; padding-top: 1.6rem; display: grid; gap: .6rem; }
.mnav__cta {
  background: var(--action); color: #fff;
  padding: .95rem; text-align: center; font-weight: 700; text-decoration: none;
  font-family: var(--font-display);
}
.mnav__cta--ghost {
  background: transparent; color: var(--ink); box-shadow: inset 0 0 0 2px var(--ink);
}
/* Links rise into place after the sheet lands; exit is instant so closing
   never feels slower than the visitor's intent. */
.mnav__panel > * { opacity: 0; transform: translateY(14px); transition: none; }
body.mnav-open .mnav { visibility: visible; }
body.mnav-open .mnav__backdrop { opacity: 1; transition-duration: .32s; }
body.mnav-open .mnav__panel {
  transform: none; opacity: 1;
  transition: transform .5s cubic-bezier(.22,1,.36,1), opacity .28s ease;
}
body.mnav-open .mnav__panel > * {
  opacity: 1; transform: none;
  transition: opacity .4s cubic-bezier(.22,1,.36,1), transform .46s cubic-bezier(.22,1,.36,1);
}
body.mnav-open .mnav__panel > :nth-child(1)  { transition-delay: .05s }
body.mnav-open .mnav__panel > :nth-child(2)  { transition-delay: .08s }
body.mnav-open .mnav__panel > :nth-child(3)  { transition-delay: .11s }
body.mnav-open .mnav__panel > :nth-child(4)  { transition-delay: .14s }
body.mnav-open .mnav__panel > :nth-child(5)  { transition-delay: .17s }
body.mnav-open .mnav__panel > :nth-child(6)  { transition-delay: .2s }
body.mnav-open .mnav__panel > :nth-child(7)  { transition-delay: .23s }
body.mnav-open .mnav__panel > :nth-child(8)  { transition-delay: .26s }
body.mnav-open .mnav__panel > :nth-child(9)  { transition-delay: .29s }
body.mnav-open .mnav__panel > :nth-child(10) { transition-delay: .32s }
body.mnav-open .mnav__panel > :nth-child(11) { transition-delay: .35s }
body.mnav-open .mnav__panel > :nth-child(12) { transition-delay: .38s }
body.mnav-open .mnav__panel > :nth-child(13) { transition-delay: .41s }
body.mnav-open .mnav__panel > :nth-child(14) { transition-delay: .44s }
body.mnav-open .mnav__panel > :nth-child(15) { transition-delay: .47s }
body.mnav-open .mnav__panel > :nth-child(16) { transition-delay: .5s }
body.mnav-open .mnav__panel > :nth-child(17) { transition-delay: .53s }
body.mnav-open .mnav__panel > :nth-child(18) { transition-delay: .56s }
body.mnav-locked { overflow: hidden; }
/* The header rides above the open drawer, the way Stripe's does: the
   wordmark and the morphed X stay visible and the X is tappable to close.
   Without this the sheet slid over the toggle, the morph played to nobody,
   and the only ways out were the backdrop and Escape. */
body.mnav-open .site-header { z-index: 70; }
body.mnav-open .topbar { position: relative; z-index: 70; }
/* Mobile header is wordmark + hamburger only (Wayne): the sticky bottom
   bar already carries Call, and the drawer carries the number twice. */
@media (max-width: 1020px) { .site-header .hdr-phone { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .mnav__panel, .mnav__link, .mnav__cta { transform: none; transition: opacity .15s ease; }
  body.mnav-open .mnav__panel > * { transition-delay: 0s; }
  .mnav-toggle span, .mnav-toggle span::before, .mnav-toggle span::after { transition: none; }
}

@media (max-width: 1020px) { .mnav-toggle { display: block; } }

/* --------------------------------------------------------------- sections */

.section { padding-block: var(--section-pad); }
.section--lg { padding-block: var(--section-pad-lg); }
.section--tight { padding-block: var(--section-pad-tight); }
/* A band that follows a photograph. The image already gave the eye somewhere to
   rest, so repeating the full pad on top of it is the doubled-air problem in
   miniature. */
.section--after-media { padding-top: var(--section-pad-tight); }
.section--surface { background: var(--surface); }
.section--alt { background: var(--surface-2); }
.section--dark { background: var(--dark-bg); color: var(--dark-ink); }
.section--dark h2, .section--dark h3 { color: var(--dark-ink); }
.section--dark p { color: var(--dark-ink-2); }
/* Between two bands sharing a ground, a hairline at wrap width reads more
   expensive than a colour flip, and costs a band of contrast we can spend
   elsewhere. research/16 section 2.6. */
.section--ruled { border-top: 1px solid var(--bord); }
.section--dark.section--ruled { border-top-color: var(--dark-bord); }

/* --------------------------------------------------------- asphalt ground */

/* Four placements: the dark spec band, the final CTA, the footer, and the two
   --alt bands. The white and paper bands stay clean, so the asphalt is marking
   a change of ground rather than covering the page.

   background-size: cover rather than a repeat. The file has a vignette and a
   run of cracks across it, both of which are the reason it looks like a real
   surface and both of which would announce themselves as a pattern the moment
   they tiled. One instance per band, no repeat, no seam to solve.

   As a pseudo-element rather than a background on the section, because the
   section already paints its ground colour and the photograph has to sit ON it
   at its own opacity. pointer-events none so it never eats a click, and the
   content goes to z-index 1 so it is never underneath. */
.section--alt, .section--dark, .final, .site-footer { position: relative; }
.section--alt::before, .section--dark::before, .final::before, .site-footer::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: var(--tex-asphalt);
  background-size: cover; background-position: center;
}
/* On the dark bands it is nearly the ground itself: the band colour is already
   asphalt black, so the photograph mostly supplies grain and the cracks. */
.section--dark::before, .final::before, .site-footer::before { opacity: .34; }
/* On the light --alt bands it has to be far weaker. This band carries body
   copy at 17px, and a photographic ground under running text is unreadable
   long before it is ugly. Enough to feel a surface, not enough to read one. */
.section--alt::before { opacity: .085; }
.section--alt > *, .section--dark > *, .final > *, .site-footer > * { position: relative; z-index: 1; }

/* The hero and the mediaband are deliberately NOT in that list. Both already
   carry a photograph and a grain layer over it, and a third texture on top of
   those is mud. */

/* THE BAND HEAD, WHICH WAS THE TEMPLATE TELL.

   It was a 46rem block pinned top-left of a 1180px band, sixteen times running.
   So the top right 60% of every band opening was empty paper, at the exact
   moment the reader is deciding whether the next band is worth their attention.
   Emptiness there does not read as confidence; it reads as a layout that only
   had one thing to put in it.

   Now the statement and the argument sit side by side: heading left at a size
   that can hold the column, supporting prose right at a readable measure. The
   split is 1.15fr / 1fr rather than half and half, because two equal columns
   read as a grid and an uneven one reads as a decision. */
.band-head { margin-bottom: 2.4rem; }
.band-head h2 { max-width: 18ch; }
.band-head p { font-size: 1.05rem; color: var(--ink-2); margin: 1rem 0 0; }
.section--dark .band-head p { color: var(--dark-ink-2); }

@media (min-width: 1000px) {
  .band-head--split {
    display: grid; grid-template-columns: 1.15fr 1fr;
    column-gap: clamp(2rem, 5vw, 4.5rem);
    grid-template-rows: auto auto;
    align-items: end;
  }
  /* The eyebrow is also a <p>, so a bare `> p` rule catches it and drops the
     label underneath the heading it labels. Every selector here has to say
     which paragraph it means. */
  .band-head--split > .eyebrow { grid-column: 1; grid-row: 1; align-self: start; }
  .band-head--split > h2 { grid-column: 1; grid-row: 2; max-width: none; }
  .band-head--split > p:not(.eyebrow) { grid-column: 2; grid-row: 2; margin: 0 0 .35rem; }
}

/* The lead rule. One of the six places --line is allowed: a short heavy mark
   above the eyebrow, which is the gesture this trade makes on a lot before it
   does anything else. It replaces nothing, it anchors the band head to the top
   of the band so the heading is not floating. */
.band-head .eyebrow::before,
.eyebrow--ruled::before {
  content: ""; width: 26px; height: 3px; background: var(--line); flex: none;
}
/* The hourglass and the rule together is two marks doing one job. The rule wins
   inside a band head; the mark keeps the places where there is no rule. */
.band-head .eyebrow .hourglass { display: none; }

/* ------------------------------------------------------------------- hero */

.hero { background: var(--surface); border-bottom: 1px solid var(--bord); }
.hero .wrap {
  display: grid; grid-template-columns: 1.05fr .95fr;
  gap: clamp(2rem, 4vw, 3.5rem); align-items: center;
  padding-block: clamp(2.5rem, 5vw, 4.25rem);
}
.hero h1 em { font-style: normal; color: var(--action); }
/* The bottom margin is load-bearing on the location pages, where the lede is
   followed by the geography paragraphs rather than going straight to the CTA.
   At zero they sat flush against it and the two read as one run-on block. On
   the home hero nothing moves: the CTA's larger top margin collapses against
   this one. */
.hero__lede { font-size: 1.13rem; color: var(--ink-2); margin: 1.25rem 0 1rem; max-width: 34em; }
.hero__cta { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.9rem; }
.hero__note { margin-top: 1.05rem; font-size: .9rem; color: var(--steel); font-weight: 500; }
.hero__media { border: 1px solid var(--bord); }
.hero__media img { width: 100%; height: clamp(300px, 44vw, 440px); object-fit: cover; }
@media (max-width: 880px) { .hero .wrap { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------- trust strip */

.trust { background: var(--paper); border-bottom: 1px solid var(--bord); }
.trust .wrap { padding-block: 1.6rem; }
.trust dl { display: grid; grid-template-columns: repeat(4, 1fr); margin: 0; }
.trust dl > div { padding-inline: 1.1rem; border-left: 1px solid var(--bord); }
.trust dl > div:first-child { border-left: 0; padding-left: 0; }
.trust dt {
  font-family: var(--font-display); font-weight: 800; font-stretch: 105%;
  font-size: clamp(1.45rem, 3vw, 2rem); line-height: 1; font-variant-numeric: tabular-nums;
}
.trust dd { margin: .4rem 0 0; font-size: .81rem; font-weight: 600; color: var(--steel); line-height: 1.35; }

/* The promise variant. One number and three phrases, so the phrases must NOT
   inherit the numeral size or the row becomes four competing headlines. The
   asymmetry is the point: the rating is the hero, the rest support it. */
.trust--promise dt {
  font-size: clamp(.95rem, 1.6vw, 1.12rem);
  font-stretch: 100%;
  letter-spacing: -0.004em;
  line-height: 1.2;
  text-wrap: balance;
}
.trust--promise .trust__rating dt {
  display: flex; flex-direction: column; align-items: flex-start; gap: .15rem;
}
.trust--promise .trust__rating .stars { font-size: .78rem; line-height: 1; }
.trust--promise .trust__score {
  font-size: clamp(1.7rem, 3.4vw, 2.35rem); line-height: 1;
  font-variant-numeric: tabular-nums;
}
/* The rating column carries less text than the others and reads better narrow. */
@media (min-width: 781px) {
  .trust--promise dl { grid-template-columns: .8fr 1.07fr 1.07fr 1.07fr; }
}

/* THE ONE OVERLAP.

   research/16 section 2.6: a card crossing a band boundary, exactly once on the
   page. Once is art direction, three times is a theme, and the difference is
   the whole of it.

   This is the right place for it because it is also doing two other jobs. The
   hero had no trust signal on it at all beyond a topbar line most people scroll
   past, and a rating that arrives 700px below the fold is a rating a stranger
   deciding in five seconds never saw. Lifting the strip onto the photograph
   puts the number where the decision happens, and it removes a whole band from
   a page that had sixteen of them.

   The card is on --surface, not --paper: it has to read as sitting ON the
   photograph rather than as the next band starting early. */
@media (min-width: 781px) {
  .trust--float {
    background: transparent; border-bottom: 0;
    margin-top: clamp(-4.5rem, -5vw, -3rem);
    position: relative; z-index: 2;
  }
  .trust--float .wrap { padding-block: 0; }
  /* Borders stay neutral. A 3px --line bar across the top of this card was the
     first draft and it is AI slop flag 4, the coloured accent stripe, which is
     what an agent reaches for when it cannot think of another way to brand a
     component. The shadow is doing the lifting; the card does not need a
     racing stripe to prove it is ours. */
  .trust--float dl {
    background: var(--surface);
    border: 1px solid var(--bord);
    padding: 1.5rem 1.75rem;
    box-shadow: var(--shadow-pop);
  }
  .trust--float dl > div:first-child { padding-left: 0; }
}
@media (max-width: 780px) {
  .trust dl { grid-template-columns: repeat(2, 1fr); gap: 1.4rem 0; }
  .trust dl > div:nth-child(3) { border-left: 0; padding-left: 0; }
}

/* -------------------------------------------------------------- receipt */

/* The proof directly under the hero. Set larger than the mid-page pull quote,
   because this one is carrying the H1's claim rather than decorating a band,
   and centred, which is the one place on this site centring is right: it is a
   short statement standing alone with nothing to align to. */
.receipt { background: var(--surface); border-bottom: 1px solid var(--bord); }
.receipt .wrap { max-width: 56rem; text-align: center; }
.receipt blockquote {
  margin: 0; font-family: var(--font-display); font-weight: 700; font-stretch: 102%;
  font-size: clamp(1.35rem, 3vw, 2.15rem); line-height: 1.22; letter-spacing: -.022em;
  text-wrap: balance; color: var(--ink);
}
.receipt blockquote::before { content: "\201C"; }
.receipt blockquote::after  { content: "\201D"; }
.receipt cite {
  display: block; font-style: normal; margin-top: 1.1rem;
  font-size: .82rem; font-weight: 700; font-stretch: 118%;
  letter-spacing: .1em; text-transform: uppercase; color: var(--steel);
}

/* ----------------------------------------------------------- the curve ---

   Four stages of pavement failure, which is the page's core argument and had
   no home on the page at all until now.

   Numbered, because the sequence IS the content: stage three costs several
   times stage one and the reader needs to feel the ladder. The numeral is the
   marking-out yellow rather than the accent red, because this is a diagram of
   a process rather than a call to action, and red here would be the fifth
   accent object on the fold. */

.curve { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--bord); }
.curve li {
  display: grid; grid-template-columns: 3.25rem 1fr; gap: 1.4rem;
  padding: 1.35rem 0; border-bottom: 1px solid var(--bord); min-width: 0;
}
.curve__n {
  font-family: var(--font-display); font-weight: 800; font-size: 1.9rem;
  line-height: 1; color: var(--line); font-variant-numeric: tabular-nums;
  padding-top: .1rem;
}
.curve b {
  display: block; font-family: var(--font-display); font-stretch: 112%;
  font-size: clamp(1.05rem, 1.9vw, 1.25rem); letter-spacing: -.012em;
}
.curve span:not(.curve__n) {
  display: block; margin-top: .35rem; max-width: 52em;
  color: var(--ink-2); font-size: .97rem; line-height: 1.6;
}
.curve__foot { margin-top: 1.75rem; max-width: 52em; color: var(--ink-2); }
.curve__foot b { color: var(--ink); }
@media (max-width: 560px) {
  .curve li { grid-template-columns: 2.25rem 1fr; gap: .9rem; }
  .curve__n { font-size: 1.4rem; }
}

/* ------------------------------------------------------------- segments */

/* Who the business works for. PLM Paving runs twelve of these on one page and
   it is the clearest tier signal in the Wisconsin field: a driveway outfit has
   no reason to list property types, so listing them says what a paragraph of
   positioning cannot.

   Type-led with a rule per item, NOT a bordered cell grid. Boxed cells read as
   a data table (slop flag 2) and a table is the wrong genre for a statement
   about who somebody's clients are. The rule under each is the same gesture as
   the band-head lead rule, so the two read as one system.

   Two columns rather than three: each item carries a line of explanation, and
   at three columns that line breaks four times and stops being scannable. */
.segments {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 4rem);
  border-top: 1px solid var(--bord);
}
.segments li { padding: 1.15rem 0; border-bottom: 1px solid var(--bord); min-width: 0; }
.segments b {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-stretch: 112%; font-size: clamp(1.02rem, 1.7vw, 1.18rem);
  letter-spacing: -.01em;
}
.segments span {
  display: block; margin-top: .3rem; font-size: .93rem;
  color: var(--ink-2); line-height: 1.5; max-width: 42em;
}
.segments__foot { margin-top: 1.75rem; }
@media (max-width: 760px) {
  .segments { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------- audience split */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--bord); border: 1px solid var(--bord); }
/* Grid and flex children default to min-width:auto, which means they refuse to
   shrink below their content and push the whole document wider instead. This is
   the single most common cause of horizontal overflow on a narrow screen. */
.split > article { background: var(--surface); padding: clamp(1.6rem, 3vw, 2.4rem); display: flex; flex-direction: column; min-width: 0; }
/* The photograph bleeds to the card's edges: it cancels the article's padding
   with a negative margin so the image sits hard against the hairline border
   rather than floating inside a frame inside a frame. 21:9 keeps it a band
   across the top rather than a second subject competing with the heading. */
.split__shot {
  margin: calc(clamp(1.6rem, 3vw, 2.4rem) * -1);
  margin-bottom: clamp(1.4rem, 2.5vw, 1.9rem);
  /* 21:9 was too shallow for the two most important cards on the page: it
     read as a letterbox strip rather than as a photograph. 16:9 gives them
     presence without pushing the headings below the fold. */
  aspect-ratio: 16 / 9; overflow: hidden; position: relative;
  background: var(--surface-2);
}
.split__shot img { width: 100%; height: 100%; object-fit: cover; }
.two-col > *, .cards > *, .svc-grid > *, .reviews > *, .prices > * { min-width: 0; }
/* These are h2s, not h3s, because each column is a section of the page in its
   own right. The rule only named h3, so the heading sat flush on its own
   paragraph and the two read as one run-on block. */
.split h2, .split h3 { font-size: clamp(1.25rem, 2.2vw, 1.6rem); margin-bottom: .9rem; }
.split p { color: var(--ink-2); margin: 0 0 1.2rem; }
.split ul { list-style: none; margin: 0 0 1.7rem; padding: 0; display: grid; gap: .55rem; }
.split li { display: flex; gap: .6rem; font-size: .96rem; font-weight: 500; }
.split li::before { content: ""; width: 7px; height: 7px; background: var(--ink); flex: none; margin-top: .5rem; }
.split .btn { margin-top: auto; align-self: flex-start; }
.split__tag { font-size: .7rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--steel); margin-bottom: .7rem; }
@media (max-width: 800px) { .split { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- services */

/* The photographs are the best asset this business has and they were being used
   as 180px thumbnails inside bordered cards, which is the treatment a stock
   icon gets. A 4:3 frame at the full card width is roughly two and a half times
   the painted area, and the border comes off: air on both sides plus a frame
   ornament is the catalogue read. Hard edge, no radius, no shadow. */
.svc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem 1.75rem; }
.svc { display: flex; flex-direction: column; text-decoration: none; }
.svc__shot {
  position: relative; background-color: var(--surface-2);
  background-image: repeating-linear-gradient(-45deg, var(--hatch) 0 2px, transparent 2px 11px);
  aspect-ratio: 4 / 3;
  display: flex; align-items: flex-end; padding: .85rem;
}
.svc__shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.svc__shot span { position: relative; font-size: .72rem; font-weight: 600; color: var(--steel); }
.svc h3 { margin-top: 1.05rem; }
.svc p { margin: .45rem 0 0; font-size: .93rem; color: var(--ink-2); max-width: 34em; }
.svc__more { margin-top: .7rem; font-size: .87rem; font-weight: 700; color: var(--ink); text-decoration: underline; text-underline-offset: .3em; text-decoration-thickness: 1px; }
.svc:hover .svc__more { text-decoration-thickness: 2px; }

/* THE IN-BODY LINK, AND THE ACCENT LEAK IT WAS CAUSING.

   Seventeen links across eight page files carried an inline
   style="font-weight:700;color:var(--action)". Every one of them was a "read
   more" sitting at the foot of a band. That is seventeen red objects on a page
   whose whole accent budget is two visible at once, spent on the least
   important link in each band.

   Every premium peer measured sets body links to INK and signals them with rule
   weight rather than hue: 1px underline going to 2px, offset far enough off the
   baseline to read as deliberate. Red is reserved for the thing you are meant
   to press. */
.more {
  display: inline-block; font-weight: 700; color: var(--ink); text-decoration: underline;
  text-underline-offset: .3em; text-decoration-thickness: 1px;
}
.more:hover { text-decoration-thickness: 2px; }
.section--dark .more, .more--light { color: var(--dark-ink); }
@media (max-width: 880px) { .svc-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .svc-grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------- pull quote */

/* A pull quote is not a call to action.

   Given the band rather than a 46rem column of it. This is the only commercial
   voice anywhere on the page and it answers the exact question a property
   manager arrives with, which is not "is the work good" but "will this shut my
   business for a week". At caption size it was a footnote to the photographs
   above it. At display size it is the argument they were making. */
.pull { border-left: 3px solid var(--ink); padding-left: clamp(1.4rem, 3vw, 2.4rem); max-width: 56rem; }
.pull blockquote {
  margin: 0; font-family: var(--font-display); font-weight: 700; font-stretch: 102%;
  font-size: clamp(1.4rem, 3.2vw, 2.35rem); line-height: 1.2; letter-spacing: -.024em;
  text-wrap: balance;
}
.pull cite { display: block; font-style: normal; margin-top: 1.25rem; font-size: .92rem; font-weight: 600; color: var(--steel); }

/* -------------------------------------------------------- mid-page strip */

.strip { background: var(--action); color: #fff; }
.strip .wrap {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  align-items: center; justify-content: space-between; padding-block: 1.4rem;
}
.strip p {
  margin: 0; font-family: var(--font-display); font-weight: 700; font-stretch: 110%;
  font-size: clamp(1.02rem, 2.2vw, 1.38rem); text-transform: uppercase; letter-spacing: -.01em;
}
.strip .btn { background: #fff; color: var(--action); }
.strip .btn:hover { background: var(--ink); color: #fff; }

/* ----------------------------------------------------------- price bands */

.prices { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--bord); border: 1px solid var(--bord); }
.prices > div { background: var(--surface); padding: 1.5rem 1.25rem; }
.prices > div.is-featured { background: var(--ink); color: var(--paper); }
.prices h3 { font-size: 1.05rem; }
.prices .size { font-size: .8rem; font-weight: 600; color: var(--steel); margin: .3rem 0 .9rem; }
.prices > div.is-featured .size { color: var(--dark-ink-2); }
.prices .amount {
  font-family: var(--font-display); font-weight: 800; font-size: 1.55rem;
  line-height: 1; font-variant-numeric: tabular-nums;
}
.prices ul { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: .4rem; font-size: .87rem; }
.prices li { display: flex; gap: .5rem; }
.prices li::before { content: ""; width: 5px; height: 5px; background: var(--ink); flex: none; margin-top: .5rem; }
@media (max-width: 980px) { .prices { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .prices { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- reviews */

.rev-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .6rem 1.5rem; margin-bottom: 2.4rem; }
.rev-score { font-family: var(--font-display); font-weight: 800; font-size: 3.2rem; line-height: 1; font-variant-numeric: tabular-nums; }
.reviews { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.reviews--auto { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.rev { background: var(--surface); border: 1px solid var(--bord); padding: 1.5rem; display: flex; flex-direction: column; }
.rev p { margin: .8rem 0 1.1rem; font-size: .96rem; }
.rev footer { margin-top: auto; font-size: .84rem; font-weight: 600; color: var(--steel); }
.rev footer b { display: block; color: var(--ink); font-weight: 700; font-size: .93rem; }
.rev--biz { border-color: var(--ink); }
.tag-biz {
  display: inline-block; margin-left: .45rem; font-size: .58rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: #fff; background: var(--action);
  padding: .13rem .4rem; vertical-align: .14em;
}
@media (max-width: 880px) { .reviews { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------- spec / stats */

.specs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--dark-bord); border: 1px solid var(--dark-bord); }
.specs > div { background: var(--dark-bg); padding: clamp(1.4rem, 3vw, 2.2rem); }
.specs dt {
  font-family: var(--font-display); font-weight: 800; font-stretch: 105%;
  font-size: clamp(2.2rem, 5vw, 3.4rem); line-height: 1;
  color: var(--dark-ink); font-variant-numeric: tabular-nums;
}
.specs dt small { font-size: .38em; font-weight: 700; letter-spacing: .02em; }
.specs dd { margin: .7rem 0 0; color: var(--dark-ink-2); font-size: .94rem; line-height: 1.5; }
.specs dd b { color: var(--dark-ink); font-weight: 700; }
@media (max-width: 780px) { .specs, .specs--two { grid-template-columns: 1fr !important; } }
.specs--two { grid-template-columns: repeat(2, 1fr); }

/* ------------------------------------------------------------- ADA offer */

/* The free-slope-check offer on the commercial page. A concrete, technical,
   genuinely free thing with a named deliverable beats another "contact us for
   a consultation" by a distance, and it generates patch and overlay work,
   which is self-performed scope.

   Sits inside the dark ADA band on a lifted panel rather than as another
   full-width row, so it reads as an offer attached to the argument above it
   rather than as the next section. */
.ada-offer {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  display: grid; grid-template-columns: 1fr auto; gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: center;
  background: rgba(244,242,239,.055);
  border: 1px solid var(--dark-bord);
  padding: clamp(1.4rem, 3vw, 2rem);
}
.ada-offer h3 { color: var(--dark-ink); font-size: clamp(1.15rem, 2.2vw, 1.45rem); }
.ada-offer p { margin: .6rem 0 0; color: var(--dark-ink-2); font-size: .96rem; max-width: 52em; }
.ada-offer .btn { white-space: nowrap; }
@media (max-width: 720px) {
  .ada-offer { grid-template-columns: 1fr; }
  .ada-offer .btn { justify-self: start; }
}

/* The citation line. Publishing figures like 1-in-6 and 1:48 is only worth
   anything if the reader can see where they came from, and a facilities
   professional is exactly the reader who will check. */
.ada-note {
  margin-top: 1.5rem; max-width: 60em;
  font-size: .88rem; color: var(--dark-ink-2); line-height: 1.55;
}
.ada-note span {
  display: block; margin-top: .4rem;
  font-size: .78rem; color: var(--steel); font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ steps list */

.steps { display: grid; gap: 0; border-top: 1px solid var(--bord); }
.step { display: grid; grid-template-columns: 4.5rem 1fr; gap: 1.25rem; padding: 1.5rem 0; border-bottom: 1px solid var(--bord); }
/* Six red numerals is six accent objects in one band, which on its own blows the
   whole page's budget of two visible at once. They are also not a call to
   action, so hue was signalling nothing. Ink at 800 carries a numeral perfectly
   well; the size is what makes it a numeral. */
.step__n {
  font-family: var(--font-display); font-weight: 800; font-size: 2.1rem; line-height: 1;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.step h3 { margin-bottom: .4rem; }
.step p { color: var(--ink-2); font-size: .97rem; }
/* The commercial timing band labels its steps with a season rather than a
   numeral. "Winter" at 2.1rem does not fit a 4.5rem column, and the label is
   not a count, so it should not be typeset as one. */
.steps--labelled .step { grid-template-columns: 7rem 1fr; }
.steps--labelled .step__n {
  font-size: 1.05rem; font-stretch: 118%; letter-spacing: .1em;
  text-transform: uppercase; color: var(--steel); padding-top: .2rem;
}
@media (max-width: 560px) {
  .steps--labelled .step { grid-template-columns: 1fr; gap: .35rem; }
  .steps--labelled .step__n { font-size: .78rem; padding-top: 0; }
}
@media (max-width: 560px) { .step { grid-template-columns: 2.6rem 1fr; gap: .9rem; } .step__n { font-size: 1.5rem; } }

/* --------------------------------------------------------- service area */

/* .neighborhoods is the same shape and was carrying no rule at all, so the
   neighborhood list rendered as a default bulleted list on every Tier 1 town
   page. Found by tools/orphan-classes. */
.area-list, .neighborhoods { columns: 4; column-gap: 2rem; list-style: none; padding: 0; margin: 0; font-size: .95rem; font-weight: 500; }
.area-list li, .neighborhoods li { break-inside: avoid; padding: .28rem 0; display: flex; gap: .55rem; }
.area-list li::before, .neighborhoods li::before { content: ""; width: 5px; height: 5px; background: var(--ink); flex: none; margin-top: .56rem; }
.area-list a, .neighborhoods a { text-decoration: none; }
.area-list a:hover, .neighborhoods a:hover { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .25em; }
@media (max-width: 900px) { .area-list, .neighborhoods { columns: 3; } }
@media (max-width: 640px) { .area-list, .neighborhoods { columns: 2; } }

/* ----------------------------------------------------------------- owner */

/* 300px was a thumbnail beside a letter, and the letter won by so much that the
   photograph read as an afterthought stuck in the margin. A portrait crop at
   roughly a third of the band is the smallest a photograph of people can be and
   still be a photograph of people. 4:5 is the one portrait ratio in the crop
   family; everything else on the site is 3:2 or 4:3. */
.owner { display: grid; grid-template-columns: minmax(0, .78fr) minmax(0, 1fr); gap: clamp(1.75rem, 4vw, 3.5rem); align-items: start; }
/* display:grid is load-bearing, not decoration. The hatch is the placeholder
   for a photo that does not exist yet, and min-height keeps the block from
   collapsing when it is showing. But a percentage height resolves against the
   parent's COMPUTED height, and min-height alone leaves that auto, so the img
   sized itself to its own ratio: 300 by 192 in a 300 by 300 box, with 108px of
   placeholder hatching visible underneath a photo that had loaded perfectly
   well. Grid stretches the item to the full area, and object-fit does the rest. */
.owner__shot { position: relative; overflow: hidden; background-color: var(--surface-2);
  background-image: repeating-linear-gradient(-45deg, var(--hatch) 0 2px, transparent 2px 11px);
  aspect-ratio: 4 / 5; display: grid; }
.owner__shot img { width: 100%; height: 100%; object-fit: cover; }
.owner p { font-size: 1.05rem; }
.sig { font-family: var(--font-display); font-weight: 700; font-stretch: 108%; font-size: 1.28rem; margin-top: 1.5rem; }
.sig span { display: block; font-family: var(--font-body); font-size: .85rem; font-weight: 600; color: var(--steel); margin-top: .2rem; }
@media (max-width: 760px) { .owner { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------- faq */

.faq { max-width: 52rem; }
.faq__item { border-bottom: 1px solid var(--bord); }
.faq__item summary {
  cursor: pointer; list-style: none; padding: 1.1rem 2rem 1.1rem 0;
  font-family: var(--font-display); font-weight: 700; font-stretch: 106%; font-size: 1.08rem;
  position: relative;
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after {
  content: "+"; position: absolute; right: 0; top: .95rem;
  font-size: 1.5rem; font-weight: 400; color: var(--steel); line-height: 1;
}
.faq__item[open] summary::after { content: "\2212"; }
.faq__a { padding-bottom: 1.3rem; color: var(--ink-2); max-width: 46rem; }

/* -------------------------------------------------------- decision table */

.decision { border: 1px solid var(--bord); background: var(--surface); }
.decision__row { display: grid; grid-template-columns: 1fr 8rem; gap: 1rem; padding: 1.05rem 1.25rem; border-bottom: 1px solid var(--bord-soft); align-items: start; }
.decision__row:last-child { border-bottom: 0; }
.decision__sym { font-weight: 600; }
.decision__exp { grid-column: 1 / -1; font-size: .9rem; color: var(--steel); margin-top: .3rem; }
.verdict { font-size: .72rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; padding: .3rem .55rem; color: #fff; text-align: center; white-space: nowrap; }
.verdict--fix { background: var(--good); }
.verdict--maybe { background: var(--warn); }
.verdict--replace { background: var(--action); }

/* ------------------------------------------------------------- lead form */

.leadform { background: var(--surface); border: 1px solid var(--bord); padding: clamp(1.4rem, 3vw, 2rem); }
.leadform__h { font-family: var(--font-display); font-weight: 700; font-size: 1.35rem; margin: 0 0 1.1rem; }
.leadform__field { display: grid; gap: .35rem; margin-bottom: .9rem; }
.leadform label { font-size: .84rem; font-weight: 600; }
.leadform input, .leadform select, .leadform textarea {
  font-family: inherit; font-size: 1rem; padding: .75rem .85rem;
  border: 1px solid var(--bord); border-radius: var(--radius); background: var(--paper); color: var(--ink);
  width: 100%;
}
.leadform textarea { min-height: 7rem; resize: vertical; }
.leadform button[type="submit"] {
  width: 100%; background: var(--action); color: #fff; border: 0; border-radius: var(--radius);
  font-family: var(--font-body); font-weight: 700; font-size: 1.05rem; padding: 1.05rem; cursor: pointer;
}
.leadform button[type="submit"]:hover { background: var(--action-deep); }
.leadform__legal { font-size: .78rem; color: var(--steel); margin-top: .9rem; line-height: 1.45; }

/* -------------------------------------------------------------- CTA band */

.final { background: var(--ink); color: var(--paper); text-align: center; }
.final h2 { color: var(--paper); }
.final p { color: var(--dark-ink-2); font-size: 1.08rem; margin: 1.1rem auto 2rem; max-width: 38rem; }
.final__btns { display: flex; flex-wrap: wrap; gap: .9rem; justify-content: center; }
.final .btn--ghost { color: var(--paper); }
.final .btn--ghost:hover { background: var(--paper); color: var(--ink); border-color: var(--paper); }

/* The variant that carries a form. Left-aligned, because centred long-form is
   the AI default and this column has four elements in it, not a slogan. */
.final--form { text-align: left; }
.final--form p { margin-left: 0; margin-right: 0; }
.final--form .lede { color: var(--dark-ink-2); margin: 1rem 0 0; max-width: 34em; }
/* The phone as the largest thing in the band, which is what a contractor page
   is for. Bigger than the h2 beside it on purpose: seventy to eighty percent of
   these leads close on a call, and the form is the fallback.

   Selector has to out-specify `.final p { font-size: 1.08rem }`, which is
   (0,1,1) and was quietly rendering the whole point of this band at nineteen
   pixels. */
.final .final__phone {
  margin: 1.9rem 0 0;
  font-family: var(--font-display); font-weight: 800; font-stretch: 100%;
  font-size: clamp(2.1rem, 4.6vw, 3.2rem); line-height: 1; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums; max-width: none; color: var(--paper);
}
.final__phone a { color: var(--paper); text-decoration: none; }
.final__phone a:hover { text-decoration: underline; text-underline-offset: .14em; text-decoration-thickness: 3px; }
.final .final__note { color: var(--dark-ink-2); font-size: .92rem; margin: .9rem 0 0; max-width: 30em; }

/* What happens after they press it. The left column ran about 400px shorter
   than the form beside it, and the hole was at the exact moment the visitor is
   deciding whether to hand over a phone number. Three lines answering "then
   what" is the cheapest anxiety reducer available and it fills the column
   with the thing that belongs there. */
.final__next { list-style: none; margin: 2.25rem 0 0; padding: 0; display: grid; gap: 0; max-width: 30em; }
.final__next li {
  display: grid; grid-template-columns: 1.6rem 1fr; gap: .9rem;
  padding: .85rem 0; border-top: 1px solid var(--dark-bord);
  font-size: .96rem; color: var(--dark-ink-2);
}
.final__next li:last-child { border-bottom: 1px solid var(--dark-bord); }
.final__next b { color: var(--dark-ink); font-weight: 700; }
.final__next span:first-child {
  font-family: var(--font-display); font-weight: 800; color: var(--steel);
  font-variant-numeric: tabular-nums;
}

/* The form keeps its light ground: a dark form on a dark band is a field a
   55-year-old cannot see the edges of. `.final h2` was painting the form's own
   heading --paper, on white, so it read as blank space above the first field. */
.final--form .leadform { color: var(--ink); }
.final--form .leadform .leadform__h, .final--form .leadform h2 { color: var(--ink); }
.final--form .leadform p, .final--form .leadform__legal { color: var(--steel); font-size: .78rem; }

/* ---------------------------------------------------------------- footer */

.site-footer { background: var(--dark-bg); color: var(--dark-ink-2); font-size: .9rem; padding-block: 3rem 2rem; }
.site-footer a { text-decoration: none; }
.site-footer a:hover { color: var(--dark-ink); text-decoration: underline; }
/* Red on ink is a legible pairing and it is his own artwork, so the footer gets
   the identity rather than a repeat of the nav. */
.site-footer__logo { height: 78px; width: auto; margin-bottom: 2rem; }
@media (max-width: 520px) { .site-footer__logo { height: 62px; } }
.site-footer__nav { display: flex; flex-wrap: wrap; gap: .6rem 1.5rem; padding-bottom: 1.75rem; border-bottom: 1px solid var(--dark-bord); font-weight: 600; }
.site-footer__local { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 2rem; padding-block: 1.75rem; }
.site-footer__local b, .site-footer__local strong { color: var(--dark-ink); }
/* GbpLink emits .gbp and nothing styles it, in WebKit or in any client
   stylesheet. One link got away with that; two next to each other would
   have run together the way the NAP block did. */
.site-footer__off { display: grid; gap: .55rem; align-content: start; }
.gbp, .site-footer__gbp { text-decoration: none; font-weight: 600; }
.gbp:hover, .site-footer__gbp:hover { text-decoration: underline; }

/* ------------------------------------------------------- sticky mobile bar */

.mobar { display: none; }
/* 640 -> 720: this now overlaps the header CTA slightly rather than leaving a
   gap under it. Two CTAs on a tablet is not a problem; none was. */
@media (max-width: 720px) {
  .mobar { display: grid; grid-template-columns: 1fr 1fr; position: fixed; bottom: 0; left: 0; right: 0; z-index: 50; }
  /* iOS safe area, third attempt. The second one continued each button's
     color through the safe area, so when Safari's toolbar collapsed on
     scroll the buttons looked like they had grown (Wayne, twice). The
     chin is now neutral ink: the buttons keep one fixed height in every
     browser state, labels dead-centered by flex, and the safe-area strip
     reads as the bar's base rather than as more button. */
  .mobar { padding-bottom: env(safe-area-inset-bottom); background: var(--ink); }
  .mobar a { display: flex; align-items: center; justify-content: center;
    min-height: 3.1rem; padding: 0 .8rem; line-height: 1; text-align: center;
    text-decoration: none; font-weight: 700; font-size: .95rem; }
  .mobar .call { background: var(--ink); color: var(--paper); }
  .mobar .quote { background: var(--action); color: #fff; }
  .mobar a:active { filter: brightness(1.15); }
  body { padding-bottom: calc(3.1rem + env(safe-area-inset-bottom)); }
}

/* ------------------------------------------------------------------ misc */

.page-hero { background: var(--surface); border-bottom: 1px solid var(--bord); padding-block: clamp(2.5rem, 5vw, 4rem); }
.page-hero p { font-size: 1.1rem; color: var(--ink-2); max-width: 40em; }

.lede { font-size: 1.1rem; color: var(--ink-2); max-width: 44em; }
.prose { max-width: 44em; }
.prose h2 { margin-top: 2.5rem; }
.prose h3 { margin-top: 1.75rem; }
.prose ul, .prose ol { padding-left: 1.2rem; }
.prose li { margin-bottom: .4rem; }

.two-col { display: grid; grid-template-columns: 1.25fr .75fr; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }
@media (max-width: 900px) { .two-col { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- cross-links

   The two internal-link lists at the foot of a location page. They had no rule
   at all, so 171 pages ended in two runs of default-blue bulleted links. */

.cross-links {
  list-style: none; margin: 1.1rem 0 2.2rem; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: .5rem 1.5rem;
}
.cross-links li { display: flex; gap: .55rem; min-width: 0; }
.cross-links li::before { content: ""; width: 6px; height: 6px; background: var(--ink); flex: none; margin-top: .62rem; }
.cross-links a { color: var(--ink-2); text-decoration: none; font-size: .95rem; font-weight: 500; }
.cross-links a:hover { color: var(--ink); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .25em; }
.cross-links + h2 { margin-top: .5rem; }

/* --------------------------------------------------------------- photo grade

   One grade across every job photograph. They were shot on a phone over two
   months in different light, and an inconsistent set reads cheaper than a soft
   one. Slight desaturation is the documentary register; slight contrast hides
   the compression mush in asphalt shadows, which is most of what these photos
   are made of. */

.svc__shot img, .proof__shot img, .hero__media img, .split__shot img, .work__shot img,
.owner__shot img, .hero--shot .hero__bg img, .mediaband > img, .mediaband > picture > img {
  filter: contrast(1.06) saturate(.94) brightness(.98);
}

/* GRAIN, AS THE EQUALISER.

   These are phone photographs downscaled to 1400px sitting next to type that is
   perfectly crisp at any zoom. That mismatch is what actually reads as cheap,
   more than the softness itself: two objects on one page that plainly did not
   come from the same place. A single turbulence layer at 8% over the photo
   frames gives them a shared surface, and the eye stops noticing which half is
   soft.

   Applied to photo FRAMES only, never to body. A page-wide noise layer is a
   real paint cost on a phone, and a grain background is the editorial
   fingerprint the register bans. Inside a frame it is a photographic property,
   which is a different thing. */
.svc__shot::after, .proof__shot::after, .owner__shot::after, .split__shot::after,
.work__shot::after,
.hero--shot .hero__bg::before, .mediaband::before {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  opacity: .075; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}
.mediaband::before { z-index: 1; }
.hero--shot .hero__bg::before { z-index: 1; }

/* Photo hover inside a fixed frame: the frame never moves, the image inside
   scales. The restrained version of the move, and the only motion on a card. */
.svc__shot { overflow: hidden; }
.svc__shot img { transition: transform .38s cubic-bezier(.2,.6,.2,1); }
.svc:hover .svc__shot img { transform: scale(1.035); }
@media (prefers-reduced-motion: reduce) {
  .svc:hover .svc__shot img { transform: none; }
}

/* ------------------------------------------------------------ shot hero ----

   Photograph behind, copy and picker over it.

   The image is capped at --wrap-wide (1440) rather than 100vw, on an ink
   ground. Every photo we hold is 1400px, and 1400 across a 1920 viewport is a
   1.37x upscale, which reads soft; at 1440 it is 1.03x. The ground carries the
   full-bleed feel and the photograph stays sharp. When BW-06 lands and we have
   8000px originals, drop the max-width and let it run to the edge. */

.hero--shot { position: relative; background: var(--ink); border-bottom: 0; overflow: hidden; }
.hero--shot .hero__bg { position: absolute; inset: 0; }
.hero--shot .hero__bg img {
  width: 100%; max-width: var(--wrap-wide, 1440px);
  margin-inline: auto;
  height: 100%; object-fit: cover;
  /* The crop was letting the bottom-left corner of the source in, which is the
     photographer's own wing mirror, and putting a black blob across the corner
     the CTA sits in. Pulling up cuts the mirror out and brings the saw-cut
     trench and the cone line into the right half, which is the half the copy
     is not using. */
  object-position: 46% 20%;
}
/* Directional, not a uniform wash. A flat overlay kills the photograph to save
   the text; a gradient keeps the lot readable on the right where the picker
   sits. Tinted to --ink rather than pure black so it matches the ground. */
/* Retuned 2026-08-24. The old values ran a veil across the WHOLE frame: 30%
   even at the far right, on top of a bottom wash, so nothing in the photograph
   was ever seen at full strength and the band read as grey rather than as a
   parking lot. A scrim's job is to make one region safe for type, not to lower
   the volume of the picture.

   So it is steeper and it finishes. Heavy under the copy, gone by 72%, and the
   right third of the photograph is now simply the photograph. */
.hero--shot .hero__bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(96deg, rgba(22,24,28,.95) 0%, rgba(22,24,28,.88) 30%, rgba(22,24,28,.45) 56%, rgba(22,24,28,.06) 78%, rgba(22,24,28,0) 100%),
    linear-gradient(0deg,  rgba(22,24,28,.62) 0%, rgba(22,24,28,0) 38%);
}

.hero--shot .hero__inner {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: minmax(0, 40rem);
  padding-block: clamp(4rem, 9vw, 7.5rem);
}
.hero__act { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }
.hero--shot .hero__copy { color: var(--dark-ink); min-width: 0; }
/* Narrower than the column on purpose: at full width the line broke as
   "part. Repaving", splitting the sentence across the accent word.

   13ch is tuned to the home headline. The commercial one is two short
   sentences rather than one long one, and at 13ch it laddered into five lines;
   it wants room to break at the full stop instead. Per-hero rather than a
   global change, because the constraint is a property of the sentence. */
.hero--shot h1 { color: var(--dark-ink); max-width: 13ch; }
.hero--commercial h1 { max-width: 17ch; }

/* THE CAPABILITY HEADLINE NEEDS A SMALLER SIZE THAN A BILLBOARD HEADLINE.

   "Sealcoating is the cheap part. Repaving isn't." is six short words and a
   punchline; it wants 76px. "Parking lots, school tracks and loading docks.
   And your driveway." is a list of what the company does, and at 76px a list
   is five lines with the accent stretched across two of them, which pushes the
   buttons off the fold and reads as shouting rather than as scope.

   Both Wisconsin benchmarks set their capability H1 small. PLM's is nine words
   and nowhere near display size. The tier signal is the CONTENT of the line,
   not its point size, and giving it room to sit on two lines is what lets it
   be read as a sentence. */
.hero--capability h1 {
  /* A range statement is longer than a list, so it drops another step and gets
     a wider measure. Fifteen words at 76px is a wall; at 3rem across 26
     characters it is three lines that each end on a natural pause. */
  font-size: clamp(2rem, 3.9vw, 3.05rem);
  letter-spacing: -.024em;
  line-height: 1.1;
  max-width: 26ch;
}
.hero--capability .hero__lede { max-width: 34em; }
.hero--shot .hero__lede { color: var(--dark-ink-2); max-width: 30em; }
.hero--shot .hero__note { color: var(--dark-ink-2); }

@media (max-width: 900px) {
  .hero--shot .hero__inner { grid-template-columns: 1fr; gap: 1.5rem; }
  /* The picker is the point of this band and on a phone it was landing below
     the fold behind six lines of lede. Tighten the paragraph and drop the note,
     which the topbar already says and the sticky bar already offers. */
  .hero--shot .hero__lede { font-size: 1rem; line-height: 1.5; }
  /* On a phone the photograph is behind a tall stack, so the scrim has to work
     vertically rather than left to right or the copy lands on the bright half. */
  .hero--shot .hero__bg::after {
    background: linear-gradient(180deg, rgba(22,24,28,.88) 0%, rgba(22,24,28,.80) 55%, rgba(22,24,28,.92) 100%);
  }
}
/* ------------------------------------------------------- cheap vs done right

   The argument that justifies the price, on every service page. Two columns,
   the failure mode on the left and what we do on the right, marked with a
   times and a tick rather than color alone: color is not available to every
   reader and this distinction is the whole point of the band. */

.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--bord); border: 1px solid var(--bord); }
.compare > div { background: var(--surface); padding: clamp(1.4rem, 2.8vw, 2rem); min-width: 0; }
.compare h3 { margin-bottom: .3rem; }
.compare__sub { font-size: .82rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--steel); margin: 0 0 1.1rem; }
.compare ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .7rem; }
.compare li { display: flex; gap: .65rem; font-size: .96rem; color: var(--ink-2); line-height: 1.5; }
.compare li::before { flex: none; font-weight: 800; line-height: 1.5; }
.compare__bad li::before { content: "\00d7"; color: var(--action); }
.compare__good li::before { content: "\2713"; color: var(--good); }
.compare__good { background: var(--surface); }
.compare__foot { margin-top: 1.5rem; max-width: 52rem; color: var(--ink-2); }

/* The stats strip on a service page reuses .trust, whose numerals can carry a
   unit (400 degrees F, 2-3 yrs). .specs already had this; .trust did not,
   because the home page never passed one. */
.trust dt small { font-size: .4em; font-weight: 700; letter-spacing: .02em; }

/* Price-band footnote, and the tick list inside a package card. Both existed in
   the markup with no rule behind them. */
.prices__foot { margin-top: 1.5rem; max-width: 52rem; color: var(--ink-2); }
.card .amount { font-family: var(--font-display); font-size: 1.5rem; font-weight: 800; margin: .5rem 0 .8rem; }
.ticks { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: .45rem; font-size: .9rem; }
.ticks li { display: flex; gap: .55rem; color: var(--ink-2); }
.ticks li::before { content: "\2713"; color: var(--good); font-weight: 800; flex: none; }

@media (max-width: 720px) {
  .compare { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------- proof band

   Three stages of a lot repair, image-led. Same grid as the service cards, but
   these are figures rather than links: nothing to click, the photograph is the
   argument. Stage label sits over the image so the caption underneath can be a
   real sentence instead of a fragment doing two jobs. */

/* ------------------------------------------------------- full-bleed media ---

   The scroll punctuation: one cinematic moment at about 70% depth, on a
   photograph rather than a rectangle of colour.

   Kept SHORT on purpose. Every file we hold is 1400px wide, and 1400 across a
   1920 viewport is a 1.37x upscale that reads soft anywhere the eye can audit
   detail. At half a viewport the eye reads texture and never audits, so the
   band can run genuinely edge to edge where the capped hero cannot.

   (Restored after a component merge deleted it as collateral. The merge cut a
   range by comment marker and this block sat inside the range. orphan-classes
   caught it immediately, which is what that tool is for.) */

.mediaband {
  position: relative; background: var(--dark-bg);
  min-height: clamp(340px, 48vh, 520px);
  display: grid; align-items: end; overflow: hidden;
}
.mediaband > img, .mediaband > picture > img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  /* Tuned by eye against the render, twice. Too low and the band is lane
     markings with no horizon, which is a texture rather than a place. Too high
     and it is a playing field with a strip of track at the bottom, which is
     somebody else's photograph. 58% is where the curve and the treeline are
     both in frame. */
  object-fit: cover; object-position: 50% 58%;
}
.mediaband::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(0deg,  rgba(22,24,28,.94) 0%, rgba(22,24,28,.62) 34%, rgba(22,24,28,.10) 72%),
    linear-gradient(92deg, rgba(22,24,28,.88) 0%, rgba(22,24,28,.62) 34%, rgba(22,24,28,.10) 68%, rgba(22,24,28,0) 100%);
}
.mediaband .wrap { position: relative; z-index: 1; padding-block: clamp(1.75rem, 4vw, 3rem); }
.mediaband__line {
  font-family: var(--font-display); font-weight: 700; font-stretch: 104%;
  font-size: clamp(1.35rem, 3vw, 2.25rem); line-height: 1.15; letter-spacing: -.02em;
  color: var(--dark-ink); margin: 0; max-width: 22ch; text-wrap: balance;
}
.mediaband .meta { color: rgba(244,242,239,.72); margin-bottom: .9rem; }

/* --------------------------------------------------------------- work grid

   ONE component for every "photograph, when, what" band on the site. It was
   two, .proof and .work, which were the same idea built twice: a figure, a
   fixed-ratio frame, a metadata line and a caption. They existed separately
   only because they were built in different weeks for different bands.

   Writing the page's copy as a document first made it obvious in about a
   minute. Building band by band had hidden it for the whole project.

   --stage is the one real difference: the repair sequence needs a numbered
   marker on the frame and the named-jobs grid does not. That is a modifier,
   not a second component. */

.work { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.75rem 1.5rem; }
.work figure { margin: 0; min-width: 0; }
.work__shot {
  position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--surface-2);
}
.work__shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.work figcaption { margin-top: .55rem; font-size: .9rem; line-height: 1.5; color: var(--ink-2); }
.work figcaption b { color: var(--ink); font-weight: 700; }
.work .meta { margin-top: .8rem; }

/* Three across, and a taller frame, for the sequence bands. Three steps of a
   repair want room to be read; four named jobs want to be scanned. */
.work--seq { grid-template-columns: repeat(3, 1fr); gap: 2rem 1.75rem; }
.work--seq .work__shot { aspect-ratio: 3 / 2; }
.work--seq figcaption { font-size: .93rem; line-height: 1.55; }

/* The stage marker. One of the six --line placements: a numeral on the
   marking-out colour, which is what a crew does to a lot before it cuts it. */
.work__stage {
  position: absolute; left: 0; top: 0; z-index: 3;
  background: var(--line); color: var(--ink);
  font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  padding: .45rem .8rem;
}

@media (max-width: 1040px) { .work { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px)  { .work--seq { grid-template-columns: 1fr; gap: 1.75rem; } }
@media (max-width: 560px)  { .work { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------- commitment list

   P12, the numbered-behaviour pattern. Deliberately NOT the .steps treatment
   used by the process band: two identical-looking numbered lists on one page
   read as a template, and these are doing a different job. Process is what
   happens on the day; this is what holds regardless of the job. Big type, wide
   measure, one rule between each. */

.commits { display: grid; border-top: 1px solid var(--bord); }
.commits > div {
  display: grid; grid-template-columns: 7.5rem 1fr; gap: 1.4rem;
  padding: 1.4rem 0; border-bottom: 1px solid var(--bord);
}
/* Small uppercase label rather than a big numeral, matching .eyebrow and
   .split__tag. Padded to sit on the baseline of the heading beside it. */
.commits dt {
  font-size: .72rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--steel); padding-top: .42rem;
}
.commits dd { margin: 0; min-width: 0; }
.commits dd b {
  display: block; font-size: clamp(1.05rem, 1.9vw, 1.28rem); font-weight: 700;
  color: var(--ink); margin-bottom: .35rem; text-wrap: balance;
}
/* Running text wants roughly 65 characters. Left unconstrained these lines
   ran the full 1180px wrap, which is about 110 and genuinely harder to read. */
.commits dd span { display: block; max-width: 46em; color: var(--ink-2); font-size: .97rem; line-height: 1.6; }

@media (max-width: 720px) {
  /* Label above the commitment rather than beside it: a 7.5rem column plus a
     heading does not fit a phone without the heading going ragged. */
  .commits > div { grid-template-columns: 1fr; gap: .35rem; }
  .commits dt { padding-top: 0; }
}

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 1.25rem; }
.card { background: var(--surface); border: 1px solid var(--bord); padding: 1.4rem; }
/* The recommended one. Same emphasis mechanism as the featured price band. */
.card--pick { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.card--pick h2, .card--pick .more { color: var(--paper); }
.card--pick .split__tag { color: var(--dark-ink-2); }
.card--pick p { color: var(--dark-ink-2) !important; }

table { border-collapse: collapse; width: 100%; }
.table-scroll { overflow-x: auto; }
th, td { text-align: left; padding: .7rem .85rem; border-bottom: 1px solid var(--bord); }
th { font-weight: 700; font-size: .85rem; letter-spacing: .04em; text-transform: uppercase; color: var(--steel); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}

/* ============================================================================
   LANDING V2 (2026-08-24). The rebuilt home page's band system, namespaced
   under .lv2 so nothing here can reach the other pages. Reads the site's own
   tokens; defines no new palette. Design source: design-prototype/landing-v2
   plus the contractor-frontend skill. Migrate other pages onto these classes
   band by band; when the last page moves, the pre-v2 band styles above can go.
   ========================================================================= */

.lv2{--hair:var(--bord);--hair-dark:var(--dark-bord);--action-lift:#E4515C}
.lv2 .disp,.lv2 h1,.lv2 h2,.lv2 h3{font-family:var(--font-display);font-variation-settings:"wdth" 116;font-weight:790;line-height:1.03;text-transform:uppercase;letter-spacing:.004em}
.lv2 .wrap{max-width:var(--wrap);margin:0 auto;padding-left:var(--gutter);padding-right:var(--gutter)}

/* hero */
.lv2-hero{position:relative;color:var(--dark-ink);background:var(--dark-bg)}
.lv2-hero__img{position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/lot-sealed-institutional.jpg") center 65%/cover no-repeat}
.lv2-hero__scrim{position:absolute;inset:0;background:linear-gradient(76deg,rgba(10,11,13,.95) 0%,rgba(10,11,13,.82) 44%,rgba(10,11,13,.42) 78%,rgba(10,11,13,.58) 100%)}
.lv2-hero__inner{position:relative;display:grid;grid-template-columns:1.18fr .82fr;gap:clamp(2rem,5vw,4rem);align-items:center;padding-top:clamp(3.5rem,7vw,6.5rem);padding-bottom:clamp(3rem,6vw,5rem);min-height:82vh}
.lv2-kick{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.22em;font-size:.8rem;color:rgba(244,242,239,.68);margin-bottom:1.1rem}
.lv2-kick i{font-style:normal;color:var(--line)}
.lv2-hero h1{font-size:clamp(2.2rem,4.3vw,3.4rem);max-width:16ch;color:#fff}
.lv2-hero h1 em{font-style:normal;color:var(--action-lift)}
.lv2-hero__sub{margin:1.35rem 0 .6rem;font-size:1.12rem;max-width:50ch;color:rgba(255,255,255,.9)}
.lv2-hero__rating{margin:.7rem 0 1.4rem;color:rgba(255,255,255,.82)}
.lv2-hero__rating b{color:#fff;font-size:1.1rem}
.lv2-hero__rating a{color:#fff;font-weight:600;text-decoration:none}
.lv2-hero__rating a:hover{color:var(--action-lift)}
@media(max-width:920px){.lv2-hero__inner{grid-template-columns:1fr;min-height:0;gap:2.2rem}}

/* hero form card: wraps the shared LeadForm without touching its internals */
.lv2-qcard{background:var(--paper);color:var(--ink);padding:clamp(1.4rem,3vw,2.1rem);box-shadow:var(--shadow-3)}
.lv2-qcard>h2{font-size:1.5rem;margin-bottom:.2rem}
.lv2-qcard__sub{font-size:.92rem;color:var(--ink-2);margin-bottom:.8rem}

/* ledger bar */
.lv2-ledger{background:#1A1D21;color:var(--dark-ink);border-top:1px solid var(--hair-dark)}
.lv2-ledger .wrap{display:flex;flex-wrap:wrap}
.lv2-ledger__item{flex:1 1 220px;padding:1.4rem 1.6rem 1.4rem 0;margin-right:1.6rem;border-right:1px solid var(--hair-dark);font-size:.94rem;color:var(--dark-ink-2)}
.lv2-ledger__item:last-child{border-right:none;margin-right:0}
.lv2-ledger__item b{display:block;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.04em;font-size:1.08rem;color:var(--dark-ink);font-weight:650}
@media(max-width:880px){.lv2-ledger__item{border-right:none;padding:.8rem 0;margin-right:0}}

/* doors */
.lv2-doors{background:var(--dark-bg)}
.lv2-doors__grid{display:grid;grid-template-columns:1fr 1fr;gap:2px}
.lv2-door{position:relative;min-height:500px;display:flex;align-items:flex-end;color:#fff;text-decoration:none;overflow:hidden}
.lv2-door img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .8s ease;filter:saturate(.93)}
.lv2-door:hover img{transform:scale(1.035)}
.lv2-door::after{content:"";position:absolute;inset:0;background:linear-gradient(8deg,rgba(10,11,13,.92) 10%,rgba(10,11,13,.4) 48%,rgba(10,11,13,.05) 78%)}
.lv2-door__body{position:relative;z-index:2;padding:clamp(1.6rem,3.5vw,2.6rem)}
.lv2-door h2{font-size:2rem;color:#fff}
.lv2-door p{margin:.55em 0 1.1em;color:rgba(255,255,255,.88);font-size:1rem;max-width:44ch}
.lv2-door__go{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.12em;font-weight:650;color:#fff;border-bottom:2px solid var(--action);padding-bottom:3px}
.lv2-door:hover .lv2-door__go{color:var(--action-lift)}
@media(max-width:880px){.lv2-doors__grid{grid-template-columns:1fr}.lv2-door{min-height:360px}}

/* ruled section head */
.lv2-shead{display:flex;align-items:baseline;gap:1.4rem;border-bottom:2px solid var(--ink);padding-bottom:.85rem}
.lv2-shead h2{font-size:clamp(1.9rem,3.6vw,2.8rem)}
.lv2-shead .tag{margin-left:auto;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.16em;font-size:.78rem;color:var(--steel);white-space:nowrap}
.lv2-dark .lv2-shead{border-bottom-color:var(--dark-ink)}
.lv2-dark .lv2-shead .tag{color:var(--dark-ink-2)}

/* segment strip rows */
.lv2-segs{background:var(--paper);padding:var(--section-pad) 0 0}
.lv2-seg{display:grid;grid-template-columns:5fr 7fr;border-bottom:1px solid var(--hair);align-items:stretch}
.lv2-seg:nth-child(even){grid-template-columns:7fr 5fr}
.lv2-seg:nth-child(even) figure{order:2}
.lv2-seg figure{margin:0;overflow:hidden;position:relative}
.lv2-seg img{width:100%;height:100%;min-height:290px;object-fit:cover}
.lv2-cap{position:absolute;left:0;bottom:0;background:var(--dark-bg);color:var(--dark-ink);font-family:var(--font-display);text-transform:uppercase;letter-spacing:.12em;font-size:.7rem;padding:.55em 1em;opacity:.93}
.lv2-seg__copy{padding:clamp(1.6rem,3.5vw,3rem);display:flex;flex-direction:column;justify-content:center}
.lv2-seg__copy h3{font-size:1.6rem;margin-bottom:.45em}
.lv2-seg__copy p{color:var(--ink-2);font-size:1.01rem;max-width:56ch}
@media(max-width:880px){.lv2-seg,.lv2-seg:nth-child(even){grid-template-columns:1fr}.lv2-seg:nth-child(even) figure{order:0}.lv2-seg__copy{padding:1.4rem 0 1.9rem}}

/* services index */
.lv2-svc{padding:var(--section-pad) 0}
.lv2-svc__item{display:grid;grid-template-columns:minmax(220px,1fr) 2fr auto;gap:1.4rem;align-items:baseline;padding:1.15rem 0;border-bottom:1px solid var(--hair);text-decoration:none;transition:background .15s}
.lv2-svc__item:hover{background:rgba(22,24,28,.035)}
.lv2-svc__item h3{font-size:1.3rem}
.lv2-svc__item p{font-size:.95rem;color:var(--ink-2)}
.lv2-svc__item .go{font-family:var(--font-display);color:var(--action);font-weight:650;font-size:1.1rem}
@media(max-width:760px){.lv2-svc__item{grid-template-columns:1fr;gap:.25rem}}

/* includes: photo + dark checklist */
.lv2-inc{padding:0 0 var(--section-pad)}
.lv2-inc__grid{display:grid;grid-template-columns:1fr 1fr;align-items:stretch}
.lv2-inc figure{margin:0;position:relative}
.lv2-inc img{width:100%;height:100%;object-fit:cover;min-height:420px}
.lv2-inc__copy{background:var(--dark-bg);color:var(--dark-ink);padding:clamp(2rem,4.5vw,3.4rem)}
.lv2-inc__copy h2{font-size:clamp(1.7rem,2.9vw,2.3rem);margin-bottom:.6em;color:#fff}
.lv2-inc__list{list-style:none;padding:0;margin:0}
.lv2-inc__list li{padding:.75rem 0 .75rem 2.1rem;position:relative;border-bottom:1px solid var(--hair-dark);font-size:1.01rem;color:rgba(244,242,239,.88)}
.lv2-inc__list li:last-child{border-bottom:none}
.lv2-inc__list li::before{content:"";position:absolute;left:2px;top:1.15rem;width:13px;height:7px;border-left:3px solid var(--action);border-bottom:3px solid var(--action);transform:rotate(-45deg)}
@media(max-width:880px){.lv2-inc__grid{grid-template-columns:1fr}}

/* honest band: dark, real asphalt texture */
.lv2-honest{position:relative;background:var(--dark-bg);color:var(--dark-ink);padding:var(--section-pad-lg) 0;overflow:hidden}
.lv2-honest::before{content:"";position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/asphalt-bg.jpg") center/cover;opacity:.12;mix-blend-mode:luminosity}
.lv2-honest .wrap{position:relative}
.lv2-honest__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5vw,4rem)}
.lv2-honest h2{font-size:clamp(1.9rem,3.4vw,2.7rem);max-width:16ch;color:#fff}
.lv2-honest blockquote{font-size:1.12rem;font-style:italic;color:rgba(244,242,239,.9);border-left:3px solid var(--action);padding-left:1.3rem;margin:0 0 1.4rem}
.lv2-honest cite{display:block;margin-top:.7rem;font-style:normal;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.1em;font-size:.78rem;color:var(--dark-ink-2)}
.lv2-honest p{color:rgba(244,242,239,.82)}
@media(max-width:880px){.lv2-honest__grid{grid-template-columns:1fr;gap:1.6rem}}

/* pull quote */
.lv2-pull{background:var(--action);color:#fff;padding:clamp(3.4rem,6vw,5.4rem) 0}
.lv2-pull blockquote{font-family:var(--font-display);font-variation-settings:"wdth" 112;font-size:clamp(1.5rem,3vw,2.3rem);line-height:1.16;font-weight:650;max-width:28ch;margin:0;text-indent:-.45em}
.lv2-pull cite{display:block;margin-top:1.3rem;font-family:var(--font-body);font-style:normal;font-size:1rem;opacity:.92}

/* drive band */
.lv2-drive__grid{display:grid;grid-template-columns:1fr 1fr;align-items:stretch}
.lv2-drive figure{margin:0;position:relative}
.lv2-drive img{width:100%;height:100%;object-fit:cover;min-height:460px}
.lv2-drive__copy{padding:clamp(2.4rem,5vw,4.4rem) clamp(1.6rem,4vw,3.6rem);background:var(--surface-2)}
.lv2-drive__copy h2{font-size:clamp(1.8rem,3.2vw,2.5rem);max-width:14ch;margin-bottom:.6em}
.lv2-drive__copy p{color:var(--ink-2)}
.lv2-drive__copy p+p{margin-top:.85rem}
.lv2-qsmall{border-left:3px solid var(--action);padding-left:1.1rem;margin-top:1.5rem;font-size:.97rem}
.lv2-qsmall b{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.08em;font-size:.78rem;color:var(--steel);display:block;margin-top:.4rem}
@media(max-width:920px){.lv2-drive__grid{grid-template-columns:1fr}}

/* work carousel */
.lv2-work{background:var(--surface-2);padding:var(--section-pad) 0}
.lv2-car{position:relative;overflow:hidden}
.lv2-car__track{display:flex;transition:transform .6s cubic-bezier(.22,.8,.3,1)}
.lv2-car__slide{flex:0 0 100%;position:relative}
.lv2-car__slide img{width:100%;height:min(60vh,540px);object-fit:cover}
.lv2-car__cap{position:absolute;left:0;bottom:0;background:var(--dark-bg);color:var(--dark-ink);padding:1rem 1.5rem;max-width:min(520px,88%)}
.lv2-car__cap b{display:block;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;font-size:1.1rem;font-weight:650}
.lv2-car__cap span{display:block;font-size:.88rem;color:var(--dark-ink-2);margin-top:2px}
.lv2-car__nav{position:absolute;right:0;bottom:0;display:flex}
.lv2-car__nav button{width:54px;height:54px;border:none;cursor:pointer;font-size:1.35rem;background:var(--paper);color:var(--ink);transition:background .2s,color .2s}
.lv2-car__nav button:hover{background:var(--action);color:#fff}
.lv2-car__nav button+button{border-left:1px solid var(--hair)}
.lv2-car__count{position:absolute;top:0;right:0;background:var(--dark-bg);color:var(--dark-ink);font-family:var(--font-display);letter-spacing:.1em;padding:.45em 1em;font-size:.82rem}

/* reviews */
.lv2-reviews{padding:var(--section-pad) 0}
.lv2-reviews .lead{font-family:var(--font-body);font-size:clamp(1.3rem,2.3vw,1.7rem);line-height:1.32;max-width:34ch;margin:1.9rem 0 .5rem;text-indent:-.42em}
.lv2-reviews .lead+cite{font-style:normal;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.1em;font-size:.82rem;color:var(--steel)}
.lv2-reviews__pair{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.6rem,4vw,3.4rem);margin-top:2.2rem;padding-top:1.8rem;border-top:1px solid var(--hair)}
.lv2-reviews__pair blockquote{font-size:1rem;margin:0;text-indent:-.42em}
.lv2-reviews__pair cite{display:block;margin-top:.6rem;font-style:normal;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.1em;font-size:.78rem;color:var(--steel)}
@media(max-width:760px){.lv2-reviews__pair{grid-template-columns:1fr;gap:1.4rem}}

/* specs: big count-up numerals on dark */
.lv2-specs{position:relative;background:var(--dark-bg);color:var(--dark-ink);padding:var(--section-pad-lg) 0;overflow:hidden}
.lv2-specs::before{content:"";position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/asphalt-bg.jpg") center/cover;opacity:.1;mix-blend-mode:luminosity}
.lv2-specs .wrap{position:relative}
.lv2-specs__row{display:grid;grid-template-columns:repeat(4,1fr);margin-top:.5rem}
.lv2-spec{padding:2.1rem 1.9rem 0 0;margin-right:1.9rem;border-right:1px solid var(--hair-dark)}
.lv2-spec:last-child{border-right:none;margin-right:0}
.lv2-spec b{display:block;font-family:var(--font-display);font-variation-settings:"wdth" 118;font-weight:790;font-size:clamp(2.8rem,5vw,4.3rem);line-height:.95;color:#fff}
.lv2-spec b i{font-style:normal;color:var(--action-lift)}
.lv2-spec span{display:block;margin-top:.85rem;font-size:.9rem;color:var(--dark-ink-2)}
@media(max-width:920px){.lv2-specs__row{grid-template-columns:1fr 1fr;row-gap:2rem}.lv2-spec{border-right:none}}

/* identity strip */
.lv2-id{padding:2.4rem 0;border-bottom:1px solid var(--hair);background:var(--paper)}
.lv2-id .wrap{display:flex;justify-content:space-between;align-items:center;gap:1.4rem;flex-wrap:wrap}
.lv2-id__main{font-family:var(--font-display);text-transform:uppercase;font-weight:790;font-variation-settings:"wdth" 116;font-size:clamp(1.25rem,2.3vw,1.7rem);letter-spacing:.04em}
.lv2-id__main i{font-style:normal;color:var(--action)}
.lv2-id__side{font-size:.94rem;color:var(--ink-2);text-align:right}
@media(max-width:700px){.lv2-id__side{text-align:left}}

/* area */
.lv2-area{padding:var(--section-pad) 0}
.lv2-area__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5vw,4rem)}
.lv2-area__copy{padding-top:1.9rem}
.lv2-area__copy>p{color:var(--ink-2)}
.lv2-towns{margin-top:1.5rem;column-count:3;column-gap:2rem;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.06em;font-size:1rem;line-height:2.15}
.lv2-towns a{display:block;border-bottom:1px solid var(--hair);text-decoration:none;color:var(--ink)}
.lv2-towns a:hover{color:var(--action)}
@media(max-width:880px){.lv2-area__grid{grid-template-columns:1fr}.lv2-towns{column-count:2}}

/* final CTA */
.lv2-final{position:relative;color:#fff;padding:clamp(4rem,8vw,7rem) 0}
.lv2-final__img{position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/school-lot-sealed.jpg") center/cover no-repeat}
.lv2-final__scrim{position:absolute;inset:0;background:linear-gradient(90deg,rgba(10,11,13,.93),rgba(10,11,13,.72))}
.lv2-final .wrap{position:relative}
.lv2-final h2{font-size:clamp(2.1rem,4.2vw,3.2rem);max-width:14ch;color:#fff}
.lv2-final p{margin:1.1rem 0 1.9rem;color:rgba(255,255,255,.85);max-width:52ch}
.lv2-final__ctas{display:flex;gap:.9rem;flex-wrap:wrap}

/* reveal + buttons on dark grounds */
.lv2 .btn--ghost{box-shadow:inset 0 0 0 2px #fff;color:#fff;background:transparent}
.lv2 .btn--ghost:hover{background:#fff;color:var(--ink)}
.lv2-rev{opacity:0;transform:translateY(20px);transition:opacity .7s ease,transform .7s ease}
.lv2-rev.lv2-in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.lv2-rev{opacity:1;transform:none;transition:none}.lv2-car__track{transition:none}}

/* lv2 addenda */
.lv2-faqband{padding:var(--section-pad) 0}
.lv2-towns span{display:block;border-bottom:1px solid var(--hair)}
.lv2-mapslot{border:1px solid var(--hair);min-height:340px;display:flex;align-items:center;justify-content:center;text-align:center;color:var(--steel);font-size:.92rem;padding:1.4rem;background:repeating-linear-gradient(0deg,transparent,transparent 39px,rgba(22,24,28,.05) 40px),repeating-linear-gradient(90deg,transparent,transparent 39px,rgba(22,24,28,.05) 40px)}

/* ---------------------------------------------------------------------------
   DARK HEADER (2026-08-24). Sitewide: the header joins the topbar on ink so
   the top of every page reads as one dark cap, matching the v2 hero. The
   wordmark is red with a white outline and was drawn for dark grounds (it
   sat on black on his trucks and his Wix header). The dropdown panel stays
   light: a light sheet under a dark bar is the readable convention.
   ------------------------------------------------------------------------ */
.site-header{background:var(--dark-bg);border-bottom:1px solid var(--dark-bord);box-shadow:none}
.site-header .site-nav a{color:var(--dark-ink)}
.site-header .site-nav a:hover{color:#fff}
.site-header .hdr-phone{color:#fff}
.site-header .hdr-rating{color:var(--dark-ink)}
.mnav-toggle span,.mnav-toggle span::before,.mnav-toggle span::after{background:var(--dark-ink)}

/* ---------------------------------------------------------------------------
   HERO FORM, COMPACTED (2026-08-24). The shared LeadForm renders five fields
   plus the TCPA consent block, which made the hero card tower over the copy.
   Scoped to .lv2-qcard only: the contact page keeps the roomy version.
   Name/phone and email/zip pair up on one row each, the consent legalese
   drops to fine print (still fully visible: it is a compliance text, not
   decoration), and every vertical gap tightens.
   ------------------------------------------------------------------------ */
.lv2-qcard>h2{font-size:1.35rem}
.lv2-qcard .leadform{display:grid;grid-template-columns:1fr 1fr;gap:.35rem .8rem}
.lv2-qcard .leadform>*{grid-column:1/-1}
.lv2-qcard .leadform__field:has(#hero-name),.lv2-qcard .leadform__field:has(#hero-email){grid-column:1}
.lv2-qcard .leadform__field:has(#hero-phone),.lv2-qcard .leadform__field:has(#hero-zip){grid-column:2}
.lv2-qcard .leadform__field{margin:0}
.lv2-qcard .leadform__field label{font-size:.72rem;letter-spacing:.07em;text-transform:uppercase;font-family:var(--font-display);color:var(--ink-2);margin-bottom:.15rem}
.lv2-qcard .leadform__field input,.lv2-qcard .leadform__field textarea{padding:.45em .6em;font-size:.95rem}
.lv2-qcard .leadform__field textarea{min-height:3.2em}
.lv2-qcard .sms-consent{margin:.4rem 0 0}
.lv2-qcard .sms-consent__text{font-size:.66rem;line-height:1.35;color:var(--steel)}
.lv2-qcard .leadform .btn,.lv2-qcard .leadform button[type=submit]{margin-top:.6rem;width:100%}
@media(max-width:560px){.lv2-qcard .leadform{grid-template-columns:1fr}.lv2-qcard .leadform>*{grid-column:1/-1 !important}}

/* ---------------------------------------------------------------------------
   HERO CARD, DARK REWORK (2026-08-24). The paper card fought the photo: a
   white rectangle floating on a dark hero reads as an overlay, not part of
   the page. Now it is an asphalt panel that belongs to the hero: dark ground,
   hairline underline inputs that focus red, the red submit as the only loud
   element. Overrides the earlier paper treatment by cascade; the compact
   two-column field pairing above still applies.
   ------------------------------------------------------------------------ */
.lv2-qcard{background:rgba(19,21,25,.92);color:var(--dark-ink);border:1px solid var(--dark-bord);border-top:3px solid var(--action);box-shadow:var(--shadow-3);backdrop-filter:blur(2px)}
.lv2-qcard>h2{color:#fff}
.lv2-qcard__sub{color:var(--dark-ink-2)}
.lv2-qcard__sub a{color:#fff}
.lv2-qcard .leadform__field label{color:var(--dark-ink-2)}
.lv2-qcard .leadform__field input,.lv2-qcard .leadform__field textarea{background:rgba(244,242,239,.05);border:0;border-bottom:2px solid var(--dark-bord);color:#fff;border-radius:0}
.lv2-qcard .leadform__field input::placeholder,.lv2-qcard .leadform__field textarea::placeholder{color:rgba(244,242,239,.35)}
.lv2-qcard .leadform__field input:focus,.lv2-qcard .leadform__field textarea:focus{outline:none;border-bottom-color:var(--action);background:rgba(244,242,239,.08)}
.lv2-qcard .sms-consent__text{color:rgba(169,173,180,.85)}
.lv2-qcard .sms-consent__link{color:var(--dark-ink)}
.lv2-qcard .sms-consent__checkbox{accent-color:var(--action)}
.lv2-qcard .leadform__submit{width:100%;margin-top:.6rem}

/* ---------------------------------------------------------------------------
   PREMIUM POLISH PASS (2026-08-24). Fixes from the rendered-page audit plus
   the micro-interaction layer: the small things that make a page feel
   finished. Grouped: audit fixes first, then interactions.
   ------------------------------------------------------------------------ */

/* AUDIT FIX: the LeadForm ships its own light panel; inside the dark hero
   card it rendered a white box with white text. Strip it to bare fields. */
.lv2-qcard .leadform{background:transparent;border:0;box-shadow:none;padding:0;border-radius:0}

/* AUDIT FIX: the H1 ran six uppercase lines. Sentence case, tighter width
   axis, smaller clamp: two to three confident lines instead of a shout. */
.lv2-hero h1{text-transform:none;font-size:clamp(2.1rem,3.4vw,2.9rem);max-width:19ch;font-variation-settings:"wdth" 108;letter-spacing:-.01em;line-height:1.06}

/* AUDIT FIX: the hero photo's interest is the sealed lot at the bottom of
   the frame; the old crop showed the top of the scene. */
.lv2-hero__img{background-position:center bottom}

/* AUDIT FIX: consent row rendered with the checkbox orphaned above its
   text. Pin them side by side and tighten the fine print. */
.lv2-qcard .sms-consent__row{display:flex;gap:.55rem;align-items:flex-start}
.lv2-qcard .sms-consent__checkbox{margin-top:2px;flex:none}
.lv2-qcard .sms-consent__text{display:block;line-height:1.4}

/* Crisp text on dark grounds. */
.lv2-hero,.lv2-ledger,.lv2-doors,.lv2-inc__copy,.lv2-honest,.lv2-pull,.lv2-specs,.site-header,.lv2-qcard{-webkit-font-smoothing:antialiased}

/* Selection and tap color carry the brand. */
.lv2 ::selection{background:var(--action);color:#fff}
.lv2 a,.lv2 button{-webkit-tap-highlight-color:transparent}

/* Anchors land clear of the sticky header. */
.lv2 [id]{scroll-margin-top:96px}

/* Buttons: lift on hover, settle on press, visible keyboard focus. */
.lv2 .btn,.site-header .btn{transition:background .18s,color .18s,transform .18s,box-shadow .18s}
.lv2 .btn:hover{transform:translateY(-1px);box-shadow:var(--shadow-chip)}
.lv2 .btn:active{transform:translateY(0);box-shadow:none}
.lv2 a:focus-visible,.lv2 button:focus-visible,.lv2 input:focus-visible,.lv2 textarea:focus-visible,.site-header a:focus-visible{outline:2px solid var(--action);outline-offset:2px}

/* Services index: the arrow answers the hover. */
.lv2-svc__item .go{transition:transform .2s}
.lv2-svc__item:hover .go{transform:translateX(5px)}
.lv2-svc__item:hover h3{color:var(--action)}
.lv2-svc__item h3{transition:color .15s}

/* Doors: the go-line brightens and steps forward with the photo. */
.lv2-door__go{transition:color .2s,letter-spacing .2s}
.lv2-door:hover .lv2-door__go{letter-spacing:.15em}

/* FAQ: the plus turns, the question warms. */
.faq__item summary{transition:color .15s}
.faq__item summary:hover{color:var(--action)}
.faq__item summary::after{transition:transform .25s}
.faq__item[open] summary::after{transform:rotate(45deg)}

/* Inputs ease between states instead of snapping. */
.lv2-qcard .leadform__field input,.lv2-qcard .leadform__field textarea{transition:border-color .18s,background .18s}

/* Carousel: keyboard focus ring on the frame, grab cursor on touch-ish. */
.lv2-car{cursor:grab}
.lv2-car:active{cursor:grabbing}
.lv2-car:focus-visible{outline:2px solid var(--action);outline-offset:4px}
.lv2-car__nav button:focus-visible{outline:2px solid var(--action);outline-offset:-2px}

/* Quiet links get a live underline. */
.lv2 .more{transition:color .15s}
.lv2 .more:hover{color:var(--action)}
.lv2-towns a{transition:color .15s,border-color .15s}
.lv2-towns a:hover{border-bottom-color:var(--action)}

/* Reveal transition stays JS-gated; nothing hides without it. */
@media(prefers-reduced-motion:reduce){
  .lv2 .btn:hover{transform:none}
  .lv2-svc__item:hover .go{transform:none}
}

/* AUDIT FIX 2: the consent text span was collapsing to min-content and the
   checkbox drifting center (an inherited rule the cascade would not give
   up). Grid with an explicit 1fr text track cannot collapse, whatever the
   ancestors say. */
.lv2-qcard .sms-consent__row{display:grid;grid-template-columns:16px minmax(0,1fr);gap:.55rem;align-items:start;width:100%}
.lv2-qcard .sms-consent__checkbox{margin:2px 0 0;justify-self:start}
.lv2-qcard .sms-consent__text{width:auto;min-width:0;max-width:none}

/* AUDIT FIX 3: the hero photo's top edge carries scene clutter (building
   roofline, event tents). A top vignette settles it without flattening the
   lot below. */
.lv2-hero__scrim{background:linear-gradient(180deg,rgba(10,11,13,.88) 0%,rgba(10,11,13,0) 30%),linear-gradient(76deg,rgba(10,11,13,.95) 0%,rgba(10,11,13,.82) 44%,rgba(10,11,13,.42) 78%,rgba(10,11,13,.58) 100%)}

/* ---------------------------------------------------------------------------
   SERVICE AREA MAP (2026-08-24). The real BW-07 boundary rendered as inline
   SVG on a dark panel: red line, a dot for all 105 places, majors labeled,
   Eau Claire pulsing as home. Replaces the dashed placeholder.
   ------------------------------------------------------------------------ */
.lv2-map{margin:0;background:var(--dark-bg);border:1px solid var(--dark-bord);padding:1.2rem 1.2rem .6rem;position:relative;overflow:hidden}
.lv2-map::before{content:"";position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/asphalt-bg.jpg") center/cover;opacity:.1;mix-blend-mode:luminosity}
.lv2-map svg{position:relative;width:100%;height:auto;display:block}
.lv2-map .map-bound{fill:rgba(191,30,44,.07);stroke:var(--action);stroke-width:2.5;stroke-linejoin:round}
.lv2-map .map-dot{fill:rgba(244,242,239,.4)}
.lv2-map .map-town{fill:var(--dark-ink)}
.lv2-map .map-home{fill:var(--action)}
.lv2-map .map-home-ring{fill:none;stroke:var(--action);stroke-width:1.5;opacity:.5;animation:lv2-pulse 2.6s ease-out infinite}
@keyframes lv2-pulse{0%{transform:scale(.6);opacity:.7}70%{transform:scale(1.25);opacity:0}100%{opacity:0}}
.lv2-map .map-home-ring{transform-origin:center;transform-box:fill-box}
.lv2-map .map-lbl{font-family:var(--font-display);font-size:12.5px;letter-spacing:.08em;fill:var(--dark-ink);font-weight:600}
.lv2-map .map-lbl--home{font-size:14px;fill:#fff;font-weight:700}
.lv2-map figcaption{position:relative;font-size:.85rem;color:var(--dark-ink-2);padding:.7rem .2rem .5rem;text-align:center}
@media(prefers-reduced-motion:reduce){.lv2-map .map-home-ring{animation:none;opacity:.4}}

/* POP PASS: photographs get more vertical presence; the identity strip
   reads as a statement instead of a footnote. */
.lv2-seg img{min-height:340px}
.lv2-id{padding:3rem 0;border-top:1px solid var(--hair)}
.lv2-id__main{font-size:clamp(1.5rem,2.8vw,2.1rem)}
.lv2-towns span{break-inside:avoid}

/* ---------------------------------------------------------------------------
   LV2 SUBPAGE SYSTEM (2026-08-24). The pieces the commercial-layer pages
   share: a dark page hero (no form), prose bands, data tables, and a
   numbered process list. Everything reads the same tokens as the home page.
   ------------------------------------------------------------------------ */
.lv2-phero{position:relative;background:var(--dark-bg);color:var(--dark-ink);overflow:hidden}
.lv2-phero::before{content:"";position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/asphalt-bg.jpg") center/cover;opacity:.14;mix-blend-mode:luminosity}
.lv2-phero .wrap{position:relative;padding-top:clamp(3rem,6vw,5rem);padding-bottom:clamp(2.6rem,5vw,4.2rem)}
.lv2-phero h1{font-size:clamp(2rem,3.6vw,3rem);max-width:22ch;color:#fff;text-transform:none;font-variation-settings:"wdth" 108;letter-spacing:-.01em;line-height:1.06}
.lv2-phero__sub{margin:1.2rem 0 1.4rem;font-size:1.1rem;max-width:56ch;color:rgba(244,242,239,.88)}
.lv2-phero__meta{color:rgba(244,242,239,.8)}
.lv2-phero__meta b{color:#fff}
.lv2-phero__meta a{color:#fff;font-weight:600;text-decoration:none}
.lv2-band{padding:var(--section-pad) 0}
.lv2-band--alt{background:var(--surface-2)}
.lv2-band--dark{background:var(--dark-bg);color:var(--dark-ink)}
.lv2-band--dark p{color:rgba(244,242,239,.82)}
.lv2-prose{max-width:62ch}
.lv2-prose p+p{margin-top:.9rem}
.lv2-cols2{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.8rem,4vw,3.4rem);align-items:start}
@media(max-width:880px){.lv2-cols2{grid-template-columns:1fr}}
.lv2-table{width:100%;border-collapse:collapse;margin-top:1.4rem;font-size:.97rem}
.lv2-table th{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.07em;font-size:.8rem;text-align:left;color:var(--steel);padding:.6rem .9rem .6rem 0;border-bottom:2px solid var(--ink)}
.lv2-table td{padding:.7rem .9rem .7rem 0;border-bottom:1px solid var(--hair);vertical-align:top}
.lv2-table td:first-child{font-weight:600}
.lv2-steps{list-style:none;padding:0;margin:1.4rem 0 0;counter-reset:lv2step}
.lv2-steps li{position:relative;padding:.9rem 0 .9rem 3.4rem;border-bottom:1px solid var(--hair);counter-increment:lv2step}
.lv2-steps li::before{content:counter(lv2step);position:absolute;left:0;top:.8rem;width:2.2rem;height:2.2rem;display:flex;align-items:center;justify-content:center;background:var(--action);color:#fff;font-family:var(--font-display);font-weight:700;font-size:1.05rem}
.lv2-qbig{border-left:3px solid var(--action);padding-left:1.3rem;margin:1.6rem 0;font-size:1.08rem;font-style:italic}
.lv2-qbig cite{display:block;margin-top:.6rem;font-style:normal;font-family:var(--font-display);text-transform:uppercase;letter-spacing:.09em;font-size:.78rem;color:var(--steel)}
.lv2-band--dark .lv2-qbig cite{color:var(--dark-ink-2)}
.lv2-band--dark .lv2-table th{border-bottom-color:var(--dark-ink);color:var(--dark-ink-2)}
.lv2-band--dark .lv2-table td{border-bottom-color:var(--hair-dark)}
.lv2-callout{background:var(--dark-bg);color:var(--dark-ink);padding:1.3rem 1.5rem;margin-top:1.4rem;border-left:3px solid var(--action);font-size:.98rem}

/* ---------------------------------------------------------------------------
   PREMIUM PASS 2 (2026-08-24). The finish layer: hero choreography, drawn
   section rules, staggered reveals, carousel progress, typographic links.
   ------------------------------------------------------------------------ */

/* Links inside v2 prose were falling to browser blue on the new pages. The
   house link: inherit the text color, red underline, warm to red on hover. */
.lv2 :is(p,li,td) a{color:inherit;font-weight:600;text-decoration:underline;text-decoration-color:var(--action);text-decoration-thickness:1.5px;text-underline-offset:3px;transition:color .15s}
.lv2 :is(p,li,td) a:hover{color:var(--action)}
.lv2-band--dark :is(p,li,td) a:hover,.lv2-honest :is(p,li,td) a:hover,.lv2-inc__copy li a:hover{color:var(--action-lift)}

/* Hero entrance choreography: kicker, headline, subhead, rating rise in
   turn; the form card arrives from the right. Pure CSS, so it needs no
   script and cannot strand content hidden. */
@keyframes lv2Up{from{opacity:0;transform:translateY(26px)}to{opacity:1;transform:none}}
@keyframes lv2Side{from{opacity:0;transform:translateX(34px)}to{opacity:1;transform:none}}
.lv2-up{animation:lv2Up .7s cubic-bezier(.22,.8,.3,1) both}
.lv2-side{animation:lv2Side .8s cubic-bezier(.22,.8,.3,1) both}
.lv2-d1{animation-delay:.08s}.lv2-d2{animation-delay:.2s}.lv2-d3{animation-delay:.34s}.lv2-d4{animation-delay:.48s}.lv2-d5{animation-delay:.6s}

/* The photo breathes: one slow settle-in zoom, then still. */
@keyframes lv2Drift{from{transform:scale(1.06)}to{transform:scale(1)}}
.lv2-hero__img{animation:lv2Drift 14s ease-out both}

/* The kicker draws its own red rule before the text lands. */
.lv2-kick{position:relative;padding-left:2.6rem}
.lv2-kick::before{content:"";position:absolute;left:0;top:.45em;width:2rem;height:3px;background:var(--action);transform-origin:left;animation:lv2Rule .7s ease-out both}
@keyframes lv2Rule{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* Section-head rules draw themselves in as the head reveals. The rule moves
   from border-bottom to a pseudo so it can animate; pages that never run the
   reveal script simply show it complete. */
.lv2-shead{border-bottom:0;position:relative}
.lv2-shead::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--ink);transform-origin:left}
.lv2-band--dark .lv2-shead::after,.lv2-dark.lv2-shead::after,.lv2-shead.lv2-dark::after{background:var(--dark-ink)}
.lv2-shead.lv2-rev::after{transform:scaleX(0);transition:transform .9s cubic-bezier(.22,.8,.3,1) .15s}
.lv2-shead.lv2-in::after{transform:scaleX(1)}

/* Doors light up under the pointer. */
.lv2-door img{filter:saturate(.93) brightness(.92);transition:transform .8s ease,filter .5s ease}
.lv2-door:hover img{filter:saturate(1) brightness(1)}

/* Carousel: autoplay progress along the bottom, captions that step in with
   their slide, drawn arrow buttons. */
.lv2-car__bar{position:absolute;left:0;bottom:0;height:3px;width:100%;background:rgba(12,13,15,.25);z-index:2}
.lv2-car__bar i{display:block;height:100%;width:0;background:var(--action)}
.lv2-car__bar.run i{animation:lv2CarRun 5s linear both}
@keyframes lv2CarRun{from{width:0}to{width:100%}}
.lv2-car__cap{opacity:0;transform:translateY(10px);transition:opacity .45s ease .15s,transform .45s ease .15s}
.lv2-car__slide.is-on .lv2-car__cap{opacity:.96;transform:none}
.lv2-car__nav svg{width:20px;height:20px;display:block;margin:auto}

/* FAQ answers ease open instead of snapping. */
@keyframes lv2FaqIn{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}
.faq__item[open] .faq__a{animation:lv2FaqIn .3s ease both}

/* The header earns a shadow once the page is moving under it. */
.site-header{transition:box-shadow .25s}
.site-header.is-scrolled{box-shadow:var(--shadow-pop)}

@media(prefers-reduced-motion:reduce){
  .lv2-up,.lv2-side,.lv2-hero__img,.lv2-kick::before{animation:none}
  .lv2-shead.lv2-rev::after{transform:none;transition:none}
  .lv2-car__bar{display:none}
  .lv2-car__cap{opacity:.96;transform:none;transition:none}
}

/* COLOR AUDIT (2026-08-24): gold back to stars-only (kicker dots now carry
   the lane-line yellow, the trade's own marking color); the light red is a
   token; and the spec band's head rule takes the yellow, the one placement
   the token rules explicitly allow it. */
.lv2-specs .lv2-shead::after{background:var(--line)}

/* ============================================================================
   HS SYSTEM (2026-08-24). The approved sample (design-prototype/sample-hss,
   hybrid direction) ported as the home page's band system. Light-dominant
   body under the existing dark header, one dark punch band, site tokens
   only. The lv2 layers above are retired; remove them when no page uses
   them.
   ========================================================================= */
.hs-hero{position:relative;color:#fff;padding:0;overflow:hidden}
.hs-hero__img{position:absolute;inset:0;background:url("/assets/black-widow-sealcoating/lot-sealed-institutional.jpg") center 70%/cover no-repeat}
.hs-hero__scrim{position:absolute;inset:0;background:linear-gradient(180deg,rgba(15,16,18,.55),rgba(15,16,18,.72))}
.hs-hero__in{position:relative;padding-top:clamp(3.4rem,7vw,6rem);padding-bottom:clamp(3rem,6vw,5.2rem);max-width:720px}
.hs-hero h1{font-size:clamp(1.9rem,3.9vw,2.9rem);font-weight:800;color:#fff;line-height:1.1}
.hs-hero p{margin:1rem 0 .3rem;font-size:1.1rem;color:rgba(255,255,255,.94);max-width:54ch}
.hs-hero__meta{margin:.5rem 0 1.4rem;color:rgba(255,255,255,.9)}
.hs-hero__ctas{display:flex;gap:.8rem;flex-wrap:wrap}
.hs-btn-white{background:#fff;color:var(--ink)}
.hs-btn-white:hover{background:var(--surface-2)}

/* Trust bar (PA-12): anchor-led cells, value over label, hairline rules
   between. Four cells in one row on desktop, 2x2 on phones. Dark since
   2026-08-25 (Wayne): in cream it was a thin light stripe pinched between
   the dark hero and the dark doors and read as a gap; on ink it is the
   hero's baseboard, and the whole opening act runs dark before the light
   body starts at the services band. */
.hs-facts{background:var(--dark-bg);color:var(--dark-ink);border-top:1px solid rgba(255,255,255,.08);border-bottom:1px solid rgba(255,255,255,.08);padding:1.15rem 0}
.hs-facts__grid{display:grid;grid-template-columns:repeat(4,auto);justify-content:center}
.hs-facts__grid>div{padding:.15rem 2.2rem;border-left:1px solid var(--dark-bord)}
.hs-facts__grid>div:first-child{border-left:none}
.hs-facts b{display:block;font-family:var(--font-display);font-weight:800;font-size:1.05rem;letter-spacing:-.01em;color:#fff}
.hs-facts span{display:block;font-size:.7rem;text-transform:uppercase;letter-spacing:.08em;color:var(--dark-ink-2);font-weight:600;margin-top:2px}
@media(max-width:980px){
  .hs-facts__grid{grid-template-columns:1fr 1fr;gap:.9rem 0}
  .hs-facts__grid>div{padding:.1rem 1.1rem}
  .hs-facts__grid>div:nth-child(odd){border-left:none;padding-left:0}
}
/* COMPAT for the span form of the strip. Ten interior pages still carry
   <span> children from the pre-rebuild markup; deleting the old rules
   unstyled them all silently (caught 2026-08-25 while editing About).
   :not(.hs-facts__grid) keeps this away from the homepage's grid form.
   Retire this block when the interior pages move to the cell markup. */
.hs-facts .wrap:not(.hs-facts__grid){display:flex;flex-wrap:wrap;justify-content:center;
  font-family:var(--font-display);font-weight:600;gap:.4rem 0}
.hs-facts .wrap:not(.hs-facts__grid)>span{white-space:nowrap;padding:0 1.5rem;
  border-left:1px solid var(--dark-bord);font-size:.92rem;color:var(--dark-ink)}
.hs-facts .wrap:not(.hs-facts__grid)>span:first-child{border-left:none}
@media(max-width:820px){
  .hs-facts .wrap:not(.hs-facts__grid)>span{border-left:none;padding:.1rem .9rem}
}

.hs-band{padding:var(--section-pad) 0}
.hs-band h2,.hs-dark h2,.hs-final h2{font-size:clamp(1.7rem,3.1vw,2.3rem);font-weight:700;letter-spacing:-.012em;margin-bottom:.5em}

/* BAND-HEAD GRAMMAR (PA-25). Every band opens the same way: kicker, then
   heading, then lede where prose exists. The kicker is the hero eyebrow's
   device (red dash + small caps) promoted to a site-wide convention, so the
   page reads as one voice rather than a different head per band. Kicker
   text stays a plain label, never a slogan. */
.bh-kick{display:flex;align-items:center;gap:.6rem;white-space:nowrap;font-family:var(--font-display);
  font-weight:600;font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--steel);margin:0 0 .7rem}
.bh-kick::before{content:"";flex:none;width:26px;height:3px;background:var(--action)}
.hs-dark .bh-kick,.hs-final .bh-kick{color:var(--dark-ink-2)}

/* Editorial grid, not boxed cards (PA-14). The bordered white cards were
   the most generic band on the page, and unequal blurb lengths left bottom
   voids the box edges advertised. Photo, rule, title, blurb; the photograph
   is the card. */
.hs-svc-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:2rem 1.4rem;margin-top:1.6rem}
.hs-svc{text-decoration:none;display:block}
.hs-svc img{height:165px;width:100%;object-fit:cover;display:block}
.hs-svc__b{padding:.85rem 0 0;border-top:2px solid var(--ink);margin-top:.75rem}
.hs-svc__b h3{font-family:var(--font-display);font-weight:700;font-size:1.12rem;color:var(--ink)}
.hs-svc__b p{font-size:.93rem;color:var(--ink-2);margin-top:.25rem}
@media(max-width:1180px){.hs-svc-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:900px){.hs-svc-grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.hs-svc-grid{grid-template-columns:1fr}}

.hs-trio{display:grid;grid-template-columns:1fr 1fr 1fr}
.hs-trio>div{padding:2.6rem 2.1rem}
.hs-trio h3{font-family:var(--font-display);font-weight:700;font-size:1.22rem;margin-bottom:.4em}
.hs-trio p{font-size:.97rem}
.hs-t-red{background:var(--action);color:#fff}
.hs-t-dark{background:var(--dark-bg);color:#fff}
.hs-t-red p,.hs-t-dark p{color:rgba(255,255,255,.93)}
.hs-t-red a,.hs-t-dark a{color:#fff;font-weight:700}
.hs-t-light{background:var(--surface);border:1px solid var(--bord);border-left:none}
@media(max-width:820px){.hs-trio{grid-template-columns:1fr}.hs-t-light{border-left:1px solid var(--bord)}}

/* Mid-page phone strip, made quiet (PA-05). The full-bleed red banner with
   centered all-caps read as an ad and spent the accent budget on a
   repetition. Now: hairline-ruled line on paper, ink text, red on the
   number only. Sits on every page type, so the quiet version has to work
   between any two bands. */
.hs-strip{background:var(--paper);color:var(--ink);padding:1.05rem 0;text-align:center;
  border-top:1px solid var(--bord);border-bottom:1px solid var(--bord)}
.hs-strip a{color:var(--ink);text-decoration:none;font-family:var(--font-display);
  font-weight:700;font-size:clamp(.98rem,2vw,1.15rem);letter-spacing:.01em}
.hs-strip b{color:var(--action);font-weight:800;white-space:nowrap}

.hs-rev-head{display:flex;align-items:baseline;gap:1rem;flex-wrap:wrap}
.hs-num{font-family:var(--font-display);font-weight:800;font-size:clamp(2.5rem,4.6vw,3.4rem);line-height:1;font-variant-numeric:tabular-nums}
.hs-rev-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.3rem;margin-top:1.5rem}
.hs-rev{border:1px solid var(--bord);border-radius:var(--radius-card);padding:1.2rem;background:var(--surface)}
.hs-rev p{font-size:.96rem;margin-top:.4rem}
.hs-rev cite{display:block;margin-top:.7rem;font-style:normal;font-weight:700;font-family:var(--font-display);font-size:.9rem}
.hs-rev .stars{font-size:.85rem}
@media(max-width:820px){.hs-rev-grid{grid-template-columns:1fr}}

.hs-gal{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-top:1.4rem}
.hs-gal figure{position:relative;border-radius:var(--radius-card);overflow:hidden;margin:0}
.hs-gal img{height:210px;width:100%;object-fit:cover}
.hs-gal figcaption{position:absolute;left:0;right:0;bottom:0;background:rgba(15,16,18,.84);color:#fff;font-family:var(--font-display);font-weight:600;font-size:.8rem;padding:.5em .9em}
@media(max-width:820px){.hs-gal{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.hs-gal{grid-template-columns:1fr}}

.hs-dark{background:var(--dark-bg);color:var(--dark-ink);padding:var(--section-pad) 0}
.hs-dark h2{color:#fff}
.hs-numbers{display:grid;grid-template-columns:repeat(4,1fr);gap:2rem;margin-top:1.6rem}
.hs-numbers b{display:block;font-family:var(--font-display);font-weight:800;font-size:clamp(2.4rem,4.6vw,3.7rem);line-height:1;color:#fff;font-variant-numeric:tabular-nums}
.hs-numbers b i{font-style:normal;color:#E4515C;font-size:.6em}
.hs-numbers span{display:block;margin-top:.6rem;font-size:.91rem;color:var(--dark-ink-2)}
.hs-numbers a{color:#fff}
@media(max-width:820px){.hs-numbers{grid-template-columns:1fr 1fr}}

.hs-steps{margin-top:1.4rem;border-top:3px solid var(--ink);border-bottom:3px solid var(--ink)}
.hs-step{display:grid;grid-template-columns:280px 1fr;gap:1.2rem;align-items:baseline;padding:1.25rem 0;border-bottom:1px solid var(--bord)}
.hs-step:last-child{border-bottom:none}
.hs-step h3{font-family:var(--font-display);font-weight:700;font-size:1.2rem}
.hs-step p{color:var(--ink-2);font-size:.97rem}
@media(max-width:820px){.hs-step{grid-template-columns:1fr;gap:.3rem}}

.hs-towns{columns:3;column-gap:2.2rem;margin-top:1.3rem}
.hs-towns div{break-inside:avoid;font-family:var(--font-display);font-weight:700;font-size:1rem;padding:.4em 0 .4em 18px;position:relative}
.hs-towns div::before{content:"";position:absolute;left:0;top:.95em;width:6px;height:6px;border-radius:50%;background:var(--ink)}
@media(max-width:700px){.hs-towns{columns:2}}

/* Owner band on asphalt (2026-08-25). It was quote-plus-hairlines on cream,
   the flattest 700px on the page in a stretch Wayne called boring; the
   seven-step cut of the numbers band had also left the middle of the page
   with no dark punch at all. The owner's own words in display type on the
   dark material give it back. About inherits this treatment. */
.hs-owner{background:var(--dark-bg);color:var(--dark-ink);padding:var(--section-pad) 0;position:relative;overflow:hidden}
/* Plain ink, no texture. Asphalt was on every dark ground on the site
   (Wayne, 2026-08-25: "every black background has the same asphalt image
   now"); it now lives in exactly two places, the footer and the final CTA,
   so it reads as material rather than wallpaper. Here the red quote mark
   is the band's only ornament. */
.hs-owner .wrap{position:relative}
.hs-owner .bh-kick{color:var(--dark-ink-2)}
.hs-owner__grid{display:grid;grid-template-columns:1.1fr .9fr;gap:2.6rem;align-items:center}
.hs-owner blockquote{font-family:var(--font-display);font-size:clamp(1.4rem,2.5vw,1.9rem);line-height:1.35;max-width:26ch;font-weight:600;margin:0;color:#fff;letter-spacing:-.01em}
.hs-owner cite{display:block;margin-top:1rem;font-style:normal;font-family:var(--font-display);font-weight:700;color:#fff}
.hs-owner cite small{display:block;font-weight:500;color:var(--dark-ink-2);font-size:.85rem;margin-top:2px}
.hs-owner__story{margin-top:1.4rem;color:var(--dark-ink-2);max-width:52ch;font-size:.98rem;line-height:1.6}
.hs-owner__facts{border-top:2px solid rgba(255,255,255,.92);border-bottom:1px solid var(--dark-bord);padding:1.1rem 0;display:grid;gap:.75rem}
.hs-owner__facts b{font-family:var(--font-display);font-weight:700;font-size:1.02rem;display:block;color:#fff}
.hs-owner__facts span{font-size:.8rem;text-transform:uppercase;letter-spacing:.06em;color:var(--dark-ink-2);font-weight:600}
@media(max-width:820px){.hs-owner__grid{grid-template-columns:1fr}}

/* Final CTA (PA-26). Was a flat field of sign-paint crimson, the largest
   single red object on the site. Keeps the red identity but on the deep
   brand red with the asphalt texture under a heavy scrim, the same ground
   treatment the dark bands and footer use, so it reads as material rather
   than paint. Red stays the ask; the texture supplies the depth. */
.hs-final{background:var(--action-deep);color:#fff;padding:var(--section-pad) 0;
  position:relative;overflow:hidden}
.hs-final::before{content:"";position:absolute;inset:0;
  background:url("/assets/black-widow-sealcoating/asphalt-bg.jpg") center/cover;
  opacity:.32;mix-blend-mode:multiply}
.hs-final>.wrap{position:relative}
.hs-final__grid{display:grid;grid-template-columns:1fr 1fr;gap:2.6rem;align-items:center}
.hs-final p{color:rgba(255,255,255,.94)}
.hs-phone-big{font-family:var(--font-display);font-weight:800;font-size:clamp(1.5rem,3.2vw,2.2rem);color:#fff;text-decoration:none;display:inline-block;margin:.7rem 0;font-variant-numeric:tabular-nums}
.hs-formcard{background:var(--surface);border-radius:var(--radius-card);padding:.4rem}
@media(max-width:820px){.hs-final__grid{grid-template-columns:1fr}}

/* HS SYSTEM, BUILD-UP PASS (2026-08-24). The fullness layer: taller hero
   with entrance choreography, doors, includes band, honest band on real
   asphalt texture, carousel with caption rectangles and progress, season
   band, area map, reveals. Motion is CSS/JS-gated and reduced-motion safe. */

/* scale and presence */
.hs-hero__in{min-height:66vh;display:flex;flex-direction:column;justify-content:center}
.hs-hero h1{font-size:clamp(2.1rem,4.4vw,3.3rem)}
.hs-band h2,.hs-dark h2,.hs-final h2,.hs-honest h2,.hs-inc__copy h2{font-size:clamp(1.9rem,3.5vw,2.6rem)}


/* entrance choreography */
@keyframes hsUp{from{opacity:0;transform:translateY(24px)}to{opacity:1;transform:none}}
.hs-up{animation:hsUp .65s cubic-bezier(.22,.8,.3,1) both}
.hs-d1{animation-delay:.06s}.hs-d2{animation-delay:.18s}.hs-d3{animation-delay:.3s}.hs-d4{animation-delay:.42s}
@keyframes hsDrift{from{transform:scale(1.05)}to{transform:scale(1)}}
.hs-hero__img{animation:hsDrift 13s ease-out both}

/* reveals (JS-added, progressive) */
.hs-rev-el{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}
.hs-rev-el.hs-in{opacity:1;transform:none}

/* BAND CHOREOGRAPHY (2026-08-25). The hero had a staged entrance and the
   rest of the page had a one-note fade, so the site felt alive for one
   viewport and then stopped (Wayne). Each band below the fold now plays
   ONE orchestrated entrance when it arrives: the kicker dash draws in,
   the heading rises, and the band's children stagger up on the same
   curve family as the hero and the drawer. JS puts .hs-anim on bands
   below the fold at load and .hs-in when they intersect; without JS
   neither class exists and everything renders visible. */
.hs-anim .bh-kick{opacity:0;transition:opacity .4s ease .08s}
.hs-anim .bh-kick::before{transform:scaleX(0);transform-origin:left;
  transition:transform .55s cubic-bezier(.22,1,.36,1) .08s}
.hs-anim h2,.hs-anim .hs-wall-head,.hs-anim blockquote,.hs-anim cite,
.hs-anim .hs-owner__story{
  opacity:0;transform:translateY(16px);
  transition:opacity .5s ease .14s,transform .6s cubic-bezier(.22,1,.36,1) .14s}
.hs-anim .hs-svc,.hs-anim .hs-wr,.hs-anim .hs-facts__grid>div,
.hs-anim .hs-towns>div,.hs-anim .hs-inc__list li,.hs-anim .hs-owner__facts>div,
.hs-anim .hs-door,.hs-anim .faq__item,.hs-anim .hs-two>div,
.hs-anim .hs-final__grid>div,.hs-anim .hs-gmap{
  opacity:0;transform:translateY(20px);
  transition:opacity .5s ease,transform .6s cubic-bezier(.22,1,.36,1)}
.hs-anim :is(.hs-svc,.hs-wr,.hs-towns>div,.hs-inc__list li,.hs-owner__facts>div,.hs-door,.faq__item,.hs-two>div,.hs-final__grid>div):nth-child(1){transition-delay:.18s}
.hs-anim :is(.hs-svc,.hs-wr,.hs-towns>div,.hs-inc__list li,.hs-owner__facts>div,.hs-door,.faq__item,.hs-two>div,.hs-final__grid>div):nth-child(2){transition-delay:.26s}
.hs-anim :is(.hs-svc,.hs-wr,.hs-towns>div,.hs-inc__list li,.hs-owner__facts>div,.faq__item,.hs-two>div):nth-child(3){transition-delay:.34s}
.hs-anim :is(.hs-svc,.hs-wr,.hs-towns>div,.hs-inc__list li,.faq__item):nth-child(4){transition-delay:.42s}
.hs-anim :is(.hs-svc,.hs-towns>div,.hs-inc__list li):nth-child(5){transition-delay:.5s}
.hs-anim :is(.hs-svc,.hs-towns>div):nth-child(6){transition-delay:.58s}
.hs-anim :is(.hs-towns>div):nth-child(n+7){transition-delay:.64s}
/* the review aggregate pops the way the hero stars do */
.hs-anim .hs-num{opacity:0;transform:scale(.72);
  transition:opacity .35s ease .15s,transform .55s cubic-bezier(.34,1.56,.64,1) .15s}
/* photographs settle from a slight zoom, matching the carousel */
.hs-anim .hs-car2__stage,.hs-anim .hs-gmap img{opacity:0;
  transition:opacity .6s ease .1s}
.hs-anim.hs-in .bh-kick{opacity:1}
.hs-anim.hs-in .bh-kick::before{transform:none}
.hs-anim.hs-in :is(h2,.hs-wall-head,blockquote,cite,.hs-owner__story,
  .hs-svc,.hs-wr,.hs-facts__grid>div,.hs-towns>div,.hs-inc__list li,
  .hs-owner__facts>div,.hs-door,.faq__item,.hs-two>div,.hs-final__grid>div,
  .hs-gmap,.hs-num,.hs-car2__stage,.hs-gmap img){opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){
  .hs-anim :is(*,*::before){transition:none!important;transform:none!important;opacity:1!important}
}

/* doors */
.hs-doors{background:var(--dark-bg)}
.hs-doors__grid{display:grid;grid-template-columns:1.9fr 1fr;gap:2px}
/* The owner's argument under his pull quote. Reads as him continuing to
   talk, so it is body weight rather than quote weight. */
.hs-owner__body{margin-top:1.15rem;color:var(--dark-ink-2);max-width:54ch;line-height:1.65}
.hs-door{position:relative;min-height:430px;display:flex;align-items:flex-end;color:#fff;text-decoration:none;overflow:hidden}
.hs-door img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .7s ease,filter .5s ease;filter:saturate(.94) brightness(.94)}
.hs-door:hover img{transform:scale(1.03);filter:saturate(1) brightness(1)}
.hs-door::after{content:"";position:absolute;inset:0;background:linear-gradient(8deg,rgba(10,11,13,.9) 12%,rgba(10,11,13,.38) 50%,rgba(10,11,13,.05) 78%)}
.hs-door__b{position:relative;z-index:2;padding:2rem 2.2rem}
.hs-door__b h2{color:#fff;font-family:var(--font-display);font-weight:800;font-size:1.8rem;margin-bottom:.3em}
.hs-door__b p{color:rgba(255,255,255,.9);font-size:.98rem;max-width:46ch}
.hs-door__go{display:inline-block;margin-top:.8rem;font-family:var(--font-display);font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:.92rem;border-bottom:2px solid var(--action);padding-bottom:3px;transition:color .2s}
.hs-door:hover .hs-door__go{color:#E4515C}
/* Equal paragraph boxes so the two door headings sit on the same line
   (PA-13): the blocks are bottom-anchored and the commercial copy runs a
   line longer than the residential. */
@media(min-width:861px){.hs-door__b p{min-height:6.3em}}
@media(max-width:860px){.hs-doors__grid{grid-template-columns:1fr}.hs-door{min-height:330px}}

/* includes band */
.hs-inc__grid{display:grid;grid-template-columns:1fr 1fr;align-items:stretch}
.hs-inc figure{margin:0;position:relative}
.hs-inc img{width:100%;height:100%;object-fit:cover;min-height:400px}
.hs-cap{position:absolute;left:0;bottom:0;background:rgba(15,16,18,.85);color:#fff;font-family:var(--font-display);font-weight:600;font-size:.8rem;padding:.5em .9em}
.hs-inc__copy{background:var(--dark-bg);color:var(--dark-ink);padding:clamp(1.8rem,4vw,3rem)}
.hs-inc__copy h2{color:#fff;margin-bottom:.5em}
.hs-inc__list{list-style:none;padding:0;margin:0}
.hs-inc__list li{padding:.7rem 0 .7rem 2rem;position:relative;border-bottom:1px solid var(--dark-bord);font-size:1rem;color:rgba(244,242,239,.9)}
.hs-inc__list li:last-child{border-bottom:none}
.hs-inc__list li::before{content:"";position:absolute;left:2px;top:1.05rem;width:13px;height:7px;border-left:3px solid var(--action);border-bottom:3px solid var(--action);transform:rotate(-45deg)}
@media(max-width:860px){.hs-inc__grid{grid-template-columns:1fr}}

/* honest band with asphalt texture */
.hs-honest{position:relative;background:var(--dark-bg);color:var(--dark-ink);padding:var(--section-pad-lg) 0;overflow:hidden}
/* (texture removed; see the two-placement rule at .hs-owner) */
.hs-honest .wrap{position:relative}
.hs-honest__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.8rem,4.5vw,3.6rem)}
.hs-honest h2{color:#fff;max-width:17ch}
.hs-honest blockquote{font-size:1.1rem;font-style:italic;color:rgba(244,242,239,.9);border-left:3px solid var(--action);padding-left:1.2rem;margin:0 0 1.2rem}
.hs-honest cite{display:block;margin-top:.7rem;font-style:normal;font-family:var(--font-display);font-weight:600;text-transform:uppercase;letter-spacing:.08em;font-size:.76rem;color:var(--dark-ink-2)}
.hs-honest p{color:rgba(244,242,239,.84)}
@media(max-width:860px){.hs-honest__grid{grid-template-columns:1fr}}

/* carousel */
.hs-car{position:relative;overflow:hidden;border-radius:var(--radius-card);margin-top:1.4rem}
.hs-car__track{display:flex;transition:transform .6s cubic-bezier(.22,.8,.3,1)}
.hs-car__slide{flex:0 0 100%;position:relative}
.hs-car__slide img{width:100%;height:min(58vh,520px);object-fit:cover}
.hs-car__cap{position:absolute;left:0;bottom:0;background:rgba(15,16,18,.88);color:#fff;padding:.9rem 1.4rem;max-width:min(480px,88%);opacity:0;transform:translateY(10px);transition:opacity .45s ease .15s,transform .45s ease .15s}
.hs-car__slide.is-on .hs-car__cap{opacity:1;transform:none}
.hs-car__cap b{display:block;font-family:var(--font-display);font-weight:700;font-size:1.08rem}
.hs-car__cap span{display:block;font-size:.86rem;color:rgba(244,242,239,.75);margin-top:2px}
.hs-car__bar{position:absolute;left:0;bottom:0;height:3px;width:100%;background:rgba(15,16,18,.3);z-index:2}
.hs-car__bar i{display:block;height:100%;width:0;background:var(--action)}
.hs-car__bar.run i{animation:hsCarRun 5s linear both}
@keyframes hsCarRun{from{width:0}to{width:100%}}
.hs-car__count{position:absolute;top:0;right:0;background:rgba(15,16,18,.88);color:#fff;font-family:var(--font-display);font-weight:600;letter-spacing:.08em;padding:.45em 1em;font-size:.8rem}
.hs-car__nav{position:absolute;right:0;bottom:0;display:flex;z-index:3}
.hs-car__nav button{width:52px;height:52px;border:none;cursor:pointer;background:var(--paper);color:var(--ink);transition:background .2s,color .2s}
.hs-car__nav button:hover{background:var(--action);color:#fff}
.hs-car__nav button+button{border-left:1px solid var(--bord)}
.hs-car__nav svg{width:18px;height:18px;display:block;margin:auto}

/* season band */
/* The alt band carries a faint broom-finished concrete grain (cut from
   Grant's own fresh-walk photo, BW-165) instead of flat cream - the
   light counterpart of the asphalt texture on the dark bands. The
   texture's mean is tuned to sit at --surface-2's tone, so the band
   color reads the same and only the grain is new. */
/* The texture file is a 2x2 mirror tile with its lighting gradient
   flattened, so it repeats seamlessly - at 1500px one tile covers most
   sections and no seam or restart is visible at any width. */
.hs-band--alt{background:
  linear-gradient(rgba(234,231,226,.9),rgba(234,231,226,.9)),
  url("/assets/black-widow-sealcoating/concrete-bg.jpg") var(--surface-2);
  background-size:auto,1500px}
.hs-season{display:grid;grid-template-columns:repeat(3,1fr);gap:2rem;margin-top:1.4rem}
.hs-season h3{font-family:var(--font-display);font-weight:700;font-size:1.15rem;margin-bottom:.35em}
.hs-season p{font-size:.96rem;color:var(--ink-2)}
@media(max-width:820px){.hs-season{grid-template-columns:1fr}}

/* area with map */
.hs-area{display:grid;grid-template-columns:.72fr 1.28fr;gap:clamp(1.8rem,4vw,3.4rem);margin-top:1.2rem;align-items:start}
@media(max-width:880px){.hs-area{grid-template-columns:1fr}}

@media(prefers-reduced-motion:reduce){
  .hs-up,.hs-hero__img{animation:none}
  .hs-rev-el{opacity:1;transform:none;transition:none}
  .hs-car__bar{display:none}
  .hs-car__cap{opacity:1;transform:none;transition:none}
}

/* ---------------------------------------------------------------------------
   PREMIUM CAROUSEL v2 (2026-08-24). Image stage + dark caption panel +
   thumbnail rail. Crossfade slides, caption text swaps with a rise, thumbs
   ring red when active. Replaces the bare image swapper.
   ------------------------------------------------------------------------ */
.hs-car2{display:grid;grid-template-columns:1fr 320px;grid-template-rows:auto auto;gap:0;margin-top:1.4rem;border-radius:var(--radius-card);overflow:hidden;outline:none}
.hs-car2:focus-visible{outline:2px solid var(--action);outline-offset:3px}
.hs-car2__stage{position:relative;grid-row:1;grid-column:1;aspect-ratio:16/9.5;background:var(--dark-bg)}
.hs-car2__slide{position:absolute;inset:0;opacity:0;transition:opacity .55s ease}
.hs-car2__slide.is-on{opacity:1}
/* The incoming frame settles from a slight zoom while it fades, so a slide
   change reads as a move, not a swap. */
.hs-car2__slide img{width:100%;height:100%;object-fit:cover;transform:scale(1.035);transition:transform 1.2s ease}
.hs-car2__slide.is-on img{transform:scale(1)}
/* Caption column centers as one block (PA-07): caption pinned top with
   arrows pinned bottom left a 300px void between them at desktop heights. */
.hs-car2__panel{grid-row:1;grid-column:2;background:var(--dark-bg);color:var(--dark-ink);padding:2rem 1.9rem;display:flex;flex-direction:column;justify-content:center;gap:1.6rem;position:relative;overflow:hidden}
/* (texture removed: the panel sits inside a dark band and the photographs
   are the texture; see the two-placement rule at .hs-owner) */
.hs-car2__panel>div{position:relative}
.hs-car2__index{font-family:var(--font-display);font-weight:600;font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;color:var(--dark-ink-2);border-bottom:1px solid var(--dark-bord);padding-bottom:.8rem;margin-bottom:1rem}
.hs-car2__title{font-family:var(--font-display);font-weight:700;font-size:1.45rem;color:#fff;line-height:1.15}
.hs-car2__line{margin-top:.5rem;font-size:.95rem;color:var(--dark-ink-2)}
@keyframes hsSwap{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.hs-car2__title.swap,.hs-car2__line.swap{animation:hsSwap .45s ease both}
.hs-car2__line.swap{animation-delay:.06s}
.hs-car2__nav{display:flex;gap:.6rem;position:relative}
.hs-car2__nav button{width:46px;height:46px;border:1px solid var(--dark-bord);background:transparent;color:var(--dark-ink);cursor:pointer;border-radius:var(--radius-ctl);transition:background .18s,border-color .18s,color .18s}
.hs-car2__nav button:hover{background:var(--action);border-color:var(--action);color:#fff}
.hs-car2__nav button:focus-visible{outline:2px solid var(--action);outline-offset:2px}
.hs-car2__nav svg{width:17px;height:17px;display:block;margin:auto}
.hs-car2__thumbs{grid-row:2;grid-column:1/-1;display:flex;gap:8px;background:var(--dark-bg);padding:10px;border-top:1px solid var(--dark-bord)}
.hs-car2__thumb{flex:1;height:86px;padding:0;border:2px solid transparent;border-radius:var(--radius-ctl);overflow:hidden;cursor:pointer;background:none;opacity:.5;transition:opacity .2s,border-color .2s}
.hs-car2__thumb img{width:100%;height:100%;object-fit:cover;display:block}
.hs-car2__thumb:hover{opacity:.85}
.hs-car2__thumb.is-on{opacity:1;border-color:var(--action)}
.hs-car2__thumb:focus-visible{outline:2px solid var(--action);outline-offset:1px}
@media(max-width:900px){
  .hs-car2{grid-template-columns:1fr}
  .hs-car2__stage{grid-column:1;aspect-ratio:16/10}
  .hs-car2__panel{grid-row:2;grid-column:1;padding:1.4rem;flex-direction:row;align-items:center;gap:1rem}
  .hs-car2__panel>div{flex:1}
  .hs-car2__index{border-bottom:none;padding-bottom:0;margin-bottom:.3rem}
  .hs-car2__title{font-size:1.15rem}
  .hs-car2__thumbs{grid-row:3;overflow-x:auto}
  .hs-car2__thumb{flex:0 0 84px}
}

/* ---------------------------------------------------------------------------
   MAP, LIGHT PANEL (2026-08-24). The dark map read as a black box at page
   scale. Light card, red circle with a visible wash, ink labels.
   ------------------------------------------------------------------------ */
.hs-map{margin:0;background:var(--surface);border:1px solid var(--bord);border-radius:var(--radius-card);padding:1.1rem 1.1rem .4rem}
.hs-map svg{width:100%;height:auto;display:block}
.hs-map .map-bound{fill:rgba(185,18,27,.05);stroke:var(--action);stroke-width:3}
.hs-map .map-town{fill:var(--ink)}
.hs-map .map-home{fill:var(--action)}
.hs-map .map-home-ring{fill:none;stroke:var(--action);stroke-width:1.5;opacity:.45;transform-origin:center;transform-box:fill-box;animation:lv2-pulse 2.6s ease-out infinite}
.hs-map .map-lbl{font-family:var(--font-display);font-size:13px;letter-spacing:.06em;fill:var(--ink);font-weight:700}
.hs-map .map-lbl--home{font-size:14.5px;fill:var(--action);font-weight:800}
.hs-map figcaption{font-size:.86rem;color:var(--steel);padding:.7rem .2rem .6rem;text-align:center}
@media(prefers-reduced-motion:reduce){.hs-map .map-home-ring{animation:none;opacity:.35}.hs-car2__slide{transition:none}.hs-car2__title.swap,.hs-car2__line.swap{animation:none}}

/* ---------------------------------------------------------------------------
   GLOBAL INTERACTION POLISH (2026-08-24). The small things, sitewide, not
   scoped to one page's system: button states, focus rings, selection,
   anchor margins, link affordances.
   ------------------------------------------------------------------------ */
::selection{background:var(--action);color:#fff}
[id]{scroll-margin-top:96px}
a,button{-webkit-tap-highlight-color:transparent}
.btn{transition:background .18s,color .18s,transform .16s,box-shadow .16s}
.btn:hover{transform:translateY(-1px);box-shadow:var(--shadow-chip)}
.btn:active{transform:translateY(0);box-shadow:none}
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid var(--action);outline-offset:2px}
.more{transition:color .15s}
.more:hover{color:var(--action)}
.hs-strip a{display:block;transition:opacity .15s}
.hs-strip a:hover{opacity:.92}
.hs-towns div{transition:color .15s}
.faq__item summary{transition:color .15s;min-height:40px}
.faq__item summary:hover{color:var(--action)}
@media(prefers-reduced-motion:reduce){.btn:hover{transform:none}}

/* ---------------------------------------------------------------------------
   AUDIT FIXES, PASS 2 (2026-08-24). Found by looking at the rendered page.
   ------------------------------------------------------------------------ */

/* The dark-header link color cascaded into the white dropdown panel, so
   the service names rendered ghost-white on white. Panel text goes back to
   ink explicitly. */
.site-header .navdrop__panel a{color:var(--ink)}
.site-header .navdrop__panel a b{color:var(--ink)}
.site-header .navdrop__panel a span{color:var(--ink-2)}
.site-header .navdrop__panel a:hover b{color:var(--action)}
.site-header .navdrop__all{color:#fff}

/* The final band's white text inherited into the white form card: labels
   and the TCPA consent were invisible. The card asserts its own colors. */
.hs-formcard{color:var(--ink);padding:1.1rem 1.3rem}
.hs-formcard .leadform__field label{color:var(--ink-2)}
.hs-formcard .sms-consent__text{color:var(--steel)}
.hs-formcard .sms-consent__link{color:var(--ink)}
.hs-formcard a{color:var(--ink)}

/* Footer hours: the day names sat at low contrast on the dark ground. */
.site-footer__hours th,.site-footer__hours td,.site-footer__hours dt,.site-footer__hours dd{color:rgba(244,242,239,.85)}
/* Specificity casualty: the panel-link ink rule beat the all-services bar. */
.site-header .navdrop__panel a.navdrop__all{color:#fff}
.site-header .navdrop__panel a.navdrop__all:hover{color:#fff;text-decoration:underline}
/* Consent checkbox pinned beside its text in the final-band card. */
.hs-formcard .sms-consent__row{display:grid;grid-template-columns:16px minmax(0,1fr);gap:.55rem;align-items:start}
.hs-formcard .sms-consent__checkbox{margin:3px 0 0;justify-self:start}

/* ---------------------------------------------------------------------------
   POP PASS 3 (2026-08-24). Reviews as aggregate block + quote cards,
   service-card hover depth, textured numbers band, owner quote mark,
   door arrows, season rules.
   ------------------------------------------------------------------------ */
.hs-rev-wrap{display:grid;grid-template-columns:250px 1fr;gap:clamp(1.6rem,3.5vw,3rem);align-items:start;margin-top:.4rem}
.hs-rev-agg{position:sticky;top:110px;border-top:3px solid var(--ink);padding-top:1.1rem}
.hs-rev-agg .hs-num{font-size:clamp(3.4rem,6vw,4.6rem);display:block;line-height:1}
.hs-rev-agg__stars{font-size:1.15rem;display:block;margin:.4rem 0 .2rem}
.hs-rev-agg p{color:var(--ink-2);margin-bottom:.9rem}
.hs-rev-grid{grid-template-columns:1fr;gap:1rem;margin-top:0}
.hs-rev{transition:border-color .2s,box-shadow .2s,transform .2s}
.hs-rev:hover{border-color:var(--steel);box-shadow:var(--shadow-2);transform:translateY(-2px)}
.hs-rev:nth-child(2){margin-left:2.2rem}
.hs-rev:nth-child(3){margin-left:4.4rem}
@media(max-width:900px){.hs-rev-wrap{grid-template-columns:1fr}.hs-rev-agg{position:static}.hs-rev:nth-child(2),.hs-rev:nth-child(3){margin-left:0}}

/* Hover for the editorial grid: photo wakes up, rule turns red. The old
   boxed-card lift went with the boxes. */
.hs-svc img{transition:filter .3s ease}
.hs-svc:hover img{filter:brightness(1.06) saturate(1.05)}
.hs-svc__b{transition:border-color .2s}
.hs-svc:hover .hs-svc__b{border-color:var(--action)}
.hs-svc__b h3{transition:color .15s}
.hs-svc:hover .hs-svc__b h3{color:var(--action)}

.hs-dark{position:relative;overflow:hidden}
/* (texture removed; see the two-placement rule at .hs-owner) */
.hs-dark .wrap{position:relative}
.hs-numbers>div{border-left:1px solid var(--dark-bord);padding-left:1.6rem}
.hs-numbers>div:first-child{border-left:none;padding-left:0}
@media(max-width:820px){.hs-numbers>div{border-left:none;padding-left:0}}

.hs-owner blockquote{position:relative;padding-left:2.6rem}
.hs-owner blockquote::before{content:"\201C";position:absolute;left:0;top:-.35em;font-family:var(--font-display);font-weight:800;font-size:4rem;line-height:1;color:var(--action)}

.hs-door__go::after{content:"\2192";display:inline-block;margin-left:.45em;transition:transform .2s}
.hs-door:hover .hs-door__go::after{transform:translateX(4px)}

.hs-season>div{border-top:3px solid var(--ink);padding-top:1rem}

/* ---------------------------------------------------------------------------
   REVIEW WALL (2026-08-24). The whole quotable base, masonry columns, one
   dark featured card, aggregate header with the big number.
   ------------------------------------------------------------------------ */
.hs-wall-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1.4rem;flex-wrap:wrap;margin-bottom:1.6rem}
.hs-wall-agg{display:flex;align-items:center;gap:1.1rem}
.hs-wall-agg .hs-num{font-size:clamp(3.2rem,5.5vw,4.4rem);line-height:1}
.hs-wall-stars{font-size:1.2rem;display:block}
.hs-wall-agg p{color:var(--ink-2);margin-top:.15rem;max-width:26ch}
.hs-btn-ghost-ink{box-shadow:inset 0 0 0 2px var(--ink);color:var(--ink);background:transparent}
.hs-btn-ghost-ink:hover{background:var(--ink);color:#fff}
.hs-wall{columns:3;column-gap:1.6rem}
/* Editorial review cards, same ink-rule language as the services grid: the
   white boxes on cream read flat and beige (Wayne, 2026-08-25). The quote
   IS the card. The --dark boxed variant below keeps its own padding and
   ground for the commercial and segment pages. */
.hs-wr{break-inside:avoid;background:none;border:0;border-top:2px solid var(--ink);border-radius:0;padding:1.05rem 0 0;margin:0 0 1.7rem;transition:border-color .2s}
.hs-wr:hover{border-top-color:var(--action)}
.hs-wr .stars{font-size:.9rem;color:var(--gold)}
.hs-wr blockquote{margin:.6rem 0 .9rem;font-size:1.02rem;line-height:1.55}
.hs-wr figcaption b{display:block;font-family:var(--font-display);font-weight:700;font-size:.95rem}
.hs-wr figcaption span{font-size:.8rem;color:var(--steel)}
.hs-wr--dark{background:var(--dark-bg);border:1px solid var(--dark-bg);border-top:1px solid var(--dark-bg);padding:1.4rem 1.4rem 1.2rem;color:var(--dark-ink);position:relative;overflow:hidden}
/* (texture removed; see the two-placement rule at .hs-owner) */
.hs-wr--dark>*{position:relative}
.hs-wr--dark blockquote{color:#fff;font-size:1.06rem}
.hs-wr--dark figcaption b{color:#fff}
.hs-wr--dark figcaption span{color:var(--dark-ink-2)}
@media(max-width:1000px){.hs-wall{columns:2}}
@media(max-width:640px){.hs-wall{columns:1}}
/* Homepage wall: the property manager's line is the site's best third-party
   sentence, so it runs featured-width and display-size; the other three sit
   under it in columns. */
.hs-wall--feat{columns:auto;display:grid;grid-template-columns:repeat(3,1fr);gap:0 1.6rem;margin-top:1.8rem}
.hs-wall--feat .hs-wr--lead{grid-column:1/-1;margin-bottom:2.1rem}
.hs-wall--feat .hs-wr--lead blockquote{font-family:var(--font-display);font-weight:600;font-size:clamp(1.35rem,2.6vw,1.95rem);line-height:1.32;max-width:42ch;letter-spacing:-.01em}
@media(max-width:900px){.hs-wall--feat{grid-template-columns:1fr}}

/* (The old fact-strip ledger rules lived here; superseded by the PA-12
   anchor-led trust bar above.) */

/* FAQ: sticky header column beside the accordion. */
.hs-faqgrid{display:grid;grid-template-columns:300px 1fr;gap:clamp(1.8rem,4vw,3.6rem);align-items:start}
.hs-faqhead{position:sticky;top:110px;border-top:3px solid var(--ink);padding-top:1rem}
.hs-faqhead p{color:var(--ink-2);margin:.4rem 0 1rem;max-width:24ch}
@media(max-width:880px){.hs-faqgrid{grid-template-columns:1fr}.hs-faqhead{position:static}}

/* Photo band: a full-bleed breather between text bands. */
.hs-photoband{position:relative;overflow:hidden;line-height:0}
.hs-photoband img{width:100%;height:min(52vh,440px);object-fit:cover;filter:saturate(.96)}
.hs-photoband .hs-cap{line-height:1.4}

/* ============ HERO v2: video, split copy/form ============ */
.hs-hero2{position:relative;overflow:hidden;background:var(--dark-bg);color:#fff;display:flex;align-items:center}
.hs-hero2__video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(.92) brightness(.85)}
.hs-hero2__scrim{position:absolute;inset:0;background:
  linear-gradient(100deg,rgba(10,11,13,.88) 0%,rgba(10,11,13,.72) 42%,rgba(10,11,13,.42) 70%,rgba(10,11,13,.55) 100%)}
/* The hero owns the first viewport (Wayne, 2026-08-25): with the doors
   band peeking in at the fold the eye had three competing surfaces. Header
   (~82px) plus topbar (~36px) plus the trust bar (~92px) come off 100vh so
   the fold lands on the trust bar's bottom edge; the section's flex
   centering absorbs the extra height on tall screens. Desktop only: on
   phones the form card already fills the first screens. */
@media(min-width:961px){
  /* 150, not the exact chrome sum: landing the fold precisely on the trust
     bar's bottom edge needs the header and topbar heights to be exact on
     every screen, and they are not; Wayne could still see the doors. With
     the overshoot the trust bar straddles the fold as the scroll cue and
     the doors sit safely below on any desktop viewport. */
  .hs-hero2{min-height:calc(100vh - 206px)}
}
/* Top-aligned (PA-42): center alignment left the card top a near-miss off
   the H1, which read as accident. Both columns now hang from one line. */
.hs-hero2__grid{position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,1.25fr) minmax(340px,420px);
  gap:clamp(2rem,4.5vw,4.5rem);align-items:start;padding-top:clamp(3.4rem,6vw,5.2rem);padding-bottom:clamp(3.4rem,6vw,5.2rem)}
.hs-hero2__eyebrow{font-family:var(--font-display);font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  font-size:.8rem;color:rgba(255,255,255,.85);margin-bottom:1rem}
.hs-hero2__eyebrow::before{content:"";display:inline-block;width:26px;height:3px;background:var(--action);
  vertical-align:middle;margin-right:.7em}
.hs-hero2 h1{color:#fff;font-family:var(--font-display);font-weight:800;line-height:1.06;
  font-size:clamp(2.4rem,4vw,3.55rem);max-width:17ch;text-wrap:balance}
.hs-hero2__sub{margin-top:1.1rem;font-size:1.08rem;line-height:1.6;color:rgba(255,255,255,.92);max-width:52ch}
/* Phone is the primary ask (PA-38): the call button carries more weight
   than the form submit, and the rating now sits above it in the eye path
   (PA-37), so the meta margin tightens into a proof-then-ask pair. */
.hs-hero2 .hs-hero__ctas{margin-top:.9rem;display:flex;gap:.8rem;flex-wrap:wrap}
.hs-hero2 .hs-hero__ctas .btn--primary{padding:1em 1.7em;font-size:1.05rem;font-weight:800}
.hs-hero2__meta{margin-top:1.5rem}
.hs-formcard--hero .leadform [type=submit]{background:var(--action-deep)}
.hs-formcard--hero .leadform [type=submit]:hover{background:var(--action)}
.hs-hero2 .btn svg{vertical-align:-2px;margin-right:.45em}

/* star row that pops */
.hs-hero2__meta{margin-top:1.5rem;display:flex;align-items:center;gap:.6rem;font-size:.98rem;color:rgba(255,255,255,.92)}
.hs-hero2__meta b{font-family:var(--font-display);font-weight:800;font-size:1.05rem;color:#fff}
.starrow{display:inline-flex;gap:2px;color:var(--gold);filter:drop-shadow(0 1px 6px rgba(217,148,20,.45))}
.starrow .st{width:19px;height:19px}
@keyframes starPop{0%{transform:scale(.3);opacity:0}70%{transform:scale(1.22)}100%{transform:scale(1);opacity:1}}
.hs-up .starrow .st,.hs-in .starrow .st{animation:starPop .5s cubic-bezier(.34,1.56,.64,1) both}
.starrow .st:nth-child(1){animation-delay:.55s}.starrow .st:nth-child(2){animation-delay:.65s}
.starrow .st:nth-child(3){animation-delay:.75s}.starrow .st:nth-child(4){animation-delay:.85s}
.starrow .st:nth-child(5){animation-delay:.95s}

/* assure list */
.hs-assure{list-style:none;padding:0;margin:1.2rem 0 0;display:flex;gap:1.4rem;flex-wrap:wrap}
.hs-assure li{display:flex;align-items:center;gap:.45em;font-size:.92rem;color:rgba(255,255,255,.88)}
.hs-assure svg{color:var(--action);flex:none;background:rgba(255,255,255,.95);border-radius:50%;padding:2px}

/* the hero form card, compact */
.hs-formcard--hero{background:#fff;border-radius:var(--radius-card);padding:1.5rem 1.6rem 1.6rem;box-shadow:var(--shadow-3);
  position:relative}
.hs-formtag{position:absolute;top:0;right:1.4rem;transform:translateY(-50%);background:var(--action);color:#fff;
  font-family:var(--font-display);font-weight:700;text-transform:uppercase;letter-spacing:.1em;font-size:.72rem;
  padding:.45em 1em;border-radius:var(--radius-ctl)}
.hs-formhead{font-family:var(--font-display);font-weight:800;font-size:1.35rem;color:var(--ink)}
.hs-formsub{font-size:.9rem;color:var(--ink-2);margin:.25rem 0 .9rem}
.hs-formcard--hero .leadform label{font-size:.8rem}
.hs-formcard--hero .leadform input,.hs-formcard--hero .leadform textarea{padding:.55em .7em;font-size:.95rem}
.hs-formcard--hero .leadform textarea{min-height:2.6em}
.hs-formcard--hero .leadform .field,.hs-formcard--hero .leadform .field__row{margin-bottom:.55rem}
.hs-formcard--hero .leadform input:focus,.hs-formcard--hero .leadform textarea:focus{
  border-color:var(--action);box-shadow:var(--focus-ring);outline:none}

@media(max-width:960px){
  .hs-hero2__grid{grid-template-columns:1fr;align-items:start}
  .hs-hero2 h1{font-size:clamp(2rem,7vw,2.7rem)}
  .hs-formcard--hero{max-width:520px}
}
@media(prefers-reduced-motion:reduce){
  .hs-hero2__video{display:none}
  .hs-hero2{background:url("/assets/black-widow-sealcoating/lot-sealed-institutional.jpg") center/cover}
  .starrow .st{animation:none}
}

/* Hero v2 tightening: shorter section, calmer video, denser card. */
.hs-hero2__grid{padding-top:2.6rem;padding-bottom:2.6rem}
.hs-hero2__video{filter:saturate(.85) brightness(.72)}
/* Heavier and more even (PA-35): the old stops left the photo's busiest
   region, the road and white car rows center-right, as its brightest,
   exactly between the H1 and the card. */
.hs-hero2__scrim{background:
  linear-gradient(100deg,rgba(10,11,13,.93) 0%,rgba(10,11,13,.84) 45%,rgba(10,11,13,.7) 75%,rgba(10,11,13,.78) 100%)}
.hs-formcard--hero .leadform .field,.hs-formcard--hero .leadform .field__row{margin-bottom:.45rem}
.hs-formcard--hero .sms-consent__text{font-size:.74rem;line-height:1.45}
.hs-formcard--hero .leadform__legal{font-size:.74rem;line-height:1.45;margin-top:.6rem}
.hs-formcard--hero .leadform__field{margin-bottom:.45rem}
.hs-formcard--hero .leadform textarea{min-height:2.2em}

/* Hero H1: four confident lines, not six. */
.hs-hero2 h1{font-size:clamp(2.2rem,3.2vw,3rem);max-width:20ch}

/* ============ ICON SYSTEM (Lucide-style, currentColor) ============ */
.hs-ic{display:block}
.hs-trio .hs-ic{width:30px;height:30px;margin-bottom:.9rem;opacity:.95}
.hs-t-red .hs-ic,.hs-t-dark .hs-ic{color:#fff}
.hs-t-light .hs-ic{color:var(--action)}
.hs-trio>div{transition:transform .35s ease}
.hs-trio>div:hover .hs-ic{transform:translateY(-3px)}
.hs-trio .hs-ic{transition:transform .3s cubic-bezier(.34,1.56,.64,1)}

/* steps: icon chip beside the row title */
.hs-step{display:grid;grid-template-columns:52px 1fr;gap:0 1.1rem;align-items:start}
.hs-step__ic{width:44px;height:44px;border:1.5px solid var(--bord);border-radius:var(--radius-ctl);display:flex;
  align-items:center;justify-content:center;color:var(--action);background:var(--paper);
  transition:background .25s,border-color .25s,transform .25s}
.hs-step__ic .hs-ic{width:22px;height:22px}
.hs-step:hover .hs-step__ic{background:var(--action);border-color:var(--action);color:#fff;transform:translateY(-2px)}
.hs-step h3{grid-column:2}
.hs-step p{grid-column:2}
@media(max-width:640px){.hs-step{grid-template-columns:44px 1fr}}

/* season: small red icon above each column */
.hs-season__ic{display:inline-flex;width:40px;height:40px;border-radius:50%;background:rgba(185,18,27,.08);
  color:var(--action);align-items:center;justify-content:center;margin-bottom:.7rem}
.hs-season__ic .hs-ic{width:21px;height:21px}

/* review wall aggregate stars */
.starrow--lg{color:var(--gold);filter:drop-shadow(0 2px 8px rgba(217,148,20,.4))}
.starrow--lg .st{width:24px;height:24px}
.hs-wall-agg .starrow{display:inline-flex;gap:3px}

/* global input focus glow, matches the hero card */
.leadform input:focus,.leadform textarea:focus{border-color:var(--action);
  box-shadow:var(--focus-ring);outline:none}

/* ============ FOOTER v2: near-black, red kickers, slide underlines ============ */
.hs-foot{background:#0A0B0D;border-top:1px solid rgba(255,255,255,.08);padding-block:3.6rem 0;overflow:hidden}
.hs-foot::after{content:"";position:absolute;top:-160px;left:-120px;width:560px;height:440px;
  background:radial-gradient(closest-side,rgba(185,18,27,.18),transparent 70%);pointer-events:none}
.hs-foot__grid{display:grid;grid-template-columns:1.55fr .95fr .95fr 1.3fr;gap:clamp(2rem,4vw,3.4rem);
  position:relative;z-index:1}
.hs-foot .site-footer__logo{height:92px;margin-bottom:1.1rem}
.hs-foot__line{color:rgba(244,242,239,.72);font-size:.95rem;line-height:1.6;max-width:34ch}
.hs-foot__stars{display:flex;align-items:center;gap:.5rem;margin-top:1rem;color:rgba(244,242,239,.85)}
.hs-foot__stars b{color:#fff;font-family:var(--font-display);font-weight:800;font-size:1rem}
.hs-foot__stars .starrow{display:inline-flex;gap:2px;color:var(--gold);
  filter:drop-shadow(0 1px 5px rgba(217,148,20,.4))}
.hs-foot__stars .st{width:16px;height:16px}
.hs-foot__cta{margin-top:1.25rem}
.hs-foot__col{display:flex;flex-direction:column;gap:.55rem;align-items:flex-start}
.hs-foot__col h3{font-family:var(--font-display);font-weight:700;text-transform:uppercase;
  letter-spacing:.13em;font-size:.78rem;color:#fff;margin-bottom:.55rem;position:relative;padding-left:.95rem}
.hs-foot__col h3::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:14px;background:var(--action)}
.hs-foot__col a{color:rgba(244,242,239,.64);font-weight:500;font-size:.94rem;padding-bottom:2px;
  background:linear-gradient(var(--action),var(--action)) left bottom/0 2px no-repeat;
  transition:color .2s,background-size .28s}
.hs-foot__col a:hover{color:#fff;background-size:100% 2px;text-decoration:none}
.hs-foot__contact .site-footer__nap{color:rgba(244,242,239,.72);font-style:normal}
.hs-foot__contact .site-footer__hours{color:rgba(244,242,239,.6);font-size:.87rem}
.hs-foot__contact .gbp{color:rgba(244,242,239,.72)}
.hs-foot__bottom{display:flex;justify-content:space-between;align-items:center;gap:1rem;flex-wrap:wrap;
  border-top:1px solid rgba(255,255,255,.09);margin-top:3rem;padding-block:1.2rem;
  color:rgba(244,242,239,.48);font-size:.85rem;position:relative;z-index:1}
.hs-foot__bottom a{color:rgba(244,242,239,.62);transition:color .2s}
.hs-foot__bottom a:hover{color:#fff;text-decoration:none}
@media(max-width:1024px){.hs-foot__grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.hs-foot__grid{grid-template-columns:1fr}}

/* Footer contact column: quiet the town list, compact the hours. */
.hs-foot__contact .nap-area{display:block;font-size:.78rem;color:rgba(244,242,239,.42);line-height:1.55;margin-top:.3rem}
.hs-foot__contact .site-footer__hours{width:100%}
.hs-foot__contact .site-footer__hours caption{text-align:left;font-family:var(--font-display);font-weight:700;
  text-transform:uppercase;letter-spacing:.13em;font-size:.72rem;color:rgba(244,242,239,.55);padding-bottom:.35rem}
.hs-foot__contact .site-footer__hours th,.hs-foot__contact .site-footer__hours td{padding:.14em 0;font-size:.82rem}
.hs-foot__contact .site-footer__hours th{color:rgba(244,242,239,.55);font-weight:600;letter-spacing:.04em}
.hs-foot__contact .site-footer__hours td{text-align:right;color:rgba(244,242,239,.75)}

/* Hero meta: never let the rating number wrap. */
.hs-hero2__meta{flex-wrap:wrap}
.hs-hero2__meta b{white-space:nowrap}

/* ===== INTERIOR: REVIEWS/ABOUT/FAQ (agent) =====
   BW-57, for three of the pages it names. The home page grew a band system
   (hs-*) and the interior pages were still rendering the pre-pass shell, so
   the gap showed the moment anyone clicked off the landing page.

   Almost nothing new is invented here. Reviews reuses .hs-wall / .hs-wr,
   About reuses .hs-owner / .hs-inc / .hs-gal / .hs-photoband, FAQ reuses
   .hs-faqgrid. What follows is the small amount those three pages needed and
   the home page did not: an interior page head, the aggregate block that
   sits beside it, the review-tag row, and the FAQ jump list.

   The 3px ink rule over a side column is the site's existing structural
   device (.hs-faqhead, .hs-rev-agg, .hs-season>div). It is used again rather
   than replaced, because a fourth way of anchoring a column is how a
   stylesheet stops reading as one system. */

/* --- interior page head -------------------------------------------------- */
/* INTERIOR PAGE HERO, dark on the asphalt texture (Wayne, 2026-08-25:
   "the hero should have either a background image or that asphalt
   background, not just white"). This amends the two-placement texture
   rule: asphalt now lives in exactly three roles - the footer, the final
   CTA, and interior page heroes - so every interior page opens on the
   material and hands off to a light body. */
.hs-ph{background:var(--dark-bg);color:var(--dark-ink);position:relative;overflow:hidden;
  padding:clamp(2.8rem,5vw,4.2rem) 0}
.hs-ph::before{content:"";position:absolute;inset:0;
  background:var(--tex-asphalt) center/cover;opacity:.16;mix-blend-mode:luminosity}
.hs-ph>.wrap{position:relative}
.hs-ph h1{color:#fff}
.hs-ph .eyebrow{color:var(--dark-ink-2)}
.hs-ph .bh-kick{color:var(--dark-ink-2)}
.hs-ph .hs-btn-ghost-ink{color:#fff;border-color:rgba(255,255,255,.55);box-shadow:none}
.hs-ph .hs-btn-ghost-ink:hover{border-color:#fff;background:rgba(255,255,255,.08)}
.hs-ph .hs-agg{border-top-color:rgba(255,255,255,.92)}
.hs-ph .hs-agg .hs-num{color:#fff}
.hs-ph .hs-agg p{color:var(--dark-ink-2)}
.hs-ph .hs-agg .more{color:#fff}
.hs-ph__grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(240px,.65fr);
  gap:clamp(1.6rem,4vw,3.4rem);align-items:center}
.hs-ph h1{font-size:clamp(2rem,3.6vw,3rem);max-width:19ch}
.hs-ph__sub{margin:1rem 0 0;font-size:1.06rem;line-height:1.6;color:rgba(244,242,239,.85);max-width:58ch}
.hs-ph__ctas{display:flex;gap:.7rem;flex-wrap:wrap;margin-top:1.5rem}
@media(max-width:880px){.hs-ph__grid{grid-template-columns:1fr;align-items:start}}

/* The aggregate, beside the H1 rather than under the fold. Same big-number
   treatment as the home page's review wall head. */
.hs-agg{border-top:3px solid var(--ink);padding-top:1.1rem}
.hs-agg .hs-num{display:block;font-size:clamp(3rem,5.2vw,4.2rem);line-height:1}
.hs-agg .starrow{display:inline-flex;gap:3px;margin:.4rem 0 .3rem}
.hs-agg p{color:var(--ink-2);margin:.2rem 0 0;max-width:26ch;font-size:.95rem}
.hs-agg__link{margin-top:.8rem}

/* --- reviews ------------------------------------------------------------- */
.hs-wall-foot{margin:.2rem 0 0;color:var(--steel);font-size:.92rem}

/* Google's own topic tags on the profile, on the dark band. Read off the
   profile, not written by us, which is the whole reason it earns a band. */
.hs-tags__lead{color:var(--dark-ink-2);max-width:62ch}
.hs-tags{list-style:none;padding:0;margin:1.5rem 0 0;display:grid;grid-template-columns:repeat(4,1fr)}
.hs-tags li{border-left:1px solid var(--dark-bord);padding:.1rem 1.5rem}
.hs-tags li:first-child{border-left:none;padding-left:0}
.hs-tags b{display:block;font-family:var(--font-display);font-weight:700;font-size:1.18rem;color:#fff}
.hs-tags span{display:block;margin-top:.35rem;font-size:.85rem;color:var(--dark-ink-2)}
@media(max-width:820px){
  .hs-tags{grid-template-columns:1fr 1fr;gap:1.3rem 1.2rem}
  .hs-tags li{border-left:none;padding:0}
}

.hs-note{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(1.6rem,4vw,3.2rem);align-items:start}
.hs-note h2{font-size:clamp(1.6rem,2.8vw,2.1rem)}
.hs-note p{color:var(--ink-2);max-width:52ch}
.hs-note__cta{margin-top:1.4rem}
.hs-note__card{background:var(--surface);border:1px solid var(--bord);border-top:3px solid var(--ink);
  border-radius:var(--radius-card);padding:1.5rem}
.hs-note__card h3{font-family:var(--font-display);font-weight:700;font-size:1.15rem;margin-bottom:.5em}
.hs-note__card p{font-size:.95rem;margin-bottom:.9rem}
@media(max-width:820px){.hs-note{grid-template-columns:1fr}}

/* --- about --------------------------------------------------------------- */
.hs-lead{color:var(--ink-2);max-width:64ch;font-size:1.02rem;margin-bottom:0}
.hs-band .hs-lead+.hs-gal{margin-top:1.5rem}

/* Once .hs-inc stacks, its 400px min-height is a 400px tall slice cut out of
   a landscape photograph: on a phone the Merrillan shot became a column of
   parking lot with the rigs along the top edge. Scoped to this page rather
   than fixed on .hs-inc, because the home page's band was signed off as it
   renders and a shared-rule change would move it too. */
@media(max-width:860px){
  .hs-inc--about img{min-height:0;aspect-ratio:16/10}
}

/* --- faq ----------------------------------------------------------------- */
/* Nine grids, so the head column runs shorter and quieter than the home
   page's single one; at the home page's 24ch a card summary became a column
   of two-word lines. */
.hs-faqsec .hs-faqhead h2{font-size:clamp(1.45rem,2.5vw,1.95rem);margin-bottom:0}
.hs-faqsec .hs-faqhead p{max-width:32ch;font-size:.95rem}

.hs-jump{border-top:3px solid var(--ink);padding-top:1rem}
.hs-jump__head{font-family:var(--font-display);font-weight:700;text-transform:uppercase;
  letter-spacing:.13em;font-size:.72rem;color:var(--steel);margin:0 0 .5rem}
.hs-jump a{display:flex;justify-content:space-between;gap:1rem;align-items:baseline;
  text-decoration:none;font-family:var(--font-display);font-weight:600;font-size:.94rem;
  padding:.42rem 0;border-bottom:1px solid var(--bord-soft);transition:color .15s}
.hs-jump a:last-child{border-bottom:none}
.hs-jump a:hover{color:var(--action)}
.hs-jump a span{font-size:.8rem;color:var(--steel);font-variant-numeric:tabular-nums;flex:none}
/* ===== INTERIOR: COMMERCIAL/AREA/CONTACT (agent) ===== */
/* ---------------------------------------------------------------------------
   2026-08-24. The homepage got the premium hs- system and the interior pages
   did not (BW-57). This block is everything those pages needed that the
   homepage had no use for: an interior hero, a scoping table, contact cards,
   place lists, and the light-ground variants of two dark-ground components.

   Rule followed throughout: reuse first, add second. .hs-band, .hs-facts,
   .hs-svc, .hs-steps, .hs-season, .hs-honest, .hs-photoband, .hs-formcard,
   .hs-wr--dark, .starrow and .hs-strip are all the homepage's, unchanged.
   ------------------------------------------------------------------------ */

/* --- interior hero: dark band, photograph, red kicker, plain-label H1 ---- */
.hs-phero{position:relative;overflow:hidden;background:var(--dark-bg);color:#fff}
.hs-phero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center 62%;filter:saturate(.82) brightness(.68)}
.hs-phero__scrim{position:absolute;inset:0;background:
  linear-gradient(100deg,rgba(10,11,13,.93) 0%,rgba(10,11,13,.8) 44%,rgba(10,11,13,.55) 72%,rgba(10,11,13,.68) 100%)}
.hs-phero__in,.hs-phero__grid{position:relative;z-index:2;
  padding-top:clamp(2.6rem,5vw,4rem);padding-bottom:clamp(2.6rem,5vw,4rem)}
.hs-phero h1{color:#fff;font-family:var(--font-display);font-weight:800;line-height:1.06;
  font-size:clamp(2rem,3.4vw,2.9rem);max-width:22ch;text-wrap:balance}
.hs-phero__sub{margin-top:1.05rem;font-size:1.06rem;line-height:1.6;
  color:rgba(255,255,255,.9);max-width:58ch}
.hs-phero .hs-hero__ctas{margin-top:1.5rem;display:flex;gap:.7rem;flex-wrap:wrap}
.hs-phero .btn svg{vertical-align:-2px;margin-right:.4em}
.hs-phero__meta{margin-top:1.3rem;display:flex;align-items:center;gap:.55rem;flex-wrap:wrap;
  font-size:.95rem;color:rgba(255,255,255,.9)}
.hs-phero__meta b{font-family:var(--font-display);font-weight:800;color:#fff;white-space:nowrap}
.hs-phero .hs-assure{margin-top:1.1rem}

/* The flat variant has no photograph: thank-you and 404 are not places to
   spend a job photo, and the asphalt ground alone says "same site". */
.hs-phero--flat::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:var(--tex-asphalt) center/cover;opacity:.3;mix-blend-mode:luminosity}

/* Contact's hero carries the form card, on the homepage's split. */
.hs-phero__grid{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(330px,420px);
  gap:clamp(1.8rem,4vw,4rem);align-items:center}
/* min-width:0 rather than nothing: a grid item defaults to min-content width,
   so a long unbroken string in the copy column would widen the track and push
   the form card off the viewport. */
.hs-phero__copy{min-width:0}
@media(max-width:960px){
  .hs-phero__grid{grid-template-columns:1fr;align-items:start}
  .hs-phero--form .hs-formcard--hero{max-width:520px}
}

/* --- shared interior furniture ------------------------------------------ */
.hs-lede{margin-top:.6rem;font-size:1.05rem;color:var(--ink-2);max-width:var(--wrap-text)}
.hs-two{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.4rem,3vw,2.6rem)}
/* Spec-sheet panel: the product column as an object on the band. */
.hs-spec{background:var(--surface);border-top:2px solid var(--ink);padding:1.5rem 1.6rem 1.6rem;box-shadow:var(--shadow-1)}
.hs-two p{color:var(--ink-2);max-width:52ch}
.hs-split{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(1.8rem,4vw,3.4rem);align-items:start}
@media(max-width:880px){.hs-two,.hs-split{grid-template-columns:1fr}}

/* --- the scoping table -------------------------------------------------- */
.hs-tablewrap{overflow-x:auto;margin-top:1.4rem;-webkit-overflow-scrolling:touch}
.hs-table{width:100%;border-collapse:collapse;font-size:.97rem;min-width:34rem}
.hs-table th{font-family:var(--font-display);text-transform:uppercase;letter-spacing:.07em;
  font-size:.76rem;text-align:left;color:var(--steel);white-space:nowrap;
  padding:.6rem 1.1rem .6rem 0;border-bottom:2px solid var(--ink)}
.hs-table td{padding:.8rem 1.1rem .8rem 0;border-bottom:1px solid var(--bord);vertical-align:top;
  color:var(--ink-2)}
.hs-table td:first-child{font-weight:600;color:var(--ink)}
.hs-table tbody tr:last-child td{border-bottom:none}
.hs-table--area{min-width:30rem}
.hs-table--area td:nth-child(2),.hs-table--area td:nth-child(3){white-space:nowrap}

/* --- the verbatim-review band ------------------------------------------- */
.hs-qband{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(1.6rem,3.5vw,3rem);
  align-items:start;margin-top:1.4rem}
.hs-qband__q{margin:0}
.hs-qband__q blockquote{font-size:1.12rem;line-height:1.55}
.hs-qband__side{border-top:3px solid var(--ink);padding-top:1.1rem}
.hs-qband__side p{color:var(--ink-2);max-width:46ch}
@media(max-width:880px){.hs-qband{grid-template-columns:1fr}}

/* --- audience tiles ----------------------------------------------------- */
.hs-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:1.2rem;margin-top:1.5rem}
.hs-tile{background:var(--surface);border:1px solid var(--bord);border-radius:var(--radius-card);
  padding:1.5rem 1.4rem 1.6rem;transition:border-color .2s,box-shadow .2s,transform .2s}
.hs-tile:hover{border-color:var(--steel);box-shadow:var(--shadow-2);transform:translateY(-2px)}
.hs-tile__ic{display:inline-flex;width:42px;height:42px;border-radius:var(--radius-ctl);
  background:rgba(185,18,27,.08);color:var(--action);align-items:center;justify-content:center;
  margin-bottom:.9rem}
.hs-tile h3{font-family:var(--font-display);font-weight:700;font-size:1.1rem;margin-bottom:.4em}
.hs-tile p{font-size:.95rem;color:var(--ink-2)}
.hs-tile a{font-weight:600;color:var(--action)}
@media(max-width:880px){.hs-tiles{grid-template-columns:1fr}}

/* --- light-ground variant of the dark checklist ------------------------- */
.hs-inc__list--light{margin-top:1.2rem}
.hs-inc__list--light li{color:var(--ink-2);border-bottom-color:var(--bord);font-size:.97rem}
/* Ink checks on light ground (PA-16): the red ticks spent accent budget on
   list punctuation and read as clip-art. Red checks stay on dark bands,
   where they are the brand pop; on paper the check is structure, not a CTA. */
.hs-inc__list--light li::before{border-left-color:var(--ink);border-bottom-color:var(--ink)}

/* --- final band extras -------------------------------------------------- */
.hs-final__list{list-style:none;padding:0;margin:1.3rem 0 0;display:grid;gap:.5rem}
.hs-final__list li{position:relative;padding-left:1.6rem;font-size:.94rem;color:rgba(255,255,255,.92)}
.hs-final__list li::before{content:"";position:absolute;left:0;top:.5em;width:11px;height:6px;
  border-left:2.5px solid #fff;border-bottom:2.5px solid #fff;transform:rotate(-45deg)}
.hs-final__center{text-align:center}
.hs-final__center p{max-width:46ch;margin-inline:auto}

/* --- service area: edges list, place lists ------------------------------ */
.hs-edges{list-style:none;padding:0;margin:1.4rem 0 0;display:grid;gap:.85rem}
.hs-edges li{display:flex;gap:.8rem;align-items:flex-start}
.hs-edges svg{color:var(--action);flex:none;margin-top:.15rem}
.hs-edges b{display:block;font-family:var(--font-display);font-weight:700;font-size:1rem}
.hs-edges span{display:block;font-size:.9rem;color:var(--steel)}

.hs-places{list-style:none;padding:0;margin:1.3rem 0 0;columns:4;column-gap:2rem;
  font-size:.96rem;font-weight:500}
.hs-places li{break-inside:avoid;padding:.32rem 0 .32rem 16px;position:relative}
.hs-places li::before{content:"";position:absolute;left:0;top:.82em;width:5px;height:5px;
  border-radius:50%;background:var(--action)}
.hs-places a{text-decoration:none;font-weight:700}
.hs-places a:hover{color:var(--action)}
.hs-places--tight{font-size:.92rem;font-weight:400}
.hs-places--tight li::before{background:var(--steel);width:4px;height:4px}
@media(max-width:900px){.hs-places{columns:3}}
@media(max-width:640px){.hs-places{columns:2}}

/* --- contact cards ------------------------------------------------------ */
.hs-ccards{display:grid;grid-template-columns:repeat(3,1fr);gap:1.2rem}
.hs-ccard{background:var(--surface);border:1px solid var(--bord);border-radius:var(--radius-card);
  padding:1.5rem 1.4rem 1.6rem;text-decoration:none;display:block;color:var(--ink);
  transition:border-color .2s,box-shadow .2s,transform .2s}
a.hs-ccard:hover{border-color:var(--steel);box-shadow:var(--shadow-2);transform:translateY(-2px)}
.hs-ccard__ic{display:inline-flex;width:40px;height:40px;border-radius:var(--radius-ctl);
  background:rgba(185,18,27,.08);color:var(--action);align-items:center;justify-content:center;
  margin-bottom:.85rem}
.hs-ccard__tag{font-family:var(--font-display);font-size:.72rem;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--steel);margin:0 0 .5rem}
.hs-ccard h2,.hs-ccard h3{font-family:var(--font-display);font-weight:700;
  font-size:1.15rem;letter-spacing:-.008em;line-height:1.25}
.hs-ccard h2 a,.hs-ccard h3 a{text-decoration:none}
.hs-ccard h2 a:hover,.hs-ccard h3 a:hover{color:var(--action)}
.hs-ccard p{font-size:.94rem;color:var(--ink-2);margin:.6rem 0 0}
.hs-ccard .more{font-weight:600}
/* Ink ground marks the recommended card. A brand-tinted border is the tell of
   a component that could not think of another way to say "this one". */
.hs-ccard--pick{background:var(--dark-bg);border-color:var(--dark-bg);color:var(--dark-ink)}
.hs-ccard--pick .hs-ccard__ic{background:rgba(228,81,92,.16);color:#E4515C}
.hs-ccard--pick .hs-ccard__tag{color:var(--dark-ink-2)}
.hs-ccard--pick h2{font-size:1.6rem;color:#fff}
.hs-ccard--pick h2 a{color:#fff}
.hs-ccard--pick h2 a:hover{color:#E4515C}
.hs-ccard--pick p{color:var(--dark-ink-2)}
@media(max-width:900px){.hs-ccards{grid-template-columns:1fr}}

.hs-napgrid{display:grid;grid-template-columns:1.15fr .85fr;gap:1.2rem;align-items:start}
.hs-napgrid table{width:100%}
@media(max-width:820px){.hs-napgrid{grid-template-columns:1fr}}

.hs-places-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.1rem;margin-top:1.4rem}
@media(max-width:1000px){.hs-places-grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.hs-places-grid{grid-template-columns:1fr}}

/* --- the season trio, borrowed onto a dark ground ----------------------- */
/* .hs-season was written for the light --alt band: ink rules and --ink-2 body
   copy. Both disappear on asphalt, so the dark host restates them. */
.hs-dark .hs-season>div{border-top-color:var(--dark-ink)}
.hs-dark .hs-season h3{color:#fff}
.hs-dark .hs-season p{color:var(--dark-ink-2)}
.hs-dark .hs-season__ic{background:rgba(228,81,92,.16);color:#E4515C}

/* --- narrow-viewport safety --------------------------------------------- */
/* The tables are the only elements on these pages wide enough to push the
   document sideways, and .hs-tablewrap is what stops them. Everything else
   here is a grid that collapses to one column well above 390px. */
@media(max-width:560px){
  .hs-phero__in,.hs-phero__grid{padding-top:2.2rem;padding-bottom:2.2rem}
  .hs-qband__q blockquote{font-size:1.02rem}
  .hs-ccard--pick h2{font-size:1.4rem}
}

/* --- specificity casualty ----------------------------------------------- */
/* .hs-formhead is one class, and `.hs-band h2` is a class plus an element, so
   the band's 2.3rem heading beat the form card's 1.35rem the moment a card
   landed inside a band rather than inside a hero. It rendered as a heading
   twice the size of the form it labels. Restated at equal weight. */
.hs-band .hs-formhead,.hs-band--alt .hs-formhead,.hs-final .hs-formhead{font-size:1.35rem}

/* --- NAP block, sitewide ------------------------------------------------ */
/* WebKit's NapBlock emits inline spans and anchors with no separators between
   them, on the assumption that the consuming stylesheet lays them out. This
   one never did, so every rendering of it ran the name, the service-area list,
   the phone and the email together into one sentence:
   "...Jim Falls, WI(715) 450-9897blackwidowsealcoating@gmail.com".
   Visible in the footer of every page and, once the contact page started
   rendering it in a card, in the middle of the page too. BW-73. */
.nap{font-style:normal}
.nap .nap-name{display:block;font-family:var(--font-display);font-weight:700}
.nap .nap-addr,.nap .nap-area{display:block;margin-top:.25rem}
.nap .nap-phone{display:block;margin-top:.55rem;font-family:var(--font-display);
  font-weight:700;font-size:1.05rem;text-decoration:none;font-variant-numeric:tabular-nums}
.nap .nap-email{display:block;margin-top:.15rem}
.hs-foot__contact .nap .nap-phone{font-size:1rem;color:#fff}
/* In a contact card the town list is supporting detail, not body copy. */
.hs-ccard .nap .nap-area{font-size:.88rem;color:var(--steel);line-height:1.5}
/* HoursTable brings its own caption; dressed as a card tag so the two cards
   in the NAP row are labelled the same way. */
.hs-ccard .hours-caption{text-align:left;font-family:var(--font-display);font-size:.72rem;
  font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--steel);
  padding-bottom:.7rem}
.hs-ccard .hours th,.hs-ccard .hours td{padding:.35em 0}
.hs-ccard .hours td{text-align:right}

/* Section-head tag: let it wrap under the heading on phones instead of
   pushing past the viewport (170px overflow on /commercial/ at 390). */
@media(max-width:640px){
  .lv2-shead{flex-wrap:wrap}
  .lv2-shead .tag{margin-left:0;white-space:normal;flex-basis:100%}
}

/* ===== INTERIOR: SERVICES (agent) ===== */
/* The three service templates (/services/, /services/<slug>/ and
   /services/<slug>/<city>/) brought onto the home page's hs- band system.

   Almost everything these pages need already exists above: hs-band,
   hs-band--alt, hs-dark, hs-steps + hs-step__ic, hs-season__ic, hs-photoband,
   hs-cap, hs-strip, hs-final, hs-formcard, hs-towns, hs-faqgrid, starrow.
   What is here is the two pieces the home page never needed (an interior page
   hero and a light spec strip), plus the extensions that let those existing
   components sit on a dark ground. Site tokens only; no new palette. */

/* --- interior page hero: dark, asphalt texture, kicker rule, photo ------- */
.svp-hero{position:relative;background:var(--dark-bg);color:var(--dark-ink);overflow:hidden}
.svp-hero::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:url("/assets/black-widow-sealcoating/asphalt-bg.jpg") center/cover;
  opacity:.16;mix-blend-mode:luminosity}
/* Concrete pages sit on their own material: the broom-finished concrete
   grain instead of asphalt. Lower opacity because the texture is light
   and glows more under the luminosity blend. */
.svp-hero--concrete::before{
  background:url("/assets/black-widow-sealcoating/concrete-bg.jpg") center/cover;
  opacity:.12}
.svp-hero__grid{position:relative;z-index:1;display:grid;
  grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr);gap:clamp(1.8rem,4vw,3.4rem);
  align-items:center;padding-top:clamp(2.6rem,5vw,4.2rem);padding-bottom:clamp(2.6rem,5vw,4.2rem)}
.svp-hero__copy{min-width:0}
.svp-hero h1{color:#fff;font-family:var(--font-display);font-weight:800;line-height:1.07;
  font-size:clamp(1.95rem,3.3vw,2.95rem);max-width:20ch;text-wrap:balance;letter-spacing:-.015em}
.svp-hero__sub{margin-top:1.05rem;font-size:1.05rem;line-height:1.6;
  color:rgba(244,242,239,.88);max-width:56ch}
.svp-hero__sub p{margin:0 0 .75rem}
.svp-hero__ctas{display:flex;gap:.75rem;flex-wrap:wrap;margin-top:1.5rem}
.svp-hero__ctas .btn svg{vertical-align:-2px;margin-right:.4em}
.svp-hero__meta{margin-top:1.35rem;display:flex;align-items:center;gap:.55rem;flex-wrap:wrap;
  font-size:.95rem;color:rgba(244,242,239,.9)}
.svp-hero__meta b{font-family:var(--font-display);font-weight:800;color:#fff;white-space:nowrap}
.svp-hero__note{margin-top:.85rem;font-size:.9rem;color:rgba(244,242,239,.66);max-width:52ch}
.svp-hero .hs-assure{margin-top:1.1rem}

/* The photo frame. Fixed ratio, so nine different job photos give nine heroes
   the same shape, and the grain layer every other photo frame on this site
   carries, so these do not read as a different set of pictures. */
.svp-shot{position:relative;overflow:hidden;border:1px solid var(--dark-bord);border-radius:var(--radius-card);
  background:#101215;min-width:0}
.svp-shot img{width:100%;aspect-ratio:4/3;object-fit:cover;
  filter:contrast(1.06) saturate(.94) brightness(.98)}
.svp-shot::after{content:"";position:absolute;inset:0;pointer-events:none;
  opacity:.07;mix-blend-mode:overlay;background-size:180px 180px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E")}
@media(max-width:960px){
  .svp-hero__grid{grid-template-columns:1fr;align-items:start;gap:1.6rem}
  .svp-shot img{aspect-ratio:16/10}
}

/* --- light spec strip, under the hero ------------------------------------ */
.svp-spec{background:var(--surface-2);border-bottom:1px solid var(--bord)}
/* auto-fit, not repeat(4): only two of the nine services author four stats.
   A fixed four-column track put concrete's two numerals in the left half of
   the strip with an empty right half, which reads as a band that lost its
   content rather than as a band with two facts in it. */
.svp-spec .wrap{display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));padding-block:1.5rem}
.svp-spec>.wrap>div{padding-inline:1.4rem;border-left:1px solid var(--bord);min-width:0}
.svp-spec>.wrap>div:first-child{border-left:0;padding-left:0}
.svp-spec b{display:block;font-family:var(--font-display);font-weight:800;line-height:1;
  font-size:clamp(1.45rem,2.7vw,2.05rem);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.svp-spec b i{font-style:normal;font-size:.48em;color:var(--action);margin-left:.08em;letter-spacing:0}
.svp-spec span{display:block;margin-top:.5rem;font-size:.83rem;line-height:1.4;
  color:var(--ink-2);font-weight:700}
.svp-spec span em{display:block;font-style:normal;color:var(--steel);font-weight:600;margin-top:.15rem}
@media(max-width:820px){
  .svp-spec .wrap{grid-template-columns:1fr 1fr;gap:1.25rem 0}
  .svp-spec>.wrap>div:nth-child(3){border-left:0;padding-left:0}
}
@media(max-width:430px){
  .svp-spec .wrap{grid-template-columns:1fr;gap:1rem 0}
  .svp-spec>.wrap>div{border-left:0;padding-left:0}
}

/* --- the hs- components, on a dark ground -------------------------------- */
/* The process band is the one dark punch on a service hub. The steps list and
   its icon chips were built for paper, so the chip inverts: hairline on a
   barely-lit panel, warm red glyph, filling solid red under the pointer. */
.hs-dark .hs-steps{border-top-color:var(--dark-ink);border-bottom-color:var(--dark-ink)}
.hs-dark .hs-step{border-bottom-color:var(--dark-bord)}
.hs-dark .hs-step:last-child{border-bottom:none}
.hs-dark .hs-step h3{color:#fff}
.hs-dark .hs-step p{color:var(--dark-ink-2)}
.hs-dark .hs-step__ic{background:rgba(244,242,239,.06);border-color:var(--dark-bord);color:#E4515C}
.hs-dark .hs-step:hover .hs-step__ic{background:var(--action);border-color:var(--action);color:#fff}
.hs-dark .svp-lede{color:var(--dark-ink-2)}
.hs-dark .more{color:#fff}

/* --- band furniture ------------------------------------------------------ */
.svp-lede{color:var(--ink-2);font-size:1.03rem;line-height:1.6;max-width:64ch;margin:0 0 1.5rem}
.svp-two{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,.65fr);
  gap:clamp(1.8rem,4vw,3.2rem);align-items:start}
@media(max-width:900px){.svp-two{grid-template-columns:1fr}}

/* BW-156: the town band on the two services that carry no housing-stock
   prose (athletic surfaces, snow plowing). One paragraph beside a full
   card leaves the grid row set by the card and the column under the prose
   empty. One column instead, card under prose at reading width: nothing to
   leave empty, and the card reads as a footnote to the paragraph rather
   than as a sidebar with nothing beside it. */
.svp-two--narrow{grid-template-columns:minmax(0,1fr);gap:1.9rem}
.svp-two--narrow .svp-card{max-width:44rem}

.svp-prose p{color:var(--ink-2);max-width:66ch}
.svp-prose p+p{margin-top:.85rem}
.svp-prose h3{font-family:var(--font-display);font-weight:700;font-size:1.16rem;
  margin:1.9rem 0 .5rem}
.svp-prose :is(p,li) a,.svp-card a,.faq__a a{color:inherit;font-weight:600;text-decoration:underline;
  text-decoration-color:var(--action);text-decoration-thickness:1.5px;text-underline-offset:3px;
  transition:color .15s}
.svp-prose :is(p,li) a:hover,.svp-card a:hover,.faq__a a:hover{color:var(--action)}

/* The local card beside the town prose. Red top rule rather than a coloured
   border all the way round: one mark, not a frame. */
.svp-card{background:var(--surface);border:1px solid var(--bord);border-top:3px solid var(--action);
  border-radius:var(--radius-card);padding:1.3rem 1.4rem}
.svp-card h3{font-family:var(--font-display);font-weight:700;font-size:1.08rem}
.svp-card ul{list-style:none;margin:.8rem 0 0;padding:0;display:grid;gap:.4rem}
.svp-card li{display:flex;gap:.55rem;font-size:.93rem;color:var(--ink-2);min-width:0}
.svp-card li::before{content:"";width:5px;height:5px;background:var(--action);flex:none;margin-top:.55rem}
.svp-card__note{margin-top:1.05rem;font-size:.88rem;color:var(--steel);line-height:1.5}
.svp-card__note b{color:var(--ink)}

/* Town lists reuse the home page's dotted hs-towns, which never carried a link
   because the home page's list does not go anywhere. */
.hs-towns a{color:inherit;text-decoration:none;transition:color .15s}
.hs-towns a:hover{color:var(--action);text-decoration:underline;
  text-underline-offset:.28em;text-decoration-thickness:2px}

/* Internal-link lists at the foot of a location page: ruled rows that nudge
   right, rather than two runs of bullets. */
.svp-links{list-style:none;margin:1rem 0 2rem;padding:0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(16rem,100%),1fr));gap:0 1.8rem}
.svp-links li{min-width:0;border-bottom:1px solid var(--bord)}
.svp-links a{display:block;padding:.7rem 0;font-size:.94rem;font-weight:600;
  color:var(--ink-2);text-decoration:none;transition:color .15s,padding-left .18s}
.svp-links a:hover{color:var(--action);padding-left:.35rem}

/* The lead-form band's left column, so the form is not the only thing in it. */
.hs-final .svp-final__list{list-style:none;margin:1.4rem 0 0;padding:0;display:grid;gap:0;max-width:34em}
.hs-final .svp-final__list li{display:flex;gap:.65rem;padding:.7rem 0;
  border-top:1px solid rgba(255,255,255,.22);font-size:.95rem;color:rgba(255,255,255,.94)}
.hs-final .svp-final__list li:last-child{border-bottom:1px solid rgba(255,255,255,.22)}
.hs-final .svp-final__list svg{flex:none;margin-top:.22rem}

/* The compare, prices and package cards predate the hs- system and set their
   own top margin nowhere, so they sat flush under a band heading. */
.hs-band .compare,.hs-band .prices,.hs-band .cards{margin-top:1.3rem}
/* .prices is repeat(4,1fr) with a 1px grid background showing through the
   gaps, so a service with two price bands rendered two cards and a 590px
   rectangle of border grey. Snow plowing has two, sealcoating has four. */
.hs-band .prices{grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr))}
.hs-band .prices__foot,.hs-band .compare__foot{margin-top:1.4rem;color:var(--ink-2)}
/* The WebKit DecisionMatrix ships its own scoped styles under bs-decision and
   its heading is a real h2, so it only needs air above it here. */
.hs-band .bs-decision{margin-top:.4rem}

/* AUDIT FIX, found by looking at the rendered closing band. `.hs-final p` is
   (0,1,1) and `.leadform__legal` is (0,1,0), so the form's own legal line was
   being painted white on the white card and read as an empty 90px of nothing
   under the submit button. This is a HOME PAGE bug too; the rule is written
   against .hs-formcard so it fixes both. */
.hs-formcard .leadform__legal{color:var(--steel)}

/* The closing band's left column is four short elements and the form beside it
   is nine fields tall, so top-aligning them left roughly 500px of empty red
   under the phone number. Centring is the cheaper of the two fixes and the
   right one: the column is a statement, not a list that has to start at the
   top of the band. Scoped to these pages, so the home page is untouched. */
@media(min-width:821px){
  .svp-final .hs-final__grid{align-items:center}
}

/* The split band head. A full-width h2 over a 66ch column leaves the top right
   of the band empty at the moment the reader is deciding whether to keep
   going: research/16 section 2.2 calls that the template tell. Heading left
   under its own rule, argument right at a readable measure. */
@media(min-width:1000px){
  .svp-splithead{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
    column-gap:clamp(2rem,5vw,4rem);align-items:start}
  .svp-splithead>h2{grid-column:1;margin:0;border-top:3px solid var(--ink);
    padding-top:1rem;max-width:17ch}
  .svp-splithead>div{grid-column:2;min-width:0}
  .svp-splithead .svp-prose p{max-width:none}
}
@media(max-width:999px){
  .svp-splithead>h2{margin-bottom:.6em}
}

/* Structural wrappers the orphan-classes gate flagged. min-width:0 is the
   real grid-child overflow guard; the trio wrap clips any child bleed. */
.hs-hero2__copy{min-width:0}
.hs-foot__brand{min-width:0}
.hs-trio-wrap{overflow:hidden}

/* Reviewed line for the hand-authored commercial pages (BW-95). Month-level
   on purpose: a self-updating date is a lie the day nobody re-reads the page. */
.hs-updated{font-size:.82rem;color:var(--ink-2);letter-spacing:.02em;margin-top:2.2rem}

/* Flyover footage: bright aerial, so the muffle tuned for the old close-up
   clip comes off. Copy side keeps its gradient; the right lets the lots show. */
.hs-hero2__video{filter:saturate(.95) brightness(.9)}
.hs-hero2__scrim{background:
  linear-gradient(100deg,rgba(10,11,13,.86) 0%,rgba(10,11,13,.66) 40%,rgba(10,11,13,.28) 68%,rgba(10,11,13,.38) 100%)}

/* Recent Jobs on black: the caption panel needs a seam against the band. */
.hs-dark .hs-car2{box-shadow:var(--shadow-3)}
.hs-dark .hs-car2__panel{border-left:1px solid var(--dark-bord)}

/* ============ SERVICE AREA v2: town cards, no taxonomy ============ */
.hs-area__photo{margin:0;position:relative;border-radius:var(--radius-card);overflow:hidden;line-height:0}
.hs-area__photo img{width:100%;height:100%;min-height:340px;object-fit:cover}
.hs-towngrid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.2rem;margin-top:1.6rem}
.hs-town{background:#fff;border:1px solid var(--bord);border-radius:var(--radius-card);padding:1.3rem 1.4rem;
  display:flex;flex-direction:column;transition:transform .25s ease,box-shadow .25s ease}
.hs-town:hover{transform:translateY(-3px);box-shadow:var(--shadow-2)}
.hs-town header{display:flex;align-items:baseline;justify-content:space-between;gap:.6rem;margin-bottom:.5rem}
.hs-town h3{font-family:var(--font-display);font-weight:800;font-size:1.12rem}
.hs-town__drive{font-size:.78rem;color:var(--ink-2);white-space:nowrap}
.hs-town p{font-size:.9rem;color:var(--ink-2);line-height:1.55;flex:1}
.hs-town__links{list-style:none;padding:.9rem 0 0;margin:.9rem 0 0;border-top:1px solid var(--bord);
  display:flex;flex-wrap:wrap;gap:.35rem .9rem}
.hs-town__links a{font-size:.85rem;font-weight:600;color:var(--action);text-decoration:none;
  background:linear-gradient(var(--action),var(--action)) left bottom/0 1.5px no-repeat;
  transition:background-size .25s;padding-bottom:2px}
.hs-town__links a:hover{background-size:100% 1.5px}
@media(max-width:1024px){.hs-towngrid{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.hs-towngrid{grid-template-columns:1fr}}

/* Town cards on phones: a long drive-time string was propping cards past the
   viewport. Let the header wrap and never let the span set the track width. */
.hs-town{min-width:0}
.hs-town header{flex-wrap:wrap}
.hs-town__drive{white-space:normal}

/* The real map: Google embed in a framed panel. */
.hs-gmap{margin:0;position:relative;border-radius:var(--radius-card);overflow:hidden;border:1px solid var(--bord);
  box-shadow:var(--shadow-2);line-height:0;background:var(--surface-2)}
.hs-gmap iframe{width:100%;height:100%;min-height:420px;border:0;display:block}
.hs-gmap .hs-cap{line-height:1.4}

/* The reviewed line landed between sections, outside any wrap. Give it the
   wrap's own geometry so it sits where body copy sits. */
.hs-updated{max-width:var(--wrap);margin-inline:auto;padding:0 var(--gutter) 2.2rem}

/* Map facade: the static shot is the map until asked; the button invites. */
.hs-gmap__load{display:block;position:relative;width:100%;border:0;padding:0;cursor:pointer;background:none;line-height:0}
/* Muted toward the page's palette (PA-08): Google's default mint fought the
   warm paper ground. Saturation eases back on hover so "this is a live map"
   still reads; the loaded iframe is untouched. */
.hs-gmap__load img{width:100%;height:auto;display:block;filter:saturate(.55) contrast(1.03);transition:filter .25s}
.hs-gmap__load:hover img{filter:saturate(.8)}
/* The coverage annotation drawn over the capture: tint, boundary, home dot. */
.hs-gmap__area{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
.hs-gmap__cta{position:absolute;right:14px;top:14px;background:var(--ink);color:#fff;
  font-family:var(--font-display);font-weight:700;font-size:.82rem;letter-spacing:.06em;
  text-transform:uppercase;padding:.6em 1.1em;border-radius:var(--radius-ctl);line-height:1;
  box-shadow:var(--shadow-chip);transition:background .2s}
.hs-gmap__load:hover .hs-gmap__cta{background:var(--action)}
.hs-gmap iframe{aspect-ratio:1200/877;min-height:0;height:auto}
/* ...and take it straight back off when the line is already inside a wrap,
   which is where it belongs. Nested, the gutter applies twice and the line
   sits indented from the copy it is supposed to align with. */
.wrap .hs-updated{max-width:none;margin-inline:0;padding:0}

/* The featured price band is ink-on-ink, and its list markers were painted in
   var(--ink) like every other band's, so the bullets on the one card people
   look at hardest were invisible. Renders on the sealcoating hub, the 19
   sealcoating town pages and the driveway page. */
.prices > div.is-featured li::before{background:var(--paper)}

/* Hero rebalance: H1 up a step; the form card goes two fields per row so it
   reads as a card instead of a tall thin strip. Guarded to desktop: written
   unguarded, these two lines overrode the 960px stack from the bottom of the
   file and crushed the mobile text column to one character per line (PA-01). */
@media(min-width:961px){
  .hs-hero2 h1{font-size:clamp(2.5rem,3.9vw,3.5rem);max-width:18ch}
}
/* Balanced rag on the H1 at every width (PA-30); no-op where unsupported. */
.hs-hero2 h1{text-wrap:balance}
@media(min-width:961px){
  .hs-hero2__grid{grid-template-columns:minmax(0,1.15fr) minmax(400px,500px)}
}
.hs-formcard .leadform{display:grid;grid-template-columns:1fr 1fr;column-gap:.9rem;align-items:start}
.hs-formcard .leadform > *{grid-column:1 / -1}
.hs-formcard .leadform > .leadform__field:has(input){grid-column:auto}
.hs-formcard .leadform > .leadform__field:has(textarea){grid-column:1 / -1}
/* With email off (PA-43) the zip was a half-width orphan beside a hole. */
.hs-formcard .leadform:not(:has(input[name="email"])) > .leadform__field:has(input[name="zip"]){grid-column:1 / -1}
.hs-formcard--hero .leadform__legal{margin-top:.5rem}

/* Hero form card goes dark: the white card fought the video band. Same
   fields, same contract, dressed for the black theme. */
.hs-formcard--hero{background:#1B1D22;border:1px solid rgba(255,255,255,.1);color:var(--dark-ink);
  box-shadow:var(--shadow-3)}
.hs-formcard--hero .hs-formhead{color:#fff}
.hs-formcard--hero .hs-formsub{color:rgba(244,242,239,.65)}
.hs-formcard .leadform{background:none;border:0;padding:0}
/* BW-64 class of bug, third occurrence: .hs-final p paints band text white
   and reaches inside the white card; the sub was invisible. */
.hs-final .hs-formcard .hs-formsub{color:var(--ink-2)}
.hs-formcard--hero .leadform label{color:rgba(244,242,239,.8)}
.hs-formcard--hero .leadform input,.hs-formcard--hero .leadform textarea{
  background:#26292F;border:1px solid rgba(255,255,255,.16);color:#fff}
.hs-formcard--hero .leadform input::placeholder,.hs-formcard--hero .leadform textarea::placeholder{
  color:rgba(244,242,239,.38)}
.hs-formcard--hero .leadform input:focus,.hs-formcard--hero .leadform textarea:focus{
  border-color:var(--action);box-shadow:var(--focus-ring)}
.hs-formcard--hero .sms-consent__text{color:rgba(244,242,239,.55)}
.hs-formcard--hero .sms-consent__link{color:rgba(244,242,239,.75)}
.hs-formcard--hero .leadform__legal{color:rgba(244,242,239,.45)}
.hs-formcard--hero .leadform__legal a{color:rgba(244,242,239,.65)}

/* ================= /gallery/ =================
   The page reuses the site's existing .hs-gal grammar (3-col grid, uniform
   crop, dark overlay caption - already live on About and two segment pages).
   The modifier only makes the tiles taller on the dedicated page. */
.hs-gal--lg img{height:280px}
.hs-gal--lg figure a{display:block}
@media(max-width:560px){.hs-gal--lg img{height:220px}}

/* ============ .hs-jobs: the job-photo mosaic (2026-08-26) ============
   The premium treatment for photo bands (Wayne: image areas must pop).
   A featured lead tile earns hierarchy, the rest fill a dense grid, and
   the count-keyed patterns below make 1-4 tiles each fill their band
   cleanly. Hover lifts the shadow one rung and zooms the frame; the
   caption sits on a scrim with the red kick. Square corners, per the
   register. */
.hs-jobs{display:grid;gap:14px;margin-top:1.6rem}
.hs-jobs figure{position:relative;margin:0;overflow:hidden;background:var(--ink);box-shadow:var(--shadow-1)}
.hs-jobs a{display:block;height:100%}
.hs-jobs img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s cubic-bezier(.2,.6,.2,1)}
.hs-jobs figure:hover img{transform:scale(1.045)}
.hs-jobs figure{transition:box-shadow .25s ease}
.hs-jobs figure:hover{box-shadow:var(--shadow-2)}
.hs-jobs figcaption{position:absolute;left:0;right:0;bottom:0;padding:.55rem .85rem .6rem;
  color:#fff;font-family:var(--font-display);font-weight:600;font-size:.82rem;letter-spacing:.01em;
  background:linear-gradient(to top,rgba(15,16,18,.88),rgba(15,16,18,.45) 70%,transparent);
  border-left:3px solid var(--action)}
@media(min-width:861px){
  .hs-jobs{grid-template-columns:repeat(4,1fr);grid-auto-rows:225px;grid-auto-flow:dense}
  /* The lead tile: 2x2 whenever there are three or more photos. */
  .hs-jobs:not([data-n="1"]):not([data-n="2"]) figure:first-child{grid-column:span 2;grid-row:span 2}
  .hs-jobs[data-n="1"] figure{grid-column:span 4;grid-row:span 2}
  .hs-jobs[data-n="2"] figure{grid-column:span 2;grid-row:span 2}
  .hs-jobs[data-n="3"] figure:not(:first-child){grid-column:span 2}
  .hs-jobs[data-n="4"] figure:nth-child(4){grid-column:span 2}
}
@media(max-width:860px){
  .hs-jobs{grid-template-columns:1fr 1fr;grid-auto-rows:180px}
  .hs-jobs figure:first-child{grid-column:span 2;grid-row:span 2}
  .hs-jobs[data-n="1"] figure{grid-column:span 2;grid-row:span 2}
  /* After the 2-row lead, tiles pair up - so a last tile at an even
     index would sit beside an empty cell. Give it the full row. */
  .hs-jobs figure:last-child:nth-child(even){grid-column:span 2}
}

/* ================= tactile polish (2026-08-26) =================
   The details that make touch feel native: no gray tap flash, no
   double-tap-zoom delay on controls, buttons settle a pixel on press
   (the lv2 pages had this; the hs system did not), anchor jumps land
   clear of the sticky header, and selection is in the brand red. */
a, button { -webkit-tap-highlight-color: transparent; }
.btn, .mobar a, .mnav__link, .mnav__cta, .mnav-toggle,
.hs-car2__thumb, .hs-car2__nav button, .leadform button { touch-action: manipulation; }
.btn:active { transform: translateY(1px); }
[id] { scroll-margin-top: 96px; }
::selection { background: var(--action); color: #fff; }
/* The thumb rail snaps to whole thumbnails instead of stopping mid-tile,
   and neither it nor the open drawer chains scroll to the page behind. */
.hs-car2__thumbs { scroll-snap-type: x proximity; overscroll-behavior-x: contain; }
.hs-car2__thumb { scroll-snap-align: start; }
.mnav__panel { overscroll-behavior: contain; }

/* ---------------------------------------------------------------------------
   ESTIMATE FORM, 2026-08-26. Wayne: "the estimate in the red sections needs
   to be cleaned up, and for some reason the check box is different than the
   one in the hero."

   Both were the same bug wearing two hats. The hero card got a tightening
   pass on 2026-08-24 (consent at .74rem, tighter legal, tighter fields, short
   textarea) and the base .hs-formcard never did, so the card in the red band
   still rendered the TCPA block at full body size: six lines of compliance
   copy set larger and looser than the fields it belongs to, which made the
   legal text the loudest thing in the form.

   The checkbox was never styled at all. Both cards drew the browser default,
   and a default checkbox renders one way on white and another on #1B1D22, so
   the two forms genuinely did not match. It is drawn explicitly now, one
   shape, one size, one behaviour, with only its ground colour differing.

   The consent WORDING is untouched and must stay untouched: it is the verbatim
   TCPA disclosure Twilio's toll-free verification reads, and it is shared
   across every client site through SmsConsentField. This block is presentation
   only.
   ------------------------------------------------------------------------ */

/* The tightening the hero got, applied to the card itself so both inherit it
   rather than one being a special case. */
.hs-formcard .leadform__field{margin-bottom:.45rem}
.hs-formcard .leadform label{font-size:.8rem}
.hs-formcard .leadform input,.hs-formcard .leadform textarea{padding:.55em .7em;font-size:.95rem}
.hs-formcard .leadform textarea{min-height:2.6em}
.hs-formcard .sms-consent{margin-top:.55rem}
.hs-formcard .sms-consent__text{font-size:.74rem;line-height:1.45}
.hs-formcard .leadform__legal{font-size:.74rem;line-height:1.45;margin-top:.6rem}

/* One checkbox everywhere. Drawn rather than inherited from the user agent,
   because that is what made the hero's and the red band's look unrelated. */
.leadform input.sms-consent__checkbox,
.sms-consent__checkbox{
  appearance:none;-webkit-appearance:none;
  width:17px;height:17px;flex:none;margin:0;padding:0;
  border:1.5px solid rgba(22,24,28,.38);border-radius:3px;
  background:#fff;cursor:pointer;
  display:grid;place-content:center;
  transition:background .15s,border-color .15s;
}
.leadform input.sms-consent__checkbox::before,
.sms-consent__checkbox::before{
  content:"";width:10px;height:10px;background:#fff;
  transform:scale(0);transition:transform .12s ease-out;
  clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0,43% 62%);
}
.leadform input.sms-consent__checkbox:checked,
.sms-consent__checkbox:checked{background:var(--action);border-color:var(--action)}
.leadform input.sms-consent__checkbox:checked::before,
.sms-consent__checkbox:checked::before{transform:scale(1)}
.leadform input.sms-consent__checkbox:focus-visible,
.sms-consent__checkbox:focus-visible{outline:2px solid var(--action);outline-offset:2px}
.leadform input.sms-consent__checkbox:hover,
.sms-consent__checkbox:hover{border-color:var(--action)}

/* Same box on the dark card, tuned to its ground rather than redrawn. */
.hs-formcard--hero .leadform input.sms-consent__checkbox,
.lv2-qcard .leadform input.sms-consent__checkbox{
  background:rgba(244,242,239,.06);border-color:rgba(244,242,239,.32);
}
.hs-formcard--hero .leadform input.sms-consent__checkbox:checked,
.lv2-qcard .leadform input.sms-consent__checkbox:checked{background:var(--action);border-color:var(--action)}

/* The row keeps the box level with the first line of text now that the box has
   a known height, rather than nudging it with a magic margin per card. */
.hs-formcard .sms-consent__row,
.hs-formcard--hero .sms-consent__row{align-items:start;grid-template-columns:17px minmax(0,1fr)}
.hs-formcard .leadform input.sms-consent__checkbox,
.hs-formcard--hero .leadform input.sms-consent__checkbox{margin-top:1px}

/* The submit button sat flush against the last line of the consent block on
   both cards, so the tick box and the red button read as one object. */
.hs-formcard .leadform__submit,
.hs-formcard--hero .leadform__submit{margin-top:.9rem}

/* Zip stopped being an orphan. With no email field it was pushed full width
   under a half-width Name and Phone, which left one lonely box across the
   card. Name takes the top row and Phone and Zip pair underneath: contact,
   then where you are. */
.hs-formcard .leadform:not(:has(input[name="email"])) > .leadform__field:has(input[name="name"]){grid-column:1 / -1}
.hs-formcard .leadform:not(:has(input[name="email"])) > .leadform__field:has(input[name="zip"]){grid-column:auto}

/* ---------------------------------------------------------------------------
   COMPARISON PHOTOGRAPHS, 2026-08-26. Grant sent a matched good-and-bad pair
   and the point of sending them was the contrast, so they belong in the
   comparison the page already runs rather than loose in the gallery.

   His own versions carried a green check mark and a red prohibition circle
   burned over the frames. That is how a comparison gets labelled in a social
   post; here the column heading already does that job, so the photographs go in
   plain and the headings say which is which.

   Edge to edge at the top of each column, which is why the negative margins
   cancel the card padding. Both columns are locked to one aspect ratio: the two
   sources are different shapes, and a comparison whose halves are different
   heights reads as a layout bug rather than as a pair. Square rather than 4:3:
   both of Grant's frames are portrait and both carry a centred mark, and a
   landscape crop cut the marks off.
   ------------------------------------------------------------------------ */
.compare__shot{
  display:block;width:calc(100% + 2 * clamp(1.4rem,2.8vw,2rem));
  margin:calc(-1 * clamp(1.4rem,2.8vw,2rem)) calc(-1 * clamp(1.4rem,2.8vw,2rem)) 1.2rem;
  aspect-ratio:1 / 1;object-fit:cover;object-position:center;
  /* Beats the global img{max-width:100%} on line 199, which was clamping the
     width calc back to the content box and leaving a gap down one side. */
  max-width:none;
  background:var(--surface-2);
}

/* BW-08: a card with no published price. The figure is not missing, it was
   never Grant's. Sized down from .amount because it is a statement, not a
   number, and it should not shout where a price used to. */
.prices .amount--quote,.card .amount--quote{font-size:1rem;font-weight:600;
  color:var(--ink-2);letter-spacing:0;text-transform:none}
.prices > div.is-featured .amount--quote{color:var(--dark-ink-2)}

/* Photo wraps its img in a picture element for the WebP sources.
   display:contents takes the wrapper out of the layout tree so the img stays
   the flex/grid child every rule below already expects. Selectors are NOT
   affected by display:contents, which is why .mediaband's direct-child rule is
   widened in place rather than left to break silently. */
picture { display: contents; }
