:root {
  /* 417 Dumpster Rental brand palette, sampled from the client's real assets:
     fleet red #C00811 (eyedropped from daylight can photos, gallery-33) and
     logo green #39AB2A (eyedropped from the raccoon-mascot logo). Two-tier
     system: action tier (--red*) = fleet red, filled CTAs + phone buttons —
     #C00811 passes AA with white text (~6:1), so no lighter/darker split is
     needed like the FA402B brands. Accent tier (legacy --yellow* token names)
     = brand green, tying accents (eyebrows, prices, step numbers, icons) to
     the green mascot. Bright logo green fails AA for text on white (2.99:1),
     so the accent tokens use deep green #257A1C (5.41:1); reserve bright
     #39AB2A (--green-bright) for non-text uses (icons, borders, marker fills).
     --ok (accepted ✓) aligns to the same deep green; --red stays the ✕. */
  --yellow: #257a1c;
  --yellow-deep: #1e6b17;
  --yellow-tint: #eaf6e8;
  --green-bright: #39ab2a;
  --red: #c00811;
  --red-deep: #a1060e;
  --red-deeper: #870a10;  /* hover for filled CTAs (white text ~8:1) */
  --ok: #257a1c;          /* green — "accepted" checkmarks only */
  --black: #0b0b0b;
  --ink: #141414;
  --muted: #5a5a5a;
  --line: #e6e3dd;
  --logo-gray: #d0d0d0;
  --bg: #fdfcfa;
  --bg-warm: #f6f4f0;

  --font-display: "Archivo", system-ui, sans-serif;
  --font-body: "Public Sans", system-ui, sans-serif;

  /* Radius scale. Was eight ad-hoc values (2/3/4/6/8/10/50%/999) with no
     rule; the stylesheet is the design spec and it has to read like one. */
  --r-sm: 4px;      /* inputs, chips, small surfaces */
  --r-md: 8px;      /* cards and panels */
  --r-pill: 999px;
  --r-btn: 10px;  /* pills and buttons */
  /* Section rhythm. Every body section was padded identically, which is the
     canned-skeleton tell; these give sections a role instead. */
  /* One between-groups gap. Five different inline margin-tops (1rem to
     1.75rem) were scattered across 166 CTA rows - the near-miss drift that
     made pages feel assembled. The hero's group gap is the same value. */
  --gap-group: 2rem;
  --sec-tight: clamp(2.25rem, 5vw, 3.75rem);
  --sec: clamp(3.5rem, 8vw, 6rem);
  --sec-feature: clamp(4.5rem, 10vw, 7.5rem);
  --max: 1280px;
  --pad: clamp(1.25rem, 4vw, 2.5rem);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

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

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
  text-wrap: balance;
  margin: 0 0 0.5em;
  color: var(--black);
}

h1 {
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  font-weight: 700;
}

.hero h1 {
  font-size: clamp(2rem, 4.5vw, 3.25rem);
  line-height: 1.08;
  text-wrap: balance;
}

h2 {
  font-size: clamp(1.8rem, 3.5vw, 2.5rem);
}

h3 {
  font-size: clamp(1.2rem, 2vw, 1.4rem);
  letter-spacing: -0.015em;
}

p {
  margin: 0 0 1em;
}

.wrap {
  max-width: var(--max);
  margin: 0 auto;
  padding-left: var(--pad);
  padding-right: var(--pad);
}/* ===== Photo placeholder ===== */
.photo {
  background: var(--yellow-tint);
  border: 2px dashed var(--yellow);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  border-radius: var(--r-sm);
}
.photo::before {
  content: "PHOTO";
  position: absolute;
  top: 12px;
  left: 12px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  background: var(--black);
  color: var(--yellow);
  padding: 4px 8px;
  border-radius: var(--r-sm);
}
.photo span {
  font-family: var(--font-body);
  color: #6a5a00;
  font-size: 0.85rem;
  max-width: 80%;
  text-align: center;
  line-height: 1.4;
  padding: 2rem 1rem 1rem;
}
.photo.ar-hero {
  aspect-ratio: 5 / 4;
}
.photo.ar-square {
  aspect-ratio: 1 / 1;
}
.photo.ar-wide {
  aspect-ratio: 16 / 9;
}
.photo.ar-tall {
  aspect-ratio: 4 / 5;
}
.photo.ar-card {
  aspect-ratio: 3 / 2;
}/* When a real <img> is in the .photo container, hide placeholder styling */
.photo:has(img) {
  background: transparent;
  border: none;
}
.photo:has(img)::before {
  display: none;
}
.photo:has(img) span {
  display: none;
}
.photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}/* ===== Nav ===== */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--black);
  border-bottom: 1px solid #1f1f1f;
}/* When users follow an #anchor link, scroll lands with breathing room
   above the section heading rather than slamming the section to the
   sticky topbar's edge. */
[id] {
  scroll-margin-top: 110px;
}
.topbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 92px;
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
  gap: 1.5rem;
}
.brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  color: var(--black);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}
.brand-mark {
  height: 74px;
  width: auto;
  display: block;
  margin: 0.5rem 0;
  flex-shrink: 0;
}
.brand {
  flex-shrink: 0;
}
nav.primary {
  display: none;
  /* 1.15rem rather than 1.4: with six items the row has to share 1000px with the
     phone CTA and the logo, and the wider gap squeezed the logo at that width. */
  gap: 1.15rem;
  font-weight: 500;
  white-space: nowrap;
}
nav.primary a {
  color: #fff;
  text-decoration: none;
  font-size: 0.97rem;
  position: relative;
  padding-bottom: 4px;
  transition: color 180ms ease;
}
nav.primary a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--yellow);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
}
nav.primary a:hover {
  color: #fff;
}
nav.primary a:hover::after {
  transform: scaleX(1);
}/* Current page: coral label + a persistent underline (same bar as the hover
   state, just locked open) so you can always tell where you are. */
nav.primary a[aria-current="page"] {
  color: #39ab2a;
}
nav.primary a[aria-current="page"]::after {
  transform: scaleX(1);
  background: #39ab2a;
}

.tel-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--yellow);
  color: var(--black);
  text-decoration: none;
  padding: 0.7rem 1.15rem;
  border-radius: var(--r-sm);
  font-weight: 700;
  font-family: var(--font-display);
  font-size: 1.2rem;
  white-space: nowrap;
}
.tel-cta:hover {
  background: var(--red-deeper);
}
.tel-cta::before {
  content: "";
  width: 14px;
  height: 14px;
  background: var(--black);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>")
    center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>")
    center/contain no-repeat;
}

/* Full horizontal nav appears at 1000px — covers iPad landscape (1024).
   Six items + phone CTA + logo fit comfortably at that width. */
@media (min-width: 1000px) {
  nav.primary {
    display: inline-flex;
  }
}

/* ===== Nav layout: phone on the LEFT, logo on the RIGHT (order-only swap) =====
   The two side zones share equal flex so the center nav stays optically
   centered even though the left cluster (hours + phone) is wider than the
   logo. flex-basis:0 + grow:1 gives each side (container - nav) / 2. */
@media (min-width: 1000px) {
  .topbar-inner > nav.primary { order: 2; flex: 0 0 auto; }
  .topbar-inner > .brand { order: 3; flex: 1 1 0; justify-content: flex-end; }
}
@media (max-width: 999px) {
  .topbar-inner > .brand { order: 5; margin-right: 0; }
}/* ===== Mobile hamburger menu ===== */
.nav-toggle-cb {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.nav-toggle {
  display: none;
}
@media (max-width: 999px) {/* Push brand to the left, group call + hamburger on the right */
  .topbar-inner {
    justify-content: flex-start;
    gap: 0.5rem;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    min-height: 76px;
  }
  .brand {
    margin-right: auto;
  }
  .brand-mark {
    height: 40px;
  }
  .tel-cta {
    padding: 0.5rem 0.7rem;
    font-size: 1rem;
    gap: 0.35rem;
  }
  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    cursor: pointer;
    background: transparent;
    border: 2px solid #fff;
    border-radius: var(--r-sm);
    flex-shrink: 0;
    order: 10;
  }
  .nav-toggle span {
    display: block;
    width: 22px;
    height: 2px;
    background: #fff;
    border-radius: var(--r-sm);
    transition:
      transform 180ms ease,
      opacity 180ms ease;
  }
  .topbar:has(.nav-toggle-cb:checked) .nav-toggle span:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
  }
  .topbar:has(.nav-toggle-cb:checked) .nav-toggle span:nth-child(2) {
    opacity: 0;
  }
  .topbar:has(.nav-toggle-cb:checked) .nav-toggle span:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
  }
  .topbar:has(.nav-toggle-cb:checked) nav.primary {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: #0b0b0b;
    padding: 0.5rem 1.5rem;
    border-top: 2px solid #1f1f1f;
    border-bottom: 2px solid var(--red);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.4);
    z-index: 49;
    gap: 0;
  }
  .topbar:has(.nav-toggle-cb:checked) nav.primary a {
    padding: 0.95rem 0;
    font-size: 1.05rem;
    font-weight: 600;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  }
  .topbar:has(.nav-toggle-cb:checked) nav.primary a:last-child {
    border-bottom: none;
  }
}/* ===== Scroll-morphing topbar (mobile only) — slide transition ===== */
.topbar-inner {
  position: relative;
  overflow: hidden;
}/* When hamburger nav is open, allow overflow so the drawer can drop below */
.topbar:has(.nav-toggle-cb:checked) .topbar-inner {
  overflow: visible;
}
/* ===== Hero ===== */
.hero {
  padding: clamp(2.5rem, 6vw, 5rem) 0 clamp(3rem, 7vw, 6rem);
  border-bottom: 1px solid var(--line);
}
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: center;
}
@media (min-width: 900px) {
  /* Measured 2026-08-21 at 1440x900: 1.1fr/1fr gave the copy a 590px column,
     but "Dumpster Rental" alone sets 624px at the capped 78px h1 - so the
     headline could not fit its first two words on one line and ran to FOUR
     lines, 303px tall. That pushed the primary Call button to bottom=912,
     below the 900px fold on a laptop. The ticket beside it only ever needs
     459px of its 537px column, so the space was already there: cap that
     column and the copy gets 752px, the h1 sets in two lines at 152px, and
     the button lands at 761 with room to spare. */
  .hero-grid {
    /* clamp rather than minmax on the ticket: a flat 460px max meant the
       ticket held 459px at EVERY width, so at a 900px viewport it was wider
       than the 323px copy column beside it. Letting it fall to 340px there
       - the width it already sets at on a phone - hands the headline back
       ~150px exactly where the layout is tightest. */
    grid-template-columns: minmax(0, 1fr) clamp(340px, 32vw, 460px);
    gap: clamp(2rem, 5vw, 4rem);
  }
}

.eyebrow {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--black);
  background: var(--green-bright); /* black on #39ab2a = 6.6:1; deep green failed AA */
  padding: 4px 10px;
  margin-bottom: 1.5rem;
  border-radius: var(--r-sm);
}

.hero p.lead {
  font-size: clamp(1.1rem, 1.8vw, 1.3rem);
  color: var(--muted);
  max-width: 32em;
  margin-bottom: 2rem;
  line-height: 1.5;
}

.cta-row {
  margin-top: var(--gap-group);
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem 0.75rem;
  align-items: center;
  margin-bottom: 1.25rem;
}/* Canonical CTA-row mobile stacking (local-service-design, "CTA rows and
   mobile stacking"): every button-group container on the site shares this
   rule instead of a per-page patch. gap survives wrapping, sibling margins
   don't, so spacing is gap-only here. Below 640px, stack to full-width
   column at a 48px tap-target floor with 12px+ vertical breathing room. */
.cta-row,
.cta-buttons,
.hero-ctas {
  row-gap: 0.85rem;
}
/* Every multi-button row uses .cta-row (or .cta-buttons / .hero-ctas). 13
   ad-hoc `display:flex` divs across 12 files were carrying their own gaps
   and, because the mobile stacking rule targets these classes by name, were
   silently opting out of full-width stacking on phones. */
.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}
@media (max-width: 640px) {
  .cta-row,
  .cta-buttons,
  .hero-ctas {
    flex-direction: column;
    align-items: stretch;
    /* 1rem, not 0.85: stacked full-width buttons at 48px+ tall need more
       separation than side-by-side ones, or the pair reads as one control
       with a seam (Ryan, 2026-08-12: "make sure mobile buttons have some
       space to breathe, aren't stacked on top of each other"). */
    row-gap: 1rem;
  }
  .cta-row .btn,
  .cta-row .tel-big,
  .cta-row .text-big,
  .cta-row .book-big,
  .cta-buttons .btn,
  .cta-buttons .tel-big,
  .cta-buttons .text-big,
  .cta-buttons .book-big,
  .hero-ctas .btn,
  .hero-ctas .tel-big,
  .hero-ctas .text-big,
  .hero-ctas .book-big {
    width: 100%;
    min-height: 48px;
    justify-content: center;
    margin: 0;
  }
}
.btn {
  display: inline-flex;
  align-items: center;
  /* Horizontal centring belongs on the base rule, not on the handful of
     media-query contexts that stretch a button to width:100%. Without it,
     the next full-width button silently left-aligns its label. */
  justify-content: center;
  gap: 0.5rem;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  padding: 0.85rem 1.5rem;
  border-radius: var(--r-md);
  border: 2px solid var(--black);
  white-space: nowrap;
  box-shadow: 4px 4px 0 var(--black);
  transition:
    transform 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
}
.btn:hover {
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--black);
}
.btn:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--black);
}
.btn-primary {
  background: var(--yellow);
  color: var(--black);
}
.btn-primary:hover {
  background: var(--red-deeper);
  /* Bigger lift + deeper shadow than the generic .btn so the main
     CTA feels weighty on hover. */
  transform: translate(-3px, -3px);
  box-shadow: 8px 8px 0 var(--black);
}
.btn-primary:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--black);
}
.btn-secondary {
  background: transparent;
  color: var(--black);
}
/* Was red-deep on black: 2.39:1, illegible. The inverted state keeps the
   ink/paper flip that every other secondary control uses. */
.btn-secondary:hover {
  background: var(--black);
  color: #fff;
}
.btn-big {
  font-size: clamp(1.25rem, 2.3vw, 1.65rem);
  font-weight: 700;
  padding: 0.85rem 1.5rem;
}

.tel-big {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.25rem, 2.3vw, 1.65rem);
  color: var(--black);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--yellow);
  padding: 0.85rem 1.5rem;
  border-radius: var(--r-md);
  border: 2px solid var(--black);
  margin-bottom: 0.75rem;
  box-shadow: 4px 4px 0 var(--black);
  transition:
    transform 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
}
.tel-big:hover {
  background: var(--red-deeper);
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--black);
}
.tel-big:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--black);
}
.tel-big::before {
  content: "";
  width: 1.1em;
  height: 1.1em;
  background: var(--black);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>")
    center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>")
    center/contain no-repeat;
  flex-shrink: 0;
}

.tel-sub {
  font-size: 0.95rem;
  color: var(--muted);
}

.text-big {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.25rem, 2.3vw, 1.65rem);
  color: var(--black);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--yellow);
  padding: 0.85rem 1.5rem;
  border-radius: var(--r-md);
  border: 2px solid var(--black);
  margin-bottom: 0.75rem;
  box-shadow: 4px 4px 0 var(--black);
  transition:
    transform 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
}
.text-big:hover {
  background: var(--red-deeper);
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--black);
}
.text-big:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--black);
}
.text-big::before {
  content: "";
  width: 1.1em;
  height: 1.1em;
  background: var(--black);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z'/></svg>")
    center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z'/></svg>")
    center/contain no-repeat;
  flex-shrink: 0;
}/* ===== Trust strip ===== */
.trust {
  background: var(--bg-warm);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 1.5rem 0;
}
.trust-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  font-size: 0.95rem;
}
.trust-item {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.trust-item strong {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--black);
}
.trust-item span {
  color: var(--muted);
}/* ===== Section base ===== */
section.block {
  padding: var(--sec) 0;
}/* Roles, not a single value. Short supporting sections breathe less; the
   product grid and the closing CTA earn more. */
section.block.tight { padding: var(--sec-tight) 0; }
section.block.feature { padding: var(--sec-feature) 0; }
section.block.alt {
  background: var(--bg-warm);
}

.section-head {
  max-width: 44rem;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.section-head p {
  font-size: 1.1rem;
  color: var(--muted);
  max-width: 36em;
}/* ===== Services two-up ===== */
.services-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
@media (min-width: 800px) {
  .services-split {
    grid-template-columns: 1fr 1fr;
    gap: 2rem;
  }
}
.svc-card {
  position: relative;
  background: var(--black);
  color: #fff;
  border-radius: var(--r-sm);
  overflow: hidden;
  min-height: 380px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.svc-card .photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: 0;
  border-color: rgba(245, 184, 0, 0.6);
}
.svc-card .photo::before {
  background: var(--yellow);
  color: var(--black);
}
.svc-card .svc-body {
  position: relative;
  z-index: 1;
  padding: 2rem;
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.92) 30%,
    rgba(0, 0, 0, 0.55) 75%,
    transparent
  );
}
.svc-card h3 {
  font-size: 1.8rem;
  color: #fff;
  margin-bottom: 0.5rem;
}
.svc-card p {
  color: rgba(255, 255, 255, 0.85);
  margin-bottom: 1rem;
  font-size: 0.97rem;
  line-height: 1.5;
}
.svc-card a.svc-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--red-deep);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
}
.svc-card a.svc-link:hover {
  color: #fff;
}/* ===== Sizes row ===== */
.sizes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
  margin-top: 2rem;
}
@media (min-width: 700px) {
  .sizes {
    grid-template-columns: repeat(4, 1fr);
  }
}
.size-card {
  border: 1px solid var(--line);
  padding: 1.5rem 1.25rem;
  background: #fff;
  border-radius: var(--r-sm);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s;
}
.size-card:hover {
  border-color: var(--yellow);
}
.size-card .yd {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  letter-spacing: 0.2px;
  color: var(--black);
  line-height: 1.05;
  display: block;
}
.size-card .yd small {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--muted);
}
.size-card p {
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.4;
}/* ===== Story strip ===== */
.story-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: center;
}
@media (min-width: 900px) {
  .story-grid {
    grid-template-columns: 0.9fr 1.1fr;
    gap: clamp(2.5rem, 5vw, 4rem);
  }
}
.story-grid .photo.ar-tall {
  max-height: 540px;
}

.story-body p {
  font-size: 1.05rem;
  line-height: 1.65;
}
.story-body p.kicker {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 600;
  color: var(--black);
  line-height: 1.35;
  margin-bottom: 1.25rem;
}/* ===== Reviews ===== */
/* Review strip scrolls horizontally at every width, the way a real review
   widget does: three cards visible on desktop, one and a bit on a phone, the
   rest a swipe away. Native scrollbar is hidden; reviews-strip.js draws the
   track/thumb indicator beneath it (iOS never renders styled scrollbars). */
.reviews {
  display: flex;
  gap: 1.25rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.reviews::-webkit-scrollbar {
  display: none;
}
.reviews .review {
  scroll-snap-align: start;
  flex: 0 0 84%;
  flex-shrink: 0;
}
@media (min-width: 800px) {
  .reviews .review {
    flex: 0 0 calc((100% - 2.5rem) / 3);
  }
}/* Review cards, styled like a Google review widget: initial avatar, name +
   date, Google mark, then gold stars over the quote. Gold (not brand red or
   green) is deliberate here; it is the strongest visual cue that the rating
   is real Google data rather than a testimonial we wrote. */
.review {
  background: #fff;
  border: 1px solid var(--line);
  padding: 1.4rem 1.35rem;
  border-radius: var(--r-md);
  /* No soft shadow. The house depth technique is the hard offset; a second
     ~0.07-opacity drop shadow on every review card is the exact "same soft
     shadow on everything" tell, and it competed with the signature. */
  display: flex;
  flex-direction: column;
}
.rv-head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.7rem;
}
.rv-avatar {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  background: var(--red-deep);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  line-height: 1;
}
.reviews .review:nth-child(3n + 2) .rv-avatar {
  background: #33383d;
}
.reviews .review:nth-child(3n) .rv-avatar {
  background: var(--yellow);
}
.rv-who {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
}
.rv-name {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--ink);
  font-size: 0.97rem;
}
.rv-date {
  font-size: 0.8rem;
  color: var(--muted);
}
.rv-g {
  margin-left: auto;
  flex-shrink: 0;
}
.rv-stars {
  margin: 0 0 0.6rem;
  color: #fbbc04;
  font-size: 1.02rem;
  letter-spacing: 0.08em;
  line-height: 1;
}
.review blockquote {
  margin: 0;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--ink);
}/* JS-injected swipe indicator: a little left-right scrollbar that tracks the
   review strip, visible on every platform including iOS. */
.hscroll-track {
  height: 5px;
  background: var(--line);
  border-radius: var(--r-sm);
  margin: 0.75rem auto 0;
  max-width: 11rem;
  position: relative;
  overflow: hidden;
}
.hscroll-thumb {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--red);
  border-radius: var(--r-sm);
  transition: none;
}

.google-cta {
  margin-top: 2rem;
  font-size: 0.95rem;
  color: var(--muted);
}
.google-cta a {
  color: var(--black);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--yellow);
  text-decoration-thickness: 3px;
}/* ===== Service area ===== */
.area-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: start;
}
@media (min-width: 900px) {
  .area-grid {
    grid-template-columns: 0.85fr 1.15fr;
    gap: clamp(2.5rem, 5vw, 4rem);
  }
}
.big-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(8rem, 18vw, 14rem);
  line-height: 0.85;
  color: var(--black);
  letter-spacing: -0.06em;
  display: block;
}
.big-num-cap {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: 0.04em;
  color: var(--ink);
  margin-top: 0.5rem;
  display: block;
  max-width: 18em;
}

.town-list {
  columns: 2;
  column-gap: 1.5rem;
  font-size: 0.97rem;
  line-height: 1.85;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 700px) {
  .town-list {
    columns: 3;
  }
}
.town-list li a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px dotted transparent;
}
.town-list li a:hover {
  border-bottom-color: var(--yellow);
}
.town-list li.more {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--black);
  margin-top: 0.5rem;
}/* ===== FAQ ===== */
/* FAQ accordion — card style, matching the junk-page service accordion */
.faq {
  max-width: 50rem;
  margin-top: 2rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.faq details {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: box-shadow 150ms;
}
.faq details[open] {
  box-shadow: 4px 4px 0 var(--yellow);
}
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.25rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  color: var(--black);
  transition: background 120ms;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary:hover {
  background: #fafaf7;
}
.faq summary::after {
  content: "+";
  font-size: 1.7rem;
  font-weight: 400;
  line-height: 0.8;
  flex-shrink: 0;
  color: var(--black);
  transition: transform 0.2s;
}
.faq details[open] summary {
  border-bottom: 1px solid var(--line);
}
.faq details[open] summary::after {
  transform: rotate(45deg);
}
.faq details > p,
.faq details > ul {
  margin: 0;
  padding: 1rem 1.25rem;
  color: var(--ink);
  line-height: 1.6;
}
.faq details > ul {
  padding-left: 2.6rem;
}
.faq details > p + p,
.faq details > p + ul {
  padding-top: 0;
}/* ===== Final CTA ===== */
.cta-final {
  background: var(--black);
  color: #fff;
  text-align: center;
}
.cta-final h2 {
  color: #fff;
  max-width: 18em;
  margin-left: auto;
  margin-right: auto;
}
.cta-final h2 em {
  color: var(--yellow);
  font-style: normal;
}
.cta-final p {
  color: rgba(255, 255, 255, 0.75);
  max-width: 34em;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: 2rem;
  font-size: 1.1rem;
}
.cta-final .cta-row {
  justify-content: center;
}
.cta-final .tel-big,
.cta-final .text-big,
.cta-final .btn {
  border-color: var(--yellow);
  box-shadow: 4px 4px 0 var(--yellow);
}
.cta-final .tel-big:hover,
.cta-final .text-big:hover,
.cta-final .btn:hover {
  box-shadow: 6px 6px 0 var(--yellow);
}
.cta-final .tel-big:active,
.cta-final .text-big:active,
.cta-final .btn:active {
  box-shadow: 0 0 0 var(--yellow);
}
.cta-final .btn-primary {
  background: var(--yellow);
  color: var(--black);
}
.cta-final .btn-primary:hover {
  background: var(--red-deeper);
}
.cta-final .btn-secondary {
  background: transparent;
  color: var(--red-deep);
}
.cta-final .btn-secondary:hover {
  background: #fff;
  color: var(--black);
}/* ===== Footer ===== */
footer.site {
  background: #0a0a0a;
  color: rgba(255, 255, 255, 0.7);
  padding: 4rem 0 2rem;
  font-size: 0.92rem;
}
footer.site .foot-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-bottom: 3rem;
}
@media (min-width: 640px) {
  footer.site .foot-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (min-width: 960px) {
  footer.site .foot-grid {
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
  }
}
footer.site h4 {
  color: #fff;
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 1rem;
}
footer.site a {
  color: rgba(255, 255, 255, 0.8);
  text-decoration: none;
}
footer.site a:hover {
  color: var(--yellow);
}
footer.site ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
footer.site ul li {
  margin-bottom: 0.5rem;
  line-height: 1.5;
}
footer.site .foot-brand {
  display: block;
  height: 110px;
  width: auto;
  margin-bottom: 0.85rem;
}
footer.site .nap p {
  margin-bottom: 0.5rem;
  color: rgba(255, 255, 255, 0.75);
}
footer.site .nap strong {
  color: #fff;
  font-weight: 600;
}
footer.site .legal {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: 1.5rem;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.5);
}/* ===== Floating sticky Call button (mobile + desktop) ===== */
.mobile-cta {
  position: fixed;
  bottom: 1.25rem;
  right: 1.25rem;
  left: auto;
  z-index: 60;
  display: flex;
  gap: 0;
  background: transparent;
  border-top: none;
  padding: 0;
}
.mobile-cta a.book {
  display: none; /* keep just the Call button */
}
.mobile-cta a.call {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--red-deep);
  color: #fff;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  padding: 0.85rem 1.5rem;
  border-radius: var(--r-pill);
  /* Floating pill sits over content, so it keeps a real drop shadow — the one
     place a soft shadow earns its place rather than decorating a static card. */
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.3);
  white-space: nowrap;
}
.mobile-cta a.call:hover {
  /* Stay in the red family: --yellow is remapped to GREEN on this brand, and
     a red pill flashing green on tap read as a different button. */
  background: var(--red-deeper);
}
.mobile-cta a.call::before {
  content: "";
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background: #fff;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>") center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>") center/contain no-repeat;
}

/* Add bottom padding on mobile so sticky CTA doesn't cover content */
@media (max-width: 899px) {
  footer.site {
    padding-bottom: 6rem;
  }
}/* ===== Sub-page primitives ===== */

.crumb {
  font-family: var(--font-display);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.crumb a {
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px dotted transparent;
}
.crumb a:hover {
  color: var(--black);
  border-bottom-color: var(--yellow);
}
.crumb .sep {
  opacity: 0.4;
  margin: 0 0.35rem;
}
.crumb .current {
  color: var(--black);
}

.page-hero {
  padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(2rem, 5vw, 3.5rem);
  border-bottom: 1px solid var(--line);
}
.page-hero h1 {
  font-size: clamp(2rem, 4.5vw, 3.5rem);
  max-width: 18em;
}
.page-hero .lead {
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  color: var(--muted);
  max-width: 36em;
  line-height: 1.55;
  margin-top: 1rem;
}

.page-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: start;
}
@media (min-width: 900px) {
  .page-grid {
    grid-template-columns: 1.1fr 1fr;
    gap: clamp(2rem, 5vw, 4rem);
  }
}
@media (min-width: 900px) {
  .page-grid .photo {
    min-height: 320px;
  }
}

.spec-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem;
  margin: 2rem 0;
}
/* Below ~400px two columns can't hold a long value like "Springfield &
   southwest Missouri" without pushing the grid past the viewport, so stack. */
@media (max-width: 400px) {
  .spec-grid {
    grid-template-columns: 1fr;
  }
}
@media (min-width: 700px) {
  .spec-grid {
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  }
}
.spec {
  min-width: 0;
  background: #fff;
  border: 1px solid var(--line);
  padding: 1.1rem 1.25rem;
  border-radius: var(--r-sm);
}
.spec .label {
  font-family: var(--font-display);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
  margin-bottom: 0.35rem;
}
.spec .val {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--black);
  line-height: 1.05;
}

.prose p {
  font-size: 1.05rem;
  line-height: 1.65;
  color: var(--ink);
}
.prose p + p {
  margin-top: 1em;
}
.prose h3 {
  margin-top: 2rem;
}
.prose ul {
  padding-left: 1.25rem;
  line-height: 1.7;
}
.prose ul li {
  margin-bottom: 0.35rem;
}/* :not(.btn) so a section-closing button inside prose keeps its own styling
   instead of picking up the inline-link underline. */
.prose a:not(.btn) {
  color: var(--black);
  border-bottom: 2px solid var(--yellow);
  text-decoration: none;
}
.prose a:not(.btn):hover {
  color: var(--yellow-deep);
}/* Buttons inside prose keep button styling, not link styling */
/* Do NOT zero border-bottom here. This rule was meant to stop the inline-link
   underline applying to buttons, but the underline rule above is already
   a:not(.btn) - so it never applied - while `border-bottom: 0` deleted the
   BUTTON'S OWN bottom border. Every .btn inside .prose rendered with three
   borders and an open bottom edge, which is the "buttons cut off" Ryan kept
   seeing (2026-08-12). Buttons in prose need no border override at all. */
.prose a.btn-primary {
  color: #fff;
}
.prose a.btn-primary:hover {
  color: #fff;
}/* Related sizes row */
.related-sizes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.85rem;
  margin-top: 1.5rem;
}
@media (min-width: 700px) {
  .related-sizes {
    grid-template-columns: repeat(4, 1fr);
  }
}
.related-sizes a {
  display: block;
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  text-decoration: none;
  color: var(--ink);
  background: #fff;
  transition: border-color 0.15s;
}
.related-sizes a:hover {
  border-color: var(--yellow);
}
.related-sizes a strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--black);
}
.related-sizes a small {
  display: block;
  color: var(--muted);
  font-size: 0.85rem;
  margin-top: 0.25rem;
}
.related-sizes a.current {
  border-color: var(--black);
  background: #faf8f2;
}/* Map: single HQ pin + permanent label (Google-style coverage map) */
.hq-pin {
  background: transparent;
  border: none;
}
.leaflet-tooltip.hq-label {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--black);
  padding: 3px 9px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  white-space: nowrap;
}
.leaflet-tooltip.hq-label::before {
  display: none;
}/* Per-size "see details" link on the dumpsters size cards */
.size-card .size-more {
  display: inline-block;
  margin-top: 0.85rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--red-deep);
  text-decoration: none;
}
.size-card .size-more:hover {
  text-decoration: underline;
}/* Dense town chips (homepage service-area section) */
.related-sizes.areas-towns {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.related-sizes.areas-towns a {
  padding: 0.5rem 0.95rem;
  border-radius: var(--r-pill);
}
.related-sizes.areas-towns a:hover {
  border-color: var(--red);
}
.related-sizes.areas-towns a strong {
  display: inline;
  font-size: 0.95rem;
  font-weight: 700;
}
.related-sizes.areas-towns a small {
  display: none;
}/* AI-summary / quick-facts callout (answer-engine snippet) */
.ai-summary {
  background: #faf8f2;
  border: 1px solid var(--line);
  border-left: 4px solid var(--yellow);
  border-radius: var(--r-md);
  padding: 1.4rem 1.6rem;
}
.ai-summary h2 {
  font-size: 1.15rem;
  margin: 0 0 0.75rem;
}
.ai-summary ul {
  margin: 0;
  padding-left: 1.15rem;
  display: grid;
  gap: 0.4rem;
}
.ai-summary li {
  font-size: 0.97rem;
  line-height: 1.45;
}
.ai-summary strong {
  font-family: var(--font-display);
}/* ===== Reviews: summary badge, reviews-page grid, verified badge ===== */
/* Google review summary. Styled to Google's own surface rather than the house
   style: hairline border, gold stars, Google's greys, body font. Layout
   mirrors how Google states a rating (number, star row, then the count
   beneath). No "Excellent" word: that's Trustpilot vocabulary, Google never
   labels a rating.
   The .rb-text > strong + span structure is load-bearing, fetch-reviews.mjs
   patches exactly that shape to keep the number current, so it stays put and
   display:contents lets its children sit in this grid. */
.reviews-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  margin: 0 auto;
  padding: 0.8rem 1.15rem;
  background: #fff;
  border: 1px solid #dadce0;
  border-radius: var(--r-md);
  font-family: var(--font-body);
  text-align: left;
}
.rs-source {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.rs-source svg {
  flex-shrink: 0;
}
.rs-source-text {
  display: grid;
  grid-template-columns: auto auto;
  align-items: center;
  column-gap: 0.5rem;
  row-gap: 0.1rem;
}
.rb-text {
  display: contents;
}
.rb-text strong {
  grid-column: 1;
  grid-row: 1;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1.45rem;
  line-height: 1;
  color: #202124;
  letter-spacing: 0;
}
.rs-stars {
  grid-column: 2;
  grid-row: 1;
  color: #fbbc04;
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  line-height: 1;
  white-space: nowrap;
}
.rb-text > span {
  grid-column: 1 / -1;
  grid-row: 2;
  font-size: 0.82rem;
  font-weight: 400;
  color: #5f6368;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
@media (max-width: 460px) {
  .reviews-summary {
    gap: 0.65rem;
    padding: 0.7rem 0.9rem;
  }
  .rb-text strong {
    font-size: 1.3rem;
  }
  .rs-stars {
    font-size: 0.85rem;
  }
}/* Reviews page: live Google review cards (regenerated weekly by
   fetch-reviews.mjs from the keyless feed). House card geometry, gold stars. */
.reviews-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1.25rem;
  margin-top: 2.25rem;
}
/* The reviews page uses the same `.review` card as the homepage strip — one
   card component sitewide. `.review-card` is kept on those articles purely
   as the hook for the display cap below and reviews-cap.js; it carries no
   look of its own, or the two would read as different widgets. */
.reviews-grid .review:nth-child(3n + 2) .rv-avatar {
  background: #33383d;
}
.reviews-grid .review:nth-child(3n) .rv-avatar {
  background: var(--yellow);
}/* Reviews page display cap: 3 cards visible on mobile (<=640px), 12 on
 * desktop, pure CSS so it holds even with JS off. assets/js/reviews-cap.js
 * progressively reveals further same-size batches via the .rc-shown class
 * (never removes a card from the DOM — stays crawlable). This block and the
 * "Show more reviews" button live outside the <div class="reviews-grid">
 * markup itself, which is the only region fetch-reviews.mjs regenerates
 * weekly, so neither survives a refresh untouched. */
.reviews-grid .review-card:nth-of-type(n + 4) {
  display: none;
}
@media (min-width: 641px) {
  .reviews-grid .review-card:nth-of-type(n + 4) {
    display: flex;
  }
  .reviews-grid .review-card:nth-of-type(n + 13) {
    display: none;
  }
}
.reviews-grid .review-card.rc-shown {
  display: flex !important;
}
.reviews-more-btn {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 1.75rem auto 0;
  min-height: 48px;
  cursor: pointer;
  font: inherit;
}
@media (max-width: 640px) {
  .reviews-more-btn {
    width: 100%;
  }
}/* Verified-reviews badge, styled to Google's own surface language rather than
   the site's chunky house style: hairline #dadce0 border, Material elevation
   instead of a hard offset shadow, Google's text greys (#202124 / #5f6368),
   Google blue for the action, and the body font rather than the display face.
   The whole card is the link. */
.verified-badge {
  display: flex;
  align-items: center;
  gap: 1rem;
  max-width: 44rem;
  margin: 2.25rem auto 0;
  padding: 1rem 1.15rem;
  background: #fff;
  border: 1px solid #dadce0;
  border-radius: var(--r-md);
  box-shadow: none;
  text-decoration: none;
  font-family: var(--font-body);
  transition: box-shadow 160ms ease, border-color 160ms ease;
}
.verified-badge:hover,
.verified-badge:focus-visible {
  transform: none;
  border-color: transparent;
  box-shadow:
    0 1px 2px rgba(60, 64, 67, 0.3),
    0 2px 6px 2px rgba(60, 64, 67, 0.15);
}
.vb-mark {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 0;
  background: transparent;
}
.vb-body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.vb-top {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.95rem;
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: #202124;
  display: flex;
  align-items: center;
  gap: 0.45rem;
}/* Google shows a star row beside the average rather than a claim of veracity,
   so the badge does the same: a factual summary, not a statement from us. */
.vb-stars {
  color: #fbbc04;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  margin-right: 0.15rem;
}
.vb-sub {
  font-size: 0.82rem;
  color: #5f6368;
  line-height: 1.45;
  letter-spacing: 0.01em;
}
.vb-go {
  margin-left: auto;
  flex-shrink: 0;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.85rem;
  letter-spacing: 0.01em;
  color: #1a73e8;
  white-space: nowrap;
}
.verified-badge:hover .vb-go {
  text-decoration: underline;
}
@media (max-width: 640px) {
  .verified-badge {
    flex-wrap: wrap;
    gap: 0.75rem;
  }
  .vb-go {
    margin-left: 0;
    width: 100%;
  }
}/* Town index */
.region {
  border-top: 1px solid var(--line);
  padding-top: 1.5rem;
  margin-top: 2.5rem;
}
.region h3 {
  font-size: 1.1rem;
  letter-spacing: 0.02em;
  margin-bottom: 0.5rem;
}
.region .region-cap {
  font-size: 0.95rem;
  color: var(--muted);
  margin-bottom: 1rem;
}
.region-towns {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.5rem 1.5rem;
  list-style: none;
  padding: 0;
  margin: 0;
}
@media (min-width: 700px) {
  .region-towns {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (min-width: 1000px) {
  .region-towns {
    grid-template-columns: repeat(4, 1fr);
  }
}
.region-towns li a {
  color: var(--ink);
  text-decoration: none;
  font-size: 0.97rem;
  border-bottom: 1px dotted transparent;
}
.region-towns li a:hover {
  border-bottom-color: var(--yellow);
}
.region-towns .hq a {
  font-weight: 700;
}
.region-towns .hq a::after {
  content: " · HQ";
  color: var(--muted);
  font-weight: 400;
  font-size: 0.85rem;
}/* Items lists for acceptable-items page */
.items-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-top: 2rem;
}
@media (min-width: 800px) {
  .items-grid {
    grid-template-columns: 1fr 1fr;
  }
}
.items-block {
  background: #fff;
  border: 1px solid var(--line);
  border-left: 4px solid var(--yellow);
  padding: 1.5rem 1.75rem;
  border-radius: var(--r-sm);
}
.items-block.warn {
  border-left-color: #c4574e;
}
.items-block.no {
  border-left-color: var(--black);
}
.items-block h3 {
  font-size: 1.15rem;
  margin-bottom: 0.75rem;
}
.items-block ul {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.97rem;
  line-height: 1.7;
  color: var(--ink);
}/* Contact NAP card */
.nap-card {
  background: var(--bg-warm);
  border: 1px solid var(--line);
  padding: 2rem;
  border-radius: var(--r-sm);
}
.nap-card .label {
  font-family: var(--font-display);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: block;
  margin-bottom: 0.25rem;
}
.nap-card .val {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--black);
  margin-bottom: 1.25rem;
  display: block;
}
.nap-card .val a {
  color: var(--black);
  text-decoration: none;
  border-bottom: 2px solid var(--yellow);
}/* ===== Town search ===== */
.town-search {
  margin: 0 0 3rem;
  max-width: 640px;
  position: relative;
}
.town-search label {
  display: block;
  font-family: var(--font-display) !important;
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--black);
  margin: 0 0 0.65rem;
}
.town-search-input-wrap {
  position: relative;
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: var(--r-md);
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.town-search-input-wrap:focus-within {
  border-color: var(--yellow);
  box-shadow: 0 0 0 4px rgba(245, 184, 0, 0.18);
}
.town-search input[type="search"] {
  width: 100%;
  padding: 1.1rem 3rem 1.1rem 3.25rem;
  font-family: var(--font-body) !important;
  font-size: 1.1rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  border-radius: var(--r-md);
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  font-weight: 500;
}
.town-search input[type="search"]::-webkit-search-decoration,
.town-search input[type="search"]::-webkit-search-cancel-button,
.town-search input[type="search"]::-webkit-search-results-button,
.town-search input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none;
  appearance: none;
}
.town-search input::placeholder {
  color: #9a9a9a;
  font-weight: 400;
}
.town-search-icon {
  position: absolute;
  left: 1.1rem;
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 22px;
  color: var(--ink);
  pointer-events: none;
  opacity: 0.7;
}
.town-search-input-wrap:focus-within .town-search-icon {
  opacity: 1;
  color: var(--black);
}

.town-search .clear-btn {
  position: absolute;
  right: 0.65rem;
  top: 50%;
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  background: var(--bg-warm);
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  border-radius: 50%;
  display: none;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1;
  transition:
    background 0.15s,
    color 0.15s;
}
.town-search .clear-btn:hover {
  background: var(--yellow);
  color: var(--black);
}
.town-search.has-query .clear-btn {
  display: flex;
}

.town-search-count {
  margin-top: 0.85rem;
  font-size: 0.92rem;
  color: var(--muted);
  font-family: var(--font-body);
  min-height: 1.2em;
}
.town-search-count strong {
  color: var(--black);
  font-weight: 700;
}/* ===== Suggestions dropdown ===== */
.town-suggestions {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  background: #fff;
  border: 2px solid var(--ink);
  border-radius: var(--r-md);
  box-shadow: 0 16px 32px rgba(0, 0, 0, 0.12);
  max-height: 380px;
  overflow-y: auto;
  z-index: 30;
  display: none;
  padding: 0.35rem 0;
}
.town-suggestions.is-open {
  display: block;
}
.town-suggestion {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 1.1rem;
  text-decoration: none;
  color: var(--ink);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.3;
  border: 0;
}
.town-suggestion + .town-suggestion {
  border-top: 1px solid var(--line);
}
.town-suggestion:hover,
.town-suggestion.is-active {
  background: var(--yellow-tint);
}
.town-suggestion.is-active {
  outline: 2px solid var(--yellow);
  outline-offset: -2px;
}
.town-suggestion-name {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--black);
  font-size: 1.05rem;
}
.town-suggestion-name mark {
  background: transparent;
  color: var(--yellow-deep);
  font-weight: 700;
  padding: 0;
}
.town-suggestion-region {
  font-size: 0.82rem;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}
.town-suggestion-empty {
  padding: 1rem 1.1rem;
  font-size: 0.95rem;
  color: var(--muted);
  font-style: italic;
}/* ===== No-match fallback panel ===== */
.no-match {
  display: none;
  padding: 2rem 1.75rem;
  margin: 0 0 2rem;
  background: var(--bg-warm);
  border-left: 4px solid var(--yellow);
  border-radius: var(--r-sm);
}
.no-match.is-active {
  display: block;
}
.no-match h3 {
  font-size: 1.35rem;
  margin: 0 0 0.5rem;
}
.no-match p {
  color: var(--muted);
  font-size: 1.02rem;
  max-width: 36em;
  margin: 0 0 1.25rem;
}/* Hidden state for filtered items */
.region-towns li.is-hidden,
.region.is-hidden {
  display: none;
}/* ===== Blog featured image / category banner ===== */
.featured-image {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  border-radius: var(--r-md);
  border: 2px solid var(--ink);
  margin: 0;
  display: block;
}
.post-banner {
  background: var(--yellow);
  border: 3px solid var(--black);
  border-radius: var(--r-md);
  padding: 2.25rem 1.75rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin: 0;
}
.post-banner-mark {
  width: 72px;
  height: 72px;
  background: var(--black);
  color: var(--yellow);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 2.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
  flex-shrink: 0;
  line-height: 1;
}
.post-banner-text {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.8rem, 4.5vw, 3rem);
  letter-spacing: 0.04em;
  color: var(--black);
  text-transform: uppercase;
  line-height: 1.02;
}
.post-banner-text small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--ink);
  margin-top: 0.35rem;
}
@media (max-width: 600px) {
  .post-banner {
    padding: 1.5rem 1.25rem;
    gap: 1rem;
  }
  .post-banner-mark {
    width: 56px;
    height: 56px;
    font-size: 1.9rem;
  }
}

/* Stop region container from being too tight on mobile when search opens */
@media (max-width: 600px) {
  .town-suggestions {
    max-height: 280px;
  }
  .town-suggestion-region {
    display: none;
  }
}/* ===== Service area map ===== */
.map-wrap {
  position: relative;
  margin: 0 0 2.5rem;
}
#service-map {
  height: 640px;
  width: 100%;
  border: 2px solid var(--ink);
  border-radius: var(--r-md);
  background: var(--bg-warm);
  z-index: 1;
}
@media (max-width: 600px) {
  #service-map {
    height: 420px;
  }
}/* Static service-area map (image + our own pin, no JS) */
.town-map-static {
  position: relative;
  border: 2px solid var(--ink);
  border-radius: var(--r-md);
  overflow: hidden;
  line-height: 0;
  box-shadow: 6px 6px 0 var(--black);
}
.town-map-static img {
  display: block;
  width: 100%;
  height: auto;
}
.town-map-pin {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -100%);
  width: 30px;
  height: 40px;
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
}/* Static service-AREA map (home + hub): base image + SVG coverage overlay + HQ pin, no JS */
.area-map-static {
  position: relative;
  max-width: 880px;
  margin: 0 auto;
  border: 2px solid var(--ink);
  border-radius: var(--r-md);
  overflow: hidden;
  line-height: 0;
  box-shadow: 6px 6px 0 var(--black);
}
.area-map-static img {
  display: block;
  width: 100%;
  height: auto;
}
.area-map-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.area-map-pin {
  position: absolute;
  width: 30px;
  height: 40px;
  transform: translate(-50%, -100%);
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
  z-index: 2;
}/* Label that floats above the HQ pin so it's clear the pin = home base */
.area-map-flag {
  position: absolute;
  transform: translate(-50%, -58px);
  background: var(--black);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.26rem 0.7rem;
  border-radius: var(--r-pill);
  white-space: nowrap;
  line-height: 1.2;
  pointer-events: none;
  z-index: 3;
  box-shadow: 0 3px 9px rgba(0, 0, 0, 0.28);
}/* soft diamond nub instead of a sharp triangle */
.area-map-flag::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 9px;
  height: 9px;
  background: var(--black);
  border-radius: 0 0 2px 0;
  transform: translate(-50%, -5px) rotate(45deg);
}/* Legend under the area map: explains the pin and the shaded coverage area */
.area-map-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.6rem;
  margin: 0.95rem auto 0;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.25;
}
.area-map-legend > span {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.amleg-pin {
  display: inline-flex;
  flex-shrink: 0;
}
.amleg-swatch {
  width: 20px;
  height: 14px;
  flex-shrink: 0;
  background: rgba(253, 93, 20, 0.16);
  border: 2px solid #141414;
  border-radius: var(--r-sm);
}

.map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-top: 0.85rem;
  font-size: 0.9rem;
  color: var(--muted);
  font-family: var(--font-body);
}
.map-legend .legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.map-legend .dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--yellow);
  border: 2px solid var(--ink);
  flex-shrink: 0;
}
.map-legend .dot.hq {
  background: var(--ink);
  border-color: var(--yellow);
  position: relative;
}/* Leaflet marker custom styling */
.town-marker-icon {
  background: transparent;
  border: 0;
}
.town-marker-icon .dot {
  width: 16px;
  height: 16px;
  background: var(--yellow);
  border: 2px solid var(--ink);
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  transition: transform 0.12s;
}
.town-marker-icon:hover .dot {
  transform: scale(1.25);
}
.town-marker-icon.hq .dot {
  width: 26px;
  height: 26px;
  background: var(--ink);
  border-color: var(--yellow);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--yellow);
  font-size: 0.62rem;
  letter-spacing: 0.05em;
}
.town-marker-icon.hq .dot::after {
  content: "HQ";
}/* Leaflet popup styling */
.leaflet-popup-content-wrapper {
  border-radius: var(--r-sm);
  border: 2px solid var(--ink);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}
.leaflet-popup-content {
  margin: 0.85rem 1rem;
  font-family: var(--font-body);
}
.leaflet-popup-content .popup-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--black);
  display: block;
  margin-bottom: 0.35rem;
}
.leaflet-popup-content .popup-name .hq-tag {
  font-size: 0.72rem;
  color: var(--muted);
  font-weight: 600;
  margin-left: 0.4rem;
}
.leaflet-popup-content .popup-link {
  display: inline-block;
  color: var(--black);
  text-decoration: none;
  border-bottom: 2px solid var(--yellow);
  font-weight: 700;
  font-size: 0.92rem;
  padding-bottom: 1px;
}
.leaflet-popup-content .popup-link:hover {
  color: var(--yellow-deep);
}
.leaflet-popup-tip {
  border: 2px solid var(--ink);
}/* ===== Homepage size cards with image + price (3-up) ===== */
.sizes.cols-3 {
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .sizes.cols-3 {
    grid-template-columns: repeat(3, 1fr);
  }
}
.size-card.priced {
  display: flex;
  flex-direction: column;
  text-align: left;
}
.size-card.priced img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  height: auto;
  margin-bottom: 0.5rem;
}
.size-card.priced .price {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  color: var(--yellow-deep);
  display: block;
  margin: 0.1rem 0 0.6rem;
}
.size-card.priced ul {
  list-style: none;
  padding: 0;
  margin: 0.25rem 0 0;
  font-size: 0.82rem;
  color: var(--muted);
  line-height: 1.5;
}
.size-card.priced ul li::before {
  content: "✓ ";
  color: var(--yellow-deep);
  font-weight: 700;
}/* ===== Junk-removal item chips ===== */
.item-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6rem 1rem;
  margin-top: 1.5rem;
}
@media (min-width: 700px) {
  .item-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}
.item-grid span {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--line);
}/* Job types that have their own page read as links without breaking the row. */
.item-grid a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--red-deep);
  text-underline-offset: 3px;
}
.item-grid a:hover {
  color: var(--red-deep);
}
.item-grid span::before {
  content: "🔥";
  font-size: 0.85rem;
  flex: 0 0 auto;
}
.steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin-top: 1.5rem;
}
@media (min-width: 760px) {
  .steps {
    grid-template-columns: repeat(3, 1fr);
  }
}
.step {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 1.25rem 1.25rem 1.4rem;
}
.step .n {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  color: var(--yellow-deep);
  line-height: 1;
}
.step h3 {
  margin: 0.4rem 0 0.3rem;
}
.step p {
  margin: 0;
  font-size: 0.92rem;
  color: var(--muted);
}
@media (min-width: 760px) {
  .steps.steps-4 { grid-template-columns: repeat(4, 1fr); }
}/* ===== Pricing table + fee list ===== */
/* Let the rates table scroll on narrow screens instead of pushing the page wide. */
.price-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}/* Per-row "Book" button: deep-links to that exact size + rental period. */
.price-table .row-book {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: #fff;
  background: var(--red-deep);
  padding: 0.4rem 0.7rem;
  border-radius: var(--r-sm);
  text-decoration: none;
  white-space: nowrap;
  transition: background 150ms ease;
}
.price-table .row-book:hover,
.price-table .row-book:focus-visible {
  /* Red family, not var(--yellow): that token is green on this brand, and a
     red button must not change color family on hover. */
  background: var(--red-deeper);
}

.price-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.5rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.price-table th,
.price-table td {
  text-align: left;
  padding: 0.9rem 1rem;
  border-bottom: 1px solid var(--line);
}
.price-table thead th {
  background: var(--black);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
}
.price-table tbody tr:last-child td {
  border-bottom: none;
}
.price-table .size {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--black);
}
.price-table .amt {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--yellow-deep);
  white-space: nowrap;
}
.fee-list {
  list-style: none;
  padding: 0;
  margin: 1.25rem 0 0;
  display: grid;
  gap: 0.75rem;
}
.fee-list li {
  background: #fff;
  border: 1px solid var(--line);
  border-left: 4px solid var(--yellow);
  border-radius: var(--r-sm);
  padding: 0.85rem 1.1rem;
  font-size: 0.95rem;
}
.fee-list li strong {
  font-family: var(--font-display);
  color: var(--black);
}
.includes {
  list-style: none;
  padding: 0;
  margin: 1.25rem 0 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
}
@media (min-width: 600px) {
  .includes {
    grid-template-columns: repeat(2, 1fr);
  }
}
.includes li {
  font-size: 0.97rem;
}
.includes li::before {
  content: "✓ ";
  color: var(--yellow-deep);
  font-weight: 700;
}/* ===== Service menu (Residential / Commercial lists) ===== */
.svc-menu {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-top: 1.5rem;
}
@media (min-width: 760px) {
  .svc-menu {
    grid-template-columns: repeat(2, 1fr);
  }
}
.svc-menu .col {
  background: #fff;
  border: 1px solid var(--line);
  border-top: 4px solid var(--yellow);
  border-radius: var(--r-sm);
  padding: 1.5rem 1.5rem 1.75rem;
}
.svc-menu .col h3 {
  margin: 0 0 0.75rem;
}
.svc-menu .col ul {
  list-style: none;
  padding: 0;
  margin: 0 0 1.25rem;
}
.svc-menu .col li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 1rem;
  font-weight: 500;
}
.svc-menu .col li::before {
  content: "🔥 ";
}
.svc-area {
  margin-top: 1.5rem;
  font-size: 0.95rem;
  color: var(--muted);
  line-height: 1.6;
}/* ===== Acceptable items: approved / restricted lists ===== */
.no-list {
  list-style: none;
  padding: 0;
  margin: 1.25rem 0 0;
  display: grid;
  gap: 0.5rem;
}
.no-list li {
  font-size: 0.97rem;
}
.no-list li::before {
  content: "✕ ";
  color: var(--yellow-deep);
  font-weight: 700;
}/* ===== Online booking embed (survcart / Docket) ===== */
.booking-embed {
  position: relative;
  width: 100%;
  min-height: 720px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  background: #fff;
}
.booking-embed iframe {
  width: 100%;
  min-height: 720px;
  height: 100%;
  border: 0;
  display: block;
}/* ===== Full-bleed hero (real-photo background) ===== */
.hero.hero-bg {
  position: relative;
  padding: clamp(4rem, 9vw, 7rem) 0 clamp(5rem, 10vw, 8rem);
  border-bottom: 0;
  overflow: hidden;
  isolation: isolate;
  min-height: 70vh;
  display: flex;
  align-items: center;
}
.hero.hero-bg .wrap.hero-grid { width: 100%; }
.hero-bg-media { position: absolute; inset: 0; z-index: -2; }
.hero-bg-media img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.hero-bg-overlay {
  position: absolute;
  inset: 0;
  /* Lighter over the sky (top) so the sunset shows, darker toward the bottom
     where the headline + buttons sit. */
  background: linear-gradient(180deg, rgba(0,0,0,0.42) 0%, rgba(0,0,0,0.62) 46%, rgba(0,0,0,0.82) 100%);
  z-index: -1;
}
@media (min-width: 900px) {
  .hero-bg-overlay {
    /* Directional scrim: dark behind the left text column, clear over the
       right/top so the sunset comes through. */
    background:
      linear-gradient(90deg, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.62) 42%, rgba(0,0,0,0.08) 72%),
      linear-gradient(0deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.12) 38%, rgba(0,0,0,0) 62%);
  }
}
.hero.hero-bg .hero-grid { align-items: center; }
.hero.hero-bg .hero-content { color: #fff; }
.hero.hero-bg h1 { color: #fff; font-size: clamp(2.35rem, 5.9vw, 4.6rem); line-height: 0.97; letter-spacing: -0.028em; max-width: 15ch; margin-bottom: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.92), 0 1px 22px rgba(0,0,0,0.55); }
/* AMC-pattern sub: one flowing paragraph under the H1, slightly larger than
   body, soft shadow so it reads on the photo. */
.hero.hero-bg .hero-sub { font-size: clamp(1.05rem, 1.6vw, 1.28rem); line-height: 1.55; max-width: 34rem; margin: 1.1rem 0 1rem; color: rgba(255, 255, 255, 0.94); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6), 0 2px 18px rgba(0, 0, 0, 0.4); }
.hero.hero-bg .hero-accent { color: #39ab2a; display: inline-block; }
@media (min-width: 900px) {
  .hero-bg-media img { object-position: right center; }
}
/* "Springfield,&nbsp;MO" is one unbreakable unit, and at the 2.35rem clamp
   floor it sets 295px against the 278px of content width a 320px phone has
   left after padding - so it ran flush to the screen edge. Only the very
   narrow band needs the smaller size; 375px and up keep the full 2.35rem. */
@media (max-width: 360px) {
  .hero.hero-bg h1 { font-size: 2.05rem; }
}
/* Measured 2026-08-21: worst pixel under this paragraph was 3.5:1 against
   the 4.5:1 AA floor for 17.9px text - the bright gravel patch the photo
   puts behind the last two lines. Two causes, both here: the text was 85%
   white (a 15% contrast giveaway for nothing) and, unlike the h1 directly
   above it, it carried NO text-shadow. Full white plus the h1's own shadow
   recipe fixes it without darkening the photo further. */
/* Hero promise line: the one-sentence benefit under the H1. Slightly heavier
   than the description that follows it so the read order is promise -> what
   -> price -> speed. */
@media (max-width: 760px) {
    }

.hero.hero-bg .lead {
  color: #fff;
  text-shadow: 0 1px 3px rgba(0,0,0,0.9), 0 1px 18px rgba(0,0,0,0.6);
  max-width: 36em;
  margin-bottom: 2rem;
  font-size: clamp(1rem, 1.4vw, 1.15rem);
}
.eyebrow-on-dark {
  background: none; padding: 0; color: #39ab2a;
  font-family: var(--font-display); font-weight: 700; font-size: 1rem;
  letter-spacing: 0.17em; text-transform: uppercase; margin-bottom: 1.25rem; display: inline-block;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.95), 0 0 4px rgba(0, 0, 0, 0.85), 0 2px 14px rgba(0, 0, 0, 0.6);
}
.hero-ctas { display: flex; flex-wrap: wrap; gap: 1.1rem 0.75rem; margin-bottom: 1.75rem; }
.btn.btn-on-dark, .btn-secondary.btn-on-dark {
  background: transparent; color: #fff; border-color: #fff; box-shadow: 4px 4px 0 var(--yellow);
}
.btn.btn-on-dark:hover, .btn-secondary.btn-on-dark:hover { background: #fff; color: var(--black); }/* Trust bar */
.trust-bar {
  list-style: none; padding: 0; margin: 1.5rem 0 0;
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.25rem;
  font-family: var(--font-display); font-size: 0.9rem; font-weight: 600; color: var(--ink);
}
.trust-bar li { display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap; }
.trust-bar .trust-check {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; background: var(--yellow); color: var(--black);
  font-size: 0.72rem; font-weight: 700; border: 1px solid var(--black);
}
.trust-bar-on-dark { color: #fff; font-weight: 700; gap: 0.6rem 0.6rem; }
.trust-bar-on-dark li {
  background: rgba(17,17,17,0.85); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  padding: 7px 14px 7px 8px; border-radius: var(--r-pill); border: 1px solid rgba(255,255,255,0.22); color: #fff;
}
.trust-bar-on-dark .trust-check { background: var(--yellow); color: var(--black); border: 1px solid var(--black); }/* Hero floating card */
.hero-card { background: #fff; border-radius: var(--r-md); padding: 1.5rem; border: 3px solid var(--black); box-shadow: 8px 8px 0 var(--yellow); position: relative; z-index: 1; }
.hero-card-head { display: flex; align-items: center; gap: 0.85rem; margin-bottom: 1.25rem; padding-bottom: 1rem; border-bottom: 2px solid var(--line); }
.hero-card-logo { width: 48px; height: 48px; flex-shrink: 0; object-fit: contain; }
.hero-card-title { font-family: var(--font-display); font-weight: 700; font-size: 1.5rem; margin: 0; color: var(--black); line-height: 1.1; }
.hero-card-list { list-style: none; padding: 0; margin: 0 0 1.25rem; display: flex; flex-direction: column; gap: 0.7rem; }
.hero-card-list li { display: flex; align-items: flex-start; gap: 0.6rem; font-size: 0.95rem; line-height: 1.4; color: var(--ink); font-family: var(--font-display); font-weight: 600; }
.hero-card-check { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; background: var(--yellow); color: var(--black); font-size: 0.72rem; font-weight: 700; flex-shrink: 0; margin-top: 1px; border: 2px solid var(--black); }
.hero-card-cta { display: block; background: var(--red-deep); color: #fff; text-align: center; padding: 1rem; font-family: var(--font-display); font-weight: 700; font-size: 1rem; text-decoration: none; border-radius: var(--r-sm); box-shadow: 0 0 0 var(--yellow); transition: background 150ms ease, transform 150ms ease, box-shadow 150ms ease; }
.hero-card-cta:hover { background: var(--red-deeper); transform: translate(-3px, -3px); box-shadow: 6px 6px 0 var(--yellow); }
.hero-card-cta:active { transform: translate(1px, 1px); box-shadow: 0 0 0 var(--yellow); }/* ===== Full-bleed centered hero (major pages: dumpsters, services, service area) ===== */
.hero.hero-bg-centered {
  text-align: center;
  padding-bottom: clamp(7rem, 11vw, 9rem);
}
.hero.hero-bg-centered .hero-content-centered {
  max-width: 56rem;
  margin: 0 auto;
  color: #fff;
}
.hero.hero-bg-centered h1 {
  color: #fff;
  font-size: clamp(2rem, 4.8vw, 3.6rem);
  line-height: 1.05;
  margin-bottom: 1rem;
}
.hero.hero-bg-centered .hero-accent {
  color: var(--yellow);
}
.hero.hero-bg-centered .lead {
  color: rgba(255, 255, 255, 0.88);
  max-width: 44rem;
  margin: 0 auto 2rem;
  font-size: clamp(1rem, 1.4vw, 1.15rem);
}
.hero.hero-bg-centered .hero-ctas {
  justify-content: center;
  margin-bottom: 0;
}
.hero.hero-bg-centered .eyebrow {
  margin-bottom: 1.25rem;
}/* ============================================================
   COLOR HIERARCHY (override): RED = filled action buttons,
   ORANGE = accents (eyebrows, checks, underlines, prices, etc.)
   Red ties the CTAs to the red dumpster; orange stays the accent.
   ============================================================ */
.btn-primary {
  background: var(--red-deep);
  color: #fff;
}
.btn-primary:hover {
  background: var(--red-deeper);
}/* Topbar phone pill + scroll-morph Call/Text CTAs */
.tel-cta {
  background: var(--red-deep);
  color: #fff;
}
.tel-cta:hover {
  background: var(--red-deeper);
}
.tel-cta::before {
  background: #fff;
}/* Big phone + text CTAs (hero/section/contact) */
.tel-big,
.text-big {
  background: var(--red-deep);
  color: #fff;
}
.tel-big:hover,
.text-big:hover {
  background: var(--red-deeper);
}/* Prominent "Book Online" button — flame-orange so it stands out from the
   red Call/Text buttons. The primary action on dumpster pages. */
.book-big {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.25rem, 2.3vw, 1.65rem);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  /* Filled red like every other primary CTA. It was the site's only green
   button (black on green, 3.64:1 - below AA), which read as a different
   kind of control and put the accent colour on an action. */
  background: var(--red-deep);
  color: #fff;
  padding: 0.85rem 1.5rem;
  border-radius: var(--r-md);
  border: 2px solid var(--black);
  box-shadow: 4px 4px 0 var(--black);
  transition:
    transform 120ms ease,
    box-shadow 120ms ease,
    background 120ms ease;
}
.book-big:hover {
  background: var(--red-deeper);
  color: #fff;
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--black);
}
.book-big:active {
  transform: translate(2px, 2px);
  box-shadow: 0 0 0 var(--black);
}/* Unified CTA button group: one centered, wrapping row (fixes the
   split-row / off-center spacing). */
.cta-buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.1rem 0.85rem;
  margin-top: 1.5rem;
}
.cta-buttons .tel-big,
.cta-buttons .text-big,
.cta-buttons .book-big {
  margin: 0;
}
.cta-final .cta-buttons {
  justify-content: center;
}
.tel-big::before,
.text-big::before {
  background: #fff;
}
.mobile-cta a.call {
  background: var(--red-deep);
  color: #fff;
}
.price-asterisk {
  margin: 1rem 0 0;
  font-size: 0.9rem;
  color: var(--muted);
}/* ============================================================
   Shared structural/UX components
   brought over from the reference site. Orange (--yellow) =
   accent, consistent with the red-primary hierarchy.
   ============================================================ */

/* --- Size-card polish (chunky border + top accent bar + hover lift) --- */
.size-card {
  border: 3px solid var(--black);
  border-radius: var(--r-md);
  box-shadow: 6px 6px 0 var(--black);
  position: relative;
  /* No overflow:hidden - the availability badge straddles the top border and
     a clip slices it in half. This is what defeated three earlier passes at
     the badge; wasteonwheels carries the same warning in its own CSS. */
}
.size-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  background: var(--yellow);
}
.size-card:hover {
  transform: translate(-3px, -3px);
  box-shadow: 8px 8px 0 var(--yellow) var(--yellow);
  border-color: var(--black);
}
.size-card.priced {
  padding-top: 1.75rem;
}/* Featured "Most Popular" card (the 20-yard) — red frame + labeled banner */
/* RANK vs STATUS - two kinds of information, two visual registers rather
   than two competing pills (ported from wasteonwheels, which tried six
   positions before settling here).

   "Available Today" is a STATUS: it is on every card, so it stays the filled
   pill straddling the border - same position on each card, scannable down
   the row. "Most Popular" is a RANK: it is on exactly ONE card, and a second
   filled pill of the same shape read as a mismatched twin of the first
   wherever it was put. So rank becomes a typographic label inside the card
   above the size name, where product labels live on real product cards.

   The featured card's FRAME stays identical to its neighbours. A red border,
   a heavier shadow and a 10px lift all made sense under a red top ribbon;
   with the ribbon gone they are orphaned, and one card sitting higher with a
   different border reads as a rendering fault rather than as emphasis. */
.size-card .yd::before {
  content: "";
  display: block;
  height: 1.15rem;
  margin-bottom: 0.15rem;
}
.size-card.featured .yd::before {
  content: "★ Most Popular";
  color: var(--red-deep);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.15rem;
}/* --- Why-us pillar grid --- */
.pillar-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin-top: 2.5rem;
}
@media (min-width: 850px) {
  .pillar-grid {
    grid-template-columns: 1fr 1fr 1fr;
  }
}
.pillar {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  padding: 1.5rem 1.25rem;
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
.pillar-icon {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--black);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--black);
}
.pillar-icon svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
}
.pillar h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  margin: 0 0 0.4rem;
  line-height: 1.3;
}
.pillar p {
  margin: 0;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.45;
}/* --- Town-page "services available here" quick-link cards --- */
.town-services-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  margin-top: 1.25rem;
}
@media (min-width: 600px) {
  .town-services-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media (min-width: 900px) {
  .town-services-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}
.town-service-card {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.9rem 1rem;
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  text-decoration: none;
  color: inherit;
  transition:
    transform 150ms,
    box-shadow 150ms;
  box-shadow: 4px 4px 0 var(--black) var(--black);
}
.town-service-card:hover {
  transform: translate(-2px, -2px);
  box-shadow: 4px 4px 0 var(--yellow) var(--yellow);
}
.town-service-card .ts-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.97rem;
  color: var(--black);
}
.town-service-card .ts-detail {
  font-size: 0.78rem;
  color: var(--muted);
  font-weight: 600;
}/* --- Contact quick-links related block --- */
.quick-links {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  margin-top: 1.25rem;
}
@media (min-width: 640px) {
  .quick-links {
    grid-template-columns: 1fr 1fr;
  }
}
@media (min-width: 900px) {
  .quick-links {
    grid-template-columns: repeat(4, 1fr);
  }
}/* ============================================================
   DESIGN POLISH PASS (2026-06-11): unify flat cards into the
   brand's chunky bordered-card family for visual consistency.
   ============================================================ */

/* Process steps — number becomes an orange circle badge */
.step {
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  padding: 1.6rem 1.4rem 1.45rem;
  box-shadow: 4px 4px 0 var(--black) var(--black);
  position: relative;
  transition:
    transform 150ms ease,
    box-shadow 150ms ease;
}
.step:hover {
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--yellow) var(--yellow);
}
.step .n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--black);
  border: 2px solid var(--black);
  font-size: 1.3rem;
  margin-bottom: 0.9rem;
}/* Specialty-cleanout cards (services.html) — were an orphan dark
   image-card with no image (rendered as a black box). Restyle to the
   site's white chunky card with an orange top accent. */
.svc-card {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  box-shadow: 6px 6px 0 var(--black);
  min-height: 0;
  overflow: hidden;
  position: relative;
  transition:
    transform 150ms ease,
    box-shadow 150ms ease;
}
.svc-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  background: var(--yellow);
  z-index: 2;
}
.svc-card:hover {
  transform: translate(-3px, -3px);
  box-shadow: 8px 8px 0 var(--yellow) var(--yellow);
}
.svc-card .svc-body {
  background: none;
  padding: 2.25rem 1.85rem 1.85rem;
}
.svc-card h3 {
  color: var(--black);
}
.svc-card p {
  color: var(--ink);
}
.svc-card a.svc-link {
  color: var(--yellow-deep);
  border-bottom: 2px solid var(--yellow);
  padding-bottom: 1px;
}
.svc-card a.svc-link:hover {
  color: var(--black);
}/* Restricted-items list — red ✕ marks (red = stop/no) to contrast
   with the orange ✓ on the approved list. */
.no-list li::before {
  color: var(--red);
}/* ============================================================
   "What goes in" allow / don't-allow card grid (dumpsters page).
   DF colors: orange = accepted,
   red = not accepted (matches our do/don't system).
   ============================================================ */
.allow-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  margin-top: 2.5rem;
}
@media (min-width: 800px) {
  .allow-grid {
    grid-template-columns: 1fr 1fr;
    gap: 1.75rem;
  }
}
.allow-card {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  overflow: hidden;
  box-shadow: 6px 6px 0 var(--black);
  display: flex;
  flex-direction: column;
}
.allow-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.15rem 1.5rem;
}
.allow-yes .allow-head {
  background: var(--yellow);
  color: var(--black);
}
.allow-no .allow-head {
  background: var(--black);
  color: #fff;
}
.allow-head h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  margin: 0;
  color: inherit;
}
.allow-badge {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2px solid currentColor;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-weight: 700;
  font-size: 1rem;
}
.allow-yes .allow-badge {
  background: rgba(0, 0, 0, 0.1);
}
.allow-no .allow-badge {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
}
.allow-list {
  list-style: none;
  padding: 1.5rem 1.5rem 0;
  margin: 0;
  flex: 1;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.65rem;
}
@media (min-width: 480px) {
  .allow-list {
    grid-template-columns: 1fr 1fr;
    column-gap: 1rem;
  }
}
.allow-list li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
  border-radius: var(--r-md);
  border: 1.5px solid var(--line);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.92rem;
  line-height: 1.3;
  color: var(--ink);
  background: #fff;
}
.allow-yes .allow-list li {
  background: var(--yellow-tint);
  border-color: rgba(253, 93, 20, 0.4);
}
.allow-no .allow-list li {
  background: #f7f6f4;
  border-color: rgba(20, 20, 20, 0.14);
}
.allow-list li::before {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-weight: 700;
  font-size: 0.72rem;
  border: 1.5px solid var(--black);
}
.allow-yes .allow-list li::before {
  content: "✓";
  background: var(--yellow);
  color: var(--black);
}
.allow-no .allow-list li::before {
  content: "✕";
  background: var(--red-deep);
  color: #fff;
}
.allow-note {
  margin: 1.5rem;
  padding: 0.95rem 1.1rem;
  background: var(--bg-warm);
  border-radius: var(--r-md);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink);
  border-left: 3px solid var(--yellow);
}
.allow-no .allow-note {
  border-left-color: var(--red);
}/* ===== Why-us pillar grid (homepage "why folks keep calling us back") ===== */
.pillar-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin-top: 2.5rem;
}
@media (min-width: 850px) {
  .pillar-grid {
    grid-template-columns: 1fr 1fr 1fr;
  }
}
.pillar {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  padding: 1.6rem 1.35rem;
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  box-shadow: 4px 4px 0 var(--black) var(--black);
}
.pillar-icon {
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--black);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--black);
}
.pillar-icon svg {
  width: 24px;
  height: 24px;
  fill: currentColor;
}
.pillar h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  margin: 0 0 0.4rem;
  line-height: 1.3;
}
.pillar p {
  margin: 0;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.5;
}/* ============================================================
   ACCESSIBILITY (audit fixes): keyboard focus, reduced motion,
   mobile tap targets.
   ============================================================ */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
summary:focus-visible,
input:focus-visible,
[tabindex]:focus-visible,
.town-service-card:focus-visible,
.size-card:focus-visible {
  outline: 3px solid var(--yellow-deep);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}/* Light focus ring on red/dark surfaces for contrast */
.btn-primary:focus-visible,
.tel-cta:focus-visible,
.tel-big:focus-visible,
.text-big:focus-visible,
.btn-on-dark:focus-visible,
.hero-card-cta:focus-visible,
.cta-final a:focus-visible,
.mobile-cta a:focus-visible {
  outline-color: #fff;
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* Bigger mobile tap target on the topbar phone pill (was ~22px) */
@media (max-width: 999px) {
  .tel-cta {
    min-height: 44px;
    padding: 0.65rem 0.85rem;
    font-size: 0.9rem;
  }
}/* ===== Service accordion (junk-removal style) ===== */
.service-accordion {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.acc-item {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: box-shadow 150ms;
}
.acc-item[open] {
  box-shadow: 4px 4px 0 var(--yellow);
}
.acc-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.25rem;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  color: var(--black);
  transition: background 120ms;
}
.acc-item summary::-webkit-details-marker {
  display: none;
}
.acc-item summary:hover {
  background: #fafaf7;
}
.acc-title {
  flex: 1;
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  color: inherit;
}
.acc-icon {
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.7rem;
  line-height: 0.8;
  color: var(--black);
  transition: transform 0.2s;
}
.acc-icon::before {
  content: "+";
}
.acc-item[open] .acc-icon {
  transform: rotate(45deg);
}
.acc-body {
  padding: 0 1.25rem 1.25rem;
  color: var(--ink);
  line-height: 1.6;
  border-top: 1px solid var(--line);
  padding-top: 1rem;
  margin-top: 0;
}
.acc-body p {
  margin: 0 0 0.85rem;
  color: var(--ink);
}
.acc-link {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--black);
  text-decoration: none;
  border-bottom: 2px solid var(--yellow);
  padding-bottom: 1px;
}
.acc-link:hover {
  color: var(--red-deep);
  border-bottom-color: var(--black);
}/* ===== Mid-page booking CTA band ===== */
.cta-band {
  background: var(--red-deep);
  border: 3px solid var(--black);
  box-shadow: 8px 8px 0 var(--black);
  border-radius: var(--r-md);
  text-align: center;
  padding: 2.5rem 1.5rem;
}
.cta-band h2 {
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2rem);
  margin: 0 0 0.5rem;
}
.cta-band p {
  color: rgba(255, 255, 255, 0.92);
  margin: 0 0 1.5rem;
  font-size: 1.05rem;
}
.cta-band-row {
  display: flex;
  gap: 0.85rem;
  justify-content: center;
  flex-wrap: wrap;
}
.cta-band .btn-book {
  background: #fff;
  color: var(--red-deep);
  border: 2px solid var(--black);
}
.cta-band .btn-book:hover {
  background: var(--black);
  color: #fff;
}
.cta-band .btn-call {
  background: transparent;
  color: #fff;
  border: 2px solid #fff;
}
.cta-band .btn-call:hover {
  background: #fff;
  color: var(--red-deep);
}/* Contact-page Google Map embed */
.map-embed {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
  line-height: 0;
}
.map-embed iframe { display: block; width: 100%; }/* About-page "why us" cards */
.why-grid { display: grid; grid-template-columns: 1fr; gap: 1.25rem; }
@media (min-width: 800px) { .why-grid { grid-template-columns: repeat(3, 1fr); } }
.why-card { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-md); padding: 1.5rem 1.4rem; }
.why-card h3 { margin: 0 0 .5rem; font-family: var(--font-display); font-size: 1.15rem; }
.why-card p { margin: 0; color: var(--muted); }/* Pricing page "good to know" notes */
.price-note-grid { display: grid; grid-template-columns: 1fr; gap: 1.1rem; margin-top: 1.5rem; }
@media (min-width: 800px) { .price-note-grid { grid-template-columns: repeat(3, 1fr); } }
.price-note { border-left: 3px solid var(--red); padding: .25rem 0 .25rem 1rem; }
.price-note h3 { margin: 0 0 .35rem; font-family: var(--font-display); font-size: 1.05rem; }
.price-note p { margin: 0; color: var(--muted); font-size: 0.97rem; }/* ============================================================
   Homepage conversion additions (2026-07-12)
   Stats band · size-card actions · pull-quote · service-area map
   ============================================================ */

/* --- Stats band (real facts, sits under the hero) --- */
.stat-band { background: var(--black); }
.stat-band .wrap {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px; background: rgba(255, 255, 255, 0.12);
  border-radius: var(--r-md); overflow: hidden; margin-top: 0; margin-bottom: 0;
}
.stat-band { padding: 0; }
.stat-item {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 0.25rem; padding: 1.4rem 1rem;
  background: var(--black); color: #fff; text-decoration: none;
  transition: background 0.15s;
}
.stat-item:hover { background: #191919; }
.stat-item .si-val {
  font-family: var(--font-display); font-weight: 700; font-size: clamp(1.25rem, 2.4vw, 1.7rem);
  line-height: 1; color: #fff;
}
.stat-item:hover .si-val { color: var(--red); }
.stat-item .si-label {
  font-size: 0.8rem; line-height: 1.3; color: rgba(255, 255, 255, 0.72);
}
@media (max-width: 700px) {
  .stat-band .wrap { grid-template-columns: 1fr 1fr; }
}/* --- Size cards: per-duration price table --- */
.price-rows { list-style: none; padding: 0; margin: 0.5rem 0 0.7rem; }
.price-rows li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: 0.3rem 0; border-bottom: 1px dotted var(--line);
}
.price-rows li:last-child { border-bottom: none; }/* override the feature-bullet checkmark that .size-card.priced ul li::before adds */
.size-card.priced .price-rows li::before { content: none; }
.price-rows .dur {
  font-family: var(--font-display); font-weight: 600; font-size: 0.92rem;
  letter-spacing: 0.02em; text-transform: uppercase; color: var(--muted);
}
.price-rows .amt {
  font-family: var(--font-display); font-weight: 700; font-size: 1.4rem;
  line-height: 1; color: var(--red-deep);
}/* "Most Popular" pill for the best-value 3-day 20-yard option
   (pricing table row + the 20-yard page price list) */
.pop-badge {
  display: inline-block;
  background: var(--red-deep);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.16rem 0.45rem;
  border-radius: var(--r-sm);
  vertical-align: middle;
  margin-left: 0.5rem;
  white-space: nowrap;
}
.price-table tr.featured-row td { background: rgba(216, 51, 31, 0.06); }
.price-table tr.featured-row td:first-child { box-shadow: inset 3px 0 0 var(--red-deep); }
.price-rows li.featured .dur { color: var(--red-deep); }/* --- Size cards: info link + booking action footer --- */
.size-card-link { display: block; text-decoration: none; color: inherit; }
.size-card-dims {
  display: block; margin: 0 0 0.6rem; font-size: 0.82rem;
  color: var(--muted); line-height: 1.4;
}
.size-card-actions {
  display: flex; gap: 0.8rem 0.6rem; margin-top: auto; padding-top: 1.1rem;
}
.size-act {
  flex: 1; text-align: center; text-decoration: none;
  font-family: var(--font-display); font-weight: 700; font-size: 0.95rem;
  padding: 1rem 0.9rem; transition: background 0.15s, color 0.15s;
}
.size-act-book { background: var(--red-deep); color: #fff; }
.size-act-book:hover { background: var(--black); }
.size-act-info {
  background: transparent; color: var(--black);
  border: 1px solid var(--line);
}
.size-act-info:hover { border-color: var(--black); }/* --- Owner pull-quote (story section) --- */
.pull-quote {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.2rem, 2.1vw, 1.55rem); line-height: 1.28;
  letter-spacing: -0.01em; color: var(--black);
  border-left: 4px solid var(--red); padding-left: 1.2rem;
  margin: 1.5rem 0; quotes: none;
}/* --- Service-area map (Leaflet, keyless) --- */
#area-map {
  min-height: 400px; height: 400px; margin: 0 0 2rem;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--bg-warm); z-index: 0;
}
#area-map .leaflet-popup-content { margin: 0.6rem 0.9rem; font-family: var(--font-body); }
@media (max-width: 700px) { #area-map { min-height: 300px; height: 300px; } }/* ===== Footer social icon row (ported from the Proudfoot build) ===== */
.foot-social {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.foot-social a {
  color: #fff;
  opacity: 0.75;
  display: inline-flex;
  transition: opacity 140ms ease, color 140ms ease;
}
.foot-social a:hover,
.foot-social a:focus-visible {
  opacity: 1;
  color: var(--green-bright);
}
.foot-social svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
}/* ===== "Do you come to me?" area checker (ported from Proudfoot) ===== */
.area-check {
  margin: 0 0 1.25rem;
  scroll-margin-top: 130px;
}
.area-check label {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  margin-bottom: 0.4rem;
}
.area-check-row {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.area-check-row input {
  flex: 1 1 16rem;
  min-width: 0;
  padding: 0.8rem 0.9rem;
  border: 2px solid var(--line);
  border-radius: var(--r-md);
  font-size: 1rem;
  font-family: var(--font-body);
}
.area-check-row input:focus {
  border-color: var(--black);
  outline: none;
}
.area-check-result {
  margin: 0.7rem 0 0;
  font-weight: 600;
  min-height: 1.3em;
}
.area-check-result.is-yes {
  color: var(--ok);
}
.area-check-result.is-maybe,
.area-check-result.is-unknown {
  color: var(--red-deep);
}
.area-check-result.is-busy {
  color: var(--muted);
}/* Project accordion on the size guide. Native <details> on purpose: the copy
   ships in the HTML and stays fully indexable, which is not true of panels
   whose content is injected on click. No FAQPage schema on these either, since
   they are project headings rather than questions. */
.proj-list {
  margin-top: 1.5rem;
}
.proj {
  margin-bottom: 0.8rem;
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
}
.proj summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.05rem 1.35rem;
  cursor: pointer;
  list-style: none;
  border-radius: var(--r-sm);
}
.proj summary::-webkit-details-marker {
  display: none;
}/* The label is an <h3> so these project names land in the document outline; a
   crawler otherwise sees unlabelled disclosure widgets under a lone H2. Reset
   so the heading doesn't disturb the summary row. */
.proj summary h3 {
  margin: 0;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--black);
}
.proj summary::after {
  content: "+";
  flex-shrink: 0;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--red);
}
.proj[open] summary::after {
  content: "\2212";
}
.proj summary:hover {
  background: #f7f6f5;
}
.proj summary:focus-visible {
  outline: 3px solid var(--red);
  outline-offset: -3px;
}
.proj > p {
  margin: 0;
  padding: 0.4rem 1.35rem 1.35rem;
  font-size: 0.95rem;
  line-height: 1.72;
  color: #333;
}
@media (prefers-reduced-motion: no-preference) {
  .proj[open] > p {
    animation: proj-open 160ms ease-out;
  }
  @keyframes proj-open {
    from { opacity: 0; transform: translateY(-3px); }
    to   { opacity: 1; transform: none; }
  }
}/* Rental-terms strip (dumpsters hub #pricing and pricing.html). The four
   facts a caller actually asks about, as scannable tiles instead of a prose
   paragraph. Unique class names on purpose: checked that no earlier .terms-*
   block exists in this file, so nothing in the cascade can shadow these. */
.terms-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem;
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}
.terms-tile {
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-md);
  padding: 1rem 0.7rem;
  text-align: center;
}
.terms-val {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.3rem;
  line-height: 1.15;
  color: var(--black);
}
.terms-tile.is-extra .terms-val {
  color: var(--red-deep);
}
.terms-key {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #555;
}
.terms-link {
  margin: 0 0 1.75rem;
  text-align: center;
  font-size: 0.9rem;
}
@media (max-width: 720px) {
  .terms-strip {
    grid-template-columns: repeat(2, 1fr);
  }
  .terms-val {
    font-size: 1.15rem;
  }
}/* Sizing-tool pills grouped under the pricing prose on the dumpsters hub. */
.tool-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  margin-top: 1.5rem;
}
.tool-pills a {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--black);
  text-decoration: none;
  background: #fff;
  border: 2px solid var(--black);
  border-radius: var(--r-sm);
  padding: 0.45rem 0.9rem;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.tool-pills a:hover,
.tool-pills a:focus-visible {
  background: var(--red-deep);
  border-color: var(--red-deep);
  color: #fff;
}/* Plain rate line under the size-section headings on the dumpsters hub. */
.rate-line {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--red-deep);
  margin: 0.15rem 0 0.9rem;
}/* ===== Size comparison diagram (dumpsters hub + size guide) ===== */
.size-diagram {
  max-width: 58rem;
  margin: 0 auto;
}
.size-diagram img {
  width: 100%;
  height: auto;
}
.size-diagram-note {
  text-align: center;
  color: var(--muted);
  font-weight: 600;
  margin: 0.75rem 0 0;
}/* ===== Delivery photo sequence (how-it-works) ===== */
.photo-seq {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}
@media (min-width: 760px) {
  .photo-seq { grid-template-columns: 1fr 1fr 1fr; }
}
.photo-seq figure {
  margin: 0;
}
.photo-seq img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-md);
  border: 2px solid var(--black);
}
.photo-seq figcaption {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  margin-top: 0.5rem;
  color: var(--ink);
}

/* Mirrored story-grid: photo on the right at desktop (gives-back section) */
@media (min-width: 900px) {
  .story-grid.flip { grid-template-columns: 1.1fr 0.9fr; }
  .story-grid.flip > .photo { order: 2; }
  .story-grid.flip > .story-body { order: 1; }
}/* CTA pair in the homepage how-it-works section: flex with a real gap so the
   buttons never stack flush at mobile widths. */
.how-ctas {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}/* ============================================================
   HERO QUOTE FORM
   Sits in the hero's right column, where the directional scrim
   already clears the background photo. Same card idiom as the
   rest of the site: white, hard black border, offset yellow
   shadow. One red element only — the submit button — so the
   eye lands on the single action that matters.
   ============================================================ */
.hero-quote {
  background: #fff;
  border: 3px solid var(--black);
  border-radius: var(--r-md);
  box-shadow: 8px 8px 0 var(--yellow);
  padding: 1.5rem 1.4rem 1.3rem;
  position: relative;
  z-index: 1;
  max-width: 27rem;
  width: 100%;
  justify-self: end;
}
.hero-quote-head { margin-bottom: 1.1rem; }
.hero-quote-head h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  line-height: 1.1;
  margin: 0 0 0.3rem;
  color: var(--black);
  text-shadow: none;
}/* Yellow rule under the title picks up the shadow colour and
   separates head from fields without another border line. */
.hero-quote-head h2::after {
  content: "";
  display: block;
  width: 2.4rem;
  height: 4px;
  background: var(--yellow);
  margin-top: 0.55rem;
}
.hero-quote-head p {
  margin: 0.7rem 0 0;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--muted);
}
.hero-quote-fields { display: grid; gap: 0.75rem; }
.hero-quote-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.hero-quote-field { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.hero-quote-field label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--black);
}
.hero-quote-field input,
.hero-quote-field select {
  font-family: inherit;
  font-size: 1rem; /* 16px floor: anything smaller zooms the page on iOS */
  color: var(--ink);
  background: #fff;
  border: 2px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.6rem 0.7rem;
  width: 100%;
  min-height: 44px; /* touch target */
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.hero-quote-field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%23111' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
  background-size: 11px;
  padding-right: 2rem;
}
.hero-quote-field input:focus,
.hero-quote-field select:focus {
  outline: none;
  border-color: var(--black);
  box-shadow: 0 0 0 3px var(--yellow);
}
.hero-quote-submit {
  display: block;
  width: 100%;
  margin-top: 1.1rem;
  background: var(--red-deep);
  color: #fff;
  border: 0;
  border-radius: var(--r-sm);
  padding: 0.95rem 1rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  cursor: pointer;
  box-shadow: 0 0 0 var(--yellow);
  transition: background 150ms ease, transform 150ms ease, box-shadow 150ms ease;
}
.hero-quote-submit:hover { background: var(--red-deeper); transform: translate(-3px, -3px); box-shadow: 6px 6px 0 var(--yellow); }
.hero-quote-submit:active { transform: translate(1px, 1px); box-shadow: 0 0 0 var(--yellow); }
.hero-quote-submit:focus-visible { outline: 3px solid var(--black); outline-offset: 2px; }/* Phone escape hatch: people who won't fill a form still convert. */
.hero-quote-alt {
  margin: 0.85rem 0 0;
  text-align: center;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--muted);
}
.hero-quote-alt a { color: var(--black); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 899px) {
  .hero-quote { justify-self: stretch; max-width: 100%; box-shadow: 6px 6px 0 var(--yellow); }
}
@media (max-width: 400px) {
  .hero-quote { padding: 1.25rem 1.1rem 1.1rem; }
}
/* ZIP + size stay paired down to the narrowest common phones; only split
   below 340px, where two columns would squeeze the select. */
@media (max-width: 339px) {
  .hero-quote-row { grid-template-columns: 1fr; }
}/* Hero secondary action: a text link, so the hero reads as two clear
   choices (call / fill the form) rather than three button blocks. */
.hero-textlink {
  display: inline-flex;
  align-items: center;
  align-self: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
  text-decoration-color: rgba(255, 255, 255, 0.45);
  padding: 0.4rem 0.2rem;
  min-height: 44px;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.75);
  transition: text-decoration-color 140ms ease;
}
.hero-textlink:hover { text-decoration-color: #fff; }
.hero-textlink:focus-visible { outline: 3px solid var(--yellow); outline-offset: 3px; border-radius: var(--r-sm); }
/* Same weight and underline as .hero-textlink, inked for a light section.
   The hero variant is white-on-photo; reusing it on paper renders invisible. */
.section-textlink {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  color: var(--black);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--red-deep);
}
.section-textlink:hover { color: var(--red-deep); }
.section-textlink:focus-visible { outline: 3px solid var(--red-deep); outline-offset: 3px; border-radius: var(--r-sm); }/* Floating call pill yields to the hero quote form (see hero-cta-guard.js). */
.mobile-cta { transition: opacity 180ms ease, transform 180ms ease, visibility 180ms; }
.mobile-cta.is-behind-form { opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(10px); }
@media (prefers-reduced-motion: reduce) { .mobile-cta { transition: none; } }/* Hero Google rating: same content as the reviews-section badge, restyled
   for the dark hero using the existing on-dark glass pill treatment. */
.hero-rating {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1.6rem;
  padding: 8px 16px 8px 12px;
  border-radius: var(--r-pill);
  background: rgba(17, 17, 17, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  text-decoration: none;
  transition: border-color 140ms ease, background 140ms ease;
}
.hero-rating:hover { background: rgba(17, 17, 17, 0.95); border-color: rgba(255, 255, 255, 0.5); }
.hero-rating:focus-visible { outline: 3px solid var(--yellow); outline-offset: 3px; }
.hero-rating svg { flex-shrink: 0; }
.hero-rating .rs-stars { color: #ffc107; font-size: 0.95rem; letter-spacing: 0.05em; line-height: 1; }
.hero-rating .rb-text { display: inline-flex; align-items: baseline; gap: 0.4rem; font-family: var(--font-display); line-height: 1; }
.hero-rating .rb-text strong { color: #fff; font-weight: 700; font-size: 1rem; }
.hero-rating .rb-text > span { color: rgba(255, 255, 255, 0.8); font-weight: 600; font-size: 0.85rem; }
@media (max-width: 420px) {
  .hero-rating { gap: 0.5rem; padding: 7px 13px 7px 10px; }
  .hero-rating .rb-text { gap: 0.3rem; }
  .hero-rating .rb-text > span { font-size: 0.8rem; }
}

/* ------------------------------------------------------------------
   Fold guard for the hero form.
   The card's submit button was landing below the fold on 1366x660-class
   laptops, which is the one element in the hero that must always be
   visible. Tighten the hero's vertical rhythm and the card's internal
   spacing so the button clears the fold on short screens.
   Scoped with :has() so it only applies to a hero that carries the form.
   ------------------------------------------------------------------ */
@media (min-width: 900px) {
  .hero.hero-bg:has(.hero-quote) {
    padding-top: clamp(1.75rem, 3.5vw, 3rem);
    padding-bottom: clamp(2.25rem, 4.5vw, 4rem);
    min-height: 0;
  }
  .hero.hero-bg:has(.hero-quote) .hero-quote { padding: 1.3rem 1.4rem 1.15rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-head { margin-bottom: 0.9rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-head p { margin-top: 0.55rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-fields { gap: 0.65rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-submit { margin-top: 0.9rem; padding: 0.85rem 1rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-alt { margin-top: 0.7rem; }
}
/* Short viewports: trim the headline block so the card still clears.
   The slab display face sets taller than the condensed one it replaced, so
   the card needs a little more headroom here than it used to. */
@media (min-width: 900px) and (max-height: 700px) {
  .hero.hero-bg:has(.hero-quote) { padding-top: 1.25rem; padding-bottom: 1.5rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote { padding: 1.05rem 1.3rem 0.95rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-head { margin-bottom: 0.7rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-fields { gap: 0.5rem; }
  .hero.hero-bg:has(.hero-quote) .hero-quote-submit { margin-top: 0.7rem; padding: 0.75rem 1rem; }
  .hero.hero-bg:has(.hero-quote) h1 { font-size: clamp(1.9rem, 3.4vw, 2.6rem); }
  .hero.hero-bg:has(.hero-quote) .lead { margin-bottom: 1.25rem; font-size: 1rem; }
  .hero.hero-bg:has(.hero-quote) .hero-rating { margin-bottom: 0; }
  .hero.hero-bg:has(.hero-quote) .eyebrow { margin-bottom: 1rem; }
}/* ============================================================
   LIGHT HEADER  (ported from Scribby's)
   The horizontal logo has a red 417 + black wordmark, so it
   carries a white bar; the footer keeps the white-on-dark mark.
   ============================================================ */
.topbar {
  background: #fff;
  border-bottom: 1px solid var(--line);
}
nav.primary a { color: var(--ink); }
nav.primary a:hover,
nav.primary a[aria-current="page"] { color: var(--red-deep); }
@media (max-width: 999px) {
  .nav-toggle span { background: var(--black); }
  .topbar:has(.nav-toggle-cb:checked) nav.primary {
    background: #fff;
    border-top: 2px solid var(--line);
  }
}/* Bigger, tighter hero headline. Most of why Scribby's reads confident. */
/* Hero trust row: Google badge + two confirmed claims. */
.hero-trust {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  /* Same between-group gap as the rest of the hero column. Was 1.6rem,
     giving 29px against the 34px everywhere else - the near-miss drift that
     made the hero feel assembled rather than composed. */
  margin-top: 2rem;
}
.hero-trust .hero-rating { margin-bottom: 0; }
.hero-trust-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 8px 15px 8px 11px;
  border-radius: var(--r-pill);
  background: rgba(17, 17, 17, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.85rem;
  color: #fff;
  white-space: nowrap;
}
.hero-trust-pill .trust-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--black);
  font-size: 0.72rem;
  font-weight: 700;
  border: 1px solid var(--black);
  flex-shrink: 0;
}
@media (max-width: 420px) {
  .hero-trust { gap: 0.45rem; }
  .hero-trust-pill { font-size: 0.8rem; padding: 7px 12px 7px 9px; }
}
/* Short viewports: the trust row is the first thing to give up space. */
@media (min-width: 900px) and (max-height: 700px) {
  .hero.hero-bg:has(.hero-quote) .hero-trust { margin-top: 1.1rem; }
}

/* Logo left, nav centre, phone right (Scribby's arrangement). Overrides the
   earlier order-swap that parked the logo on the right. The phone wrapper
   needs an explicit order or it defaults to 0 and jumps to the far LEFT,
   which is where users least expect a phone number. Both side zones get
   flex 1 1 0 so the nav sits optically centered between them. */
@media (min-width: 1000px) {
  .topbar-inner > .brand { order: 1; flex: 1 1 0; justify-content: flex-start; }
  .topbar-inner > nav.primary { order: 2; flex: 0 0 auto; }
  .topbar-inner > div { order: 3; flex: 1 1 0; display: flex; justify-content: flex-end; }
}
@media (max-width: 999px) {
  .topbar-inner > .brand { order: 1; margin-right: auto; }
}/* Uniform pill height so the trust row reads as one set, not a ragged mix
   (the Google badge is naturally taller than the two text pills). Fixed
   height + zero vertical padding, so both types land on exactly 40px. */
.hero-trust { align-items: center; }
.hero-trust .hero-rating,
.hero-trust .hero-trust-pill {
  height: 40px;
  min-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  box-sizing: border-box;
}/* House glyph on the Home nav link. currentColor so it follows the link's
   default, hover and active-page colours without extra rules. */
.nav-home {
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
}
.nav-home::before {
  content: "";
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 3.2 1.8 12.1h3v8.7h5.3v-5.2h3.8v5.2h5.3v-8.7h3L12 3.2z'/></svg>") center/contain no-repeat;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 3.2 1.8 12.1h3v8.7h5.3v-5.2h3.8v5.2h5.3v-8.7h3L12 3.2z'/></svg>") center/contain no-repeat;
}
/* In the mobile drawer the links are stacked and left-aligned; keep the
   glyph from stretching the row height. */
@media (max-width: 999px) {
  .nav-home { justify-content: flex-start; }
}/* ============================================================
   SIZE CARDS (dumpsters.html) — clickable, Scribby's idiom
   ============================================================ */
.sizes {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.25rem;
  margin-top: 2rem;
}
.size-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 3px solid var(--black);
  border-radius: var(--r-md);
  padding: 1.75rem 1.5rem 1.5rem;
  text-decoration: none;
  color: inherit;
  box-shadow: 6px 6px 0 var(--black);
  transition: transform 180ms ease, box-shadow 180ms ease;
}
.size-card:hover { transform: translate(-3px, -3px); box-shadow: 8px 8px 0 var(--yellow) var(--yellow); }
.size-card:active { transform: translate(1px, 1px); box-shadow: 4px 4px 0 var(--yellow) var(--yellow); }
.size-card:focus-visible { outline: 3px solid var(--red-deep); outline-offset: 3px; }
.size-card-spec {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.size-card .yd {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.6rem, 5vw, 3.4rem);
  line-height: 1;
  color: var(--black);
  margin-top: 0.35rem;
}
.size-card .yd small { font-size: 0.36em; margin-left: 0.28rem; letter-spacing: 0.06em; }
.size-card-kicker {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--red-deep);
  margin-top: 0.15rem;
}/* The art is the to-scale comparison; it must not be cropped or stretched. */
.size-card-art {
  display: block;
  width: 100%;
  height: auto;
  margin: 1rem 0 0.9rem;
}
.size-card p { margin: 0 0 1rem; font-size: 0.95rem; line-height: 1.5; color: var(--ink); }
.size-card-price {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--red-deep);
  margin-bottom: 0.9rem;
}
.size-card-cta {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--black);
  border-bottom: 3px solid var(--yellow);
  padding-bottom: 2px;
  align-self: flex-start;
  margin-top: auto;
}
.size-diagram-note {
  margin-top: 1.5rem;
  text-align: center;
  font-size: 0.92rem;
  color: var(--muted);
}
@media (max-width: 700px) {
  .sizes { grid-template-columns: 1fr; gap: 1rem; }
}
@media (prefers-reduced-motion: reduce) {
  .size-card { transition: none; }
  .size-card:hover { transform: none; }
}/* Featured size card: Kyle wants the 20-yard taken by default, so it gets
   the badge and a green frame while the 14 stays neutral. Wording is
   "Most homes" (the residential box, per the interview) rather than "Most
   popular", which would be a rental-volume claim nobody has confirmed. */
.size-card { position: relative; }
.size-card-featured { border-color: var(--yellow); box-shadow: 6px 6px 0 var(--yellow); }
.size-card-featured:hover { box-shadow: 8px 8px 0 var(--black) var(--black); }
.size-card-featured:active { box-shadow: 4px 4px 0 var(--black) var(--black); }
.size-card-badge {
  position: absolute;
  top: -3px;
  right: -3px;
  background: var(--yellow);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 7px 12px;
  border-radius: 0 5px 0 8px;
}/* Keep the spec line clear of the badge on narrow cards. */
.size-card-featured .size-card-spec { padding-right: 7.5rem; }

/* Four pills don't fit one row in the left column, and a natural wrap
   strands the last one alone. Cap the row so it breaks 2+2 instead. */
@media (min-width: 900px) {
  .hero-trust { max-width: 29rem; }
}/* Section-closing CTA. Secondary weight so it supports the block instead of
   competing with the hero's phone button. white-space:normal because the base
   .btn is nowrap for short labels, and a three-word section label would
   overflow a phone screen. */
.btn-inline {
  margin-top: 1.25rem;
  font-size: 0.95rem;
  padding: 0.7rem 1.2rem;
  box-shadow: 4px 4px 0 var(--black) var(--black);
  white-space: normal;
}/* Decision CTA under a size-card grid: the person who couldn't pick between
   the two boxes had no next step. Prompt as text, phone as the primary
   button (the conversion action), per local-service-section-cta. */
.size-grid-cta {
  margin-top: 2rem;
  text-align: center;
}
.size-grid-cta p {
  margin: 0 0 1rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ink);
}/* Neighbour links in the town hero: same mesh, surfaced where mobile visitors
   and crawlers actually reach it instead of 3000px down the page. */
.hero-neighbors { margin-top: 1rem; font-size: 0.95rem; color: var(--muted); }
.hero-neighbors a { color: var(--black); font-weight: 700; border-bottom: 2px solid var(--yellow); text-decoration: none; }/* Folded towns: named, never linked (local-service-town-selection). */
.areas-also { margin-top: 1.5rem; font-size: 0.95rem; line-height: 1.6; color: var(--muted); }
.also-serve { margin-top: 2.5rem; }
.also-serve h3 { font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; margin: 0 0 0.5rem; }
.also-serve > p { color: var(--muted); margin: 0 0 1rem; max-width: 60ch; }
.also-serve-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }
.also-serve-list li { font-size: 0.95rem; line-height: 1.5; color: var(--ink); }
.also-serve-list strong { font-family: var(--font-display); }/* .size-grid-cta-person removed 2026-08-12: the owner block under the size
   grid duplicated card 3's question, answer and phone CTA about 100px below
   it, and its two alignment systems (block centered, button row flush left)
   read as unfinished. Card 3 kept the job and the better copy. *//* The slab display face sets taller than the condensed one, leaving the
   featured badge flush against the spec line. Small clearance so they
   never touch. */
.size-card-featured .size-card-spec { margin-top: 0.35rem; }

/* The floating pill is the persistent mobile action, so the header does not
   carry a second always-visible tel: link. Desktop keeps its header number.
   Added with the removal of the scroll-morphing topbar; see
   local-service-design/SKILL.md. */
@media (max-width: 999px) {
  .topbar .tel-cta { display: none; }
}

/* ============================================================================
   FAMILY TRASH ALIGNMENT
   Matching the system Ryan built on familytrashsc.com, with 417's own brand
   colours. What's shared is the *system*, not the palette:
     - Archivo display + Public Sans body
     - ONE depth technique: a single large, brand-tinted soft shadow. Family
       Trash tints toward its plum; 417 tints toward its fleet red. This is a
       deliberate chosen shadow, not a default 0.1-opacity drop on everything
       (local-service-design allows one earned technique, bans the generic one).
     - 14px radius
     - warm/soft tinted section grounds instead of flat white and grey
   ============================================================================ */
:root {
  --radius-ft: 14px;
  --shadow-ft: 0 18px 40px -22px rgba(60, 6, 10, 0.38);
  --shadow-ft-lg: 0 26px 55px -22px rgba(0, 0, 0, 0.55);
  /* --bg-warm deliberately NOT redeclared here. This donor block set it to
     #fbf7f5, which beat the #f6f4f0 in the token block at the top of the file
     and quietly weakened every alternating section ground on the site: body
     #fdfcfa against #fbf7f5 is a 1.7% luminance step, where the house rule
     asks for 3-5% and the original value gives 3.1%. The bands were doing no
     separating, which is why so many sections read as one continuous wash. */
  --bg-soft: #f6f5f3;
  --line-ft: #ece8e8;
}

/* Display face */
:root { --font-display: "Archivo", system-ui, sans-serif; }
h1, h2, h3, h4, .btn, .tel-big, .text-big, .book-big { letter-spacing: -0.01em; }

/* Depth: earned, not blanket. Only real surfaces get the shadow. */
.size-card,
.hero-quote,
.svc-card,
.town-service-card {
  border: 1px solid var(--line-ft);
  border-radius: var(--radius-ft);
  box-shadow: var(--shadow-ft);
}
.size-card:hover,
.svc-card:hover,
.town-service-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-ft-lg);
}
.size-card-featured { border-color: var(--yellow); }
.size-card-badge { border-radius: 0 var(--radius-ft) 0 12px; }

/* Buttons: rounded, house hard-offset stamp. The donor rule here used to
   set box-shadow:none, which silently disabled the stamp choreography the
   base .btn system already defines (4px resting, 6px on hover-lift, 0 on
   press). Reversed 2026-08-24 on Ryan's call - the stamp is the site's one
   depth technique and the buttons were the only surface not using it. */
.btn, .tel-big, .text-big, .book-big, .hero-quote-submit, .tel-cta, .size-act {
  border-radius: var(--r-btn);
  box-shadow: 4px 4px 0 var(--black);
  transition: transform 150ms ease, box-shadow 150ms ease, background-color 150ms ease;
}
/* Control boundaries must clear 3:1 (WCAG 2.1 SC 1.4.11). --line-ft is a
   DIVIDER colour: measured at 1.14:1 against the page background, which is
   why every outlined button read as floating text rather than a control
   ("some of these CTAs are almost invisible", Ryan 2026-08-12). --muted
   clears it at ~6.3:1 and still reads as the quiet sibling of a filled
   primary. 2px matches the primary's weight so the pair look like one set. */
.btn-secondary { border: 2px solid var(--muted); }

/* Final CTA sits on the black band. Two actions with real hierarchy: the
   phone filled red (the money action - phone leads close best in home
   services), the quote form outlined in white so its boundary actually
   shows on black. The old rule ringed BOTH in var(--yellow), a leftover
   from when that token was yellow; once it became green a green ring around
   a red button on black was arbitrary decoration. */
.cta-final .tel-big {
  /* Brighter --red here, not --red-deep. On the black band the deep red is
     only 2.39:1 as a SHAPE, so the button barely separates from the
     background; --red clears the 3:1 control-boundary bar at 3.08:1 and
     still carries white text at 6.39:1. Filled CTAs on white keep
     --red-deep, which needs the darker shade to pass there. */
  background: var(--red);
  color: #fff;
  border-color: var(--red);
  box-shadow: none;
}
.cta-final .text-big {
  background: transparent;
  color: #fff;
  border-color: #fff;
  box-shadow: none;
}
.cta-final .text-big:hover { background: #fff; color: var(--black); }

/* Eyebrow becomes a soft tinted pill, the Family Trash treatment */
.eyebrow {
  background: rgba(255, 255, 255, 0.92);
  color: var(--red-deep);
  border-radius: 999px;
  padding: 7px 16px;
  letter-spacing: 0.14em;
}
.eyebrow-on-dark { background: rgba(255, 255, 255, 0.94); color: var(--red-deep); }

/* Alternating grounds get a tint instead of flat grey */
.block.alt { background: var(--bg-warm); }

/* Form fields */
.hero-quote-field input, .hero-quote-field select,
input[type="text"], input[type="tel"], input[type="email"],
input[type="date"], input[type="number"], select, textarea {
  border: 1px solid var(--line-ft);
  border-radius: 10px;
}
.hero-quote-field input:focus, .hero-quote-field select:focus,
input:focus, select:focus, textarea:focus {
  border-color: var(--yellow);
  box-shadow: 0 0 0 3px rgba(37, 122, 28, 0.16);
  outline: none;
}

/* ---- Hero panel (phone + what's included), Family Trash pattern ---- */
.hero-panel {
  background: #fff;
  color: var(--ink);
  border-radius: 16px;
  padding: 1.6rem 1.7rem;
  box-shadow: var(--shadow-ft-lg);
  align-self: center;
  max-width: 27rem;
  width: 100%;
  justify-self: end;
  position: relative;
  z-index: 1;
}
.hero-panel-kicker {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--red-deep);
  margin-bottom: 0.3rem;
}
.hero-panel-phone {
  /* The panel's biggest element is also its highest-converting action (phone
     leads close at 46% in home services), but styled as plain display type it
     read as a heading rather than a tap target. The handset glyph and the
     hover underline are the affordance; the size stays. */
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.9rem, 3vw, 2.4rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--black);
  text-decoration: none;
}
.hero-panel-phone::before {
  content: "";
  flex-shrink: 0;
  width: 0.78em;
  height: 0.78em;
  background: var(--red-deep);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>") center/contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.4 21 3 13.6 3 4.5c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.3 0 .7-.2 1l-2.3 1.7z'/></svg>") center/contain no-repeat;
}
.hero-panel-phone:hover { color: var(--red-deep); text-decoration: underline; text-underline-offset: 3px; }
/* The rule the phone used to carry moves to the owner block, so the divider
   spans the panel instead of stopping at the end of the number. */
.hero-panel-owner {
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line-ft);
}
.hero-panel-list {
  list-style: none;
  padding: 0;
  margin: 1.1rem 0 1.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.hero-panel-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.97rem;
  line-height: 1.35;
  font-weight: 500;
}
.hero-panel-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--yellow);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  flex-shrink: 0;
  margin-top: 1px;
}
.hero-panel-cta {
  display: block;
  text-align: center;
  background: var(--red-deep);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  padding: 0.95rem 1rem;
  border-radius: 10px;
  text-decoration: none;
  transition: transform 150ms ease, box-shadow 150ms ease, background-color 150ms ease;
}
.hero-panel-cta:hover { background: var(--red-deeper); transform: translateY(-2px); box-shadow: var(--shadow-ft); }
.hero-panel-cta:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

/* ---- Quote modal ---- */
.quote-modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; padding: 1.25rem; }
.quote-modal[hidden] { display: none; }
.quote-modal-backdrop { position: absolute; inset: 0; background: rgba(17, 10, 10, 0.62); backdrop-filter: blur(2px); }
.quote-modal-panel {
  position: relative;
  background: #fff;
  border-radius: var(--radius-ft);
  box-shadow: var(--shadow-ft-lg);
  padding: 1.75rem 1.6rem 1.5rem;
  width: 100%;
  max-width: 30rem;
  max-height: calc(100vh - 2.5rem);
  overflow-y: auto;
}
.quote-modal-panel h2 { font-size: 1.6rem; margin: 0 0 0.35rem; }
.quote-modal-sub { margin: 0 0 1.2rem; color: var(--muted); font-size: 0.95rem; line-height: 1.45; }
.quote-modal-x {
  position: absolute;
  top: 0.45rem;
  right: 0.5rem;
  background: none;
  border: 0;
  font-size: 1.9rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  border-radius: 8px;
  /* 44px minimum touch target (local-service-accessibility). */
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.quote-modal-x:hover { color: var(--black); background: var(--bg-soft); }
.quote-modal-x:focus-visible { outline: 3px solid var(--red-deep); outline-offset: 2px; }
/* The modal form reuses the hero-quote field styles; drop the card chrome. */
.quote-modal-form { border: 0; box-shadow: none; padding: 0; background: none; max-width: none; }
.quote-modal-form .hero-quote-head { display: none; }
@media (max-width: 899px) {
  .hero-panel { justify-self: stretch; max-width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-panel-cta, .btn { transition: none; }
  .hero-panel-cta:hover, .btn:hover { transform: none; }
}

/* Sets the expectation the CTA implies: the form is the path to a price. */
.hero-panel-note { margin: 0.7rem 0 0; text-align: center; font-size: 0.85rem; line-height: 1.4; color: var(--muted); }

/* ---- Quote modal calculator ---- */
.qm-choice { border: 0; padding: 0; margin: 0 0 1.1rem; }
.qm-choice legend {
  font-family: var(--font-display); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--black);
  padding: 0; margin-bottom: 0.5rem;
}
.qm-choice label { display: block; cursor: pointer; margin-bottom: 0.5rem; }
.qm-choice input { position: absolute; opacity: 0; pointer-events: none; }
.qm-choice span {
  display: block; border: 1px solid var(--line-ft); border-radius: 10px;
  padding: 0.7rem 0.85rem; transition: border-color 120ms ease, box-shadow 120ms ease;
}
.qm-choice strong { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.02rem; }
.qm-choice small { display: block; color: var(--muted); font-size: 0.85rem; margin-top: 1px; }
.qm-choice input:checked + span { border-color: var(--yellow); box-shadow: 0 0 0 2px rgba(37,122,28,.18); }
.qm-choice input:focus-visible + span { outline: 3px solid var(--red-deep); outline-offset: 2px; }

.qm-days { margin-bottom: 1.1rem; }
.qm-days > label {
  display: block; font-family: var(--font-display); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--black); margin-bottom: 0.4rem;
}
.qm-days-row { display: flex; align-items: stretch; gap: 0.5rem; max-width: 12rem; }
.qm-days-row input {
  flex: 1; text-align: center; font-size: 1rem; min-height: 44px;
  border: 1px solid var(--line-ft); border-radius: 10px;
}
.qm-step {
  width: 44px; min-height: 44px; border: 1px solid var(--line-ft); background: #fff;
  border-radius: 10px; font-size: 1.3rem; line-height: 1; cursor: pointer; color: var(--black);
}
.qm-step:hover { border-color: var(--yellow); color: var(--red-deep); }
.qm-step:focus-visible { outline: 3px solid var(--red-deep); outline-offset: 2px; }
.qm-days-note { margin: 0.45rem 0 0; font-size: 0.85rem; color: var(--muted); }

.qm-price {
  background: var(--bg-warm); border: 1px solid var(--line-ft); border-radius: var(--radius-ft);
  padding: 0.9rem 1rem; margin-bottom: 1.1rem; text-align: center;
}
.qm-price-label {
  display: block; font-family: var(--font-display); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
}
.qm-price-value {
  display: block; font-family: var(--font-display); font-weight: 800;
  font-size: clamp(2.1rem, 6vw, 2.7rem); line-height: 1.05; color: var(--red-deep); letter-spacing: -0.02em;
}
.qm-price-foot { display: block; font-size: 0.85rem; color: var(--muted); margin-top: 0.15rem; }
/* Two columns once there is room. The modal collects the whole order now -
   Kyle's call - so a single stacked column ran the form far past the fold on
   a laptop. Address and notes span both. */
.qm-fields { display: grid; gap: 0.7rem; margin-bottom: 0.2rem; }
@media (min-width: 560px) {
  .qm-fields { grid-template-columns: 1fr 1fr; }
  .qm-fields .qm-wide { grid-column: 1 / -1; }
}
.qm-fields select,
.qm-fields textarea {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line-ft);
  border-radius: var(--r-md);
  padding: 0.6rem 0.7rem;
}
.qm-fields textarea { resize: vertical; }
.qm-fields select:focus-visible,
.qm-fields textarea:focus-visible {
  outline: none;
  border-color: var(--yellow);
  box-shadow: 0 0 0 3px rgba(37, 122, 28, 0.25);
}
.qm-fine { margin: 0.8rem 0 0; font-size: 0.78rem; line-height: 1.45; color: var(--muted); }
.qm-fine a { color: var(--black); text-decoration: underline; }

/* Skip link: keyboard users shouldn't tab the whole nav to reach content. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 300;
  background: var(--red-deep);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 8px 0;
  text-decoration: none;
}
.skip-link:focus { left: 0; }

/* Two inputs killed their focus ring with no replacement — a keyboard user
   could not see where they were (local-service-accessibility). */
.town-search input[type="search"]:focus,
.area-check-row input:focus {
  outline: none;
  border-color: var(--yellow);
  box-shadow: 0 0 0 3px rgba(37, 122, 28, 0.25);
}

/* Footer social icon was 22x22; WCAG 2.2 AA 2.5.8 wants 24x24 minimum.
   The glyph stays its size, the hit area grows around it. */
.foot-social a {
  min-width: 44px;
  min-height: 44px;
  align-items: center;
  justify-content: center;
}

/* ---- Stat band (house component). Four peers, no accent cell — ranking one
   by colour reads as a mistake in a row of four equals. Order carries the
   ranking instead. 2-up at <=760px, never 1-up. ---- */
.stat-band { background: var(--black); color: #fff; }
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); }
.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  text-align: center;
  padding: 1.5rem 1rem;
  border-right: 1px solid rgba(255, 255, 255, 0.14);
  text-decoration: none;
  color: inherit;
}
.stat-item:last-child { border-right: 0; }
.stat-value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.25rem, 2.2vw, 1.65rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: #fff;
}
.stat-cap { font-size: 0.82rem; line-height: 1.3; color: rgba(255, 255, 255, 0.72); }
/* the rating cell renders the shared rb-text markup */
.stat-item .rb-text { display: flex; flex-direction: column; gap: 0.2rem; }
.stat-item .rb-text strong { font-size: inherit; }
.stat-item .rb-text > span { font-size: 0.82rem; font-weight: 400; color: rgba(255, 255, 255, 0.72); }
a.stat-item:hover .stat-value { color: var(--green-bright); }
@media (max-width: 760px) {
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .stat-item { padding: 1.15rem 0.6rem; border-bottom: 1px solid rgba(255, 255, 255, 0.14); }
  .stat-item:nth-child(2n) { border-right: 0; }
  .stat-item:nth-last-child(-n + 2) { border-bottom: 0; }
}

/* Size-card actions: the card had one exit — a page ABOUT the box — so the
   decision was never captured. Now a primary action that opens pricing with
   the chosen size carried through, plus the detail link (local-service-
   conversion: size cards are a prominent slot and get the pricing CTA). */
.size-card-actions { margin-top: auto; display: flex; flex-direction: column; gap: 0.6rem; }
.size-card-book {
  display: block;
  width: 100%;
  background: var(--red-deep);
  color: #fff;
  border: 0;
  border-radius: 10px;
  padding: 0.85rem 1rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  transition: transform 150ms ease, box-shadow 150ms ease, background-color 150ms ease;
}
.size-card-book:hover { background: var(--red-deeper); transform: translateY(-2px); box-shadow: var(--shadow-ft); }
.size-card-book:focus-visible { outline: 3px solid var(--black); outline-offset: 2px; }
.size-card-more {
  align-self: center;
  /* 27px tall measured - under the 40px touch floor. Padding grows the hit
     area without moving the text's visual position in the card. */
  padding: 0.7rem 0.75rem;
  margin: -0.7rem -0.75rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--black);
  text-decoration: none;
  border-bottom: 2px solid var(--yellow);
  padding-bottom: 1px;
}
.size-card-more:hover { color: var(--red-deep); }
/* the card is no longer an <a>, so it needs its own hover lift */
div.size-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-ft-lg); }

/* ---- Proof strip: live rating + two rotated real reviews, sitting at the
   decision point on money pages (local-service-proof). ---- */
/* Base tone, not warm: every proof strip on the site sits directly after a
   warm .alt band (measured: all 25), so a warm strip made two same-tone bands
   touch on every money page. Base gives alt -> base -> dark closing rhythm. */
.proof-strip { background: transparent; }
.proof-strip .wrap { display: flex; flex-direction: column; align-items: center; gap: 1.4rem; }
/* The wrap centers its children, which makes flex kids shrink-to-fit; the
   swipe row must span the wrap or it escapes it sideways on phones. */
.proof-strip .reviews { width: 100%; }
/* Rating badge in a page hero (money, town and hub pages). Their review
   strip sits at position 9-10 of 11, roughly 2,000-2,500 words down, so
   before this only the homepage carried proof above the fold -
   local-service-conversion names "at least one review visible without
   scrolling" as a trait of top-converting local pages. */
.hero-proof { margin-top: 1.25rem; }

/* Mobile hero footprint. Measured at 375x812 the town hero ran 879px against
   an 812px viewport, so the CTA row and the rating badge - the two things the
   hero exists to deliver - both fell below the fold. The neighbour-link line
   is SEO plumbing rather than a decision aid, so on a phone it drops below
   them; nothing is removed, only reordered. Crumb and eyebrow margins tighten
   to buy the rest. */
@media (max-width: 760px) {
  .page-hero .wrap { display: flex; flex-direction: column; }
  /* Explicit order: headline -> proof -> pitch -> action. The badge sits
     directly under the H1 where it is above the fold on every page length,
     instead of trailing the CTAs where a long lead pushed it off-screen
     (money-page heroes run a longer lead than town heroes). The neighbour
     link line is SEO plumbing and goes last. */
  /* Catch-all slot FIRST, so any child this map doesn't name lands after
     the lead instead of jumping to order:0 at the very top of the hero.
     Third member of this bug family: the size pages' price line and
     size-switch pills had been rendering ABOVE the breadcrumb at phone
     widths since the map shipped - unnamed children default to 0. The
     class and element rules below out-specify this. */
  :where(.page-hero .wrap) > * { order: 6; }
  /* ^ :where() zeroes the selector, or this catch-all (two classes, 0-2-0)
     out-specifies `.page-hero h1` (0-1-1) and throws the HEADLINE into the
     default slot - which is exactly what it did on the first attempt. */
  .page-hero .crumb { order: 1; }
  /* Flex column stretch was inflating the eyebrow chip into a full-width
     band on every page-hero at phone widths - a chip is a label, not a
     banner. Shrink-wrap it; centered heroes (404, thank-you) center it. */
  .page-hero .eyebrow { align-self: flex-start; }
  .page-hero[style*="center"] .eyebrow { align-self: center; }
  /* The thank-you/404 mascot and the order readback joined the hero after
     this order map was written; without explicit slots, flex order:0 threw
     them to the FRONT of the column (mascot, order card, buttons, THEN the
     headline). Mascot leads, the readback follows the lead, buttons after. */
  .page-hero .ty-mascot { order: 1; }
  /* Same order as .lead: source order then places the card right after it,
     ahead of the steps list (which computes order 6). */
  .page-hero .ty-card { order: 5; margin-top: 1.25rem; }
  /* Bridge card follows the phone CTA (order 8), never splits it from the lead. */
  .page-hero .ty-bridge { order: 9; }
  .page-hero .cta-buttons { order: 8; }
  .page-hero .eyebrow { order: 2; }
  .page-hero h1 { order: 3; }
  /* The comment above this map has always said "the badge sits directly
     under the H1 where it is above the fold on every page length" - but the
     code gave hero-proof order:6, trailing the CTAs, and the audit measured
     the rating below the fold on 13 of 14 tall pages. The code now does what
     the comment says. */
  .page-hero .hero-proof { order: 4; margin-top: 0.8rem; }
  .page-hero .lead { order: 5; }
  .page-hero .cta-row { order: 7; }
  .page-hero .hero-neighbors { order: 10; margin-top: 1.1rem; margin-bottom: 0; }
  /* The 20-yard hero lead measured 286px at 375w - nine lines of 17px. One
     step down holds the copy and returns ~40px; the crumb held to one line
     returns ~20 more. Both offset the proof badge moving up the column. */
  .page-hero .lead { font-size: 1rem; line-height: 1.55; }
  .page-hero .crumb { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  .page-hero .crumb { margin-bottom: 0.6rem; }
  .page-hero .eyebrow { margin-bottom: 0.8rem; }
  .page-hero { padding-top: 1.5rem; }
  /* Reordering alone cannot shrink the hero, only change what lands in the
     first 812px. These trims buy the ~45px that puts the rating badge inside
     it too. Vertical rhythm only - no copy, no controls, no tap targets. */
  .page-hero h1 { margin-bottom: 0.7rem; }
  /* The lead is the tallest thing in these heroes (300px+ on a money page).
     1.02rem/1.5 stays well above the 16px mobile readability floor and buys
     ~55px, which is the difference between the CTA and the rating badge both
     landing in the first screen and neither of them doing so. */
  .page-hero .lead { margin-bottom: 0.55rem; font-size: 1.02rem; line-height: 1.5; }
  .page-hero .cta-row { margin-top: 1rem !important; }
}

.proof-rating {
  display: inline-flex; align-items: center; gap: 0.6rem;
  background: #fff; border: 1px solid var(--line-ft); border-radius: 999px;
  padding: 8px 18px 8px 12px; text-decoration: none; box-shadow: var(--shadow-ft);
}
/* Google gold, not the brand accent and not a near-miss orange — this is the
   cue that says the rating is real Google data (review-widget). */
.proof-rating .rs-stars { color: #fbbc04; font-size: 0.95rem; letter-spacing: 0.05em; }
.proof-since {
  margin: -0.6rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  text-align: center;
}
.proof-rating .rb-text { display: inline-flex; align-items: baseline; gap: 0.4rem; font-family: var(--font-display); }
.proof-rating .rb-text strong { color: var(--black); font-size: 1rem; font-weight: 700; }
.proof-rating .rb-text > span { color: var(--muted); font-size: 0.85rem; font-weight: 600; }
.proof-quotes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; width: 100%; max-width: 56rem; }
.proof-quote {
  margin: 0; background: #fff; border: 1px solid var(--line-ft);
  border-radius: var(--radius-ft); padding: 1.1rem 1.2rem; box-shadow: var(--shadow-ft);
}
.proof-quote blockquote { margin: 0 0 0.7rem; font-size: 0.97rem; line-height: 1.5; color: var(--ink); }
.proof-quote figcaption { font-family: var(--font-display); font-weight: 700; font-size: 0.82rem; color: var(--muted); }
@media (max-width: 700px) { .proof-quotes { grid-template-columns: 1fr; } }

/* Owner's face on the hero panel. */
.hero-panel-owner { display: flex; align-items: center; gap: 0.9rem; padding-bottom: 1rem; border-bottom: 1px solid var(--line-ft); }
.hero-panel-owner img {
  width: 62px; height: 62px; flex-shrink: 0; object-fit: cover; object-position: center 30%;
  border-radius: 50%; border: 2px solid var(--line-ft);
}
.hero-panel-owner .hero-panel-phone { padding-bottom: 0; border-bottom: 0; }
@media (max-width: 420px) { .hero-panel-owner img { width: 52px; height: 52px; } }

/* The owner's own words, set apart. One per page — this is a quote, not a
   decorative pull-quote pattern to repeat. */
.owner-quote {
  margin: 1.6rem 0;
  padding: 1.2rem 1.4rem;
  background: var(--bg-warm);
  border-left: 4px solid var(--yellow);
  border-radius: 0 var(--radius-ft) var(--radius-ft) 0;
}
.owner-quote blockquote {
  margin: 0 0 0.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.1rem, 2vw, 1.35rem);
  line-height: 1.35;
  color: var(--black);
}
.owner-quote figcaption { font-size: 0.85rem; color: var(--muted); font-weight: 600; }

/* Mobile hero compaction (local-service-homepage: a photo-background hero is
   capped at 65-80% of the viewport; this one measured 168% at 375px). Nothing
   is removed — Ryan's owner panel is deliberate — but the padding, the trust
   row and the panel's internal spacing were all desktop-tuned and stacked into
   1,368px on a phone. The trust pills wrapped to three rows, orphaning
   "Since 2021" on a line of its own. */
@media (max-width: 640px) {
  .hero.hero-bg { padding-top: 2.4rem; padding-bottom: 2.6rem; }
  .hero-trust { gap: 0.3rem; }
  /* The three pills need 381px of a 333px row at 375px, so the last one
     orphaned onto a third line. Dropping the decorative check glyph (it is
     already aria-hidden, so nothing is lost) buys ~17px each and lands all
     three on one row. Equal flex sharing was tried first and collapsed
     "Veteran Owned" to 29px of clipped text. */
  .hero-trust-pill { font-size: 0.72rem; padding: 5px 9px; }
  .hero-trust-pill .trust-check { display: none; }
  .hero-panel { padding: 1.15rem 1.2rem; }
  /* 32px in the 240px left beside the avatar wrapped the number mid-digits
     ("(417) 7" / "2029"). nowrap plus a smaller face keeps it on one line. */
  .hero-panel-phone {
    font-size: 1.55rem;
    white-space: nowrap;
    /* A tel: link on a phone, so give it a real target height rather than the
       28px the text alone produced. */
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .hero-panel-list { margin: 0.85rem 0 1rem; gap: 0.5rem; }
  .hero-panel-list li { font-size: 0.92rem; }
}

/* Decision blocks on service pages (scripts/build-decision-blocks.mjs). The
   two size pages carried this shape as repeated inline styles; this is the
   same look as a class so nine more copies don't ship inline. */
.pros-cons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem;
  margin-top: 1.5rem;
}
.pros-cons .pc-card {
  border: 3px solid var(--black);
  border-radius: 8px;
  padding: 1.1rem 1.25rem;
  background: #fff;
}
.pros-cons .pc-card h3 { margin-top: 0; }
.pros-cons .pc-card ul { margin: 0; padding-left: 1.1rem; }
.pros-cons .pc-card li { margin-bottom: 0.45rem; line-height: 1.5; }
.pros-cons .pc-card li:last-child { margin-bottom: 0; }
/* The negative column reads as the honest half, not as a warning. */
.pros-cons .pc-no { background: var(--bg-warm); }

/* Sibling size switcher under the hero CTA (scripts/build-size-switch.mjs). */
.size-switch {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1rem;
}
/* The size pages use the LIGHT .page-hero, not the homepage's dark photo
   hero, so this is dark ink on the warm background. Styled white first and it
   shipped invisible in the browser check. */
.size-switch .ss-label {
  font-size: 0.85rem;
  color: var(--muted);
  margin-right: 0.15rem;
}
.size-switch a,
.size-switch .ss-cur {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 0.85rem;
  border-radius: 6px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
  border: 2px solid var(--black);
  color: var(--black);
  background: #fff;
}
.size-switch a:hover { background: var(--bg-warm); }
/* Current page: filled, and not a link. */
.size-switch .ss-cur { background: var(--black); color: #fff; }
.size-switch .ss-guide { border-style: dashed; font-weight: 600; }

/* County layer on the service-areas hub (scripts/build-county-blocks.mjs).
   Linked towns have a page; plain pills are towns we name but never link,
   because a link would land on a redirect. */
.county-block { margin-top: 1.9rem; }
.county-block h3 { margin: 0 0 0.4rem; }
.county-block p { margin: 0 0 0.8rem; max-width: 68ch; }
.county-towns { display: flex; flex-wrap: wrap; gap: 0.45rem; }
.county-town {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 0.7rem;
  border-radius: 6px;
  font-size: 0.85rem;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
  text-decoration: none;
}
.county-pages { margin: 0 0 0.7rem; max-width: 68ch; }
a.county-town {
  border-color: var(--black);
  font-family: var(--font-display);
  font-weight: 700;
}
a.county-town:hover { background: var(--black); color: #fff; }
.county-town.is-plain { color: var(--muted); background: transparent; }
/* County-layer town links: rows, not a run-in of full-phrase anchors. The
   shared head mutes via .hub-tail; the town name leads the eye. */
ul.county-pages { list-style: none; margin: 0.75rem 0 1rem; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr)); column-gap: 2rem; }
ul.county-pages a { display: block; padding: 0.35rem 0; text-decoration: none; color: var(--black); font-weight: 700; }
ul.county-pages a:hover { color: var(--red-deep); }
ul.county-pages li + li a { box-shadow: 0 -1px 0 var(--line); }
@media (max-width: 640px) { ul.county-pages { grid-template-columns: 1fr; } }
/* The pill row now follows the linked town cards directly, so it needs its
   own top separation where the removed heading used to provide it. */
.areas-towns + .county-towns { margin-top: 1rem; }

/* Hub index line carrying the one exact-match anchor per service page
   (scripts/build-exact-anchors.mjs). */
/* Hub index. The anchors are deliberately the pages' FULL target phrases
   (Zyppy: one exact-match internal anchor is worth ~5x), so they are long and
   must not be shortened for looks. The design has to carry them instead:
   three 15rem columns wrapped all 13 to two lines and underlined every one,
   which read as a wall rather than a directory.

   CSS columns, not grid: with grid, the group in row 2 is pushed down by the
   tallest row-1 group, and "By job" has 8 items against 3 and 2. Multi-column
   flows the groups and balances them instead. */
/* Groups run FULL WIDTH and their links flow in columns, rather than the
   groups themselves being columned. The groups are 3 / 8 / 2 items, so
   columning the groups stranded "By box" alone beside 700px of dead space.
   Flowing the links balances automatically whatever the group sizes are. */
.hub-index { display: block; }
.hub-index-group { margin: 0 0 1.75rem; }
.hub-index-group ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr));
  column-gap: 2.5rem;
}
@media (max-width: 640px) {
  .hub-index-group ul { grid-template-columns: 1fr; }
}
.hub-index-group h3 {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--line);
}
.hub-index-group ul { list-style: none; margin: 0; padding: 0; }
.hub-index-group li { margin: 0; line-height: 1.35; }
.hub-index-group a {
  display: block;
  padding: 0.4rem 0;
  font-size: 0.92rem;
  color: var(--ink);
  text-decoration: none;
}
.hub-index-group a {
  border-radius: 6px;
  padding: 0.45rem 0.6rem;
  margin-left: -0.6rem;
  transition: background 120ms ease, color 120ms ease;
}
/* The shared "in Springfield, MO" tail recedes so the differentiating word
   at the head of each row is what the eye lands on. Same anchor string. */
.hub-tail { color: var(--muted); font-weight: 400; }
.hub-index-group a:hover { background: var(--bg-warm); color: var(--red-deep); }
.hub-index-group a:hover .hub-tail { color: var(--red-deep); }
.hub-index-group a:focus-visible { outline: 2px solid var(--red-deep); outline-offset: 2px; }
/* A hairline under each row turns a stack of text into a directory. */
.hub-index-group li + li a { box-shadow: 0 -1px 0 var(--line); }

/* Stat band, 2-up mobile (local-service-conversion). Two rules from the skill
   were failing at 375px: the captions all wrapped to two lines, which makes
   the grey caption blocks outweigh the numbers they caption, and the rating
   cell's value wrapped because "5.0" and "92 Google reviews" sat on one line.
   Stacking the rating cell gives it the skill's own shape (value 5.0, caption
   "92 Google reviews") without touching the rb-text markup that
   fetch-reviews.mjs rewrites weekly. */
@media (max-width: 760px) {
  .stat-band .stat-value .rb-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.1rem;
  }
  .stat-band .stat-value .rb-text > span {
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.72rem;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    opacity: 0.72;
  }
  .stat-band .stat-cap { font-size: 0.72rem; }
}

/* Size cards on mobile (local-service-design budget: a card <= 0.5 of the
   viewport, the card section <= ~2.5 screens). Measured at 375x812 the cards
   ran 512px (0.63) and the section 3.02 screens, so a visitor could never see
   two dumpsters at once on a page whose whole job is picking between them.

   Fixed in the skill's own order: duplication first (the duplicate "Details"
   links came out in the previous pass), then type scale and padding. Nothing
   real is removed - the title just stops wrapping to two lines, which was 88px
   of a 512px card on its own. */
@media (max-width: 760px) {
  /* The card photo was 181px of a 455px card - 40% - which pushed the card to
     0.56 of the viewport against the 0.5 budget, so a visitor could never see
     two boxes at once on the section whose whole job is choosing between them.
     A 2:1 crop keeps the dumpster readable and returns ~30px. */
  .size-card img { aspect-ratio: 2.2 / 1; object-fit: cover; height: auto; }
  /* The rank-label slot is reserved on EVERY card so a desktop ROW keeps its
     photos, titles and buttons aligned. Stacked in one column there is no row
     to align, so on the cards that carry no label it is ~20px of nothing.
     Collapse it there; the featured card still renders its label. */
  .size-card:not(.featured) .yd::before { display: none; }
  /* dumpsters.html comparison cards carry more than the homepage ones (spec
     chip, kicker, scale diagram, description, price, two controls) and ran
     544px - 0.67 of the viewport - so the 20 and the 14 could not be seen
     together on the page whose entire job is comparing them. Trims below are
     scale and rhythm only; no content leaves the card. */
  /* Measured at 375px the card was 499px against a 406px budget, and only
     373px of that was content - roughly 87px was inter-element margin. So the
     trim is rhythm first, scale second: nothing leaves the card, the diagram
     and every line of copy stay. */
  .size-card-art { max-height: 78px; width: auto; margin: 0.35rem auto; }
  .size-card-spec { letter-spacing: 0.02em; font-size: 0.72rem; margin-bottom: 0.15rem; }
  /* The featured card reserves padding-right so its spec line clears the
     "Most homes" chip. At 127px of a 295px box it wrapped IDENTICAL text
     ("14 ft x 7 ft . 6 ft walls") onto two lines while its neighbour sat on
     one - 21px, and a ragged mismatch between two cards meant to compare. The
     chip is ~95px on mobile. */
  .size-card-featured .size-card-spec { padding-right: 6.25rem; }
  .size-card-art { max-height: 64px; }
  .size-card .yd { margin: 0; }
  .size-card-kicker { margin-top: 0.1rem; margin-bottom: 0.1rem; }
  .size-card p { font-size: 0.92rem; line-height: 1.4; margin: 0.4rem 0; }
  .size-card-price { margin-top: 0.25rem; }
  .size-card-actions { padding-top: 0.6rem; gap: 0.4rem; }
  .size-card.priced { padding-top: 1.2rem; }
  /* 1.15rem, not 1.3: at 1.3 "20-Yard Dumpster" still wrapped to two lines in
     the 297px card (that tuning predates the current card width), and the
     second line was 22px of a 421px card. One line keeps the card inside the
     half-viewport budget, which is what lets a visitor see two boxes at once. */
  .size-card .yd { font-size: 1.15rem; }
  .size-card { padding: 1.15rem 1.05rem; }
  .size-card ul { margin: 0.6rem 0; }
  .size-card-actions { padding-top: 0.85rem; }
}

/* Heading rhythm (local-service-remediation). Space above a heading should beat
   space below it by roughly 2:1, or the heading groups with the paragraph it
   FOLLOWS instead of the section it introduces.

   Measured at 18px above / 15px below (1.2:1) because `.prose h3` carried a
   margin-top and `.prose h2` carried none, so the only gap above an h2 was the
   previous paragraph's own margin-bottom. That is the exact variant the skill
   documents. :not(:first-child) so a heading that opens a block is not pushed
   off the top of its own section. */
.prose h2:not(:first-child) { margin-top: 2.25rem; }
.prose h3:not(:first-child) { margin-top: 2rem; }

/* Town-page map wrapper and contact form fields. Both carried their layout as
   inline style=, which beats every stylesheet rule short of !important and so
   cannot be overridden at a breakpoint (local-service-site-pipeline). */
.town-map { border-radius: 8px; overflow: hidden; line-height: 0; }
.town-map iframe { border: 0; width: 100%; display: block; }
.contact-form input,
.contact-form textarea,
form.prose input[type="text"],
form.prose input[type="tel"],
form.prose input[type="email"],
form.prose textarea { width: 100%; }
/* Text link sitting beside a section button; was an inline margin-left. */
.cta-row a:not(.btn) { margin-left: 1rem; }
@media (max-width: 640px) { .cta-row a:not(.btn) { margin-left: 0; } }

/* ===== Design pass 2026-08-11 (batched, one bump) ===== */

/* Stat band: the rating cell reuses the hero badge's .rb-text markup (so
   fetch-reviews.mjs can rewrite it weekly), and inherited its near-black
   strong color - a black "5.0" on the black band. The inconsistency Ryan
   spotted. Every value in the band is white. */
.stat-band .rb-text strong { color: #fff; }

/* Availability badge on the size cards (fleet ruling: "Available Today" is a
   stock statement, never a delivery promise). Ink chip, brand-green dot -
   the green is reserved for this badge alone. */
.size-card { position: relative; }
.avail-badge {
  /* WOW-style: the pill straddles the card's top border (Ryan 2026-08-11,
     matching wasteonwheels). Works on every card now that Most Popular
     lives on the featured card's photo instead of a top band. */
  position: absolute;
  top: -0.7rem;
  right: 0.9rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--black);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
}
.avail-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #39ab2a;
}
/* The featured card's "Most Popular" ribbon owns the top edge; drop the
   badge inside the card's corner there instead of overlapping the ribbon. */
/* dumpsters.html size cards carry their spec chip top-right, so availability
   sits top-left there. */
.avail-badge-left { right: auto; left: 0.9rem; }

/* ===== Size-card content stack (design pass: price is the second anchor) =====
   The card's job order is: what it is (title) -> what it costs (price, the
   open-pricing differentiator, display-scale not metadata) -> what it's for ->
   will it fit (quiet spec line). The old stack buried $299 at 13.9px muted
   grey inside the dims line and spent 53px on a one-item bulleted list. */
.size-card-price {
  display: block;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.4rem;
  color: var(--black);
  margin-top: 0.35rem;
  line-height: 1.1;
}
.size-card-price small {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.78rem;
  color: var(--muted);
  letter-spacing: 0.02em;
}
.size-card-for {
  display: block;
  font-size: 0.95rem;
  color: var(--ink);
  line-height: 1.4;
  margin-top: 0.45rem;
}
.size-card-spec {
  display: block;
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 0.3rem;
}

/* Proof strips on money pages (Ryan 2026-08-11) reuse the homepage .reviews
   swipe row wholesale - same cards, same indicator/auto-advance JS. With only
   three cards the row fills the desktop grid exactly and scrolls on phones,
   so the 12,000px side-scroller trap (many cards in .reviews on a stacked
   page) does not apply. No extra CSS needed. */

/* ============ Contact page: contact card + real form styling ============
   The short contact form was rendering as bare <label><br><input>, which the
   browser draws as thin full-round pills that match nothing else on the site.
   The proper field pattern already existed but was inline-scoped inside
   request-a-quote.html, so no other page could reach it. Promoted here. */

/* The phone/hours block. Phone is the primary action on this page type, so it
   gets the visual weight rather than sitting in a list of paragraphs. */
.contact-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 1.5rem 1.4rem;
  margin-bottom: 1.75rem;
}
.contact-phone {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.45rem 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 5vw, 2.1rem);
  color: var(--black);
  text-decoration: none;
  line-height: 1.15;
}
.contact-phone:hover { color: var(--yellow); }
.contact-card .cc-label {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.3rem;
}
.contact-meta {
  margin: 1.1rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 0.55rem;
  font-size: 0.95rem;
}
.contact-meta div { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.contact-meta dt, .contact-meta .k {
  font-weight: 700;
  color: var(--ink);
  min-width: 5.5rem;
}

/* The form itself, in a card so it reads as a distinct task. */
.form-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 1.6rem 1.4rem 1.4rem;
}
.form-card > h3 { margin-top: 0; }
.form-field { margin-bottom: 1.15rem; }
.form-field label {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  margin-bottom: 0.35rem;
}
.form-field small {
  display: block;
  color: var(--muted);
  font-weight: 400;
  font-size: 0.85rem;
  margin-top: 0.3rem;
}
.form-field input[type="text"],
.form-field input[type="tel"],
.form-field input[type="email"],
.form-field textarea {
  width: 100%;
  max-width: 100%;
  padding: 0.8rem 0.9rem;
  border: 2px solid var(--line);
  border-radius: 8px;
  background: #fff;
  /* inherit, not monospace: the textarea was rendering its placeholder in the
     browser default mono face while the inputs above it used the body font. */
  font-family: inherit;
  font-size: 1rem;
  color: var(--ink);
}
.form-field textarea { min-height: 7rem; resize: vertical; }
.form-field input::placeholder,
.form-field textarea::placeholder { color: #8b8b8b; }
.form-card button[type="submit"] { width: 100%; justify-content: center; }
.form-fine {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 0.85rem 0 0;
}
@media (min-width: 600px) {
  .form-card button[type="submit"] { width: auto; }
}


/* ============ Hero ticket card, built 2026-08-12 ============
   Replaces .hero-panel, which was the stock pattern this whole vertical
   ships: white rounded box, soft drop shadow, centered avatar, one flat
   surface. Ryan flagged that a competitor runs the identical card.

   This is built as a dispatch ticket, which is what the business actually
   runs on. A solid green header carries the call, Kyle's face sits ON the
   seam between header and body, the list is ruled rather than floating, and
   depth is the house hard-offset shadow (same technique as .review) rather
   than a soft float. Corners 4px, not 16px.

   Conversion fundamentals from local-service-conversion are unchanged: still
   a contained box (+50.5% in Google's own split test), phone still the
   dominant element, still four falsifiable checklist items, still one CTA.

   Namespaced .hero-ticket rather than reusing .hero-card: that class already
   exists in this stylesheet as dead donor CSS with different geometry, and
   reviving it would inherit rules nobody intended. */
.hero-ticket {
  --ht-pad: 1.45rem;
  align-self: center;
  justify-self: end;
  max-width: 27rem;
  width: 100%;
  background: #fff;
  border: 2px solid var(--black);
  border-radius: 4px;
  box-shadow: 8px 8px 0 var(--black);
  overflow: hidden;
}
.hero-ticket-head {
  background: var(--yellow);
  /* extra bottom padding leaves room for the avatar that straddles the seam;
     without it the face crowds the phone number descenders. */
  padding: 1.15rem var(--ht-pad) 2.5rem;
  text-align: center;
}
.hero-ticket-kicker {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.88);
  margin-bottom: 0.3rem;
}
/* clamp floor sized so (417) 766-2029 never breaks to two lines. The card it
   replaces wrapped the number at every width below ~430px, which is the one
   element on the page that must never wrap. */
.hero-ticket-phone {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 6vw, 2.05rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: #fff;
  text-decoration: none;
  white-space: nowrap;
}
.hero-ticket-phone { padding: 0.2rem 0 0.25rem; }
.hero-ticket-phone:hover { text-decoration: underline; text-underline-offset: 4px; }
.hero-ticket-phone:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
/* Face straddles the seam: costs no vertical space and is the detail the
   stock card doesn't have. */
.hero-ticket-face { display: flex; justify-content: center; margin-top: -34px; }
.hero-ticket-face img {
  width: 68px;
  height: 68px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #fff;
  box-shadow: 0 2px 6px rgba(11, 11, 11, 0.18);
}
.hero-ticket-body { padding: 0.55rem var(--ht-pad) var(--ht-pad); }
.hero-ticket-name {
  text-align: center;
  font-size: 0.85rem;
  color: var(--muted);
  margin: 0 0 0.9rem;
}
.hero-ticket-list { list-style: none; margin: 0 0 1.1rem; padding: 0; }
.hero-ticket-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--line);
  font-size: 0.97rem;
  line-height: 1.4;
}
.hero-ticket-list li:first-child { border-top: 0; }
/* Square check: the green circle-check is the tell of the card this replaces. */
.hero-ticket-check {
  flex: 0 0 auto;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: 0.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--yellow);
  color: #fff;
  border-radius: 3px;
  font-size: 0.72rem;
  font-weight: 700;
}
@media (max-width: 900px) {
  .hero-ticket { justify-self: center; box-shadow: 6px 6px 0 var(--black); }
}
/* Hero CTA is a .btn from the shared family; this only makes it fill the
   ticket's width, which the bespoke .hero-panel-cta used to hard-code. */
.hero-ticket-cta { display: flex; width: 100%; justify-content: center; margin-top: 0.2rem; }


/* ===== 3-step process visual, ported from scribbys-site 2026-08-12 =====
   Ryan asked for the same treatment here. Icon circle + number badge + dashed
   connector between steps on desktop, stacking on phones. --yellow is 417's
   green token, so the badge and icon read in brand without edits. */
/* ===== 3-step process: icon circles + dashed connector ===== */
.process-steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.25rem;
  margin-top: 2.5rem;
}
@media (min-width: 800px) {
  .process-steps {
    grid-template-columns: repeat(3, 1fr);
    gap: 2rem;
  }
}
.process-step {
  text-align: center;
  position: relative;
  padding: 0 0.5rem;
}
.process-step-visual {
  position: relative;
  width: 96px;
  height: 96px;
  margin: 0 auto 1.25rem;
  z-index: 1;
}
.process-step-icon {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--yellow);
  border: 3px solid var(--black);
  box-shadow: 4px 4px 0 var(--black);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--black);
  position: relative;
  z-index: 1;
}
.process-step-icon svg {
  width: 46px;
  height: 46px;
}
/* Spec panel on the two size pages: the landscape rework of the spec card.
   Diagram beside the facts at section width; stacks on phones. */
.spec-panel {
  position: relative;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 1.5rem 2.25rem;
  align-items: center;
  background: #fff;
  border: 3px solid var(--black);
  border-radius: var(--r-md);
  box-shadow: 6px 6px 0 var(--black);
  padding: 1.75rem 2rem;
}
.spec-panel-art img { width: 100%; height: auto; display: block; }
.spec-panel-art .size-card-spec { display: block; text-align: center; margin-top: 0.5rem; }
.spec-panel-facts .size-card-kicker { display: block; }
.spec-panel-facts .size-card-price { display: block; margin-top: 0.35rem; }
.spec-panel-facts p { margin: 0.6rem 0 0; }
@media (max-width: 760px) {
  .spec-panel { grid-template-columns: 1fr; padding: 1.25rem; gap: 1rem; }
}

/* About page: two curated cards side by side. The strip's equal-height
   stretch is right for a swipe row, but with exactly two cards of very
   different lengths it left the short one two-thirds empty (Ryan's
   screenshot, 2026-08-13). Scoped here only - the strips keep equal height
   per his standing ruling. */
.reviews-pair { overflow-x: visible; flex-wrap: wrap; align-items: flex-start; }
.reviews-pair .review { flex: 1 1 280px; scroll-snap-align: none; }

/* Unused on index.html as of 2026-08-13. The number badges came off the
   three-step block: the dashed connector, the left-to-right reading order and
   the step headings themselves ("Call it in" -> "We set it down" -> "Call when
   it's full") each already carry the sequence, and a second small circle stuck
   on the icon circle read as a sticker on a sticker. Rule kept because the
   pattern is shared with other builds. */
.process-step-num {
  position: absolute;
  top: -6px;
  right: -8px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--black);
  color: var(--yellow);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--black);
  z-index: 2;
}
.process-step h3 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.2rem;
  margin: 0 0 0.6rem;
  line-height: 1.25;
}
.process-step p {
  margin: 0 auto;
  color: var(--ink);
  font-size: 0.97rem;
  line-height: 1.55;
  max-width: 30ch;
}
/* Dashed connector between steps — desktop only. Line sits behind
   the next icon (z-index 0; icon is z-index 1) so overlap is hidden. */
@media (min-width: 800px) {
  .process-step:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 48px;
    left: calc(50% + 58px);
    right: calc(-50% - 32px + 58px);
    border-top: 3px dashed var(--black);
    opacity: 0.28;
    z-index: 0;
  }
}
/* ── Mobile hero height (design audit, 2026-08-23) ───────────────────────────
   Measured at 375x812: the homepage hero ran 1192px, 147% of the viewport,
   against a 65-80% house target - the worst on the fleet, and worse than the
   106% case the doctrine cites as a failure. Nothing below it peeked, so the
   page read as though it had no second section.

   Cut duplication before anything real, in the prescribed order. The ticket's
   green head is a kicker plus the phone number, and the copy column already
   shows a full-width "Call (417) 766-2029" button ~20px above it - the same
   tel:, twice, inside one viewport. Hiding just that pair costs a visitor
   nothing they cannot still tap, and returns 117px.

   The avatar straddles the head/body seam with margin-top:-34px, so it has to
   stop hanging once the head above it is gone.

   Kyle's four value props, his face and his name all stay. Deleting those to
   hit a number would be trading the content that answers "who am I calling"
   for a metric. */
@media (max-width: 760px) {
  .hero.hero-bg .hero-ticket { display: none; }
  .hero.hero-bg { padding-top: 2rem; padding-bottom: 2.25rem; }
  .hero.hero-bg .lead { margin-bottom: 1.15rem; }
  .hero.hero-bg .hero-trust { margin-bottom: 0; }
}

/* ── Photo grid ─────────────────────────────────────────────────────────────
   Shared by gallery.html and the homepage teaser. Was inline on gallery.html,
   so the homepage could not use it without duplicating it. A regular uniform
   grid on purpose: NN/g is explicit that photo galleries want a grid, not
   cards or masonry, and one crop style across every photo is what makes a set
   read as one shoot rather than a pile of uploads. */
.gallery-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 620px) { .gallery-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 980px) { .gallery-grid { grid-template-columns: 1fr 1fr 1fr; } }
.gallery-grid figure { margin: 0; }
.gallery-grid img {
  width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--r-btn); border: 2px solid var(--black);
}
/* Captions carry information - town, job, size - because 56% of users go to
   the images first and skip the prose around them. */
.gallery-grid figcaption {
  font-family: var(--font-display); font-weight: 600; font-size: 0.9rem;
  color: var(--muted); margin-top: 0.4rem;
}

/* ── Post cards ─────────────────────────────────────────────────────────────
   Shared by blog/index.html and the homepage strip. */
.post-card {
  display: block; padding: 0; overflow: hidden; background: #fff;
  border: 1px solid var(--line); border-radius: 6px;
  text-decoration: none; color: inherit;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.post-card:hover { border-color: var(--red); transform: translateY(-2px); box-shadow: 4px 4px 0 var(--black); }
.post-thumb { aspect-ratio: 16 / 9; background: var(--bg-warm); overflow: hidden; }
.post-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-card-body { padding: 1.5rem; }
.home-posts { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .home-posts { grid-template-columns: repeat(3, 1fr); } }

/* ── Veteran & first responder band ─────────────────────────────────────────
   The discount moved out of the hero price line (Ryan, 2026-08-24) into its
   own band after the photo strip: identity (story) -> proof (photos) -> the
   offer. Dark like the stat band so it reads as a landmark, not a section.
   The offer is real and unnumbered - Kyle's register is "ask about", so the
   band states it and hands over the phone. */
.vet-band { background: var(--black); color: #fff; padding: clamp(2.25rem, 5vw, 3.25rem) 0; }
.vet-band-inner { display: flex; align-items: center; justify-content: space-between; gap: 2rem; }
.vet-band h2 { color: #fff; font-size: clamp(1.5rem, 2.6vw, 2rem); margin: 0 0 0.5rem; }
.vet-band p { margin: 0; max-width: 52ch; color: rgba(255, 255, 255, 0.85); }
.vet-band .btn-primary { background: var(--red); border-color: var(--red); color: #fff; flex: none; }
@media (max-width: 760px) {
  .vet-band-inner { flex-direction: column; align-items: flex-start; }
  .vet-band .btn-primary { width: 100%; }
}

/* ── Quote wizard stages ────────────────────────────────────────────────────
   The modal walks the order in three stages instead of one 1390px screen.
   Stages are fieldsets so each carries a real legend; only .active shows. */
.qm-stage { display: none; border: 0; padding: 0; margin: 0; min-width: 0; }
.qm-stage.active { display: block; animation: qm-stage-in 0.28s ease; }
@keyframes qm-stage-in {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .qm-stage.active { animation: none; }
}
/* Size picker: two selectable cards. Shipped unstyled for a while - bare
   inline radios running together - so this block is load-bearing, not
   decoration. */
.qm-sizes {
  display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem;
  margin-bottom: 1.1rem;
}
.qm-sizes label {
  position: relative; display: block; cursor: pointer;
  border: 2px solid var(--line); border-radius: 8px;
  padding: 0.8rem 0.9rem; background: var(--bg);
  transition: border-color 140ms ease, background 140ms ease;
}
.qm-sizes label:hover { border-color: var(--red-deep); }
.qm-sizes input { position: absolute; opacity: 0; pointer-events: none; }
.qm-sizes span { display: block; }
.qm-sizes strong {
  display: block; font-family: var(--font-display); font-weight: 800;
  font-size: 1.05rem; line-height: 1.2;
}
.qm-sizes small { display: block; color: var(--muted); margin-top: 2px; font-size: 0.82rem; }
.qm-sizes label:has(input:checked) {
  border-color: var(--red-deep);
  background: var(--yellow-tint);
}
.qm-sizes label:has(input:checked)::after {
  content: "\2713"; position: absolute; top: 0.55rem; right: 0.7rem;
  font-weight: 800; color: var(--red-deep);
}
.qm-sizes label:has(input:focus-visible) { outline: 3px solid var(--red-deep); outline-offset: 2px; }
@media (max-width: 420px) {
  .qm-sizes { grid-template-columns: 1fr; }
}
.qm-stage-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.1rem; padding: 0; margin-bottom: 0.9rem;
}
.qm-progress {
  display: flex; gap: 0.4rem; list-style: none; counter-reset: qmstep;
  margin: 0 0 1.1rem; padding: 0;
}
.qm-progress li {
  counter-increment: qmstep; flex: 1; text-align: center;
  font-family: var(--font-display); font-weight: 700; font-size: 0.78rem;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted);
  padding: 0.45rem 0.2rem 0.55rem; border-bottom: 3px solid var(--line-ft);
}
.qm-progress li::before { content: counter(qmstep) ". "; }
.qm-progress li.active { color: var(--red-deep); border-bottom-color: var(--red-deep); }
.qm-progress li.done { color: var(--ink); border-bottom-color: var(--yellow); }
.qm-back {
  display: block; width: 100%; margin-top: 0.7rem; padding: 0.5rem;
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-display); font-weight: 700; font-size: 0.92rem;
  color: var(--muted); text-align: center;
}
.qm-back:hover { color: var(--ink); }
.qm-back:focus-visible { outline: 3px solid var(--red-deep); outline-offset: 2px; }
.qm-opt { font-weight: 400; color: var(--muted); }
.qm-echo {
  margin: 0 0 0.9rem; padding: 0.65rem 0.8rem; font-size: 0.92rem;
  background: var(--bg-warm); border: 1px solid var(--line-ft); border-radius: var(--r-md);
}
.qm-echo:empty { display: none; }

/* Numbers that sit in columns or update in place get fixed-width digits, so
   $299/$249/$20 align vertically and the live price doesn't wiggle as the
   day count changes. */
.qm-price-value, .qm-echo, .price-note, .fee-list, table td, .hero-prices strong,
.size-act, .stat-band strong { font-variant-numeric: tabular-nums; }

/* Thank-you receipt card: the order read back as the centerpiece - "here's
   your order, we'll call to confirm" (Ryan, 2026-10-05). */
.ty-card {
  max-width: 27rem; margin: 1.75rem auto 0; text-align: left;
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--r-md); overflow: hidden;
}
.ty-card-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding: 0.9rem 1.3rem;
  background: var(--red-deep);
}
.ty-card-head h2 {
  margin: 0; font-size: 1.05rem; color: #fff;
  font-family: var(--font-display); font-weight: 800;
}
.ty-card-head span { color: rgba(255, 255, 255, 0.9); font-size: 0.88rem; white-space: nowrap; }
.ty-row {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; padding: 0.7rem 1.3rem;
}
.ty-row + .ty-row { border-top: 1px solid var(--line-ft); }
.ty-row span { font-family: var(--font-display); font-weight: 600; font-size: 0.88rem; color: var(--muted); }
.ty-row strong { font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.ty-row-price { background: var(--yellow-tint); }
.ty-row-price span { color: var(--ink); }
.ty-row-price strong { font-family: var(--font-display); font-weight: 800; font-size: 1.3rem; }
/* Contact thank-you: the booking cross-sell in its own quiet card. */
.ty-bridge {
  max-width: 26rem; margin: 2.25rem auto 0; padding: 1.4rem 1.5rem 1.5rem;
  background: var(--bg-warm); border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.ty-bridge-head {
  margin: 0 0 0.3rem; font-family: var(--font-display);
  font-weight: 800; font-size: 1.1rem;
}
.ty-bridge p:not(.ty-bridge-head) { margin: 0 0 1rem; color: var(--muted); font-size: 0.95rem; }
.ty-card-foot {
  margin: 0; padding: 0.8rem 1.3rem; font-size: 0.88rem; color: var(--muted);
  border-top: 1px solid var(--line-ft);
}
