:root {
  /* J'S DUMPSTER RENTALS design spec (locked 2026-08-18). Sampled from Jeff's
     own logo (the round badge off his Facebook profile): lime ring #c0d000,
     navy core #204088, black type. This block IS the design spec; everything
     below obeys it.

     Two-shade system, all pairs AA-verified at palette time:
       lime #c0d000    the action accent. ONLY ever a background carrying ink
                       text (10.37:1) or an accent on navy (5.7:1). NEVER text
                       on a light background (1.78:1, hard fail).
       lime-deep       hover tier for lime fills, ink text (7.73:1).
       navy #204088    brand structure: headings accent, links, the Book CTA
                       fill with white text (9.5:1), footer, dark bands.
       navy-deep       hover tier for navy fills (12.58:1 with white).
     Button split per the design skill: CALL = lime fill + ink text (hi-vis,
     the thing you tap), BOOK = navy fill + white text. --more outlined.
     Legacy token names kept so the whole donor sheet reskins from here:
     "yellow" now holds lime, "red-deep" now holds navy. Rename nothing
     mid-sheet; the names are wrong but consistent, and the values are right. */
  --yellow: #c0d000;
  --yellow-deep: #a6b400;
  --yellow-tint: #f4f8d6;
  --red: #c0d000;
  --red-deep: #204088;
  --red-deeper: #16306b;
  --no: #c62828;
  --ok: #1e9e4a;
  --ok-deep: #14713a;
  --blue-on-dark: #c0d000;   /* legacy name: the on-dark accent, now lime (5.7:1 on navy) */
  /* Hero accent on dark bands. No hero photo on this build (photo-free site),
     so this can be the lime itself. */
  --hero-accent: #c0d000;
  --navy: #204088;
  --black: #10142a;
  --ink: #12172b;
  --muted: #565f80;
  --line: #dde1ec;
  --logo-gray: #d0d0d0;
  --bg: #ffffff;
  --bg-warm: #fafbf7;

  --font-display: "Barlow Condensed", "Arial Narrow", sans-serif;
  --font-body: "Source Sans 3", 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;
}/* Kept from the donor (Zilla Slab shipped old-style figures). Barlow Condensed
   uses lining figures anyway, so this is belt-and-braces, not load-bearing. 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
   "(765) 238-1393" 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: 56px;
  width: auto;
  margin: 0.3rem 0;
  /* 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(--yellow-deep);
}
.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: 54px;
  }
  .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;
}
@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 {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: #0e1626;
  }
  /* The --morph custom property and the transform/opacity rule that read it
     went with the scroll-morphing topbar. This site drove the morph from a
     scroll-position variable rather than a class, so the selectors never named
     topbar-scroll and a selector-based sweep leaves them behind: --morph would
     have sat at its 0 default forever, computing to translateY(0)/opacity 1 on
     every frame -- harmless to look at, and exactly the kind of dead machinery
     that reads as load-bearing later. */
}/* ===== 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;
  /* Vertical centring was set and horizontal never was. It looked fine while every
     button shrank to its own content, then the mobile rule below stretched CTAs to
     width:100% and every label slid to the left edge -- on the hero pair, the final
     CTA band, and the size-picker results. Centre it once at the base. */
  justify-content: center;
  gap: 0.5rem;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  padding: 0.85rem 1.5rem;
  border-radius: 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(--yellow-deep);
  /* 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-book {
  /* The booking CTA. Solid per the button invariants: an outlined button never
     carries a conversion action. Navy + white 9.5:1, hover 12.58:1. */
  background: var(--red-deep);
  color: #fff;
}
.btn-book:hover {
  background: var(--red-deeper);
  color: #fff;
}
.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 under the donor's display face, which was 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 Jeff 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: 480px;
}

.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. */
.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(--yellow-deep);
}
.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;
  }
}
/* Five children since the footer was unified: NAP + Dumpsters, Services,
   Company, Service Area. It was four columns when Services lived inside the
   Dumpsters list; splitting them is what let every page carry the same 36
   links without one column running twice the length of the rest. */
@media (min-width: 960px) {
  footer.site .foot-grid {
    grid-template-columns: 1.3fr repeat(4, 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: flex;
  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 {
  /* tel: links wear the lime call fill sitewide; the pill is the most-tapped
     tel link of all. Ink text at 10.37:1. */
  background: var(--yellow);
  color: var(--ink);
}
/* 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) {
  }

/* 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):not(.ls-link) {
  color: var(--black);
  border-bottom: 2px solid var(--yellow);
  text-decoration: none;
}
.prose a:not(.btn):not(.ls-link):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 the display face's 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,
.town-marker-icon:focus-visible .dot {
  /* was scale(1.25) hover-grow, the generated-UI tell; a color shift reads
     just as well on a 10px map dot without the inflate */
  background: var(--yellow);
}
.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:not(.box-diagram) {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  height: auto;
  margin-bottom: 0.5rem;
}
/* The scale drawings are never cropped: both render at full card width, and
   because the two SVGs share one canvas and one px-per-foot, equal width IS
   the shared scale. The 12's drawing sits visibly lower than the 16's, which
   is the entire sales argument, drawn. */
.size-card .box-diagram {
  width: 100%;
  height: auto;
  aspect-ratio: auto;
  object-fit: contain;
  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);
  /* scale-up removed per the design skill; press-down lives on :active */
  color: var(--black);
}
.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 in Richmond, IN" plus the sub-line as one run-on.
     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 brand 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.
   ============================================================ */
/* Late .btn-primary re-declaration deleted on the J's build: it overrode the
   base lime call button back to a navy fill. One declaration per class; the
   base block at the top of the sheet is the truth. */
/* Topbar phone pill + scroll-morph Call/Text CTAs */
/* Late .tel-cta override trio deleted on the nav redesign: it forced the
   header phone navy+white while every other tel: wears the lime call fill.
   One declaration per class; the base rule near the top is the truth. *//* 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.75rem;
  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.75rem; 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 card (the 16-yard) — accent 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,
.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 {
  /* Grid, not wrapping flex: four stats must always read as one 4-across band
     (2x2 on phones). The old 14.5rem flex min meant mid-size windows fit three
     and dropped the fourth to its own full-width row. */
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  padding-left: 0;
  padding-right: 0;
  margin-top: 0;
  margin-bottom: 0;
}
.stat-item {
  min-width: 0;
  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);
}
/* Two per row on phones. The 14.5rem (232px) min-width above meant only one
   cell fit a 333px container, so five stat cells became five full-width blocks
   running 424px -- 52% of a 375x812 screen. A vertical stack of identical
   centred blocks is read one item at a time, which is the opposite of what an
   at-a-glance band is for. Two columns takes it to about 180px.
   The value sits on its clamp floor at this width, which is what the old
   one-per-row rule was protecting against; the smaller padding buys that room
   back instead. */
@media (max-width: 700px) {
  .stat-band .wrap { grid-template-columns: repeat(2, 1fr); }
  .stat-item {
    padding: 1.15rem 0.6rem;
  }
  /* Odd cell count: the last one spans instead of sitting half-width against a
     gap, which reads as a wrapping bug rather than a layout. */
  .stat-item:last-child:nth-child(odd) { grid-column: 1 / -1; }
}/* --- 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. Jeff 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;
  }
  /* duplicate .call fill removed on the J's build; the base rule above is
     the single declaration (lime + ink) */
  .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 (Jeff 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 brand 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.

   There is no horizontal footer logo: logo-js-footer-560.png and the header mark 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; }
}/* 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. the trust line is verified (findings 24:13); family
   owned since founding 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 came from the donor build, which topped out smaller, 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 16-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: Jeff
   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;
}

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


/* ---- Mobile card + hero footprint (Ryan, 2026-08-11) ---------------------
   Measured at 375x812: the homepage ran 21.6 screens. The single largest
   cause was a broken CSS comment above .reviews (fixed separately) that had
   swallowed the strip rule and left eight review cards stacked at 2,191px.
   What follows is the rest of the trim.

   NOTE: .sizes deliberately stays a stacked column on mobile, per the reasoning
   already written above its rule -- a swipe row hides products someone has to
   choose between. These cards get shorter, they do not become a carousel. */
@media (max-width: 699px) {
  /* 3:2 is the shape of the source photo, so nothing was being cropped and
     every card carried its full slab of pavement. The can sits at 25-81% of
     frame with its centre at ~51%, so a centred 2:1 crop removes only ground
     and sky and keeps the whole dumpster. ~47px back per card. */
  .size-card.priced img { aspect-ratio: 2 / 1; }

  /* The hero card repeated the phone (same tel:) and the pricing link (same
     href) that .hero-content already shows directly above it. Its checklist is
     real content and stays; the duplicated pair does not. */
  .hero-card-head,
  .hero-card-cta { display: none; }
  .hero-card-list { margin-bottom: 0; }
  .hero-card { padding: 1.1rem 1.2rem; }
}


/* ---- Size-card footprint on mobile (Ryan, 2026-08-11) --------------------
   Measured 497px at 375x812 -- 0.61 of a screen per card against a 0.5 budget,
   with the sizes section at 3.35 screens. The card is deliberately dense (it
   carries a price, a duration, a weight allowance and dimensions, and those
   are the reason the page converts), so this trims spacing only. No content
   is cut to hit a number.

   The duplicate "Details" button came out separately: the card itself is
   already a link to the same slug, so the pair offered one destination twice.
   Book Now now takes the full width, which is a bigger primary tap target. */
@media (max-width: 699px) {
  .size-card { padding: 1.05rem 1rem 1.1rem; }
  .size-card .yd { line-height: 1.15; }
  .size-card-price { margin-top: .35rem; }
  .size-card-dims { margin-bottom: .45rem; }
  .size-card-actions { padding-top: .75rem; }
  .size-card-actions .size-act:only-child { width: 100%; }
  /* A two-button row at 375px gives each button ~140px, which is not enough for a
     descriptive label: "How pricing works" wrapped to two lines and dragged both
     buttons to 76px tall, leaving "Call" floating alone in a deep box. Stacking
     keeps the label (naming the destination is the point of it) and gives both
     buttons a full-width target instead of half of one. */
  .size-card-actions { flex-direction: column; align-items: stretch; }
  .size-card-actions .size-act { width: 100%; }
}

/* ── J's mobile budget fixes (measured 2026-08-18 at 375x812) ──────────────
   Hero measured 100% of the viewport: the hero-card's phone + pricing link
   duplicate the CTA row 20px above it, so the card hides on small screens
   (cut duplication before cutting real content — design skill order).
   Size cards measured 0.72 of a screen; the scale diagram caps its height on
   phones so two cards fit ~1.4 screens and comparison is possible. */
@media (max-width: 700px) {
  .hero-card { display: none; }
  .hero { padding-bottom: 2rem; }
  .size-card .box-diagram { max-height: 110px; width: auto; margin: 0 auto; }
  .size-card-link { padding-bottom: 0.5rem; }
  /* price-rows measured 113px and the "Starting at" block 64px on a 563px
     card; the rows carry the same three numbers the block leads with, so on
     phones the rows compress to a single inline line each and the gaps close.
     Facts stay (never fix a tall card by deleting content), spacing goes. */
  /* The three duration rows collapse to one inline line on phones. The same
     numbers live in the Starting-at block and the pricing table one section
     down, so the vertical menu is the duplication, not the information. */
  .size-card .price-rows { margin: 0.35rem 0; display: flex; flex-wrap: wrap; gap: 0.2rem 0.9rem; }
  .size-card .price-rows li { padding: 0; display: inline-flex; gap: 0.35rem; border: 0; }
  .size-card .price-rows li .dur::after { content: ""; }
  .size-card .yd { font-size: 1.25rem; }
  .size-card .size-card-price { padding: 0.3rem 0; }
}

/* ── Inline-style eviction (checklist A4, 2026-08-18): components authored
   this build carried layout inline, which is un-overridable at breakpoints.
   One home each, here. ── */
.size-switch { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin-top: 1rem; }
.size-switch .ss-label { font-family: var(--font-display); font-weight: 600; }
.size-switch .ss-cur { padding: 0.3rem 0.8rem; border: 2px solid var(--black); border-radius: 6px; background: var(--yellow-tint); font-weight: 700; }
.size-switch a { padding: 0.3rem 0.8rem; border: 2px solid var(--line); border-radius: 6px; text-decoration: none; color: var(--ink); font-weight: 600; }
.size-switch a:hover { border-color: var(--black); }
.pros-cons { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1.25rem; margin-top: 1.5rem; }
.field-input { width: 100%; padding: 0.8rem; border: 2px solid var(--line); border-radius: 8px; font: inherit; }
.field-label { font-family: var(--font-display); font-weight: 600; }
.pc-box { border: 2px solid var(--ink); border-radius: 8px; padding: 1.1rem 1.25rem; background: var(--bg); }

/* Checklist B4 (2026-08-18): the big CTA trio are inline-flex and were never
   given horizontal centring, so their labels slid left once the mobile stack
   stretched them full-width. Measured 61px/158px asymmetry at 375px. */
.tel-big, .book-big, .text-big { justify-content: center; }

/* Town-page diagram slot: the donor's .photo.ar-hero forces a portrait photo
   box; a 456x250 scale drawing must render at its own aspect. */
.diagram-slot { display: flex; align-items: center; justify-content: center; padding: 1rem 0; }
.diagram-slot .box-diagram { width: 100%; max-width: 456px; height: auto; }

/* ── Compact size cards (Ryan, 2026-08-18: "make the cards fit better").
   Measured 470px at 375w; the trims below target ~400px (≈0.49 screens)
   without deleting a fact. The name and price tighten, the diagram drops to
   96px on phones, the duplicated white space between blocks closes up. ── */
.size-card .yd { font-size: 1.35rem; }
.size-card-price { font-size: clamp(1.45rem, 2.6vw, 1.8rem); margin-top: 0.4rem; }
.size-card-price small { line-height: 1.25; }
.size-card .price-rows { margin: 0.3rem 0 0.2rem; }
.size-card .size-card-dims { margin-top: 0.15rem; }
.size-card-link > ul:not(.price-rows) { margin: 0.35rem 0 0.2rem; }
.size-card-actions { margin-top: 0.4rem; padding-top: 0; }
@media (max-width: 700px) {
  .size-card .box-diagram { max-height: 96px; }
  .size-card-actions .size-act { min-height: 48px; }
}

/* ── Goes In / Stays Out chip panels (Ryan, 2026-08-18). The old version was
   two long bulleted prose lists with redundant markers (a dot AND a ✓). This
   is the scannable form: two bordered panels, items as color-coded chips.
   Same pill anatomy as .town-pills; ✓/✕ colors from the --ok/--no tokens. ── */
.inout-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin-top: 1.5rem; }
@media (max-width: 700px) { .inout-grid { grid-template-columns: 1fr; } }
.inout-panel { border: 2px solid var(--black); border-radius: 10px; padding: 1.1rem 1.2rem 1.25rem; background: var(--bg); box-shadow: 4px 4px 0 var(--black); }
.inout-panel.is-out { background: var(--bg-warm); }
.inout-panel h2 { font-size: 1.35rem; margin: 0 0 0.75rem; display: flex; align-items: center; gap: 0.5rem; }
.inout-badge { display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; border-radius: 50%; color: #fff; font-size: 0.95rem; flex-shrink: 0; }
.inout-panel h2 .inout-badge { background: var(--ok); }
.inout-panel.is-out h2 .inout-badge { background: var(--no); }
.item-pills { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.45rem; }
.item-pills li { border: 1.5px solid var(--line); border-radius: 999px; padding: 0.32rem 0.75rem; font-size: 0.92rem; font-weight: 600; color: var(--ink); background: var(--bg); cursor: default; }
.item-pills li::before { content: "✓ "; color: var(--ok-deep); font-weight: 700; }
.inout-panel.is-out .item-pills li::before { content: "✕ "; color: var(--no); }
.inout-note { margin-top: 0.85rem; font-size: 0.92rem; color: var(--muted); }

/* ── The price table (Ryan, 2026-08-18: "this could be better visually").
   Was an unstyled default table. House treatment: navy header band, 2px
   frame with the hard offset shadow, display-font prices, tinted heavy row.
   Wide tables scroll inside their own container, never the page. ── */
.table-scroll { overflow-x: auto; margin-top: 1.25rem; }
.price-table { width: 100%; border-collapse: collapse; border: 2px solid var(--black); box-shadow: 4px 4px 0 var(--black); background: var(--bg); table-layout: fixed; }
.price-table thead th:first-child { width: 40%; }
.price-table thead th { background: var(--navy); color: #fff; font-family: var(--font-display); font-size: 1.05rem; letter-spacing: 0.3px; padding: 0.75rem 1rem; text-align: left; }
.price-table thead th:not(:first-child) { text-align: center; }
.price-table tbody th { font-family: var(--font-display); font-size: 1.05rem; text-align: left; padding: 0.85rem 1rem; border-top: 1px solid var(--line); }
.price-table tbody th a { color: var(--navy); text-decoration: none; border-bottom: 2px solid var(--yellow); }
.price-table tbody th a:hover { border-bottom-color: var(--navy); }
.price-table tbody td { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; color: var(--red-deep); text-align: center; padding: 0.85rem 1rem; border-top: 1px solid var(--line); }
.price-table tbody tr:nth-child(odd) { background: var(--bg-warm); }
/* No tint on the heavy row (Ryan, 2026-08-18): in this system the lime wash
   means "recommended" (rate-chip pick, the picker's active state), and the heavy row
   is different-rules, not recommended. The small note differentiates it. */
.price-table tbody th .row-note { display: block; font-weight: 400; font-family: var(--font-body); font-size: 0.85rem; color: var(--muted); letter-spacing: 0; }

/* Phones: the 4-column money table compresses to fit 375px rather than
   hiding the prices behind a horizontal scroll. Measured: Size ~120px +
   three ~70px price columns fits with room. */
@media (max-width: 700px) {
  .price-table thead th { padding: 0.55rem 0.45rem; font-size: 0.92rem; }
  .price-table tbody th { padding: 0.65rem 0.45rem; font-size: 0.95rem; }
  .price-table tbody td { padding: 0.65rem 0.3rem; font-size: 1rem; }
  .price-table tbody th .row-note { font-size: 0.78rem; }
}

/* The pricing page's own money table: three sizes, four columns, must FIT a
   phone rather than scroll (scrolling hid the prices). The donor's
   .table-scroll .price-table min-width serves the 5-column town comparison
   tables and stays; this modifier out-specifies it for the main table only. */
.table-scroll .price-table.price-main { min-width: 0; table-layout: fixed; }
.price-table.price-main thead th:first-child { width: 40%; }

/* ── Batch (Ryan, 2026-08-18): size grid, topbar, town features ── */
/* Cards: a real responsive grid. 3-up at desktop for the 3 products, 1-up on
   phones. The markup said .size-grid but the class had no rules, so every
   page stacked single-column at every width. */
.size-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.75rem; margin-top: 1.75rem; align-items: start; }

/* Topbar: fully opaque. The donor's 0.97-alpha + blur let lime hero buttons
   ghost through as a pale wash on every scrolled page. Solid white, thinner
   (brand 40px), crisp bottom rule. */
.topbar { background: #fff; backdrop-filter: none; -webkit-backdrop-filter: none; border-bottom: 2px solid var(--line); }
.topbar-inner { padding-top: 0.35rem; padding-bottom: 0.35rem; min-height: 0; }

/* Featured-town cards on the hub reuse the pc-box anatomy in a grid. */
.town-features { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: 1.5rem; margin-top: 1.5rem; }
.town-features .pc-box h3 { margin-top: 0; }
.town-features .pc-box .btn { margin-top: 0.75rem; }

/* ── Nav redesign (Ryan, 2026-08-18): the pro home-service header ──
   Logo LEFT, nav links CENTER-RIGHT, actions RIGHTMOST with the phone as the
   terminal element. The donor left the actions div with no flex order, so it
   defaulted to 0 and rendered leftmost: CTAs first, logo center, nav right,
   which is a fashion-site layout, not a trades one. */
.topbar-actions { display: flex; align-items: center; gap: 0.9rem; }
@media (min-width: 1000px) {
  .topbar-inner > .topbar-actions { order: 3; flex: 0 0 auto; margin-left: auto; }
  .topbar-inner > nav.primary { margin-left: auto; }
  nav.primary a.drawer-only { display: none; }
}

/* ── Per-service rate strip (Ryan, 2026-08-18): the page's relevant prices
   directly under the hero, before any prose. Chips are data-driven from
   sizes.data.mjs so a price change propagates everywhere. One lime accent
   per strip marks the size this page actually recommends. ── */
.rate-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1rem; }
.rate-chip { display: block; border: 2px solid var(--black); border-radius: 8px; background: var(--bg); box-shadow: 3px 3px 0 var(--black); padding: 0.9rem 1.1rem; text-decoration: none; color: var(--ink); }
.rate-chip:hover { transform: translate(-2px, -2px); box-shadow: 5px 5px 0 var(--black); }
.rate-chip .rc-name { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; }
.rate-chip .rc-price { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.6rem; color: var(--red-deep); line-height: 1.1; margin: 0.15rem 0; }
.rate-chip .rc-price em { font-style: normal; font-weight: 600; font-size: 0.78rem; color: var(--muted); display: inline-block; margin-right: 0.3rem; vertical-align: 0.35em; }
.rate-chip .rc-sub { display: block; font-size: 0.85rem; color: var(--muted); line-height: 1.4; }
.rate-chip.is-pick { background: var(--yellow-tint); border-color: var(--black); position: relative; }
.rate-chip.is-pick::before { content: "THE USUAL PICK"; position: absolute; top: -0.65rem; right: 0.8rem; background: var(--yellow); color: var(--ink); font-family: var(--font-display); font-weight: 700; font-size: 0.68rem; letter-spacing: 0.5px; padding: 0.15rem 0.55rem; border: 1.5px solid var(--black); border-radius: 999px; }
.rate-strip-note { margin-top: 0.85rem; font-size: 0.9rem; color: var(--muted); }

/* ── The load-split visual (Ryan, 2026-08-18): the two-dumpster billing story
   drawn instead of described. Reuses the scale diagrams; the lime tag marks
   the flat-rate (default) load, navy marks the weighed one. ── */
.load-split { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; margin: 1.5rem 0; }
@media (max-width: 760px) { .load-split { grid-template-columns: 1fr; } }
.ls-panel { border: 2px solid var(--black); border-radius: 10px; background: var(--bg); box-shadow: 4px 4px 0 var(--black); padding: 1rem 1.15rem 1.15rem; position: relative; }
.ls-tag { position: absolute; top: -0.7rem; left: 0.9rem; font-family: var(--font-display); font-weight: 700; font-size: 0.7rem; letter-spacing: 0.5px; padding: 0.18rem 0.6rem; border: 1.5px solid var(--black); border-radius: 999px; }
.ls-tag.is-flat { background: var(--yellow); color: var(--ink); }
.ls-tag.is-weighed { background: var(--navy); color: #fff; }
.ls-panel .box-diagram { width: 100%; max-width: 300px; height: auto; display: block; margin: 0.5rem auto 0.35rem; }
.ls-panel h3 { font-size: 1.05rem; margin: 0.4rem 0 0.5rem; }
.ls-panel .item-pills li { font-size: 0.85rem; padding: 0.25rem 0.6rem; }
.ls-panel .item-pills li::before { content: ""; }
.ls-facts { margin-top: 0.6rem; font-size: 0.88rem; color: var(--muted); }

/* Phones only: the tighter mark so call button + hamburger clear 360px. */
@media (max-width: 640px) {
  .brand-mark { height: 50px; }
}

/* Size cards (Ryan, 2026-08-19): the 3 product cards ride 3-across whenever
   the row fits, 2+1 in the middle with the odd card centered at card width
   (not stretched, not stranded left), single column on phones. The bare
   auto-fit rule wrapped 2+1 with the orphan left-aligned at ~950px. */
.size-grid.two-up { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1020px) {
  .size-grid.two-up { grid-template-columns: repeat(2, 1fr); }
  .size-grid.two-up > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
    width: calc(50% - 0.875rem);
    justify-self: center;
  }
}
@media (max-width: 700px) {
  .size-grid.two-up { grid-template-columns: 1fr; }
  .size-grid.two-up > :last-child:nth-child(odd) { width: 100%; }
}

/* CTA rows that sit under centered copy center too. */
.size-grid-cta .cta-row { justify-content: center; }

/* Equal-height product cards (Ryan, 2026-08-19): the grid stretches rows and
   each card pins its Book button to the bottom, so three cards with different
   text lengths still bottom-align. */
.size-grid.two-up { align-items: stretch; }
.size-grid.two-up .size-card { display: flex; flex-direction: column; height: 100%; }
.size-grid.two-up .size-card .size-card-link { flex: 1 1 auto; }
.size-grid.two-up .size-card .size-card-actions { margin-top: auto; }

/* Large review badge for section heads (Ryan, 2026-08-20). Same swept
   internals as .g-rating (g-rating-score / g-rating-count / aria-label), so
   the weekly review feed keeps the number current here too. */
.g-rating.g-rating-lg {
  gap: 0.8rem;
  padding: 0.7rem 1.15rem 0.7rem 0.95rem;
  border-radius: 12px;
  margin-top: 0.6rem;
}
.g-rating-lg .g-rating-logo { width: 26px; height: 26px; }
.g-rating-lg .g-rating-score {
  font-family: var(--font-display); font-weight: 700;
  font-size: 1.75rem; line-height: 1; color: var(--black);
}
.g-rating-lg .gr-meta { display: flex; flex-direction: column; gap: 0.2rem; align-items: flex-start; }
.g-rating-lg .g-rating-stars { font-size: 1.02rem; letter-spacing: 0.08em; }
.g-rating-lg .g-rating-count { font-size: 0.86rem; }
@media (max-width: 420px) {
  .g-rating.g-rating-lg { gap: 0.6rem; padding: 0.6rem 0.85rem; }
  .g-rating-lg .g-rating-score { font-size: 1.45rem; }
}

/* ── Mobile audit fixes (Ryan, 2026-08-20) ───────────────────────────────── */
/* Town-page size table: 4 columns with a prose "Best for" cell can't fit a
   phone, and a sideways swipe hides the 7-day price. Stack it into labelled
   cards instead, which is how the data reads on a phone anyway. */
@media (max-width: 640px) {
  .table-scroll .price-table.stackable { min-width: 0; }
  .price-table.stackable thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap;
  }
  .price-table.stackable tbody tr {
    display: block; border: 2px solid var(--line); border-radius: 10px;
    padding: 0.7rem 0.9rem; margin-bottom: 0.8rem; background: #fff;
  }
  .price-table.stackable tbody td {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 1rem; border: 0; padding: 0.3rem 0; text-align: right;
  }
  .price-table.stackable tbody td::before {
    content: attr(data-label); text-align: left; flex: 0 0 auto;
    font-family: var(--font-display); font-weight: 600; color: var(--muted);
  }
  .price-table.stackable tbody td.size {
    display: block; text-align: left; padding-bottom: 0.5rem;
    margin-bottom: 0.3rem; border-bottom: 1px solid var(--line);
  }
  .price-table.stackable tbody td.size::before { content: none; }
  /* Inline town links on the homepage sat at 27px tall, under the 44px tap
     minimum, ten of them in one run of text. */
  .serving-links a { display: inline-block; padding: 0.4rem 0.1rem; }
}

/* Four-step flow strip stays four across (Ryan, 2026-08-20). The shared
   .pros-cons auto-fit grid broke it to 3+1 on mid-size screens. Phones drop
   to 2x2 rather than four ~80px columns, which would wrap every line to
   three words. */
.pros-cons.flow-4 { grid-template-columns: repeat(4, 1fr); gap: 1rem; }
@media (max-width: 700px) {
  .pros-cons.flow-4 { grid-template-columns: repeat(2, 1fr); gap: 0.8rem; }
  .pros-cons.flow-4 .pc-box { padding: 0.9rem 0.8rem; }
}

/* ── Design double-check fixes (2026-08-20) ─────────────────────────────── */
/* .faq is capped at 850px but had no auto margins, so every FAQ list on the
   site sat left of centre inside its wrap (156px left vs 275px right at
   1280). Centre it. */
.faq { margin-left: auto; margin-right: auto; }
/* Contractor / homeowner panels: unequal copy lengths left their buttons at
   different heights. Pin both to the bottom of the panel. */
#who .pc-box { display: flex; flex-direction: column; }
#who .pc-box > .btn { margin-top: auto; align-self: flex-start; }
