/* =============================================================================
   GB Tooling — site.css

   The original Wix reconstruction's visual system (measurements in
   docs/WIX-AUDIT.md, including its dated departures section) carried forward
   as the five-page site. Same materials — ink ground,
   1px paper rules, Syne display, Nunito Sans wordmark, the 1440px design
   unit — extended with the components the new pages need: promo marquee,
   nav, comparison board, part cards, rig tour, ledgers, act rows.
   ========================================================================== */

/* ----------------------------------------------------------------- tokens */
:root {
  --ink:        #191a1b;
  --ink-2:      #1b2530;          /* lifted plate on ink, warmed to the blue  */
  --paper:      #ffffff;          /* body text — never an accent, see below   */

  /* Brushed blue metal, sampled off the client's own logo plates.
     #295887 is 2.36:1 on --ink, so the logo blue can only ever be a FILL
     (white on it is 7.39:1). Anything that reads AS TEXT on ink uses
     --accent, the same 210deg hue lifted to 6.25:1. Two roles, one colour. */
  --metal-lo:   #1b4369;
  --metal-mid:  #295887;
  --metal-hi:   #4679a8;
  /* the crest of --brushed-text: white on it is 5.47:1, which leaves headroom
     for the grain overlay and for how the rake lands on a narrow button */
  --metal-crest: #3c6d99;
  --metal-spec: #7ba6d0;
  --accent:     #6f9fce;
  --on-metal:   #ffffff;

  --rule:       #5f8fbe;          /* firm 1px rules                          */
  --rule-soft:  rgba(122, 163, 206, .55);
  --rule-faint: rgba(122, 163, 206, .26);
  --field-rule: rgba(122, 163, 206, .62);
  --watermark:  #24384c;
  --muted:      #c2c2c2;
  --muted-2:    #9a9a9a;          /* only on ink, large/secondary text       */
  /* error state is set from site.js; it lives here so no colour is authored
     outside :root (AGENTS.md) */
  --status-error: #ff8a80;

  --header-h:   68px;
  --promo-h:    46px;

  /* column stops from the 1440 reference */
  --col-a:  50%;
  --col-s:  79.6528%;
  --col-f:  36.1806%;

  /* 1 design unit = 1px at 1440, scaling down, floored at 1180 */
  --u: clamp(0.8194px, 0.0694444vw, 1px);
  --pad: calc(51 * var(--u));

  --font-display: "Syne", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mark:    "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

  accent-color: var(--accent);
}

/* ------------------------------------------------------------------ reset */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  caret-color: var(--paper);
}

h1, h2, h3, p, ul, ol, dl, dd, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }

::selection { background: var(--paper); color: var(--ink); }
html { scrollbar-color: var(--watermark) var(--ink); }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  padding: 10px 16px; background: var(--paper); color: var(--ink);
}
.skip-link:focus { left: 0; }

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

/* --------------------------------------------------------------- wordmark */
/* "G B" in Nunito Sans, letters on one baseline. The original mark set a 1px
   rule rotated 21deg between them; this version drops it. */
.wordmark {
  --wm-b-x: .78em;  --wm-b-y: 0em;
  position: relative;
  display: inline-block;
  flex: none;
  width: 1.64em;
  height: 1.583em;
  font-family: var(--font-mark);
  font-size: 36px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--paper);
}
.wordmark__g, .wordmark__b { position: absolute; top: 0; left: 0; }
.wordmark__b { left: var(--wm-b-x); top: var(--wm-b-y); }
.wordmark--dark { color: var(--ink); }

/* Header lockup: the mark, then the company name set small and tracked, both
   sitting on the mark's own baseline.

   Three corrections, all measured on the rendered page after
   document.fonts.ready — Nunito Sans, 36u mark against a 15u name:

   1. WIDTH. The .wordmark box is 1.64em, but the B's ink stops at
      .78em (--wm-b-x) + .6143em (the B's right ink edge) = 1.3943em. The box
      was carrying 8.84u of dead air on its right, so every gap written after
      the mark rendered 8.84u wider than its number — which is why the name
      sat closer to the divider than to the mark it names. Trimmed to the ink.
   2. SIZE + CAP-CENTRE. At 15u the name's cap band was 10.7u against the
      mark's 25.7u, so whatever the alignment, 15u of the mark's height stayed
      empty — sitting it on the mark's baseline just moved the whole void
      above it. At 26u the name's caps measure 18.6u, which closes the void to
      2.9u a side, and the two are cap-centred rather than box-centred: the
      measured offset between the mark's cap centre and the name's is 1.44u.
      The nudge is relative, so the mark itself stays centred in the header,
      and it is linear in --u, so one value holds at every breakpoint.
   3. TRACKING. .14em letter-spacing leaves 2.1u of air after the final G of
      TOOLING. Pulling the box back to the ink is what lets the divider sit on
      equal air either side. */
.brand { display: flex; align-items: center; gap: calc(12 * var(--u)); }
.brand .wordmark { width: 1.3943em; height: 1.3em; }
.brand--dark .brand__name { color: #4a4c4e; }
.brand__name {
  position: relative;
  top: calc(1.44 * var(--u));
  margin-right: -.14em;
  font-family: var(--font-mark);
  font-size: calc(26 * var(--u));
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}
.wordmark--xl {
  /* same letter geometry as the base mark, only larger */
  height: 1.4em;
  font-size: calc(125.4 * var(--u));
}

/* --------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border: 0;
  border-radius: 0;
  cursor: pointer;
  text-align: center;
  transition: background-color .18s ease, color .18s ease;
}
.btn--solid {
  min-width: calc(150 * var(--u));
  height: calc(41 * var(--u));
  padding: 0 calc(22 * var(--u));
  background: var(--paper);
  color: var(--ink);
  font-size: calc(15 * var(--u));
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.btn--solid:hover { background: var(--muted); }

.btn--line {
  min-width: calc(150 * var(--u));
  height: calc(41 * var(--u));
  padding: 0 calc(22 * var(--u));
  background: transparent;
  color: var(--paper);
  box-shadow: inset 0 0 0 1px var(--rule-soft);
  font-size: calc(15 * var(--u));
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.btn--line:hover { background: var(--paper); color: var(--ink); box-shadow: none; }

.btn--ghost {
  width: 100%;
  height: calc(102 * var(--u));
  margin-top: auto;
  border-top: 1px solid var(--rule);
  background: transparent;
  color: var(--paper);
  font-size: calc(16 * var(--u));
  letter-spacing: .04em;
  text-transform: uppercase;
}
.btn--ghost:hover { background: var(--paper); color: var(--ink); }

.btn--submit {
  width: 100%;
  height: calc(41 * var(--u));
  background: var(--paper);
  color: var(--ink);
  font-size: calc(16 * var(--u));
  line-height: 1.2;
}
.btn--submit:hover { background: var(--muted); }

/* ------------------------------------------------------------ promo strip */
/* GB Market walkthrough marquee: one strip, content duplicated once for the
   seamless loop; the duplicate is aria-hidden. Buttons open the step dialog. */
.promo {
  position: relative;
  height: var(--promo-h);
  background: var(--ink);
  border-bottom: 1px solid var(--rule-faint);
  overflow: hidden;
}
.promo__track {
  display: flex;
  width: max-content;
  height: 100%;
  animation: promo-run 46s linear infinite;
}
/* :has(:focus-visible), not :focus-within — clicking a step opens the dialog
   and the browser restores focus to that button on close, which under
   :focus-within left the marquee paused forever. Keyboard focus still pauses
   it; a mouse click no longer does. */
.promo:hover .promo__track,
.promo:has(:focus-visible) .promo__track,
.promo.is-paused .promo__track { animation-play-state: paused; }
@keyframes promo-run { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.promo__pause {
  position: absolute;
  right: 0; top: 0; bottom: 0;
  z-index: 2;
  width: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-left: 1px solid var(--rule-faint);
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
}
.promo__pause:hover { background: var(--ink-2); }
.promo__pause .ic-play { display: none; }
.promo.is-paused .promo__pause .ic-pause { display: none; }
.promo.is-paused .promo__pause .ic-play { display: block; }
.promo__track { padding-right: 46px; }

.promo__set { display: flex; align-items: center; height: 100%; }
.promo__lead {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 0 22px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.promo__lead::after {
  content: "";
  width: 34px; height: 1px;
  background: var(--rule-soft);
}
.promo__step {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 100%;
  padding: 0 22px;
  border: 0;
  background: transparent;
  color: var(--paper);
  cursor: pointer;
  white-space: nowrap;
  font-size: 14px;
}
.promo__step:hover { background: var(--ink-2); }
.promo__step b { font-family: var(--font-mark); font-weight: 800; font-size: 13px; color: var(--muted); }
.promo__step img {
  height: 32px; width: auto;
  border: 1px solid var(--rule-faint);
  background: var(--paper);
}
.promo__step::after {
  content: "";
  align-self: center;
  width: 1px; height: 16px;
  margin-left: 22px;
  background: var(--rule-faint);
}

@media (prefers-reduced-motion: reduce) {
  .promo { overflow-x: auto; }
  .promo__track { animation: none; width: max-content; }
  .promo__set[aria-hidden="true"] { display: none; }
}

/* ------------------------------------------------------------ step dialog */
.stepdlg {
  width: min(92vw, 860px);
  border: 1px solid var(--rule-soft);
  padding: 0;
  background: var(--ink);
  color: var(--paper);
}
.stepdlg::backdrop { background: rgba(12, 13, 14, .82); }
.stepdlg__inner {
  display: grid;
  grid-template-columns: minmax(0, 320px) 1fr;
}
.stepdlg__shot { background: var(--ink-2); padding: 26px; display: flex; justify-content: center; }
.stepdlg__shot img { max-height: min(70vh, 640px); width: auto; border: 1px solid var(--rule-faint); }
.stepdlg__copy { padding: 30px 30px 26px; display: flex; flex-direction: column; gap: 14px; }
.stepdlg__copy .k { font-family: var(--font-mark); font-weight: 800; font-size: 13px; letter-spacing: .12em; color: var(--muted); }
.stepdlg__copy h2 { font-size: 26px; font-weight: 700; line-height: 1.2; }
.stepdlg__copy p { color: var(--muted); font-size: 15px; }
.stepdlg__nav { margin-top: auto; display: flex; gap: 10px; }
.stepdlg__close {
  position: absolute; top: 0; right: 0;
  width: 46px; height: 46px;
  border: 0; border-left: 1px solid var(--rule-faint); border-bottom: 1px solid var(--rule-faint);
  background: var(--ink); color: var(--paper);
  font-size: 20px; line-height: 1; cursor: pointer;
}
.stepdlg__close:hover { background: var(--paper); color: var(--ink); }

/* ---------------------------------------------------------------- header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--header-h);
  background: var(--ink);
  border-bottom: 1px solid var(--rule);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(28 * var(--u));
  height: 100%;
  padding: 0 calc(61 * var(--u)) 0 calc(42 * var(--u));
}
.site-header .wordmark { font-size: calc(36 * var(--u)); }
.site-slogan {
  font-size: calc(14 * var(--u));
  line-height: 1.35;
  color: var(--muted);
}
.site-header .site-slogan {
  /* The divider is a cell edge, not a decoration. It used to be as tall as
     whatever two lines of 14u text happened to make (37.8u in a 68u bar) and
     floated clear of both rules, with 8u of air on its left and 11u on its
     right — the residue of clawing back the inner's 28u flex gap. Stretched
     to the full header it lands on the header's own bottom rule, and it moves
     from the Hairline Ladder's row-separator rung (.22) to the interior-grid
     rung (.5) that every other cell edge in the system uses. The negative
     margin now cancels the flex gap and nothing else, so the air either side
     of the rule is equal. */
  align-self: stretch;
  display: flex;
  align-items: center;
  margin-left: calc(-6 * var(--u));
  padding-left: calc(22 * var(--u));
  border-left: 1px solid var(--rule-soft);
}
.site-footer .site-slogan { color: #4a4c4e; margin: calc(10 * var(--u)) 0 0; font-size: calc(13 * var(--u)); }
.site-nav { display: flex; align-items: center; gap: calc(34 * var(--u)); margin-left: auto; }
.site-nav a {
  font-size: calc(15 * var(--u));
  letter-spacing: .02em;
  padding: 6px 0;
  border-bottom: 1px solid transparent;
}
.site-nav a:hover { border-bottom-color: var(--rule-soft); }
.site-nav a[aria-current="page"] { border-bottom-color: var(--rule); }

/* --------------------------------------------------------- language switch
   One link to the other language, not an EN|FR pair: half the width, and it
   is what a bilingual Québec site is expected to look like. It sits inside
   .site-nav so the phone gets it for free — the dropdown lays it out as one
   more full-width row — while on desktop the hairline on its left tells the
   eye it is a control and not a sixth page. The -14u margin halves the 34u
   flex gap so the rule ends up centred in its own gutter, the same trick the
   header slogan uses against the same gap. */
.lang-switch__ab { display: none; }
.site-nav .lang-switch {
  margin-left: calc(-14 * var(--u));
  padding-left: calc(20 * var(--u));
  border-left: 1px solid var(--rule-soft);
  font-weight: 700;
  letter-spacing: .06em;
}
.site-nav .lang-switch__ab { display: inline; }
.site-nav .lang-switch__full { display: none; }
.site-header .btn--solid { min-width: calc(170 * var(--u)); height: calc(33 * var(--u)); font-size: calc(13 * var(--u)); }
.nav-toggle { display: none; }

/* ------------------------------------------------------------------ hero */
.hero {
  position: relative;
  z-index: 0;
  min-height: calc(814 * var(--u));
  background: var(--ink);
  overflow: hidden;
}
.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 42% 55%;
  opacity: .55;
}
.hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: var(--col-a) 1fr 3.5417%;
  grid-template-rows: calc(411 * var(--u)) auto;
  min-height: calc(814 * var(--u));
}
.hero__grid::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: calc(69 * var(--u));
  width: 100%;
  border-top: 1px solid var(--rule-soft);
  pointer-events: none;
}
.hero__cell { position: relative; min-width: 0; }
.hero__cell--title, .hero__cell--logo, .hero__cell--social { border-bottom: 1px solid var(--rule-soft); }
.hero__cell--title, .hero__cell--logo, .hero__cell--tagline, .hero__cell--form { border-right: 1px solid var(--rule-soft); }

/* The right pad is deliberately tighter than --pad: the H1 is the one block
   allowed to run close to the column rule, which is what lets it fill the
   cell instead of sitting in a narrow ragged column. */
.hero__cell--title { display: flex; flex-direction: column; align-items: flex-start; padding: calc(52 * var(--u)) calc(28 * var(--u)) 0 var(--pad); }
/* 60u, not 96u: the H1 now carries the full slogan, which sets as four lines.
   Measured on the rendered page in loaded Syne 800 uppercase, the longest word
   "SOLUTIONS." is 717.6u at 72u against a 617u column (720u cell less 2x51u
   gutter); 60u brings it to 598u. Four lines at 1.02 is 245u, which with the
   60u head pad, the 28u lede margin and a two-line lede leaves ~20u inside the
   411u row. Do not raise this without re-measuring — the old 78u head pad was
   spent to buy the fourth line. */
.hero h1 {
  font-size: calc(64 * var(--u));
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -.02em;
  text-transform: uppercase;
}
.hero__lede {
  margin-top: calc(28 * var(--u));
  max-width: calc(560 * var(--u));
  font-size: calc(18 * var(--u));
  line-height: 1.6;
  color: var(--muted);
}
.hero__lede b { color: var(--paper); font-weight: 700; }

.hero__cell--logo { display: flex; align-items: center; justify-content: flex-end; padding: calc(16 * var(--u)) 0; }
.hero__cell--logo img { width: calc(300 * var(--u)); height: auto; }

.hero__cell--social { display: flex; align-items: flex-end; justify-content: center; padding-bottom: calc(18 * var(--u)); }
.social { display: flex; flex-direction: column; gap: calc(15 * var(--u)); }
.social a { display: flex; align-items: center; justify-content: center; width: calc(30 * var(--u)); height: calc(30 * var(--u)); color: var(--paper); opacity: .9; }
.social a:hover { opacity: 1; }
.social svg { width: calc(23 * var(--u)); height: calc(23 * var(--u)); }

.hero__cell--tagline { display: flex; flex-direction: column; justify-content: flex-end; gap: calc(26 * var(--u)); padding: calc(24 * var(--u)) var(--pad) calc(79 * var(--u)) var(--pad); }
/* Was 36u/400, which read thin and airy at this size — Syne 400 opens up badly
   above ~30u. Bigger, bolder and tracked in, so it holds the cell. */
.hero__cell--tagline p {
  max-width: calc(620 * var(--u));
  font-size: calc(42 * var(--u));
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -.02em;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: calc(14 * var(--u)); }

/* ------------------------------------------------------------- book form */
.hero__cell--form { padding: calc(24 * var(--u)); }
.book { max-width: calc(620 * var(--u)); }

/* Two ways in, one box. The tabs occupy exactly the 42u + 10u the single
   "Book a call:" heading used to, so swapping panels never resizes the hero
   cell. Selected tab is the usual inversion. */
.book__tabs {
  display: flex;
  gap: calc(8 * var(--u));
  height: calc(42 * var(--u));
  margin-bottom: calc(10 * var(--u));
}
.book__tab {
  flex: none;
  padding: 0 calc(18 * var(--u));
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: inset 0 0 0 1px var(--rule-soft);
  color: var(--paper);
  font-family: var(--font-display);
  font-size: calc(15 * var(--u));
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
.book__tab:hover { background: var(--ink-2); }
.book__tab[aria-selected="true"] {
  background: var(--paper);
  color: var(--ink);
  box-shadow: none;
}
.book__panel[hidden] { display: none; }
.book__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: calc(104 * var(--u));
  margin-bottom: calc(10 * var(--u));
}
.book__row:last-of-type { margin-bottom: 0; }
.field { display: flex; flex-direction: column; }
.field label {
  /* min-height, not height: a single-line label still measures exactly 26u so
     the two columns stay on the same baseline, but a label that wraps pushes
     the input down instead of painting its second line on top of it. */
  min-height: calc(26 * var(--u));
  font-size: calc(15 * var(--u));
  line-height: calc(26 * var(--u));
  color: var(--paper);
}
.field .req { font-weight: 700; }
.field input, .field select {
  flex: none;
  height: calc(41 * var(--u));
  padding: 0 2px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--field-rule);
  color: var(--paper);
  font-size: 16px;
  line-height: 1.5;
}
.field input::placeholder { color: var(--muted); }
.field input:focus, .field select:focus { outline: 0; border-bottom-color: var(--paper); }
.field input[type="date"], .field input[type="time"] { color-scheme: dark; }

/* The enquiry panel carries a real message box, so a visitor can write here
   rather than being handed off to their mail client with nothing to say.
   Full-bleed rows opt out of the two-column grid the rest of the form uses. */
.book__row--full, .book__row--send { grid-template-columns: 1fr; }
.book__row--send { justify-items: end; }
.field textarea {
  padding: calc(8 * var(--u)) 2px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--field-rule);
  color: var(--paper);
  font-family: inherit;
  font-size: 16px;
  line-height: 1.55;
  resize: vertical;
  min-height: calc(62 * var(--u));
}
.field textarea::placeholder { color: var(--muted); }
.field textarea:focus { outline: 0; border-bottom-color: var(--accent); }
.field input[type="date"]:invalid::-webkit-datetime-edit,
.field input[type="time"]:invalid::-webkit-datetime-edit { color: transparent; }
.field input[type="date"]:focus::-webkit-datetime-edit,
.field input[type="time"]:focus::-webkit-datetime-edit { color: var(--paper); }
.field select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--paper) 50%),
                    linear-gradient(135deg, var(--paper) 50%, transparent 50%);
  background-position: calc(100% - 15px) 18px, calc(100% - 9px) 18px;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.field select option { background: var(--ink); color: var(--paper); }
.field--submit { justify-content: flex-end; }
.book__status { margin-top: 12px; font-size: 14px; line-height: 1.4; color: var(--muted); }
.book__status:empty { display: none; }

/* ------------------------------------------------- mission (sticky pin) */
.mission {
  position: sticky;
  top: calc(705 * var(--u) * -.05);
  z-index: 2;
  min-height: calc(705 * var(--u));
  background: var(--ink);
  border-top: 1px solid var(--rule);
}
.mission__top {
  display: grid;
  grid-template-columns: var(--col-a) 1fr;
  min-height: calc(324 * var(--u));
}
.mission__heading {
  display: flex;
  align-items: center;
  padding: calc(40 * var(--u)) 0 calc(40 * var(--u)) var(--pad);
  border-right: 1px solid var(--rule);
}
.h-display {
  font-size: calc(90 * var(--u));
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -.03em;
}
.mission__heading h2 { max-width: calc(560 * var(--u)); }
.mission__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1.5em;
  padding: calc(40 * var(--u)) calc(30 * var(--u)) calc(40 * var(--u)) calc(60 * var(--u));
  text-align: right;
}
.mission__copy p {
  font-size: calc(17.07 * var(--u));
  font-weight: 700;
  line-height: 1.6;
}
.mission__copy .dim { color: var(--muted); font-weight: 400; }
.mission__copy u { text-decoration-thickness: 1px; text-underline-offset: 3px; }
.mission__media { height: calc(381 * var(--u)); }
.mission__media img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------- section band */
.band {
  position: relative;
  padding: calc(62 * var(--u)) var(--pad) calc(58 * var(--u)) calc(50 * var(--u));
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.band p { margin-top: calc(14 * var(--u)); max-width: 62ch; color: var(--muted); font-size: calc(17 * var(--u)); }

/* -------------------------------------------------------------- services */
.services { position: relative; z-index: 3; background: var(--ink); overflow: hidden; }
.services__watermark {
  position: absolute;
  top: -93px;
  left: var(--col-s);
  width: calc(293 * var(--u));
  height: calc(293 * var(--u));
  fill: var(--watermark);
  pointer-events: none;
}
.services__body {
  position: relative;
  display: grid;
  grid-template-columns: var(--col-s) 1fr;
  min-height: calc(580 * var(--u));
}
.services__pitch {
  position: relative;
  border-right: 1px solid var(--rule);
  display: flex;
  align-items: center;
}
.services__pitchbox { position: relative; width: 100%; }
.services__pitch .wordmark--xl { position: absolute; left: calc(46 * var(--u)); top: calc(-48 * var(--u)); }
.services__pitch p {
  position: relative;
  margin: 0 calc(40 * var(--u)) 0 calc(62 * var(--u));
  max-width: calc(1030 * var(--u));
  /* clears the XL mark; retuned when the mark lost its rule and narrowed */
  text-indent: calc(227 * var(--u));
  font-size: calc(88 * var(--u));
  font-weight: 400;
  line-height: 1.16;
  letter-spacing: -.03em;
}
/* The left inset lives on the items, not the column, so every rule below
   reaches the vertical column rule instead of stopping 28u short of it. */
.services__aside { display: flex; flex-direction: column; padding: calc(90 * var(--u)) 0 0; }
.services__list { display: flex; flex-direction: column; }
.services__list li {
  padding: calc(20 * var(--u)) calc(20 * var(--u)) calc(20 * var(--u)) calc(28 * var(--u));
  border-bottom: 1px solid var(--rule-faint);
}
.services__list li:last-child { border-bottom: 0; }
.services__list b { display: block; font-size: calc(22 * var(--u)); font-weight: 700; }
.services__list span { display: block; margin-top: 4px; font-size: calc(15 * var(--u)); color: var(--muted); }

/* ------------------------------------------------------------- vs board */
.vs { position: relative; z-index: 3; background: var(--ink); }
.vs__grid {
  display: grid;
  grid-template-columns: minmax(140px, .55fr) 1fr 1fr;
  border-bottom: 1px solid var(--rule-soft);
}
.vs__grid > * { padding: calc(22 * var(--u)) var(--pad) calc(22 * var(--u)) calc(28 * var(--u)); border-top: 1px solid var(--rule-faint); }
.vs__head {
  border-top: 0 !important;
  padding-top: calc(30 * var(--u));
  padding-bottom: calc(26 * var(--u));
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.vs__head h3 { font-size: calc(21 * var(--u)); font-weight: 700; }
.vs__head span { display: block; margin-top: 2px; font-size: calc(14 * var(--u)); color: var(--muted); }
.vs__head--gb { background: var(--paper); color: var(--ink); }
.vs__head--gb span { color: #4a4c4e; }
.vs__key {
  font-size: calc(14 * var(--u));
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  /* first baseline aligned with the cells' 19u bold line, not row-centered */
  padding-top: calc(27 * var(--u));
  line-height: 1.5;
}
.vs__cell b { display: block; font-size: calc(19 * var(--u)); font-weight: 700; }
.vs__cell span { display: block; margin-top: 2px; font-size: calc(14.5 * var(--u)); color: var(--muted); }
.vs__cell--oem b { font-weight: 400; color: var(--muted); }
.vs__cell--gb { border-left: 1px solid var(--rule-soft); }
.vs__note {
  padding: calc(24 * var(--u)) var(--pad) calc(56 * var(--u)) calc(28 * var(--u));
  max-width: 96ch;
  font-size: calc(13.5 * var(--u));
  line-height: 1.6;
  color: var(--muted-2);
}

/* --------------------------------------------------------- market strip */
.mstrip { position: relative; z-index: 3; background: var(--ink); }
.mstrip__body {
  display: grid;
  grid-template-columns: var(--col-a) 1fr;
  border-bottom: 1px solid var(--rule);
}
.mstrip__media {
  padding: calc(56 * var(--u)) var(--pad);
  border-right: 1px solid var(--rule-soft);
  display: flex;
  flex-direction: column;
  gap: calc(14 * var(--u));
}
.shotframe { border: 1px solid var(--rule-soft); background: var(--ink-2); padding: calc(14 * var(--u)); }
.shotframe img { width: 100%; height: auto; }
/* A portrait phone plate sitting in a half-width column: cap the frame, not
   the image, so the shot fills its well instead of floating in a half-page
   of empty --ink-2. */
.shotframe--phone { max-width: calc(300 * var(--u)); margin-inline: auto; }
.shotcap { font-size: calc(13.5 * var(--u)); color: var(--muted-2); }
.mstrip__copy { display: flex; flex-direction: column; justify-content: center; padding: calc(56 * var(--u)) var(--pad); }
.mstrip__copy h3 { font-size: calc(44 * var(--u)); font-weight: 700; line-height: 1.15; letter-spacing: -.02em; }
.mstrip__copy > p { margin-top: calc(18 * var(--u)); max-width: 52ch; font-size: calc(17 * var(--u)); color: var(--muted); }
.mstrip__copy > p b { color: var(--paper); }
.facts { margin-top: calc(30 * var(--u)); }
.facts li {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: calc(15 * var(--u)) 0;
  border-top: 1px solid var(--rule-faint);
  font-size: calc(16 * var(--u));
}
.facts li span { color: var(--muted); }
.facts li b { font-weight: 700; text-align: right; }
.mstrip__cta { display: flex; flex-wrap: wrap; gap: calc(14 * var(--u)); margin-top: calc(34 * var(--u)); }

/* ------------------------------------------------------------- phone box */
/* The closing band of the market section, and the one block whose subject is
   the primary visitor's actual scene: a phone, in a truck, in bad light.
   Three cells — evidence, claim, action — read the way the .act rows read.

   It now sits on the page's own spine. The band used to run a 150u/1fr grid
   off a 28u left pad, so its shot started at 28u while the .shotframe directly
   above it started at 51u, and its 1fr copy cell was 1177u holding 731u of
   text: neither edge agreed with the composition it closes. Both gutters are
   --pad now, so the shot lines up with the frame above and the button lands on
   1389u with the hero cells and the market copy.

   The shot is a real 780x1688 phone capture. Rendered whole into the old 150u
   frame it was a 130u smear that proved nothing the copy claims. The frame is
   220u here and the screen is clipped inside its well at 74% of the image,
   which falls just under the first row of part cards — so the search field,
   the fleet chips and one complete card (GB number, GB MADE tag, price) all
   survive at a size worth printing. Clipping rather than scaling is the device
   the services watermark already uses. */
.appbox {
  display: grid;
  grid-template-columns: calc(220 * var(--u)) minmax(0, 1fr) auto;
  align-items: center;
  gap: calc(40 * var(--u));
  padding: calc(34 * var(--u)) var(--pad) calc(36 * var(--u));
}
.appbox__shot {
  border: 1px solid var(--rule-soft);
  background: var(--ink-2);
  padding: calc(9 * var(--u));
}
/* 220u frame - 2px border - 18u padding = 200u of image; 200 * 1688/780 =
   432.8u tall whole, clipped to 320u. */
.appbox__screen { display: block; height: calc(320 * var(--u)); overflow: hidden; }
.appbox__screen img { display: block; width: 100%; height: auto; }
/* Outranks .appbox__copy > p, which is one element more specific than a bare
   .appbox__k and was quietly rendering this kicker at 16u/--muted instead of
   the 13u/--muted-2 it declares. */
.appbox__copy > .appbox__k {
  margin-top: 0;
  font-size: calc(13 * var(--u));
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.appbox__copy h3 {
  margin-top: calc(8 * var(--u));
  max-width: 24ch;
  /* the line is long enough to strand "on." by itself in the narrow column */
  text-wrap: balance;
  font-size: calc(30 * var(--u));
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.02em;
}
.appbox__copy > p {
  margin-top: calc(12 * var(--u));
  max-width: 62ch;
  font-size: calc(16 * var(--u));
  line-height: 1.6;
  color: var(--muted);
}
.appbox__copy > p b { color: var(--paper); }
.appbox__cta { display: flex; flex-wrap: wrap; align-items: center; gap: calc(14 * var(--u)); }

/* ------------------------------------------------------------ page head */
.phead {
  position: relative;
  background: var(--ink);
  border-bottom: 1px solid var(--rule);
  overflow: hidden;
}
.phead__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .38; }
.phead__grid {
  position: relative;
  display: grid;
  grid-template-columns: var(--col-a) 1fr;
  min-height: calc(440 * var(--u));
}
.phead__title {
  display: flex;
  align-items: flex-end;
  padding: calc(150 * var(--u)) var(--pad) calc(56 * var(--u)) var(--pad);
  border-right: 1px solid var(--rule-soft);
}
.phead h1 {
  max-width: calc(640 * var(--u));
  font-size: calc(58 * var(--u));
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.02em;
}
.phead h1 em { font-style: normal; color: var(--muted); }
.phead__side {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: calc(22 * var(--u));
  padding: calc(150 * var(--u)) var(--pad) calc(56 * var(--u)) var(--pad);
}
.phead__side p { max-width: 48ch; font-size: calc(17.5 * var(--u)); line-height: 1.6; color: var(--muted); }
.phead__side p b { color: var(--paper); }
.notestrip {
  display: flex;
  flex-wrap: wrap;
  border-top: 1px solid var(--rule-soft);
  position: relative;
}
.notestrip li {
  flex: 1 1 auto;
  padding: calc(16 * var(--u)) var(--pad);
  border-right: 1px solid var(--rule-faint);
  font-size: calc(14 * var(--u));
  color: var(--muted);
}
.notestrip li:last-child { border-right: 0; }
.notestrip b { color: var(--paper); font-weight: 700; }

/* -------------------------------------------------------------- rig tour */
.rig { position: relative; z-index: 1; }
.rig__track { position: relative; min-height: 520svh; }
.rig__stage {
  position: sticky;
  top: var(--header-h);
  height: calc(100svh - var(--header-h));
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(360px, 1fr);
}
.rig__view {
  position: relative;
  border-right: 1px solid var(--rule-soft);
  overflow: hidden;
}
.rig__cam {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  transition: transform .8s cubic-bezier(0.22, 1, 0.36, 1);
}
.rig__cam img {
  width: 100%;
  height: auto;
  filter: invert(1) brightness(1.25) contrast(.82);
  opacity: .4;
  transition: opacity .5s ease;
}
.rig.is-zoomed .rig__cam img { opacity: .62; }
.rig__dim {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s ease;
  -webkit-mask-image: radial-gradient(circle 340px at var(--mx, 50%) var(--my, 50%), transparent 0 30%, #000 78%);
  mask-image: radial-gradient(circle 340px at var(--mx, 50%) var(--my, 50%), transparent 0 30%, #000 78%);
}
.rig.is-zoomed .rig__dim { opacity: .82; }
.hot {
  position: absolute;
  left: calc(var(--x) * 100%);
  top: calc(var(--y) * 100%);
  /* counter-scale against the camera zoom so pins keep their size */
  transform: translate(-50%, -50%) scale(calc(1 / var(--zz, 1)));
  transition: transform .8s cubic-bezier(0.22, 1, 0.36, 1);
  width: 44px; height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--paper);
}
.hot::before {
  content: "";
  width: 11px; height: 11px;
  background: var(--paper);
  outline: 1px solid var(--rule-soft);
  outline-offset: 3px;
}
.hot::after {
  content: "";
  position: absolute;
  width: 11px; height: 11px;
  outline: 1px solid var(--rule-soft);
  animation: hotping 2.6s ease-out infinite;
  animation-delay: calc(var(--i, 0) * .4s);
}
@keyframes hotping {
  0% { transform: scale(1); opacity: .9; }
  70%, 100% { transform: scale(3.4); opacity: 0; }
}
.hot span {
  position: absolute;
  left: calc(100% + 6px);
  top: 50%;
  transform: translateY(-50%);
  padding: 5px 10px;
  background: var(--ink);
  border: 1px solid var(--rule-soft);
  font-size: 13px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity .2s ease;
  pointer-events: none;
}
.hot:hover span, .hot:focus-visible span, .hot[aria-expanded="true"] span { opacity: 1; }
.hot[aria-expanded="true"]::before { background: var(--ink); outline-color: var(--paper); border: 2px solid var(--paper); }

.rig__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(34 * var(--u)) var(--pad);
  min-width: 0;
}
.rig__hint { font-size: calc(16 * var(--u)); color: var(--muted); max-width: 40ch; }
.rig__hint b { color: var(--paper); }
.rig__count {
  position: absolute;
  top: calc(24 * var(--u));
  right: var(--pad);
  font-family: var(--font-mark);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: .12em;
  color: var(--muted-2);
}

/* part card */
.pcard {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  justify-content: center;
  padding: calc(34 * var(--u)) var(--pad);
  min-width: 0;
  overflow-y: auto;
}
.pcard.is-on { display: flex; }
.pcard__well {
  position: relative;
  align-self: flex-start;
  /* white, not #eef0f2: these are GB Market's own photos and they are shot on
     white, so a tinted well framed each one in a visible white box. */
  background: #fff;
  border: 1px solid var(--rule-soft);
  width: min(100%, calc(330 * var(--u)));
}
.pcard__well img { width: 100%; height: calc(170 * var(--u)); object-fit: contain; padding: 12px; }
.pcard__well small {
  position: absolute;
  right: 8px; bottom: 6px;
  font-size: 10.5px;
  letter-spacing: .06em;
  color: #6b6e71;
}
.pcard__num {
  margin-top: calc(18 * var(--u));
  font-family: var(--font-mark);
  font-weight: 800;
  font-size: calc(13.5 * var(--u));
  letter-spacing: .1em;
  color: var(--muted);
}
.pcard h3 { margin-top: 4px; font-size: calc(27 * var(--u)); font-weight: 700; line-height: 1.15; }
.pcard__fit { margin-top: calc(8 * var(--u)); font-size: calc(15.5 * var(--u)); line-height: 1.5; color: var(--muted); }
.pcard__fit b { color: var(--paper); font-weight: 700; }
.pcard__row { display: flex; align-items: baseline; gap: calc(16 * var(--u)); margin-top: calc(14 * var(--u)); flex-wrap: wrap; }
.tag {
  display: inline-block;
  padding: 4px 9px;
  border: 1px solid var(--rule-soft);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.tag--fill { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.pcard__price { font-size: calc(30 * var(--u)); font-weight: 800; font-family: var(--font-mark); }
.pcard__price small { font-size: .5em; font-weight: 700; color: var(--muted); letter-spacing: .06em; }
.pcard__price--na { font-size: calc(17 * var(--u)); font-weight: 400; font-family: var(--font-display); color: var(--muted); }
/* USD sits beside the CAD price, quieter — only three parts in the GB-app
   catalogue carry sale_price_usd, so this renders only where the data exists
   rather than being faked by conversion. */
.pcard__usd {
  font-family: var(--font-mark);
  font-weight: 700;
  font-size: calc(13 * var(--u));
  letter-spacing: .04em;
  color: var(--muted-2);
}
.pcard__meta { margin-top: calc(16 * var(--u)); padding-top: calc(12 * var(--u)); border-top: 1px solid var(--rule-faint); font-size: calc(14.5 * var(--u)); color: var(--muted); }
.pcard__meta b { color: var(--paper); font-family: var(--font-mark); font-weight: 800; }
/* Compatible rigs and the rest of the assembly used to be the smallest, dimmest
   things on the card — 13.5u of --muted-2 running as a sentence, which is why
   they read as a disclaimer rather than as the answer someone came for. Both
   are now chips: the rigs in the accent, the assembly in paper on a rule. */
.pcard__rigs {
  display: flex;
  flex-wrap: wrap;
  gap: calc(6 * var(--u));
  margin-top: calc(10 * var(--u));
}
.pcard__rigs li {
  padding: calc(4 * var(--u)) calc(10 * var(--u));
  border: 1px solid var(--accent);
  color: var(--accent);
  font-family: var(--font-mark);
  font-weight: 800;
  font-size: calc(12.5 * var(--u));
  letter-spacing: .09em;
  text-transform: uppercase;
  white-space: nowrap;
}
.pcard__also-k {
  margin-top: calc(16 * var(--u));
  font-family: var(--font-mark);
  font-weight: 800;
  font-size: calc(11.5 * var(--u));
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.pcard__chips {
  display: flex;
  flex-wrap: wrap;
  gap: calc(6 * var(--u));
  margin-top: calc(8 * var(--u));
}
.pcard__chips li {
  padding: calc(5 * var(--u)) calc(10 * var(--u));
  border: 1px solid var(--rule-faint);
  font-size: calc(13 * var(--u));
  line-height: 1.35;
  color: var(--paper);
}
.pcard .btn--line { margin-top: calc(20 * var(--u)); align-self: flex-start; height: calc(37 * var(--u)); font-size: calc(13 * var(--u)); }

/* static fallback (mobile / reduced motion) */
.rig__static { display: none; }

/* ---------------------------------------------------------------- ledger */
.ledger { border-bottom: 1px solid var(--rule); }
.ledger__row {
  display: grid;
  grid-template-columns: calc(90 * var(--u)) minmax(220px, .9fr) 1.6fr;
  gap: calc(24 * var(--u));
  padding: calc(30 * var(--u)) var(--pad) calc(30 * var(--u)) calc(28 * var(--u));
  border-top: 1px solid var(--rule-faint);
}
.ledger__n { font-family: var(--font-mark); font-weight: 800; font-size: calc(15 * var(--u)); color: var(--muted-2); }
.ledger__name b { display: block; font-size: calc(21 * var(--u)); font-weight: 700; }
.ledger__name span { display: block; margin-top: 6px; font-size: calc(14.5 * var(--u)); color: var(--muted); max-width: 44ch; }
.ledger__parts { display: flex; flex-wrap: wrap; gap: 8px 0; align-content: flex-start; font-size: calc(14 * var(--u)); color: var(--muted); }
.ledger__parts i { font-style: normal; }
.ledger__parts i:not(:last-child)::after { content: "·"; margin: 0 10px; color: var(--watermark); }
.ledger__parts b { font-weight: 700; color: var(--paper); }

/* ------------------------------------------------------------ walkthrough */
.walk { border-bottom: 1px solid var(--rule); }
.walk__row {
  display: grid;
  grid-template-columns: var(--col-a) 1fr;
  border-top: 1px solid var(--rule-soft);
}
.walk__row:first-child { border-top: 0; }
.walk__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(56 * var(--u)) var(--pad);
  border-right: 1px solid var(--rule-soft);
}
.walk__row--flip .walk__copy { order: 2; border-right: 0; border-left: 1px solid var(--rule-soft); }
.walk__n { font-family: var(--font-mark); font-weight: 800; font-size: calc(15 * var(--u)); letter-spacing: .12em; color: var(--muted-2); }
.walk__copy h3 { margin-top: calc(10 * var(--u)); font-size: calc(32 * var(--u)); font-weight: 700; line-height: 1.15; letter-spacing: -.01em; }
.walk__copy > p { margin-top: calc(14 * var(--u)); max-width: 50ch; font-size: calc(16.5 * var(--u)); color: var(--muted); }
.walk__copy > p b, .walk__list b { color: var(--paper); }
.walk__list { margin-top: calc(18 * var(--u)); }
.walk__list li {
  position: relative;
  padding: 8px 0 8px 22px;
  font-size: calc(15 * var(--u));
  color: var(--muted);
}
.walk__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 1.05em;
  width: 12px; height: 1px;
  background: var(--paper);
}
.walk__media { display: flex; flex-direction: column; justify-content: center; gap: calc(12 * var(--u)); padding: calc(56 * var(--u)) var(--pad); }

/* --------------------------------------------------------------- design */
.design { position: relative; overflow: hidden; border-bottom: 1px solid var(--rule); }
.design__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .30; }
.design__body { position: relative; padding: calc(74 * var(--u)) var(--pad) calc(80 * var(--u)); }
.design__body > p { max-width: 58ch; font-size: calc(18 * var(--u)); line-height: 1.6; color: var(--muted); }
.design__body > p b { color: var(--paper); }
.design__steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin-top: calc(48 * var(--u));
  border: 1px solid var(--rule-soft);
  background: rgba(25, 26, 27, .72);
}
.design__steps li { padding: calc(26 * var(--u)) calc(24 * var(--u)) calc(30 * var(--u)); border-right: 1px solid var(--rule-faint); }
.design__steps li:last-child { border-right: 0; }
.design__steps .k { font-family: var(--font-mark); font-weight: 800; font-size: 13px; letter-spacing: .12em; color: var(--muted-2); }
.design__steps b { display: block; margin-top: 10px; font-size: calc(19 * var(--u)); font-weight: 700; }
.design__steps p { margin-top: 8px; font-size: calc(14.5 * var(--u)); color: var(--muted); }
.design__cta { display: flex; flex-wrap: wrap; gap: calc(14 * var(--u)); margin-top: calc(40 * var(--u)); }

/* -------------------------------------------------------------- prose rows */
.rows { border-bottom: 1px solid var(--rule); }
.rows__item {
  display: grid;
  grid-template-columns: minmax(220px, .8fr) 1.6fr;
  gap: calc(30 * var(--u));
  padding: calc(30 * var(--u)) var(--pad) calc(30 * var(--u)) calc(28 * var(--u));
  border-top: 1px solid var(--rule-faint);
}
.rows__item:first-child { border-top: 0; }
.rows__item > b { font-size: calc(22 * var(--u)); font-weight: 700; line-height: 1.3; }
.rows__item > div, .rows__item > span { font-size: calc(16 * var(--u)); color: var(--muted); max-width: 72ch; }
.rows__item b i { font-style: normal; }
.rows__item div b, .rows__item span b { color: var(--paper); }

/* steps with rail (about) */
.wsteps { counter-reset: ws; }
.wsteps li { position: relative; counter-increment: ws; padding: calc(26 * var(--u)) var(--pad) calc(26 * var(--u)) calc(76 * var(--u)); border-top: 1px solid var(--rule-faint); }
.wsteps li::before {
  content: "0" counter(ws);
  position: absolute;
  left: calc(28 * var(--u));
  top: calc(30 * var(--u));
  font-family: var(--font-mark);
  font-weight: 800;
  font-size: calc(14 * var(--u));
  color: var(--muted-2);
}
.wsteps b { display: block; font-size: calc(20 * var(--u)); font-weight: 700; }
.wsteps p { margin-top: 6px; max-width: 72ch; font-size: calc(15.5 * var(--u)); color: var(--muted); }
.wsteps p b { display: inline; font-size: inherit; color: var(--paper); }

/* quote plate */
.shift { position: relative; overflow: hidden; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
.shift__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 54% 52%; opacity: .5; }
.shift__body { position: relative; padding: calc(120 * var(--u)) var(--pad); max-width: calc(880 * var(--u)); }
.shift__from { font-size: calc(24 * var(--u)); color: var(--muted); text-decoration: line-through; text-decoration-thickness: 1px; }
.shift__to { margin-top: calc(18 * var(--u)); font-size: calc(40 * var(--u)); font-weight: 700; line-height: 1.25; letter-spacing: -.01em; }
.shift__cap { margin-top: calc(22 * var(--u)); font-size: calc(13.5 * var(--u)); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }

/* share bar */
.share { margin-top: calc(26 * var(--u)); max-width: calc(420 * var(--u)); }
.share__bar { position: relative; height: 3px; background: var(--watermark); }
.share__bar i { position: absolute; left: 0; top: -2px; height: 7px; width: 1.02%; min-width: 4px; background: var(--paper); }
.share__legend { display: flex; justify-content: space-between; margin-top: 10px; font-size: calc(13.5 * var(--u)); color: var(--muted); }
.share__legend b { color: var(--paper); font-family: var(--font-mark); font-weight: 800; }

/* act rows */
/* Every content section in the stacking ladder carries `position: relative;
   z-index: 3; background: var(--ink)` — .services, .vs and .mstrip all do — so
   the sticky .mission (z-index 2) slides UNDER them. .act never did, because
   until index and market gained one it was always preceded by a section that
   had already pushed it clear of the mission's sticky range. On the home page
   it is now the last section, so the mission's photo band rendered over both
   buttons. Same ladder as its siblings. */
.act { position: relative; z-index: 3; background: var(--ink); border-bottom: 1px solid var(--rule); }
.act a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: calc(118 * var(--u));
  padding: calc(20 * var(--u)) var(--pad) calc(20 * var(--u)) calc(28 * var(--u));
  border-top: 1px solid var(--rule-soft);
  transition: background-color .18s ease, color .18s ease;
}
.act a:first-child { border-top: 0; }
.act a:hover { background: var(--paper); color: var(--ink); }
/* The last act row sits directly on the white footer. Inverting it on hover
   turns the row paper-white, so the section's white bottom rule disappears
   into the footer and the two read as one block — this rule survives the
   inversion in ink. */
.act a:last-child { border-bottom: 1px solid transparent; }
.act a:last-child:hover { border-bottom-color: var(--ink); }
.act__k { font-size: calc(15 * var(--u)); color: var(--muted); }
.act a:hover .act__k { color: #4a4c4e; }
.act__v { display: flex; align-items: center; gap: 16px; font-size: calc(30 * var(--u)); font-weight: 700; letter-spacing: -.01em; white-space: nowrap; }
.act__v svg { width: calc(26 * var(--u)); height: calc(26 * var(--u)); }

/* question cells (contact) */
.qs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--rule-faint);
  border-top: 1px solid var(--rule-faint);
  border-bottom: 1px solid var(--rule);
}
.qs li { background: var(--ink); padding: calc(30 * var(--u)) var(--pad) calc(34 * var(--u)) calc(28 * var(--u)); }
.qs p { font-size: calc(19 * var(--u)); font-weight: 700; line-height: 1.35; max-width: 30ch; }
.qs small { display: block; margin-top: 10px; font-size: calc(14 * var(--u)); line-height: 1.55; color: var(--muted); }

/* facts dl */
.fdl { border-bottom: 1px solid var(--rule); }
.fdl > div {
  display: grid;
  grid-template-columns: minmax(200px, .7fr) 1.8fr;
  gap: calc(30 * var(--u));
  padding: calc(24 * var(--u)) var(--pad) calc(24 * var(--u)) calc(28 * var(--u));
  border-top: 1px solid var(--rule-faint);
}
.fdl > div:first-child { border-top: 0; }
.fdl dt { font-size: calc(15 * var(--u)); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.fdl dd { font-size: calc(16 * var(--u)); color: var(--muted); max-width: 72ch; }
.fdl dd b { color: var(--paper); }

/* contact line rows */
.cline { border-bottom: 1px solid var(--rule); }
.cline__grid { display: grid; grid-template-columns: minmax(240px, .8fr) 1.6fr; }
.cline__who { padding: calc(48 * var(--u)) var(--pad) calc(48 * var(--u)) calc(28 * var(--u)); border-right: 1px solid var(--rule-soft); }
.cline__who .role { font-size: calc(13.5 * var(--u)); letter-spacing: .12em; text-transform: uppercase; color: var(--muted-2); }
.cline__who h2 { margin-top: 8px; font-size: calc(34 * var(--u)); font-weight: 700; }
.cline__who p { margin-top: 14px; max-width: 40ch; font-size: calc(15 * var(--u)); color: var(--muted); }
.cline__rows { display: flex; flex-direction: column; justify-content: center; }
.cline__rows a, .cline__rows .r {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: calc(86 * var(--u));
  padding: calc(14 * var(--u)) var(--pad);
  border-top: 1px solid var(--rule-faint);
  transition: background-color .18s ease, color .18s ease;
}
.cline__rows > :first-child { border-top: 0; }
.cline__rows a:hover { background: var(--paper); color: var(--ink); }
.cline__rows .k { font-size: calc(14 * var(--u)); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.cline__rows a:hover .k { color: #4a4c4e; }
.cline__rows .v { font-size: calc(24 * var(--u)); font-weight: 700; overflow-wrap: anywhere; text-align: right; }

/* ---------------------------------------------------------------- footer */
.site-footer {
  position: relative;
  z-index: 4;
  background: var(--paper);
  color: var(--ink);
}
/* Three cells now: identity + contact | nav | service-area map. The map takes
   the space the nav column used to leave empty on the right. */
.site-footer__main {
  display: grid;
  grid-template-columns: var(--col-f) calc(232 * var(--u)) 1fr;
  min-height: calc(414 * var(--u));
}
.site-footer__col {
  position: relative;
  padding: calc(24 * var(--u)) calc(28 * var(--u)) calc(28 * var(--u)) calc(21 * var(--u));
  border-right: 1px solid var(--ink);
}
/* The wordmark gets its own ruled cell, the way the original site boxed it.
   That cell's left rule is the column's left edge: the legal list and the
   contact block hang off it, and the mark and the slogan share the cell's own
   content edge. Before this there were four left edges stacked down one 521u
   column — the cell at 21u, legal and contact at 28u (a 7u nudge inherited
   from Wix, where the mark sat outside any box), the mark at 40u and the
   slogan at 47u — and none of them lined up with any other. */
.site-footer__mark {
  padding: calc(16 * var(--u)) calc(18 * var(--u)) calc(18 * var(--u));
  border: 1px solid var(--ink);
}
.site-footer .wordmark { font-size: calc(36 * var(--u)); }
.site-footer__legal { margin: calc(30 * var(--u)) 0 0; }
.site-footer__legal a {
  display: inline-block;
  font-size: calc(15.75 * var(--u));
  line-height: 1.6;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.site-footer__contact { margin: calc(40 * var(--u)) 0 0; }
.site-footer__contact h2 {
  margin-bottom: 4px;
  font-size: calc(21.66 * var(--u));
  font-weight: 700;
  line-height: 1.6;
  text-decoration: underline;
  text-underline-offset: 4px;
}
.site-footer__contact p { font-size: calc(17.1 * var(--u)); line-height: 1.6; }
.site-footer__contact a[href^="mailto:"] { text-decoration: underline; text-underline-offset: 3px; overflow-wrap: anywhere; }
.site-footer__addr { margin-top: calc(10 * var(--u)); color: #4a4c4e; }
.site-footer__nav { display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: calc(6 * var(--u)); padding: calc(28 * var(--u)) calc(28 * var(--u)) calc(28 * var(--u)) calc(28 * var(--u)); border-right: 1px solid var(--ink); }
.site-footer__nav a { font-size: calc(24 * var(--u)); font-weight: 700; padding: 4px 0; border-bottom: 1px solid transparent; }
.site-footer__nav a:hover { border-bottom-color: var(--ink); }
.site-footer__nav a:focus-visible { outline-color: var(--ink); }
.site-footer__col a:focus-visible { outline-color: var(--ink); }
/* ------------------------------------------------------ service-area map */
/* Drawn, not photographed, and now from real data: Natural Earth 50m coasts,
   provinces, states and lakes on a Lambert conformal conic — the projection
   North America is normally drawn on. The hatched regions are the ones GB's
   customers actually operate in, read off the GB-app `clients` table; the
   hatch runs at 21 degrees, the angle of the rule the original Wix wordmark
   set between its G and B. Generated by tools/mapgen.mjs -> mapgen-svg.mjs
   and shipped as one external SVG (/images/na-map.svg) rather than inlined,
   because the same 47KB would otherwise be duplicated into all five pages. */
.site-footer__map {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  padding: calc(28 * var(--u)) calc(34 * var(--u)) calc(28 * var(--u)) calc(24 * var(--u));
}
.site-footer__map figure { margin: 0; }
/* The cell is 651u wide at 1440; the map was capped at 330u inside it and sat
   hard left, leaving 293u of the footer empty. It now fills the cell. */
.namap { display: block; width: 100%; max-width: calc(636 * var(--u)); height: auto; }
.site-footer__map figcaption {
  margin-top: calc(14 * var(--u));
  max-width: 44ch;
  font-size: calc(13.5 * var(--u));
  line-height: 1.5;
  color: #4a4c4e;
}
.site-footer__map figcaption b { color: var(--ink); font-weight: 700; }

/* ------------------------------------------------------------ footer Q&A */
/* <details name> gives exclusive-accordion behaviour natively, so only one
   answer is ever open and the footer's height stays bounded. */
.site-faq {
  padding: calc(26 * var(--u)) var(--pad) calc(30 * var(--u));
  border-top: 1px solid var(--ink);
}
.site-faq h2 {
  margin-bottom: calc(14 * var(--u));
  font-size: calc(15 * var(--u));
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #4a4c4e;
}
/* The rows are the architecture here, the way every other full-bleed rule on
   the site is: capped at 980u they stopped 358u short of the right gutter and
   the section read as truncated. The answer keeps its own measure instead. */
.site-faq__list { max-width: none; }
.site-faq details { border-top: 1px solid rgba(25, 26, 27, .22); }
.site-faq details:last-child { border-bottom: 1px solid rgba(25, 26, 27, .22); }
.site-faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: calc(52 * var(--u));
  padding: calc(12 * var(--u)) 0;
  font-size: calc(17 * var(--u));
  font-weight: 700;
  line-height: 1.4;
  cursor: pointer;
  list-style: none;
  transition: color .18s ease;
}
.site-faq summary::-webkit-details-marker { display: none; }
.site-faq summary::after {
  content: "";
  flex: none;
  width: calc(13 * var(--u));
  height: calc(13 * var(--u));
  border-right: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .18s ease;
}
.site-faq details[open] summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.site-faq summary:hover { color: #4a4c4e; }
.site-faq summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.site-faq__a {
  padding: 0 calc(34 * var(--u)) calc(18 * var(--u)) 0;
  max-width: 72ch;
  font-size: calc(16 * var(--u));
  line-height: 1.6;
  color: #4a4c4e;
}
.site-faq__a b { color: var(--ink); font-weight: 700; }

.site-footer__strip {
  min-height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px var(--pad);
  border-top: 1px solid var(--ink);
  text-align: center;
}
.site-footer__strip p { font-size: calc(13.5 * var(--u)); line-height: 1.5; color: #4a4c4e; max-width: 120ch; }

/* =============================================================== responsive */
/* The header gained a sixth nav item (the language switch) and, on the French
   side, nav labels that run ~30px longer than the English ones. At 901px the
   old layout finished 5px over. The slogan is the only cell that can leave
   without losing a function — it repeats verbatim in the footer — so it now
   stands down at 1080 instead of 900. Measured, not estimated: see the
   breakpoint table in docs/WIX-AUDIT.md. */
/* At 360px the header already ran ~22px past the viewport before any of this
   — brand 139 + CTA 154 + toggle 44 + 40 padding + 24 gap = 401 in a 360 box —
   and "Ouvrir GB Market" is 15px wider than "Open GB Market" again. The verb is
   the redundant part on a phone: the fixed action bar at the bottom of the same
   screen carries the full label. Dropping it, plus 3px off the logo, puts both
   languages back inside the viewport. */
@media (max-width: 430px) {
  .site-header .cta__verb { display: none; }
  .site-header .brand__logo { height: 23px; }
}

@media (max-width: 1080px) {
  .site-header .site-slogan { display: none; }
}

@media (max-width: 1180px) {
  :root { --pad: 32px; }
  .hero h1 { font-size: clamp(34px, 4.45vw, 64px); }
  .hero__cell--tagline p { font-size: clamp(24px, 3vw, 42px); }
  .h-display { font-size: clamp(46px, 6.4vw, 90px); }
  .services__pitch p { font-size: clamp(36px, 5.2vw, 80px); text-indent: 20vw; }
  .services__pitch .wordmark--xl { font-size: clamp(56px, 8.4vw, 125px); left: 32px; top: 15%; }
  .phead h1 { font-size: clamp(34px, 4.6vw, 58px); }
  .book__row { column-gap: 40px; }
  /* six items now, not five — the switch has to come out of the gaps */
  .site-nav { gap: 14px; }
}

@media (max-width: 900px) {
  :root { --u: 1px; --header-h: 60px; }

  .site-header { height: 60px; }
  .site-header__inner { padding: 0 20px; }
  .site-header .wordmark { font-size: 28px; }
  /* the phone header carries the mark, the CTA and the menu — the name and
     slogan would push the CTA onto two lines */
  .site-header .site-slogan,
  .site-header .brand__name { display: none; }
  .site-nav {
    position: absolute;
    top: 100%; left: 0; right: 0;
    z-index: 9;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--ink);
    border-bottom: 1px solid var(--rule);
  }
  .site-nav.is-open { display: flex; }
  .site-nav a { padding: 16px 20px; border-bottom: 1px solid var(--rule-faint); }
  .site-nav a[aria-current="page"] { border-bottom-color: var(--rule-faint); background: var(--ink-2); }
  /* in the dropdown there is room for the language's own name, and no room
     for a vertical rule in a column layout */
  .site-nav .lang-switch { margin-left: 0; padding: 16px 20px; border-left: 0; letter-spacing: .02em; }
  .site-nav .lang-switch__ab { display: none; }
  .site-nav .lang-switch__full { display: inline; }
  .site-header .btn--solid { margin-left: auto; min-width: 0; padding: 0 14px; }
  .nav-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px; height: 44px;
    margin-left: 8px;
    border: 1px solid var(--rule-soft);
    background: transparent;
    color: var(--paper);
    cursor: pointer;
  }

  .promo__step { padding: 0 14px; font-size: 13px; }
  .promo__step::after { margin-left: 14px; }
  .stepdlg__inner { grid-template-columns: 1fr; }
  .stepdlg__shot { padding: 18px; }
  .stepdlg__shot img { max-height: 52vh; }

  .hero { min-height: 0; }
  /* Client note 2026-08-25: "the rig is barely visible, all you see is sky."
     The hero box is 390 x 1259 (aspect 0.31) and the landscape source is 1.79,
     so `cover` scales to fill the HEIGHT and crops width only — which means
     object-position's Y term does nothing and the frame always shows the
     image's full vertical range, sky included. A dedicated portrait crop
     (820 x 1025, cut from the same original around the machine) fixes the
     vertical; the X term then has to be pushed onto the rig, because at this
     box only 39% of the crop's width is on screen. */
  .hero__bg { opacity: .48; object-position: 78% 50%; }
  .hero__grid { grid-template-columns: 1fr; grid-template-rows: auto; min-height: 0; }
  .hero__grid::after { display: none; }
  .hero__cell--title, .hero__cell--logo, .hero__cell--tagline, .hero__cell--form { border-right: 0; }
  .hero__cell--title { padding: 44px 20px 28px; border-bottom: 0; }
  /* The longest word is now "SOLUTIONS." at 717.6u/72u — 8.8vw keeps it inside
     a 390px viewport's 350px text column (was 9.2vw, tuned for "STRONGER"). */
  .hero h1 { font-size: clamp(30px, 8.8vw, 64px); }
  .hero__lede { font-size: 16px; color: var(--paper); }
  .hero__cell--logo { display: none; }
  .hero__cell--social { order: -1; flex-direction: row; justify-content: flex-end; padding: 12px 20px; border-bottom: 0; }
  .social { flex-direction: row; }
  .hero__cell--tagline { padding: 16px 20px; border-top: 1px solid var(--rule-soft); border-bottom: 1px solid var(--rule-soft); }
  .hero__cell--tagline p { font-size: 22px; }
  .hero__cell--form { padding: 24px 20px 40px; }
  .book__row { grid-template-columns: 1fr; row-gap: 22px; column-gap: 0; margin-bottom: 22px; }
  .field--submit { margin-top: 6px; }

  .mission { position: static; min-height: 0; }
  .mission__top { grid-template-columns: 1fr; min-height: 0; }
  .mission__heading { justify-content: center; padding: 44px 20px 24px; border-right: 0; border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule); }
  .h-display { font-size: clamp(40px, 11.5vw, 60px); }
  .mission__heading h2 { max-width: none; }
  /* the heading cell gained a bottom rule in the 24 Aug pass and the copy was
     still padded to 0 at the top, so the paragraph sat on the rule */
  .mission__copy { padding: 26px 20px 44px; }
  /* Removing the mobile `center` left the DESKTOP rule showing through —
     .mission__copy is text-align: right there, a deliberate rag against the
     column rule. On one column that put a ragged left edge on the block that
     carries the argument, which is worse than the centring it replaced. */
  .mission__copy, .mission__copy p { text-align: left; }
  .mission__copy p { font-size: 16px; }
  .mission__media { height: 52vw; min-height: 220px; }

  /* Centred only because a two-column grid vacated the space — nothing
     else in this system is centred, and a ragged left edge is the slowest
     way to read the blocks that carry the argument. */
  .band { padding: 32px 20px; }

  .services__watermark { display: none; }
  .services__body { grid-template-columns: 1fr; min-height: 0; }
  .services__pitch { border-right: 0; padding: 40px 20px 44px; }
  .services__pitch .wordmark--xl {
    position: relative; left: auto; top: auto;
    display: inline-block;
    height: 1.18em;
    vertical-align: baseline;
    font-size: clamp(36px, 9vw, 64px);
    margin-right: .2em;
  }
  .services__pitch p { position: static; margin: 0; max-width: none; text-indent: 0; display: inline; font-size: clamp(24px, 6.4vw, 44px); }
  .services__pitchbox { width: auto; }
  .services__aside { padding: 8px 20px 0; border-top: 1px solid var(--rule); }
  .services__aside .btn--ghost { margin: 24px -20px 0; width: calc(100% + 40px); height: 76px; }

  .vs__grid { grid-template-columns: 1fr 1fr; }
  .vs__head--label { display: none; }
  /* The key spans both columns, so the GB column's vertical rule could only
     ever start BELOW it — it had nothing to meet at the top of the row. The
     key now closes with its own faint rule, which is what the vertical divider
     runs down from. */
  .vs__key {
    grid-column: 1 / -1;
    padding-top: 18px;
    padding-bottom: 12px;
    border-top: 1px solid var(--rule-faint);
    border-bottom: 1px solid var(--rule-faint);
  }
  .vs__cell { border-top: 0 !important; padding-top: 14px; }
  .vs__grid > * { padding-left: 20px; padding-right: 20px; }
  .vs__note { padding: 20px 20px 44px; }

  .mstrip__body { grid-template-columns: 1fr; }
  .mstrip__media { border-right: 0; border-bottom: 1px solid var(--rule-soft); padding: 32px 20px; }
  .mstrip__copy { padding: 36px 20px 44px; }
  .mstrip__copy h3 { font-size: 32px; }

  .phead__grid { grid-template-columns: 1fr; min-height: 0; }
  .phead__title { padding: 110px 20px 8px; border-right: 0; }
  .phead h1 { max-width: none; }
  .phead__side { padding: 18px 20px 36px; }
  .notestrip { flex-direction: column; }
  /* `display: flex` on the <li> made every text node and every <b> a separate
     flex item, and flex drops the whitespace between items — which is why
     "G.B Réseau Distribution Inc. — independent distributor",
     "Shipping across North America" and "Prices in CAD or USD" all lost the
     space before their bold run. Block keeps the text as one inline flow;
     symmetric padding gets the 48px hit area without a flex container. */
  .notestrip li { border-right: 0; border-top: 1px solid var(--rule-faint); padding: 14px 20px; }
  .notestrip li > a { display: block; margin: -14px -20px; padding: 14px 20px; }

  .rig__track { min-height: 0; }
  .rig__stage { position: static; height: auto; grid-template-columns: 1fr; }
  .rig__view { display: none; }
  .rig__panel { display: none; }
  .rig__static { display: block; }
  .rig__static > figure { padding: 24px 20px 8px; }
  .rig__static > figure img { filter: invert(1) brightness(1.25) contrast(.82); opacity: .5; }
  .rig__static .pcard { position: static; display: flex; padding: 28px 20px; border-top: 1px solid var(--rule-faint); overflow: visible; }

  .ledger__row { grid-template-columns: 1fr; gap: 10px; padding: 24px 20px; }
  .rows__item { grid-template-columns: 1fr; gap: 10px; padding: 24px 20px; }
  .wsteps li { padding: 22px 20px 22px 58px; }
  .wsteps li::before { left: 20px; top: 26px; }
  .walk__row { grid-template-columns: 1fr; }
  .walk__copy { padding: 32px 20px 8px; border-right: 0; }
  .walk__row--flip .walk__copy { order: 0; border-left: 0; }
  .walk__media { padding: 20px 20px 36px; }
  .design__steps { grid-template-columns: 1fr; }
  .design__steps li { border-right: 0; border-bottom: 1px solid var(--rule-faint); }
  .design__steps li:last-child { border-bottom: 0; }
  .design__body { padding: 44px 20px 52px; }
  .qs { grid-template-columns: 1fr; }
  .qs li { padding: 24px 20px 28px; }
  .fdl > div { grid-template-columns: 1fr; gap: 6px; padding: 20px; }
  .cline__grid { grid-template-columns: 1fr; }
  .cline__who { padding: 32px 20px 24px; border-right: 0; border-bottom: 1px solid var(--rule-soft); }
  .cline__rows .v { font-size: 19px; }
  .cline__rows a, .cline__rows .r { padding: 14px 20px; }
  .act__v { font-size: 20px; white-space: normal; text-align: right; }
  .act a { padding: 18px 20px; min-height: 96px; }
  .shift__body { padding: 72px 20px; }
  .shift__to { font-size: 28px; }

  .site-footer__main { grid-template-columns: 1fr; min-height: 0; }
  .site-footer__col { border-right: 0; padding: 28px 20px 24px; }
  .site-footer__mark { padding: 14px 16px 16px; }
  .site-footer__legal { margin: 20px 0 0; }
  .site-footer__contact { margin: 24px 0 0; }
  .site-footer__nav { padding: 0 20px 28px; border-right: 0; }
  .site-footer__nav a { font-size: 20px; }
  .site-footer__map { padding: 0 20px 28px; border-top: 1px solid rgba(25, 26, 27, .22); padding-top: 24px; }
  .namap { max-width: 340px; }
  .site-faq { padding: 22px 20px 26px; }
  .site-faq summary { font-size: 16px; min-height: 48px; }
  .site-faq__a { font-size: 15px; padding-right: 0; }
  .site-footer__strip { padding: 14px 20px; }

  .appbox { grid-template-columns: 116px 1fr; gap: 16px 18px; padding: 24px 20px 26px; align-items: start; }
  /* 116px frame - 2px - 18px = 96px of image; 96 * 1688/780 = 207.7 whole,
     clipped to 154px — the same 74% as the desktop frame. */
  .appbox__screen { height: 154px; }
  .appbox__cta { grid-column: 1 / -1; margin-top: 4px; }
  .appbox__copy h3 { font-size: 22px; }
  .appbox__copy > p { font-size: 15px; }
}

@media (min-width: 901px) and (prefers-reduced-motion: reduce) {
  /* the scroll tour is a motion feature; without motion, present the same
     information statically */
  .rig__track { min-height: 0; }
  .rig__stage { position: static; height: auto; grid-template-columns: 1fr; }
  .rig__view, .rig__panel { display: none; }
  .rig__static { display: block; }
  .rig__static > figure { padding: 40px var(--pad) 8px; }
  .rig__static > figure img { filter: invert(1) brightness(1.25) contrast(.82); opacity: .5; }
  .rig__static .pcard { position: static; display: flex; padding: 36px var(--pad); border-top: 1px solid var(--rule-faint); overflow: visible; }
  .hot::after { animation: none; }
}

/* ===================================================== BLUE METAL ACCENT */
/* Applied 2026-08-23. Level 2 of the accent round, plus the promo banner and
   the footer marks from level 3. See docs/BRAINDUMP-2026-08-19.md.

   Two rules hold this together and neither is negotiable:
     · --paper stays white, because body text is --paper.
     · The footer is the page's one inverted plate (white ground, ink text), so
       it takes --metal-mid at 7.39:1, never --accent, which is a lifted blue
       for ink grounds and drops to 2.81:1 on white. */

/* the brushed plate: fine near-horizontal grain over a broad raking sheen */
:root {
  --brushed:
    repeating-linear-gradient(4deg,
      rgba(255,255,255,.055) 0 1px, rgba(0,0,0,.055) 1px 2px,
      rgba(255,255,255,.022) 2px 3px, rgba(0,0,0,.030) 3px 5px),
    linear-gradient(97deg,
      var(--metal-lo) 0%,  var(--metal-mid) 20%, var(--metal-hi) 40%,
      var(--metal-spec) 50%, var(--metal-hi) 61%, var(--metal-mid) 80%,
      var(--metal-lo) 100%);
}

/* The same plate, for surfaces that carry text. --brushed's crest is
   --metal-spec, where white measures 2.41:1; this one crests at --metal-hi and
   measures 4.60:1. Same grain, same 97deg rake, one stop down in the middle.
   Applied below 900px only — desktop still uses --brushed on its buttons and
   still fails there. See docs/WIX-AUDIT.md. */
:root {
  --brushed-text:
    repeating-linear-gradient(4deg,
      rgba(255,255,255,.055) 0 1px, rgba(0,0,0,.055) 1px 2px,
      rgba(255,255,255,.022) 2px 3px, rgba(0,0,0,.030) 3px 5px),
    linear-gradient(97deg,
      var(--metal-lo) 0%, var(--metal-mid) 26%, var(--metal-crest) 50%,
      var(--metal-mid) 74%, var(--metal-lo) 100%);
}

/* ---------------------------------------------------------- brand lockups */
.brand__logo { height: calc(44 * var(--u)); width: auto; }
.site-footer .brand__logo { height: calc(40 * var(--u)); }
.hero__cell--logo img { width: calc(430 * var(--u)); }
.services__gb {
  position: absolute;
  left: calc(46 * var(--u));
  top:  calc(-6 * var(--u));
  width: calc(270 * var(--u));
  height: auto;
}
/* The mark this replaces was 205.6u wide and the paragraph cleared it with
   text-indent:227u. The blue lockup is wider, so the indent moves with it:
   46 left + 270 wide + 37 air - 62 margin = 291. */
@media (min-width: 1001px) {
  .services__pitch p { text-indent: calc(291 * var(--u)); }
}

/* --------------------------------------------------------- accent marking */
.site-nav a[aria-current="page"] { border-bottom-color: var(--accent); }
:focus-visible { outline-color: var(--accent); }
.vs__head--gb { background: var(--brushed); color: var(--on-metal); }
.vs__head--gb span { color: rgba(255,255,255,.78); }
.vs__cell--gb b { color: var(--accent); }
.tag--fill { background: var(--brushed); color: var(--on-metal); border-color: var(--metal-hi); }
.facts li:first-child b { color: var(--accent); }
.appbox__k, .appbox__copy > .appbox__k { color: var(--accent); }
.share__bar i { background: var(--accent); }

/* --------------------------------------------------- rules, fills, buttons */
/* The hover used to swap the brushed plate for flat --metal-hi. Two problems:
   background-image is not interpolatable, so .btn's background-color transition
   never applied and it snapped; and it threw the grain away, turning a machined
   face into a painted one. The plate now stays put and an inset shadow deepens
   it — that does animate, and it reads as the metal turning under the light
   rather than changing material. */
.btn--solid, .btn--submit {
  background: var(--brushed);
  color: var(--on-metal);
  border-color: var(--metal-hi);
  box-shadow: inset 0 0 0 999px rgba(8, 22, 38, 0);
  transition: box-shadow .22s ease, border-color .22s ease, color .18s ease;
}
.btn--solid:hover, .btn--submit:hover {
  background: var(--brushed);
  color: var(--on-metal);
  box-shadow: inset 0 0 0 999px rgba(8, 22, 38, .40);
  border-color: var(--metal-spec);
}
.btn--solid:active, .btn--submit:active {
  box-shadow: inset 0 0 0 999px rgba(8, 22, 38, .56);
}
.btn--ghost { border-color: var(--accent); color: var(--accent); }
.btn--ghost:hover { background: var(--brushed); color: var(--on-metal); border-color: var(--metal-hi); }
.book__tab[aria-selected="true"] { background: var(--brushed); color: var(--on-metal); }
.act a:hover { background: var(--brushed); color: var(--on-metal); }
.hot[aria-expanded="true"]::before { outline-color: var(--accent); border-color: var(--accent); }
.stepdlg__close:hover { background: var(--accent); color: var(--ink); }
.wordmark:not(.wordmark--dark) { color: var(--accent); }
.wordmark--dark { color: var(--metal-mid); }
.brand:not(.brand--dark) .brand__name { color: var(--accent); }
.hero__lede b, .mission b, .vs b, p b { color: var(--accent); }
.services__watermark { fill: var(--watermark); }
::selection { background: var(--accent); color: var(--ink); }
html { scrollbar-color: var(--metal-mid) var(--ink); }

/* ------------------------------------------- promo banner (from level 3) --
   The banner becomes a brushed plate, so everything that sat on ink inside it
   is re-cut for a metal ground: the ink hover states become dark translucent,
   and the hairlines go white rather than blue-on-blue. */
.promo { background: var(--brushed); }
.promo__lead, .promo__step { color: var(--on-metal); }
.promo__step b { color: var(--on-metal); }
.promo__step:hover, .promo__pause:hover { background: rgba(0,0,0,.28); }
.promo__pause { background: rgba(0,0,0,.18); border-left-color: rgba(255,255,255,.34); }
.promo__lead::after, .promo__step::after { background: rgba(255,255,255,.45); }
.promo__step img { border-color: rgba(255,255,255,.45); }

/* ------------------------------------------------ footer (from level 3) --
   The plate stays white. Turning it to ink puts ink text on ink at 1:1, and
   na-map.svg bakes #191a1b and loads through <img>, so no CSS can lift the map
   off a dark ground. White is also where this blue is strongest. */
.site-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: calc(3 * var(--u));
  background: var(--brushed);
}
.site-footer .wordmark--dark { color: var(--metal-mid); }
.site-footer__contact h2 { color: var(--metal-mid); }
.site-footer__nav a:hover { border-bottom-color: var(--metal-mid); }
.site-footer__map figcaption b { color: var(--metal-mid); }

@media (max-width: 1000px) {
  .brand__logo { height: 26px; }
  .site-footer .brand__logo { height: 30px; }
  .services__gb {
    position: relative; left: 0; top: 0;
    width: min(58vw, 320px);
    margin-bottom: 14px;
  }
}
/* ================================================= END BLUE METAL ACCENT */

/* ═══════════════════════════════════════════ MOBILE CORRECTIONS 2026-08-24 */
/* Findings from the mobile inspection of 2026-08-24. Everything here is
   scoped to touch capability or to ≤900px, so the desktop render is
   byte-identical — verified by full-page screenshot diff at 1440px.

   Three defects found in this pass are ALSO live on desktop and are
   deliberately NOT fixed here, because the brief for this pass was
   "mobile only". They remain outstanding:
     · `.vs b` (line 1743) paints the OEM column and the GB column the same
       --accent, so only font-weight separates them. Unconditional.
     · The `img` reset (line 77) has no `height: auto`, so the reduced-motion
       rig drawing renders 1301×1493 at 1400px.
     · --metal-spec sits at the brushed gradient's 50% stop and every button
       centres its label there: white on that plate is 2.41:1. Desktop keeps
       the failure; mobile takes text-bearing buttons off the plate below. */

/* ─────────────────────────────────────────────── touch, not screen width ──
   A capability query, not a breakpoint: on a pointer:fine device every rule
   here is inert, which is why it can sit outside the ≤900px block without
   touching desktop. It also catches the 901–1194px tablet band, where an iPad
   in landscape gets the hover-driven desktop build with no mouse attached. */
@media (hover: none) {
  /* iOS latches :hover after a tap and holds it until you tap elsewhere, so
     every inversion below read as a permanent "selected" state. Press
     feedback moves to :active, which is transient. */
  .act a:hover,
  .cline__rows a:hover,
  .btn--line:hover,
  .btn--ghost:hover,
  .site-faq summary:hover,
  .site-footer__nav a:hover,
  .promo__step:hover {
    background: transparent;
    color: inherit;
    border-bottom-color: transparent;
  }
  .act a:hover { background: transparent; color: var(--paper); }
  .cline__rows a:hover { background: transparent; color: var(--paper); }
  .btn--line:hover { background: transparent; color: var(--paper); }
  .btn--ghost:hover { background: transparent; color: var(--accent); }
  .site-faq summary:hover { color: var(--ink); }
  .site-footer__nav a:hover { border-bottom-color: transparent; }

  .act a:active,
  .cline__rows a:active { background: var(--paper); color: var(--ink); }
  .act a:active .act__k { color: #4a4c4e; }
  .btn--line:active { background: var(--paper); color: var(--ink); }
  .btn--ghost:active { background: var(--paper); color: var(--ink); }
  .site-faq summary:active { color: #4a4c4e; }
  a, button { -webkit-tap-highlight-color: transparent; }

  /* The marquee paused on :hover, so the first tap latched it paused and the
     second tap flipped aria-pressed to false while the track stayed frozen —
     a two-state control that only worked once. Pause is now the class and
     the focus ring only. */
  .promo:hover .promo__track { animation-play-state: running; }
  .promo.is-paused .promo__track,
  .promo:has(:focus-visible) .promo__track { animation-play-state: paused; }
}

@media (max-width: 900px) {
  /* the token was dead below 900px: 47 literal gutters, zero var(--pad) */
  :root { --pad: 20px; }

  html { scroll-padding-top: calc(var(--header-h) + 16px); }

  /* ─────────────────────────────────────────────────────────── the header ──
     Three elements were competing for a 60px bar and flexbox settled it by
     shrinking the two that declared no floor: the logo compressed 19.3% at
     390px and 42.4% at 320px (object-fit is `fill`, so it stretched rather
     than scaled), and the 44px hamburger rendered 31.3–38.2px. */
  .site-header__inner { gap: 12px; }
  .brand, .site-header .brand__logo { flex: none; }
  .nav-toggle { flex: none; margin-left: 0; }
  .site-header .btn--solid {
    flex: none;
    height: 44px;
    padding: 0 12px;
    white-space: nowrap;
    font-size: 12px;
    letter-spacing: .02em;
  }


  /* The accent flattened the comparison: .vs b paints both columns
     rgb(111,159,206) and only font-weight tells them apart — on the section
     that IS the argument, on a board 1,378px tall whose head has scrolled
     away by row 3. White wins, grey loses. */
  .vs__cell--gb b { color: var(--paper); font-weight: 700; }
  .vs__cell--oem b { color: var(--muted); font-weight: 400; }

  /* ────────────────────────────────────────────────────── the touch floor ──
     41px buttons, 41px inputs, 37px part-card CTAs, 30px social icons,
     21px footer contact links. 48 keeps the ramp on the system's own step
     and leaves a margin for gloves. */
  .btn--solid, .btn--line, .btn--submit { height: 48px; }
  .field input, .field select { height: 48px; }
  .field textarea { min-height: 68px; }
  .book__tab { height: 48px; }
  .pcard .btn--line { height: 48px; }
  .social a { width: 44px; height: 44px; }
  .site-footer__contact p a,
  .site-footer__legal a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .site-footer__nav a { display: flex; align-items: center; min-height: 44px; }
  .brand, .site-footer__mark .brand { min-height: 44px; align-items: center; }
  .stepdlg__nav .btn--line { height: 48px; }

  /* Form fields suppressed the focus ring entirely (outline: 0 at :550), so
     the only signal was a 1px hairline changing shade. Restore the system's
     own ring and keep the underline for the mouse path. */
  .field input:focus-visible,
  .field select:focus-visible,
  .field textarea:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  /* ──────────────────────────────────────────────────────── the book tabs ──
     `flex: none` inside `.hero { overflow: hidden }` meant 338.6px of tabs in
     a 320px column was silently amputated below ~386px rather than
     overflowing — which is why document-level overflow read clean. Two equal
     halves sharing one hairline reads as one control, and cannot clip. */
  .book__tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
  .book__tab { flex: none; width: 100%; min-width: 0; padding: 0 10px; font-size: 12.5px; }
  .book__tab + .book__tab { border-left: 0; }

  /* Switching panels grew the box 164px and shoved the page under the thumb.
     Both panels now share one grid cell, so the taller sets the height. */
  .book__panels { display: grid; }
  .book__panels > .book__panel { grid-area: 1 / 1; }
  .book__panels > .book__panel[hidden] { display: block; visibility: hidden; pointer-events: none; }

  /* ───────────────────────────────────────────────────────── the act rows ──
     A desktop label-left / verb-right row squeezed into 390px: the kicker
     took 218px and wrapped to three lines while the action took 107px and
     wrapped to four, and the arrow — with no flex floor — was crushed to
     width 0 on the longest label. On touch that arrow is the only signal the
     row is tappable, because the hover inversion never fires. */
  .act a { flex-direction: column; align-items: stretch; gap: 10px; min-height: 96px; }
  .act__k { text-align: left; }
  .act__v {
    font-size: 24px;
    text-align: left;
    justify-content: space-between;
    white-space: normal;
  }
  .act__v svg { flex: 0 0 auto; width: 24px; height: 24px; }

  /* ────────────────────────────────────────────────────────── the drawing ──
     The reset clamps width but leaves the height attribute literal, and
     object-fit is `fill` — so a 2000×1493 drawing rendered 350×1493, a 5.7×
     squeeze, across 1,525px of page. */
  .rig__static > figure img { height: auto; }

  /* ─────────────────────────────────────── text over photographs, on ink ──
     The mobile hero already solves this by dropping its photo to .4; the
     other two plates never got the same treatment. Measured minimums before:
     .shift__cap 1.77:1, .design__body p 3.23:1. */
  .shift__bg { opacity: .28; }
  .design__bg { opacity: .16; }
  .phead__bg { opacity: .26; }

  /* ────────────────────────────────────────────────────── the step dialog ──
     A centred desktop modal on a 640px-tall phone computed 602px with 680px
     of content: Previous/Next landed 34px past the viewport and the close,
     being absolute, scrolled away when you reached them. Anchored to the
     bottom, browser chrome eats dead space at the top instead of the
     controls, and the nav bar is sticky so it cannot scroll off. */
  .stepdlg {
    width: 100%;
    max-width: none;
    max-height: 92dvh;
    margin: auto auto 0;
    border-bottom: 0;
    display: flex;
    flex-direction: column;
    overscroll-behavior: contain;
  }
  .stepdlg__inner {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(0, 1fr);
    overflow-y: auto;
    min-height: 0;
  }
  .stepdlg__shot { padding: 14px; }
  .stepdlg__shot img { max-height: 38svh; }
  .stepdlg__nav {
    position: sticky;
    bottom: 0;
    margin-top: 0;
    padding: 12px 0 calc(12px + env(safe-area-inset-bottom));
    background: var(--ink);
    border-top: 1px solid var(--rule-faint);
  }
  .stepdlg__nav .btn--line { flex: 1; min-width: 0; }
  /* the close stays absolute to the dialog, which now works: only
     .stepdlg__inner scrolls, so the corner no longer slides away */

  /* ──────────────────────────────────────────────────────── the marquee ──
     Client call, 2026-08-25: the banner keeps moving on mobile. It had been
     frozen into a swipeable strip because its labels were fully legible only
     6.6s of every 45.4s cycle and its tap targets slid while you aimed.

     Two things have to hold for a moving banner to stay legitimate:
       · WCAG 2.2.2 needs a pause control for anything that auto-moves for more
         than five seconds, so .promo__pause comes back — with an OPAQUE ground,
         because at rgba(0,0,0,.18) the step labels scrolled visibly underneath
         it and it read as a rendering fault.
       · The hover-pause never fires on touch, so that button is the only pause
         a phone has; the @media (hover: none) block above is what stops iOS
         latching it paused after the first tap. */
  .promo__pause { display: flex; background: var(--metal-lo); }
  .promo__track { padding-right: 46px; }

  /* The first row of the home page was two 30px social icons floating right
     against an empty left — the hole left by the hidden logo cell, put there
     by `order: -1`. The identity block in the footer is where they belong;
     here they cost 100px of the first viewport before the first word. */
  .hero__cell--social { display: none; }

  /* ───────────────────────────────────────────────────────── safe areas ──
     viewport-fit=cover is now set on all five pages, so the gutters have to
     clear the notch in landscape and the footer strip has to clear the home
     indicator. */
  .site-header__inner,
  .promo__track { padding-left: max(20px, env(safe-area-inset-left)); padding-right: max(20px, env(safe-area-inset-right)); }
  .site-footer__strip { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
}

/* ───────────────────────────────────── components added in the mobile pass ─
   Base declarations are deliberately inert on desktop: the action bar is
   display:none and .book__panels is display:contents, so a 1440px render is
   unchanged. Both come alive inside the ≤900px block below. */
.actionbar { display: none; }
.book__panels { display: contents; }
/* `display: contents` and not `block`: several of these images are
   position:absolute background plates, and a picture box in the flow shifted
   the mission photo band on the desktop home page. Caught by screenshot diff. */
picture { display: contents; }

/* "Privacy policy" and "Accessibility statement" were href="#" on all five
   pages — tapping either threw the reader 5,774px back to the hero. They read
   as plain text until the pages exist. See docs/QUESTIONS-FOR-GB.md. */
.site-footer__legal .pending { color: #4a4c4e; }

/* the skip link's target is focusable now; it should not draw a ring */
main:focus { outline: none; }

@media (max-width: 900px) {
  /* ─────────────────────────────────────────────── the bottom action bar ──
     The two actions that matter, in the thumb zone, on every screen. The
     header CTA was 33px pinned to the least reachable corner, and index and
     market ended with two full screens carrying no action at all. Ink ground
     with a firm top rule — the same plate language as the header, inverted
     only on the CTA cell, which is the system's law for emphasis. */
  .actionbar {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 11;
    display: grid;
    grid-template-columns: 1fr auto;
    background: var(--ink);
    border-top: 1px solid var(--rule);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .actionbar a {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    min-height: 56px;
    padding: 0 18px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
  }
  .actionbar__tel { color: var(--paper); border-right: 1px solid var(--rule-soft); }
  .actionbar__tel span { font-family: var(--font-mark); font-weight: 800; letter-spacing: .06em; }
  .actionbar__tel svg { width: 18px; height: 18px; flex: none; }
  /* The bar was built before the metal came back, and .actionbar__cta is its
     own class — so it was not in the selector list that lifted --brushed-text
     site-wide and stayed the last paper-filled button on the site. Every other
     "Open GB Market" is metal; a white one here read as a different kind of
     control. The bar keeps its separation from the ink ground and its firm top
     rule, not from the fill. */
  .actionbar__cta { background: var(--brushed-text); color: var(--on-metal); }
  .actionbar__cta:active { box-shadow: inset 0 0 0 999px rgba(8, 22, 38, .56); }
  .actionbar__tel:active { background: var(--ink-2); }
  body { padding-bottom: 56px; }
  /* the bar would otherwise cover the nav panel and the dialog backdrop */
  body:has(.site-nav.is-open) .actionbar,
  body:has(dialog[open]) .actionbar { display: none; }

  /* both hero panels share one grid cell, so the taller sets the height and
     switching tabs stops moving the page 164px under the thumb */
  .book__panels { display: grid; }
  .book__panels > .book__panel { grid-area: 1 / 1; }
  .book__panels > .book__panel[hidden] {
    display: block;
    visibility: hidden;
    pointer-events: none;
  }

  /* the phone captures are 780×1688; at full column width they would tower.
     Capped and centred, the app renders at ~38% of true size and the part
     numbers, prices and fleet chips read. */
  .shotframe { max-width: 300px; margin-inline: auto; }
}

/* ─────────────────────────────── the walkthrough deck (market.html, mobile) ─
   Desktop keeps the alternating media/copy rows exactly as they were: the deck
   is display:contents and the rail is display:none, so a 1440px render is
   unchanged. Below 900px the alternation collapses — .walk__row--flip un-flips
   — and five byte-identical blocks stack for 4,047px, 49% of the page, with no
   way to tell step 2 of 5 from step 4 of 5. The deck restores what the
   alternation was doing (making five parallel things feel parallel) in a
   gesture the app itself already uses. */
.walk__deck { display: contents; }
.walk__rail, .walk__hint { display: none; }

@media (max-width: 900px) {
  /* the largest section on the page had only an sr-only heading, so a phone
     reader met five screenshots with no idea what they were */
  .walk > .sr-only#walk-title {
    position: static;
    width: auto; height: auto;
    clip: auto; clip-path: none;
    overflow: visible; white-space: normal;
    display: block;
    padding: 40px 20px 0;
    font-size: clamp(30px, 8vw, 40px);
    font-weight: 400;
    line-height: 1.06;
    letter-spacing: -.02em;
    max-width: 14ch;
  }
  .walk__hint {
    display: block;
    padding: 14px 20px 20px;
    font-size: 13.5px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-2);
  }

  .walk__deck {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    /* the band closes on both edges — the row's right rule alone read as a
       border that ran halfway down the section and stopped */
    border-top: 1px solid var(--rule-soft);
    border-bottom: 1px solid var(--rule-faint);
  }
  .walk__deck::-webkit-scrollbar { display: none; }
  .walk__row {
    flex: 0 0 86vw;
    scroll-snap-align: start;
    border-top: 0;
    border-right: 1px solid var(--rule-faint);
  }
  .walk__row:last-child { border-right: 0; }
  .walk__copy { padding: 26px 20px 4px; }
  .walk__media { padding: 16px 20px 30px; }
  .walk__copy h3 { font-size: 26px; }

  /* the rail is the primary control: five hairline segments, each in a 44px
     hit box, the active one stepping --rule-faint → --rule. It is also the
     only "3 of 5" signal the page has ever had. */
  .walk__rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    border-top: 1px solid var(--rule-soft);
  }
  .walk__rail button {
    width: 100%;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-top: 2px solid transparent;
    color: var(--muted-2);
    cursor: pointer;
  }
  .walk__rail li + li button { border-left: 1px solid var(--rule-faint); }
  .walk__rail b {
    font-family: var(--font-mark);
    font-weight: 800;
    font-size: 13px;
    letter-spacing: .12em;
  }
  .walk__rail button[aria-current="true"] {
    border-top-color: var(--paper);
    color: var(--paper);
  }
  .walk__rail button:active { background: var(--ink-2); }

  /* clipped, not scaled: the phone capture is a 2× shot of a 390pt screen, so
     at 270px it renders the app at ~69% of true size and the part numbers,
     prices and fleet chips read. Showing all 1688px of it would cost 584px of
     scroll per row, so the frame is a window onto the top of the screen —
     the same device .appbox__screen already uses. */
  .walk__media .shotframe { max-width: 262px; }
  .walk__media .shotframe picture { display: block; height: 360px; overflow: hidden; }
  .walk__media .shotframe img { height: 100%; object-fit: cover; object-position: top center; }
}

@media (min-width: 901px) {
  /* Wrapping the rows in .walk__deck made `.walk__row:first-child` (line 1146)
     match for the first time — the sr-only <h2> used to hold that slot — so
     row 1 silently lost the 1px rule it has always rendered with. Restored, so
     the desktop render stays byte-identical. Caught by screenshot diff. */
  .walk__deck > .walk__row:first-child { border-top: 1px solid var(--rule-soft); }
}

/* The Facebook link lived ONLY in the home hero's social rail, which is
   display:none below 900px — so hiding that rail would have removed GB's only
   Facebook link from every phone. It moves to the footer identity block, where
   it reaches all five pages at a real tap size on every device. */
.site-footer__social { display: flex; gap: calc(14 * var(--u)); margin: calc(22 * var(--u)) 0 0; }
.site-footer__social a {
  display: inline-flex;
  align-items: center;
  gap: calc(8 * var(--u));
  color: #4a4c4e;
  font-size: calc(15 * var(--u));
}
.site-footer__social svg { width: calc(20 * var(--u)); height: calc(20 * var(--u)); }
.site-footer__social a:hover { color: var(--ink); }
@media (max-width: 900px) {
  .site-footer__social a { min-height: 44px; }
}

/* ══════════════════════════ the mobile rig section (solutions.html, ≤900px) ─
   The desktop scroll tour is a 520svh pinned stage with a zooming camera and a
   masked spotlight. It cannot be ported to a phone, and the reasons are
   measurements, not taste:
     · all five hotspots sit in the left quarter of the drawing and two are
       0.064 apart in data-y — on a correctly proportioned 350×261 render that
       is 17 CSS px of separation, and two 44px targets cannot sit 17px apart;
     · the spotlight masks a `circle 340px` hole, which on a 350px-wide stage
       is the entire frame;
     · a 460svh pinned stage resizes mid-tour when iOS collapses the URL bar,
       moving the step boundaries under the thumb.

   So the relationship inverts: on desktop the drawing leads and the card is
   the readout; here the CARD is the hero and the drawing is the compass. Its
   job is to say "on your machine, here".

   Everything below is inert above 900px — .rigm__* is display:none and
   .rig__static keeps its existing `display: none` from the desktop rules. */
.rigm__pin, .rigm__count, .rigm__hint, .rigm__rail { display: none; }
.rigm__deck, .rigm__stage { display: contents; }

@media (max-width: 900px) {
  /* --rig-img-h drives both the drawing and the marker geometry, so a tier
     that changes the drawing's size cannot desync the markers from it. */
  /* --rig-img-h is stamped by site.js from screen.height, which is the one
     height on a phone that never moves. The tiers used to be `@media
     (min-height/max-height)`, and those re-evaluate the moment the URL bar
     collapses on the first scroll — which is exactly the few-pixel shrink-and-
     grow the client reported. This value is written once and only recomputed
     on an orientation change. The declaration below is the no-JS fallback,
     keyed to width, which is also stable. */
  .rig__static { --rig-img-h: 158px; }
  @media (min-width: 415px) { .rig__static { --rig-img-h: 200px; } }
  @media (max-width: 374px) { .rig__static { --rig-img-h: 124px; } }

  .rigm__stage { display: block; position: relative; }

  /* A plain band at the top of the section: fixed height, in normal flow.
     It was sticky, which parked it on top of the part cards when you scrolled
     a little too far; and for one pass it was a flex item absorbing whatever
     the card left over, which made it resize when the card's lazy render
     arrived. Neither now. */
  .rig__static > .rigm__stage > figure {
    position: static;
    height: auto;
    padding: 12px 20px 10px;
    margin: 0;
    background: var(--ink);
    border-bottom: 1px solid var(--rule-soft);
    overflow: hidden;
  }

  /* The camera. The drawing is 2000x1493, so the box is exactly its painted
     size and the markers can be placed on it in plain percentages. Scaling
     this element toward the active marker is what makes the machine read
     bigger than the band it sits in — the same device the desktop tour uses,
     at a fraction of its travel. */
  .rigm__cam {
    position: relative;
    width: calc(var(--rig-img-h) * 1.3396);
    height: var(--rig-img-h);
    margin: 0 auto;
    transform: scale(var(--rig-z, 1));
    transform-origin: calc(var(--rig-ox, .5) * 100%) calc(var(--rig-oy, .5) * 100%);
    transition: transform .78s cubic-bezier(.22, 1, .36, 1);
    will-change: transform;
    /* The drawing is composited with `mix-blend-mode: screen` so its inverted
       black ground drops out. `will-change` + `transform` make this element its
       own stacking context, so that blend was compositing against transparency
       instead of the page — which painted the camera's box as a visibly
       different black. Giving the camera the same ink ground puts the backdrop
       back under the blend. */
    background: var(--ink);
  }
  .rig__static > .rigm__stage > figure img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: .5;
    /* The drawing is dark lines on a white ground, inverted for the ink page.
       `contrast(.82)` lifts that inverted black off pure, which was invisible
       while the image filled the band and became a visible grey rectangle once
       object-fit:contain letterboxed it. `screen` drops the ground entirely —
       black contributes nothing — so only the lines survive. */
    filter: invert(1) brightness(1.25);
    mix-blend-mode: screen;
    transition: opacity .28s ease;
  }
  .rig__static.is-live > .rigm__stage > figure img { opacity: .66; }

  /* Markers, not controls. They reuse the desktop hotspot coordinates verbatim
     and follow the card you are on, but nothing on the drawing is tappable:
     two of the five sit 0.064 apart in data-y, about 6px at this size, and two
     44px targets cannot live there. The rail under the deck is the control.
     They counter-scale so the camera move does not inflate them. */
  .rigm__pin {
    display: block;
    position: absolute;
    left: calc(var(--x) * 100%);
    top: calc(var(--y) * 100%);
    /* 9px again. They went to 7 because two sit 0.064 apart in data-y and were
       touching — but at 2.05 the drawing is twice the size, so the gap between
       them on screen doubles and 9px clears comfortably. */
    width: 9px;
    height: 9px;
    transform: translate(-50%, -50%) scale(calc(1 / var(--rig-z, 1)));
    background: var(--paper);
    outline: 1px solid var(--rule-soft);
    outline-offset: 2px;
    opacity: .45;
    pointer-events: none;
    transition: opacity .3s ease, background .3s ease, outline-color .3s ease,
                transform .78s cubic-bezier(.22, 1, .36, 1);
  }
  .rigm__pin[aria-current="true"] {
    opacity: 1;
    background: var(--accent);
    outline: 2px solid var(--paper);
    outline-offset: 1px;
  }

  .rigm__count {
    display: block;
    position: absolute;
    top: 12px;
    right: 20px;
    font-family: var(--font-mark);
    font-weight: 800;
    font-size: 13px;
    letter-spacing: .12em;
    color: var(--muted-2);
  }

  .rigm__hint {
    display: block;
    padding: 16px 20px 12px;
    font-size: 13px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-2);
  }

  /* one card per viewport instead of five stacked for 3,831px */
  .rigm__deck {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    border-top: 1px solid var(--rule-faint);
  }
  .rigm__deck::-webkit-scrollbar { display: none; }
  .rig__static .pcard {
    flex: 0 0 88vw;
    scroll-snap-align: start;
    border-top: 0;
    border-right: 1px solid var(--rule-faint);
    padding: 24px 20px 30px;
  }
  .rig__static .pcard:last-child { border-right: 0; }

  /* the rail is the PRIMARY control — five 44px segments you can hit with a
     glove. The pins are the secondary one. */
  .rigm__rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    border-top: 1px solid var(--rule-soft);
    border-bottom: 1px solid var(--rule);
  }
  .rigm__rail button {
    width: 100%;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-top: 2px solid transparent;
    color: var(--muted-2);
    cursor: pointer;
  }
  .rigm__rail li + li button { border-left: 1px solid var(--rule-faint); }
  .rigm__rail b { font-family: var(--font-mark); font-weight: 800; font-size: 13px; letter-spacing: .12em; }
  .rigm__rail button[aria-current="true"] { border-top-color: var(--paper); color: var(--paper); }
  .rigm__rail button:active { background: var(--ink-2); }
}

/* The deck is a progressive enhancement, not a mode: with reduced motion the
   cards stack vertically exactly as they did before this pass, the strip stops
   being sticky, and the pins and rail render inert. Content-complete either
   way — no information lives only inside the interaction. */
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .rig__static > .rigm__stage > figure img { height: var(--rig-img-h); }
  .rigm__deck { display: block; overflow: visible; scroll-snap-type: none; }
  .rig__static .pcard { border-right: 0; border-top: 1px solid var(--rule-faint); }
  .rigm__pin, .rigm__count, .rigm__rail, .rigm__hint { display: none; }
}

/* ═══════════════════════════════ form pass — client feedback 2026-08-25 ════
   "What's it about?" is gone from both panels, and the two forms now have to
   toggle without moving anything around them. */

/* Both panels occupy ONE grid cell, so the box is always the height of the
   taller one and switching tabs cannot resize the hero. Previously the email
   panel un-collapsed a row and stretched the hero on desktop; on mobile the
   call panel left the gap that row would have filled. */
.book__panels { display: grid; }
.book__panels > .book__panel { grid-area: 1 / 1; }
.book__panels > .book__panel[hidden] {
  display: block;
  visibility: hidden;
  pointer-events: none;
}
/* The call panel is one row shorter than the email panel, so the shared cell
   leaves it some slack. Collecting that slack in one place — above the button
   — just moved the hole the client reported rather than closing it, so it is
   distributed across the panel's own gaps instead: the call form reads as the
   roomier of the two rather than as a form with a hole in it. */
.book__panel { display: flex; flex-direction: column; justify-content: space-between; }

/* The tab pair sat flush against the first label. */
.book__tabs { margin-bottom: calc(26 * var(--u)); }

/* The Send button was `justify-items: end` on a full-width row — a small
   square in the corner, reading as a default form control rather than the
   twin of "Book the call". Both are now the full measure of the panel. */
.book__row--send { justify-items: stretch; }
.book__row--send .field--submit { justify-content: stretch; }
.book__row--send .btn--submit { width: 100%; }

@media (max-width: 900px) {
  .book__tabs { margin-bottom: 22px; }
}

/* The pause control was absolutely positioned OVER the moving track, so
   whichever step happened to sit under it could not be tapped at all —
   Playwright reports "<button class=promo__pause> intercepts pointer events"
   and a thumb hits the same wall. `padding-right: 46px` on the track only
   reserved clearance at the END of the loop, not continuously.
   The window wrapper is display:contents above 900px, so .promo clips the
   track exactly as it always has and the desktop render is unchanged. */
.promo__window { display: contents; }

@media (max-width: 900px) {
  .promo { display: flex; align-items: stretch; }
  .promo__window { display: block; flex: 1 1 auto; min-width: 0; overflow: hidden; }
  /* order:2 keeps it on the right, where the desktop banner puts it */
  .promo__pause { position: static; flex: 0 0 46px; height: auto; order: 2; }
  .promo__track { padding-right: 0; }
}

/* ═════════════════════════════ text-bearing plates — client call 2026-08-25 ═
   The buttons keep the brushed blue; the sheen is what moves.

   --brushed puts --metal-spec (#7ba6d0) at the gradient's 50% stop, and every
   button centres its label there — so white measured 2.41:1 on the header CTA,
   2.88:1 on submit and 1.00:1 on the selected tab, sampled off the bare plate.
   Ink is not the alternative: it falls to 1.70:1 at the plate's dark edges.

   --brushed-text is the same grain and the same 97deg rake, cresting at
   --metal-crest (#3c6d99) where white measures 5.47:1 and clears AA. Beside the
   promo banner — which keeps --brushed, since it is the one plate the client
   confirmed reads well — it is the same material one stop down in the middle.

   This was mobile-only when it landed; it is site-wide now because the desktop
   Submit went full-measure in the same pass, which put more of the label
   across the specular band, and because a control should not change material
   at a breakpoint. The banner and the brand lockups still take --brushed. */
.btn--solid, .btn--submit,
.book__tab[aria-selected="true"],
.tag--fill,
.vs__head--gb {
  background: var(--brushed-text);
  border-color: var(--metal-hi);
}
.btn--ghost:hover { background: var(--brushed-text); }
.act a:hover { background: var(--brushed-text); }
.vs__head--gb h3 { color: var(--on-metal); }
.vs__head--gb span { color: rgba(255, 255, 255, .86); }

@media (max-width: 900px) {
  /* the sticky comparison head repaints .vs__head, and .vs__head and
     .vs__head--gb are both single-class selectors, so the GB plate has to be
     re-asserted after it */
  .vs__head--gb { background: var(--brushed-text); }
}

/* ══════════ the rig section fits one screen — client call 2026-08-25 ══════
   "The cards are too big to fit in-screen with the rig drawing, the drawing
   needs to be bigger, and the section needs to be smaller."

   Measured at 390×844: the section wanted 1,169px against 727px of usable
   viewport (844 minus the 60px sticky header and the 56px action bar), and
   the card alone was 888. On a 375×667 SE the budget is 563.

   So the card is CUT, not scaled — shrinking type to fit would have made the
   part number and price unreadable, which is the only reason the card exists.
   The "Also in this assembly" chip list goes (154px + its 17px label): the
   meta line above it already says how many GB-made components the assembly
   holds, and the CTA goes to the place that lists them. Everything else keeps
   its type size and loses only slack. */
@media (max-width: 900px) {
  /* the drawing scales with the viewport instead of a fixed 168px, so it can
     be BIGGER on a normal phone and still clear the budget on a short one */
  .rig__static > .rigm__stage > figure img {
    height: calc(100% - 4px);
    opacity: .55;
  }
  .rigm__count { top: 8px; }

  /* The hint is gone rather than shrunk. At 360px it wrapped to two lines and
     cost 60px — which was the entire margin between "fits one screen" and
     "overflows into the next section" on that width. The rail below the deck
     is self-evident, and the section heading already frames it. */
  .rigm__hint { display: none; }

  .rig__static .pcard { padding: 16px 20px 20px; }
  .rig__static .pcard__well { margin-bottom: 2px; }
  .rig__static .pcard__well img { height: 104px; padding: 8px; }
  .rig__static .pcard h3 { font-size: 22px; margin-top: 2px; }
  .rig__static .pcard__fit {
    margin-top: 6px;
    font-size: 14px;
    line-height: 1.45;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .rig__static .pcard__rigs { margin-top: 8px; }
  .rig__static .pcard__row { margin-top: 10px; gap: 12px; }
  .rig__static .pcard__price { font-size: 26px; }
  .rig__static .pcard__usd { margin-top: 2px; }
  .rig__static .pcard__meta {
    margin-top: 10px;
    padding-top: 8px;
    font-size: 13.5px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  /* the chip list and its label — the meta line above already carries the count */
  .rig__static .pcard__also-k,
  .rig__static .pcard__chips { display: none; }
  .rig__static .pcard .btn--line { margin-top: 12px; height: 44px; }

  /* Short phones — an SE has 563px of usable viewport against a card whose
     rows want 496. The instruction line goes first, then the assembly count
     (the CTA leads to the place that lists them), then the fitment line drops
     to one clamp. The part number, the fitment chips, the price, the USD
     conversion and the render all survive at every height. */
  /* Short phones. Keyed off a data attribute stamped from screen.height, not
     a max-height media query — the query re-evaluates when the URL bar
     collapses and the section visibly resized on the first scroll. */
  /* Three tiers, escalating. site.js tries them in order and stops at the
     first that leaves room for a usable drawing and render — it does not pick
     from a height threshold, because the amount a card needs depends on how
     its copy wraps at that width, not on the viewport alone. */
  .rig__static[data-rig-tier="short"] .pcard__meta,
  .rig__static[data-rig-tier="tiny"] .pcard__meta { display: none; }
  .rig__static[data-rig-tier="short"] .pcard__fit,
  .rig__static[data-rig-tier="tiny"] .pcard__fit { -webkit-line-clamp: 1; }
  .rig__static[data-rig-tier="short"] .pcard .btn--line,
  .rig__static[data-rig-tier="tiny"] .pcard .btn--line { height: 40px; margin-top: 10px; }
  .rig__static[data-rig-tier="short"] .pcard,
  .rig__static[data-rig-tier="tiny"] .pcard { padding: 12px 20px 14px; }

  /* tiny is for SE-class phones, where the usable viewport is about 447px.
     The USD conversion and the fitment chips go; the part number, the name,
     the price, the render and the CTA survive at every size. */
  .rig__static[data-rig-tier="tiny"] .pcard__usd,
  .rig__static[data-rig-tier="tiny"] .pcard__rigs { display: none; }
  .rig__static[data-rig-tier="tiny"] .pcard h3 { font-size: 19px; }
}

/* The drawing is a FIXED size and is not sticky.
   It was briefly both a flex absorber (taking whatever the card left over) and
   sticky. Both were wrong: the absorber made it visibly resize on the first
   scroll, because the card's lazy-loaded render arrives then and changes the
   card's height; and sticky meant that scrolling a little too far parked the
   drawing on top of the part cards. It is a plain band at the top of the
   section now — the numbers below are what make the section fit a screen, not
   a layout trick. */
@media (max-width: 900px) {
  .rig__static { display: block; }
  .rigm__stage { display: block; }

  .rig__static > .rigm__stage > figure {
    position: static;
    height: auto;
    padding: 12px 20px 10px;
  }
  .rig__static > .rigm__stage > figure img {
    height: var(--rig-img-h);
    opacity: .55;
  }
  .rig__static .pcard__well img { height: var(--rig-well-h, 104px); }
}

/* Reduced motion keeps the vertical stack, so the viewport-height composition
   has to stand down with it — otherwise five full-height cards would be
   clipped inside one screen's worth of box. */
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .rig__static { display: block; height: auto; }
  .rigm__stage { display: block; }
  .rig__static > .rigm__stage > figure { flex: none; height: auto; }
  .rig__static .pcard { height: auto; overflow: visible; }
  .rig__static .pcard__well img { height: var(--rig-well-h, 104px); }
}

/* ═════════ the walkthrough fits one screen — client call 2026-08-25 ═══════
   Same problem as the rig section and the same answer: the step card was
   995px against 728px of usable viewport at 390×844. The section is sized to
   the viewport and the SCREENSHOT absorbs the difference, so every line of
   copy keeps its measured size on every phone and the app capture is large on
   a roomy screen and smaller on a short one.

   The instruction line goes for the same reason it went on the rig section —
   at 360px it wrapped to two lines and ate the entire margin. */
@media (max-width: 900px) {
  .walk {
    display: flex;
    flex-direction: column;
    height: calc(100svh - var(--header-h) - 58px);
    min-height: 460px;
  }
  .walk > .sr-only#walk-title {
    flex: 0 0 auto;
    /* it was padded to 0 at the foot and sat straight on the deck's top rule */
    padding: 22px 20px 18px;
    font-size: clamp(26px, 7vw, 34px);
    max-width: 18ch;
  }
  .walk__hint { display: none; }
  .walk__deck { flex: 1 1 auto; min-height: 0; align-items: stretch; }
  .walk__rail { flex: 0 0 auto; }

  .walk__row {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
  }
  .walk__copy { flex: 0 0 auto; padding: 16px 20px 0; }
  .walk__copy h3 { font-size: 21px; margin-top: 2px; }
  .walk__copy > p {
    margin-top: 6px;
    font-size: 14px;
    line-height: 1.45;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .walk__list { margin-top: 8px; }
  .walk__list li {
    font-size: 12.5px;
    line-height: 1.4;
    padding-top: 4px;
    padding-bottom: 4px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* the capture is the flexible element */
  .walk__media { flex: 1 1 auto; min-height: 0; padding: 10px 20px 14px; justify-content: flex-start; }
  .walk__media .shotframe { flex: 1 1 auto; min-height: 0; max-width: 244px; }
  .walk__media .shotframe picture { height: 100%; min-height: 90px; }
  .shotcap { display: none; }

  @media (max-height: 720px) {
    .walk__list { display: none; }
    .walk__copy > p { -webkit-line-clamp: 2; }
  }
}

/* the vertical composition stands down with reduced motion, where the rows
   stack instead of running as a deck */
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .walk { display: block; height: auto; }
  .walk__row { display: block; overflow: visible; }
  .walk__media { display: flex; }
  .walk__media .shotframe { flex: none; }
  .walk__media .shotframe picture { height: 360px; }
  .shotcap { display: block; }
}
