/* B&B Hauling — components. Tokens come from tokens.css. */

.skip {
  position: absolute; left: var(--gutter); top: -100px; z-index: 100;
  background: var(--red); color: #fff; padding: 0.75rem 1rem;
  border-radius: var(--r-btn); text-decoration: none; font-weight: 700;
}
.skip:focus { top: 0.75rem; color: #fff; }

.wrap.narrow { max-width: 760px; }
.wrap.wide { max-width: var(--maxw-wide); }   /* the before/after slider only */
.lede { font-size: clamp(1.125rem, 2.2vw, 1.375rem); color: var(--text); max-width: 52ch; }
.dim { color: var(--text-dim); }
.small { font-size: var(--small); }
.mt { margin-top: 2rem; }
.eyebrow {
  font-family: var(--font-head); font-size: var(--small); font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); margin-bottom: 0.75rem;
}

/* ---- Header ----------------------------------------------------------- */
.site-head { border-bottom: 1px solid var(--line); position: relative; z-index: 10; background: var(--bg); }
.head-inner { display: flex; align-items: center; gap: 1.5rem; min-height: 72px; }
.brand {
  font-family: var(--font-head); font-weight: 800; font-size: 1.25rem;
  color: var(--text); text-decoration: none; letter-spacing: -0.02em; white-space: nowrap;
}
.site-head nav { margin-left: auto; }
.site-head nav ul { display: flex; gap: 1.25rem; list-style: none; margin: 0; padding: 0; font-size: var(--small); }
.site-head nav a { text-decoration: none; }
.site-head nav a.is-here { text-decoration: underline; text-underline-offset: 5px; }
.head-call { min-height: 44px; padding-inline: 1.1rem; font-size: 1rem; }

@media (max-width: 900px) {
  .site-head nav { display: none; }          /* footer nav carries it; the call bar is the mobile UI */
  .head-inner { justify-content: space-between; }
  .head-call { margin-left: auto; }
}

/* ---- Hero ------------------------------------------------------------- */
.hero { position: relative; isolation: isolate; overflow: clip; padding-block: 0; min-height: min(78vh, 680px); display: grid; }
/* Positive z-index throughout: a composited layer (will-change below) at a
   negative index can paint beneath the page background. */
.hero-media { position: absolute; inset: -8% 0; z-index: 0; will-change: transform; }
/* <picture> is inline by default, so a percentage height on the img has nothing
   to resolve against. Make the wrapper a real box. */
.hero-media picture { display: block; width: 100%; height: 100%; }
.hero-media .photo { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }
/* Functional scrim: keeps the headline legible over the photo. Not decoration. */
.hero::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(10,10,11,.45) 0%, rgba(10,10,11,.7) 55%, rgba(10,10,11,.95) 100%);
}
.hero-inner { position: relative; z-index: 2; align-self: end; padding-block: clamp(3rem, 8vw, 6rem); }
.hero h1 { margin-bottom: 0.4em; }
.hero .lede { margin-bottom: 1.75rem; }

.btns { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.btns-hero .btn { flex: 1 1 auto; min-width: 200px; }
@media (max-width: 480px) { .btns .btn { flex: 1 1 100%; } }

/* ---- Before / after slider -------------------------------------------- */
/* The centrepiece: it takes the full wide wrap rather than sitting small. */
.ba { max-width: none; }
/* Default is the stacked pair: correct with no JS, and the reduced-motion view.
   site.js adds .ba-live only when it can actually drive the wipe. */
.ba-frame {
  display: grid; gap: 0.5rem; position: relative;
  border-radius: var(--r-photo); background: var(--surface);
}
.ba-frame picture { display: block; width: 100%; }
.ba-img { border-radius: var(--r-photo); display: block; width: 100%; }
.ba-handle { display: none; }
.ba-tag { justify-self: start; }
/* Stacked fallback: label, before, label, after — in that reading order.
   The clipped layer holds the "before", so it has to be pulled above the base. */
.ba-frame:not(.ba-live) .ba-tag-l { order: 1; }
.ba-frame:not(.ba-live) .ba-clip { order: 2; }
.ba-frame:not(.ba-live) .ba-tag-r { order: 3; }
.ba-frame:not(.ba-live) > picture:has(.ba-after) { order: 4; }

.ba-frame.ba-live {
  display: block; overflow: hidden;
  touch-action: pan-y; user-select: none; cursor: ew-resize;
}
/* Full width at 4:3 would stand 1039px tall on a 900px screen — you could not
   see the whole comparison at once. A wider crop keeps it big and on screen,
   and trims sky and grass rather than the gate and wall that carry the change.
   Both frames crop identically, so the comparison stays honest. */
@media (min-width: 900px) {
  .ba-live { aspect-ratio: 16 / 9; max-height: 70vh; }
  .ba-live .ba-img { height: 100%; object-fit: cover; }
  .ba-live > picture { height: 100%; }
}
.ba-live .ba-img { border-radius: 0; }
.ba-live .ba-handle { display: grid; }
.ba-live .ba-clip picture { height: 100%; }
/* The "before" sits on top of the "after" at identical size and is wiped away
   from the right. No width maths, so the two frames cannot drift apart. */
.ba-live .ba-clip { position: absolute; inset: 0; clip-path: inset(0 50% 0 0); }
.ba-live .ba-clip .ba-img { width: 100%; height: 100%; object-fit: cover; }
.ba-live .ba-handle {
  position: absolute; top: 0; bottom: 0; left: 50%; width: 44px; margin-left: -22px;
  place-items: center; cursor: ew-resize; background: none; border: 0;
}
.ba-handle::before { content: ''; position: absolute; top: 0; bottom: 0; width: 3px; background: var(--red); }
.ba-grip {
  width: 44px; height: 44px; border-radius: 50%; background: var(--red);
  box-shadow: 0 2px 12px rgba(0,0,0,.5); position: relative;
}
.ba-grip::before, .ba-grip::after {
  content: ''; position: absolute; top: 50%; width: 0; height: 0;
  border-block: 5px solid transparent; translate: 0 -50%;
}
.ba-grip::before { left: 11px; border-right: 7px solid #fff; }
.ba-grip::after  { right: 11px; border-left: 7px solid #fff; }
.ba-handle:focus-visible { outline: 3px solid var(--red-hover); outline-offset: 2px; border-radius: var(--r-photo); }

.ba-tag {
  font-family: var(--font-head); font-weight: 800;
  font-size: var(--small); letter-spacing: 0.04em; text-transform: uppercase;
  background: rgba(10,10,11,.8); color: var(--text); padding: 0.3rem 0.6rem; border-radius: 6px;
}
.ba-live .ba-tag { position: absolute; bottom: 0.75rem; }
.ba-live .ba-tag-l { left: 0.75rem; }
.ba-live .ba-tag-r { right: 0.75rem; }

/* ---- Service cards ---------------------------------------------------- */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.25rem; }
.card {
  display: block; text-decoration: none; color: var(--text);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 1rem;
}
.card h3 { color: var(--red); margin: 0.9rem 0 0.4rem; }   /* the card is tappable, so its title is red */
.card p { color: var(--text-dim); font-size: var(--small); margin: 0; max-width: none; }
.card:hover { border-color: var(--text-dim); }
.card:hover h3 { color: var(--red-hover); }

/* ---- Steps ------------------------------------------------------------ */
.steps { list-style: none; counter-reset: s; margin: 0; padding: 0; display: grid; gap: 1.5rem; }
/* Three across on desktop instead of one narrow stack. */
@media (min-width: 820px) {
  .steps { grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem, 3vw, 2.5rem); }
}
.steps li { counter-increment: s; display: grid; grid-template-columns: auto 1fr; gap: 1rem; align-items: start; }
.steps li::before {
  content: counter(s); font-family: var(--font-head); font-weight: 800; font-size: 1.25rem;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 1px solid var(--line); border-radius: 50%; color: var(--text-dim);
}
.steps strong { grid-column: 2; font-family: var(--font-head); font-size: 1.25rem; }
.steps span { grid-column: 2; color: var(--text-dim); }

/* ---- Photo layouts ---------------------------------------------------- */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.25rem; }
.pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.25rem; }
.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }

.fig { margin: 0; display: grid; gap: 0.5rem; align-content: start; }
/* Only for figures stacked in normal flow — a grid or flex gap handles its own
   spacing, and this would otherwise push every item after the first down 20px. */
.fig + .fig { margin-top: 1.25rem; }
.grid .fig + .fig,
.pair .fig + .fig { margin-top: 0; }
.fig figcaption { color: var(--text-dim); font-size: var(--small); }

/* One shape for every photo in a gallery, so rows line up and captions sit at
   the same depth. Display only — no image file is re-cropped. */
.grid .photo,
.pair .photo { aspect-ratio: 4 / 3; object-fit: cover; }
.grid picture,
.pair picture { display: block; }

/* The side-by-side before/after composites are ~2.5:1. No crop of those keeps
   both halves, so they letterbox into the same 4:3 box instead of cropping. */
.photo.is-wide { object-fit: contain; background: var(--bg); }

/* ---- Lists ------------------------------------------------------------ */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.ticks li { padding-left: 1.6rem; position: relative; }
.ticks li::before {
  content: ''; position: absolute; left: 0; top: 0.55em;
  width: 8px; height: 8px; border-radius: 50%; background: var(--text-dim);
}
.towns {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 0.5rem 1.5rem;
}

/* "Where we work": list and rig photo side by side on desktop, stacked on
   mobile with the photo after the list. */
.area { display: grid; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
@media (min-width: 900px) { .area { grid-template-columns: 1.15fr 1fr; } }
.towns li { color: var(--text); border-bottom: 1px solid var(--line); padding: 0.45rem 0; }
.plain { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: 0.6rem; font-size: 1.25rem; }

/* ---- FAQ -------------------------------------------------------------- */
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item summary {
  cursor: pointer; list-style: none; padding: 1.1rem 2.5rem 1.1rem 0; position: relative;
  font-family: var(--font-head); font-weight: 800; font-size: 1.1875rem; line-height: 1.3;
  color: var(--red);                      /* a summary is tappable, so it is red */
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--red-hover); }
.faq-item summary::after {
  content: ''; position: absolute; right: 0.5rem; top: 1.5rem;
  width: 10px; height: 10px; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  rotate: 45deg; translate: 0 -25%;
}
.faq-item[open] summary::after { rotate: -135deg; translate: 0 25%; }
.faq-a { padding-bottom: 1.25rem; color: var(--text-dim); max-width: var(--maxw-text); }
.faq-a p { margin: 0; }

/* ---- Reviews marquee --------------------------------------------------- */
/* --fb is a deliberate exception for Facebook-sourced content only, and is
   allowed on exactly three things inside a card: the source tag, the thumbs up
   and the top accent. It must never read as tappable — red is still the only
   tap signal on this site, and these cards are not links. */
.reviews { --fb: #1877F2; }
.reviews .lede { margin-bottom: 2rem; }

.marquee { overflow: hidden; }
.marquee-track {
  display: flex; gap: 1.25rem; list-style: none; margin: 0; padding: 0 var(--gutter);
  width: max-content;
  animation: marquee-scroll var(--marquee-dur, 90s) linear infinite;
}
/* Pause for anyone reading: pointer, keyboard focus, or a finger held down. */
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track,
.marquee.is-held .marquee-track { animation-play-state: paused; }

@keyframes marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

.rv {
  flex: 0 0 min(340px, 78vw);   /* most of a card visible on a phone */
  display: flex; flex-direction: column; gap: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--fb);
  border-radius: var(--r-card);
  padding: 1.25rem;
}
.rv-rec {
  display: flex; align-items: center; gap: 0.4rem; margin: 0;
  font-family: var(--font-head); font-weight: 800; font-size: var(--small);
  letter-spacing: 0.02em; color: var(--text);
}
.fb-thumb { color: var(--fb); flex: none; }
.rv-text {
  margin: 0; font-size: 1rem; line-height: 1.55; color: var(--text);
  max-width: none; quotes: none;
}
.rv-who { margin: auto 0 0; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.rv-name { font-weight: 600; }
.rv-date { color: var(--text-dim); font-size: var(--small); }
.rv-src {
  margin: 0; align-self: flex-start;
  font-size: 0.8125rem; letter-spacing: 0.02em;
  color: var(--fb);
  border: 1px solid color-mix(in srgb, var(--fb) 40%, transparent);
  border-radius: 999px; padding: 0.15rem 0.55rem;
  cursor: default;              /* never looks tappable */
}

/* Reduced motion: no travel. Static wrap, clones removed so each review is
   shown and announced exactly once. */
@media (prefers-reduced-motion: reduce) {
  .marquee-track {
    animation: none;
    width: auto; flex-wrap: wrap;
    padding-inline: 0;
  }
  .marquee { overflow: visible; }
  .marquee-track > [aria-hidden="true"] { display: none; }
  .rv { flex: 1 1 300px; }
  .reviews .marquee { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
}

/* ---- CTA -------------------------------------------------------------- */
.cta { border-top: 1px solid var(--line); }
.cta .lede { margin-bottom: 1.75rem; }
.cta .dim { margin-top: 1rem; }

/* ---- Form ------------------------------------------------------------- */
.form { display: grid; gap: 1.25rem; max-width: 520px; }
.field { display: grid; gap: 0.4rem; }
.field label { font-weight: 600; font-size: var(--small); }
.field input, .field select, .field textarea {
  background: var(--surface); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-btn);
  padding: 0.85rem 0.9rem; font: inherit; font-size: 1rem; min-height: 52px; width: 100%;
}
.field textarea { min-height: 120px; resize: vertical; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { border-color: var(--red-hover); }

/* Error state carries a border, an icon-free text message and aria — never colour alone. */
.field.is-bad input, .field.is-bad select, .field.is-bad textarea { border-color: var(--red); }
.err { color: var(--red); font-size: var(--small); margin: 0; min-height: 0; }
.err:empty { display: none; }
.form-err[hidden] { display: none; }
.form-note { margin: 0; }
.form .btn { justify-self: start; }

/* ---- Footer ----------------------------------------------------------- */
.site-foot { border-top: 1px solid var(--line); padding-block: var(--section) 3rem; }
.site-foot p { margin: 0 0 0.5rem; }
.foot-name { font-family: var(--font-head); font-weight: 800; font-size: 1.25rem; }
.site-foot nav ul {
  list-style: none; margin: 1.5rem 0 1rem; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; font-size: var(--small);
}
.site-foot nav a { text-decoration: none; }

/* ---- Steps tracker (thank-you) ---------------------------------------- */
/* Deliberately monochrome: nothing here is tappable, so nothing here is red.
   Status is carried by the "Done" / "Next" words, not by colour alone. */
.track { list-style: none; margin: 2.5rem 0; padding: 0; }
.track-step {
  position: relative;
  display: grid; grid-template-columns: 36px 1fr; gap: 1rem;
  padding-bottom: 2rem;
}
.track-step:last-child { padding-bottom: 0; }
/* The line joining one step to the next. */
.track-step::before {
  content: ''; position: absolute; left: 17px; top: 40px; bottom: 0;
  width: 2px; background: var(--line);
}
.track-step:last-child::before { display: none; }
.track-step.is-done::before { background: var(--text-dim); }

.track-mark {
  position: relative; z-index: 1;
  width: 36px; height: 36px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bg); border: 1px solid var(--line);
  font-family: var(--font-head); font-weight: 800; font-size: 0.9375rem;
  color: var(--text-dim);
}
.is-done .track-mark { background: var(--text); border-color: var(--text); color: var(--bg); }
.is-next .track-mark { border: 2px solid var(--text); color: var(--text); }

.track-title {
  margin: 0 0 0.3rem; max-width: none;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  font-family: var(--font-head); font-weight: 800; font-size: 1.125rem; line-height: 1.25;
}
.track-tag {
  font-family: var(--font-body); font-size: 0.75rem; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.15rem 0.5rem; border-radius: 999px;
  border: 1px solid var(--line); color: var(--text-dim);
}
.is-next .track-tag { color: var(--text); border-color: var(--text); }
.track-note { margin: 0; color: var(--text-dim); font-size: 1rem; max-width: 46ch; }
.track-step:not(.is-done):not(.is-next) .track-title { color: var(--text-dim); }

/* ---- Page head -------------------------------------------------------- */
.page-head { padding-block: clamp(3rem, 7vw, 5.5rem) clamp(2rem, 4vw, 3rem); }
.page-head.tall { min-height: 60vh; display: grid; align-content: center; }
.page-head .lede { margin-bottom: 1.75rem; }

.prose h2 { font-size: 1.5rem; margin-top: 2.5rem; }
.prose h2:first-child { margin-top: 0; }
