/* Judge Batteries. Standalone stylesheet, no framework, no build step.
   Palette and type are the same contract as the design brief:
   midnight navy ground, one signal red accent, Geist and Geist Mono. */

:root {
  /* LIGHT THEME. Roles are unchanged from the original dark build:
     --ink is still "the page ground", --bone is still "the primary text".
     Only their lightness is swapped, so all 151 var() uses stay correct.
     Brand red and gold are untouched. */
  --ink: #ffffff;
  --night: #f5f8fc;
  --steel: #eaf0f8;
  --line: #dbe3ee;
  --mist: #56677f;
  --bone: #0d1524;
  /* Nudged down from #e0353b: white text on the old red measured 4.43:1, just
     under AA. This is 4.68:1 and reads as the same brand red. */
  --signal: #db3036;
  --signal-deep: #b4262b;
  --ok: #2e8b57;
  --gold: #f2b705;
  --gold-deep: #d9a204;
  --gold-ink: #0a0a0c;
  /* Used where a control inverts on hover (light text on a dark fill). */
  --invert-bg: #0d1524;
  --invert-fg: #ffffff;
  /* Red reads brightly on dark but needs deepening on white to stay legible. */
  --eyebrow: #b4262b;

  --display: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --wrap: 1200px;
  --pad: 20px;
  --radius: 16px;
}

@media (min-width: 768px) {
  :root { --pad: 32px; }
}

*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--ink);
  color: var(--bone);
  color-scheme: light;
  scroll-behavior: smooth;
  /* Clears the fixed header so anchor jumps do not land underneath it. */
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--ink);
  color: var(--bone);
  font-family: var(--display);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p { margin: 0; }

::selection { background: var(--signal); color: var(--bone); }

:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: 12px;
  top: 12px;
  z-index: 100;
  background: var(--signal);
  color: var(--bone);
  padding: 10px 16px;
  border-radius: 999px;
}

/* ---------------------------------------------------------------- type --- */

.display {
  font-size: clamp(2.25rem, 6vw, 4rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  font-weight: 600;
}

.h2 {
  font-size: clamp(1.75rem, 4vw, 3rem);
  line-height: 1.05;
  letter-spacing: -0.03em;
  font-weight: 600;
}

.h3 {
  font-size: 1.25rem;
  line-height: 1.3;
  letter-spacing: -0.015em;
  font-weight: 600;
}

.lede {
  font-size: 1.125rem;
  line-height: 1.65;
  color: var(--mist);
  max-width: 65ch;
}

.body { color: var(--mist); max-width: 65ch; }
.body + .body { margin-top: 16px; }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--eyebrow);
}

.label {
  font-family: var(--mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--mist);
}

.mono { font-family: var(--mono); }

/* ----------------------------------------------------------------- nav --- */

/* Fixed, so the phone number is reachable from any point on any page. The
   translucent ground keeps the film and the hero plates readable underneath. */
.nav {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 60;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 76px;
}

.brand { display: flex; align-items: center; gap: 11px; flex: none; }
.brand img { width: 38px; height: 38px; border-radius: 9px; }
.brand-txt { display: flex; flex-direction: column; line-height: 1.12; }
.brand-name { font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.015em; }
.brand-since {
  font-family: var(--mono);
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--mist);
}

/* Burger. Desktop hides it; mobile hides the menu instead. */
.navtoggle {
  display: inline-flex; flex-direction: column; justify-content: center; gap: 5px;
  width: 42px; height: 38px; padding: 0 9px;
  background: transparent; border: 1px solid var(--line); border-radius: 8px;
  cursor: pointer;
}
.navtoggle span { display: block; height: 1.5px; background: var(--bone); border-radius: 2px; }

.navmenu { display: none; }
.nav-links { display: flex; align-items: center; gap: 26px; }
.nav-links > li { position: relative; }
.nav-links > li > a {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--mist);
  padding-block: 8px;
  transition: color 0.2s;
}
.nav-links > li > a:hover { color: var(--bone); }
.has-menu > a::after {
  content: "";
  display: inline-block;
  margin-left: 7px;
  border: 4px solid transparent;
  border-top-color: currentColor;
  transform: translateY(2px);
}

.submenu {
  position: absolute;
  top: 100%;
  left: -14px;
  min-width: 264px;
  padding: 8px;
  background: var(--night);
  border: 1px solid var(--line);
  border-radius: 11px;
  box-shadow: 0 16px 36px rgba(13, 21, 36, 0.16);
  display: none;
  max-height: 70vh;
  overflow-y: auto;
}
.has-menu:hover .submenu,
.has-menu:focus-within .submenu { display: block; }
.submenu a {
  display: block;
  padding: 8px 12px;
  border-radius: 7px;
  font-size: 0.875rem;
  color: var(--bone);
  transition: background 0.15s, color 0.15s;
}
.submenu a:hover { background: var(--steel); color: var(--signal); }

.nav-ctas { display: flex; align-items: center; gap: 10px; }
/* Second CTA in the bar, so it stays visually quieter than the call button. */
.quote {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 20px;
  border: 1px solid var(--gold);
  border-radius: 999px;
  font-size: 0.875rem; font-weight: 700;
  letter-spacing: -0.01em;
  background: var(--gold);
  color: var(--gold-ink);
  white-space: nowrap;
  transition: background 0.2s, border-color 0.2s, transform 0.14s;
}
.quote:hover { background: var(--gold-deep); border-color: var(--gold-deep); }
.quote:active { transform: translateY(1px); }
.quote::before {
  content: "";
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--gold-ink); flex: none;
}

@media (min-width: 1180px) {
  .navtoggle { display: none; }
  .navmenu { display: flex; align-items: center; gap: 26px; }
}

/* Mobile: the burger opens a full panel under the fixed bar. */
@media (max-width: 1179px) {
  .navmenu.open {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 18px;
    position: fixed;
    inset-inline: 0;
    top: 76px;
    max-height: calc(100dvh - 76px);
    overflow-y: auto;
    padding: 22px var(--pad) 32px;
    background: var(--ink);
    border-bottom: 1px solid var(--line);
  }
  .navmenu.open .nav-links { flex-direction: column; align-items: stretch; gap: 4px; }
  .navmenu.open .nav-links > li > a { padding-block: 10px; font-size: 0.8rem; }
  .navmenu.open .has-menu > a::after { display: none; }
  .navmenu.open .submenu {
    display: block;
    position: static;
    min-width: 0;
    max-height: none;
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: 0 0 8px 14px;
    border-left: 1px solid var(--line);
    margin-left: 2px;
  }
  .navmenu.open .nav-ctas { flex-direction: column; align-items: stretch; }
  .navmenu.open .quote,
  .navmenu.open .call { justify-content: center; }
}

/* ----------------------------------------------------------------- cta --- */
/* Each call to action has its own interaction identity. No shared button. */

.call {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 12px 24px;
  border-radius: 999px;
  background: var(--signal);
  color: #ffffff;
  font-weight: 600;
  letter-spacing: -0.01em;
  /* One line, always. A wrapped call button is the worst looking thing on a
     page whose whole job is getting that button pressed. */
  white-space: nowrap;
  box-shadow: 0 0 0 0 rgba(219, 48, 54, 0.55);
  transition: box-shadow 0.26s cubic-bezier(0.22, 1, 0.36, 1), background 0.2s, transform 0.14s;
}
.call::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #ffffff;
  flex: none;
}
.call:hover {
  background: var(--signal-deep);
  box-shadow: 0 0 0 6px rgba(219, 48, 54, 0.22);
}
.call:active { transform: translateY(1px); }
.call .num { font-family: var(--mono); font-size: 0.85em; opacity: 0.9; white-space: nowrap; }
.call.sm { padding: 8px 16px; font-size: 0.875rem; gap: 9px; }
.call.lg { padding: 16px 32px; font-size: 1.125rem; }

/* Between the gold quote button and the nav links there is not always room for
   the number as well. Drop it in the header only; it is still on the button
   everywhere else, and in the sticky bar on mobile. */
@media (max-width: 1400px) {
  .nav .call .num { display: none; }
}

.request {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 24px;
  border-radius: 999px;
  border: 1px solid var(--bone);
  color: var(--bone);
  font-weight: 500;
  letter-spacing: -0.01em;
  transition: color 0.2s, transform 0.14s;
}
.request::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--bone);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}
.request:hover, .request:focus-visible { color: var(--invert-fg); }
.request:hover::before, .request:focus-visible::before { transform: scaleY(1); }
.request:active { transform: translateY(1px); }

.draw {
  display: inline-block;
  padding-bottom: 4px;
  font-family: var(--mono);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--mist);
  background-image: linear-gradient(var(--signal), var(--signal));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 0.3s cubic-bezier(0.22, 1, 0.36, 1), color 0.2s;
}
.draw:hover, .draw:focus-visible { background-size: 100% 1px; color: var(--bone); }

.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }

/* --------------------------------------------------------------- bands --- */

.band {
  border-top: 1px solid var(--line);
  background: var(--ink);
  padding-block: 64px;
}
.band.night { background: var(--night); }
@media (min-width: 768px) {
  .band { padding-block: 96px; }
}

.plate {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.plate > img.bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.62;
  filter: grayscale(0.3) brightness(1.32) contrast(0.92);
}
.plate::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to right,
      rgba(255, 255, 255, 0.95) 0%,
      rgba(255, 255, 255, 0.82) 44%,
      rgba(255, 255, 255, 0.58) 100%),
    rgba(255, 255, 255, 0.30);
}

.hero { padding-block: 128px 64px; }
@media (min-width: 768px) {
  .hero { padding-block: 176px 96px; }
}

/* ---------------------------------------------------------------- grid --- */

.cards {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 32px;
}
@media (min-width: 640px) { .cards.two, .cards.three, .cards.four { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) {
  .cards.three { grid-template-columns: repeat(3, 1fr); }
  .cards.four { grid-template-columns: repeat(4, 1fr); }
}

.card { background: var(--ink); padding: 28px; display: block; height: 100%; transition: background 0.2s; }
.card.on-night { background: var(--night); }
a.card:hover { background: var(--steel); }
.card img.icon { width: 32px; height: 32px; }
.card .h3 { margin-top: 20px; }
.card p { margin-top: 12px; color: var(--mist); }

.step-n { font-family: var(--mono); font-size: 0.875rem; color: var(--signal); }

/* ----------------------------------------------------------------- zip --- */

.zips {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
@media (min-width: 640px) { .zips { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 768px) { .zips { grid-template-columns: repeat(6, 1fr); } }

.zips li {
  background: var(--ink);
  padding: 16px 8px;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.875rem;
}

.zip-blob {
  font-family: var(--mono);
  font-size: 0.875rem;
  line-height: 2;
  color: var(--mist);
  word-break: break-word;
}

/* --------------------------------------------------------------- lists --- */

.split { display: grid; gap: 40px; }
/* Grid items default to min-content width, so one nowrap value inside (the
   spec rows) was pushing the whole column past the viewport on a phone. */
.split > * { min-width: 0; }
@media (min-width: 768px) {
  .split { grid-template-columns: repeat(12, 1fr); gap: 64px; }
  .c4 { grid-column: span 4; }
  .c5 { grid-column: span 5; }
  .c7 { grid-column: span 7; }
  .c8 { grid-column: span 8; }
  .c6 { grid-column: span 6; }
}

.ticks { margin-top: 24px; display: grid; gap: 12px; }
.ticks li { display: flex; gap: 12px; font-size: 1.0625rem; }
.ticks li::before {
  content: "";
  margin-top: 11px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--signal);
  flex: none;
}

.rows { border-block: 1px solid var(--line); }
.rows li, .rows > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  padding-block: 18px;
  border-bottom: 1px solid var(--line);
}
.rows > *:last-child { border-bottom: 0; }
.rows dd, .rows .val { font-family: var(--mono); font-size: 0.875rem; color: var(--mist); white-space: nowrap; margin: 0; }
/* On a narrow screen the value is allowed to wrap rather than force the row
   wider than the screen. */
@media (max-width: 639px) {
  .rows dd, .rows .val { white-space: normal; text-align: right; }
}

.chips { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
.chips a {
  display: inline-block;
  padding: 8px 20px;
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: border-color 0.2s, color 0.2s;
}
.chips a:hover { border-color: var(--bone); }
.chips a.all { font-family: var(--mono); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.18em; color: var(--mist); }
.chips a.all:hover { color: var(--bone); }

.linklist { display: grid; gap: 8px; margin-top: 16px; }
.linklist a { transition: color 0.2s; }
.linklist a:hover { color: var(--signal); }

.note-box {
  border: 1px solid var(--line);
  background: var(--steel);
  border-radius: var(--radius);
  padding: 32px;
}
.note-box.warn { border-color: var(--signal); }

.media { border: 1px solid var(--line); border-radius: var(--radius); aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }

/* ----------------------------------------------------------------- faq --- */

.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); padding-block: 24px; }
.faq summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary .q { font-size: 1.125rem; font-weight: 500; letter-spacing: -0.015em; }
.faq .x {
  position: relative;
  margin-top: 6px;
  width: 16px;
  height: 16px;
  flex: none;
  transition: transform 0.3s;
}
.faq details[open] .x { transform: rotate(45deg); }
.faq .x::before, .faq .x::after {
  content: "";
  position: absolute;
  background: var(--mist);
}
.faq .x::before { top: 50%; left: 0; width: 100%; height: 1px; transform: translateY(-50%); }
.faq .x::after { left: 50%; top: 0; height: 100%; width: 1px; transform: translateX(-50%); }
.faq .a { padding-top: 16px; color: var(--mist); max-width: 65ch; }
.faq .a p + p { margin-top: 12px; }

/* ---------------------------------------------------------------- form --- */

.form {
  border: 1px solid var(--line);
  background: var(--night);
  border-radius: var(--radius);
  padding: 24px;
}
@media (min-width: 768px) { .form { padding: 32px; } }

.field { margin-top: 24px; }
.field:first-child { margin-top: 0; }
.field label { display: block; }
.field input, .field select, .field textarea {
  margin-top: 8px;
  width: 100%;
  border: 1px solid var(--line);
  background: var(--ink);
  color: var(--bone);
  border-radius: 10px;
  padding: 12px 16px;
  font: inherit;
  transition: border-color 0.2s;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--signal);
}
.field .help { margin-top: 8px; font-size: 0.875rem; color: var(--mist); }
.field textarea { resize: vertical; min-height: 120px; }

.pair { display: grid; gap: 24px; }
@media (min-width: 640px) { .pair { grid-template-columns: 1fr 1fr; } }

/* Honeypot. Off screen rather than display:none, because some bots skip
   hidden fields but happily fill this one. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ------------------------------------------------------- confirmation --- */

.tick {
  display: inline-grid;
  place-items: center;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  background: var(--signal);
  color: var(--bone);
  box-shadow: 0 0 0 10px rgba(219, 48, 54, 0.14);
}
.tick svg { width: 30px; height: 30px; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 20px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--night);
  font-size: 0.875rem;
  color: var(--mist);
}
.pill .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); flex: none; }

/* --------------------------------------------------------------- prose --- */

.prose { max-width: 68ch; }
.prose p, .prose ul, .prose ol { margin-top: 20px; color: var(--mist); }
.prose ul { list-style: disc; padding-left: 22px; }
.prose ol { list-style: decimal; padding-left: 22px; }
.prose li { margin-top: 8px; }
.prose h2 {
  margin-top: 48px;
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--bone);
}
.prose h3 {
  margin-top: 32px;
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--bone);
}
.prose strong { color: var(--bone); font-weight: 600; }
.prose a,
.prose .prose-link { color: var(--bone); text-decoration: underline; text-underline-offset: 4px; }
.prose a:hover,
.prose .prose-link:hover { color: var(--signal); }

/* -------------------------------------------------------------- footer --- */

.footer { border-top: 1px solid var(--line); background: var(--ink); padding-bottom: 96px; }
@media (min-width: 640px) { .footer { padding-bottom: 0; } }
.footer-grid { display: grid; gap: 48px; padding-block: 64px; }
@media (min-width: 768px) {
  .footer-grid { grid-template-columns: repeat(12, 1fr); padding-block: 80px; }
  .f4 { grid-column: span 4; }
  .f3 { grid-column: span 3; }
  .f2 { grid-column: span 2; }
}
.footer-bottom {
  display: flex;
  flex-direction: column;
  gap: 24px;
  border-top: 1px solid var(--line);
  padding-block: 32px;
}
@media (min-width: 768px) {
  .footer-bottom { flex-direction: row; align-items: center; justify-content: space-between; }
}
.footer-legal { display: flex; flex-wrap: wrap; gap: 12px 32px; }
.footer-legal a,
.footer-legal .linklike {
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--mist);
  transition: color 0.2s;
}
.footer-legal a:hover,
.footer-legal .linklike:hover { color: var(--bone); }
.two-col { columns: 2; column-gap: 24px; }

/* -------------------------------------------------------- social float --- */

/* Bottom left, clear of the call bar that owns the bottom of the screen on
   phones. Neutral until hovered, then each takes its own brand colour. */
/* Sits inside the hero, directly under the Call now / Request service row.
   On the home page the hero stage is sticky for 450dvh, so these stay on
   screen for the whole scrubbed banner instead of scrolling away with it. */
.social-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-top: 16px;
}

/* Gold pill, black label, black glyph - identical at every screen width. */
.soc {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 16px 9px 11px;
  border-radius: 999px;
  border: 1px solid var(--gold-deep);
  background: var(--gold);
  color: var(--gold-ink);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  /* Colour only, never transform, so the buttons cannot shift on hover. */
  transition: background 0.2s, border-color 0.2s;
}
.soc svg { width: 22px; height: 22px; display: block; flex: none; }
.soc span { color: var(--gold-ink); }
/* Both logos forced monochrome: the Instagram gradient's lightest stop
   (#feda75) is almost the same colour as the gold pill behind it. */
.soc svg[fill]:not([fill="none"]) { fill: var(--gold-ink); }
.soc svg [fill]:not([fill="none"]) { fill: var(--gold-ink); }
.soc svg [stroke]:not([stroke="none"]) { stroke: var(--gold-ink); }
.soc:hover {
  background: var(--gold-deep);
  border-color: var(--gold-deep);
}

.footer-social { display: flex; gap: 20px; margin-top: 16px; }
.footer-social a {
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--mist);
  transition: color 0.2s;
}
.footer-social a:hover { color: var(--bone); }

@media (prefers-reduced-motion: reduce) {
  .soc, .soc:hover { transition: none; transform: none; }
}

/* --------------------------------------------------------- sticky call --- */

.sticky-call {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 50;
  border-top: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(8px);
}
.sticky-call a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px 20px;
  font-weight: 600;
}
.sticky-call .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--signal); }
.sticky-call .num { font-family: var(--mono); font-size: 0.875rem; color: var(--mist); }
@media (min-width: 640px) { .sticky-call { display: none; } }

/* ------------------------------------------------------------- cookies --- */

.cookie {
  position: fixed;
  inset-inline: 0;
  bottom: 64px;
  z-index: 50;
  padding-inline: 16px;
}
@media (min-width: 640px) { .cookie { bottom: 16px; } }
.cookie-inner {
  max-width: 780px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  border: 1px solid var(--line);
  background: var(--steel);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 10px 30px rgba(13, 21, 36, 0.14);
}
@media (min-width: 640px) {
  .cookie-inner { flex-direction: row; align-items: center; justify-content: space-between; }
}
.cookie p { font-size: 0.875rem; color: var(--mist); }
.cookie a { color: var(--bone); text-decoration: underline; text-underline-offset: 4px; }
.cookie button {
  flex: none;
  border: 1px solid var(--bone);
  background: transparent;
  color: var(--bone);
  border-radius: 999px;
  padding: 8px 20px;
  font: inherit;
  font-size: 0.875rem;
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}
.cookie button:hover { background: var(--invert-bg); color: var(--invert-fg); }

/* Consent banner actions. Accept and Reject carry equal visual weight so the
   choice is genuine; only the fill differs, for a clear default target. */
.cookie-actions { display: flex; gap: 10px; flex: none; }

/* On a phone the notice is a fixed panel sitting over the page, so it has to
   stay small: tighter padding, smaller type, and buttons that share one row.
   Anything taller starts covering the hero call button. */
.cookie-inner { padding: 14px 16px; gap: 12px; }
.cookie p { font-size: 0.8125rem; line-height: 1.45; }
.cookie-actions button { padding: 9px 18px; min-height: 40px; }
@media (min-width: 640px) {
  .cookie-inner { padding: 20px; gap: 16px; }
  .cookie p { font-size: 0.875rem; }
}

/* While the notice is up it must not be the thing that hides the end of the
   page. site.js measures it and publishes the height here, so the document
   gains exactly that much room to scroll past. It returns to 0 on dismiss. */
body { padding-bottom: var(--jb-cookie-h, 0px); }
.cookie-actions button { flex: 1 0 auto; white-space: nowrap; }
.cookie button.cookie-yes { background: var(--bone); color: var(--invert-fg); }
.cookie button.cookie-yes:hover { background: var(--invert-bg); color: var(--invert-fg); }

/* A button that has to sit in a list of links and read as one. */
.linklike {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
}

/* ---------------------------------------------------------- scroll film --- */

.scrub { position: relative; background: var(--ink); }
.scrub-stage {
  position: sticky;
  top: 0;
  height: 100dvh;
  overflow: hidden;
}
.scrub-stage video,
.scrub-stage img.poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The poster is held until the clip has painted a real frame, then faded so
   there is never a black box between the two. */
.scrub-stage img.poster {
  z-index: 1;
  transition: opacity 0.45s ease;
}
.scrub-stage video { z-index: 0; }
.scrub-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to right,
    rgba(255, 255, 255, 0.95) 0%,
    rgba(255, 255, 255, 0.82) 45%,
    rgba(255, 255, 255, 0.55) 100%
  );
}
.scrub-copy {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
}
.scrub-copy .inner { max-width: 640px; }
.scrub-copy .display { margin-top: 20px; }
.scrub-copy .lede { margin-top: 20px; color: var(--bone); }
.scrub-copy .cta-row { margin-top: 32px; }
.scrub-tags { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }
.scrub-tags li {
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--mist);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 14px;
}
/* Scroll distance the film is played over. */
.scrub-track { height: 450dvh; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .scrub-track { height: auto; }
  .scrub-stage { position: relative; height: 70dvh; }
  .call, .request, .request::before, .draw, .faq .x { transition: none; }
}


/* --------------------------------------------------- light hero surfaces ---
   The hero sections used to sit on a dark scrim over photography, so the token
   roles flipped to light-on-dark inside them. The scrim is white now, so the
   root tokens are already correct and only the hairline needs a touch more
   presence than it has over flat white. */
.plate,
.scrub-copy {
  --line: #ccd7e6;
  --steel: #eef3f9;
  color: var(--bone);
}
.plate .lede,
.scrub-copy .lede { color: var(--mist); }


/* --------------------------------------------------- native control reset ---
   With color-scheme now light, native buttons and fields default to the
   browser's own grey. Everything here is styled by the design system, so
   opt out of the UA appearance explicitly. */
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; }
.request, button.request { background: transparent; }


/* ------------------------------------------------------ sticky call bar ---
   Two actions, not one. Texting works on a signal too weak to hold a call,
   and lets someone send their location instead of describing it. */
.sticky-call { display: flex; }
/* This section re-declares display, which would otherwise beat the mobile-only
   rule further up the file and leave the bar floating over the footer on
   desktop. Re-assert the breakpoint here, after it. */
@media (min-width: 640px) { .sticky-call { display: none; } }
.sticky-call a:first-child { flex: 1 1 0; min-width: 0; padding-inline: 12px; }
.sticky-call .sticky-text {
  flex: 0 0 auto;
  padding-inline: 16px;
  border-left: 1px solid var(--line);
  color: var(--signal);
  font-weight: 600;
}


/* ============================================================ mobile pass ===
   Tuned against real device widths, including 360px, which is still one of
   the most common Android viewports and where the layout was overflowing. */

@media (max-width: 480px) {
  /* Nothing may exceed the viewport. Deliberately `clip`, not `hidden`:
     overflow-x:hidden turns body into a scroll container, which silently
     disables position:sticky everywhere inside it (it broke the cutaway on
     the story page). `clip` trims the same overflow without that side effect,
     and where it is unsupported the rule is simply dropped. */
  html, body { overflow-x: clip; }

  /* Text small enough to force a pinch-zoom is text a stranded driver
     will not read. Nothing drops below 13px. */
  /* Written at matching specificity so these actually beat the desktop rules. */
  .call .num, .sticky-call .num, .nav .num { font-size: 0.85rem; }
  body .eyebrow { font-size: 0.85rem; letter-spacing: 0.14em; }
  body .label, body .mono, body .chips a, body .scrub-tags li,
  body .foot-note, body .draw { font-size: 0.85rem; }
  body .footer-legal a, body .footer-legal .linklike, body .footer-social a,
  body .nav-links > li > a { font-size: 0.85rem; }
  body { font-size: 17px; }

  /* Touch targets. 44px is the minimum comfortable size, and this audience
     is often using one cold hand. */
  .navtoggle { width: 46px; height: 46px; }
  .brand { min-height: 44px; }
  .soc { min-height: 44px; }
  .sticky-call a { min-height: 52px; }
  .nav-ctas .call.sm { min-height: 44px; }
  /* The same small call button also appears in page body copy (the FAQ block
     on the home page), where the nav-scoped rule above does not reach it. */
  .call.sm { min-height: 44px; }

  /* The link lists are most of the site's tap surface on a phone, and a bare
     line box is only about 20px tall. Give each row a real height so a cold
     thumb hits the right one, and keep the rows visually separated. */
  .linklist a,
  .footer-legal a,
  .footer-legal .linklike,
  .footer-social a,
  .nav-links > li > a,
  .submenu a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .linklist { gap: 0; }

  /* Only the summary toggles a details, not the padding around it, so the
     question itself has to carry the tap area. */
  .faq summary { min-height: 44px; }

  /* Buttons go full width so they are unmissable. */
  .cta-row .call,
  .cta-row .request { width: 100%; }
  .cta-row { gap: 12px; }

  /* The scroll-scrubbed hero centres its copy in the viewport, which pushed
     the first line up under the fixed header. Pad past the header height. */
  .scrub-copy { padding-top: 88px; }
  .plate .wrap { padding-block: 24px; }
}

@media (max-width: 380px) {
  /* At the very narrow end the dialling code is redundant - tapping calls it. */
  .sticky-call .num { display: none; }
  .brand-txt small { display: none; }
}


/* =========================================================== home hero ===
   The homepage hero is now a photograph rather than video. The flat 85%
   scrim the other heroes use would bury it, so this one uses a gradient
   weighted to the side the headline sits on: dark where the type is,
   open where the van and skyline are. */
.home-hero { min-height: 86vh; display: flex; align-items: center; padding-block: 140px 72px; }
.home-hero::after {
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.93) 0%,
    rgba(255, 255, 255, 0.82) 45%,
    rgba(255, 255, 255, 0.88) 100%);
}
@media (min-width: 900px) {
  .home-hero::after {
    background: linear-gradient(100deg,
      rgba(255, 255, 255, 0.96) 0%,
      rgba(255, 255, 255, 0.90) 34%,
      rgba(255, 255, 255, 0.66) 64%,
      rgba(255, 255, 255, 0.50) 100%);
  }
}
.home-hero .bg { object-position: 70% 50%; }
@media (max-width: 899px) { .home-hero .bg { object-position: 76% 50%; } }
@media (max-width: 480px) { .home-hero { min-height: 78vh; padding-block: 108px 56px; } }

/* ========================================================== our story ===
   Depth is used to carry the chronology: each era sits on its own plane and
   rotates upright as it reaches the viewport, so scrolling the page reads
   as walking forward through the years rather than sliding sideways. */
.story-scene { perspective: 1400px; perspective-origin: 50% 40%; }
.story-era {
  position: relative;
  transform-style: preserve-3d;
  transform: translateZ(-220px) rotateX(9deg) translateY(28px);
  opacity: 0;
  transition: transform 1s cubic-bezier(.22,.8,.26,1), opacity .9s ease;
  background: var(--night);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 32px;
}
.story-era.inview { transform: none; opacity: 1; }
.story-era + .story-era { margin-top: 28px; }
.story-year {
  font-family: var(--mono);
  font-size: 2.4rem;
  font-weight: 500;
  color: var(--signal);
  letter-spacing: -0.02em;
  line-height: 1;
  transform: translateZ(60px);
  display: inline-block;
}
.story-era h3 { margin: 14px 0 10px; transform: translateZ(34px); }
.story-era p { transform: translateZ(18px); }

/* Cards that lean toward the pointer. Subtle, and disabled for touch. */
.tilt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; perspective: 900px; }
.tilt {
  background: var(--night);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  transform-style: preserve-3d;
  transition: transform .25s ease, border-color .25s ease;
  will-change: transform;
}
.tilt:hover { border-color: var(--signal); }
.tilt .tilt-in { transform: translateZ(40px); }
.tilt .big {
  font-family: var(--display);
  font-size: 2.1rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  display: block;
  font-variant-numeric: tabular-nums;
}

/* A battery rendered as a real box in space, turning slowly. Six faces, no
   library and no image, so the case label stays crisp at any size.

   The box is W x H x D and centred on its own origin. Each face is placed at
   half of the axis it faces: the side faces are D wide and pushed out by W/2,
   the top and bottom are D tall and pushed out by H/2. The previous version
   mixed those offsets up, which is what left one side hanging out of the box
   and slicing through the paragraph above it. */
/* ======================================================= the cutaway shot ===
   Two photographs of the same battery, sealed and taken apart, stacked and
   cross-faded by --x as the rail scrolls past. CSS owns the whole transition;
   site.js only sets the number. */

/* The CSS battery always renders, so the rail always has its full height. */
.cut-rail { position: relative; height: 280vh; }
.cut-stage {
  --x: 0;
  --legend: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}
.cut-scene,
.cut-cap,
.cut-legend { position: absolute; left: 0; right: 0; }
.cut-scene {
  top: 84px;
  bottom: calc(92px + var(--jb-cookie-h, 0px));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-inline: 20px;
  perspective: 1500px;
  perspective-origin: 50% calc(48% - var(--x) * 22%);
  transform: translateY(calc(var(--x) * 92px)) scale(calc(1 - var(--x) * 0.08));
  will-change: transform;
}
.cut-stage.is-photo .cut-scene { perspective: none; transform: none; }
.cut-cap { bottom: calc(58px + var(--jb-cookie-h, 0px)); }
.cut-legend { bottom: calc(20px + var(--jb-cookie-h, 0px)); }

/* The frame holds the 3:2 shots and never grows past the free band, so the
   battery is always whole on screen rather than cropped. */
.cut-shot {
  position: relative;
  margin: 0;
  width: min(100%, 1080px);
  aspect-ratio: 3 / 2;
  max-height: 100%;
}
.shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* The pair is one object coming apart, so they scale together very slightly
     as the swap happens rather than sitting dead still. */
  transform: scale(calc(1 + var(--x) * 0.03));
  will-change: opacity, transform;
}
.shot-sealed { opacity: calc(1 - var(--x)); }
.shot-open   { opacity: var(--x); }

/* ======================================================= the cutaway cell ===
   A lead-acid car battery, built to the real thing's proportions: a long low
   case (roughly 2:1 against its height), six cells in a row behind five cast
   partitions, a plate group per cell, and a moulded cover carrying six vent
   caps and the two tapered posts.

   Scrolling the rail drives --x from 0 (sealed) to 1 (apart). CSS owns where
   every part sits for a given --x; site.js only sets the number and the
   viewing angle, so scroll and drag never fight over one transform. */


.cell {
  --w: 320px;               /* length  */
  --h: 152px;               /* height  */
  --d: 152px;               /* width   */
  --pitch: calc(var(--w) / 6);
  position: relative;
  width: var(--w);
  height: var(--h);
  transform-style: preserve-3d;
  will-change: transform;
  transform: rotateX(-14deg) rotateY(-32deg);
  cursor: grab;
  touch-action: pan-y;
  outline: none;
}
.cell.is-held { cursor: grabbing; }
.grp { position: absolute; inset: 0; transform-style: preserve-3d; }

/* ---- shared face treatment ---- */
.fc {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--w);
  height: var(--h);
  border-radius: 5px;
  background: linear-gradient(168deg, #2f342e 0%, #1b1e1a 56%, #0c0e0c 100%);
  box-shadow:
    inset 0 0 0 1px rgba(166, 210, 75, 0.13),
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -22px 40px rgba(0, 0, 0, 0.45);
}
.fc.f::after,
.fc.bk::after,
.fc.l::after,
.fc.r::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(128deg, rgba(255,255,255,0.13) 0%, rgba(255,255,255,0.04) 26%, rgba(255,255,255,0) 56%);
}

/* ---- case ---- */
.fc.f  { transform: translateZ(calc(var(--d) / 2)); }
.fc.bk { transform: rotateY(180deg) translateZ(calc(var(--d) / 2)); }
.fc.l,
.fc.r {
  width: var(--d);
  left: calc((var(--w) - var(--d)) / 2);
  background: linear-gradient(168deg, #262a24 0%, #0a0c0a 100%);
}
.fc.l { transform: rotateY(-90deg) translateZ(calc(var(--w) / 2)); }
.fc.r { transform: rotateY(90deg)  translateZ(calc(var(--w) / 2)); }
.fc.bt {
  height: var(--d);
  top: calc((var(--h) - var(--d)) / 2);
  transform: rotateX(-90deg) translateZ(calc(var(--h) / 2));
  background: #070806;
}
/* Cast partitions between the six cells. Only ever seen once the cover and
   the plate groups are out, which is exactly when they should appear. */
.part {
  position: absolute;
  width: var(--d);
  height: calc(var(--h) - 10px);
  top: 10px;
  left: calc((var(--w) - var(--d)) / 2);
  background: linear-gradient(168deg, #23261f, #101208);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.05);
  transform: rotateY(90deg) translateZ(calc(var(--w) / 2 - var(--p) * var(--pitch)));
}

/* ---- cover ---- */
.grp.lid {
  --lh: 22px;
  transform: translateY(calc(var(--x) * -250px));
}
.fc.l-top,
.fc.l-bot {
  height: var(--d);
  top: calc((var(--h) - var(--d)) / 2);
}
.fc.l-top {
  transform: rotateX(90deg) translateZ(calc(var(--h) / 2 + var(--lh)));
  background: linear-gradient(168deg, #43483f 0%, #1e211b 100%);
  transform-style: preserve-3d;
}
.fc.l-bot {
  transform: rotateX(90deg) translateZ(calc(var(--h) / 2));
  background: #14160f;
}
.fc.l-f,
.fc.l-bk,
.fc.l-l,
.fc.l-r {
  height: var(--lh);
  top: calc(-1 * var(--lh));
  background: linear-gradient(180deg, #383d34 0%, #14160f 100%);
}
.fc.l-f  { transform: translateZ(calc(var(--d) / 2)); }
.fc.l-bk { transform: rotateY(180deg) translateZ(calc(var(--d) / 2)); }
.fc.l-l,
.fc.l-r { width: var(--d); left: calc((var(--w) - var(--d)) / 2); }
.fc.l-l { transform: rotateY(-90deg) translateZ(calc(var(--w) / 2)); }
.fc.l-r { transform: rotateY(90deg)  translateZ(calc(var(--w) / 2)); }

/* Six vent caps in a row, one per cell, sunk into the cover. */
.cap {
  position: absolute;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  top: calc(50% - 13px);
  left: calc(var(--n) * var(--pitch) + var(--pitch) / 2 - 13px);
  background: radial-gradient(circle at 38% 32%, #464c42, #191c16 72%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.07), 0 1px 2px rgba(0,0,0,0.5);
  transform: translateZ(3px);
}
/* The two posts: tapered lead, red for positive and dark for negative, on the
   diagonal corners the way they sit on a real top-post battery. */
.post {
  position: absolute;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  transform-style: preserve-3d;
  transform: translateZ(calc(5px + var(--x) * 7px));
  box-shadow: 0 2px 5px rgba(0,0,0,0.55);
}
.post-cap {
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  transform: translateZ(7px);
}
.post.pos {
  left: 30px;
  top: 22px;
  background: radial-gradient(circle at 36% 30%, #8d9488, #4d5348 68%, #23271f);
}
.post.pos .post-cap { background: radial-gradient(circle at 36% 30%, #ef7d80, #c62b31 62%, #7d1418); }
.post.neg {
  right: 30px;
  bottom: 22px;
  background: radial-gradient(circle at 36% 30%, #8d9488, #4d5348 68%, #23271f);
}
.post.neg .post-cap { background: radial-gradient(circle at 36% 30%, #6a7065, #33382f 62%, #14170f); }

/* ---- the six element groups ---- */
.grp.stack {
  /* No opacity here on purpose: any value below 1 gives the group its own
     stacking context, which flattens preserve-3d and collapses the plates
     into one flat sheet. The case walls already hide them when sealed. */
  transform: translateY(calc(var(--x) * -168px));
}
.cellgrp { position: absolute; inset: 0; transform-style: preserve-3d; }

/* Plates stand across the case and stack along its length, as they do in the
   real thing: each plate faces the end of the battery, not the front. */
.pl {
  position: absolute;
  width: calc(var(--d) - 30px);
  height: calc(var(--h) - 46px);
  left: calc((var(--w) - var(--d)) / 2 + 15px);
  top: 26px;
  border-radius: 2px;
  box-shadow: 0 0 2px rgba(0,0,0,0.55);
  transform:
    rotateY(90deg)
    translateZ(calc(
      var(--w) / 2
      - (var(--c) + 0.5) * var(--pitch)
      - (var(--i) - 2) * (4px + var(--x) * 3.4px)
    ));
}
.pl.neg {
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,0.07) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(0deg, rgba(255,255,255,0.07) 0 1px, transparent 1px 8px),
    linear-gradient(168deg, #414340, #232522);
}
.pl.pos {
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,0.17) 0 1px, transparent 1px 8px),
    repeating-linear-gradient(0deg, rgba(0,0,0,0.17) 0 1px, transparent 1px 8px),
    linear-gradient(168deg, #9d6437, #653d1f);
}
.pl.sep { background: linear-gradient(168deg, #efebe1, #c9c3b6); }

/* The cast strap that ties one cell's plates together and links to the next. */
.strap {
  position: absolute;
  width: calc(var(--pitch) - 8px);
  height: 11px;
  top: 14px;
  left: calc(var(--c) * var(--pitch) + 4px);
  border-radius: 3px;
  background: linear-gradient(180deg, #c3cabd, #6c7367);
  box-shadow: 0 1px 2px rgba(0,0,0,0.55);
  transform: translateZ(0);
}

/* ---- the label ---- */
.cell-label {
  position: absolute;
  inset: auto 16px 16px 16px;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: #f1f4ec;
}
.cell-bolt {
  width: 15px;
  height: 30px;
  fill: #eef3e4;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.45));
  flex: none;
}
.cell-mark {
  font-family: var(--display);
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.cell-rule {
  width: 2px;
  height: 22px;
  border-radius: 2px;
  background: linear-gradient(180deg, #A6D24B, #2E7038);
  flex: none;
}
.cell-sub {
  font-family: var(--mono);
  font-size: 0.5rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #93a08c;
}

.cell-shadow {
  width: 360px;
  height: 30px;
  margin-top: 30px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(12,16,12,0.30), rgba(12,16,12,0) 70%);
  transform: scaleX(calc(1 + var(--x, 0) * 0.12));
}

/* A phone gets a smaller battery and shorter travel, so the whole assembly
   still fits the band between the header and the legend. */
@media (max-width: 640px) {
  .cut-rail { height: 240vh; }
  .cell { --w: 232px; --h: 110px; --d: 110px; }
  .fc { border-radius: 4px; }
  .pl { width: calc(var(--d) - 22px); height: calc(var(--h) - 34px); left: calc((var(--w) - var(--d)) / 2 + 11px); top: 19px; }
  .cap { width: 18px; height: 18px; top: calc(50% - 9px); left: calc(var(--n) * var(--pitch) + var(--pitch) / 2 - 9px); }
  .post { width: 24px; height: 24px; }
  .strap { height: 8px; top: 10px; }
  .grp.lid { --lh: 16px; transform: translateY(calc(var(--x) * -168px)); }
  .grp.stack { transform: translateY(calc(var(--x) * -108px)); }
  .cut-scene { transform: translateY(calc(var(--x) * 66px)) scale(calc(1 - var(--x) * 0.1)); }
  .cell-shadow { width: 250px; }
  .cell-label { inset: auto 10px 10px 10px; gap: 7px; }
  .cell-mark { font-size: 0.8rem; }
  .cell-bolt { width: 12px; height: 24px; }
  .cut-legend { gap: 6px 16px; font-size: 0.56rem; }
}


/* ------------------------------------------------- which one is showing ---
   The CSS battery is what ships and what everyone sees. If the two photographs
   are ever dropped into assets/kit/, site.js confirms they load and adds
   .is-photo, and the page swaps to them. Neither state leaves a gap. */
.cut-shot { display: none; }
.cut-stage.is-photo .cell,
.cut-stage.is-photo .cell-shadow { display: none; }
.cut-stage.is-photo .cut-shot { display: block; }
.cut-stage.is-photo .cut-scene { display: flex; align-items: center; }

/* ---- caption and legend ---- */
.cut-cap {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--mist);
  opacity: calc(0.75 - var(--x) * 0.75);
  text-align: center;
}
.cut-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 22px;
  max-width: 660px;
  margin-inline: auto;
  padding: 0 20px;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mist);
  opacity: var(--legend, 0);
  transition: opacity 0.3s ease;
}
.cut-legend li { display: flex; align-items: center; gap: 8px; }
.sw { width: 10px; height: 10px; border-radius: 2px; flex: none; }
.sw-lid  { background: linear-gradient(160deg, #43483f, #1e211b); }
.sw-pos  { background: linear-gradient(160deg, #9d6437, #653d1f); }
.sw-sep  { background: linear-gradient(160deg, #efebe1, #c9c3b6); }
.sw-neg  { background: linear-gradient(160deg, #414340, #232522); }
.sw-case { background: linear-gradient(160deg, #2f342e, #0c0e0c); }

@media (max-width: 640px) {
  .cut-rail { height: 230vh; }
  .cut-scene { top: 76px; padding-inline: 12px; }
  .cut-legend { gap: 6px 16px; font-size: 0.56rem; }
}

@media (prefers-reduced-motion: reduce) {
  .story-era { transform: none; opacity: 1; transition: none; }
  .tilt { transition: none; }
}


/* Nav labels must not break across lines - "Our story" was wrapping. */
.nav-links > li > a { white-space: nowrap; }

/* =========================================================== motion layer ===
   Start states and chrome for assets/js/motion-enhance.js.

   The .jb-anim class is added by a one-line guard in <head> and removed either
   by the module (which has taken the start states over inline by then) or by
   the guard's own failsafe timer. So if the module fails to load, is blocked,
   or the browser cannot run modules, every rule below stops applying and the
   page is exactly what it was before.

   The selector list here mirrors REVEAL in motion-enhance.js. Keep in sync. */

html.jb-anim .hero .inner > *,
html.jb-anim .band > .wrap > .h2,
html.jb-anim .band > .wrap > .lede,
html.jb-anim .cards > .card,
html.jb-anim .wrap.split > .c5,
html.jb-anim .wrap.split > .c6,
html.jb-anim .wrap.split > .c7,
html.jb-anim .chips > a,
html.jb-anim .band > .wrap > .faq {
  opacity: 0;
}

/* Nav condense. The bar is fixed and already translucent; past the fold it
   picks up a shadow and gives a little height back to the page. */
.nav {
  transition: box-shadow 0.3s cubic-bezier(0.22, 1, 0.36, 1),
              background 0.3s ease;
}
.nav.scrolled {
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 1px 24px rgba(11, 13, 16, 0.09);
}
.nav.scrolled .nav-inner { min-height: 64px; }
.nav-inner { transition: min-height 0.3s cubic-bezier(0.22, 1, 0.36, 1); }

/* Scroll progress. Sits on the nav's bottom edge. */
.jb-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  z-index: 61;
  background: var(--signal);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

/* Where the browser supports scroll-driven animations this runs off the main
   thread and the JS fallback in motion-enhance.js never engages. */
@supports (animation-timeline: scroll()) {
  .jb-progress {
    animation: jb-progress-grow linear;
    animation-timeline: scroll(root block);
  }
}
@keyframes jb-progress-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

@media (prefers-reduced-motion: reduce) {
  .nav, .nav-inner { transition: none; }
  .jb-progress { display: none; }
  html.jb-anim .hero .inner > *,
  html.jb-anim .band > .wrap > .h2,
  html.jb-anim .band > .wrap > .lede,
  html.jb-anim .cards > .card,
  html.jb-anim .wrap.split > .c5,
  html.jb-anim .wrap.split > .c6,
  html.jb-anim .wrap.split > .c7,
  html.jb-anim .chips > a,
  html.jb-anim .band > .wrap > .faq { opacity: 1; }
}

/* ============================================================ phone layout ===
   On a phone the hero copy no longer sits on top of the photograph. The image
   comes out from behind the text and becomes its own band underneath it, so
   the headline, the price and the call button are on flat white and nothing
   competes with them. Desktop is unchanged. */

@media (max-width: 767px) {
  .plate.hero {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-block: 104px 0;
  }
  .plate.hero > .wrap { order: 1; }
  .plate.hero > .bg {
    order: 2;
    position: static;
    z-index: auto;
    width: 100%;
    height: 52vw;
    min-height: 170px;
    max-height: 280px;
    margin-top: 34px;
    /* Out from under the text, so it no longer needs to be washed out. */
    opacity: 1;
    filter: none;
  }
  /* The scrim existed only to keep copy legible over the photo. */
  .plate.hero::after { display: none; }

  /* Texture plates keep their ground but go flat behind the copy. */
  .plate.band::after { background: rgba(255, 255, 255, 0.95); }
  .plate.band > .bg { opacity: 0.28; }

  /* Same rule for the scroll film on the story page: copy first, footage
     under it, never one on top of the other. */
  .scrub-copy {
    position: static;
    display: block;
    padding-block: 40px 24px;
  }
  .scrub-stage::after { display: none; }
}

/* The home hero's phone override set a viewport height for the old full-bleed
   treatment. With the image lifted out, the section is as tall as its content. */
@media (max-width: 480px) {
  .home-hero { min-height: 0; padding-block: 104px 0; }
}

/* Inline text links that act as primary navigation get a real tap target on
   touch screens without changing how they look. */
@media (max-width: 767px) {
  .draw { display: inline-flex; align-items: center; min-height: 44px; }
  .chips a { min-height: 44px; display: inline-flex; align-items: center; }
}
