/* =========================================================
   Dallas Headlight Restoration — dallasheadlightrestoration.com
   Brand: black #000 / white #FFF · Bebas Neue + Raleway

   Adapted from site/styles.css. Two deliberate differences:

     - No INSTANT CHECK block. That section does not exist on this site,
       so ~250 lines of rules for it would be styling nothing.
     - A CSS wordmark (.brandmark) instead of an <img> logo. The other
       site's logo.png is a drawn lockup of a different business name and
       cannot be reused here; a typeset wordmark in the same two brand
       faces is honest, sharp at every size, and needs no new artwork.
   ========================================================= */

/* Self-hosted from the brand kit (archived outside this repo; the extracted
   woff2 files in assets/fonts are all the site needs). Raleway is a variable
   font, so one 27KB file covers every weight used (400/500/600/700). */
@font-face {
  font-family: "Bebas Neue";
  src: url("assets/fonts/bebas-neue.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Raleway";
  src: url("assets/fonts/raleway-var.woff2") format("woff2-variations"),
       url("assets/fonts/raleway-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --black: #000;
  --white: #fff;
  --gray-1: #f5f5f5;
  --gray-2: #d9d9d9;
  /* Muted text comes in two weights so both pass WCAG AA (4.5:1).
     #8a8a8a is 5.9:1 on black but only 3.6:1 on white, so light
     backgrounds get the darker token. Don't collapse these back. */
  --gray-on-dark: #8a8a8a;
  --gray-on-light: #6b6b6b;
  --gray-4: #2a2a2a;
  --heading: "Bebas Neue", "Arial Narrow", sans-serif;
  --body: "Raleway", "Helvetica Neue", sans-serif;
  --nav-h: 72px;
  --radius: 10px;
  --container: 1160px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: calc(var(--nav-h) + 12px); }

body {
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.65;
  color: var(--black);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

/* ---------- Focus & motion ----------
   The page alternates black and white sections, so a single-colour ring
   would vanish on one of them. A white ring with a black outer edge (or
   vice-versa on light sections) stays visible on both. */
:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px var(--black);
  border-radius: 4px;
}
/* Light grounds need the inverse ring: the default white one lands on a
   near-white background and only its black outer edge shows, which reads as a
   shadow rather than as focus.

   `.rv` was named here too until 22 August 2026, when /review.html became a
   redirect and its card was deleted along with the ~190 lines that styled it. */
.section:not(.section-dark) :focus-visible,
.footer-light :focus-visible {
  outline-color: var(--black);
  box-shadow: 0 0 0 6px var(--white);
}
/* Keyboard-only: don't draw rings on mouse clicks. */
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 200;
  padding: 12px 22px;
  background: var(--white);
  color: var(--black);
  font-family: var(--heading);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  border-radius: 0 0 6px 6px;
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .btn:active { transform: none; }
}

img { max-width: 100%; display: block; }

h1, h2, h3 { font-family: var(--heading); font-weight: 400; line-height: 1.05; letter-spacing: 0.01em; }
h1 { font-size: clamp(3rem, 7vw, 5.2rem); }
h2 { font-size: clamp(2.4rem, 5vw, 3.6rem); margin-bottom: 0.35em; }
h3 { font-size: 1.5rem; margin-bottom: 0.4em; }

.container { max-width: var(--container); margin: 0 auto; padding: 0 24px; }
.container-narrow { max-width: 820px; }

.eyebrow {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: 14px;
  opacity: 0.65;
}

.section { padding: 96px 0; }
.section-sub { max-width: 640px; font-size: 1.05rem; margin-bottom: 40px; color: var(--gray-4); }

.section-dark { background: var(--black); color: var(--white); }
.section-dark .section-sub { color: var(--gray-2); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--heading);
  font-size: 1.15rem;
  letter-spacing: 0.06em;
  text-decoration: none;
  padding: 13px 28px 11px;
  border-radius: 6px;
  border: 2px solid var(--black);
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
  cursor: pointer;
  text-align: center;
}
.btn:active { transform: scale(0.97); }
.btn-solid { background: var(--black); color: var(--white); }
.btn-solid:hover { background: var(--gray-4); border-color: var(--gray-4); }
.btn-outline { background: transparent; color: var(--black); }
.btn-outline:hover { background: var(--black); color: var(--white); }
.btn-light { background: var(--white); color: var(--black); border-color: var(--white); }
.btn-light:hover { background: var(--gray-2); border-color: var(--gray-2); }
.btn-outline-light { background: transparent; color: var(--white); border-color: var(--white); }
.btn-outline-light:hover { background: var(--white); color: var(--black); }
.btn-lg { font-size: 1.4rem; padding: 16px 36px 13px; }

.cta-row { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 28px; }
.cta-center { justify-content: center; }

/* Risk-reversal line, sits right under the CTA where hesitation happens. */
.cta-reassure {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin-top: 16px;
  font-size: 0.92rem;
  color: var(--gray-2);
}
.cta-reassure svg { width: 17px; height: 17px; flex: none; margin-top: 4px; }
.cta-reassure strong { color: var(--white); font-weight: 700; }

/* SMS consent disclosure.
   A2P 10DLC review checks the page for this next to whatever initiates a text —
   a campaign citing the website as its opt-in path gets rejected without it.
   Deliberately quiet: it has to be legible and findable, not loud. Both colours
   are the deliberate on-dark / on-light greys, which clear 4.5:1 on their
   respective grounds. */
.sms-note {
  margin-top: 14px;
  max-width: 46ch;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--gray-on-light);
}
.sms-note-dark { color: var(--gray-on-dark); }
/* Follow the alignment of the CTA row it belongs to. */
.cta-center + .sms-note { text-align: center; margin-left: auto; margin-right: auto; }

/* The disclosure paragraphs on the legal pages run full measure, unlike the
   46ch fine print beside a button — they are the content there, not a footnote
   under it. */
.container-narrow > .sms-note { max-width: none; font-size: 0.95rem; }

/* ---------- Texting page ---------- */
/* QR code beside the copy A2P review expects to surround it: what it does, the
   value proposition, the frequency, and the brand name. Stacks under 620px so
   the code stays big enough to scan off a phone screen. */
.qr-block {
  display: flex;
  gap: 28px;
  align-items: flex-start;
  margin: 24px 0 32px;
  padding: 24px;
  border: 1px solid var(--gray-2);
  border-radius: var(--radius);
}
.qr-block img { flex: 0 0 auto; width: 220px; height: 220px; }
.qr-block ul { margin: 10px 0 0 18px; }
.qr-block li { margin-bottom: 4px; }
@media (max-width: 620px) {
  .qr-block { flex-direction: column; align-items: center; text-align: center; }
  .qr-block ul { text-align: left; }
}

/* The verbal consent script, set apart because it is a quotation of speech and
   a reviewer needs to find it at a glance. */
.verbal-script {
  margin: 18px 0;
  padding: 18px 22px;
  border-left: 3px solid var(--black);
  background: var(--gray-1);
}
.verbal-script p { margin-bottom: 10px; }
.verbal-script p:last-child { margin-bottom: 0; }


/* ---------- Nav ---------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  background: var(--black);
  border-bottom: 1px solid var(--gray-4);
}
.nav-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: 32px;
}
/* ---------- Wordmark ----------
   Typeset, not an image. The name is three long words, so the lockup puts the
   qualifier on top as a tracked-out eyebrow and gives the full line — the words
   this business is actually looked up by — the display face at full size.

   Being real text rather than a PNG means it is sharp on any screen, it is
   selectable and readable by a screen reader without alt text to keep in sync,
   and it costs no extra request. The <a> carries the accessible name; the
   pieces below are decoration on top of it. */
.brandmark {
  display: flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  color: var(--white);
  /* The mark sits on black in both places it is used. */
}
.brandmark-icon {
  width: 30px;
  height: 30px;
  flex: none;
  /* currentColor, so the glyph follows the text it sits beside. */
  color: inherit;
}
.brandmark-text { display: block; line-height: 1; }
.brandmark-top {
  display: block;
  font-family: var(--body);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  /* Tracking adds space after the LAST letter too, which visually shifts the
     word right of the line beneath it. Pull it back by roughly that amount. */
  margin-right: -0.3em;
  text-transform: uppercase;
  opacity: 0.72;
  margin-bottom: 4px;
}
.brandmark-main {
  display: block;
  font-family: var(--heading);
  font-size: 1.42rem;
  letter-spacing: 0.045em;
  margin-right: -0.045em;
  white-space: nowrap;
}
.nav-logo.brandmark { margin-right: auto; }

.nav-links { display: flex; gap: 28px; margin-left: auto; }
.nav-links a {
  color: var(--white);
  text-decoration: none;
  font-family: var(--heading);
  font-size: 1.05rem;
  letter-spacing: 0.08em;
  opacity: 0.85;
}
.nav-links a:hover { opacity: 1; }
/* The language switcher.
   Marked out from the section links beside it because it does something
   categorically different — it reloads the page you are on in another
   language rather than scrolling to a part of it. The bordered pill is what
   says "control", not "destination".

   The label is always written in the language it leads TO, so it is the one
   item in the nav that a visitor who cannot read the rest can still read.
   That is also why it is not hidden on small screens: it is repeated inside
   .nav-mobile instead, where .nav-links is display:none. */
.nav-links .lang-switch {
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 999px;
  padding: 3px 12px 1px;
  opacity: 0.85;
}
.nav-links .lang-switch:hover { border-color: var(--white); opacity: 1; }
.nav-cta { border-color: var(--white); background: var(--white); color: var(--black); padding: 9px 20px 7px; font-size: 1rem; }
.nav-cta:hover { background: var(--gray-2); border-color: var(--gray-2); }

/* The checkbox is the open/closed state; it never needs to be seen. */
.nav-toggle-input { position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none; }
.nav-toggle { display: none; background: none; border: none; width: 40px; height: 40px; flex-direction: column; justify-content: center; gap: 6px; align-items: center; cursor: pointer; }
.nav-toggle span { display: block; width: 24px; height: 2px; background: var(--white); transition: 0.2s; }
.nav-mobile { display: none; }
/* Keyboard focus lands on the hidden checkbox, so mirror the ring onto the
   label the user can actually see. */
.nav-toggle-input:focus-visible ~ .nav-inner .nav-toggle {
  outline: 3px solid var(--white);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px var(--black);
  border-radius: 4px;
}

/* ---------- Hero ---------- */
.hero {
  background: var(--black);
  color: var(--white);
  padding: calc(var(--nav-h) + 72px) 0 88px;
}
.hero-inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: 56px;
  align-items: center;
}
.hero h1 span { display: inline-block; border-bottom: 5px solid var(--white); padding-bottom: 4px; }
.hero-sub { margin-top: 22px; font-size: 1.1rem; color: var(--gray-2); max-width: 480px; }

.trust-bar {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 34px;
  margin-top: 36px;
  padding-top: 22px;
  border-top: 1px solid var(--gray-4);
  font-size: 0.92rem;
  color: var(--gray-2);
}
.trust-bar strong { color: var(--white); font-weight: 700; }
.trust-bar-inline { border-top-color: rgba(255,255,255,0.25); }

.hero-slider-hint { text-align: center; margin-top: 12px; font-size: 0.85rem; color: var(--gray-on-dark); }

/* ---------- Before/After slider ---------- */
.ba {
  --pos: 50%;
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
  user-select: none;
  -webkit-user-select: none;
  /* pan-y, NOT none. `none` blocked vertical scrolling for any touch starting
     on the photo — on mobile that's a full-width dead zone where the page
     won't scroll. pan-y lets the page scroll vertically while leaving
     horizontal movement to the drag handler in script.js. */
  touch-action: pan-y;
  cursor: ew-resize;
  background: var(--gray-4);
}
/* Promote the layers only while actually dragging — keeping four sliders
   permanently promoted costs memory for no benefit. */
.ba.is-dragging .ba-after { will-change: clip-path; }
.ba.is-dragging .ba-handle { will-change: left; }
/* The range input is opacity:0, so a focus ring on it would be invisible.
   Put the ring on the container instead when it's keyboard-focused. */
.ba:has(input[type="range"]:focus-visible) {
  outline: 3px solid var(--white);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px var(--black);
}
.ba img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.ba .ba-after { clip-path: inset(0 0 0 var(--pos)); }
.ba-handle {
  position: absolute;
  top: 0; bottom: 0;
  left: var(--pos);
  width: 3px;
  background: var(--white);
  transform: translateX(-50%);
  pointer-events: none;
  box-shadow: 0 0 8px rgba(0,0,0,0.55);
}
.ba-handle span {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 42px; height: 42px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 2px 10px rgba(0,0,0,0.45);
}
.ba-handle span::before,
.ba-handle span::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 0; height: 0;
  border-style: solid;
  transform: translateY(-50%);
}
.ba-handle span::before { left: 8px; border-width: 6px 8px 6px 0; border-color: transparent var(--black) transparent transparent; }
.ba-handle span::after { right: 8px; border-width: 6px 0 6px 8px; border-color: transparent transparent transparent var(--black); }

/* Keyboard and screen-reader control only. pointer-events:none is deliberate:
   a range input only drags from its thumb, so while it was catching pointers
   most of the photo was unresponsive. script.js now handles pointer dragging
   on the container, and this stays for arrow-key and assistive-tech access
   (both of which are unaffected by pointer-events). */
.ba input[type="range"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  margin: 0;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}

.ba-tag {
  position: absolute;
  top: 14px;
  font-family: var(--heading);
  font-size: 0.95rem;
  letter-spacing: 0.12em;
  padding: 5px 12px 3px;
  border-radius: 4px;
  pointer-events: none;
}
.ba-tag-before { left: 14px; background: rgba(0,0,0,0.72); color: var(--white); }
.ba-tag-after { right: 14px; background: rgba(255,255,255,0.88); color: var(--black); }

/* ---------- Results ---------- */
.featured-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin-bottom: 40px;
}
.featured-grid figure { margin: 0; }
.featured-grid figcaption {
  margin-top: 10px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray-on-light);
}

.gallery-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 28px;
}
.chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  font-family: var(--heading);
  font-size: 1rem;
  letter-spacing: 0.06em;
  padding: 8px 18px 6px;
  border: 1.5px solid var(--gray-2);
  border-radius: 999px;
  background: var(--white);
  color: var(--black);
  cursor: pointer;
  transition: 0.15s;
}
.chip:hover { border-color: var(--black); }
.chip.is-active { background: var(--black); color: var(--white); border-color: var(--black); }

.pair-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 18px;
}
/* `display: grid` above outranks the hidden attribute's UA `display: none`, so
   the collapsed state has to be restated here.

   `display: none` is deliberate, and now load-bearing. The 40 cards became
   static markup (scripts/build-gallery.mjs), so all 80 photos sit in the DOM on
   every page load. An element with `display: none` generates no box, so a
   `loading="lazy"` image inside it can never intersect the viewport and is
   never fetched — which is what keeps this page at ~243 KB while shipping 80
   crawlable <img> tags. Collapsing with `max-height: 0` instead was tried and
   is worse: real layout boxes can fall inside the browser's lazy-load distance
   threshold, and then all 80 load.

   Googlebot still reads the markup, the alt text and the image URLs from the
   DOM; it does not need to fetch a photo to index it.

   NOTE: this cannot be verified with headless Chrome. Headless ignores
   loading="lazy" completely — a control with 8 images 12000px below the fold
   fetched all 8 — so a request count from a headless run says nothing about
   this rule either way. Check in a real browser's network panel. */
.pair-grid[hidden] { display: none; }

/* Without JS the gallery controls do nothing, so don't offer them. script.js
   removes .needs-js from <html> on load, revealing them. */
.needs-js .gallery-controls { display: none; }

/* The instant check, same rule and same reason. It is a file input, a fetch and
   a poller: with JavaScript off it renders a form that accepts a photo, a phone
   number and two consent ticks, and then does nothing at all — which is worse
   than not offering it, because the customer believes their quote is coming.

   Missed when the check was ported from the retired site on 6 August 2026: the
   extraction matched selectors containing `.check` and this one does not.
   check-widget.test.ts caught it. */
.needs-js .js-only { display: none; }
.noscript-note { margin: 0; }
.pair-card {
  border: 1px solid var(--gray-2);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--white);
}
/* Each card holds the same drag-to-compare slider as the featured ones. The
   card already clips to its own radius, so the slider inside shouldn't round
   its corners again. */
.pair-card .ba { border-radius: 0; }
/* The Before/After chips are sized for the big featured sliders; scale them
   down a little for the smaller gallery cards. */
.pair-card .ba-tag { font-size: 0.72rem; padding: 3px 8px 1px; }
.pair-card .ba-tag-before { left: 10px; }
.pair-card .ba-tag-after { right: 10px; }
.pair-card .ba-handle span { width: 34px; height: 34px; }
.pair-card figcaption {
  padding: 10px 14px;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray-on-light);
}

/* ---------- Testimonials ---------- */
/* Sized to look right at ONE card, not only at three.
   `auto-fit` with a `1fr` maximum collapses the empty tracks and hands the
   whole row to whatever is left, so the first genuine review rendered as a
   single card stretched across 1100px carrying two lines of text. Reviews
   arrive one at a time, so one card is the normal case for a while.

   The track keeps its `1fr` — capping the TRACK at 380px meant three no
   longer fitted the row and the third wrapped underneath. The cap belongs on
   the card, which is then centred inside whatever track it gets. */
.quote-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  justify-items: center;
  gap: 22px;
  margin-top: 28px;
}
/* One and two would otherwise sit in full-width tracks and drift apart. The
   grid is narrowed to what they actually need so the group stays together.
   Left, not centred: the eyebrow and the h2 above are left-aligned like every
   other section on the page, and a lone card floating in the middle under a
   left-aligned heading reads as a mistake rather than a choice.

   Browsers without :has() get the spread version, which is untidy rather than
   broken — and it stops mattering at three, where the row fills anyway. */
.quote-grid:has(.quote-card:only-child) { max-width: 380px; }
.quote-grid:has(.quote-card:nth-child(2):last-child) { max-width: 782px; }
.quote-card {
  border: 1px solid var(--gray-2);
  border-radius: var(--radius);
  padding: 30px 28px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  /* Fills its track, up to a width a short quote still looks composed in. */
  width: 100%;
  max-width: 380px;
}
.quote-card blockquote { font-size: 1.05rem; line-height: 1.6; }
.quote-card blockquote::before { content: "\201C"; }
.quote-card blockquote::after { content: "\201D"; }
.quote-card figcaption {
  margin-top: auto;
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
}
.quote-meta {
  display: block;
  font-weight: 500;
  text-transform: uppercase;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  color: var(--gray-on-light);
  margin-top: 3px;
}

/* ---------- Cards (why restore) ---------- */
.cards-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin-top: 44px;
}
.card {
  border: 1px solid var(--gray-4);
  border-radius: var(--radius);
  padding: 34px 28px;
}
.card p { color: var(--gray-2); font-size: 0.97rem; }
.card-icon { width: 46px; height: 46px; margin-bottom: 18px; color: var(--white); }
.card-icon svg { width: 100%; height: 100%; }

/* ---------- Steps ---------- */
.steps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 22px;
  margin-top: 44px;
  counter-reset: step;
}
.steps li {
  border-top: 3px solid var(--black);
  padding-top: 20px;
}
.step-num {
  font-family: var(--heading);
  font-size: 2.6rem;
  line-height: 1;
  display: block;
  margin-bottom: 10px;
  color: var(--gray-2);
}
.steps h3 { font-size: 1.35rem; }
.steps p { font-size: 0.95rem; color: var(--gray-4); }

/* ---------- Pricing ---------- */
.pricing-grid {
  display: grid;
  grid-template-columns: 1.2fr 0.8fr;
  gap: 22px;
  margin-top: 24px;
}
.pricing-factors, .pricing-travel {
  border: 1px solid var(--gray-4);
  border-radius: var(--radius);
  padding: 38px 34px;
}
.pricing-travel { background: var(--white); color: var(--black); display: flex; flex-direction: column; gap: 14px; }
.pricing-travel .btn { margin-top: auto; background: var(--black); color: var(--white); border-color: var(--black); }
.pricing-travel .btn:hover { background: var(--gray-4); }

.check-list { list-style: none; margin-top: 18px; display: grid; gap: 16px; }
.check-list li { padding-left: 30px; position: relative; color: var(--gray-2); font-size: 0.98rem; }
.check-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 5px;
  width: 14px; height: 8px;
  border-left: 2.5px solid var(--white);
  border-bottom: 2.5px solid var(--white);
  transform: rotate(-45deg);
}
.check-list strong { color: var(--white); }
.pricing-note { margin-top: 22px; font-size: 0.9rem; color: var(--gray-on-dark); }

.travel-free {
  font-size: 1.05rem;
  line-height: 1.45;
  padding: 14px 16px;
  border: 2px solid var(--black);
  border-radius: 8px;
}
.travel-free strong { font-family: var(--heading); font-size: 1.5rem; letter-spacing: 0.04em; margin-right: 6px; }
.travel-rate { font-size: 0.97rem; }

/* ---------- Service area ---------- */
.area-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: 22px;
}
.area-zone, .area-list {
  border: 1px solid var(--gray-2);
  border-radius: var(--radius);
  padding: 34px 30px;
}
.area-zone { background: var(--black); color: var(--white); border-color: var(--black); }
.area-zone p { font-size: 1.25rem; line-height: 1.5; margin-top: 16px; }
.area-badge {
  display: inline-block;
  font-family: var(--heading);
  font-size: 1rem;
  letter-spacing: 0.1em;
  background: var(--white);
  color: var(--black);
  padding: 6px 14px 4px;
  border-radius: 4px;
}
.area-badge-outline { background: transparent; border: 1.5px solid var(--black); }
.area-list ul {
  list-style: none;
  margin-top: 18px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px 16px;
  font-size: 0.97rem;
}
.area-list li { padding-left: 16px; position: relative; }
.area-list li::before { content: "·"; position: absolute; left: 0; font-weight: 700; }

/* ---------- About ---------- */
.about-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px 56px;
  align-items: start;
}
.about-head h2 { margin-bottom: 0; }
.about-copy p { color: var(--gray-2); font-size: 1.05rem; }
.about-copy .trust-bar { margin-top: 28px; }

/* ---------- FAQ ---------- */
#faq details {
  border-bottom: 1px solid var(--gray-2);
}
#faq details:first-of-type { border-top: 1px solid var(--gray-2); margin-top: 28px; }
#faq summary {
  font-family: var(--heading);
  font-size: 1.4rem;
  letter-spacing: 0.03em;
  padding: 20px 44px 17px 0;
  cursor: pointer;
  list-style: none;
  position: relative;
}
#faq summary::-webkit-details-marker { display: none; }
#faq summary::after {
  content: "+";
  position: absolute;
  right: 6px; top: 50%;
  transform: translateY(-50%);
  font-size: 1.6rem;
  transition: transform 0.2s;
}
#faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); }
#faq details p { padding: 0 0 22px; color: var(--gray-4); max-width: 700px; }

/* ---------- Final CTA / footer ---------- */
.final-cta {
  background: var(--black);
  color: var(--white);
  text-align: center;
  padding: 100px 0;
  border-bottom: 1px solid var(--gray-4);
}
.final-cta p { color: var(--gray-2); font-size: 1.1rem; }

/* ---------- Quote form ---------- */
.quote-form-wrap { max-width: 720px; margin: 46px auto 0; text-align: left; }
.quote-form-or {
  text-align: center;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--gray-on-dark);
  margin-bottom: 26px;
}
.quote-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.field { display: flex; flex-direction: column; gap: 7px; }
.field-full { grid-column: 1 / -1; }
.quote-form label {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.quote-form .opt { font-weight: 500; text-transform: none; letter-spacing: 0.02em; color: var(--gray-on-dark); }

/* SMS consent checkbox.
   "Clear and conspicuous" is the standard this has to meet, so it deliberately
   opts out of `.quote-form label` above — uppercase 0.82rem with 0.1em tracking
   is right for a field name and wrong for something a customer is agreeing to.
   It also has to escape `.quote-form input`'s width:100%, which would stretch
   the box across the whole row. */
.consent-check {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-size: 0.9rem;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  line-height: 1.55;
  cursor: pointer;
}
.quote-form .consent-check input[type="checkbox"] {
  width: 18px;
  flex: 0 0 18px;
  height: 18px;
  margin-top: 3px;
  padding: 0;
  /* The palette is black, white and greys — there is no accent token, and
     inventing one here would put a colour on the page that appears nowhere
     else. White reads as checked against the form's #111 fields. */
  accent-color: var(--white);
  cursor: pointer;
}
.consent-check a { color: var(--white); }
.quote-form input,
.quote-form textarea {
  font-family: var(--body);
  font-size: 1rem;
  padding: 12px 14px;
  border-radius: 6px;
  border: 1px solid var(--gray-4);
  background: #111;
  color: var(--white);
  width: 100%;
}
.quote-form input:hover:not(:disabled),
.quote-form textarea:hover:not(:disabled) { border-color: var(--gray-on-dark); }
/* Disabled is the default state until an endpoint is configured, so it has to
   read as unavailable rather than just look like an empty field. */
.quote-form input:disabled,
.quote-form textarea:disabled,
.quote-form button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.quote-form:has(input:disabled) label { opacity: 0.55; }
.quote-form textarea { resize: vertical; }
.quote-form input[type="file"] { padding: 10px 12px; cursor: pointer; }
.quote-form input[type="file"]::file-selector-button {
  font-family: var(--heading);
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  margin-right: 12px;
  padding: 7px 15px 5px;
  border: 1px solid var(--white);
  border-radius: 4px;
  background: transparent;
  color: var(--white);
  cursor: pointer;
}
.quote-form-actions { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 4px; }
.quote-form-status { font-size: 0.92rem; color: var(--gray-2); text-align: left; }
.quote-form-status.is-error { color: #ff9b9b; }

/* ---------- Per-field validation ----------
   #ff9b9b rather than a saturated red: this sits on #111, where pure red runs
   about 4:1 and reads as a glow rather than text. The same value is already
   used by .quote-form-status.is-error, so the two agree.

   The message is not the only signal. Colour alone fails anyone who cannot
   distinguish it, so the field also takes a visible border change and
   aria-invalid, which is what a screen reader announces. */
.field-error {
  font-size: 0.85rem;
  line-height: 1.4;
  color: #ff9b9b;
  margin: 0;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 500;
}
.quote-form input[aria-invalid="true"],
.quote-form textarea[aria-invalid="true"] {
  border-color: #ff9b9b;
}
/* `hidden` has to be restated: .field is display:flex, and a flex container's
   children ignore the UA `[hidden] { display: none }` the same way .pair-grid
   does. Without this the empty <p> holds a gap under every field. */
.field-error[hidden] { display: none; }
/* Honeypot — hidden from people, still reachable by bots. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

@media (max-width: 680px) {
  .quote-form { grid-template-columns: 1fr; }
}

/* ---------- 404 ----------
   The markup on both 404 pages has always asked for a DARK section:
   btn-light, btn-outline-light and sms-note-dark are all white-on-dark
   treatments. The rules were never written, so `.nf` had no background and
   the page rendered white — which made `.btn-outline-light` white text on
   white and the only text CTA on the page completely invisible.

   Nobody saw it because the page also shipped relative head assets, so it had
   no stylesheet at all and an unstyled 404 was indistinguishable from a
   half-styled one. Fixing the asset paths is what exposed this.

   Padding clears the fixed nav the same way .hero does, because .nf is the
   first thing under it and the h1 was sitting behind the header. */
.nf {
  background: var(--black);
  color: var(--white);
  min-height: 100vh;
  padding: calc(var(--nav-h) + 72px) 24px 88px;
  text-align: center;
}
/* No inner wrapper in the markup, so the measure is set on the children. */
.nf > * { max-width: 620px; margin-left: auto; margin-right: auto; }
.nf > * + * { margin-top: 18px; }
.nf h1 { color: var(--white); }
.nf > p { color: var(--gray-2); }
/* Oversized and recessive: it is decoration, and it is aria-hidden in the
   markup precisely so a screen reader does not announce a number twice. */
.nf-code {
  font-family: var(--heading);
  font-size: clamp(5rem, 20vw, 11rem);
  line-height: 0.85;
  color: var(--gray-4);
}
.nf .sms-note-dark { color: var(--gray-on-dark); }

.footer {
  background: var(--black);
  color: var(--gray-on-dark);
  padding: 56px 0 48px;
  text-align: center;
  font-size: 0.9rem;
}
/* The footer lockup is the same mark, larger and centred. `.footer` is
   text-align:center, so the flex row needs justify-content to match. */
.footer-brandmark {
  justify-content: center;
  gap: 15px;
  margin-bottom: 22px;
}
.footer-brandmark .brandmark-icon { width: 46px; height: 46px; }
.footer-brandmark .brandmark-top { font-size: 0.72rem; margin-bottom: 6px; }
.footer-brandmark .brandmark-main { font-size: 2.1rem; }
/* The two stacked lines are left-aligned to each other inside a centred row —
   inheriting the footer's text-align:center would ragged them against the
   icon. */
.footer-brandmark .brandmark-text { text-align: left; }
.footer-copy { margin-top: 18px; font-size: 0.8rem; }

/* The phone number, tappable, sized up from the surrounding footer text
   because it is the one line here anybody is trying to act on. 44px min-height
   on the anchor so the tap target clears the touch minimum without the text
   itself having to be that tall. */
.footer-phone { margin-top: 16px; font-size: 1.15rem; font-weight: 600; }
.footer-phone a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 4px;
}

/* ---------- Social profiles ----------
   Icon-only links. The 44px box is the hit target, not the glyph: the icons are
   22px and the padding does the rest, so the row still meets the touch-target
   minimum without the icons looking oversized against the small footer text.

   `list-style: none` and the flex row are both required — .footer is
   text-align:center, which centres the text but leaves the markers. */
.footer-social {
  list-style: none;
  margin: 26px 0 0;
  padding: 0;
  display: flex;
  justify-content: center;
  gap: 8px;
}
.footer-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--gray-on-dark);
  /* The .footer a:not(.brandmark) rule underlines links in running text. An
     underline under an icon is a stray dash, so it is turned off here. */
  text-decoration: none;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.footer-social svg { width: 22px; height: 22px; }
.footer-social a:hover,
.footer-social a:focus-visible {
  color: var(--black);
  background: var(--white);
}
@media (prefers-reduced-motion: reduce) {
  .footer-social a { transition: none; }
}

/* ---------- Links in running text ----------
   These had no rule at all and fell back to the browser default: #0000EE, which
   on the black footer is about 2.3:1 — and #551A8B once visited, which is worse.
   The links it applies to are Terms and Privacy Policy, the two a customer
   actually goes looking for, so being barely readable is the wrong place for it.

   The other site has the same gap. It is a real defect there rather than a style
   choice, so it is fixed here rather than cloned.

   Scoped rather than a global `a` rule: the nav, the buttons and the consent
   checkboxes all colour their own links already, and a global rule would fight
   them for no gain. `.container-narrow` is the legal pages and the FAQ — light
   ground, so black.

   The :not() is load-bearing. The footer wordmark is an <a> too, and without
   the exclusion the whole lockup gets underlined. */
.footer a:not(.brandmark) {
  color: var(--white);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.footer a:not(.brandmark):hover { color: var(--gray-2); }

/* Links in running text inside a narrow column.
   ── Two exclusions, both of which shipped as invisible text ──────────────
   This was `.container-narrow a`, unqualified, and it was right for the only
   pages that used the class: terms and privacy, which are light, all prose,
   and have no buttons. /plano.html was the first page to put a BUTTON and a
   DARK section inside a narrow column, and it broke both ways at once —
   `color: var(--black)` beats `.btn-solid`'s white on specificity, so the two
   primary CTAs rendered as unlabelled black rectangles, and the same black
   landed on black in every .section-dark, so three body links were there,
   underlined, and unreadable.
   Neither is visible in the markup, and both are obvious in a screenshot. */
.container-narrow a:not(.btn) {
  color: var(--black);
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* A button carries its own ground and its own text colour; it is not prose. */
.container-narrow a:not(.btn):hover { opacity: 0.7; }
.section-dark .container-narrow a:not(.btn) { color: var(--white); }

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .hero-inner, .about-wrap { grid-template-columns: 1fr; gap: 40px; }
  .featured-grid, .cards-3 { grid-template-columns: 1fr 1fr; }
  .steps { grid-template-columns: 1fr 1fr; }
  .pricing-grid, .area-grid { grid-template-columns: 1fr; }
}

@media (max-width: 680px) {
  .section { padding: 68px 0; }
  .nav-links, .nav-cta { display: none; }
  .nav-toggle { display: flex; margin-left: auto; }
  /* CSS-only open state — no JavaScript involved. */
  .nav-toggle-input:checked ~ .nav-mobile {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 24px 24px;
    background: var(--black);
    border-top: 1px solid var(--gray-4);
  }
  /* Hamburger morphs into an X when open. */
  .nav-toggle-input:checked ~ .nav-inner .nav-toggle span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
  .nav-toggle-input:checked ~ .nav-inner .nav-toggle span:nth-child(2) { opacity: 0; }
  .nav-toggle-input:checked ~ .nav-inner .nav-toggle span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }
  /* Full-width CTAs are the mobile convention and a bigger tap target. */
  .cta-row .btn { width: 100%; }
  .nav-mobile a {
    color: var(--white);
    text-decoration: none;
    font-family: var(--heading);
    font-size: 1.3rem;
    letter-spacing: 0.06em;
    padding: 10px 0;
  }
  /* The language switcher inside the open mobile menu.
     `align-self: flex-start` rather than the desktop pill's plain padding:
     .nav-mobile is a flex COLUMN, so a bordered element stretches the full
     width and reads as a primary button competing with the CTA below it.
     Shrinking it to its own text keeps it a control without that weight.

     This is the surface that matters most here — the QR code on the van lands
     people on a phone, so for most visitors the mobile menu IS the switcher. */
  .nav-mobile .lang-switch {
    align-self: flex-start;
    border: 1px solid rgba(255, 255, 255, 0.45);
    border-radius: 999px;
    padding: 6px 16px 4px;
    margin: 6px 0;
    font-size: 1.1rem;
  }
  .nav-mobile .btn { margin-top: 10px; }
  .featured-grid, .cards-3, .steps { grid-template-columns: 1fr; }
  .area-list ul { grid-template-columns: 1fr 1fr; }
  .btn-lg { font-size: 1.15rem; padding: 14px 26px 11px; }
  .trust-bar { gap: 8px 22px; }
}

/* The wordmark is the widest single thing in the nav bar and it cannot wrap —
   "HEADLIGHT RESTORATION" on one line is the whole point of the lockup. On a
   narrow phone it has to share 24px-padded space with the hamburger, so it
   steps down twice rather than colliding with it.

   The old <img> logo needed none of this: a fixed-height image just got
   narrower with its aspect ratio. Type does not. */
@media (max-width: 520px) {
  .brandmark { gap: 9px; }
  .brandmark-icon { width: 26px; height: 26px; }
  .brandmark-main { font-size: 1.2rem; }
  .brandmark-top { font-size: 0.52rem; letter-spacing: 0.26em; margin-right: -0.26em; }
  .footer-brandmark .brandmark-main { font-size: 1.7rem; }
  .footer-brandmark .brandmark-icon { width: 38px; height: 38px; }
  .footer-brandmark .brandmark-top { font-size: 0.62rem; }
}

@media (max-width: 380px) {
  .brandmark-icon { width: 22px; height: 22px; }
  .brandmark-main { font-size: 1.04rem; }
  .footer-brandmark .brandmark-main { font-size: 1.45rem; }
}


/* ---------------------------------------------------------------------------
   The instant check — /check.html
   ---------------------------------------------------------------------------
   Lifted unchanged from the retired site's stylesheet. Every custom
   property it uses (--black, --body, --gray-1, --gray-2, --gray-on-light,
   --heading, --radius, --white) is already defined by this file, which is why
   it needed no rewriting: the two sites were always the same design under
   different names.

   `.qr-block` further up predates this and had no image to show. It does now.
   --------------------------------------------------------------------------- */
.check-list { list-style: none; margin-top: 18px; display: grid; gap: 16px; }
.check-list li { padding-left: 30px; position: relative; color: var(--gray-2); font-size: 0.98rem; }
.check-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 5px;
  width: 14px; height: 8px;
  border-left: 2.5px solid var(--white);
  border-bottom: 2.5px solid var(--white);
  transform: rotate(-45deg);
}
.check-list strong { color: var(--white); }
.check-inner { max-width: 720px; }
.check-form {
  margin-top: 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.check-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 40px 24px;
  border: 2px dashed var(--gray-2);
  border-radius: var(--radius);
  background: var(--gray-1);
  cursor: pointer;
  text-align: center;
  transition: border-color .15s ease, background .15s ease;
}
.check-drop:focus-within { border-color: var(--black); background: #efefef; }
/* Applied while a file is dragged over. */
.check-drop.is-over { border-color: var(--black); background: #e8e8e8; }
.check-drop-icon { color: var(--gray-on-light); line-height: 0; }
.check-drop-main { font-weight: 600; font-size: 17px; }
.check-drop-sub { color: var(--gray-on-light); font-size: 14px; }
.check-preview {
  display: flex;
  gap: 16px;
  align-items: center;
  padding: 12px;
  border: 1px solid var(--gray-2);
  border-radius: var(--radius);
}
.check-preview img {
  width: 96px; height: 96px;
  object-fit: cover;
  border-radius: 6px;
  flex: none;
}
.check-preview-side { min-width: 0; }
.check-filename {
  font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.check-link {
  background: none; border: 0; padding: 0;
  font: inherit; font-size: 14px;
  color: var(--gray-on-light);
  text-decoration: underline;
  cursor: pointer;
}
.check-link:hover { color: var(--black); }
/* Contact fields on the instant check.
   The quote form's equivalents are styled under `.quote-form input`, which sets
   a #111 background and a white checkbox accent for a form sitting on black.
   This one sits on the light section, so none of that carries over and the
   selectors below are the light-ground twin rather than a reuse. Same shape,
   same 2-up grid, inverted ground. */
.check-fields {
  display: grid;
  /* ONE column is the base, and the 2-up is the override at the bottom of this
     file. It was the other way round until 9 August 2026 with no override at
     all, so "Your name" and "Mobile number" sat in ~145px columns on a 375px
     phone — on the page most likely to be opened from a QR code on a van. The
     quote form has the identical grid and always collapsed at 680px; this one
     was simply missed. */
  grid-template-columns: 1fr;
  gap: 14px;
}
.check-form label {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.check-form .opt { font-weight: 500; text-transform: none; letter-spacing: 0.02em; color: var(--gray-on-light); }
/* ALL of them, not just email.
   Until 9 August 2026 this selector named `email` alone, so `#check-name` and
   `#check-phone` rendered as unstyled browser defaults — no width, and Safari's
   13.33px UA font size. Anything under 16px makes iOS ZOOM THE PAGE when the
   field takes focus, and the visitor is then panning a zoomed form one-handed.

   16px is written literally rather than as 1rem. `body` is 16px today, so the
   two are equal — but a future root-size change would silently reintroduce the
   zoom, and this is not the file anyone would think to check. */
.check-form input[type="text"],
.check-form input[type="tel"],
.check-form input[type="email"],
.check-contact input[type="text"],
.check-contact input[type="tel"],
.check-contact input[type="email"] {
  font-family: var(--body);
  font-size: 16px;
  min-height: 48px;
  width: 100%;
  padding: 12px 14px;
  border-radius: 6px;
  border: 1px solid var(--gray-2);
  background: var(--white);
  color: var(--black);
}
.check-form input[type="text"]:focus-visible,
.check-form input[type="tel"]:focus-visible,
.check-form input[type="email"]:focus-visible,
.check-contact input[type="text"]:focus-visible,
.check-contact input[type="tel"]:focus-visible,
.check-contact input[type="email"]:focus-visible {
  outline: 2px solid var(--black);
  outline-offset: 1px;
}
/* `.consent-check` itself is ground-agnostic, but the two rules that follow it
   are not: the checkbox accent and the link colour are both white for the dark
   form. Overridden here rather than made conditional there, so the quote form
   keeps working if this section is ever removed. */
.check-form .consent-check {
  /* Escapes `.check-form label`'s uppercase field-name treatment above, which is
     right for a field name and wrong for something a customer is agreeing to.
     "Clear and conspicuous" is the standard this has to meet. */
  font-size: 0.9rem;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}
.check-form .consent-check input[type="checkbox"] {
  width: 18px;
  flex: 0 0 18px;
  height: 18px;
  margin-top: 3px;
  padding: 0;
  accent-color: var(--black);
  cursor: pointer;
}
.check-form .consent-check a { color: var(--black); }
/* `.sms-note` is 46ch with a 14px top margin — right for fine print tucked under
   a button, wrong here where it sits in a 16px-gap flex column beside full-width
   fields. Without this the margin stacks on the gap and the consent text wraps
   about half as narrow as the inputs above it. */
.check-form .sms-note { margin-top: 0; max-width: none; }
.check-submit { align-self: flex-start; }
.check-submit:disabled { opacity: .4; cursor: not-allowed; }
.check-privacy { font-size: 13px; color: var(--gray-on-light); }
/* ---- result panel ---- */

.check-result { margin-top: 28px; }
.check-panel {
  border: 1px solid var(--gray-2);
  border-left: 4px solid var(--black);
  border-radius: var(--radius);
  padding: 24px;
  background: var(--white);
}
/* "Needs a human" reads differently from a job — amber rather than black, so
   the two are distinguishable at a glance and not only by their words. */
.check-panel.is-inspect { border-left-color: #b45309; }
.check-panel h3 {
  font-family: var(--heading);
  font-size: 30px;
  line-height: 1.1;
  letter-spacing: .5px;
}
.check-panel-detail { margin-top: 8px; }
.check-steps {
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.check-steps li {
  counter-increment: step;
  display: flex;
  gap: 12px;
  align-items: baseline;
}
/* Numbered because these really are sequential — you cannot polish before you
   sand. The order is Frank's. */
.check-steps li::before {
  content: counter(step);
  font-family: var(--heading);
  font-size: 15px;
  color: var(--white);
  background: var(--black);
  border-radius: 50%;
  width: 24px; height: 24px;
  flex: none;
  display: grid; place-items: center;
  transform: translateY(2px);
}
.check-warnings {
  margin: 20px 0 0;
  padding: 14px 16px;
  background: #fdf6ec;
  border-radius: 6px;
  display: flex; flex-direction: column; gap: 8px;
  font-size: 15px;
}
.check-caveat {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--gray-2);
  font-size: 14px;
  color: var(--gray-on-light);
}
.check-cta { margin-top: 20px; display: flex; flex-wrap: wrap; gap: 12px; }
/* ---- working / error ---- */

.check-working {
  display: flex; align-items: center; gap: 12px;
  padding: 20px 24px;
  border: 1px solid var(--gray-2);
  border-radius: var(--radius);
}
.check-spinner {
  width: 20px; height: 20px; flex: none;
  border: 2px solid var(--gray-2);
  border-top-color: var(--black);
  border-radius: 50%;
  animation: check-spin .8s linear infinite;
}
.check-error {
  padding: 20px 24px;
  border: 1px solid var(--gray-2);
  border-left: 4px solid #b45309;
  border-radius: var(--radius);
}
.check-error p + p { margin-top: 10px; }
/* ── Mobile first, from here down ──────────────────────────────────────────
   These four rules used to sit here AND be repeated verbatim inside a
   `@media (max-width: 560px)` block at the end of the file. Because they came
   later in the cascade, the unconditional copies won at every width and the
   desktop values above them were dead code — the page was already rendering its
   mobile layout on a 27-inch monitor.
   Kept as the base, which is what they always effectively were, with the desktop
   values restored under a min-width query below. */
.check-drop { padding: 28px 16px; }
.check-submit { align-self: stretch; text-align: center; width: 100%; }
.check-panel { padding: 18px; }
.check-panel h3 { font-size: 26px; }

/* The two photo slots. Stacked on a phone, side by side once there is room. */
.check-slots { display: grid; grid-template-columns: 1fr; gap: 14px; }
.check-slot-label {
  margin: 0 0 6px;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.check-hint { margin: 4px 0 0; font-size: 0.95rem; color: var(--gray-on-light); }
.check-lede { margin-bottom: 20px; }

.check-contact { margin-top: 28px; display: flex; flex-direction: column; gap: 16px; }
.check-contact-h { margin: 0; }
.check-contact-sub { margin: 0; color: var(--gray-on-light); }
.check-fields-h {
  margin: 4px 0 -6px;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* Year is a fixed column; make and model share the rest. Model drops to its own
   row on the narrowest phones rather than being squeezed to nothing. */
.check-vehicle { display: grid; gap: 10px; grid-template-columns: 5.5rem 1fr; }
.check-vehicle .field:last-child { grid-column: 1 / -1; }
.check-contact label {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.check-contact .opt { font-weight: 500; text-transform: none; letter-spacing: 0.02em; color: var(--gray-on-light); }
.check-handoff { margin-top: 24px; }
.check-panel-side {
  margin: 0 0 4px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gray-on-light);
}
.check-explainer { margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--gray-2); }
.check-explainer h3 { margin: 0 0 8px; }
.check-explainer p { margin: 0; color: var(--gray-on-light); max-width: 60ch; }

/* ---------- The check page's proof block ----------
   Three before/after comparisons above the form, so the visitor sees the work
   before being asked for their photos and their number. .featured-grid and .ba
   do the layout and the drag; everything here is spacing and the heading. */
.check-proof { margin-top: 28px; }
.check-proof-h {
  margin: 0 0 14px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray-on-light);
}
/* .featured-grid carries a 40px bottom margin for the homepage, where a filter
   row follows it. Here the trust bar supplies its own spacing. */
.check-proof-grid { margin-bottom: 0; gap: 14px; }

/* ── The proof block must not push the form off the phone ──────────────────
   .featured-grid collapses to ONE column under 680px, which is right on the
   homepage and wrong here. Three 4:3 sliders stacked full-width came to about
   1300px, and measured on a phone that put the first photo slot 1600px down —
   three screens below the fold.

   That is the exact failure this page was built to avoid. The note above the
   lede in check.html records it: a three-line paragraph once pushed both photo
   slots below the fold, "and the thing the sticker promised was the thing they
   had to scroll for". Proof that costs the visitor the form is not proof, it
   is a longer bounce.

   Two across instead, at roughly 265px each. Measured on the same page that
   read 1600px: the block drops to ~306px and the first photo slot to 578px,
   one short scroll rather than three screens.

   The third comparison is desktop-only. Sedan and truck are the two most of
   DFW is driving, and the pair that survives is the pair a phone can show at
   a size worth looking at. Its images are lazy as well as hidden, so a phone
   should not pay for them either. */
@media (max-width: 680px) {
  .check-proof-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .check-proof-extra { display: none; }
}
/* .trust-bar is a DARK-BACKGROUND component and this page is white.
   Reusing it for the flex row was right; inheriting its colours was not —
   unstyled it renders #d9d9d9 text with white <strong>, which on white is a
   row of invisible words and was exactly how it first shipped here. Every
   colour .trust-bar sets is therefore restated for a light background.

   The 34px column gap is set for a full-width hero, too. In a 720px column
   with three items it wraps awkwardly, so this tightens it. */
.check-trust {
  margin-top: 22px;
  gap: 8px 24px;
  color: var(--gray-on-light);
  border-top-color: var(--gray-2);
}
.check-trust strong { color: var(--black); }

/* ---------- Objections, below the form ---------- */
/* --gray-2, matching .check-explainer above it. --gray-4 is #2a2a2a, a
   near-black meant for dark panels, and draws a hard rule across a white page. */
.check-objections {
  margin-top: 36px;
  padding-top: 24px;
  border-top: 1px solid var(--gray-2);
  display: grid;
  gap: 22px;
}
.check-objection h4 {
  margin: 0 0 6px;
  font-size: 1rem;
  letter-spacing: 0.01em;
}
.check-objection p {
  margin: 0;
  color: var(--gray-on-light);
  max-width: 60ch;
  font-size: 0.96rem;
  line-height: 1.6;
}

/* One review. .quote-grid and .quote-card style it; this only spaces it and
   keeps the single card from stretching the full 720px. */
.check-voice { margin-top: 32px; }

/* The no-JavaScript fallback. The form above is .js-only and stays hidden, so
   without this the page renders a nav, a footer and nothing between them. */
.check-noscript { padding: 56px 0; text-align: center; }
.check-noscript h2 { margin: 0 0 10px; }
.check-noscript p { margin: 0 auto 18px; color: var(--gray-on-light); max-width: 50ch; }

/* ── `hidden` has to be re-stated for anything given a display ─────────────
   A class rule setting `display` beats the UA stylesheet's
   `[hidden] { display: none }`, so an element with the attribute renders anyway.
   This file already knew: `.pair-grid[hidden]` and `.field-error[hidden]` exist
   for exactly this, and the comment above the second one spells it out.

   `.check-preview` never got the same treatment, and the bug was LIVE — the
   instant check has been rendering an empty bordered box with a broken-image
   icon under the drop zone, on page load, for anyone who visited. It is
   invisible in review because the box looks like part of the design until you
   notice the alt text.

   `.check-form` was caught by the SAME trap a few hours later: hiding the form
   after a successful send left it on screen underneath the confirmation, because
   it sets `display: flex` too. Three times in one file is not carelessness, it
   is the shape of the bug — `hidden` looks like it works, and the element that
   proves otherwise is one nobody hides until the day they do.

   Every panel this feature can hide is listed, and the parity test derives the
   list from the markup rather than trusting this comment to stay complete. */
.check-form[hidden],
.check-preview[hidden],
.check-handoff[hidden],
.check-result[hidden],
.check-slot [hidden] { display: none; }

/* The whole label row is the target, not the 22px box inside it. */
.check-form .consent-check,
.check-contact .consent-check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 44px;
  padding: 4px 0;
}
.check-form .consent-check input[type="checkbox"],
.check-contact .consent-check input[type="checkbox"] {
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
}
.check-cta .btn { width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .check-spinner { animation-duration: 2.4s; }
}

/* ── Desktop. Everything above is what a phone gets. ───────────────────── */
@media (min-width: 561px) {
  .check-fields { grid-template-columns: 1fr 1fr; gap: 18px; }
  .check-slots { grid-template-columns: 1fr 1fr; gap: 18px; }
  .check-vehicle { grid-template-columns: 5.5rem 1fr 1fr; }
  .check-vehicle .field:last-child { grid-column: auto; }
  .check-drop { padding: 40px 24px; }
  .check-submit { align-self: flex-start; width: auto; }
  .check-panel { padding: 24px; }
  .check-panel h3 { font-size: 30px; }
  .check-cta .btn { width: auto; }
}
