/* ═══════════════════════════════════════════════════════════════════
   Central Spring Service — exact duplicate of mockup 3A
   "Shop Floor — Navy + Slab Type". Tokens, classes and values are
   carried over verbatim from the mockup's design system; the
   responsive layer at the bottom only adapts layout below desktop.
   ═══════════════════════════════════════════════════════════════════ */

/* — fonts (self-hosted, extracted from the mockup deliverable) — */
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/barlow-400-viet.woff2") format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/barlow-400-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/barlow-400-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 500; font-display: swap; src: url("assets/fonts/barlow-500-viet.woff2") format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 500; font-display: swap; src: url("assets/fonts/barlow-500-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 500; font-display: swap; src: url("assets/fonts/barlow-500-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 700; font-display: swap; src: url("assets/fonts/barlow-700-viet.woff2") format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 700; font-display: swap; src: url("assets/fonts/barlow-700-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Barlow'; font-style: normal; font-weight: 700; font-display: swap; src: url("assets/fonts/barlow-700-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/barlowcond-400-viet.woff2") format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/barlowcond-400-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/barlowcond-400-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 600; font-display: swap; src: url("assets/fonts/barlowcond-600-viet.woff2") format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 600; font-display: swap; src: url("assets/fonts/barlowcond-600-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Barlow Condensed'; font-style: normal; font-weight: 600; font-display: swap; src: url("assets/fonts/barlowcond-600-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Bevan'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/bevan-viet.woff2") format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Bevan'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/bevan-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Bevan'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/bevan-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rye'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/rye-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rye'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/rye-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rubik Dirt'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/rubikdirt-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rubik Dirt'; font-style: normal; font-weight: 400; font-display: swap; src: url("assets/fonts/rubikdirt-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Rubik'; font-style: normal; font-weight: 300 900; font-display: swap; src: url("assets/fonts/rubik-var-latin-ext.woff2") format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Rubik'; font-style: normal; font-weight: 300 900; font-display: swap; src: url("assets/fonts/rubik-var-latin.woff2") format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Oswald'; font-style: normal; font-weight: 200 700; font-display: swap; src: url("assets/fonts/oswald-var-latin.woff2") format('woff2'); }

/* — tokens: design system base with the 3A navy overrides baked in — */
:root {
  --color-bg: #f4f4f6;
  --color-surface: #dfdfe3;
  --color-text: #1d1f20;
  --color-accent: #2c3157;
  --color-accent-2: #728fab;
  --color-divider: rgba(44,49,87,0.22);

  --color-neutral-100: #f5f5f8;
  --color-neutral-200: #e7e7ea;
  --color-neutral-300: #d4d4d7;
  --color-neutral-400: #b7b7ba;
  --color-neutral-500: #98989b;
  --color-neutral-600: #6e6e71; /* darkened from #7a7a7d, 2026-08-25 -- the
    lighter value was 4.28:1 on white, just under the 4.5:1 WCAG AA floor
    for the small (11-12.5px) caption/label text this token is used for
    sitewide; this value clears it (~5.1:1) */
  --color-neutral-700: #5d5d60;
  --color-neutral-800: #424244;
  --color-neutral-900: #2b2b2d;

  --color-accent-100: #ecedf3;
  --color-accent-200: #d3d6e4;
  --color-accent-300: #a9aecb;
  --color-accent-400: #7f86ae;
  --color-accent-500: #545c8a;
  --color-accent-600: #363c6b;
  --color-accent-700: #2c3157;
  --color-accent-800: #232744;
  --color-accent-900: #1b1f36;

  /* Rich picked Oswald (2026-08-19) for nav, labels, and small caps —
     industrial gothic condensed against the Rubik Dirt display face.
     Body text stays clean Rubik. */
  --font-heading: "Oswald", system-ui, sans-serif;
  --font-heading-weight: 600;
  --font-body: "Rubik", system-ui, sans-serif;
  /* Display face sitewide (Rich, 2026-08-19): Rubik Dirt, the stamped
     asphalt look matching the SERVICE word in the badge. Supersedes Rye. */
  --font-display: 'Rubik Dirt', Georgia, serif; /* stamped brand face: hero H1 + section H2s ONLY (Rich, 2026-09-03 — it costs ~1.5s of phone main thread, so it stays on the few big words) */
  --font-title: 'Oswald', 'Rubik', sans-serif;   /* everything smaller: nav, stats, card titles, labels, lightbox titles */

  --space-1: 3.4px;
  --space-2: 6.8px;
  --space-3: 10.2px;
  --space-4: 13.6px;
  --space-6: 20.4px;
  --space-8: 27.2px;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;

  --shadow-sm: 0 1px 2px color-mix(in srgb, #2b2b2d 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2b2b2d 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2b2b2d 22%, transparent);
}

/* — base, verbatim from the design system — */
*, *::before, *::after { box-sizing: border-box; }
/* Reserve the scrollbar's width permanently, whether or not it's currently
   showing. Without this, locking scroll (body.inspect-open, body.is-loading)
   removes the scrollbar track and every centered element re-centers into the
   newly-widened viewport — the whole page visibly jumps right (Rich,
   2026-08-21). Reserving the gutter always means removing the scrollbar
   later changes nothing about the available width. */
/* The reserved gutter above paints with html's own background, not body's —
   left unset, that defaults to plain white and shows as a thin pale strip
   down the right edge of the page (Rich, 2026-08-21). Match it to the page. */
html { scroll-behavior: smooth; scrollbar-gutter: stable; background: var(--color-bg); }
body {
  margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400;
  background: var(--color-bg); color: var(--color-text);
  font-family: var(--font-body);
  overflow-x: hidden;
}
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent-700); text-decoration: none; text-underline-offset: 3px; }
a:hover { color: var(--color-accent-800); }
img { display: block; max-width: 100%; }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* Phone numbers and emails never wrap to a second line, anywhere on the
   site — permanent rule (Rich, 2026-08-24). One line breaking mid-number
   ("(570) / 225-1143") reads as broken, not just cramped. Catches every
   tel:/mailto: link sitewide, present and future, in one place instead
   of patching each occurrence by hand. */
a[href^="tel:"], a[href^="mailto:"] { white-space: nowrap; }

/* — blueprint frame + registration corners, verbatim — */
.blueprint {
  position: relative;
  border: 1px solid var(--color-divider);
  border-radius: 0;
}
.blueprint > .corner {
  position: absolute; width: 11px; height: 11px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.blueprint > .corner::before, .blueprint > .corner::after {
  content: ""; position: absolute; background: currentColor;
}
.blueprint > .corner::before { left: 5px; top: 0; width: 1px; height: 100%; }
.blueprint > .corner::after  { top: 5px; left: 0; width: 100%; height: 1px; }
.blueprint > .corner.tl { top: -6px; left: -6px; }
.blueprint > .corner.tr { top: -6px; right: -6px; }
.blueprint > .corner.bl { bottom: -6px; left: -6px; }
.blueprint > .corner.br { bottom: -6px; right: -6px; }

/* — buttons, verbatim (incl. the square blueprint overrides) — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none; white-space: nowrap;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 15px; line-height: 1.2; color: var(--color-text);
  background: transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: 0; border: 1px solid var(--color-divider);
  transition: background-color 0.18s ease, color 0.18s ease;
}
.btn svg { display: block; }
.btn-primary { background: var(--color-accent); color: var(--color-bg); border-color: var(--color-accent); }
.btn-primary:hover { background: var(--color-accent-600); color: #fff; }
.btn-primary:active { background: var(--color-accent-700); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
/* CORRECTED 2026-08-25 -- this used to be Google's own brand blue
   (#4285F4), reasoning that it ties the button's color to where it's
   going. Rich: "horrendous and doesn't follow any design standards
   whatsoever... make the button the same blue as the website." A
   button's color follows the SITE's palette, not the destination's --
   the little "G" mark already does the job of signaling where this
   goes. Same navy token every other solid button on the site uses. */
.btn-google { background: var(--color-accent); color: #fff; border-color: var(--color-accent); }
.btn-google:hover { background: var(--color-accent-600); border-color: var(--color-accent-600); }
.btn-google:active { background: var(--color-accent-800); border-color: var(--color-accent-800); }
.btn-block { width: 100%; margin-top: var(--space-2); }

/* the hero's gold button keeps its inline colors; give it a matching hover */
.btn[style*="background: #f2b307"]:hover { background: #d99f04 !important; }
.btn[style*="border-color: rgba(255,255,255,0.5)"]:hover { background: rgba(255,255,255,0.1); color: #fff; }
/* dark-background buttons (white text) need a light corner mark, not the
   default dark one — otherwise it's invisible against navy/gold-on-dark */
.btn[style*="color: #fff"] > .corner { color: rgba(255,255,255,0.55); }

/* — forms, verbatim — */
.field > label {
  display: block; font-size: 15px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 15px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: 0;
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }

/* — tables, verbatim — */
.table { width: 100%; border-collapse: collapse; font-size: 15px; }
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
}
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

/* — tags, verbatim — */
.tag {
  display: inline-flex; align-items: center; font-size: 15px;
  letter-spacing: 0.02em; padding: 3px 10px; border-radius: 0;
}

/* ═══════════════════════════════════════════════════════════════════
   Live-site layer (not in the mockup canvas): fold sizing, content
   centering on wide screens, light motion, mobile navigation.
   ═══════════════════════════════════════════════════════════════════ */

/* Above-the-fold: utility bar + masthead + hero + stats bar always end
   exactly at the bottom of the viewport on desktop. */
/* the sticky header now sits above .fold in normal flow, so the fold
   (hero + stats bar) fills the viewport minus the header's live height */
.fold { display: flex; flex-direction: column; min-height: calc(100dvh - var(--header-h, 160px)); }
/* flex grows the hero so the stats bar lands exactly at the viewport
   bottom; the automatic flex minimum (content size) stops it from ever
   clipping the finder panel on short screens. At the mockup's natural
   932px stack height the hero is the mockup's exact 680px. */
.fold .hero { flex: 1 1 auto; }
.fold .hero > .hero-grid { min-height: 100%; height: auto; }

/* THE 10% RULE (Rich, 2026-08-21, revised same day from 15%: the wider
   gutter was squashing the photo cards): everything a visitor reads or
   clicks sits inside a 10% gutter on each side at every desktop
   resolution — no fixed content cap, so the site fills the screen it is
   on. Backgrounds and full-bleed call-to-action bands still run edge to
   edge. iPad and below run edge to edge with a thin 20px gutter. */
.px { padding-inline: 10% !important; }
@media (max-width: 1024px) { .px { padding-inline: 20px !important; } }

/* Small uppercase labels set in the heading font get a medium weight —
   Rubik 400 reads too plain where condensed 400 used to sit. Inline
   font-weight declarations still win where present. */
[style*="font-heading"] { font-weight: 500; }

/* Services grids (home + services page): card titles use the stamped
   display face. grid-auto-rows keeps every box the same height no
   matter how the titles wrap, and the reserved two-line title area
   keeps the text blocks aligned across cards. */
.services-grid { grid-auto-rows: 1fr; }
.services-grid .svc-card > div:nth-of-type(2) {
  /* Rich, 2026-09-03: card titles off the distressed face — thicker, plainer
     Oswald 700 (already the site's label face). Rubik Dirt stays on the
     hero + section headlines only. */
  font-family: 'Oswald', 'Rubik', sans-serif !important;
  font-weight: 700 !important;
  font-size: 24px !important;
  line-height: 1.12 !important;
  letter-spacing: 0.04em !important;
  min-height: 50px;
  display: flex;
  align-items: flex-end;
}

/* shop reel: overlay fades out while the commercial plays */
#reelOverlay { transition: opacity 0.4s ease; }
#playReel { transition: transform 0.2s ease, background-color 0.2s ease; }
#playReel:hover { transform: scale(1.06); background: rgba(255,255,255,0.08); }

/* Google Maps embeds — B&W to match the photo treatment, full color
   on hover so it's still a usable map */
.map-frame iframe {
  display: block; width: 100%; height: 240px; border: 0;
  filter: grayscale(1) contrast(1.05);
  transition: filter 0.35s ease;
}
.map-frame:hover iframe { filter: none; }
.contact-map iframe { height: 340px; }
/* Get directions under the footer map (27 Oct 2026) */
.footer-dir { display: flex; width: 100%; gap: 10px; margin-top: 12px; min-height: 52px; font-size: 17px; letter-spacing: 0.08em; text-transform: uppercase; color: #fff; border-color: rgba(255,255,255,0.45); }
.footer-dir .corner { color: rgba(255,255,255,0.6); }
.footer-dir:hover { background: #f2b307; border-color: #f2b307; color: #1b1f36; }

/* Quote form card stretches to match its neighbor column exactly —
   the what's-it-doing textarea absorbs the extra height, so the two
   columns always end on the same line with no dead space. */
.quote-card { display: flex; flex-direction: column; }
.quote-card .field-grow { flex: 1; display: flex; flex-direction: column; }
.quote-card .field-grow textarea { flex: 1; min-height: 90px; }

/* ═══════════════ loading screen ═══════════════
   Covers the page until the fonts are ready so there is never a flash
   of unstyled text. Gold leaf spring compresses like real suspension. */
#loader {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 30px;
  background: #1b1f36;
  opacity: 1;
  transition: opacity 0.45s ease;
}
#loader.is-done { opacity: 0; pointer-events: none; }
body.is-loading { overflow: hidden; }
.loader-logo {
  height: min(340px, 42vh); max-width: 82vw; width: auto; object-fit: contain;
  filter: invert(1); mix-blend-mode: screen;
}

/* the loading bar: a truck axle rolls the length of a road line,
   wheels turning, gold fill trailing behind it */
.loader-bar { position: relative; width: min(340px, 72vw); height: 36px; }
.loader-bar::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: rgba(255,255,255,0.22);
}
.loader-bar::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: #f2b307;
  transform-origin: left; transform: scaleX(0);
  animation: loader-fill 1.5s linear infinite;
}
.loader-axle-wrap {
  position: absolute; left: 0; bottom: 2px;
  width: calc(100% - 96px); height: 44px;
  animation: loader-travel 1.5s linear infinite;
}
.loader-axle { position: absolute; left: 0; bottom: -5px; width: 96px; height: 44px; }
.loader-axle .wheel {
  transform-box: fill-box; transform-origin: center;
  animation: loader-roll 0.75s linear infinite;
}
@keyframes loader-travel { from { transform: translateX(0); } to { transform: translateX(100%); } }
@keyframes loader-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes loader-roll { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .loader-bar::after, .loader-axle-wrap, .loader-axle .wheel { animation: none; }
  .loader-bar::after { transform: scaleX(1); }
  .loader-axle-wrap { transform: translateX(100%); }
}

/* light reveal on scroll */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.6s ease, transform 0.6s ease; }
.reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

.symptom { transition: background-color 0.15s ease; }


/* quote form send states */
.quote-sent { background: #f2b307 !important; border-color: #f2b307 !important; color: #1b1f36 !important; pointer-events: none; }
.quote-error { margin-top: 10px; font-size: 15px; color: #2c3157; }

/* brief gold pulse on the quote form when a symptom is carried in */
.form-flash { animation: formFlash 1.4s ease forwards; }
/* ── Book This Inspection lightbox ── */
.inspect-modal { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; padding: 24px; visibility: hidden; }
.inspect-modal.is-open { visibility: visible; }
/* 0.72 opacity + 3px blur still let heading-weight text behind the
   modal read through legibly enough to be mistaken for content
   inside it (Rich, 2026-08-24, reviews lightbox: "other testimonials
   are showing on the main screen, even though they're not even in
   focus" -- the page's own copy bleeding through the scrim, not an
   actual second review card). Darker and blurrier kills it outright. */
.inspect-scrim {
  position: absolute; inset: 0; background: rgba(15,18,40,0.9); backdrop-filter: blur(8px);
  opacity: 0; transition: opacity 0.4s ease;
}
.inspect-modal.is-open .inspect-scrim { opacity: 1; }
.inspect-panel {
  position: relative; width: 100%; max-width: 460px;
  background: #fff; padding: 30px 30px 26px; color: var(--color-text);
  opacity: 0; transform: translateY(16px) scale(0.97);
  transition: opacity 0.4s cubic-bezier(.2,.75,.2,1), transform 0.4s cubic-bezier(.2,.75,.2,1);
}
/* only scroll when the viewport is genuinely too short — on normal desktop
   heights the form content fits, and forcing overflow-y:auto unconditionally
   inside the centered flex wrapper produced a false ~6px scroll (a flexbox
   auto-height rounding quirk), not real overflow. */
@media (max-height: 700px) {
  .inspect-panel { max-height: calc(100vh - 32px); overflow-y: auto; overflow-x: hidden; scrollbar-gutter: stable; }
}
/* A tall-but-narrow phone (390x844, say) never trips the max-height gate
   above since its viewport is plenty tall -- but a panel like the reviews
   grid, 4 cards stacked in one column at that width, can still run
   longer than the screen (Rich, 2026-08-24: "opens up way longer than
   the screen on mobile"). Cap by width too, independent of height. */
@media (max-width: 700px) {
  .inspect-panel { max-height: calc(100vh - 32px); overflow-y: auto; overflow-x: hidden; scrollbar-gutter: stable; }
}
.inspect-modal.is-open .inspect-panel { opacity: 1; transform: translateY(0) scale(1); }
.inspect-x {
  position: absolute; top: 16px; right: 16px; width: 32px; height: 32px; display: grid; place-items: center;
  background: transparent; border: 1px solid var(--color-divider); color: var(--color-text);
  cursor: pointer; transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.inspect-x:hover { background: #2c3157; border-color: #2c3157; color: #fff; }
body.inspect-open { overflow: hidden; }
.inspect-sent { display: none; margin-top: 14px; font-size: 15px; color: #2c3157; background: rgba(242,179,7,0.14); border: 1px solid rgba(242,179,7,0.4); padding: 11px 14px; }
.inspect-sent.is-shown { display: block; }
.inspect-error { display: none; margin-top: 14px; font-size: 15px; color: var(--color-neutral-800); }
.inspect-error.is-shown { display: block; }
@media (prefers-reduced-motion: reduce) {
  .inspect-scrim, .inspect-panel { transition: none; }
}
@media (max-width: 560px) {
  .inspect-panel { padding: 26px 20px 22px; max-width: 100%; }
}

/* Reviews lightbox reuses .inspect-modal/.inspect-panel chrome (backdrop,
   open/close animation, short-viewport scroll) but needs its own panel
   width. One review card visible at a time via a carousel (reuses the
   .reviews-carousel component wholesale, wired up automatically since
   the JS finds every [data-reviews-carousel] on the page) instead of a
   grid -- was showing all 4 stacked, running "too big... almost
   touching the edge of your phone" (Rich, 2026-08-24). One card tall is
   dramatically shorter regardless of viewport, not just on mobile. */
.reviews-modal-panel { max-width: 460px; }
.reviews-modal-carousel .reviews-page { display: block; }
/* Panel is now short enough (one review card) that it almost never
   needs to scroll -- the scrollbar-gutter:stable it inherits from
   .inspect-panel was permanently reserving a strip down the right
   edge for a scrollbar that's essentially never there, reading as an
   uneven "scroll side" (Rich, 2026-08-24: "remove a scroll side. It
   shouldn't have a scroll side at all"). Drop the reservation; the
   overflow-y:auto safety net from .inspect-panel still catches the
   rare genuinely-short viewport, it just won't pre-claim the space. */
.reviews-modal-panel { scrollbar-gutter: auto; }
/* Drag already works everywhere (the carousel's own pointer-drag
   handling covers mouse drag and touch swipe alike) -- the arrows are
   redundant on every width, not just mobile (Rich, 2026-08-24, after
   first asking for mobile-only: "remove the arrows on the side of the
   testimonials on the lightbox" -- no width qualifier this time). Dots
   stay as the only visible position indicator/control. */
.reviews-modal-carousel .reviews-arrow { display: none; }

/* Hours lightbox: the live status chip re-used at full size, then the
   week laid out plainly with today picked out -- not a design flourish,
   just the one row someone actually came to check. */
.hours-modal-panel { max-width: 420px; }
.hours-table { width: 100%; border-collapse: collapse; }
.hours-table td {
  padding: 9px 4px; font-size: 15px; color: var(--color-neutral-800);
  border-bottom: 1px solid var(--color-divider);
}
.hours-table td:first-child { font-family: var(--font-heading); font-weight: 600; color: #2c3157; }
.hours-table td:last-child { text-align: right; }
.hours-table tr.is-today td { color: #2c3157; font-weight: 600; }
.hours-table tr.is-today td:first-child::after { content: " \2022 today"; font-weight: 400; font-size: 15px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-neutral-600); }
.hours-table tr:last-child td { border-bottom: none; }


@keyframes formFlash {
  0% { box-shadow: 0 0 0 3px rgba(242,179,7,0.95); }
  100% { box-shadow: 0 0 0 3px rgba(242,179,7,0); }
}
.symptom:hover { background: rgba(255,255,255,0.07) !important; }
.symptom[data-active="1"]:hover { background: rgba(242,179,7,0.16) !important; }

/* nav uses the stamped Rubik Dirt display face — matches the hero title */
.masthead-nav { font-family: var(--font-title) !important; font-weight: 700 !important; font-size: 22px !important; letter-spacing: 0.06em !important; }
.masthead-nav a { font-weight: 700; } /* Oswald is condensed: 22px/700 here is the same visual width the stamped face had at 18px (measured 2026-09-03) */
/* current page marked with the actual leaf-spring illustration cropped
   straight out of the client's own logo artwork (assets/logo.png, the
   art below "SERVICE" on the badge) instead of a hand-drawn recreation
   -- two prior attempts (a hand-drawn leaf spring, then a hand-drawn
   axle) both got redrawn from scratch and both missed: "just take the
   leaf springs from their logo. And use that instead" (Rich,
   2026-08-24). A straight rectangular crop, and later a hand-tuned SVG
   mask, both still clipped part of the spring or left a border sliver
   -- the badge's oval border passes directly under the spring and
   grazes both rolled eyes closely enough that no fixed-shape mask got
   both right at once (Rich: "You shouldn't cut into the spring at
   all... That whole leaf spring should be cut out," 2026-08-25 second
   round). Fixed properly with a flood-fill: seed one pixel inside a
   leaf line, walk the spring's own continuous ink (8-connected) to get
   an exact pixel-perfect set with zero manual boundary-guessing, then
   erase every inked pixel NOT in that set (border, text, flourish) --
   this can't clip the spring, because every pixel that's part of it is
   in the kept set by construction, and can't leave a border remnant,
   because every pixel that isn't is erased by construction. That first
   flood-fill pass only erased unwanted INK (border/text) and left the
   source badge's opaque white fill untouched everywhere else, which
   rendered as a visible white box on any background that isn't pure
   white (Rich: "you have a background behind it that's white. It
   should be a PNG," 2026-08-25 third round). Fixed by making every
   near-white pixel transparent too (not just the unwanted ink), so
   only the black linework itself is opaque -- a true transparent PNG,
   736x221 -- left in its native black, the logo itself is never
   recolored, this is no different. See the "never redo client logos"
   standing rule: use the real asset, don't approximate it. */
.masthead-nav .nav-active { position: relative; transform: translateY(-6px); }
/* Services is the only nav item wrapped in a flex trigger (icon + label);
   giving it the same inline-block as a plain link broke the icon alignment
   because the parent .has-drop had already been flex-blockified. Split by
   parent so each keeps the display mode it actually needs. */
.masthead-nav > a.nav-active { display: inline-block; }
.has-drop > a.nav-active { display: inline-flex !important; align-items: center; }
/* The leaf-spring decoration anchors to the TEXT only (.nav-label), never to
   the whole link box. Services carries a trailing icon that widens the link;
   without this the leaf centered under text+icon combined and read as
   shifted right of the word (Rich, 2026-08-21). */
.masthead-nav .nav-label { position: relative; display: inline-block; }
.masthead-nav .nav-active .nav-label::after {
  content: ""; position: absolute; left: 50%; bottom: -20px;
  /* scaleY flattens the source art's curve slightly (Rich: "a little
     less of a curve, not much") without needing a new crop -- the
     PNG's own arc is untouched, this just compresses it vertically
     within its box. */
  transform: translateX(-50%) scaleY(0.85);
  width: 50px; height: 15px;
  background: url("assets/nav-leaf-spring-mark.png") no-repeat center / contain;
}
/* the shop-line phone is now a button, matching Request a Quote */
.masthead-callbtn { white-space: nowrap; }

/* anchored sections (e.g. #quote) land BELOW the floating header, with
   breathing room so the section heading is fully visible */
[id] { scroll-margin-top: 106px; }

/* ═══ Sitewide motion (Rich-approved 2026-08-20). Slow + smooth is law;
   blur reveals standard. Palette colors only. ═══ */

/* 1. Hero photo: settle-in zoom on load (Ken Burns, one-shot). Was 7s
   -- long enough to still be running when a visitor started clicking
   the hero's own diagnose tool, which reads as "the background moves
   when I click" even though the click itself never touches it (Rich,
   2026-08-26: "nothing should move on the website when you click
   anything... on the hero section" -- confirmed by measurement:
   .hero's own height never moves, only the photo's own scale-driven
   edges do, and only while this animation is still running). This is
   a one-shot page-load flourish, not an ongoing motion, so it doesn't
   need to read as "slow" the way a hover or count-up does -- shortened
   enough that it reliably finishes before anyone reaches the tool,
   even testing it with fast deliberate clicks right after load. */
/* will-change lifts the (filtered, full-bleed) photo onto its own GPU layer
   so the settle scale composites instead of re-rasterising a 1920px
   grayscale image every frame — Lighthouse mobile showed 1.6s of "element
   render delay" on the hero before this (2026-09-02). */
.hero-photo, .page-hero > img { animation: csHeroSettle 0.6s ease-out both; will-change: transform; }
@keyframes csHeroSettle {
  from { transform: scale(1.07); }
  to   { transform: scale(1); }
}

/* 2. Buttons: shine sweep + slight lift on hover (shine drawn inside
   the button so the blueprint corner marks are never clipped) */
.btn { position: relative; transition: background-color 0.18s ease, color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease; }
.btn::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 42%, rgba(255,255,255,0.25) 50%, transparent 58%);
  background-size: 260% 100%; background-position: 130% 0; background-repeat: no-repeat;
}
.btn:hover { transform: translateY(-2px); box-shadow: 0 6px 16px rgba(27,31,54,0.25); }
.btn:hover::after { animation: csShine 1.6s ease-in-out; }
@keyframes csShine { from { background-position: 130% 0; } to { background-position: -130% 0; } }

/* 3. Scroll reveals sharpen from a slight blur as they fade in */
.reveal { filter: blur(5px); }
.reveal.is-visible { filter: blur(0); }
.reveal { transition-property: opacity, transform, filter; }

/* 4. Truck tiles: icon square flips navy->gold and the tile lifts */
.truck-tile { transition: transform 0.45s ease, box-shadow 0.45s ease; }
.truck-tile .t-ico { transition: background-color 0.45s ease, color 0.45s ease; }
.truck-tile:hover { transform: translateY(-4px); box-shadow: 0 10px 22px rgba(27,31,54,0.12); }
.truck-tile:hover .t-ico { background: #f2b307; color: #2c3157; }

@media (prefers-reduced-motion: reduce) {
  .hero-photo { animation: none; }
  .btn:hover { transform: none; }
  .btn:hover::after { animation: none; }
  .reveal, .reveal.is-visible { filter: none; }
  .truck-tile:hover { transform: none; }
}

/* ── Floating header: sticks to the top; on scroll the navy top bar
   slides up out of view (blue bar gone) leaving the slimmer masthead
   pinned. Done with transform + a constant flow height — nothing
   reflows, so there is no scroll jank near the top. First-load look
   is unchanged. ── */
.site-header {
  position: sticky; top: 0; z-index: 150;
  transition: transform 0.28s ease, box-shadow 0.28s ease;
  will-change: transform;
}
.site-header .topbar { transition: opacity 0.2s ease; }

body.is-scrolled .site-header { transform: translateY(-38px); box-shadow: 0 8px 26px rgba(15,18,40,0.18); }
body.is-scrolled .topbar { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }
}

/* ── Services dropdown (redesigned 2026-09-07, Rich: "too blocky with a solid
   background... make it white or gray, or see-through... make it connect to
   the bottom of the leaf spring under Services").
   The panel HANGS from the leaf spring: hovering Services lifts the word and
   shows the leaf-spring mark under it (the same mark the active page gets),
   a gold diamond hanger sits on the leaf's underside, and the panel drops
   from it. Frosted glass instead of solid navy: translucent white with a
   blur, hairline border and the site's corner brackets, navy Oswald type. */
.has-drop { position: relative; display: inline-flex; align-items: center; }
.has-drop > a { display: inline-flex; align-items: center; transition: transform 0.35s ease; }
/* on hover Services rises the 6px the active page already does, so the leaf
   and the panel sit in the same place whether the page is a service or not */
.has-drop:hover > a, .has-drop:focus-within > a { transform: translateY(-6px); }
.has-drop:hover .nav-label::after, .has-drop:focus-within .nav-label::after {
  content: ""; position: absolute; left: 50%; bottom: -20px;
  transform: translateX(-50%) scaleY(0.85);
  width: 50px; height: 15px;
  background: url("assets/nav-leaf-spring-mark.png") no-repeat center / contain;
}
.nav-drop {
  position: absolute; top: calc(100% + 28px); left: 50%; z-index: 60;
  transform: translateX(-50%) translateY(-10px);
  display: flex; flex-direction: column; min-width: 244px;
  padding: 8px 0;
  /* the site's light grey at 96%, NOT white: white hero letters pass straight
     through translucent white at any opacity (white over white stays white,
     measured 2026-09-07 at 78% and 90%); grey hides them and the blur softens
     what is left */
  background: rgba(244,244,246,0.96);
  -webkit-backdrop-filter: blur(20px) saturate(1.3); backdrop-filter: blur(20px) saturate(1.3);
  border: 1px solid rgba(44,49,87,0.28);
  box-shadow: 0 30px 50px -22px rgba(15,18,40,0.45);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.3s ease, transform 0.35s ease, visibility 0s linear 0.3s;
}
.nav-drop > .corner { color: #2c3157; }
/* no backdrop blur = the hero headline reads through translucent white */
@supports not (backdrop-filter: blur(1px)) { .nav-drop { background: rgba(244,244,246,0.99); } }
/* invisible bridge so the pointer can cross from the word to the panel */
.nav-drop::before { content: ""; position: absolute; top: -42px; left: -20px; right: -20px; height: 42px; }
/* the hanger: a gold diamond on a short navy stem, centred on the leaf */
.nav-drop-hanger { position: absolute; top: -13px; left: 50%; width: 1px; height: 13px; margin-left: -0.5px; background: #2c3157; }
.nav-drop-hanger::before { content: ""; position: absolute; top: -4px; left: 50%; width: 8px; height: 8px; margin-left: -4px; background: #f2b307; transform: rotate(45deg); }
.has-drop:hover .nav-drop, .has-drop:focus-within .nav-drop {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
  transition: opacity 0.3s ease, transform 0.35s ease, visibility 0s;
}
.nav-drop a {
  position: relative; padding: 11px 24px; color: #1b1f36 !important;
  font-size: 15px; letter-spacing: 0.08em; white-space: nowrap;
  transition: background 0.3s ease, color 0.3s ease;
}
/* the slide is a transform on the label, never padding (layout thrash) */
.nav-drop a > span { display: inline-block; transition: transform 0.3s ease; }
.nav-drop a:hover > span, .nav-drop a:focus-visible > span { transform: translateX(6px); }
.nav-drop a::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px; background: #f2b307; transform: scaleY(0); transition: transform 0.3s ease; }
.nav-drop a:hover, .nav-drop a:focus-visible { color: #2c3157 !important; background: rgba(44,49,87,0.07); }
.nav-drop a:hover::before, .nav-drop a:focus-visible::before { transform: scaleY(1); }
.nav-drop .nav-drop-all { margin-top: 6px; border-top: 1px solid rgba(44,49,87,0.22); padding-top: 13px; color: #2c3157 !important; }

/* ── "Trucks we work on" tiles: 4-across blueprint cards, every box
   identical, gold truck icon + stamped name + one-line descriptor ── */
.trucks-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 1fr; gap: 14px;
}
.truck-tile {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 20px 22px 18px;
  background: #fff;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.truck-tile:hover { transform: translateY(-4px); box-shadow: 0 12px 26px rgba(27,31,54,0.12); }
.truck-tile .t-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-bottom: 4px;
  background: #2c3157; color: #f2b307;
}
.truck-tile .t-ico svg { width: 26px; height: 26px; }
.truck-tile .t-name {
  font-family: 'Oswald', 'Rubik', sans-serif; font-weight: 700; font-size: 19px; line-height: 1.15;
  text-transform: uppercase; letter-spacing: 0.05em; color: #2c3157;
}
.truck-tile .t-desc { font-size: 15px; line-height: 1.45; color: var(--color-neutral-700); }
@media (max-width: 1024px) { .trucks-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px)  { .trucks-grid { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) { .truck-tile { transition: none; } .truck-tile:hover { transform: none; } }

/* ── footer "Shop" column: icon rows instead of plain text lines.
   Colors reused from the footer itself: gold #f2b307 icons, the map
   frame's rgba(255,255,255,0.05) fill + rgba(255,255,255,0.3) border. ── */
.shop-list { display: flex; flex-direction: column; gap: 10px; font-size: 15px; }
.shop-row {
  display: flex; align-items: center; gap: 12px;
  color: inherit; text-decoration: none; line-height: 1.45;
}
.shop-ico {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.3);
  color: #f2b307;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.shop-ico svg { width: 16px; height: 16px; }
a.shop-row:hover { color: #fff; }
a.shop-row:hover .shop-ico { background: rgba(255,255,255,0.12); border-color: #f2b307; }

/* burger + mobile menu (hidden on desktop; navy/gold to match) */
.nav-burger { display: none; background: none; border: none; padding: 13px; cursor: pointer; }
.mobile-menu {
  display: flex; flex-direction: column;
  position: absolute; top: 100%; left: 0; right: 0; z-index: 50;
  background: #1b1f36; border-top: 3px solid #f2b307;
  box-shadow: 0 24px 40px -20px rgba(15,18,40,0.5);
  opacity: 0; transform: translateY(-10px);
  visibility: hidden; pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s linear 0.3s;
}
.mobile-menu.is-open {
  opacity: 1; transform: none; visibility: visible; pointer-events: auto;
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s;
}
.mobile-menu a {
  padding: 15px 24px; color: #fff;
  font-family: var(--font-heading); font-size: 17px;
  letter-spacing: 0.08em; text-transform: uppercase;
  border-bottom: 1px solid rgba(255,255,255,0.12);
}
.mobile-menu a:hover { color: #f2b307; }
.mobile-menu .mobile-menu-call { color: #f2b307; border-bottom: none; }
.mobile-menu .mobile-sub {
  padding: 11px 24px 11px 44px;
  font-size: 15px; letter-spacing: 0.06em;
  color: rgba(255,255,255,0.75);
  background: rgba(255,255,255,0.03);
}

/* The finder's answer text is swapped by JS as the visitor picks a
   different symptom, and the six answers wrap to different line
   counts at the panel's width (one of the six runs a full line longer
   than the rest) -- so the finder card's own height changed depending
   on which symptom was selected. .hero is normally held at a fixed
   height by .fold's min-height, which hides this everywhere the
   viewport is tall enough to have slack -- but on shorter screens
   .hero has no slack left and becomes content-driven, so a finder
   card that just got a line shorter pulls .hero (and everything below
   it, stats bar included) up with it. Rich, 2026-08-26: "the whole
   hero section, including the four blocks on the bottom, moves up
   when you hit air bag." Reserve height for the longest of the six
   answers always, so the card's height -- and therefore .hero's --
   never changes no matter which symptom is picked, at any viewport
   height. 1.55em x 3 lines matches the tallest answer measured. */
#likelyNote { min-height: calc(1.55em * 3); }
/* The service NAME never wraps at any panel width (longest is "WALK-IN
   INSPECTION", ~200px in a 358px+ panel), so it needs no reserved height —
   the note below it is the only variable-height element here. Checked
   2026-09-04 before removing a reservation that cost ~28px of hero. */

/* Short desktop screens only: tighten the finder panel just enough that
   the fold still ends at the viewport bottom. Untouched on screens tall
   enough to hold the mockup's natural 932px stack.
   .finder's padding is deliberately top-heavy at every tier (base
   26px -> 34px top; this tier and the 790px one below get the same
   ratio applied) -- Rich, 2026-08-24, after the hero-centering fix
   was reverted: "the padding is thinner on the top than on the
   bottom... adjust the padding accordingly." Keep any future .finder
   padding tier top-biased the same way, not uniform. */
@media (min-width: 1025px) and (max-height: 1000px) {
  .hero-grid { padding-top: 10px !important; padding-bottom: 10px !important; }
  .finder { padding: 24px 20px 18px !important; }
  .finder .symptom { padding: 9px 11px !important; font-size: 15px !important; }
  .finder [id="likelyNote"] { margin-bottom: 12px !important; }
  .finder .btn-block { padding: 11px !important; }
}
@media (min-width: 1025px) and (max-height: 860px) {
  .finder .symptom { padding: 7px 10px !important; }
  .finder [id="likelySvc"] { font-size: 19px !important; }
  .hero-title { font-size: 64px !important; }
}
@media (min-width: 1025px) and (max-height: 790px) {
  .masthead { height: 96px !important; }
  .masthead-logo { height: 76px !important; }
  .finder { padding: 19px 16px 14px !important; }
  .finder > div:nth-of-type(2) { margin: 6px 0 10px !important; }
  .finder > div:last-child { margin-top: 12px !important; padding-top: 12px !important; }
  .finder [id="symptomList"] { gap: 5px !important; }
  .finder .symptom { padding: 5px 9px !important; font-size: 15px !important; }
  .finder [id="likelyNote"] { font-size: 15px !important; margin-bottom: 8px !important; }
  .finder .btn-block { padding: 9px !important; }
  .hero-title { font-size: 54px !important; }
  .hero-kicker { margin-top: 14px !important; }
  .hero-ctas { margin-top: 22px !important; }
  .stat { padding-top: 14px !important; padding-bottom: 14px !important; }
}

/* 14-inch laptops (1536x864 / 1366x768 at Windows scaling) give the page a
   ~750px or ~650px viewport. Rich, 2026-09-03: "the blue section on the
   bottom with the 4 sections is below the fold." The hero must fit one
   viewport (standard), so two more short-screen tiers: same design, less
   air in the diagnose panel and the stats bar. Measured: fold now ends
   above the bottom edge at 1536x750 and 1366x650. */
@media (min-width: 1025px) and (max-height: 900px) {
  .finder { padding: 16px 18px 14px !important; }
  .finder > div:nth-of-type(2) { margin: 6px 0 12px !important; }
  .finder [id="symptomList"] { gap: 5px !important; }
  .finder .symptom { padding: 5px 10px !important; }
  .finder > #finderBody > div:last-child { margin-top: 10px !important; padding-top: 10px !important; }
  #likelyNote { min-height: calc(1.55em * 3); margin-bottom: 8px !important; }
  .finder .btn-block { padding: 9px !important; }
  .stat { padding-top: 12px !important; padding-bottom: 12px !important; }
  .hero-title { font-size: 54px !important; }
}
@media (min-width: 1025px) and (max-height: 800px) {
  .finder { padding: 14px 16px 12px !important; }
  .finder > div:nth-of-type(2) { font-size: 19px !important; margin: 4px 0 10px !important; }
  .finder [id="symptomList"] { gap: 4px !important; }
  .finder .symptom { padding: 3px 9px !important; }
  .finder > #finderBody > div:last-child { margin-top: 7px !important; padding-top: 7px !important; }
  .finder [id="likelySvc"] { font-size: 18px !important; }
  #likelyNote { min-height: calc(1.5em * 3); line-height: 1.5 !important; margin-bottom: 6px !important; }
  .finder .btn-block { padding: 8px !important; }
  .stat { padding-top: 8px !important; padding-bottom: 8px !important; }
  .hero-title { font-size: 50px !important; }
  .hero-ctas { margin-top: 16px !important; }
}
@media (min-width: 1025px) and (max-height: 745px) {
  .topbar { height: 32px !important; }
  .masthead { height: 84px !important; }
  .masthead-logo { height: 66px !important; }
  .finder { padding: 10px 14px 10px !important; }
  .finder > div:nth-of-type(2) { font-size: 17px !important; margin: 2px 0 6px !important; }
  .finder [id="symptomList"] { gap: 3px !important; }
  .finder .symptom { padding: 3px 8px !important; }
  .finder > #finderBody > div:last-child { margin-top: 6px !important; padding-top: 6px !important; }
  .finder [id="likelySvc"] { font-size: 17px !important; }
  #likelyNote { min-height: calc(1.5em * 3) !important; line-height: 1.5 !important; margin-bottom: 5px !important; }
  .finder .btn-block { padding: 7px !important; }
  .stat { padding-top: 4px !important; padding-bottom: 4px !important; }
  .hero-title { font-size: 44px !important; }
  .hero-ctas { margin-top: 14px !important; }
}

/* The floor: a 1366x768 laptop with a bookmarks bar and a taskbar leaves
   about 600px of page. Everything still fits one screen; the header and
   the diagnose panel just run tight. */
@media (min-width: 1025px) and (max-height: 640px) {
  .topbar { height: 26px !important; }
  .masthead { height: 70px !important; }
  .masthead-logo { height: 56px !important; }
  .finder { padding: 8px 12px 8px !important; }
  .finder .symptom { padding: 2px 8px !important; }
  .finder [id="symptomList"] { gap: 2px !important; }
  .stat { padding-top: 1px !important; padding-bottom: 1px !important; }
  .hero-title { font-size: 34px !important; }
  .hero-kicker { margin-top: 8px !important; }
  .hero-ctas { margin-top: 10px !important; }
}

/* Only genuinely short screens (1366x768 laptops after chrome) lose the
   likely-service note — everything above keeps it. */
@media (min-width: 1025px) and (max-height: 680px) {
  #likelyNote { display: none !important; }
}

/* a 1fr grid track's implicit min-width is its content's min-content size,
   so a long label ("Generations, one family") can force the statsbar's
   track -- and the page -- wider than the viewport on phones; min-width:0
   lets it wrap inside its own column instead */
.stat { min-width: 0; }

/* ═══════════════ inner pages ═══════════════ */

/* Column-balance utilities: photo columns/cards yield to the text
   column's height (images crop via object-fit) so both columns of a
   grid always end on the same line — never a dead zone under text. */
.photo-fill { display: flex; flex-direction: column; min-height: 0; }
.photo-fill img { flex: 1 1 0; min-height: 0; width: 100%; object-fit: cover; }
.list-fill { display: flex; flex-direction: column; }
/* flex items default to align-items:stretch on the cross axis, which
   stretched the Dayton logo to the card's full width while its inline
   height:60px held height fixed — squashing the aspect ratio, worse the
   wider the card got (Rich, 2026-08-21). Any non-list child stays its
   own natural size. */
.list-fill > img { align-self: flex-start; }
.list-fill ul { flex: 1; align-content: space-evenly; }
@media (max-width: 1024px) {
  /* stacked on mobile: photos return to natural aspect */
  .photo-fill img { flex: none; min-height: auto; }
  .photo-fill img { height: auto; }
}
.page-hero h1 { text-wrap: balance; }
.svc-card { color: inherit; transition: transform 0.25s ease, box-shadow 0.25s ease; }
.svc-card:hover { transform: translateY(-3px); box-shadow: 0 18px 34px -20px rgba(20,24,50,0.35); color: inherit; }
.tag { transition: background-color 0.15s ease, color 0.15s ease; }
a.tag:hover { background: #2c3157 !important; color: #fff !important; }

/* — FAQs: native <details>, collapsed by default. Halves the vertical
   space a FAQ grid takes (especially on mobile, where every question
   used to open at full length) without any JS. — */
.faq-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; align-items: start; }
.faq-col { display: grid; gap: 22px; align-content: start; min-width: 0; }
.faq-item { padding: 0 20px; background: #fff; }
.faq-item summary {
  list-style: none; cursor: pointer; padding: 20px 0 14px;
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.faq-item[open] summary { padding-bottom: 10px; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary h3 { margin: 0; font-family: var(--font-heading); font-weight: 600; font-size: 17px; line-height: 1.25; color: #2c3157; }
.faq-caret { flex: none; color: #2c3157; transition: transform 0.3s ease; }
.faq-item[open] .faq-caret { transform: rotate(180deg); }
.faq-answer { margin: 0 0 20px; font-size: 15px; line-height: 1.65; color: var(--color-neutral-800); }

/* "Signs it's time" renders twice (build.js) so it can sit in a different
   spot per breakpoint without JS: beside the overview text on desktop,
   moved below the sub-services grid (right above FAQs) on mobile, so
   photos and services come first on a phone (Rich, 2026-08-23). */
.signs-mobile-slot { display: none; }
@media (max-width: 700px) {
  .faq-grid { grid-template-columns: 1fr !important; }
}

/* The "Common sign" hero widget wraps the Book-this-inspection button to
   its own line once the sign text no longer fits beside it -- left it
   content-width before and it stranded a wide gap next to a short button
   (Rich, 2026-08-23). First fix was full width, but Rich called that out
   as too heavy inside this bordered card specifically -- wants it sized
   closer to the sign text's own line length instead, left-aligned, not
   edge-to-edge. Not a reversal of "buttons fill the row when they wrap"
   generally, just this framed widget. */
@media (max-width: 620px) {
}

@media (max-width: 1180px) {
  .timeline-grid { grid-template-columns: repeat(3, 1fr) !important; }
  .blog-grid { grid-template-columns: repeat(2, 1fr) !important; }
  .sub-grid { grid-template-columns: repeat(3, 1fr) !important; }
  /* a lone trailing card centres instead of hanging left under a full row */
  .sub-grid > :last-child:nth-child(3n + 1) { grid-column: 2 !important; }
}
@media (max-width: 1024px) {
  .detail-grid { grid-template-columns: 1fr !important; gap: 40px !important; }
  .sub-grid { grid-template-columns: 1fr !important; }
  /* The 1180px rule's "recenter the lone trailing card into column 2"
     trick still matches here (any sub-service count that is 1 mod 3 —
     4, 7, 10...) even though the grid is down to a single column now.
     With no column 2 to move into, the browser invents an implicit one,
     splitting what should be a single-column stack into two cramped
     columns. Reset it once the grid is single-column. */
  .sub-grid > :last-child:nth-child(3n + 1) { grid-column: auto !important; }
  .page-hero h1 { font-size: 38px !important; }
}
@media (max-width: 700px) {
  .page-hero h1 { font-size: clamp(26px, 8vw, 34px) !important; }
  .page-hero .px { padding-top: 38px !important; padding-bottom: 36px !important; }
  .timeline-grid { grid-template-columns: 1fr 1fr !important; }
  .blog-grid { grid-template-columns: 1fr !important; }
  .contact-cards { grid-template-columns: 1fr !important; }
  .parts-list { grid-template-columns: 1fr !important; }
  .signs-grid { grid-template-columns: 1fr !important; }
  .signs-desktop-slot { display: none !important; }
  .signs-mobile-slot { display: block !important; }
  .cta-band .px > div:last-child { width: 100%; }
  .cta-band .btn { flex: 1 1 auto; justify-content: center; }
}

/* ═══════════════ responsive adaptations ═══════════════ */

@media (max-width: 1340px) {
  .masthead-nav { font-size: 20px !important; gap: 20px !important; }
  .masthead-cta .btn { padding: 11px 14px !important; }
}
@media (max-width: 1180px) {
  .hero-grid { grid-template-columns: 1fr 380px !important; gap: 40px !important; }
  .hero-title { font-size: 62px !important; }
  .masthead-nav { font-size: 19px !important; gap: 15px !important; }
  .masthead-cta { gap: 10px !important; padding-left: 18px !important; }
  .masthead-cta .btn { padding: 10px 12px !important; font-size: 15px !important; }
  .services-grid { grid-template-columns: repeat(2, 1fr) !important; }
  .reviews-row { grid-template-columns: 1fr !important; }
}

/* — Reviews carousel: badge stays put, the two-up track slides — one
   reusable component for the homepage teaser; the full /reviews page
   uses reviews-page-card directly in a plain grid instead. */
/* On the desktop teaser, .reviews-carousel-desktop is a grid item next
   to the 4.8 badge (.reviews-row's 260px + 1fr columns) -- CSS Grid's
   default align-items:stretch already makes ITS OWN box match the
   badge's height, but that height was dead-ending there: none of the
   plain block wrappers below it (viewport-wrap, viewport, track) had
   a height set, so they just shrank to the cards' natural content
   height, leaving the cards visibly shorter than the badge (Rich,
   2026-08-24: "keep the height of the reviews the same height as the
   badge... they look like they're a little thinner"). height:100%
   down this chain lets the stretch propagate; the actual review card
   is flex-column with its <p> already flex:1, so it absorbs the extra
   space for free. Inert everywhere else this component is reused (the
   mobile teaser collapses to one grid column with nothing to stretch
   against; the modal lightbox isn't in a grid at all) -- percentage
   heights fall back to auto without a definite-height ancestor. */
/* .reviews-carousel-mobile is a CSS Grid item of .reviews-row (the
   single 1fr mobile column, shared with the 4.8 badge next to/above
   it). Grid items default to min-width:auto, which sizes off their
   CONTENT's min-content -- and a flex track holding N slides at
   flex:0 0 100% has no real container width to resolve that
   percentage against during min-content measurement, so the browser
   falls back to summing every slide's own natural width instead
   (~180px x 4 real slides = ~720px on a 375px phone). Grid respects
   that inflated min-content as the item's floor size and blows out
   the WHOLE column -- which is why the badge sharing that column
   also ended up 720px wide, not just the carousel (Rich, 2026-08-24:
   "on mobile you can swipe left and right... the review section with
   the badge and reviews are way off the right side of the screen").
   overflow:hidden on .reviews-viewport (below) stops it from being
   visually wider, but doesn't zero out its min-content CONTRIBUTION
   to the grid's own sizing pass -- min-width:0 on the actual grid
   item is the fix, not an overflow tweak deeper in the tree. */
.reviews-carousel { min-width: 0; }
.reviews-viewport-wrap { height: 100%; }
.reviews-viewport { overflow: hidden; position: relative; height: 100%; }
.reviews-track { display: flex; height: 100%; transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1); }
/* box-sizing: border-box so this padding insets the card without
   changing the page's own width -- it's still exactly one
   viewport-width slot (the JS step math depends on that), just with
   breathing room baked in, so mid-slide the current and next card
   don't read as one continuous block (Rich, 2026-08-24: "so when they
   slide, they don't look like they're attached to each other"). */
.reviews-page { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; flex: 0 0 100%; min-width: 0; box-sizing: border-box; padding: 0 8px; }
@media (max-width: 700px) {
  .reviews-page { grid-template-columns: 1fr !important; }
}
/* Two independent carousel instances instead of one reflowing grid --
   desktop shows 2 reviews per slide, mobile shows exactly 1 (Rich,
   2026-08-24: "there should only be one review at a time, not two on
   mobile"). Reusing the 2-up grid at 1 column still stacked both
   cards vertically in the same slide; a true "one at a time" needs
   each review to be its own slide, which only a second, mobile-only
   set of pages can do without changing desktop's pairing. */
.reviews-carousel-mobile { display: none; }
@media (max-width: 700px) {
  .reviews-carousel-desktop { display: none; }
  .reviews-carousel-mobile { display: block; }
}
.reviews-arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  background: #fff; border: 1px solid var(--color-divider); cursor: pointer;
  color: #2c3157; font-size: 18px; line-height: 1; z-index: 2;
  transition: background-color 0.18s ease;
}
.reviews-arrow:hover { background: var(--color-neutral-100); }
.reviews-arrow.prev { left: -18px; }
.reviews-arrow.next { right: -18px; }
.reviews-carousel[data-pages="1"] .reviews-arrow,
.reviews-carousel[data-pages="1"] .reviews-dots { display: none; }
/* Homepage teaser, mobile instance: the carousel fills the full .px
   gutter (only 20px at this width) with nothing else to spare, so the
   arrow's -18px offset leaves it sitting flush against the true
   viewport edge -- zero margin, tips into real horizontal page
   overflow on some devices/widths (Rich, 2026-08-24: "the Google
   review section on the home page is overflowing the browser... to
   the right on the phone"). Same fix already applied to the reviews
   lightbox: drag/swipe already covers navigation, so remove the arrow
   rather than trying to patch its position back inside a gutter
   that's too narrow to hold it. Dots stay. */
@media (max-width: 700px) {
  .reviews-carousel-mobile .reviews-arrow { display: none; }
}
.reviews-dots { display: flex; justify-content: center; gap: 8px; margin-top: 18px; }
.reviews-dots button {
  width: 8px; height: 8px; border-radius: 50%; border: none; padding: 0;
  background: var(--color-neutral-300); cursor: pointer;
}
.reviews-dots button.is-active { background: #2c3157; }
@media (prefers-reduced-motion: reduce) { .reviews-track { transition: none; } }

/* The nav+CTA+logo combo genuinely doesn't fit until ~1450px wide, no
   matter how much the 1340/1180 tiers below shrink font-size and
   padding — measured overflow of 24-92px at every width from 1180 up
   to about 1400. Collapsing to the hamburger here (instead of at 1024,
   where the squeeze zone silently relied on the logo distorting to
   absorb the shortfall) means there's no in-between range where things
   almost fit and something has to give. */
@media (max-width: 1450px) {
  .masthead-nav { display: none !important; }
  .nav-burger { display: inline-flex; }
  .masthead-cta { margin-left: 0; border-left: none !important; padding-left: 0 !important; }
  .masthead-cta .btn { display: none !important; }
  .header-trust { display: flex !important; margin-left: auto; }
}
/* hidden above 1024px -- the hero's two-column layout has room for the
   diagnostic tool fully open, so there's nothing to collapse there */
.finder-toggle { display: none; }
@media (max-width: 1024px) {
  .masthead-nav { display: none !important; }
  .nav-burger { display: inline-flex; }
  .masthead { height: 96px !important; gap: 20px !important; }
  .masthead-logo { height: 76px !important; }
  .masthead-cta { margin-left: auto; border-left: none !important; padding-left: 0 !important; }

  .fold { min-height: 0; }
  .hero { min-height: 0 !important; }
  .hero-grid {
    grid-template-columns: 1fr !important;
    gap: 22px !important;
    padding-top: 28px !important; padding-bottom: 28px !important;
    align-items: start !important;
  }
  .hero-deco { display: none; }

  /* the diagnostic tool doubled the mobile hero's height stacked fully
     open below the headline (measured 1561px tall in an 844px viewport) --
     collapsed by default here, one tap reveals the same picker desktop
     always shows. See #finderToggle/#finderBody in index.html. */
  .finder-toggle { display: flex !important; }
  #finderBody { display: none; }
  .finder.is-expanded #finderBody { display: block; }
  .finder.is-expanded .finder-toggle { display: none !important; }

  .estimate-band, .lists-band { grid-template-columns: 1fr !important; gap: 44px !important; }
  /* mid widths: two columns (logo | shop info), map spans full width
     below — no skinny single column with a dead right side */
  .footer-grid { grid-template-columns: 1fr 1fr !important; gap: 36px 48px !important; }
  .footer-grid > div:nth-child(2) { display: flex; flex-direction: column; justify-content: center; }
  .footer-grid > div:nth-child(3) { grid-column: 1 / -1; }
}

/* stats bar: four-across needs ~840px; go 2x2 below that */
@media (max-width: 840px) {
  .statsbar { grid-template-columns: 1fr 1fr !important; }
  .stat { padding: 18px 16px !important; border-right: none !important; border-top: 1px solid rgba(255,255,255,0.18); }
  .statsbar .stat:nth-child(1), .statsbar .stat:nth-child(2) { border-top: none; }
  .statsbar .stat:nth-child(odd) { border-right: 1px solid rgba(255,255,255,0.18) !important; }
}

@media (max-width: 700px) {
  .px { padding-inline: 20px !important; }
  .footer-grid { grid-template-columns: 1fr !important; gap: 36px !important; }
  .footer-grid > div:nth-child(2) { justify-content: flex-start; }
  .footer-grid > div:nth-child(3) { grid-column: auto; }
  /* phones: logo sits on the column's left edge like the text, Facebook link and Shop heading under it
     (Richie, 9 Oct; it was centered since 23 Aug). -1px because the logo art starts 1px inside its image. */
  .footer-logo { display: block; margin-left: -1px !important; margin-right: 0 !important; }
  .topbar { height: auto !important; padding-top: 8px !important; padding-bottom: 8px !important; justify-content: center !important; }
  .topbar-tagline { display: none; }
  .topbar-contacts { flex-wrap: wrap; justify-content: center; gap: 12px !important; }

  .masthead { height: 84px !important; }
  .masthead-logo { height: 62px !important; }
  .masthead-cta .btn { display: none; }

  .hero-title { font-size: clamp(38px, 11.5vw, 52px) !important; }
  .hero-kicker { margin-top: 14px !important; }
  .hero-kicker-text { font-size: 15px !important; letter-spacing: 0.18em !important; }
  .hero-sub { margin-top: 16px !important; font-size: 16px !important; }
  /* Below 700px the sticky .mobile-callbar already carries Call + Get a
     Quote, and the diagnostic tool's own entry point is redundant with
     it too -- both duplicate what's one thumb-reach away at all times
     on a phone (Rich, 2026-08-25). Cut here, not above 700px: the
     header's own Call/Quote buttons are ALSO hidden up to 1024px
     (.masthead-cta .btn), and .mobile-callbar doesn't exist until
     700px -- removing these any earlier would leave 701-1024px with no
     call/quote path on the page at all. The stats bar (the "four blue
     boxes") already sits as the very next section after .hero in the
     DOM, so hiding these two just lets it land directly under the
     wording without moving any markup. */
  .hero-ctas, .finder { display: none !important; }
  .finder { padding: 20px !important; }

  .services-band { padding-top: 56px !important; padding-bottom: 56px !important; }
  .section-head { flex-direction: column !important; align-items: flex-start !important; gap: 20px !important; }
  .services-grid { grid-template-columns: 1fr !important; gap: 18px !important; }
  .svc-card { min-height: 0 !important; }

  .video-band { height: 340px !important; }
  .video-title { font-size: 26px !important; }

  .estimate-band { padding-top: 56px !important; padding-bottom: 56px !important; }
  .lists-band { padding-bottom: 56px !important; }
  .form-grid { grid-template-columns: 1fr !important; }

  .footer-band { padding-top: 44px !important; }
  .footer-bottom { flex-direction: column; gap: 6px !important; text-align: center; }
}

/* phones: icon sits above the number, and the labels lose some letter
   spacing, so "Generations, one family" and "Suspension service lines"
   wrap inside their own half instead of running into the divider and
   off the right edge of the screen (layout check 2026-10-27) */
@media (max-width: 700px) {
  .statsbar .stat { flex-direction: column; align-items: flex-start !important; gap: 10px !important; }
  .statsbar .stat > div > div:last-child { font-size: 13px !important; letter-spacing: 0.08em !important; line-height: 1.35; }
}

@media (max-width: 340px) {
  .hero-title { font-size: 34px !important; }
  .statsbar { grid-template-columns: 1fr !important; }
  .statsbar .stat { border-right: none !important; }
}


/* ═══════════════ mobile contact model (2026-08-21) ═══════════════
   Desktop shows the number as text — you cannot dial from a desktop, so the
   digits are what a person actually uses. Mobile gets a Call button instead,
   in a fixed bar with the phone on the LEFT so it is the harder accidental
   tap. The utility bar is desktop furniture and comes off entirely on phones;
   what it carried that was trust rather than contact moved into the menu. */
.mobile-callbar { display: none; }

/* — Floating trust badge: desktop only, the corner belongs to the call
   bar on phones (one floating element per viewport). Two clickable
   halves sharing one widget -- still counts as one floating element.
   Low-contrast until hover, never animates on scroll, never expands.
   Starts fully hidden and only fades in once the hero has scrolled out
   of view -- nothing floating is ever allowed to block the hero on
   load, permanent rule (Rich, 2026-08-24). */
.trust-fab {
  position: fixed; right: 24px; bottom: 24px; z-index: 40;
  display: flex; align-items: stretch; overflow: hidden;
  opacity: 0; pointer-events: none; transform: translateY(12px);
  transition: opacity 0.5s ease, transform 0.5s ease, box-shadow 0.25s ease;
}
.trust-fab.is-shown { opacity: 0.9; pointer-events: auto; transform: translateY(0); }
.trust-fab.is-shown:hover { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .trust-fab { transition: opacity 0.3s ease; transform: none; } }
/* Hover feedback lives on each half separately, not the shared
   container -- two real buttons share one widget, and lighting up the
   whole bar for either one made them read as a single control (Rich,
   2026-08-24: "only... animated for when you hover over one of the
   buttons... a different button inside that button"). Brightness, not
   transform: .trust-fab's overflow:hidden would clip a translateY lift
   on a stretch flex child. */
.trust-fab-hours, .trust-fab-reviews { position: relative; transition: filter 0.2s ease; }
.trust-fab-hours:hover, .trust-fab-hours:focus-visible { filter: brightness(0.94); }
.trust-fab-reviews:hover, .trust-fab-reviews:focus-visible { filter: brightness(1.18); }
.trust-fab-hours.cs-status {
  margin-left: 0; border: none; border-right: 1px solid var(--color-divider);
  cursor: pointer; font-family: inherit; border-radius: 0;
}
.trust-fab-reviews {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; background: #2c3157; color: #fff;
  border: none; cursor: pointer; font-family: inherit;
}
/* Badge is a novel enough pattern that hovering it isn't a given --
   name the action on hover so nobody has to guess it opens anything
   (Rich, 2026-08-24: "afraid people aren't gonna know to click it").
   Sits above the button so it never gets clipped by the bar's own
   overflow:hidden. */
.fab-tip {
  position: absolute; left: 50%; bottom: calc(100% + 10px);
  transform: translateX(-50%) translateY(4px);
  background: #1b1f36; color: #fff;
  font-family: "Rubik", system-ui, sans-serif; font-size: 15px; font-weight: 500;
  letter-spacing: 0.01em; white-space: nowrap;
  padding: 7px 12px; opacity: 0; pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.fab-tip::after {
  content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: #1b1f36;
}
.trust-fab-hours:hover .fab-tip, .trust-fab-hours:focus-visible .fab-tip,
.trust-fab-reviews:hover .fab-tip, .trust-fab-reviews:focus-visible .fab-tip {
  opacity: 1; transform: translateX(-50%) translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .trust-fab-hours, .trust-fab-reviews, .fab-tip { transition: none; }
}
.rating-fab-num { font-family: var(--font-title); font-weight: 700; font-size: 22px; line-height: 1; color: #f2b307; }
.rating-fab-stars { display: flex; gap: 2px; }
.rating-fab-count {
  display: flex; align-items: center; gap: 6px;
  font-size: 15px; letter-spacing: 0.04em; color: rgba(255,255,255,0.82);
  padding-left: 10px; border-left: 1px solid rgba(255,255,255,0.25);
  white-space: nowrap;
}
@media (max-width: 1450px) {
  .trust-fab { display: none !important; }
}

/* — Header trust badge: same widget, inline in the header instead of
   floating, for the whole range where the nav has collapsed to the
   hamburger (≤1450px) -- header order becomes Logo / hours+reviews /
   hamburger (Rich, 2026-08-24). Responsive down to the smallest phones:
   shrinks, then drops the review-count words, keeping just the number,
   stars and Google mark once space is tight. — */
.header-trust {
  display: none; align-items: stretch; overflow: hidden; flex: none;
}
/* Same per-button hover treatment as the floating .trust-fab -- no
   tooltip here, though, there's no headroom above a badge already
   sitting in the header to put one. */
.header-trust-hours, .header-trust-reviews { transition: filter 0.2s ease; }
.header-trust-hours:hover, .header-trust-hours:focus-visible { filter: brightness(0.94); }
.header-trust-reviews:hover, .header-trust-reviews:focus-visible { filter: brightness(1.18); }
@media (prefers-reduced-motion: reduce) {
  .header-trust-hours, .header-trust-reviews { transition: none; }
}
.header-trust-hours.cs-status {
  margin-left: 0; border: none; border-right: 1px solid var(--color-divider);
  cursor: pointer; font-family: inherit; border-radius: 0;
  padding: 11px 18px;
}
.header-trust-reviews {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 20px; background: #2c3157; color: #fff;
  border: none; cursor: pointer; font-family: inherit;
}
.header-trust .rating-fab-num { font-size: 24px; }
@media (max-width: 1180px) {
  .header-trust-hours.cs-status { padding: 8px 13px; }
  .header-trust-reviews { padding: 10px 13px; gap: 8px; }
}
@media (max-width: 900px) {
  .header-trust .cs-status .txt > span { display: none; }
  .header-trust-count-text { display: none; }
  .rating-fab-count { padding-left: 6px; }
}
@media (max-width: 550px) {
  .masthead { gap: 12px !important; }
  .header-trust-hours.cs-status { padding: 7px 11px; }
  .header-trust-hours .dot { width: 8px; height: 8px; }
  .header-trust-reviews { padding: 8px 11px; gap: 5px; }
  .header-trust .rating-fab-stars { display: none; }
  .header-trust .rating-fab-num { font-size: 17px !important; }
  .rating-fab-count { padding-left: 4px; }
}
/* 390px phones: logo (89) + trust badge (205) + burger (56) + gaps and
   padding came to ~413px, so the burger sat 3.5px past the viewport
   edge on every page (design-audit "horizontal overflow" at phone 390,
   pre-launch gate 2026-09-02). The 550px tier above wasn't quite
   enough; this one closes the last ~25px without dropping any text
   under the 15px floor. */
@media (max-width: 430px) {
  .masthead { gap: 8px !important; }
  .masthead-logo { height: 54px !important; }
  .nav-burger { padding: 13px 6px 13px 8px; }
  .header-trust-hours.cs-status { padding: 6px 9px; }
  .header-trust-reviews { padding: 7px 9px; gap: 4px; }
  .header-trust .rating-fab-num { font-size: 15px !important; }
}
@media (max-width: 360px) {
  .header-trust-hours.cs-status b { font-size: 15px !important; }
}

/* /reviews: the full review grid is two columns everywhere -- at 390px
   that's two 192px cards in a 350px column, overflowing the page to
   430px (pre-launch gate 2026-09-02). One column on phones. */
@media (max-width: 700px) {
  .reviews-page-grid { grid-template-columns: 1fr !important; }
}

/* /reviews sort controls were bare <button>s with no rule at all, so
   they rendered in the browser's UA default (13.33px Arial) -- under
   the 15px floor and off-brand. Styled to match the site's tag pills. */
.reviews-sort { display: flex; flex-wrap: wrap; gap: 8px; }
.reviews-sort button {
  font: inherit; font-size: 15px; letter-spacing: 0.02em;
  padding: 7px 14px; background: transparent; color: #2c3157;
  border: 1px solid #2c3157; border-radius: 0; cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}
.reviews-sort button:hover, .reviews-sort button.is-active { background: #2c3157; color: #fff; }

@media (max-width: 700px) {
  .site-header .topbar { display: none !important; }
  /* The topbar is already gone at all times on mobile (not just faded on
     scroll like desktop), so the -38px shift that slides the desktop
     masthead up into the vanished topbar's place has nothing to
     compensate for here — it just clips the top of the logo/status chip
     off-screen instead. */
  body.is-scrolled .site-header { transform: none !important; }
  .showcase-photo-row { grid-template-columns: 1fr !important; }

  .mobile-callbar {
    display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    background: rgba(244, 244, 246, 0.94);
    backdrop-filter: blur(12px);
    border-top: 3px solid #2c3157;
  }
  .mobile-callbar .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    min-height: 48px; padding: 13px 10px; color: #fff !important;
    font-size: 15px; letter-spacing: 0.06em; text-transform: uppercase;
    white-space: nowrap;
    /* a 1fr grid track's implicit min-width is its content's min-content
       size, so nowrap text can force the track (and the page) wider than
       the viewport -- min-width:0 lets it shrink to the track instead */
    min-width: 0;
  }
  /* reserve the bar's height so it never covers the footer */
  body { padding-bottom: 82px; }
}
@media (max-width: 360px) {
  .mobile-callbar .btn { font-size: 15px; padding: 13px 6px; }
}

/* the trust lines the utility bar used to carry, now in the menu */
.mobile-meta { display: none; }
@media (max-width: 1024px) {
  .mobile-meta {
    display: flex; flex-direction: column; gap: 7px;
    margin-top: 18px; padding-top: 16px;
    border-top: 1px solid rgba(255, 255, 255, 0.16);
  }
  .mobile-meta .mm-line {
    font-family: "Rubik", system-ui, sans-serif; font-size: 15px;
    color: rgba(255, 255, 255, 0.66); letter-spacing: 0.01em; text-decoration: none;
  }
  .mobile-meta .mm-line b { color: rgba(255, 255, 255, 0.9); font-weight: 600; }
  .mm-line-btn {
    display: flex; align-items: center; gap: 8px; width: 100%;
    background: none; border: none; padding: 0; margin: 0;
    text-align: left; cursor: pointer; font: inherit;
  }
  .mobile-meta .mm-line-btn.cs-status[data-state] { display: flex; padding: 8px 10px; }
}


/* ═══════════════ open / closed status chip ═══════════════
   Google Business Profile pattern — a coloured dot plus words, never the dot
   alone. Shades pulled from this site's own palette: brick for closed so it
   sits beside the navy and gold, a deep shop green for open. */
.cs-status {
  display: none; align-items: center; gap: 9px; position: relative; flex: none;
  padding: 7px 12px; margin-left: auto;
  background: var(--cs-bg); border: 1px solid var(--cs-line);
}
.cs-status[data-state] { display: flex; }
/* Standalone in the hours lightbox (no flex-row sibling forcing it to
   content-width the way it gets it for free inside the header/floating
   badge), a block-level .cs-status stretches to the full panel width --
   a banner reaching the close button's corner, way wider than the
   "Closed now / Opens 7:00 AM" text needs (Rich, 2026-08-24: "should
   only be as long as... the shop hours goes"). Size it to its content. */
.hours-modal-status[data-state] { display: inline-flex; }
.cs-status[data-state="closed"] {
  --cs-bg: #f7eae6; --cs-line: rgba(160,58,38,.34);
  --cs-dot: #a03a26; --cs-ring: rgba(160,58,38,.16);
  --cs-ink: #a03a26; --cs-tick: rgba(160,58,38,.5);
}
.cs-status[data-state="open"] {
  --cs-bg: #e8f0e8; --cs-line: rgba(45,101,60,.32);
  --cs-dot: #2d653c; --cs-ring: rgba(45,101,60,.18);
  --cs-ink: #2d653c; --cs-tick: rgba(45,101,60,.48);
}
.cs-status .dot {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--cs-dot); box-shadow: 0 0 0 3px var(--cs-ring);
}
.cs-status .txt { display: flex; flex-direction: column; line-height: 1.15; }
.cs-status b {
  font-family: "Oswald", system-ui, sans-serif; font-weight: 600; font-size: 15px;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--cs-ink);
}
.cs-status .txt > span {
  font-family: "Rubik", system-ui, sans-serif; font-size: 15px;
  color: #5d5d60; letter-spacing: 0.01em; white-space: nowrap;
}
/* the blueprint corner ticks this site already uses on its buttons */
.cs-status i { position: absolute; width: 7px; height: 7px; }
.cs-status i::before, .cs-status i::after { content: ""; position: absolute; background: var(--cs-tick); }
.cs-status i::before { left: 0; top: 0; width: 1px; height: 100%; }
.cs-status i::after  { left: 0; top: 0; width: 100%; height: 1px; }
.cs-status i.tl { left: 3px; top: 3px; }
.cs-status i.tr { right: 3px; top: 3px; transform: scaleX(-1); }
.cs-status i.bl { left: 3px; bottom: 3px; transform: scaleY(-1); }
.cs-status i.br { right: 3px; bottom: 3px; transform: scale(-1); }
@media (max-width: 700px) {
  .cs-status { padding: 6px 10px; gap: 7px; }
  .cs-status b { font-size: 15px; }
  .cs-status .txt > span { font-size: 15px; }
}
@media (max-width: 360px) { .cs-status .txt > span { display: none; } }

/* ══════════ Blog / article pages (2026-09-07) ══════════
   The RWS standard layout — DESIGN-STANDARDS "BLOG / ARTICLE PAGES":
   breadcrumb + title only across the top (the page-hero band without its
   photo), a WHITE page, the site's 10% gutters (.px), two columns and never
   three — the article beside ONE dark rail that stacks the contents list
   over the call-to-action. Measure lives on the column, in rem, centred;
   vertical rhythm uses margin-block so it can never zero the centring. */
/* Same grey ground as every other page (Rich, 2026-09-07: the white page
   read as a different site). Cards are white ON the grey, like the rest. */
.post-page { background: var(--color-bg); }
.post-layout { display: grid; gap: 34px; align-items: start; padding-top: 44px; padding-bottom: 60px; }
@media (min-width: 1080px) { .post-layout { grid-template-columns: minmax(0, 3fr) minmax(300px, 1fr); gap: 56px; } }

.post-meta { margin: 0 0 22px; }
.post-meta-note { margin: 10px 0 0; font-size: 15px; color: var(--color-neutral-600); }
.post-body { color: var(--color-neutral-900); font-size: 18px; line-height: 1.7; }
.post-body > * { margin-block: 0 1.15em; margin-inline: 0; }
/* Section headings are the site's own: the short navy rule with a gold
   diamond, then the stamped display face at the same 34px h2() uses on every
   service page. The rule is markup (withAnchors) so it matches exactly. */
.post-body .sec-rule { display: flex; align-items: center; gap: 6px; margin: 2em 0 8px; }
.post-body .sec-rule span { display: block; height: 1px; background: #2c3157; }
.post-body .sec-rule span:first-child { width: 54px; }
.post-body .sec-rule span:last-child { width: 22px; }
.post-body .sec-rule i { display: block; width: 7px; height: 7px; background: #f2b307; transform: rotate(45deg); }
.post-body .post-h2 { scroll-margin-top: 190px; margin: 0 0 0.5em; font-family: var(--font-display); font-weight: 400; font-size: 34px; line-height: 1.14; letter-spacing: 0.005em; text-transform: uppercase; color: #2c3157; }
.post-body > .sec-rule:first-child { margin-top: 0; }
.post-body p { margin-block: 0 1.15em; }
/* Lists take the site's "signs it's time" chips: gold numbered squares in
   white boxes, the component every service page already uses. */
.post-body ul { list-style: none; padding: 0; counter-reset: pl; }
.post-body li { counter-increment: pl; display: flex; align-items: flex-start; gap: 13px; padding: 13px 14px; margin-block: 10px; background: #fff; border: 1px solid var(--color-divider); font-size: 17px; line-height: 1.55; }
.post-body li::before { content: counter(pl, decimal-leading-zero); flex: none; width: 26px; height: 26px; margin-top: 1px; display: flex; align-items: center; justify-content: center; background: #f2b307; color: #2c3157; font-family: var(--font-heading); font-weight: 700; font-size: 15px; }
.post-body strong { color: #1b1f36; }
.post-body a { color: #2c3157; font-weight: 600; text-decoration: underline; text-decoration-color: #f2b307; text-decoration-thickness: 2px; text-underline-offset: 4px; }
.post-body a:hover { color: #1b1f36; text-decoration-color: #2c3157; }

/* Photos break the reading column, corner-bracketed like every other frame
   on the site. The caption sits ON the photo over the site's navy fade —
   never in a tinted strip under it (the template tell, 2026-08-24). */
/* The site's photo card: white, 10px inset, corner brackets, caption in the
   small Oswald label underneath — the same figure the service and about pages
   use, so a blog photo looks like every other photo here. */
.post-figure { position: relative; margin-block: 2.2em; margin-inline: auto; padding: 10px; background: #fff; }
.post-figure img { display: block; width: 100%; height: auto; }
/* The gradient spans the WHOLE photo (Rich, 2026-09-07: "it stops. It should
   continue across the whole picture"); only the text is capped at a measure. */
.post-figure figcaption { padding: 12px 6px 4px; font-size: 15px; line-height: 1.5; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-neutral-600); font-family: var(--font-heading); }
/* Left-aligned in the title font, like the H2s around it. A centred,
   textured pull quote between left-set headings looked wrong (Rich,
   2026-09-07). Fills the column: a capped measure wrapped early and left
   white space beside it (Rich, 2026-09-07). */
.post-pull { margin-block: 2.2em; padding: 6px 0 6px 26px; border-left: 4px solid #f2b307; text-align: left; font-family: var(--font-title); font-weight: 700; font-size: clamp(24px, 2vw, 30px); line-height: 1.2; letter-spacing: 0.01em; text-transform: uppercase; color: #2c3157; }
.post-back { margin: 34px 0 0; font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.14em; text-transform: uppercase; }
.post-back a { color: #2c3157; text-decoration: none; border-bottom: 2px solid #f2b307; padding-bottom: 2px; }

/* The rail: navy on the white page, sticky under the floating header, and
   never taller than the space under it (or the CTA scrolls out of reach). */
/* By the time the rail sticks the page has scrolled and the floating header
   is in its slim 122px state, so the offset is measured against that, not the
   full 160px header-h, or 38px of the rail is wasted and the CTA clips. */
/* The 6px padding / -6px margin pair gives the cards' corner brackets (which
   sit 6px outside each card) room inside the scroll box; without it the
   scroll box clips them and the rail always has 6px of phantom scroll. */
.post-rail { position: sticky; top: 132px; display: grid; gap: 22px; padding: 6px; margin: -6px; max-height: calc(100svh - 148px); overflow-y: auto; scrollbar-width: none; }
.post-rail::-webkit-scrollbar { display: none; }
@media (max-width: 1079.98px) {
  .post-rail { position: static; max-height: none; overflow: visible; }
  /* Under the article a contents list is a table of contents for something
     already read. The CTA still earns its place; the list does not. */
  .post-toc { display: none; }
}
/* Light rail (Rich, 2026-09-07: "too much blocky, solid blue"). The cards
   take the header's own light grey so they read as part of the page, with
   navy type and gold only on the numbers, rule and Call button. */
.rail-card { position: relative; background: #fff; color: var(--color-neutral-900); padding: 22px 20px 20px; border-color: var(--color-divider); }
.rail-card .corner { color: #2c3157; }
.rail-card h2, .rail-card h3 { display: flex; align-items: center; gap: 9px; margin: 0 0 14px; font-family: var(--font-heading); font-weight: 400; font-size: 15px; letter-spacing: 0.2em; text-transform: uppercase; color: #2c3157; }
.rail-card ol { list-style: none; margin: 0; padding: 0; counter-reset: toc; }
.rail-card li { counter-increment: toc; margin-bottom: 7px; }
.rail-card li a { display: block; color: var(--color-neutral-900); font-size: 15px; line-height: 1.4; text-decoration: none; transition: color 0.3s ease; }
.rail-card li a::before { content: counter(toc) ". "; color: #c8930a; font-weight: 700; }
.rail-card li a:hover { color: #2c3157; text-decoration: underline; text-decoration-color: #f2b307; text-decoration-thickness: 2px; text-underline-offset: 3px; }
/* Scroll-spy: the section on screen lights up in the contents list (Rich,
   2026-09-07). Gold bar + navy bold; the bar slides in, nothing jumps. */
/* Selected = a BLUE row, not black text (Rich, 2026-09-07: "maybe try blue as
   a selected part"). Row tint accent-200 with brand-navy type (7:1) and a
   navy bar sliding in on the left. */
.post-toc li a { position: relative; padding: 4px 10px 4px 14px; margin-left: -14px; margin-right: -10px; transition: color 0.3s ease, background 0.35s ease; }
.post-toc li a::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: #2c3157; transform: scaleY(0); transform-origin: center; transition: transform 0.35s ease; }
.post-toc li a.is-current { color: #2c3157; font-weight: 700; background: var(--color-accent-200); }
.post-toc li a.is-current::after { transform: scaleY(1); }
.rail-cta .rail-h { font-family: var(--font-title); font-weight: 700; font-size: 24px; line-height: 1.15; text-transform: uppercase; color: #1b1f36; margin: 0 0 10px; }
.rail-hours { list-style: none; margin: 0 0 18px; padding: 0; font-size: 15px; }
.rail-hours li { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--color-divider); }
.rail-hours li:last-child { border-bottom: 0; }
.rail-hours strong { color: #1b1f36; font-weight: 600; }
/* The reviews row does the floating badge's job inside the rail, so the
   badge itself can yield on these pages (one floating element per
   viewport, and a sticky rail already owns the right-hand edge). */
/* Styled as the third member of the button stack under it (Rich, 2026-09-07:
   "looks a little out of place with the two buttons below it"): centred, the
   buttons' Oswald uppercase and padding, white so it still reads as a fact
   rather than an action. */
.rail-reviews { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; margin: 10px 0 0; padding: 12px 18px; background: var(--color-neutral-100); border: 1px solid #1b1f36; color: #1b1f36; font-family: var(--font-title); font-weight: 700; font-size: 15px; letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer; transition: background 0.3s ease; }
.rail-reviews:hover { background: var(--color-accent-100); }
.rail-reviews-num { font-size: 18px; line-height: 1; }
@media (min-width: 1080px) { body:has(.post-page) .trust-fab { display: none; } }
.rail-cta .btn { display: flex; justify-content: center; width: 100%; margin-bottom: 10px; text-align: center; }
.rail-cta .btn:last-of-type { margin-bottom: 0; }
/* Measured 2026-09-07 at 1440 wide (after the light restyle + reviews row):
   contents list 328px + CTA card ~540px against 746px under the slim header
   on a 900-tall screen, 572px at 720, 512px at 660. The list and the two
   buttons are the point of the rail, so the CTA card sheds its extras first
   as the screen gets shorter: the paragraph, then the hours, then its
   heading, then the reviews row; the list tightens last. Every tier was
   measured to fit: the last button's bottom edge inside the viewport. */
@media (min-width: 1080px) and (max-height: 1000px) { .rail-cta p { display: none; } }
@media (min-width: 1080px) and (max-height: 940px) { .rail-hours { display: none; } }
@media (min-width: 1080px) and (max-height: 780px) { .rail-cta .rail-h { display: none; } }
@media (min-width: 1080px) and (max-height: 740px) { .rail-reviews { display: none; } .rail-card li { margin-bottom: 5px; } }

/* Index: the latest post as a feature (photo beside copy), older posts as
   hairline rows — never a card grid (Rich, 2026-09-02). */
.bi-feature { position: relative; display: grid; gap: 26px; align-items: center; padding: 24px; background: #fff; }
@media (min-width: 900px) { .bi-feature { grid-template-columns: 1.15fr 1fr; gap: 36px; } }
.bi-media { display: block; position: relative; overflow: hidden; background: var(--color-neutral-100); padding: 0; }
.bi-media img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; transition: transform 0.6s ease; }
.bi-feature:hover .bi-media img, .bi-row:hover .bi-media img { transform: scale(1.04); }
.bi-kicker { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--color-neutral-600); }
.bi-tag { background: #f2b307; color: #1b1f36; padding: 3px 9px; font-weight: 700; }
.bi-feature h2 { margin: 0 0 14px; font-family: var(--font-title); font-weight: 700; font-size: 34px; line-height: 1.1; letter-spacing: 0.02em; text-transform: uppercase; }
.bi-feature h2 a, .bi-row h3 a { color: #2c3157; text-decoration: none; }
.bi-feature h2 a:hover, .bi-row h3 a:hover { color: #1b1f36; }
.bi-lede { margin: 0 0 20px; font-size: 18px; line-height: 1.6; color: var(--color-neutral-800); }
.bi-list-head { margin: 48px 0 6px; font-family: var(--font-title); font-weight: 700; font-size: 24px; text-transform: uppercase; letter-spacing: 0.02em; color: #2c3157; }
.bi-row { position: relative; display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 22px; align-items: center; padding: 18px; margin-bottom: 14px; background: #fff; }
.bi-row .bi-media img { aspect-ratio: 16 / 10; }
.bi-row h3 { margin: 0 0 8px; font-family: var(--font-title); font-weight: 700; font-size: 22px; line-height: 1.15; text-transform: uppercase; }
.bi-row p { margin: 0; font-size: 15px; line-height: 1.55; color: var(--color-neutral-800); }
@media (max-width: 640px) { .bi-row { grid-template-columns: 1fr; } }

/* ═══ Quote form B2: hero card + pop-up (Richie picked B2 and approved it live, 9 Oct 2026) (Richie, 9 Oct) ═══
   "make the padding better, and more padding around everything in the quote form,
   everything looks to scrunched up and condensed" + "the title should be bolder and the
   pre populated text shouldnt be the same weight and size as the service, truck, etc".
   Same card, fields, words, colors and post as B. What changed:
   - more room: card padding, a gap between the field boxes, taller fields, more space
     above the button and around the call line
   - title heavier; labels are the strong part, hints are light and soft, a typed answer is full strength
   - desktop service list is a padded listbox (the native select stays for phones and for the post)
   Every rule scoped to body.opt-b2. */

.qb-panel {
  --qb-line: rgba(255,255,255,0.4);
  --qb-gold: #f2b307;
  --qb-hint: rgba(255,255,255,0.66);
  padding: 22px 26px 18px;
  background: rgba(27,31,54,0.8);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  border-color: rgba(255,255,255,0.42);
  color: #fff;
}
.qb-panel > .corner { color: rgba(255,255,255,0.75); }

/* a bit wider than B's 436px so the extra side padding doesn't squeeze the fields */
@media (min-width: 1181px) {
  body.home .hero-grid { grid-template-columns: 1fr 452px !important; }
}
/* the short panel can't set the hero's height, so the grid fills the hero (same as B) */
@media (min-width: 1025px) {
  body.home .fold .hero { display: flex; flex-direction: column; }
  body.home .fold .hero > .hero-grid { flex: 1 1 auto; width: 100%; box-sizing: border-box; }
}

/* — head: title + stamp, then the perforated tear line — */
.qb-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding-bottom: 12px; margin-bottom: 15px;
  border-bottom: 1px dashed rgba(255,255,255,0.45);
}
/* Oswald tops out at 700 in the site's font file, so a hairline of stroke takes it a step heavier */
.qb-title {
  margin: 0; font-family: var(--font-title); font-weight: 700;
  font-size: 28px; line-height: 1.1; letter-spacing: 0.015em;
  text-transform: uppercase; color: #fff;
  -webkit-text-stroke: 0.6px #fff; paint-order: stroke fill;
}
.qb-stamp {
  flex: none; padding: 3px 9px 2px;
  font-family: var(--font-heading); font-weight: 500; font-size: 15px;
  letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.4;
  color: var(--qb-gold); border: 1px solid rgba(242,179,7,0.65);
}

/* — the field boxes: same ruled boxes as B, now with a gap between them — */
.qb-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.qb-cell {
  position: relative; display: flex; flex-direction: column; min-width: 0;
  padding: 8px 15px 6px;
  background: rgba(255,255,255,0.07);
  border: 1px solid var(--qb-line);
  cursor: text; transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
.qb-wide { grid-column: 1 / -1; }
/* labels: the strong, clear part */
.qb-lab {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-family: var(--font-heading); font-weight: 600; font-size: 15px;
  letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.15;
  color: #fff;
}
.qb-opt {
  font-family: var(--font-body); font-weight: 400; font-size: 14px;
  letter-spacing: 0; text-transform: none; color: var(--qb-hint);
}
.qb-err {
  font-style: normal; font-family: var(--font-body); font-weight: 500;
  font-size: 15px; letter-spacing: 0; text-transform: none; color: #ffd666;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.qb-err:empty { display: none; }

/* values: a typed answer is full white at 500; the hint is lighter, smaller and softer */
.qb-cell input,
.qb-cell select,
.qb-cell .qb-dd-btn {
  display: block; width: 100%; min-width: 0; height: 28px; margin: 4px 0 0; padding: 0;
  font-family: var(--font-body); font-weight: 500; font-size: 17px; line-height: 28px; color: #fff;
  background: transparent; border: 0; border-radius: 0; outline: none;
  -webkit-appearance: none; appearance: none; box-shadow: none;
  caret-color: var(--qb-gold); text-align: left;
}
.qb-cell input::placeholder {
  color: var(--qb-hint); opacity: 1; font-weight: 300; font-size: 16px;
}
.qb-cell select { padding-right: 26px; cursor: pointer; text-overflow: ellipsis; }
.qb-cell select.is-empty { color: var(--qb-hint); font-weight: 300; font-size: 16px; }
.qb-cell select option { color: #fff; background: #1b1f36; font-weight: 400; }
.qb-pick { cursor: pointer; }
.qb-chev {
  position: absolute; right: 15px; bottom: 14px; color: var(--qb-gold); pointer-events: none;
  transition: transform 0.15s ease;
}
/* the box is the field: focus lights the whole box gold */
.qb-cell:focus-within {
  background: rgba(255,255,255,0.13);
  box-shadow: inset 0 0 0 1px var(--qb-gold);
  border-color: var(--qb-gold);
}
.qb-cell.is-bad { border-color: var(--qb-gold); }
@media (hover: hover) {
  .qb-cell:hover { background: rgba(255,255,255,0.11); }
}

/* — desktop service list: a padded listbox in the card's look (phones keep the native select) — */
.qb-pick.has-dd select {
  position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
.qb-dd-btn { padding-right: 26px; cursor: pointer; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.qb-dd-btn.is-empty { color: var(--qb-hint); font-weight: 300; font-size: 16px; }
.qb-pick.is-open { z-index: 30; }
.qb-pick.is-open .qb-chev { transform: rotate(180deg); }
.qb-dd-list {
  position: absolute; z-index: 30; left: -1px; right: -1px; top: calc(100% + 6px);
  margin: 0; padding: 6px 0; list-style: none;
  background: #1b1f36; border: 1px solid rgba(255,255,255,0.42);
  box-shadow: 0 14px 30px rgba(10,12,24,0.45);
  outline: none; cursor: default;
}
.qb-dd-list[hidden] { display: none; }
.qb-dd-list:focus-visible { box-shadow: 0 0 0 2px var(--qb-gold), 0 14px 30px rgba(10,12,24,0.45); }
.qb-dd-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 44px; padding: 10px 18px;
  font-family: var(--font-body); font-weight: 400; font-size: 17px; line-height: 1.3; color: #fff;
  cursor: pointer;
}
.qb-dd-opt.is-active { background: rgba(242,179,7,0.17); }
.qb-dd-opt[aria-selected="true"] { font-weight: 500; }
.qb-dd-tick { flex: none; color: var(--qb-gold); visibility: hidden; }
.qb-dd-opt[aria-selected="true"] .qb-dd-tick { visibility: visible; }

/* honeypot: off-screen, never seen or tabbed to */
.qb-hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; opacity: 0; }

/* — the gold send button — */
.qb-send {
  display: flex; align-items: center; justify-content: center; width: 100%;
  margin-top: 18px; padding: 15px 16px;
  font-family: var(--font-heading); font-weight: 600; font-size: 17px; line-height: 1.2;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: #1b1f36; background: #f2b307; border: 1px solid #f2b307; border-radius: 0;
  cursor: pointer; touch-action: manipulation;
  transition: background-color 0.18s ease, transform 0.18s ease;
}
.qb-send > .corner { color: rgba(255,255,255,0.6); }
.qb-send:active { background: #d99f04; transform: translateY(1px); }
.qb-send:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.qb-send[aria-busy="true"] { cursor: progress; background: #d99f04; }
@media (hover: hover) {
  .qb-send:hover { background: #d99f04; }
}

.qb-call {
  margin: 12px 0 0; font-size: 15px; line-height: 1.4; text-align: center;
  color: rgba(255,255,255,0.86);
}
.qb-call a, .qb-fail a, .qb-done-hours a {
  color: #fff; font-weight: 500; text-decoration: underline; text-decoration-color: rgba(242,179,7,0.8);
  text-underline-offset: 3px;
}
.qb-fail {
  margin: 14px 0 0; padding: 10px 12px; font-size: 15px; line-height: 1.4; color: #fff;
  border: 1px solid rgba(242,179,7,0.7); background: rgba(242,179,7,0.12);
}
.qb-fail[hidden], .qb-done[hidden] { display: none; }

/* — the thank-you, shown in place of the fields — */
.qb-form.is-done .qb-grid,
.qb-form.is-done .qb-send,
.qb-form.is-done .qb-call,
.qb-form.is-done .qb-fail { display: none; }
.qb-done { outline: none; }
.qb-form.is-done { display: flex; flex-direction: column; }
.qb-form.is-done .qb-done { margin: auto 0; }
.qb-done-title {
  font-family: var(--font-title); font-weight: 700; font-size: 23px; line-height: 1.2;
  text-transform: uppercase; color: #fff;
}
.qb-done-rows {
  margin: 16px 0 0; border-top: 1px solid var(--qb-line); border-left: 1px solid var(--qb-line);
}
.qb-done-rows > div {
  display: grid; grid-template-columns: 96px 1fr; align-items: baseline;
  border-right: 1px solid var(--qb-line); border-bottom: 1px solid var(--qb-line);
  background: rgba(255,255,255,0.07);
}
.qb-done-rows dt {
  padding: 10px 14px; font-family: var(--font-heading); font-weight: 600; font-size: 15px;
  letter-spacing: 0.05em; text-transform: uppercase; color: #fff;
}
.qb-done-rows dd { margin: 0; padding: 10px 14px 10px 0; font-size: 16px; color: #fff; overflow-wrap: anywhere; }
.qb-done-hours { margin: 16px 0 0; font-size: 16px; color: rgba(255,255,255,0.9); }
.qb-again {
  margin-top: 12px; padding: 8px 0; font: inherit; font-size: 15px; color: #fff;
  background: none; border: 0; border-bottom: 1px solid rgba(242,179,7,0.8); cursor: pointer;
  touch-action: manipulation;
}
@media (hover: hover) {
  .qb-again:hover { color: var(--qb-gold); }
}

/* — short desktop screens: still roomier than B, just less than the full size — */
@media (min-width: 1025px) and (max-height: 860px) {
  .qb-panel { padding: 20px 24px 15px; }
  .qb-head { padding-bottom: 10px; margin-bottom: 13px; }
  .qb-title { font-size: 27px; }
  .qb-grid { gap: 7px; }
  .qb-cell { padding: 7px 14px 5px; }
  .qb-cell input, .qb-cell select, .qb-cell .qb-dd-btn { height: 27px; line-height: 27px; margin-top: 3px; }
  .qb-chev { bottom: 12px; }
  .qb-send { margin-top: 15px; padding: 13px 16px; }
  .qb-call { margin-top: 10px; }
}
@media (min-width: 1025px) and (max-height: 700px) {
  .qb-panel { padding: 16px 22px 12px; }
  .qb-head { padding-bottom: 8px; margin-bottom: 10px; }
  .qb-title { font-size: 24px; }
  .qb-grid { gap: 6px; }
  .qb-cell { padding: 6px 13px 4px; }
  .qb-cell input, .qb-cell select, .qb-cell .qb-dd-btn { height: 26px; line-height: 26px; margin-top: 2px; }
  .qb-chev { bottom: 10px; }
  .qb-dd-opt { min-height: 38px; padding: 7px 18px; }
  .qb-send { margin-top: 11px; padding: 11px 16px; font-size: 16px; }
  .qb-call { margin-top: 7px; }
}
@media (min-width: 1025px) and (max-height: 600px) {
  .qb-call { display: none; }
}

/* Tablet and phone: the hero is just the headline + its buttons; the quote form is the pop-up. */
@media (max-width: 1024px) {
  .qb-panel { display: none !important; }
}

/* ═══ the pop-up: the same card on solid navy ═══ */
.qb-modal .qb-sheet {
  --qb-line: rgba(255,255,255,0.4);
  --qb-gold: #f2b307;
  --qb-hint: rgba(255,255,255,0.66);
  max-width: 460px; padding: 28px 28px 22px;
  background: #1b1f36; color: #fff; border: 1px solid rgba(255,255,255,0.42);
}
.qb-modal .qb-sheet > .corner { color: rgba(255,255,255,0.75); }
.qb-modal .qb-head { padding-right: 48px; }
.qb-modal .qb-sheet { max-height: none; overflow: visible; }
@media (max-height: 640px) {
  .qb-modal .qb-sheet { max-height: calc(100vh - 28px); overflow-y: auto; overflow-x: hidden; }
}
.qb-modal .qb-x {
  top: 18px; right: 18px; color: #fff; border-color: rgba(255,255,255,0.45); touch-action: manipulation;
}
.qb-modal .qb-x:focus-visible { outline: 2px solid #f2b307; outline-offset: 2px; }
@media (hover: hover) {
  .qb-modal .qb-x:hover { background: #f2b307; border-color: #f2b307; color: #1b1f36; }
}
/* phones: every field box is at least 60px tall (the whole box is the tap target), the input itself 36px */
@media (max-width: 560px) {
  .qb-modal { padding: 14px; }
  .qb-modal .qb-sheet { padding: 22px 20px 18px; }
  .qb-modal .qb-head { padding-bottom: 12px; margin-bottom: 16px; }
  .qb-modal .qb-title { font-size: 27px; }
  .qb-modal .qb-grid { gap: 9px; }
  .qb-modal .qb-cell { padding: 9px 13px 5px; }
  .qb-modal .qb-cell input, .qb-modal .qb-cell select { height: 36px; line-height: 36px; margin-top: 3px; }
  .qb-modal .qb-chev { bottom: 16px; right: 13px; }
  .qb-modal .qb-send { margin-top: 18px; padding: 16px 16px; }
  .qb-modal .qb-call { margin-top: 12px; }
}
@media (max-width: 360px) {
  .qb-modal { padding: 10px; }
  .qb-modal .qb-sheet { padding: 18px 16px 14px; }
  .qb-modal .qb-title { font-size: 24px; }
  .qb-modal .qb-grid { grid-template-columns: 1fr; gap: 8px; }
  .qb-modal .qb-cell { padding: 7px 12px 4px; }
  .qb-modal .qb-cell input, .qb-modal .qb-cell select { height: 34px; line-height: 34px; margin-top: 2px; }
  .qb-modal .qb-chev { bottom: 14px; }
  .qb-modal .qb-send { margin-top: 14px; padding: 15px 16px; }
}

/* the live header runs 22px off a 320px iPhone SE (today's page too); same fix B carries */
@media (max-width: 360px) {
  .masthead { padding-inline: 12px !important; gap: 6px !important; }
  .masthead-logo { height: 42px !important; }
}

/* ═══ Lower quote card, middle look (Richie picked it 9 Oct 2026): white card, B2 field boxes, heavier title, gold button ═══ */
/* ═══ shared: B2's ruled field boxes, label inside the box ═══ */
body .estimate-band .quote-card { --qc-gold: #f2b307; }

body .estimate-band .quote-card > div:first-of-type {
  padding-bottom: 12px; margin-bottom: 15px !important;
  border-bottom: 1px dashed var(--qc-line-strong);
}
body .estimate-band .quote-card > div:first-of-type > div {
  font-size: 28px !important; line-height: 1.1; letter-spacing: 0.015em;
  -webkit-text-stroke: 0.6px currentColor; paint-order: stroke fill;
}
body .estimate-band .quote-card > div:first-of-type::after {
  content: "Since 1941"; margin-left: auto; flex: none; padding: 3px 9px 2px;
  font-family: var(--font-heading); font-weight: 500; font-size: 15px;
  letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.4;
}

body .estimate-band .quote-card .form-grid { gap: 8px !important; }
body .estimate-band .quote-card .field {
  position: relative; display: flex; flex-direction: column; min-width: 0;
  padding: 8px 15px 6px;
  background: var(--qc-box); border: 1px solid var(--qc-line);
  cursor: text; transition: background-color 0.15s ease, box-shadow 0.15s ease;
}
body .estimate-band .quote-card .field-grow { margin-top: 8px !important; }
body .estimate-band .quote-card .field > label {
  margin: 0; font-family: var(--font-heading); font-weight: 600; font-size: 15px;
  letter-spacing: 0.06em; text-transform: uppercase; line-height: 1.15;
  color: var(--qc-label);
}
body .estimate-band .quote-card .input {
  display: block; width: 100%; min-height: 28px; height: 28px; margin: 4px 0 0; padding: 0;
  font-family: var(--font-body); font-weight: 500; font-size: 17px; line-height: 28px;
  color: var(--qc-value); background: transparent !important;
  border: 0; border-radius: 0; outline: none; box-shadow: none;
  caret-color: var(--qc-gold);
}
body .estimate-band .quote-card textarea.input { height: auto; min-height: 64px; line-height: 1.45; padding-top: 2px; resize: none; }
body .estimate-band .quote-card .input::placeholder { color: var(--qc-hint); opacity: 1; font-weight: 300; font-size: 16px; }
body .estimate-band .quote-card select.input {
  -webkit-appearance: none; appearance: none; padding-right: 26px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23f2b307' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important; background-position: right 0 center !important;
}
body .estimate-band .quote-card .field:focus-within {
  background: var(--qc-box-focus); border-color: var(--qc-gold); box-shadow: inset 0 0 0 1px var(--qc-gold);
}
@media (hover: hover) {
  body .estimate-band .quote-card .field:hover { background: var(--qc-box-hover); }
}

/* the gold send button, full width, call line under it (as on the B2 hero card) */
body .estimate-band .quote-card > div:last-child { gap: 12px !important; justify-content: center; }
body .estimate-band .quote-card .btn-primary {
  flex: 1 1 100%; padding: 15px 16px !important;
  font-weight: 600; font-size: 17px; letter-spacing: 0.04em !important;
  color: #1b1f36 !important; background: #f2b307; border-color: #f2b307;
}
body .estimate-band .quote-card .btn-primary:hover { background: #d99f04; color: #1b1f36 !important; }
body .estimate-band .quote-card .btn-primary > .corner { color: rgba(27,31,54,0.45); }
body .estimate-band .quote-card > div:last-child > span { text-align: center; color: var(--qc-call) !important; }

/* ═══ middle: white card, B2 boxes and button ═══ */
body .estimate-band .quote-card {
  --qc-line: rgba(44,49,87,0.3);
  --qc-line-strong: rgba(44,49,87,0.4);
  --qc-box: #f4f4f6;
  --qc-box-hover: #eeeef2;
  --qc-box-focus: #fff;
  --qc-label: #2c3157;
  --qc-value: #1d1f20;
  --qc-hint: #6b6e78;
  --qc-call: #4a4d55;
}
body .estimate-band .quote-card > div:first-of-type::after { color: #2c3157; border: 1px solid #f2b307; }
body .estimate-band .quote-card .field:focus-within { border-color: #2c3157; box-shadow: inset 0 0 0 1px #2c3157; }
body .estimate-band .quote-card > div:last-child > span a { text-decoration: underline; text-decoration-color: #f2b307; text-underline-offset: 3px; }

/* phones: taller boxes, same as the B2 pop-up */
@media (max-width: 560px) {
  body .estimate-band .quote-card { padding: 22px 20px 20px !important; }
  body .estimate-band .quote-card > div:first-of-type > div { font-size: 25px !important; }
  body .estimate-band .quote-card .field { padding: 9px 13px 5px; }
  body .estimate-band .quote-card .input { height: 36px; line-height: 36px; margin-top: 3px; }
  body .estimate-band .quote-card textarea.input { height: auto; min-height: 72px; line-height: 1.45; }
}
/* phones: the stamp would push the title onto two lines, so it drops out */
@media (max-width: 480px) {
  body .estimate-band .quote-card > div:first-of-type::after { display: none; }
}
/* "Pick a service" reads as a hint until a service is picked; the open list shows normal text */
body .estimate-band .quote-card select.input:has(option[value=""]:checked) { color: var(--qc-hint); font-weight: 300; font-size: 16px; }
body .estimate-band .quote-card select.input option { color: #1d1f20; font-weight: 400; font-size: 16px; }

/* ═══ Icon set (9 Oct 2026): one drawn family with the truck tiles. Solid navy, cut-outs by mask, the
   hardware the shop works on in safety yellow. Source: app/mockups/centralspring-icons/_build/icons.js ═══ */
svg.ci, svg.tk { display: inline-block; vertical-align: middle; overflow: visible; }
.ci-mark { color: inherit; }
.shop-ico svg.ci { width: 17px; height: 17px; }
/* truck tiles: option A, the drawing in a wide grey panel; hover turns it navy with a yellow truck */
.truck-tile { align-items: stretch; padding: 14px 14px 18px; gap: 4px; }
.truck-tile .t-ico { display: flex; width: auto; height: auto; aspect-ratio: 2 / 1; margin-bottom: 10px; padding: 6% 7% 4%; background: #eef0f5; color: #2c3157; }
.truck-tile .t-ico svg { display: block; width: 100%; height: auto; }
.truck-tile .t-name, .truck-tile .t-desc { padding-inline: 4px; }
.truck-tile:hover .t-ico { background: #2c3157; color: #f2b307; }
/* Safari: the drawing has no fixed size, so without these a tile grows to the svg's default 300px and the phone page scrolls sideways */
.truck-tile, .truck-tile .t-ico, .truck-tile .t-ico svg { min-width: 0; }
.truck-tile .t-ico svg { flex: 1 1 auto; }
@media (max-width: 540px) {
  .trucks-grid { grid-template-columns: repeat(2, 1fr); }
  .truck-tile { padding: 10px 10px 14px; }
  .truck-tile .t-name { font-size: 16px; letter-spacing: 0.03em; }
  .truck-tile .t-desc { font-size: 14px; }
}

/* ═══ Lower quote card: B2's service list on desktop (Richie, 9 Oct 2026: "the drop down on this contact form is bad") ═══
   The list is B2's own (.qb-dd-list: navy, gold pick, lined up with the box). This only fits its button into the white
   card's box. Phones and touch screens keep the native picker, and the native select still carries the posted value. */
body .estimate-band .quote-card .field.has-dd { cursor: pointer; }
body .estimate-band .quote-card .field.has-dd select.input {
  position: absolute; width: 1px; height: 1px; min-height: 0; margin: 0; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
body .estimate-band .quote-card .qb-dd-btn {
  position: relative; display: block; width: 100%; min-width: 0; height: 28px; margin: 4px 0 0; padding: 0 26px 0 0;
  font-family: var(--font-body); font-weight: 500; font-size: 17px; line-height: 28px; color: var(--qc-value);
  text-align: left; background: transparent; border: 0; border-radius: 0; outline: none; box-shadow: none;
  -webkit-appearance: none; appearance: none; cursor: pointer; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
body .estimate-band .quote-card .qb-dd-btn.is-empty { color: var(--qc-hint); font-weight: 300; font-size: 16px; }
body .estimate-band .quote-card .qb-dd-btn::after {
  content: ""; position: absolute; right: 0; top: 50%; width: 14px; height: 14px; margin-top: -7px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23f2b307' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat center / 14px;
  transition: transform 0.15s ease;
}
body .estimate-band .quote-card .field.is-open { z-index: 30; }
body .estimate-band .quote-card .field.is-open .qb-dd-btn::after { transform: rotate(180deg); }
/* the card is its own layer (the reveal's filter), so it rises while the list is open or the next band would cover it */
body .estimate-band .quote-card:has(.field.is-open) { position: relative; z-index: 30; }
