/* =========================================================================
   Titan Tow & Repair — design system
   Original stylesheet. Single file, no framework, no build step, ~30KB
   uncompressed so it inlines or ships in one request either way.
   ========================================================================= */

/* ---------- fonts -------------------------------------------------------
   Self-hosted so there is no third-party connection on the critical path.
   Run `npm run assets` to populate /fonts. If the files are absent the
   fallback stack below keeps the page readable and correctly proportioned. */

/* Display face: Archivo (SIL Open Font License 1.1), self-hosted, latin subset.
 *
 * It replaced Instrument Sans because that file's variation axes did not
 * work. Measured in-browser at 80px over a 48-character string: 'wdth' 75
 * rendered 3262px against 3310px at 'wdth' 100 — 1.4%, where a real 75% width
 * axis gives about 25%. 'wght' 400 against 700 differed by 10px in 3320. It
 * behaved as a single static instance, so the eighteen 'wdth'/'wght'
 * declarations in this stylesheet were decorative and the condensed uppercase
 * headings this design is built on never actually condensed.
 *
 * Archivo carries both axes for real — wght 100–900, wdth 62–125 — so those
 * declarations now do what they always said they did. It is a grotesque drawn
 * for signage and high-legibility print, which suits a recovery business.
 *
 * Costs 90 KB against the old 18 KB. That is the price of axes that work; the
 * cheaper file was cheap because it carried almost nothing.
 */
@font-face {
  font-family: 'Archivo';
  src: url('fonts/archivo.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('fonts/ibm-plex-sans.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('fonts/ibm-plex-sans-600.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}

/* ---------- tokens ----------------------------------------------------- */

:root {
  /* surface + ink */
  --concrete: #f1f2ef;
  --white: #ffffff;
  --asphalt: #15181b;
  --steel: #59636b;
  --line: #dcdfd9;
  --line-soft: #c9cec6;
  --surface-sunk: #dde1da;
  --photo-bg: #2a3036;

  /* Role tokens. Everything themeable points at one of these rather than at a
     raw palette entry, so the dark blocks below only have to redefine roles.
     A raw --white or --asphalt that survives is deliberate: white text on a
     green button stays white in both themes. */
  --surface: var(--white);
  --surface-page: var(--concrete);
  --ink: var(--asphalt);
  --header-bg: rgba(241, 242, 239, 0.94);

  /* brand */
  --green: #2fa14d;
  --green-btn: #1b7a38;
  --green-btn-hov: #12602a;
  --green-ink: #177033;
  --green-deep: #0c3218;
  --amber: #f0a227;
  /* Role token for the keyboard focus ring. A role, not a palette entry, so it
     can be retargeted per theme if a surface is ever added that green fails on.
     See the :focus-visible rule for the measured ratios. */
  --focus: var(--green-btn);

  /* Accessible variants. --green on --green-deep measures 4.26:1 and
     --steel on --footer-bg measures 3.13:1 — both under the 4.5:1 WCAG AA
     floor for body-size text. These are the same hues, lifted just far
     enough to pass, and are used only where those pairings occur. */
  --green-on-dark: #3cb45b;
  --ink-on-footer: #78838d;

  /* text tones on light */
  --ink-1: #3a4249;
  --ink-2: #4a5259;
  --ink-3: #525a61;

  /* text tones on dark */
  --ink-inv-1: #c3cad0;
  --ink-inv-2: #b6bec4;
  --ink-inv-3: #aeb7bd;
  --ink-field-1: #d6dcd3;
  --ink-field-2: #c6d0c8;

  --footer-bg: #0d0f11;
  --footer-line: #232b32;

  /* fluid type — min at 360px, max at ~1400px */
  --fs-xs: clamp(12.5px, 0.3vw + 11.6px, 13.5px);
  --fs-sm: clamp(13.5px, 0.34vw + 12.5px, 14.5px);
  --fs-base: clamp(14.5px, 0.44vw + 13.3px, 16px);
  --fs-md: clamp(15.5px, 0.52vw + 14.1px, 17.5px);
  --fs-lg: clamp(16.5px, 0.72vw + 14.6px, 19px);
  --fs-xl: clamp(18px, 1.05vw + 15.2px, 22px);
  --fs-h3: clamp(17.5px, 1.1vw + 14.6px, 22px);
  --fs-h2: clamp(27px, 3.3vw + 14px, 48px);
  --fs-h1: clamp(30px, 3.04vw + 20.3px, 66px);

  --pad: clamp(20px, 5vw, 64px);
  --sec-y: clamp(58px, 7vw, 96px);
  --r: 7px;
  --hdr: 112px;
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);

  --font-d: 'Archivo', 'Segoe UI', system-ui, sans-serif;
  --font-b: 'Plex Sans', 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
}

/* ---------- reset ------------------------------------------------------ */

*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--hdr) + 12px);
}
body {
  margin: 0;
  background: var(--surface-page);
  color: var(--ink);
  font-family: var(--font-b);
  font-size: var(--fs-base);
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img,
svg,
video {
  max-width: 100%;
  display: block;
}
img {
  height: auto;
  background: var(--surface-sunk);
}
figure {
  margin: 0;
}
a {
  color: var(--green-ink);
  text-underline-offset: 3px;
}
ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}
p {
  margin: 0 0 1em;
}
p:last-child {
  margin-bottom: 0;
}
button {
  font: inherit;
  cursor: pointer;
}
/* The keyboard focus ring.
   --amber measured 1.89:1 against the page and 2.12:1 against white cards;
   WCAG 2.1 SC 1.4.11 requires 3:1 for a focus indicator. --focus points at the
   brand green, re-measured clear on every surface a ring can land on: 5.40:1
   white, 4.81:1 light header, 3.33:1 dark page, 3.10:1 dark card, 3.30:1 the
   asphalt bands, 3.55:1 footer. Deliberately NOT --asphalt, which is 1.01:1
   against the dark header and would vanish in dark mode. */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: 2px;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ---------- type ------------------------------------------------------- */

/* Large display. Weight 620, not 700: optical compensation. A face set at one
   weight across a 12px label and a 66px headline is not consistent, it is
   miscalibrated — stem thickness scales with size, so large type carries far
   more visual weight at the same numeric value. Small roles below keep 700.

   `font-weight` stays 700 for the fallback stack only; on Archivo the
   variation setting wins. */
.d {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 100, 'wght' 620;
  font-weight: 700;
  letter-spacing: -0.028em;
  line-height: 0.97;
  text-wrap: balance;
  margin: 0;
}
h1.d {
  font-size: var(--fs-h1);
}
h2.d {
  font-size: var(--fs-h2);
}
h3.d {
  font-size: var(--fs-h3);
  /* Between .d's 620 and the 700 of label-sized roles — h3 sits in the middle
     of the size ramp, so it takes the middle of the weight ramp. */
  font-variation-settings: 'wdth' 96, 'wght' 670;
  line-height: 1.12;
  letter-spacing: -0.024em;
}
/* Uppercase condensed headings — now genuinely condensed, on Archivo's wdth
 * axis. Retuned from the emergency values that were set while the old file's
 * dead axes made this render at full width.
 *
 * Tracking stays POSITIVE. Capitals have no descenders or x-height variation
 * to separate them, and condensing pushes the stems closer still, so uppercase
 * needs air rather than the negative tracking this rule used to carry. That is
 * what made "BAD RIGGING WRECKS LOADS AND HURTS PEOPLE" read as one mass.
 *
 * Weight drops 700 → 640: at up to 48px, condensed capitals at 700 are much
 * heavier on the page than the same weight at label size.
 */
.cond {
  font-variation-settings: 'wdth' 75, 'wght' 640;
  font-stretch: 75%;
  text-transform: uppercase;
  letter-spacing: 0.012em;
  word-spacing: 0.06em;
  line-height: 0.94;
}
.lede {
  font-size: var(--fs-lg);
  color: var(--ink-1);
  max-width: 52ch;
}
.inv .lede,
.close .lede {
  color: var(--ink-inv-1);
}
.eyebrow {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 90, 'wght' 700;
  font-size: var(--fs-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--green-ink);
  display: block;
  margin-bottom: 14px;
}
.inv .eyebrow,
.field .eyebrow,
.close .eyebrow {
  color: var(--green-on-dark);
}

/* Photo-filled section headings. The gradient darkens the photo so the letter
   forms stay legible; @supports keeps solid ink for engines that cannot clip. */
.d.fill,
.d.fill-b {
  color: var(--ink);
}
@supports (-webkit-background-clip: text) or (background-clip: text) {
  .d.fill,
  .d.fill-b {
    background-image: linear-gradient(rgba(13, 16, 18, 0.66), rgba(13, 16, 18, 0.66)),
      var(--fill-img, url('img/web/wrecker-s-400.webp'));
    background-size: auto, 118%;
    background-position: 0 0, 44% 40%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
  }
  .d.fill-b {
    --fill-img: url('img/web/flatbed-container-400.webp');
    background-size: auto, 112%;
    background-position: 0 0, 48% 44%;
  }
}

/* ---------- layout ----------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: var(--pad);
}
.sec {
  padding-block: var(--sec-y);
}
.sec-alt {
  background: var(--surface);
}
.sec-head {
  max-width: 68ch;
  margin-bottom: clamp(30px, 3.6vw, 52px);
}
.sec-head.mid {
  margin-inline: auto;
  text-align: center;
}
.sec-head .lede {
  margin-top: 18px;
}
.sec-head.mid .lede {
  margin-inline: auto;
}
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--asphalt);
  color: var(--white);
  padding: 12px 18px;
  z-index: 200;
  border-radius: 0 0 var(--r) 0;
}
.skip:focus {
  left: 0;
}

/* ---------- header ----------------------------------------------------- */

header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--header-bg);
  /* -webkit- prefix is still required by iOS Safari — a large share of
     "truck broken down" traffic. The rgba background is near-opaque, so the
     unprefixed-only version degrades quietly rather than breaking. */
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.hd {
  display: flex;
  align-items: center;
  gap: 24px;
  min-height: var(--hdr);
}
.logo {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  margin-right: auto;
}
.logo img {
  height: 78px;
  width: auto;
  background: none;
  transition: transform 0.28s var(--ease);
}
.logo:hover img {
  transform: scale(1.05);
}
.logo-txt {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 80, 'wght' 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  line-height: 0.92;
  font-size: 20px;
  display: none;
}
.logo-txt small {
  display: block;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  color: var(--steel);
  font-variation-settings: 'wdth' 100, 'wght' 600;
}
nav.main {
  display: flex;
  align-items: center;
}
.navlist {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.6vw, 26px);
  list-style: none;
  margin: 0;
  padding: 0;
}
.navitem {
  position: relative;
}
.navitem.has-menu {
  display: flex;
  align-items: center;
  gap: 3px;
}
nav.main a {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  padding: 6px 0;
  position: relative;
}
nav.main a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--green);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.28s var(--ease);
}
nav.main a:hover::after,
nav.main a[aria-current='page']::after {
  transform: scaleX(1);
}

/* ---------- nav dropdowns ----------------------------------------------
   Opening is CSS-first so hover and keyboard both work without JavaScript.
   The panel is hidden with `visibility`, not `display` or opacity alone:
   visibility removes it from the accessibility tree, so a screen reader is
   never offered seventeen links that are not on screen, and it still allows
   the transition that `display` would kill. */

.navtoggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.navtoggle svg {
  width: 15px;
  height: 15px;
  stroke: currentColor;
  stroke-width: 2.1;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.24s var(--ease);
}
.navitem.open > .navtoggle svg {
  transform: rotate(180deg);
}
.navtoggle:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}

.submenu {
  position: absolute;
  top: 100%;
  left: -14px;
  z-index: 80;
  min-width: 232px;
  margin: 0;
  padding: 8px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: 0 24px 38px -26px rgba(0, 0, 0, 0.55);
  visibility: hidden;
  opacity: 0;
  transform: translateY(-6px);
  /* `0s linear 0.18s` is a DELAY, not a duration. Transitioning visibility
     over time leaves its computed value at `hidden` on the frame the menu
     opens, and a hidden element cannot take focus — so ArrowDown would depend
     on a frame having been painted first. As a delay, visibility flips
     instantly on open and only waits for the fade on the way out. */
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0s linear 0.18s;
}
/* Bridges the gap between the nav item and the panel. Without it the pointer
   crosses dead space on the way down and the menu closes underneath it. */
.submenu::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: -10px;
  height: 10px;
}
.submenu-wide {
  min-width: 380px;
  columns: 2;
  column-gap: 4px;
}
.submenu li {
  break-inside: avoid;
}
nav.main .submenu a {
  display: block;
  padding: 8px 10px;
  border-radius: 5px;
  font-weight: 500;
  line-height: 1.3;
}
nav.main .submenu a::after {
  display: none;
}
nav.main .submenu a:hover,
nav.main .submenu a:focus-visible {
  background: var(--surface-page);
  color: var(--green-ink);
}
nav.main .submenu a[aria-current='page'] {
  color: var(--green-ink);
  font-weight: 700;
}
/* Keyboard: focus anywhere inside the item opens it, with no JS required. */
.navitem.open > .submenu,
.navitem.has-menu:focus-within > .submenu {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition-delay: 0s;
}
/* Hover opening is gated to real pointers. A touch device reports
   `hover: none`, so tapping the parent link navigates as it always did and
   the panel is reached through the disclosure button instead. */
@media (hover: hover) and (pointer: fine) {
  .navitem.has-menu:hover > .submenu {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition-delay: 0s;
  }
  /* Gated with the panel it describes: on a touch screen :hover sticks after
     a tap, which would leave the chevron pointing up at a closed menu. */
  .navitem.has-menu:hover > .navtoggle svg {
    transform: rotate(180deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .submenu,
  .navtoggle svg {
    transition: none;
  }
}

.navcta {
  display: flex;
  gap: 10px;
  align-items: center;
}
/* Theme toggle. Sized to match .burger so the two header controls line up.
   Exactly one icon is ever shown: the one for the theme you would GET by
   pressing it. The visibility rules mirror the token cascade below — bare
   :root is light, so the moon shows by default; the media query flips to the
   sun only when no explicit choice overrides it; the [data-theme] rules win
   over both. */
.themetog {
  width: 42px;
  height: 42px;
  flex: none;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  padding: 0;
  transition: border-color 0.24s, background 0.24s;
}
.themetog:hover {
  border-color: var(--ink);
  background: var(--surface-sunk);
}
.themetog:focus-visible {
  outline: 2px solid var(--green-btn);
  outline-offset: 2px;
}
.themetog svg {
  width: 19px;
  height: 19px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Light is the default state, so offer dark: show the moon, hide the sun. */
.themetog .ti-sun {
  display: none;
}

:root[data-theme='dark'] .themetog .ti-sun {
  display: block;
}
:root[data-theme='dark'] .themetog .ti-moon {
  display: none;
}
:root[data-theme='light'] .themetog .ti-sun {
  display: none;
}
:root[data-theme='light'] .themetog .ti-moon {
  display: block;
}

.burger {
  display: none;
  width: 46px;
  height: 42px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  background: transparent;
  position: relative;
}
.burger span,
.burger span::before,
.burger span::after {
  position: absolute;
  left: 12px;
  right: 12px;
  height: 2px;
  /* Role token, not the raw palette entry. --asphalt is never redefined in the
     dark block, so these bars rendered #15181b on a #14171a header — 1.01:1,
     an invisible menu button on every mobile page in dark mode. --ink is what
     .themetog already uses and it flips to #e7ebee for dark. */
  background: var(--ink);
  content: '';
  transition: transform 0.28s var(--ease), top 0.2s, bottom 0.2s, background 0.2s;
}
.burger span {
  top: 50%;
  margin-top: -1px;
}
.burger span::before {
  top: -7px;
  left: 0;
  right: 0;
}
.burger span::after {
  bottom: -7px;
  left: 0;
  right: 0;
}
header.open .burger span {
  background: transparent;
}
header.open .burger span::before {
  top: 0;
  transform: rotate(45deg);
}
header.open .burger span::after {
  bottom: 0;
  transform: rotate(-45deg);
}

/* ---------- buttons ---------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 19px;
  border-radius: var(--r);
  border: 1px solid transparent;
  /* Explicit, because a <button class="btn"> otherwise inherits the UA's
     ButtonFace. That was invisible while the page was light-only; declaring
     color-scheme: dark repainted ButtonFace mid-grey and dropped the map
     button to 4.45:1. Variants that want a fill set their own. */
  background: transparent;
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  transition: background 0.24s, color 0.24s, transform 0.28s var(--ease), box-shadow 0.28s;
  white-space: nowrap;
}
.btn svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.28s var(--ease);
}
.btn:hover svg {
  transform: translateX(3px);
}
.btn-p {
  background: var(--green-btn);
  color: var(--white);
}
.btn-p:hover {
  background: var(--green-btn-hov);
  transform: translateY(-2px);
  box-shadow: 0 10px 22px -12px rgba(27, 122, 56, 0.9);
}
.btn-s {
  border-color: var(--ink);
  color: var(--ink);
}
.btn-s:hover {
  background: var(--asphalt);
  color: var(--white);
  transform: translateY(-2px);
}
.inv .btn-s,
.close .btn-s,
.field .btn-s {
  border-color: rgba(255, 255, 255, 0.55);
  color: var(--white);
}
.inv .btn-s:hover,
.close .btn-s:hover,
.field .btn-s:hover {
  background: var(--surface);
  color: var(--ink);
}
.btn-l {
  background: var(--surface);
  color: var(--ink);
}
.btn-l:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 26px -14px rgba(0, 0, 0, 0.7);
}
.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.clink {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--green-ink);
  text-decoration: none;
  border-bottom: 1px solid rgba(23, 112, 51, 0.32);
  padding-bottom: 2px;
  transition: gap 0.24s var(--ease), border-color 0.24s;
}
.clink svg {
  width: 15px;
  height: 15px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.clink:hover {
  gap: 11px;
  border-color: var(--green-ink);
}
.inv .clink,
.close .clink,
.field .clink {
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.35);
}

/* ---------- hero ------------------------------------------------------- */

.hero {
  padding-block: clamp(38px, 5vw, 78px) clamp(46px, 6vw, 84px);
}
.hero-grid {
  display: grid;
  /* 1.42fr left the photo at 455px on a 1228px wrap while the text column ran
     626px with a 418px lede inside it — measured. Both columns were leaving
     room unused. 1.28fr gives the photo ~40px more and costs the headline
     nothing, because the headline is now sized to fill what it has. */
  grid-template-columns: minmax(0, 1.28fr) minmax(0, 1fr);
  gap: clamp(28px, 3vw, 40px);
  align-items: center;
}

/* ---------- hero scale ----------------------------------------------------
   MEASURED 2026-08-23, home page at 1243x838:

     text column   626px wide, 274px tall
     lede          capped at 44ch = 418px inside that 626px column
     h1            58px
     hero total    348px of an 838px viewport

   Two thirds of the fold was empty and the lede was breaking a third of the
   way across its own column. The type scale was not wrong — --fs-h1 is shared
   with 46 other pages and is right for them — so the hero gets its own scale
   rather than the token being pushed up everywhere.

   The floor stays near the old mobile value on purpose: the phone layout was
   not the problem and is not being changed to fix a desktop one. */
.hero h1 {
  font-size: clamp(32px, 4.4vw + 10px, 84px);
  letter-spacing: -0.032em;
}
.hero-txt .lede {
  margin: 24px 0 32px;
  /* 44ch -> 54ch. At 44ch the lede wrapped after "roadside" and left ~200px of
     the column empty beside it; 54ch still sits well inside the 45-75ch
     comfortable-measure range. */
  max-width: 54ch;
  font-size: clamp(15.5px, 0.55vw + 13.6px, 20px);
}
.hero h1 .l2 {
  display: block;
}
.plate {
  position: relative;
  z-index: 2;
  transform: rotate(-2.4deg);
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: 0 34px 70px -28px rgba(21, 24, 27, 0.55);
  background: var(--photo-bg);
}
.plate img {
  width: 100%;
  /* 28vw put the photo at 366px against a 274px text column and an 838px
     viewport — the tallest thing in the hero and still only 44% of the fold.
     34vw fills the row without pushing the answer block below the fold. */
  height: clamp(300px, 34vw, 620px);
  object-fit: cover;
  object-position: 52% 50%;
  transition: transform 1.2s var(--ease);
}
.plate:hover img {
  transform: scale(1.03);
}

/* AEO: the direct-answer block. Deliberately the first prose an extractor
   meets after the H1, 40–60 words, self-contained, no pronouns pointing
   back at the heading. */
.answer {
  /* Top rule rather than a left tab: the reference's whole border vocabulary
     is horizontal (.klist li, .step, .strip, .marquee all use border-top), so
     this sits inside the theme instead of importing a different idiom. */
  border-top: 2px solid var(--asphalt);
  padding: 20px 0 0;
  font-size: var(--fs-md);
  color: var(--ink-1);
  max-width: 74ch;
  position: relative;
}
.answer::before {
  content: '';
  position: absolute;
  top: -2px;
  left: 0;
  width: 64px;
  height: 2px;
  background: var(--green);
}
.answer strong {
  color: var(--ink);
}

/* ---------- tapered dark band + stat strip ----------------------------- */

.taper {
  position: relative;
  background: var(--asphalt);
  color: var(--white);
  clip-path: polygon(0 46px, 100% 0, 100% 100%, 0 100%);
  margin-top: -46px;
  padding-block: clamp(64px, 7vw, 100px) clamp(38px, 4vw, 58px);
}
.taper::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 3px;
  background: var(--green);
  transform: rotate(-1.35deg);
  transform-origin: 0 0;
}
.inv h2.d,
.inv h3.d,
.inv .d {
  color: var(--white);
}
.strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.strip > div {
  padding: 30px 26px 10px;
  border-right: 1px solid rgba(255, 255, 255, 0.14);
}
.strip > div:first-child {
  padding-left: 0;
}
.strip > div:last-child {
  border-right: 0;
  padding-right: 0;
}
.strip .k {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 96, 'wght' 700;
  font-size: var(--fs-xl);
  color: var(--white);
  letter-spacing: -0.02em;
  line-height: 1.05;
  display: block;
  white-space: nowrap;
}
.strip .k.amb {
  color: var(--amber);
}
.strip p {
  margin: 9px 0 0;
  font-size: var(--fs-sm);
  color: var(--ink-inv-2);
  max-width: 26ch;
}

/* ---------- cards ------------------------------------------------------ */

.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 31px);
}
.grid-4 {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 21px);
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 31px);
}
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform 0.34s var(--ease), box-shadow 0.34s var(--ease), border-color 0.3s;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 22px 40px -26px rgba(21, 24, 27, 0.55);
  border-color: var(--line-soft);
}
.card > figure {
  overflow: hidden;
  background: var(--photo-bg);
}
.card > figure img {
  width: 100%;
  height: 200px;
  object-fit: cover;
  transition: transform 0.9s var(--ease);
}
.card:hover > figure img {
  transform: scale(1.045);
}
.card-b {
  padding: 24px 24px 26px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}
.card-b p {
  color: var(--ink-2);
  font-size: var(--fs-sm);
  flex: 1;
  margin: 0;
}
.card-b .clink {
  align-self: flex-start;
  margin-top: 4px;
}
.sec-alt .card {
  background: var(--surface-page);
}

/* ---------- icon lists ------------------------------------------------- */

.klist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px) clamp(20px, 3vw, 44px);
}
.klist-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.klist li {
  border-top: 1px solid var(--line-soft);
  padding-top: 18px;
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 16px;
  align-items: start;
  transition: border-color 0.3s;
}
.klist li:hover {
  border-top-color: var(--ink);
}
.inv .klist li,
.field .klist li {
  border-top-color: rgba(255, 255, 255, 0.22);
}
.field .klist li:hover {
  border-top-color: var(--white);
}
.klist b {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 96, 'wght' 700;
  font-size: var(--fs-md);
  letter-spacing: -0.02em;
  display: block;
  margin-bottom: 3px;
}
.inv .klist b,
.field .klist b {
  color: var(--white);
}
.klist .s {
  color: var(--ink-2);
  font-size: var(--fs-sm);
}
.inv .klist .s {
  color: var(--ink-inv-2);
}
.field .klist .s {
  color: var(--ink-field-2);
}
.tile {
  width: 48px;
  height: 48px;
  border-radius: var(--r);
  background: rgba(47, 161, 77, 0.13);
  display: grid;
  place-items: center;
  transition: transform 0.3s var(--ease), background 0.3s;
}
.tile svg {
  width: 24px;
  height: 24px;
  stroke: var(--green-ink);
  stroke-width: 1.7;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.inv .tile,
.field .tile {
  background: rgba(255, 255, 255, 0.14);
}
.inv .tile svg,
.field .tile svg {
  stroke: var(--white);
}
.klist li:hover .tile {
  transform: translateY(-3px) rotate(-4deg);
  background: rgba(47, 161, 77, 0.24);
}
.field .klist li:hover .tile {
  background: rgba(255, 255, 255, 0.24);
}

/* ---------- split / bleed band ----------------------------------------- */

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(26px, 4vw, 64px);
  align-items: center;
}
.stack {
  display: grid;
  gap: 16px;
}
.stack img {
  border-radius: var(--r);
  width: 100%;
  object-fit: cover;
  background: var(--photo-bg);
}
.stack .s1 {
  height: clamp(180px, 20vw, 272px);
}
.stack .s2 {
  height: clamp(130px, 14vw, 182px);
}

/* ---------- green field band ------------------------------------------- */

.field {
  background: var(--green-deep);
  color: var(--ink-field-1);
  position: relative;
  overflow: hidden;
  padding-block: clamp(58px, 7vw, 104px);
  --photoW: clamp(240px, 36vw, 560px);
}
.field::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--green);
  clip-path: polygon(54% 0, 100% 0, 100% 44%, 74% 0);
  z-index: 1;
}
.field::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 6px;
  background: var(--green);
}
.field .wrap {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) max(0px, calc(var(--photoW) - max(0px, (100vw - 1240px) / 2) + 40px));
}
.field .wrap > * {
  grid-column: 1;
  max-width: 100%;
}
.field h2 {
  color: var(--white);
  max-width: 16ch;
}
.field .lede {
  color: var(--ink-field-1);
  margin-top: 20px;
}
.field .klist {
  margin-top: clamp(28px, 3vw, 42px);
}
.field .cta-row {
  margin-top: 30px;
}
.field-photo {
  position: absolute;
  inset: 0 0 0 auto;
  width: var(--photoW);
  z-index: 0;
  overflow: hidden;
  margin: 0;
}
.field-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 34% 52%;
  filter: saturate(0.85) contrast(1.05);
}
.field-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--green-deep) 0%, rgba(12, 50, 24, 0.9) 30%, rgba(12, 50, 24, 0.5) 100%);
}

/* ---------- steps ------------------------------------------------------ */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 31px);
}
.step {
  border-top: 2px solid var(--asphalt);
  padding-top: 20px;
}
.step-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 18px;
}
.step .n {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 75, 'wght' 700;
  font-size: clamp(38px, 3.4vw, 52px);
  line-height: 0.8;
  color: var(--green);
  display: block;
  transition: transform 0.3s var(--ease);
}
.step:hover .n {
  transform: translateY(-3px);
}
.step .tile {
  width: 52px;
  height: 52px;
}
.step .tile svg {
  width: 26px;
  height: 26px;
}
.step:hover .tile {
  transform: translateY(-3px) rotate(4deg);
  background: rgba(47, 161, 77, 0.24);
}
.step p {
  color: var(--ink-2);
  font-size: var(--fs-sm);
  margin: 8px 0 0;
}

/* ---------- coverage + marquee ----------------------------------------- */

.cover {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.towns {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
}
.towns a,
.towns span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border: 1px solid var(--line-soft);
  border-radius: 100px;
  background: var(--surface);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  transition: background 0.24s, color 0.24s, transform 0.24s var(--ease), border-color 0.24s;
}
.towns a::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--green);
}
.towns a:hover {
  background: var(--asphalt);
  border-color: var(--ink);
  color: var(--white);
  transform: translateY(-2px);
}
.towns span {
  color: var(--ink-3);
  font-weight: 400;
  background: transparent;
}
.marquee {
  margin-top: clamp(32px, 4vw, 52px);
  overflow: hidden;
  position: relative;
  padding-block: 14px;
  border-block: 1px solid var(--line);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: townscroll 42s linear infinite;
  will-change: transform;
}
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track {
  animation-play-state: paused;
}
.marquee a {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 82, 'wght' 700;
  text-transform: uppercase;
  font-size: var(--fs-lg);
  /* Positive, for the same reason as .cond: the 'wdth' 82 above does nothing,
     and negative tracking on uppercase city names ran them together —
     "PLATTE CITY" was reading as "PLATTECITY". */
  letter-spacing: 0.02em;
  word-spacing: 0.1em;
  color: var(--steel);
  text-decoration: none;
  padding-inline: 20px;
  white-space: nowrap;
  transition: color 0.24s;
}
.marquee a:hover {
  color: var(--green-ink);
}
.marquee .dot {
  color: var(--green);
}
@keyframes townscroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* ---------- find us ---------------------------------------------------- */

.findus {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 40px);
  align-items: stretch;
}
.mapwrap {
  border-radius: var(--r);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--surface-sunk);
  min-height: 340px;
}
.mapwrap iframe {
  width: 100%;
  height: 100%;
  min-height: 340px;
  border: 0;
  display: block;
}
.mapfacade {
  min-height: 340px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: clamp(24px, 3vw, 36px);
  background: repeating-linear-gradient(
      45deg,
      transparent 0 14px,
      rgba(89, 99, 107, 0.055) 14px 15px
    ),
    var(--surface-sunk);
}
.mapfacade .s {
  font-size: var(--fs-sm);
  color: var(--steel);
  margin: 0;
}
.mapfacade .tiny {
  font-size: var(--fs-xs);
  max-width: 46ch;
}
.findcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(24px, 3vw, 34px);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.sec-alt .findcard {
  background: var(--surface-page);
}
.findrow {
  display: grid;
  grid-template-columns: 108px 1fr;
  gap: 12px;
  padding-block: 12px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm);
}
.findrow dt {
  color: var(--steel);
  font-weight: 600;
}
.findrow dd {
  margin: 0;
  color: var(--ink);
}
.findrow dd a {
  color: var(--green-ink);
  font-weight: 600;
  text-decoration: none;
}
.findrow dd a:hover {
  text-decoration: underline;
}
.dirbtns {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: auto;
}
.addr {
  font-style: normal;
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 96, 'wght' 700;
  font-size: var(--fs-md);
  line-height: 1.35;
  letter-spacing: -0.02em;
}

/* ---------- fleet units ------------------------------------------------ */

.unit {
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--surface);
  transition: transform 0.34s var(--ease), box-shadow 0.34s var(--ease);
}
.sec-alt .unit {
  background: var(--surface-page);
}
.unit:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 36px -24px rgba(21, 24, 27, 0.5);
}
.unit img {
  width: 100%;
  height: 160px;
  object-fit: cover;
  background: var(--photo-bg);
}
.unit-b {
  padding: 18px 20px 22px;
}
.unit-b p {
  color: var(--ink-2);
  font-size: var(--fs-sm);
  margin: 8px 0 0;
}

/* ---------- reviews ---------------------------------------------------- */

.proof {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(22px, 3vw, 46px);
  align-items: center;
}
.score {
  text-align: center;
}
.score b {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 82, 'wght' 700;
  font-size: clamp(52px, 6vw, 88px);
  line-height: 0.86;
  display: block;
  letter-spacing: -0.04em;
}
.score .s {
  font-size: var(--fs-sm);
  color: var(--steel);
  display: block;
  margin-top: 6px;
}
.stars {
  color: var(--amber);
  letter-spacing: 3px;
  font-size: 18px;
  line-height: 1;
  margin-top: 10px;
}
.quotes-wrap {
  margin-top: clamp(34px, 4vw, 54px);
}
.quotes {
  display: flex;
  gap: clamp(16px, 2vw, 24px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 14px;
  scrollbar-width: thin;
}
.rev {
  flex: 0 0 min(400px, 84vw);
  scroll-snap-align: start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.sec-alt .rev {
  background: var(--surface-page);
}
.rev-top {
  display: flex;
  align-items: center;
  gap: 12px;
}
.rev-top img {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 44px;
}
.rev-who b {
  display: block;
  font-size: var(--fs-sm);
}
.rev-who span {
  font-size: var(--fs-xs);
  color: var(--steel);
}
.rev p {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  flex: 1;
  margin: 0;
}
.rev .stars {
  margin: 0;
  font-size: 14px;
}
.qnav {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 16px;
}
.qbtn {
  width: 42px;
  height: 42px;
  border-radius: var(--r);
  border: 1px solid var(--line-soft);
  background: transparent;
  display: grid;
  place-items: center;
  transition: background 0.24s, color 0.24s, transform 0.24s var(--ease);
}
.qbtn svg {
  width: 18px;
  height: 18px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.qbtn:hover {
  background: var(--asphalt);
  color: var(--white);
}
.qhint {
  font-size: var(--fs-xs);
  color: var(--steel);
  margin-left: auto;
}

/* ---------- FAQ -------------------------------------------------------- */

.faq {
  max-width: 860px;
  margin-inline: auto;
}
.faq details {
  border-bottom: 1px solid var(--line-soft);
  position: relative;
}
.faq summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 22px 14px 22px 0;
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 96, 'wght' 700;
  font-size: var(--fs-h3);
  letter-spacing: -0.017em;
  transition: color 0.24s;
}
/* The question text slides right on hover. Done with transform on the label
   rather than padding on the <summary>: identical result (the icon is
   margin-left:auto so it never moved anyway), but it runs on the compositor
   instead of forcing a layout pass on every frame. */
.faq summary .q {
  display: block;
  transition: transform 0.3s var(--ease);
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary::before {
  content: '';
  position: absolute;
  left: 0;
  top: 14px;
  bottom: 14px;
  width: 3px;
  background: var(--green);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform 0.3s var(--ease);
}
.faq summary:hover .q,
.faq details[open] summary .q {
  transform: translateX(18px);
}
.faq summary:hover::before,
.faq details[open] summary::before {
  transform: scaleY(1);
}
.faq details[open] summary {
  color: var(--green-ink);
}
.faq .ic {
  flex: 0 0 44px;
  height: 44px;
  border-radius: var(--r);
  background: var(--asphalt);
  display: grid;
  place-items: center;
  margin-left: auto;
  transition: background 0.25s, transform 0.35s var(--ease);
}
.faq .ic svg {
  width: 19px;
  height: 19px;
  stroke: var(--white);
  stroke-width: 2.2;
  fill: none;
  stroke-linecap: round;
}
.faq details[open] .ic {
  background: var(--green-btn);
  transform: rotate(90deg);
}
.faq details[open] .ic svg line:last-child {
  transform: scaleY(0);
  transform-origin: center;
}
.faq .ans {
  padding: 0 60px 26px 18px;
  color: var(--ink-2);
  max-width: 72ch;
}

/* ---------- blog ------------------------------------------------------- */

.meta {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 90, 'wght' 700;
  font-size: var(--fs-xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--green-ink);
}
.card-b h2 a {
  color: inherit;
  text-decoration: none;
}
.card:hover .card-b h2 a {
  color: var(--green-ink);
}
.postmeta {
  margin-top: 22px;
  font-size: var(--fs-sm);
  color: var(--steel);
}
article .prose {
  max-width: 68ch;
}
article .prose p {
  font-size: var(--fs-md);
}

/* ---------- prose (city + service body copy) --------------------------- */

.prose {
  max-width: 72ch;
}
.prose h2 {
  margin-top: clamp(34px, 4vw, 52px);
  margin-bottom: 16px;
}
.prose h3 {
  margin-top: clamp(24px, 3vw, 34px);
  margin-bottom: 10px;
}
.prose > :first-child {
  margin-top: 0;
}
.prose p,
.prose li {
  color: var(--ink-2);
}
.prose ul {
  list-style: disc;
  padding-left: 22px;
  margin: 0 0 1em;
}
.prose ul li {
  margin-bottom: 8px;
}
.prose a {
  font-weight: 600;
}

/* facts table — dense, extractable, the shape answer engines quote */
.facts {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
  margin: 24px 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.sec-alt .facts {
  background: var(--surface-page);
}
.facts caption {
  text-align: left;
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
  padding-bottom: 10px;
  font-weight: 600;
}
.facts th,
.facts td {
  text-align: left;
  padding: 12px 16px;
  border-top: 1px solid var(--line);
  vertical-align: top;
}
.facts tr:first-child th,
.facts tr:first-child td {
  border-top: 0;
}
.facts th {
  color: var(--steel);
  font-weight: 600;
  width: 38%;
  white-space: nowrap;
}

/* ---------- breadcrumbs ------------------------------------------------ */

.crumbs {
  padding-top: 22px;
  font-size: var(--fs-xs);
  color: var(--steel);
}
.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.crumbs li::after {
  content: '/';
  margin-left: 8px;
  color: var(--line-soft);
}
.crumbs li:last-child::after {
  content: '';
}
.crumbs a {
  color: var(--steel);
  text-decoration: none;
}
.crumbs a:hover {
  color: var(--green-ink);
  text-decoration: underline;
}

/* ---------- page hero (interior pages) --------------------------------- */

.phero {
  padding-block: clamp(26px, 3vw, 44px) clamp(34px, 4vw, 56px);
}
.phero .lede {
  margin-top: 20px;
}
.phero .cta-row {
  margin-top: 28px;
}
.phero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: clamp(26px, 3.5vw, 48px);
  align-items: center;
}
.phero-photo {
  border-radius: var(--r);
  overflow: hidden;
  background: var(--photo-bg);
  box-shadow: 0 28px 56px -30px rgba(21, 24, 27, 0.5);
}
.phero-photo img {
  width: 100%;
  height: clamp(240px, 26vw, 420px);
  object-fit: cover;
}

/* ---------- closing CTA + footer --------------------------------------- */

.close {
  background: var(--asphalt);
  color: var(--white);
  padding-block: clamp(60px, 7.5vw, 104px) clamp(52px, 6vw, 80px);
}
.close h2 {
  color: var(--white);
}
.close .lede {
  margin: 20px 0 30px;
}
.close-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}
.dial {
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--r);
  padding: clamp(22px, 3vw, 32px);
  display: grid;
  gap: 14px;
}
.dial .num {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 88, 'wght' 700;
  font-size: clamp(26px, 3vw, 38px);
  letter-spacing: -0.03em;
  color: var(--white);
  text-decoration: none;
  line-height: 1;
}
.dial .num:hover {
  color: var(--green);
}
.dial .s {
  font-size: var(--fs-sm);
  color: var(--ink-inv-2);
}

footer {
  background: var(--footer-bg);
  color: var(--ink-inv-3);
  padding-block: clamp(44px, 5vw, 60px) 32px;
  font-size: var(--fs-sm);
}
.fgrid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr 1fr;
  gap: clamp(24px, 3vw, 40px);
}
footer h3 {
  font-family: var(--font-d);
  font-variation-settings: 'wdth' 84, 'wght' 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: var(--fs-xs);
  color: var(--white);
  margin: 0 0 14px;
}
.fcol ul li {
  margin-bottom: 9px;
}
footer a {
  color: var(--ink-inv-3);
  text-decoration: none;
  transition: color 0.22s;
}
footer a:hover {
  color: var(--white);
}
footer .logo img {
  height: 96px;
}
footer address {
  font-style: normal;
  line-height: 1.7;
}
.fbar {
  border-top: 1px solid var(--footer-line);
  margin-top: clamp(30px, 4vw, 44px);
  padding-top: 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px 24px;
  align-items: center;
  justify-content: space-between;
  font-size: var(--fs-xs);
  color: var(--ink-on-footer);
}
.fbar nav {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}
/* Build credit. Inherits the legal bar's type and muted ink so it reads as
   the same tier as the copyright line rather than competing with it. Given
   the whole row on wide screens so it does not fight the legal links for the
   space between the two ends of a space-between layout. */
.credit {
  flex-basis: 100%;
  color: var(--ink-on-footer);
}
.credit a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--footer-line);
}
.credit a:hover,
.credit a:focus-visible {
  color: var(--white);
  border-color: currentColor;
}

/* ---------- mobile call bar -------------------------------------------- */

.callbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  display: none;
  /* Brand green — the same --green-btn as the header and hero call buttons,
     so the bar reads as the same action rather than as chrome. White on this
     green measures 5.4:1, clear of AA for body text and well clear of the
     3:1 large-text threshold the digits actually fall under. */
  background: var(--green-btn);
  border-top: 1px solid rgba(0, 0, 0, 0.22);
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  gap: 10px;
}
/* The number is the whole bar. Sized off the viewport so it stays large on a
   320px phone without overflowing one — at 375px this lands near 30px, which
   is roughly double the button label it replaced. `nowrap` keeps the digits on
   one line; the bar is the last thing that should reflow. */
/* The "Tap to call" kicker above the digits.
   The template has always emitted <span class="callbar-lbl">, and no rule ever
   matched it — so it inherited .callbar-num's display type and rendered at the
   same ~29px as the number, producing "Tap to call(816) 888-8732" as one
   unbroken run of display type on every mobile page. Same kicker treatment
   .lp-kicker uses on the landing pages, so the two bars read alike. */
.callbar-lbl {
  display: block;
  font-family: var(--font-b);
  font-variation-settings: normal;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.2;
  opacity: 0.92;
}
.callbar-num {
  display: block;
  flex: 1;
  text-align: center;
  font-family: var(--font-d);
  /* 640 — heavier than the closing number because it is far smaller, but well
     below the old 800, which the previous face clamped to 700 anyway. */
  font-variation-settings: 'wdth' 86, 'wght' 640;
  /* Floor is 23px, not 26px: at 320px the digits measured exactly the width of
     the bar with zero slack, so a fallback font rendering a hair wider would
     clip them. */
  font-size: clamp(23px, 8vw, 38px);
  line-height: 1.05;
  letter-spacing: -0.03em;
  white-space: nowrap;
  color: var(--white);
  text-decoration: none;
  padding-block: 10px;
  transition: color 0.15s ease;
}
/* Feedback colours flip now the bar is green: the old --green highlight would
   vanish into its own background. */
.callbar-num:active {
  color: rgba(255, 255, 255, 0.72);
}
.callbar-num:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 2px;
  border-radius: 5px;
}
@media (prefers-reduced-motion: reduce) {
  .callbar-num {
    transition: none;
  }
}

/* ---------- responsive -------------------------------------------------- */

@media (max-width: 1080px) {
  .fgrid {
    grid-template-columns: 1fr 1fr;
  }
  .grid-4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 960px) {
  :root {
    --hdr: 84px;
  }
  .logo img {
    height: 60px;
  }
  .burger {
    display: block;
    order: 3;
  }
  nav.main {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--surface-page);
    border-bottom: 1px solid var(--line);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px var(--pad) 20px;
    box-shadow: 0 22px 34px -26px rgba(0, 0, 0, 0.5);
    /* The panel scrolls itself. With a submenu expanded it grows taller than
       the viewport, and because it is absolutely positioned the page behind it
       cannot scroll it into view — the bottom of the menu was simply
       unreachable on a phone. dvh, not vh, so the mobile browser chrome
       collapsing does not change the available height mid-scroll. */
    max-height: calc(100dvh - var(--hdr));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  header.open nav.main {
    display: flex;
  }
  nav.main a {
    padding: 14px 0;
    border-bottom: 1px solid var(--line);
    font-size: var(--fs-md);
  }
  nav.main a::after {
    display: none;
  }
  /* Inside the burger panel the dropdown stops being a dropdown: it is a
     nested list that expands in place. `display` rather than `visibility`
     here, so the collapsed rows take no vertical space — and so the
     :focus-within rule above cannot spring it open while the visitor is
     tabbing down the panel. */
  .navlist {
    flex: 1;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  /* Every row fills the panel, not just the ones with a dropdown.
     Left inline, a plain nav link is only as wide as its text — which made
     "FAQ" a 30px tap target next to a 288px "Services", and left the divider
     rules as stubs under the words instead of spanning the row. Applying the
     flex row to every .navitem rather than only .has-menu fixes the target
     size and the rules together. */
  /* `.navitem.has-menu` is also listed so this beats the desktop rule's
     `gap: 3px` on specificity — a media query adds none, so plain `.navitem`
     would lose. That 3px falls between the link's bottom rule and the
     button's, breaking the divider just before the chevron. */
  /* `align-items: stretch`, not `center`: the link and its chevron each draw
     their own half of the row's bottom rule, and centring left the 44px
     button 6px above the 55px link, so the divider rendered as two offset
     segments and read as a broken line. Stretching puts both borders on the
     same baseline.
     `.navitem.has-menu` is listed too so this beats the desktop rule's
     `gap: 3px` on specificity — a media query adds none. */
  .navitem,
  .navitem.has-menu {
    display: flex;
    align-items: stretch;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0;
  }
  .navitem > a {
    flex: 1;
  }
  .navtoggle {
    width: 44px;
    /* auto + min-height so the flex stretch above can match the link's height;
       a fixed height would defeat it. 44px stays the floor for the tap target. */
    height: auto;
    min-height: 44px;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
  }
  .navtoggle svg {
    width: 18px;
    height: 18px;
  }
  .submenu,
  .submenu-wide {
    position: static;
    display: none;
    visibility: visible;
    opacity: 1;
    transform: none;
    width: 100%;
    min-width: 0;
    columns: 1;
    padding: 0 0 6px 14px;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
    background: transparent;
  }
  .submenu::before {
    display: none;
  }
  .navitem.open > .submenu {
    display: block;
  }
  /* Block, so a submenu row is tappable across the panel rather than only on
     the words. Inline elements do not grow the line box with vertical
     padding, so these were also shorter than the 44px minimum. */
  nav.main .submenu a {
    display: block;
    padding: 12px 0;
    min-height: 44px;
    border-bottom: 0;
    font-size: var(--fs-sm);
  }
  .navcta .btn-s {
    display: none;
  }
  .hero-grid,
  .split,
  .cover,
  .findus,
  .close-grid,
  .phero-grid,
  .proof {
    grid-template-columns: minmax(0, 1fr);
  }
  .proof {
    justify-items: start;
    gap: 20px;
  }
  .score {
    text-align: left;
  }
  .plate {
    transform: none;
    order: -1;
  }
  .hero .plate img {
    height: clamp(220px, 44vw, 330px);
  }
  .grid-3,
  .steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .field .wrap {
    grid-template-columns: minmax(0, 1fr);
  }
  .field-photo {
    display: none;
  }
  .strip {
    grid-template-columns: repeat(2, 1fr);
  }
  .strip > div:nth-child(2) {
    border-right: 0;
    padding-right: 0;
  }
  .strip > div:nth-child(3) {
    padding-left: 0;
  }
  .callbar {
    display: flex;
  }
  body {
    /* Clears the fixed call bar. Raised from 72px when the bar's two buttons
       became one large number — too little here and the footer's last line
       sits under the bar. */
    padding-bottom: 84px;
  }
}

@media (max-width: 700px) {
  .grid-3,
  .grid-2,
  .steps,
  .klist,
  .klist-3,
  .fgrid {
    grid-template-columns: minmax(0, 1fr);
  }
  .strip {
    grid-template-columns: 1fr;
  }
  .strip > div {
    border-right: 0;
    padding: 22px 0 4px;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
  }
  .strip > div:first-child {
    border-top: 0;
  }
  .taper {
    clip-path: polygon(0 26px, 100% 0, 100% 100%, 0 100%);
    margin-top: -26px;
  }
  .faq .ans {
    padding: 0 0 24px 18px;
  }
  .findrow {
    grid-template-columns: 1fr;
    gap: 2px;
  }
  .facts th {
    width: 42%;
    white-space: normal;
  }
  .card > figure img {
    height: 180px;
  }
  /* Hero CTAs on a phone: the call button takes the full width and the form
     button sits under it. Left to wrap naturally the two came out at similar
     widths on two lines, which makes the reader choose between them. On this
     site the call is the action; it gets the whole first row and the easiest
     thumb reach. */
  .hero-cta .btn-p {
    flex: 1 0 100%;
    justify-content: center;
  }
}

/* ---------- touch targets ----------------------------------------------
   On a phone every interactive element gets a 44px minimum hit area. This is
   the WCAG 2.5.5 / Lighthouse tap-target threshold, but the real reason is
   the use case: people tap this site one-handed, in the rain, on a shoulder,
   often having just had an accident. A 25px-high link is a miss waiting to
   happen.

   Done with padding and min-height only — no font sizes change, so the visual
   design is untouched. Scoped to coarse pointers and small screens so desktop
   density stays as designed. */

@media (max-width: 960px), (pointer: coarse) {
  .clink,
  .findrow dd a,
  footer a,
  .fbar a,
  address a,
  .maplink {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .towns a,
  .towns span {
    min-height: 44px;
  }
  .burger {
    height: 46px;
  }
  .qbtn {
    width: 46px;
    height: 46px;
  }
  /* Footer link columns: give each row its own comfortable band rather than
     relying on line-height. */
  .fcol ul li {
    margin-bottom: 2px;
  }
  .fcol ul li a {
    padding-block: 8px;
  }
  .fbar nav {
    gap: 8px 20px;
  }
  /* The header phone CTA is the single most important target on the site. */
  .navcta .btn-p {
    min-height: 46px;
  }
  /* The dispatch number in the closing panel. */
  .dial .num {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  /* Short legal and breadcrumb links were failing on width, not height. */
  .fbar nav a,
  .crumbs a {
    padding: 13px 10px;
    margin: -13px -10px;
  }
  .crumbs li {
    display: flex;
    align-items: center;
  }
  /* Inline links that sit mid-sentence or inside a table cell cannot become
     blocks without wrecking the line. Padding plus equal negative margin grows
     the hit area to 44px and shifts no layout. Applied to every phone link
     wherever it appears — those are the ones that must never be missed. */
  a[data-call],
  .facts a,
  .prose a {
    padding-block: 13px;
    margin-block: -13px;
  }
  /* Heading and list links that were a few pixels short. */
  .klist b a,
  .card-b h2 a,
  .card-b h3 a {
    display: inline-block;
    min-height: 44px;
  }
}

@media print {
  header,
  footer,
  .callbar,
  .marquee,
  .mapwrap {
    display: none !important;
  }
  body {
    background: #fff;
    padding: 0;
  }
}

/* ---------- lead form -------------------------------------------------- */
/* Namespaced `lf-` because `.field` and `.fgrid` are already taken by the
   dark feature section above; an unprefixed `.field` here would inherit its
   inverted colours and render white text on white. */

.formcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(24px, 3.4vw, 40px);
}
.sec-alt .formcard {
  background: var(--surface-page);
}
.formhead {
  max-width: 62ch;
  margin-bottom: 26px;
}
.formhead h2 {
  margin: 6px 0 10px;
}
.formhead p {
  margin: 0;
  color: var(--ink-2);
  font-size: var(--fs-sm);
}

.lf-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 20px;
}
.lf-wide {
  grid-column: 1 / -1;
}
@media (max-width: 640px) {
  .lf-grid {
    grid-template-columns: 1fr;
  }
}

.lf-field {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.lf-field label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
}
.lf-field label span[aria-hidden] {
  color: var(--green-ink);
}
.lf-field .opt {
  font-weight: 400;
  color: var(--steel);
}
.lf-field input,
.lf-field select,
.lf-field textarea {
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  padding: 12px 13px;
  /* 44px minimum touch target without a media query. */
  min-height: 46px;
  width: 100%;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.lf-field textarea {
  resize: vertical;
  min-height: 108px;
  line-height: 1.55;
}
/* iOS Safari zooms the viewport when a focused control has a font-size below
   16px, and does not zoom back out afterwards — the page is left scrolled
   sideways mid-form. The fluid type scale lands at ~13.8px here, so the
   controls are pinned to 16px on touch devices. Cosmetic on desktop, a broken
   form on a phone. */
@media (pointer: coarse), (max-width: 640px) {
  .lf-field input,
  .lf-field select,
  .lf-field textarea {
    font-size: 16px;
  }
}
.lf-field input:focus-visible,
.lf-field select:focus-visible,
.lf-field textarea:focus-visible {
  outline: none;
  border-color: var(--green-btn);
  box-shadow: 0 0 0 3px rgba(47, 161, 77, 0.22);
}
.lf-field.has-error input,
.lf-field.has-error textarea {
  border-color: #b3261e;
}
.lf-field.has-error.has-error input:focus-visible,
.lf-field.has-error textarea:focus-visible {
  box-shadow: 0 0 0 3px rgba(179, 38, 30, 0.2);
}
.ferr:empty {
  display: none;
}
.ferr {
  font-size: var(--fs-xs);
  color: #b3261e;
}

/* Honeypot. Kept in the layout and merely moved out of sight — display:none
   and visibility:hidden are both trivially detected by the bots this is meant
   to catch, and some autofillers skip them. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.formfoot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
  margin-top: 22px;
}
.fnote {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.formfoot button[disabled] {
  opacity: 0.6;
  cursor: progress;
}

.fstatus {
  margin: 16px 0 0;
  font-size: var(--fs-sm);
  font-weight: 600;
}
.fstatus:empty {
  display: none;
}
.fstatus.is-ok {
  color: var(--green-ink);
}
.fstatus.is-bad {
  color: #b3261e;
}

@media print {
  .leadform {
    display: none;
  }
}

/* ---------- closing CTA: the number, and nothing else ------------------- */
/* Same display face and dark section as before, scaled up so it reads as the
   page's terminal action rather than one option among several. Fluid from
   phone to desktop; the ch-based cap keeps it from colliding with the wrap
   edges on a narrow screen. */

.close-num {
  display: block;
  text-align: center;
  font-family: var(--font-d);
  /* 590, down from a requested 800 the old face could not even reach — it
     declared a 400–700 axis, so 800 clamped. At up to 132px this is the
     largest type on the site; heavy numerals at that scale read as shouting
     rather than as emphasis. */
  font-variation-settings: 'wdth' 84, 'wght' 590;
  font-size: clamp(38px, 11.5vw, 132px);
  line-height: 0.95;
  letter-spacing: -0.045em;
  color: var(--white);
  text-decoration: none;
  /* Generous hit area — this is the primary action on a phone. */
  padding-block: clamp(10px, 2vw, 22px);
  transition: color 0.15s ease;
  text-wrap: balance;
}
.close-num:hover,
.close-num:focus-visible {
  color: var(--green);
}
.close-num:focus-visible {
  outline: 3px solid var(--green);
  outline-offset: 8px;
  border-radius: 6px;
}
@media (prefers-reduced-motion: reduce) {
  .close-num {
    transition: none;
  }
}

/* ---------- dark theme -------------------------------------------------
 *
 * Three states, not two: "dark", "light", and no stored choice at all. The
 * media query is guarded with :not([data-theme='light']) so that someone who
 * has explicitly chosen light keeps light on a dark-set OS, while someone who
 * has never touched the toggle still follows their system when it changes at
 * sunset. The [data-theme='dark'] block repeats the same roles so the toggle
 * wins in the other direction too.
 *
 * Only ROLE tokens are redefined here. Nothing in this file below :root
 * references a raw palette entry for a themeable surface, so these two blocks
 * are the whole theme. Redefining anything else here means a role is missing.
 *
 * ⚠ These blocks must stay OUTSIDE :root. An earlier version nested the media
 * query inside it, which orphaned every declaration after it — the type scale
 * and the brand colours silently vanished and a button measured 1.12:1.
 */

/* The role values, written once. Kept in a custom media query-free block that
   both selectors below pull in by duplication rather than by @apply, which
   does not exist. If you change one, change the other. */



:root[data-theme='dark'] {
  --surface: #1a1e22;
  --surface-page: #14171a;
  --surface-sunk: #22272c;
  --ink: #e7ebee;
  --header-bg: rgba(20, 23, 26, 0.94);

  --line: #2c3339;
  --line-soft: #3a434b;

  --ink-1: #ccd3d8;
  --ink-2: #c3cbd1;
  --ink-3: #bac3c9;

  --steel: #9ea8b0;
  --green-ink: #3cb45b;

  --footer-bg: #0b0d0f;
  --footer-line: #242c33;
  --photo-bg: #20262b;
}

/* Photo-filled headings.
 *
 * .d.fill clips a photo into the letter forms behind a darkening scrim, which
 * is what makes it readable on a light page. On a dark page the scrim and the
 * background are the same value and the heading measures about 1.2:1 — it
 * disappears. This was reported twice from screenshots and missed twice by a
 * contrast sweep that skipped these because the computed colour is
 * `transparent`. The fix is to drop the effect entirely in dark and fall back
 * to solid ink; -webkit-text-fill-color has to be reset too, or it keeps
 * winning over `color`. */

:root[data-theme='dark'] .d.fill,
:root[data-theme='dark'] .d.fill-b {
  background-image: none;
  color: var(--ink);
  -webkit-text-fill-color: var(--ink);
}

/* Photographs are mastered for a light page and read as glare on a dark one.
   A small brightness cut settles them without touching logos or icons. */

:root[data-theme='dark'] .phero-photo img,
:root[data-theme='dark'] figure img {
  filter: brightness(0.92);
}

/* Tell the engine which form controls and scrollbars to render. */

:root[data-theme='dark'] {
  color-scheme: dark;
}
:root[data-theme='light'] {
  color-scheme: light;
}

/* ---------- narrow phones (<=420px) ---------------------------------------
   MEASURED: at 400px and below the header ran out of room and resolved it by
   squeezing the two things that must not be squeezed. .logo is a flex item
   with margin-right:auto but no flex-basis, so it shrank and the wordmark
   image was pulled out of its aspect ratio; at the same time .hd's 24px gap
   and .navcta's 10px gap pushed the burger under the 44px tap floor.

   Scoped to the header only. The audit's first draft also re-padded every
   section on the site at this width, which is a far wider visual change than
   the defect calls for. */
@media (max-width: 420px) {
  .hd {
    gap: 10px;
  }
  .logo {
    flex: none;
  }
  .logo img {
    height: 40px;
    width: auto;
  }
  .navcta {
    gap: 8px;
  }
  .navcta .btn-p {
    padding-inline: 12px;
  }
}
