:root {
  /* Waste On Wheels palette v2 (2026-07-22): NAVY base + her real equipment
     ORANGE as the action/accent tier. Sampled from Logan's own assets: the
     logo monogram on her social profile is #e06800 and the cans photograph at
     #e85018, so the site now matches what customers see in the driveway.
     Navy stays the structure color (topbar, footer, dark sections, all body
     text), which keeps the wordmark and decals reading correctly.

     Two-shade orange per the dumpster-brand-red-contrast rule:
       yellow token  #e8590c  bright can orange. Only ever used as text ON navy
                          (5.05:1) or as a background carrying navy text
                          (5.05:1), so it passes AA in both directions.
       red-deep token #c43e00 filled CTAs with WHITE text (5.2:1 AA).
       red-deeper token #a33200 hover (6.97:1).
       orange-on-dark #f2610a accents on dark sections (5.59:1 on navy).
     --no stays true red for restricted-item ✕ marks; --ok green for ✓.
     Legacy yellow/red token names are kept so the whole sheet reskins here. */
  --yellow: #e8590c;
  --yellow-deep: #c43e00;
  --yellow-tint: #fdefe6;
  --red: #e8590c;
  --red-deep: #c43e00;
  --red-deeper: #a33200;
  --no: #c62828;
  --ok: #1e9e4a;
  /* --ok reads at 3.48:1 on white, which is fine for a filled badge or an
     icon but under AA for green body text. --ok-deep is the text tier
     (6.08:1 on white), same relationship --red-deep has to --yellow. */
  --ok-deep: #14713a;
  --blue-on-dark: #f2610a;   /* legacy name, now the on-dark orange accent */
  /* Hero headline accent ONLY. The orange above crosses the orange dumpster
     in the hero photo and measured 1.02:1 there, so the accent line uses a
     cream that clears AA across the whole photo. Deliberately a separate
     token: --blue-on-dark still drives footer links and button shadows,
     which never sit over the image. */
  --hero-accent: #ffedd5;
  --navy: #0d2c54;
  --black: #0e1626;
  --ink: #131c2c;
  --muted: #55607a;
  --line: #dde3ec;
  --logo-gray: #d0d0d0;
  --bg: #ffffff;
  --bg-warm: #f7f5f2;

  --font-display: "Zilla Slab", Georgia, serif;
  --font-body: "Public Sans", system-ui, sans-serif;

  --max: 1280px;
  --pad: clamp(1.25rem, 4vw, 2.5rem);
}

/* WCAG 2.4.1 Bypass Blocks. Every page opens with the same logo, six nav
   items and two CTAs, which a keyboard or screen-reader user had to walk
   through on every single page before reaching content. Off-screen until
   focused, so it costs sighted users nothing. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--black);
  color: #fff;
  padding: 0.75rem 1.25rem;
  font-family: var(--font-display);
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 8px 0;
}
.skip-link:focus {
  left: 0;
  outline: 3px solid var(--yellow);
  outline-offset: -3px;
}

/* Zilla Slab ships old-style (text) figures as its default. Measured from the
   700 weight: 6 and 8 rise to 660 (above the font's own 650 cap height) while
   3, 4, 5, 7 and 9 drop to about -140, and 0, 1, 2 sit near x-height. So
   "(919) 524-4456" renders with digits at three different heights, which reads
   as a rendering fault rather than as typography on a page full of phone
   numbers, sizes and tonnages. The font carries lnum, so switch to lining
   figures. font-variant-numeric inherits, so this reaches every one of the
   90 rules that use --font-display without touching them. */
:root {
  font-variant-numeric: lining-nums;
}

* {
  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.05;
  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: 4px;
}
.photo::before {
  content: "PHOTO";
  position: absolute;
  top: 12px;
  left: 12px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  background: var(--black);
  color: var(--yellow);
  padding: 4px 8px;
  border-radius: 2px;
}
.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: rgba(11, 11, 11, 0.97);
  backdrop-filter: blur(6px);
  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: 46px;
  width: auto;
  /* Never stretch. If a parent ever constrains the box again, letterbox rather
     than distort — a squashed logo is the most visible possible bug. */
  object-fit: contain;
  display: block;
  margin: 0.5rem 0;
  flex-shrink: 0;
}
.brand {
  flex-shrink: 0;
}
nav.primary {
  display: none;
  gap: 1.4rem;
  font-weight: 500;
  white-space: nowrap;
}
nav.primary a {
  color: #fff;
  text-decoration: none;
  font-size: 0.9rem;
  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);
}
/* You-are-here: reuses the hover underline, held open. topbar-scroll.js sets
   aria-current, and section pages resolve to their hub (a town page marks
   "Service Area", a post marks "Blog"). */
nav.primary a[aria-current="page"]::after {
  transform: scaleX(1);
}
nav.primary a[aria-current="page"] {
  font-weight: 700;
}

.tel-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--yellow);
  color: var(--black);
  text-decoration: none;
  padding: 0.65rem 1rem;
  border-radius: 3px;
  font-weight: 700;
  font-family: var(--font-display);
  font-size: 0.95rem;
  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;
}

.hours-pill {
  display: none;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.72);
}
.hours-pill strong {
  color: #fff;
  font-weight: 600;
}

/* Nav row needs 1180px, not 1000. The old comment assumed ~774px for nav +
   logo + phone; that was true before Contact joined the nav and before the
   logo was pinned at flex 0 0 auto. Measured now: logo 175 + nav 603 + phone
   ~250 + gaps 51 + padding 85 = ~1164. At 1024 the row overflowed by 178px,
   which used to hide itself by squashing the logo. iPad landscape now gets the
   hamburger, which is the honest outcome. */
@media (min-width: 1180px) {
  nav.primary {
    display: inline-flex;
  }
}


/* .hours-pill is retired from the header. At 1280 the logo (175) + nav (601) +
   actions (379) + gaps + padding ran ~10px over, and once the logo was pinned
   at flex 0 0 auto that overflow had nowhere to go. The pill was the only
   non-actionable item in the row, and the hours still appear in the footer NAP
   on every page, in openingHoursSpecification, and on the contact page. The
   rules below are kept because the pill markup may return elsewhere. */

/* ===== Mobile hamburger menu ===== */
.nav-toggle-cb {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.nav-toggle {
  display: none;
}
@media (max-width: 1179px) {
  /* 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;
  }
  /* 56px put the header 7px over at 375: brand 132 + burger 44 + phone 146 +
     gaps 17 + padding 42.5 = 382. The logo can't shrink any more (flex 0 0
     auto, deliberately), so the height comes down instead. 50px keeps the mark
     legible and clears the narrowest common phone with room to spare. */
  .brand-mark {
    height: 50px;
  }
  .tel-cta {
    padding: 0.5rem 0.55rem;
    font-size: 0.85rem;
    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: 4px;
    flex-shrink: 0;
    order: 10;
  }
  .nav-toggle span {
    display: block;
    width: 22px;
    height: 2px;
    background: #fff;
    border-radius: 2px;
    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: #0e1626;
    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;
}
.topbar-scroll-cta {
  display: none;
}
.brand,
.tel-cta {
  transition:
    transform 340ms cubic-bezier(0.33, 1, 0.68, 1),
    opacity 340ms cubic-bezier(0.33, 1, 0.68, 1);
}
@media (max-width: 899px) {
  /* backdrop-filter forces per-frame compositing of everything behind the
     fixed bar; at 97%-opaque black the blur is invisible but the frame cost
     is real on phones. Solid color = fluid morph. */
  .topbar {
    --morph: 0; /* 0..1, written by topbar-scroll.js from scroll position */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: #0e1626;
  }
  /* Scroll-DRIVEN morph: positions interpolate from --morph, so the swap
     tracks the finger. The 90ms linear transition only smooths the steps
     between discrete scroll events, it is not the animation itself. */
  .topbar .brand,
  .topbar .tel-cta {
    transform: translateY(calc(var(--morph) * -10px));
    opacity: calc(1 - var(--morph));
    transition: transform 90ms linear, opacity 90ms linear;
  }
  .topbar-scroll-cta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    position: absolute;
    left: var(--pad);
    right: calc(var(--pad) + 56px); /* leave room for hamburger (44px) + gap */
    top: 50%;
    transform: translateY(-50%) translateY(calc((1 - var(--morph)) * 12px));
    opacity: var(--morph);
    pointer-events: none;
    will-change: transform, opacity;
    transition: transform 90ms linear, opacity 90ms linear;
  }
  .topbar.topbar-scrolled .brand,
  .topbar.topbar-scrolled .tel-cta {
    pointer-events: none;
  }
  .topbar.topbar-scrolled .topbar-scroll-cta {
    pointer-events: auto;
  }
  .topbar-scroll-cta a {
    flex: 1;
    text-align: center;
    background: var(--yellow);
    color: var(--black);
    padding: 0.65rem 0.75rem;
    border-radius: 4px;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.95rem;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--black);
  }
}

/* ===== 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) {
  .hero-grid {
    grid-template-columns: 1.1fr 1fr;
    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(--yellow);
  padding: 4px 10px;
  margin-bottom: 1.5rem;
  border-radius: 2px;
}

.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 {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  align-items: center;
  margin-bottom: 1.25rem;
}
.btn {
  display: inline-flex;
  align-items: 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: 6px;
  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);
}
.btn-secondary:hover {
  background: var(--black);
  color: #fff;
}
/* Button that closes a prose block. The SEO review flagged trailing "the
   contractor page has the details" links as a weak pattern — these replace
   them. Sized down from .btn so they support the section rather than compete
   with the hero CTA, and allowed to wrap since the labels are full phrases. */
.btn-inline {
  margin-top: 1.5rem;
  white-space: normal;
}
.btn-big {
  /* Ceiling trimmed from 1.65 to 1.5rem and the side padding from 1.5 to
     1.15rem when the display face moved to Zilla Slab. Zilla is materially
     wider than Oswald: the hero pair measured 580px of button plus a 12.75px
     gap inside a 592px column, so the row wrapped by a single pixel. This
     buys real headroom rather than clearing it by one. */
  font-size: clamp(1.2rem, 2vw, 1.5rem);
  font-weight: 700;
  padding: 0.85rem 1.15rem;
}

.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: 6px;
  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: 6px;
  border: 2px solid var(--black);
  margin-bottom: 0.75rem;
  margin-left: 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;
}
@media (max-width: 500px) {
  .text-big {
    margin-left: 0;
    margin-top: 0.5rem;
  }
}

/* ===== 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: clamp(3.5rem, 8vw, 6rem) 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: 4px;
  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);
  /* Row gap has to clear two things that live outside the card's border box:
     the 6px hard shadow below it, and the availability badge on the card
     underneath, which sits at top: -0.75rem and so pokes 12px up. That is 18px
     of intrusion into what used to be a 16px gap, i.e. touching at rest, and
     hover lifts the card a further 3px for 21px. 2.5rem leaves ~19px clear at
     the worst moment. Column gap covers the 6px shadow plus the same 3px
     hover shift. */
  gap: 2.5rem 1.75rem;
  margin-top: 2rem;
}
/* Mobile: 2-up squeezes the cards into wrapped prices and truncated buttons.
   Swap to a native scroll-snap carousel: one roomy card at a time, the next
   one peeking to invite the swipe, momentum physics for free. */
@media (max-width: 699px) {
  /* Stacked, not a horizontal scroller. A swipe row hides content: plenty of
     people see the first card and never learn there are four sizes, and the
     sizes and prices are the whole point of the page.
     .reviews keeps its carousel — that one is a deliberate strip, not a list
     of products someone has to choose between. */
  .sizes {
    display: grid;
    grid-auto-flow: row;
    grid-template-columns: 1fr;
    grid-auto-columns: auto;
    overflow-x: visible;
    scroll-snap-type: none;
  }
  .sizes > .size-card {
    scroll-snap-align: none;
  }
}

/* JS-injected swipe indicator: a little left-right scrollbar that tracks the
   carousel, visible on every platform including iOS. Kept at top level rather
   than inside the mobile query because the review strip scrolls at every
   width; the size carousel only scrolls below 700px. */
.hscroll-track {
  height: 5px;
  background: var(--line);
  border-radius: 3px;
  margin: 0.75rem auto 0;
  max-width: 11rem;
  position: relative;
  overflow: hidden;
}
.hscroll-thumb {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--red-deep);
  border-radius: 3px;
  transition: none;
}
/* Two across, not four. The card photo is a 3:2 landscape of Logan beside
   the container; a quarter-width card gave it roughly a 248px slot, too
   small for the scale in the shot to read. Two columns take it to ~552px.
   Services keep three columns via .sizes.cols-3, which is more specific
   than this rule and so is untouched. */
/* Four across is the default: the homepage and pricing want all four sizes
   comparable at a glance. dumpsters.html opts into 2x2 with .cols-2, where
   the visitor is there to browse and the photo earns the extra height. */
@media (min-width: 700px) {
  .sizes {
    grid-template-columns: repeat(4, 1fr);
  }
  .sizes.cols-2 {
    grid-template-columns: repeat(2, 1fr);
  }
}
.size-card {
  border: 1px solid var(--line);
  padding: 1.5rem 1.25rem;
  background: #fff;
  border-radius: 4px;
  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.88rem;
  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; topbar-scroll.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;
}
/* flex (not grid-auto-flow: column) on purpose: grid-auto-flow inside
   overflow-x: auto collapses to a single vertical column in iOS Safari.
   flex-shrink: 0 is what keeps cards from being squashed to fit the row. */
.reviews > * {
  flex: 0 0 84%;
  flex-shrink: 0;
  scroll-snap-align: start;
}
@media (min-width: 800px) {
  .reviews > * {
    flex-basis: 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 orange)
   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: 8px;
  box-shadow: 0 1px 3px rgba(14, 22, 38, 0.09);
  display: flex;
  flex-direction: column;
}
.rv-head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.7rem;
}
/* Initial disc. All three fills carry white text well past AA:
   --red-deep 5.20:1, --navy 13.95:1, the slate 7.22:1. */
.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: var(--navy);
}
.reviews .review:nth-child(3n) .rv-avatar {
  background: #45596e;
}
.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;
}
/* Google's own star gold. At 1.71:1 on white it can't carry meaning on its
   own, so the star row must be aria-hidden and the rating stated in text
   beside it — which is how the widget reads anyway. */
.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);
}
/* Legacy card markup (.stars / .meta) still renders correctly inside the
   new shell — some pages have not been migrated to the .rv-* head yet. */
.review .stars {
  color: #fbbc04;
  font-size: 1.05rem;
  letter-spacing: 0.05em;
  margin-bottom: 0.6rem;
  font-family: var(--font-body);
}
.review .meta {
  font-size: 0.85rem;
  color: var(--muted);
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  margin-top: 0.9rem;
}
.review .meta .name {
  font-weight: 700;
  color: var(--ink);
  font-family: var(--font-display);
}

.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: 6px;
  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(--blue-on-dark);
  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 .book-big,
.cta-final .btn {
  border-color: var(--blue-on-dark);
  box-shadow: 4px 4px 0 var(--blue-on-dark);
}
.cta-final .tel-big:hover,
.cta-final .text-big:hover,
.cta-final .book-big:hover,
.cta-final .btn:hover {
  box-shadow: 6px 6px 0 var(--blue-on-dark);
}
.cta-final .tel-big:active,
.cta-final .text-big:active,
.cta-final .book-big:active,
.cta-final .btn:active {
  box-shadow: 0 0 0 var(--blue-on-dark);
}
.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: var(--yellow);
  color: var(--black);
}

/* ===== Footer ===== */
footer.site {
  background: #0a1220;
  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 h2 {
  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);
}
/* These sit in a row of separated links rather than inside a sentence, so the
   WCAG inline-link exemption doesn't apply. At 18px tall they were an awkward
   thumb target; the vertical padding lifts each one to 44px without moving
   anything visually, since the row is already gap-spaced. */
footer.site .legal a {
  display: inline-block;
  padding: 13px 0;
  margin: -13px 0;
}
/* Booking-form day shortcuts landed at 43px, one pixel under the comfortable
   thumb target. They already carry the pill styling from elsewhere in the
   sheet; this only guarantees the height. */
.date-quick button {
  min-height: 44px;
}

/* ===== Sticky mobile CTA (legacy bottom bar — superseded by scroll-morph topbar) ===== */
/* Floating call pill, every width (Ryan's ruling 2026-08-10: pill, never a
   full-width bar). Transparent container, no background box. */
.mobile-cta {
  position: fixed;
  bottom: 1.1rem;
  left: auto;
  right: 1.1rem;
  width: auto;
  background: transparent;
  padding: 0;
  display: none;
  gap: 0.5rem;
  z-index: 60;
  border-top: 0;
}
.mobile-cta a {
  flex: none;
  text-align: center;
  padding: 0.75rem 1.25rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
  border-radius: 999px;
  border: 2px solid var(--black);
  box-shadow: 0 3px 0 var(--black); /* vertical only: sideways offset reads as off-centre on a floating pill */
  min-height: 48px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.mobile-cta a.call {
  background: var(--red-deep);
  color: #fff;
}
/* Sticky pill is call-only (Ryan 2026-08-10): one floating element, one ask.
   Texting lives in the topbar and the in-page CTA rows. */
@media (min-width: 900px) {
  .mobile-cta {
    display: none;
  }
}

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

/* ===== 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;
}
/* Breadcrumb links measured 22px tall on a phone, just under the 24px WCAG
   2.5.8 minimum. Negative margin keeps the row's visual height unchanged. */
.crumb a {
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px dotted transparent;
  display: inline-block;
  padding: 11px 0;
  margin: -11px 0;
}
.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(1.5rem, 3vw, 2.5rem) 0 clamp(1.75rem, 4vw, 2.75rem);
  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, 1fr);
  gap: 0.85rem;
  margin: 2rem 0;
}
@media (min-width: 700px) {
  .spec-grid {
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  }
}
.spec {
  background: #fff;
  border: 1px solid var(--line);
  padding: 1.1rem 1.25rem;
  border-radius: 4px;
}
.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;
}
/* h3 had spacing and h2 had none, so a 42px heading sat 18px under the
   paragraph above it and 21px above its own — closer to the text it follows
   than to the text it introduces. That inversion is what reads as congested on
   any page with several headings in one block. Space above a heading should
   beat space below it by roughly 2:1 so the heading groups with its content.
   :not(:first-child) so the section's own padding isn't doubled at the top. */
.prose h2:not(:first-child) {
  margin-top: 3.25rem;
}
.prose h3 {
  margin-top: 2rem;
}
.prose ul {
  padding-left: 1.25rem;
  line-height: 1.7;
}
.prose ul li {
  margin-bottom: 0.35rem;
}
.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. Scoped on the
   rules above rather than overridden here: a `.prose a.btn { border-bottom: 0 }`
   override was stripping the button's OWN bottom border, leaving a three-sided
   box that read as a different component. */
.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: 4px;
  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;
}
/* Footprint line under each size card. WM puts real dimensions on the town
   page rather than hiding them a click deep; this is that, kept quiet. */
.related-sizes a small.dims {
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--line);
  font-size: 0.8rem;
  /* Naming only tabular-nums would reset the figure-style component and drop
     back to Zilla Slab's old-style default, so restate lining-nums here. */
  font-variant-numeric: lining-nums tabular-nums;
  letter-spacing: 0.01em;
}
.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: 5px;
  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: 999px;
}
.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: 6px;
  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 card + live widget (responsive) ===== */
.iframe-full {
  min-width: 100%;
  width: 100%;
}
/* ≤799px: stacked — summary as a slim banner above the widget */
.reviews-layout {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  align-items: stretch;
}
/* Reviews badge in Google's own surface language: white card, 1px #dadce0
   hairline, 8px radius, no shadow at rest. Deliberately NOT our house panel
   (2px black + hard offset) because the point is that it reads as Google's
   data, not our design. Type colors are Google's own (#202124 / #5f6368). */
.reviews-summary {
  width: auto;
  margin: 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.85rem;
  background: #fff;
  border: 1px solid #dadce0;
  border-radius: 8px;
  padding: 0.8rem 1.15rem;
  box-shadow: none;
  font-family: var(--font-body);
  text-align: left;
}
.rs-rating {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}
.reviews-summary-stars {
  margin: 0;
  font-size: 1.7rem;
  line-height: 1;
  color: var(--yellow);
  letter-spacing: 0.12em;
  text-shadow:
    -1px -1px 0 var(--black),
    1px -1px 0 var(--black),
    -1px 1px 0 var(--black),
    1px 1px 0 var(--black);
}
.reviews-summary-label {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.92rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--black);
  line-height: 1;
}
.rs-source {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding-left: 1.4rem;
  border-left: 2px solid var(--line);
}
.rs-source svg {
  flex-shrink: 0;
}
.rs-source-text {
  display: flex;
  flex-direction: column;
  line-height: 1.05;
}
.rs-source-text .rb-text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}
.rs-source-text .rb-text strong {
  margin-bottom: 0.1rem;
}
.rs-source-text strong {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.55rem;
  color: var(--black);
}
.rs-source-text span {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}
.review-widget-wrap {
  width: 100%;
}
@media (max-width: 460px) {
  .reviews-summary {
    gap: 1rem;
    padding: 0.85rem 1.1rem;
  }
  .reviews-summary-stars {
    font-size: 1.4rem;
  }
  .rs-source {
    padding-left: 1rem;
  }
  .rs-source-text strong {
    font-size: 1.3rem;
  }
}
@media (max-width: 410px) {
  .reviews-summary {
    gap: 0.7rem;
    padding: 0.7rem 0.85rem;
  }
  .reviews-summary-stars {
    font-size: 1.15rem;
    letter-spacing: 0.08em;
  }
  .reviews-summary-label {
    font-size: 0.72rem;
    letter-spacing: 0.12em;
  }
  .rs-source {
    padding-left: 0.7rem;
    gap: 0.5rem;
  }
  .rs-source svg {
    width: 24px;
    height: 24px;
  }
  .rs-source-text strong {
    font-size: 1.15rem;
  }
  .rs-source-text span {
    font-size: 0.7rem;
  }
}

/* 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: 4px;
}
.items-block.warn {
  border-left-color: #c77;
}
.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: 4px;
}
.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: 6px;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
}
.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: 6px;
  -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: 6px;
  /* House depth technique. The booking page address type-ahead already uses
     the hard offset; these two dropdowns should not differ. */
  box-shadow: 4px 4px 0 var(--black);
  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: 4px;
}
.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: 6px;
  border: 2px solid var(--ink);
  margin: 0;
  display: block;
}
.post-banner {
  background: var(--yellow);
  border: 3px solid var(--black);
  border-radius: 6px;
  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: 4px;
  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: 6px;
  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: 6px;
  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: 6px;
  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.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.26rem 0.7rem;
  border-radius: 999px;
  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);
}.amleg-pin {
  display: inline-flex;
  flex-shrink: 0;
}
.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: 4px;
  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.7rem;
  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 + terms (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);
}
.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: 4px;
  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 page: terms table + fee list (no figures published) ===== */
.price-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.5rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 4px;
  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: 4px;
  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.98rem;
}
.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: 4px;
  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.98rem;
}
.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: 8px;
  overflow: hidden;
  background: #fff;
}
.booking-embed iframe {
  width: 100%;
  min-height: 720px;
  height: 100%;
  border: 0;
  display: block;
}

/* ===== Booking modal (SurvCart / Docket) ===== */
.booking-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  opacity: 0;
  transition: opacity 200ms ease;
}
.booking-modal.is-open {
  display: block;
  opacity: 1;
}
.booking-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
  cursor: pointer;
}
.booking-modal-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(900px, calc(100vw - 2rem));
  height: min(780px, calc(100vh - 2rem));
  background: transparent;
  border: 2px solid var(--black);
  border-radius: 8px;
  box-shadow: 6px 6px 0 var(--yellow);
  overflow: hidden;
  padding: 0;
  margin: 0;
}
.booking-modal-close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--black);
  color: #fff;
  border: 2px solid var(--black);
  cursor: pointer;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-family: var(--font-display);
  transition:
    background 150ms,
    transform 150ms;
}
.booking-modal-close:hover {
  background: var(--yellow);
  color: var(--black);
  transform: scale(1.05);
}
.booking-modal-iframe {
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  display: block;
  background: transparent;
}
@media (max-width: 600px) {
  .booking-modal-content {
    width: calc(100vw - 4.5rem);
    height: calc(100vh - 11rem);
    border-radius: 8px;
    border: 2px solid var(--black);
    box-shadow: 4px 4px 0 var(--yellow);
  }
  .booking-modal-close {
    top: 10px;
    right: 10px;
  }
  .booking-modal-iframe {
    width: 100%;
    height: 100%;
    margin: 0;
  }
}

/* While the booking modal is open, hide the LeadConnector chat widget
   so its bottom-right bubble doesn't overlap the booking form's submit. */
html.booking-modal-open chat-widget,
html.booking-modal-open #chat-widget,
html.booking-modal-open [id^="lc_chat"],
html.booking-modal-open [class*="chat-widget"],
html.booking-modal-open iframe[src*="chat-widget"],
html.booking-modal-open iframe[src*="leadconnectorhq.com"] {
  display: none !important;
}

/* ===== Full-bleed hero (real-photo background) ===== */
.hero.hero-bg {
  position: relative;
  padding: clamp(2rem, 4vw, 3.25rem) 0 clamp(2.5rem, 5vw, 4rem);
  border-bottom: 0;
  overflow: hidden;
  isolation: isolate;
  /* No min-height. It was a floor for the background photo; without one the
     hero should be as tall as its content, and 70vh plus align-items:center
     was padding the top a second time on any tall viewport. */
  display: flex;
  align-items: center;
}
/* Photo removed at Ryan's call: the truck filled the frame behind the copy and
   read as clutter. Solid brand navy instead — white headline lands at 16.6:1,
   the white card pops harder against flat colour than it did against a busy
   photo, and the hero stops being the LCP image. */
.hero.hero-bg { background: var(--black); }
.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.32) 0%, rgba(0,0,0,0.5) 48%, rgba(0,0,0,0.78) 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.78) 0%, rgba(0,0,0,0.4) 40%, rgba(0,0,0,0.05) 68%),
      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.1rem, 5vw, 3.8rem); line-height: 1.05; margin-bottom: 1rem; }
.hero.hero-bg .hero-accent {
  color: var(--blue-on-dark);
  /* Block, not inline-block. As inline-block the tagline reflows up onto the
     last line of the headline at narrow widths, so mobile rendered
     "Dumpster Rental Raleigh NC No Time to Waste." as one run-on line.
     Desktop only looked right because the headline happened to fill the row. */
  display: block;
}
.hero.hero-bg .lead { color: rgba(255,255,255,0.85); max-width: 36em; margin-bottom: 2rem; font-size: clamp(1rem, 1.4vw, 1.15rem); }.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.7rem; 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: 999px; 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: 8px; padding: 1.5rem; border: 3px solid var(--black); box-shadow: 8px 8px 0 var(--yellow); position: relative; z-index: 1; }
/* Card header is a call prompt, not a label: an eyebrow over the number, the
   number itself the largest thing on the card and tappable. Column rather than
   row because the two lines stack. */
.hero-card-head { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 1.25rem; padding-bottom: 1rem; border-bottom: 2px solid var(--line); }
.hero-card-eyebrow {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.hero-card-phone {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.65rem, 3vw, 2.15rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--black);
  text-decoration: none;
  transition: color 140ms ease;
}
.hero-card-phone:hover,
.hero-card-phone:focus-visible { color: var(--red-deep); }
/* The WOW mark is a wide horizontal lockup (~2.9:1), so size it by height
   and let width follow; a square box would shrink it to a sliver. */
.hero-card-logo { width: auto; height: 34px; 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.75rem; 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: 6px; border: 2px solid var(--black); 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(--blue-on-dark);
}
.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;
}
.topbar-scroll-cta a {
  background: var(--red-deep);
  color: #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;
  background: var(--yellow);
  color: var(--black);
  padding: 0.85rem 1.5rem;
  border-radius: 6px;
  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;
}

/* ============================================================
   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: 8px;
  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. Verified before/after: card sizes, image boxes
     and page height byte-identical, so the clip was protecting nothing. */
}

/* Availability badge. "Available today" is a STOCK statement (this size is in
   the yard), not a delivery promise — so it is independent of turnaround, and
   it never carries delivery wording beside it. Skinned from this site's own
   tokens: navy chip, can-orange dot. Never an imported green. */
.avail-badge {
  position: absolute;
  top: -0.75rem;
  right: 0.6rem;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.32rem 0.72rem;
  border-radius: 999px;
  background: var(--navy);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.16);
}
.avail-badge::before {
  content: "";
  width: 0.44rem;
  height: 0.44rem;
  border-radius: 50%;
  background: var(--yellow);
}
@media (max-width: 640px) {
  .avail-badge { font-size: 0.68rem; right: 0.7rem; }
}
.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: 9px 9px 0 var(--yellow);
  border-color: var(--black);
}
.size-card.priced {
  padding-top: 1.75rem;
}
/* Featured "Most Popular" card (the 20-yard) — red frame + labeled banner */
/* The featured card's frame is IDENTICAL to its neighbours. It used to carry a
   red border, a heavier red shadow and a 10px lift, which all made sense when a
   red ribbon sat across its top — the frame connected to the ribbon. With the
   ribbon replaced by a typographic label, the red frame is orphaned: a row of
   cards where one has a different border colour and sits higher reads as a
   rendering fault, not as emphasis. One clear differentiator (the label) beats
   three half-signals fighting each other. */

/* --- 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: 6px;
  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: 6px;
  text-decoration: none;
  color: inherit;
  transition:
    transform 150ms,
    box-shadow 150ms;
  box-shadow: 3px 3px 0 var(--black);
}
.town-service-card:hover {
  transform: translate(-2px, -2px);
  box-shadow: 5px 5px 0 var(--yellow);
}
.town-service-card .ts-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.98rem;
  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: 8px;
  padding: 1.6rem 1.4rem 1.45rem;
  box-shadow: 5px 5px 0 var(--black);
  position: relative;
  transition:
    transform 150ms ease,
    box-shadow 150ms ease;
}
.step:hover {
  transform: translate(-2px, -2px);
  box-shadow: 7px 7px 0 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;
}

/* Review cards deliberately do NOT get the chunky border + hard shadow the
   rest of the card system uses. They are meant to read as a lifted Google
   widget, not as one of our own panels — see the .review block above. */

/* 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: 8px;
  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: 9px 9px 0 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(--no);
}

/* Goes-in / stays-out chart (pricing + acceptable-items). Two cards: an
   orange "yes" tier and a black-headed "no" tier. The grid rule below went
   missing in an earlier edit, which left the two cards stacked full-width at
   every size — the pair only makes sense read side by side. */
.allow-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  margin-top: 2.25rem;
}
@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: 8px;
  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: 6px;
  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(232, 89, 12, 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.7rem;
  border: 1.5px solid var(--black);
}
.allow-yes .allow-list li::before {
  content: "✓";
  background: var(--yellow);
  color: var(--black);
}
/* True red, not the brand orange. An orange ✕ sitting beside an orange ✓
   carries no signal — the whole point of the chart is the two tiers reading
   apart at a glance. --no on white text measures 5.62:1. */
.allow-no .allow-list li::before {
  content: "✕";
  background: var(--no);
  color: #fff;
}
.allow-note {
  margin: 1.5rem;
  padding: 0.95rem 1.1rem;
  background: var(--bg-warm);
  border-radius: 6px;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink);
  border-left: 3px solid var(--yellow);
}
.allow-no .allow-note {
  border-left-color: var(--no);
}

/* ===== 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: 8px;
  padding: 1.6rem 1.35rem;
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  box-shadow: 5px 5px 0 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.93rem;
  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: 3px;
}
/* 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,
.topbar-scroll-cta 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: 1179px) {
  .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: 6px;
  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: 8px;
  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 {
  position: relative;
  aspect-ratio: 16 / 9;
  border: 2px solid var(--black);
  border-radius: 10px;
  overflow: hidden;
  line-height: 0;
  background: var(--bg-warm);
}
/* Fill the box regardless of the width/height attributes the embed code
   ships with, so the map is responsive instead of a fixed 600x450. */
.map-embed iframe { position: absolute; inset: 0; display: block; width: 100%; height: 100%; border: 0; }
@media (max-width: 700px) { .map-embed { aspect-ratio: 4 / 3; } }

/* 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: 10px; 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: .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) --- */
/* Trust bar. Five stats, and five divides evenly into one column or five and
   nothing else, so any fixed grid in between leaves a hole on the last row.
   Flex with wrap and grow means the final row always fills, and the column
   count falls out of min-width rather than a ladder of breakpoints.

   Dividers are a 1px gap over a tinted container, which is the only way to get
   lines between wrapped rows as well as between columns. That technique was
   dropped once before because .wrap's side padding got painted with the tint
   and read as two empty end cells; the padding now lives on the section, which
   fixes the cause.

   min-width comes from the content: "10, 15 & 20 yd" needs roughly 198px at the
   top of its clamp plus 32px of cell padding, so the row wraps at 14.5rem
   instead of squeezing the number. */
.stat-band {
  background: rgba(255, 255, 255, 0.14);
  padding: 0 var(--pad);
}
.stat-band .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  padding-left: 0;
  padding-right: 0;
  margin-top: 0;
  margin-bottom: 0;
}
.stat-item {
  flex: 1 1 14.5rem;
  min-width: 14.5rem;
  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;
}
/* Navy, not the neutral #191919 it used to be: a grey hover against a navy
   band reads as a different colour family, which is what made the hovered
   cell look like a floating brown rectangle. */
.stat-item:hover { background: #16223a; }
.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);
}
/* One per row on small phones, where the value would otherwise sit on its
   clamp floor and still overflow. */
@media (max-width: 420px) {
  .stat-item { flex-basis: 100%; min-width: 0; padding: 1.2rem 0.75rem; }
}

/* --- Size cards: per-duration price table --- */
/* The flat rate, sitting between the size name and the term/tonnage rows. Solid
   brand red, never a gradient. --red-deep rather than --red because this lands
   on white and the brighter orange does not clear AA there. */
.size-card-price {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.6rem, 3vw, 2rem);
  line-height: 1;
  color: var(--red-deep);
  margin: 0.55rem 0 0;
}
/* "Starting at" sits above the figure in small caps, quiet enough that the
   number still reads as the headline. Logan asked for the qualifier because a
   mileage charge can apply outside the normal run. */
.size-card-price em {
  display: block;
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 700;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.15rem;
}
.size-card-price small {
  display: block;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--muted);
  margin-top: 0.3rem;
}
.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);
}

/* --- 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: 0.7rem 0.9rem; border-radius: 6px; 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);
  /* --line (1.29:1 on white) is a divider colour, not a control boundary. WCAG
     2.1 SC 1.4.11 wants 3:1 on the visual boundary of an interactive control;
     --muted clears it at 6.4:1 and still reads as the quiet sibling of the
     filled Book Now beside it. */
  border: 1px solid var(--muted);
}
.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: 8px;
  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; } }

/* ===== Proudfoot: sticky bottom call bar ON for mobile (owner request:
   "want to speak to a human, press the button"). (legacy comment removed)
   the scroll-morphing topbar; Proudfoot runs both. ===== */
@media (max-width: 899px) {
  .mobile-cta {
    display: flex;
  }
  /* Call-only on the mobile bar: Text lives in the scrolled topbar already,
     and one full-width Call button is the stronger single ask. Desktop keeps
     both pills (no Text affordance in the desktop topbar). */
  body {
    padding-bottom: 4.4rem; /* keep the bar off the footer/legal text */
  }
}

/* ===== Proudfoot: desktop floating call pill (call-first policy). The same
   .mobile-cta element every page already carries becomes a bottom-right pill
   cluster on desktop, so the number is one click away at any scroll depth.
   The sticky topbar shows the number too; this is the louder affordance. ===== */
@media (min-width: 900px) {
  footer.site {
    padding-bottom: 7rem; /* keep the floating call pill off the legal row */
  }
  .mobile-cta {
    display: flex;
    left: auto;
    right: 1.5rem;
    bottom: 1.5rem;
    width: auto;
    background: transparent;
    border-top: 0;
    padding: 0;
    gap: 0.6rem;
  }
  .mobile-cta a {
    flex: none;
    border-radius: 999px;
    border: 2px solid var(--black);
    box-shadow: 0 4px 0 var(--black);
    padding: 0.9rem 1.5rem;
    font-size: 1.05rem;
    transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
  }
  .mobile-cta a.call {
    background: var(--red-deep);
    color: #fff;
  }
  .mobile-cta a.call:hover {
    background: var(--red-deeper);
    transform: translateY(-2px);
    box-shadow: 0 6px 0 var(--black);
  }
}

/* hero-mobile-focus: the hero photo's subject (Logan on the truck step) sits
   right-of-center; on narrow screens the default 50% crop cuts her off. */
@media (max-width: 700px) {
  .hero.hero-bg .hero-bg-media img { object-position: 70% center; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Ported from the Proudfoot build (2026-07-31): footer social row, the
   service-area address checker, and the small text utilities the section
   headers lean on. Colors are remapped onto the WOW orange/navy tokens —
   nothing here carries a Proudfoot red.
   ═══════════════════════════════════════════════════════════════════════ */

/* Footer social row. Icons inherit currentColor so the whole row recolors
   from one rule. */
.foot-social {
  display: flex;
  align-items: center;
  /* Gap is reduced from 1rem because each link now carries its own 44px tap
     box; the padding supplies the visual spacing that the gap used to. */
  gap: 0.25rem;
  margin-left: -11px; /* pull the first icon back to the footer's left edge */
}
/* The icons render at 22px, which is under both the 44px Apple guideline and
   the 24px WCAG 2.5.8 minimum. The box is grown to 44x44 while the artwork
   stays 22px, so the target is thumb-sized without the footer looking heavier. */
.foot-social a {
  color: #fff;
  opacity: 0.75;
  min-width: 44px;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  display: inline-flex;
  transition: opacity 140ms ease, color 140ms ease;
}
.foot-social a:hover,
.foot-social a:focus-visible {
  opacity: 1;
  color: var(--blue-on-dark);
}
.foot-social svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
  display: block;
}

/* "Do you come to me?" checker above the service-area map. Injected by
   area-map.js, which owns the polygon the answer is tested against. */
.area-check {
  margin: 0 0 1.25rem;
  /* Anything on the page that jumps here needs to clear the sticky topbar,
     or the field label lands underneath it. */
  scroll-margin-top: 8.5rem;
}
.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: 8px;
  font: inherit;
  background: #fff;
}
.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;
}
/* Result text is bold body copy, not large text, so both states have to
   clear 4.5:1 on white: --ok-deep 6.08:1, --red-deep 5.20:1. Base --ok is
   too light here at 3.48:1 — that is the badge tier, not the text tier. */
.area-check-result.is-yes {
  color: var(--ok-deep);
}
.area-check-result.is-maybe,
.area-check-result.is-unknown {
  color: var(--red-deep);
}
.area-check-result.is-busy {
  color: var(--muted);
}
.area-check-result a {
  color: inherit;
}

/* Two-tone headings: constant part in ink, the town or keyword in brand
   orange. --yellow on white is 3.58:1 — over the 3:1 large-text bar, under
   AA for body copy. Scoped to h1/h2 scale only, never body text. */
.kw {
  color: var(--yellow);
}

/* Tinted eyebrow. The solid .eyebrow still exists for the pages that use it;
   this is the quieter variant for stacked section headers. --red-deep on
   --yellow-tint measures 4.63:1. */
.eyebrow-soft {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red-deep);
  background: var(--yellow-tint);
  border: 1px solid rgba(232, 89, 12, 0.22);
  padding: 6px 14px;
  border-radius: 2px;
  margin-bottom: 1.1rem;
}
.eyebrow-soft.on-dark {
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.22);
}

/* Sticky-bar clearance for the hero rating line. Placed last so it wins the
   cascade over the hero block further up the sheet. The bar is pinned to the
   viewport, so padding under the rating cannot move it; the only levers are
   tightening what sits above it and slimming the bar itself. */
@media (max-width: 899px) {
  .hero.hero-bg .lead {
    margin-bottom: 1.25rem;
  }
  .hero-ctas {
    margin-bottom: 0.75rem;
  }
}

/* Reviews page grid. The homepage uses .reviews (a horizontal snap strip);
   the dedicated page lays the same .review cards out as a grid. */
.reviews-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1.25rem;
  margin-top: 2.25rem;
  align-items: start;
}
/* Avatar colour cycling was scoped to the strip only; the grid needs it too
   or every card on the reviews page draws the same colour initial. */
.reviews-grid .review:nth-child(3n + 2) .rv-avatar { background: #45596e; }
.reviews-grid .review:nth-child(3n) .rv-avatar { background: var(--red-deep); }

/* Reviews-page display cap (Ryan, 2026-08-10, tightened from 6): 3 cards on
   mobile, 12 on desktop by default; scripts/build-support-pages.mjs assigns
   these classes to cards past that count and the extraScript on reviews.html
   removes them in matching batches when "Show More Reviews" is clicked.
   display:none only -- every card stays in the HTML source so it's still
   crawlable. */
@media (max-width: 640px) {
  .review.is-capped-mobile { display: none; }
}
.review.is-capped { display: none; }
.reviews-show-more {
  min-height: 48px;
  justify-content: center;
}
@media (max-width: 640px) {
  .reviews-show-more { width: 100%; }
}

/* Hero rating line. Sits over the photo hero, so it reads light; the
   max-width:899px rule further down lifts it clear of the sticky CTA bar. */
.town-hero-rating { color: rgba(255, 255, 255, 0.82); font-size: 0.95rem; margin: 0; }
.town-hero-rating a { color: #fff; }

/* Star row sits beside the average inside the badge grid, the way Google
   renders it. Stars are decorative; the rating is in the adjacent text. */
.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; }
.rs-source-text strong,
.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;
}
.rs-source-text span:not(.rs-stars):not(.rb-text),
.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; }
  .rs-source-text strong, .rb-text strong { font-size: 1.3rem; }
}

/* Verified badge under the review grid. Replaces a plain-text "these are
   real" claim: Google shows a factual summary and a link out, so this does
   the same rather than asserting our own veracity. Hover lifts with Google's
   elevation shadow instead of our house offset. */
.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: 8px;
  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,.3), 0 2px 6px 2px rgba(60,64,67,.15);
}
.vb-mark { flex-shrink: 0; display: grid; place-items: center; width: 40px; height: 40px; }
.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;
}
.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.875rem;
  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%; }
}

/* Hero rating chip in Google's surface language. Replaces a plain "star 4.9
   on Google" text line: the same fact, but it reads as Google's data rather
   than our assertion. Shadow (not our house offset) so it lifts off a photo
   hero; fetch-reviews keeps score and count current. */
.g-rating {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin: 0; padding: 0.42rem 0.72rem;
  background: #fff; border: 1px solid #dadce0; border-radius: 8px;
  font-family: var(--font-body); text-decoration: none; line-height: 1;
  box-shadow: 0 1px 3px rgba(0,0,0,.25);
  transition: box-shadow .15s ease;
}
.g-rating:hover, .g-rating:focus-visible {
  box-shadow: 0 1px 3px rgba(60,64,67,.3), 0 4px 8px 3px rgba(60,64,67,.15);
}
.g-rating-logo { flex-shrink: 0; }
.g-rating-score { font-weight: 500; font-size: 0.98rem; color: #202124; }
.g-rating-stars { color: #fbbc04; font-size: 0.8rem; letter-spacing: 0.06em; white-space: nowrap; }
.g-rating-count { font-size: 0.8rem; font-weight: 400; color: #5f6368; white-space: nowrap; }
@media (max-width: 420px) {
  .g-rating { gap: 0.38rem; padding: 0.38rem 0.6rem; }
  .g-rating-count { font-size: 0.74rem; }
}

/* Compact pill CTA. Smaller than .btn-big for spots where a full button
   would outweigh the paragraph it follows, but still a real tap target. */
.pill-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.55rem 1.1rem;
  border-radius: 999px;
  background: var(--red-deep);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1;
  text-decoration: none;
  border: 2px solid var(--black);
  transition: background 150ms ease, transform 150ms ease;
}
/* Touch devices only: the pills render ~39px next to 59-86px on every other
   CTA, under the 44px touch target. Desktop keeps the lighter chip. */
@media (pointer: coarse), (max-width: 699px) {
  .pill-cta { min-height: 44px; align-items: center; }
}

.pill-cta:hover, .pill-cta:focus-visible {
  background: var(--red-deeper);
  transform: translateY(-2px);
  color: #fff;
}
.pill-cta.is-quiet {
  background: #fff;
  color: var(--black);
}
.pill-cta.is-quiet:hover, .pill-cta.is-quiet:focus-visible {
  background: var(--yellow-tint);
  color: var(--black);
}

.trust-head { max-width: 46rem; margin-bottom: 2rem; }
.trust-head h2 { margin: 0 0 0.6rem; }
.trust-head p { margin: 0; font-size: 1.05rem; line-height: 1.6; color: var(--muted); }
.trust-foot { margin: 2rem 0 0; }

/* Trust signal row — four cards, one promise each.
   Every selector is scoped under .trust-row on purpose: an older, unrelated
   .trust-item component lives higher up this sheet (~line 700) and the bare
   class names collide. Do not unscope these. */
.trust-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 620px) { .trust-row { grid-template-columns: 1fr 1fr; gap: 1rem; } }
@media (min-width: 1000px) { .trust-row { grid-template-columns: repeat(4, 1fr); gap: 1.15rem; } }

.trust-row .trust-item {
  display: block;
  position: relative;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1.5rem 1.35rem 1.4rem;
  overflow: hidden;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
/* Accent cap, drawn rather than bordered so the radius stays clean. */
.trust-row .trust-item::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--red-deep);
  opacity: 0.9;
}
@media (hover: hover) {
  .trust-row .trust-item:hover {
    border-color: var(--red);
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(13, 44, 84, 0.09);
  }
}

.trust-row .trust-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 1rem;
  border-radius: 50%;
  background: var(--yellow-tint);
  color: var(--red-deep);
}
.trust-row .trust-ico svg { width: 22px; height: 22px; display: block; }

.trust-row .trust-text { display: block; }
.trust-row .trust-text strong {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.14rem;
  line-height: 1.15;
  letter-spacing: 0.005em;
  color: var(--black);
  margin-bottom: 0.45rem;
}
.trust-row .trust-text > span {
  display: block;
  font-size: 0.93rem;
  line-height: 1.55;
  color: var(--muted);
}

/* Single column: go horizontal so four stacked cards don't run the page long. */
@media (max-width: 619px) {
  .trust-row .trust-item { display: flex; gap: 0.95rem; align-items: flex-start; padding: 1.15rem 1.1rem; }
  .trust-row .trust-ico { width: 40px; height: 40px; margin-bottom: 0; flex-shrink: 0; }
  .trust-row .trust-text strong { font-size: 1.06rem; }
}

/* "What's in the price" chips. Replaces a sentence that listed delivery,
   pickup, dump fee and tax in prose: four short chips read at a glance where
   the sentence had to be parsed. Sits under a page-hero lead, so it inherits
   the light background rather than the dark hero treatment. */
.incl-chips {
  list-style: none;
  margin: 1.1rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.incl-chips li {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.9rem;
  border: 2px solid var(--black);
  border-radius: 999px;
  background: var(--yellow-tint);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1;
  color: var(--black);
}
.incl-chips li::before {
  content: "✓";
  font-weight: 700;
  color: var(--red-deep);
}
@media (max-width: 420px) {
  .incl-chips li { font-size: 0.9rem; padding: 0.45rem 0.75rem; }
}

/* ============================================================
   LIGHT HEADER + HERO — ported from Scribby's (via 417 Dumpsters)
   Appended last so it wins over the original dark-bar rules above
   without editing them, which keeps the dark treatment recoverable.

   WOW has no horizontal logo: logo-wow.png and logo-wow-footer.png are
   the same stacked lockup at 2060x872, and the bar renders it at 132x56
   either way. So this is a straight colour swap, navy artwork instead of
   white, with no layout change. The footer keeps the white mark.
   ============================================================ */
.topbar {
  background: rgba(255, 255, 255, 0.97);
  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); }
/* The hover underline was --yellow, which is the bright can orange and
   only passes on navy. On white it needs the deeper tier. */
nav.primary a::after { background: var(--red-deep); }
.hours-pill { color: var(--muted); border-color: var(--line); }
.hours-pill strong { color: var(--black); }

@media (max-width: 1179px) {
  .nav-toggle span { background: var(--black); }
  .topbar:has(.nav-toggle-cb:checked) nav.primary {
    background: #fff;
    border-top: 2px solid var(--line);
    box-shadow: 0 10px 24px rgba(13, 44, 84, 0.14);
  }
  .topbar:has(.nav-toggle-cb:checked) nav.primary a {
    border-bottom-color: var(--line);
  }
}

/* Logo left, nav centre, phone right — the Scribby's arrangement. */
@media (min-width: 1000px) {
  /* flex-basis auto, not 0: with basis 0 the logo and the actions column split
     the leftover space equally, so adding anything on the right (a Book Online
     button) shrank the brand box below the logo's intrinsic width. max-width
     then clamped the image while CSS held its height, and the default
     object-fit: fill stretched it. Basis auto was not enough — a flex item with
     shrink 1 still compresses past its content — so the logo is fixed at its
     own size and the actions column absorbs all the slack. The nav sits a few
     pixels off dead-centre as a result, which is invisible; a squashed logo is
     not. */
  .topbar-inner > .brand { order: 1; flex: 0 0 auto; justify-content: flex-start; }
  .topbar-inner > nav.primary { order: 2; flex: 0 0 auto; }
  .topbar-inner > div:not(.topbar-scroll-cta) { order: 3; flex: 1 1 auto; justify-content: flex-end; }
}

/* Bigger, tighter hero headline. Most of why Scribby's reads confident. */
.hero.hero-bg h1 {
  font-size: clamp(2.35rem, 5.9vw, 4.6rem);
  line-height: 0.97;
  letter-spacing: -0.015em;
}

/* Hero trust row: the live Google badge plus claims confirmed in the
   interview. Licensed and insured is verified (findings 24:13); family
   owned since 2024 is the Jan-2024 start. Nothing else goes in here. */
.hero-trust {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.6rem;
}
.hero-trust-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0 15px 0 11px;
  border-radius: 999px;
  background: rgba(13, 44, 84, 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.88rem;
  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.7rem;
  font-weight: 700;
  border: 1px solid var(--black);
  flex-shrink: 0;
}
/* One uniform height so the row reads as a set: the Google badge is
   naturally taller than the text pills. */
.hero-trust .g-rating,
.hero-trust .hero-trust-pill {
  height: 40px;
  min-height: 0;
  margin: 0;
  padding-top: 0;
  padding-bottom: 0;
  box-sizing: border-box;
}
@media (max-width: 420px) {
  .hero-trust { gap: 0.45rem; }
  .hero-trust-pill { font-size: 0.8rem; padding: 0 12px 0 9px; }
}

/* Attributed hero quote: a real customer's own superlative, sourced
   verbatim from scripts/reviews-data.json (Mike Dupree, live Google
   review). Source-attributed accolades outwork bare claims on-page
   (local-service-titles superlative mechanics), so this sits under the
   Google rating badge rather than replacing it. Plain text, no card, no
   quote-bubble chrome. */
/* 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;
}
@media (max-width: 1179px) { .nav-home { justify-content: flex-start; } }

/* Floating call pill yields while the hero card is on screen (see
   hero-cta-guard.js). Desktop only, because the pill is only a floating
   bottom-right cluster above 900px; below that it is the full-width bar and
   sits under the hero rather than over it. */
@media (min-width: 900px) {
  /* Default hidden, revealed by the guard once the hero card is out of view.
     It used to default VISIBLE and get hidden by JS, so on a slow connection
     the pill painted over the hero card's CTA until hero-cta-guard.js ran.
     Defaulting to the yielded state means the worst case is a pill that
     appears late, not one that covers a button. */
  .mobile-cta { transition: opacity 180ms ease, transform 180ms ease, visibility 180ms; }
  .mobile-cta:not(.is-past-hero) {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(10px);
  }
  .mobile-cta.is-behind-hero {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(10px);
  }
}
@media (prefers-reduced-motion: reduce) { .mobile-cta { transition: none; } }

/* ---- Hero trust row: design pass ----------------------------------------
   Measured at 1440: the three items needed 684px inside a 590px hero column,
   so the row broke 2 + 1, which reads as a mistake rather than a layout.
   Tightening the pills plus shortening the third label lands it at 584px on
   one line. The Google badge is deliberately NOT retextured to save width:
   fetch-reviews.mjs rewrites that span weekly and would undo it.

   The badge also carried an 8px radius against the pills' 999px, which is
   visible when they sit adjacent at a matched 40px height. Unified to a pill
   here only; the reviews page keeps the squarer Google-widget look. */
/* Gap matches 417. The pill font-size/padding that used to sit here is gone:
   it is now set in the 417-matched block below and two sources for the same
   property is how a sheet starts lying to you. The badge keeps the pill radius
   so the row reads as one set. */
.hero-trust { gap: 0.6rem; }
.hero-trust .g-rating { border-radius: 999px; }

/* Header actions are pills, matching the junkitrolloffs.com header Ryan
   pointed at. Scoped to the header on purpose: it is already the one
   shadowless zone on the site, so a pill here reads as a deliberate bar
   treatment rather than a second button language competing with the
   hard-shadow buttons in the body. */
.tel-cta { border-radius: 999px; }
/* Slim the bar toward the 73px reference: the logo is the only tall element,
   so the padding comes off around it rather than shrinking the mark further. */
.topbar-inner { padding-top: 0.45rem; padding-bottom: 0.45rem; }

/* ---- Hero headline legibility ------------------------------------------
   Measured against the actual photo: the orange accent line ("No Time to
   Waste.") crosses the orange dumpster, where it fell to 1.02:1 and a 10th
   percentile of 2.56, under the 3.0 AA floor for large text. Enlarging the
   headline made it more prominent, not less legible, but it was already
   failing before that change.

   The scrim's dark band now reaches further right, which lifts the 10th
   percentile to about 3.95 while still letting the truck and sky read on the
   right. The single brightest pixel behind the text still measures under 3.0;
   clearing that by scrim alone would mean flattening the photo, and clearing
   it by colour would mean giving up the orange accent. The text-shadow is
   what covers that remainder in practice. Flagged rather than hidden. */
@media (min-width: 900px) {
  .hero-bg-overlay {
    background:
      linear-gradient(90deg, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.58) 50%, rgba(0,0,0,0.10) 85%),
      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 h1 { text-shadow: 0 2px 14px rgba(0, 0, 0, 0.45); }

/* Hero accent: cream instead of the brand orange. Sampled over the actual
   photo with the current scrim, orange left about 4% of the line under the
   3.0 AA floor and bottomed out at 1.81:1 where it crossed the dumpster.
   Cream measures 5.11 at its worst and clears AA across 100% of the text. */
.hero.hero-bg .hero-accent { color: var(--hero-accent); }

/* ---- Trust pills: matched to 417 Dumpsters ------------------------------
   Ryan asked for these to match 417 exactly, so these are 417's values
   verbatim: near-black at 85% rather than WOW navy at 50%, weight back to 700,
   0.88rem, and the filled orange check circle restored.

   This deliberately reverses the earlier demote. Worth knowing for anyone
   reading later: 417's pills are LESS transparent than what WOW had (0.85 vs
   0.5). The glassiness never read here either way, because both hero scrim
   layers stack in this corner and the backdrop behind the pills spans a
   luminance range of only about 0.02, so there is nothing varied for the
   translucency to reveal. Consistency with the other site was the goal, not a
   change in transparency. */
.hero-trust-pill {
  gap: 0.45rem;
  padding: 8px 15px 8px 11px;
  background: rgba(17, 17, 17, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.22);
  font-weight: 700;
  font-size: 0.88rem;
  color: #fff;
}
.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.7rem;
  font-weight: 700;
  border: 1px solid var(--black);
  flex-shrink: 0;
  line-height: 1;
}

/* Town links under the service-area map. The section was the tallest on the
   homepage for the fewest words, and once the map dropped its 69 town dots it
   stopped naming a single town anywhere. A visitor scanning for their own town
   had nothing to read. These also give the town pages a link from the
   strongest page on the site rather than one hop behind the hub. */
.town-links {
  list-style: none;
  margin: 1.4rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.town-links a {
  display: inline-block;
  padding: 0.5rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.93rem;
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.town-links a:hover,
.town-links a:focus-visible {
  border-color: var(--red-deep);
  color: var(--red-deep);
  background: var(--yellow-tint);
}

/* ---- Hero rating badge: matched to 417 ---------------------------------
   417's rating is itself a dark glass pill, identical in treatment to its
   trust pills, so its whole hero row reads as one set. Matching only the two
   claim pills left WOW with a white Google-widget card sitting next to two
   dark glass pills, which is a worse mismatch than what we started with.

   So the hero badge takes the same glass treatment. HERO ONLY: reviews.html
   and every other placement keeps the white Google card, which is the right
   look in a light section and the one the review widget is meant to evoke.

   Side effect worth having: the white card is the widest item in the row and
   was the reason the row wrapped at every desktop width once the pills grew to
   417's size. The glass version is narrower. */
.hero-trust .g-rating {
  background: rgba(17, 17, 17, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: none;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  /* 12/10 rather than 14/11: the row overshot one line by 1.4px in a 590px
     column, and taking it from the badge keeps the row gap matched to 417. */
  padding: 0 12px 0 10px;
  gap: 0.45rem;
}
.hero-trust .g-rating .g-rating-score { color: #fff; font-weight: 700; font-family: var(--font-display); }
.hero-trust .g-rating .g-rating-count { color: rgba(255, 255, 255, 0.78); }
.hero-trust .g-rating:hover { border-color: rgba(255, 255, 255, 0.4); }

/* Closing line under the size grid. The section ended on four cards and a
   stretch of empty space, with the next move left to the visitor. Sizing is
   the exact question people call about, so this hands them the phone at the
   moment the question lands. */
/* Closes the size grid. Was a sentence with an inline tel: link; the SEO
   review's "make it a button" note applies here too, so the prompt stays as
   text and the phone number became a real CTA. */
.size-grid-cta {
  margin: 2.25rem 0 0;
  text-align: center;
}
.size-grid-cta p {
  margin: 0 0 1.1rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.12rem;
  color: var(--black);
}
.size-grid-cta a:not(.btn) {
  color: var(--red-deep);
  text-decoration: none;
  border-bottom: 2px solid var(--red-deep);
  padding-bottom: 1px;
  white-space: nowrap;
}
.size-grid-cta a:not(.btn):hover,
.size-grid-cta a:not(.btn):focus-visible { color: var(--red-deeper); border-bottom-color: var(--red-deeper); }

/* ============================================================
   PICKUP-LOAD SLIDER
   Ported from the Proudfoot Rolloffs build. Three deltas here:
   the truck is WOW orange rather than Proudfoot red, the tick
   spacing matches a 1-12 range instead of 1-14, and there is no
   price line in .ls-meta because this site does not publish
   rates. The .ls-swap row is new: WOW tops out at a 20-yard, so
   the biggest piles get told the truth about a swap.
   ============================================================ */
/* Pickup-load slider. The thumb is a truck and the track is a road, so the two
   have to behave like one object: the tyres sit ON the line rather than the
   line cutting through the cab, and the road behind the truck fills in as you
   drag, which is the only cue that the control is a measure and not a switch.

   --ls-pct is a plain number (0-100) set by load-slider.js. The fill can't be
   a bare percentage: a thumb's centre travels from half-a-thumb to
   width-minus-half-a-thumb, so a raw percentage drifts off the truck at both
   ends. The calc below maps it onto that shorter path.

   -webkit- and -moz- track/thumb rules are written out separately; a combined
   selector list is dropped wholesale by both engines. */
.load-slider {
  --ls-pct: 38.46;
  --ls-thumb: 60px;
  margin: 1.75rem 0 2.25rem;
  padding: 1.6rem 1.6rem 1.4rem;
  background: #fff;
  border: 2px solid var(--black);
  border-radius: 8px;
}
.ls-label {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  color: var(--black);
  margin-bottom: 1.75rem;
}
.ls-rail {
  position: relative;
  padding-top: 2.5rem;
}
/* Rides the truck. Same travel mapping as the fill, so it stays centred over
   the thumb at both ends instead of drifting. aria-hidden because the slider's
   own value text already announces the count; an <output> here would make
   every arrow-key step speak twice. */
.ls-bubble {
  position: absolute;
  top: 0;
  left: calc(var(--ls-pct) / 100 * (100% - var(--ls-thumb)) + var(--ls-thumb) / 2);
  transform: translateX(-50%);
  padding: 0.3rem 0.7rem;
  background: var(--black);
  border-radius: 4px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.15;
  white-space: nowrap;
  color: #fff;
}
.ls-bubble::after {
  content: "";
  position: absolute;
  top: 100%;
  /* Follows the truck when the bubble itself is pinned at a rail end. */
  left: calc(50% + var(--ls-caret, 0px));
  margin-left: -5px;
  border: 5px solid transparent;
  border-top-color: var(--black);
}
.load-slider input[type="range"]:active ~ .ls-bubble,
.ls-rail:has(input:active) .ls-bubble {
  background: var(--red-deep);
}
.ls-rail:has(input:active) .ls-bubble::after {
  border-top-color: var(--red-deep);
}
.load-slider input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 65px;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: grab;
  -webkit-tap-highlight-color: transparent;
}
.load-slider input[type="range"]:active {
  cursor: grabbing;
}
.load-slider input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background:
    repeating-linear-gradient(to right, rgba(255, 255, 255, 0.9) 0 9px, transparent 9px 20px)
      center / 100% 2px no-repeat,
    linear-gradient(
      to right,
      var(--red-deep) 0
        calc(var(--ls-pct) / 100 * (100% - var(--ls-thumb)) + var(--ls-thumb) / 2),
      #14140f 0
    );
}
.load-slider input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background:
    repeating-linear-gradient(to right, rgba(255, 255, 255, 0.9) 0 9px, transparent 9px 20px)
      center / 100% 2px no-repeat,
    linear-gradient(
      to right,
      var(--red-deep) 0
        calc(var(--ls-pct) / 100 * (100% - var(--ls-thumb)) + var(--ls-thumb) / 2),
      #14140f 0
    );
}
.load-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 60px;
  height: 32px;
  margin-top: -26.53px;
  border: 0;
  background-color: transparent;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2034%22%3E%3Cpath%20d%3D%22M5%2024V17.2q0-1.2%201.2-1.2h6.6L16.8%208q.6-1.1%201.9-1.1h10.6q1.3%200%201.9%201.1l3%208h3.3v-2h20q1.6%200%201.6%201.7V24z%22%20fill%3D%22%23c43e00%22%20stroke%3D%22%230b0b0b%22%20stroke-width%3D%221.7%22%20stroke-linejoin%3D%22round%22%2F%3E%3Cpath%20d%3D%22M18.6%2015.2l2.7-5.1h7.2l1.9%205.1z%22%20fill%3D%22%23e8eef3%22%2F%3E%3Ccircle%20cx%3D%2215.6%22%20cy%3D%2224%22%20r%3D%225.3%22%20fill%3D%22%230b0b0b%22%2F%3E%3Ccircle%20cx%3D%2215.6%22%20cy%3D%2224%22%20r%3D%221.9%22%20fill%3D%22%23e8eef3%22%2F%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2224%22%20r%3D%225.3%22%20fill%3D%22%230b0b0b%22%2F%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2224%22%20r%3D%221.9%22%20fill%3D%22%23e8eef3%22%2F%3E%3C%2Fsvg%3E");
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  box-shadow: none;
  border-radius: 0;
}
.load-slider input[type="range"]::-moz-range-thumb {
  width: 60px;
  height: 32px;
  border: 0;
  transform: translateY(-13.53px);
  background-color: transparent;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2034%22%3E%3Cpath%20d%3D%22M5%2024V17.2q0-1.2%201.2-1.2h6.6L16.8%208q.6-1.1%201.9-1.1h10.6q1.3%200%201.9%201.1l3%208h3.3v-2h20q1.6%200%201.6%201.7V24z%22%20fill%3D%22%23c43e00%22%20stroke%3D%22%230b0b0b%22%20stroke-width%3D%221.7%22%20stroke-linejoin%3D%22round%22%2F%3E%3Cpath%20d%3D%22M18.6%2015.2l2.7-5.1h7.2l1.9%205.1z%22%20fill%3D%22%23e8eef3%22%2F%3E%3Ccircle%20cx%3D%2215.6%22%20cy%3D%2224%22%20r%3D%225.3%22%20fill%3D%22%230b0b0b%22%2F%3E%3Ccircle%20cx%3D%2215.6%22%20cy%3D%2224%22%20r%3D%221.9%22%20fill%3D%22%23e8eef3%22%2F%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2224%22%20r%3D%225.3%22%20fill%3D%22%230b0b0b%22%2F%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2224%22%20r%3D%221.9%22%20fill%3D%22%23e8eef3%22%2F%3E%3C%2Fsvg%3E");
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  box-shadow: none;
  border-radius: 0;
}
.load-slider input[type="range"]:focus-visible {
  outline: 3px solid var(--red-deep);
  outline-offset: 8px;
  border-radius: 6px;
}
/* One notch per load, so the stops are readable without a number on each. */
.ls-ticks {
  height: 6px;
  margin: 0.45rem calc(var(--ls-half, 30px)) 0;
  background-image: linear-gradient(to right, var(--line) 0 1px, transparent 1px);
  background-size: calc(100% / 11) 100%;
  background-repeat: repeat-x;
}
.ls-scale {
  display: flex;
  justify-content: space-between;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #6b6b6b;
}
.ls-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 1.5rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
  text-align: center;
}
.ls-count {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #6b6b6b;
}
.ls-size {
  margin-top: 0.35rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 2.1rem;
  line-height: 1.05;
  letter-spacing: -0.005em;
  color: var(--black);
}
.ls-meta {
  margin-top: 0.45rem;
  font-size: 0.88rem;
  color: #5a5a5a;
}
.load-slider .ls-link {
  margin-top: 1.1rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.01em;
  color: #fff;
  text-decoration: none;
  background: var(--red-deep);
  border: 2px solid var(--red-deep);
  border-radius: 4px;
  padding: 0.6rem 1.3rem;
  transition: background 140ms ease, border-color 140ms ease;
}
.load-slider .ls-link:hover,
.load-slider .ls-link:focus-visible {
  background: var(--black);
  border-color: var(--black);
}
.load-slider .ls-note {
  margin: 1.2rem 0 0;
  font-size: 0.8rem;
  line-height: 1.55;
  color: #6b6b6b;
}
/* Shown only past what one 20-yard haul holds. */
.load-slider .ls-swap {
  margin: 0.9rem 0 0;
  padding: 0.7rem 0.9rem;
  background: #fdf3ec;
  border-left: 3px solid var(--red-deep);
  border-radius: 0 4px 4px 0;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--black);
}
.load-slider .ls-swap[hidden] { display: none; }

/* ===== Size comparison table =====
   Repeated verbatim across all 69 town pages, deliberately. A table repeating
   across pages does not read as duplicate content the way a repeated paragraph
   does, and AI retrieval pulls from tables ahead of prose. Reuses .price-table
   for its look; this block only adds the mobile scroll shell and the row links. */
.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-top: 1.5rem;
}
.table-scroll .price-table {
  margin-top: 0;
  min-width: 34rem;
}
.price-table td a {
  color: var(--red-deep);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
}
.price-table td a:hover {
  text-decoration: underline;
}
.price-table .best-for {
  color: var(--muted);
}
/* Visually hidden but read by screen readers and by crawlers. Used for the
   table <caption>, which names the town the table applies to. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ===== Header booking action =====
   Sits beside the phone CTA, deliberately outlined rather than filled: Logan
   takes most orders by phone, so the yellow tel-cta stays the primary action
   and this is the second option for people who would rather not call. Hidden
   below 1000px, where the topbar already carries Call/Text and the sticky
   mobile bar carries the rest. */
.book-cta {
  display: inline-flex;
  align-items: center;
  padding: 0.6rem 1.1rem;
  /* Pill + hairline, matching the header treatment on junkitrolloffs.com.
     Set here rather than in a later override: this base rule is ~450 lines
     below the header block and was winning the cascade. */
  border: 1px solid var(--navy);
  border-radius: 999px;
  color: var(--navy);
  background: transparent;
  text-decoration: none;
  font-weight: 700;
  font-family: var(--font-display);
  font-size: 0.95rem;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s;
}
.book-cta:hover {
  background: var(--navy);
  color: #fff;
}
/* Book Online only once the row has room for it on top of everything else:
   the full header with the button measures ~1280. Below that the phone CTA
   carries the header alone and the sticky mobile bar handles the rest. */
@media (max-width: 1279px) {
  .book-cta { display: none; }
}

/* ===== Mid-page CTA band =====
   Service pages run twelve sections with conversion points only at the hero,
   the summary and the footer CTA, so the whole middle of the page had nothing
   to act on. This is a light band that drops in after the sizes section — the
   natural decision point, once a reader knows which dumpster they want. Sits
   on the brand yellow so it reads as an interruption rather than another
   content block, and stays compact so it doesn't compete with the final CTA. */
.cta-band {
  background: var(--yellow);
  padding: 2.25rem 0;
}
.cta-band .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
}
.cta-band p {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  color: var(--black);
  max-width: 34rem;
}
.cta-band .cta-band-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}
@media (max-width: 640px) {
  .cta-band .wrap { flex-direction: column; align-items: flex-start; }
}

/* ============================================================
   CANONICAL MOBILE CTA STACK (house pattern, local-service-design skill,
   codified 2026-08-09). Every CTA-row pattern site-wide gets the same
   <=640px behavior: full-width stacked column, 48px min tap target. This
   caught real side-by-side buttons at 375px in .cta-buttons (the final-CTA
   "Book Now" / "Text Us" pair) and .cta-band-actions ("Book Now" / phone).
   .cta-row and .hero-ctas already use gap and wrap onto their own lines at
   narrow widths, but get the same explicit rule so no page can drift and
   so a future two-button hero row doesn't silently reopen the bug.
   Fix lives here once, sitewide. Never override per-page. */
@media (max-width: 640px) {
  .cta-row,
  .hero-ctas,
  .cta-buttons,
  .cta-band .cta-band-actions {
    flex-direction: column;
    align-items: stretch;
  }
  .cta-row > .btn,
  .hero-ctas > .btn,
  .cta-buttons > a,
  .cta-band .cta-band-actions > .btn {
    width: 100%;
    min-height: 48px;
  }
}

/* ===== Town pills, not clickable =====
   Towns we serve that don't carry their own page. Naming them keeps the
   geographic relevance; linking them would point at a redirect and re-add the
   sitewide links the fold removed. So these are deliberately NOT anchors, and
   the styling has to say so: no hover, no pointer, muted text and a flatter
   fill than .town-links, which is the clickable pill row. A pill that looks
   tappable and isn't is worse than plain prose. */
.town-pills {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.town-pills li {
  display: inline-block;
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--muted);
  cursor: default;
}

/* ============================================================
   LIGHT HERO
   Flips the homepage hero to a white ground, the junkitrolloffs.com
   arrangement: pale section, dark card. Written as one block at the end
   rather than edited into the ten scattered .hero-bg rules above, so the
   dark treatment stays intact and reverting is deleting this block.

   Every element that assumed a dark ground has to be answered here or it
   disappears: the outlined CTA was white-on-transparent, the trust pills
   were translucent navy with white text, and the card was white.
   ============================================================ */
.hero.hero-bg { background: #fff; }
.hero.hero-bg .hero-content { color: var(--ink); }
.hero.hero-bg h1 { color: var(--black); text-shadow: none; }
/* Cream reads as a smudge on white; the deepened orange is the AA-passing
   accent and ties the headline to the CTA below it. */
.hero.hero-bg .hero-accent { color: var(--red-deep); }
.hero.hero-bg .lead { color: var(--muted); }

/* The outlined hero CTA was white border on transparent — invisible here. */
.hero.hero-bg .btn.btn-on-dark,
.hero.hero-bg .btn-secondary.btn-on-dark {
  color: var(--black);
  border-color: var(--black);
  box-shadow: 4px 4px 0 var(--black);
}
.hero.hero-bg .btn.btn-on-dark:hover,
.hero.hero-bg .btn-secondary.btn-on-dark:hover { background: var(--black); color: #fff; }

/* Trust pills invert: was translucent navy + white text. */
.hero.hero-bg .hero-trust-pill {
  background: #fff;
  border: 1px solid var(--line);
  color: var(--black);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* Card goes dark so it still separates from the section behind it. */
.hero.hero-bg .hero-card {
  background: var(--black);
  border-color: var(--black);
  box-shadow: 8px 8px 0 var(--red-deep);
}
.hero.hero-bg .hero-card-eyebrow { color: rgba(255, 255, 255, 0.62); }
.hero.hero-bg .hero-card-phone { color: #fff; }
.hero.hero-bg .hero-card-phone:hover,
.hero.hero-bg .hero-card-phone:focus-visible { color: var(--blue-on-dark); }
.hero.hero-bg .hero-card-head { border-bottom-color: rgba(255, 255, 255, 0.18); }
.hero.hero-bg .hero-card-list li { color: rgba(255, 255, 255, 0.92); }

/* The Google badge had its own dark-hero treatment (bg + white score/count) a
   few hundred lines above. On the light hero it must go back to the standard
   white Google badge, or it sits as the one dark chip in a row of white pills
   — and its dark label text lands on a dark ground. */
.hero.hero-bg .hero-trust .g-rating {
  background: #fff;
  border: 1px solid var(--line);
}
.hero.hero-bg .hero-trust .g-rating .g-rating-score {
  color: #202124;
  font-weight: 500;
  font-family: var(--font-body);
}
.hero.hero-bg .hero-trust .g-rating .g-rating-count { color: #5f6368; }

/* ---- Hero trust row -----------------------------------------------------
   Replaces the pill chrome. Pills read as three competing chips; a plain row
   under the CTAs reads as one continuous line of reassurance and lets the
   Google badge stay the only bordered object, which is the point — it is the
   one item here carrying third-party proof. */
.hero-trust .trust-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--muted);
  white-space: nowrap;
}
.hero-trust .trust-item .trust-check {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--red-deep);
  color: #fff;
  font-size: 0.6rem;
  line-height: 1;
}
@media (max-width: 700px) {
  .hero-trust .trust-item { font-size: 0.82rem; }
}




/* RANK vs STATUS — two different kinds of information, so two different visual
   registers rather than two competing pills.

   "Available Today" is a STATUS: it appears on every card, so it stays the
   filled pill on the border — consistent position, scannable down the row.
   "Most Popular" is a RANK: it appears on exactly ONE card, and a second filled
   pill of the same shape and weight just read as a mismatched twin of the first
   at every position tried (six of them). So rank becomes a typographic label
   inside the card, above the size name, where product labels live on real
   product cards.

   The slot is reserved on EVERY card, so the featured card's photo, title and
   buttons stay aligned with its neighbours — an in-flow label on one card only
   dropped its contents 42px below the rest of the row. */
.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;
}
