/* =====================================================================
   WALKER'S REPAIR - "FORGED"
   Design system: black + white structure, racing-red heat, brand gray for
   technical detail. Engineering-schematic detailing, motorsport display type.
   ===================================================================== */
@import url('../fonts/fonts.css');

/* ---------- Tokens ---------------------------------------------------- */
:root {
  /* color - black/white base, racing red + gray accents.
     2026-08-27: whole ramp lifted a step (client: site read too dark).
     2026-08-31: lifted a second step (client asked again) - keep
     bg < bg-2 < surface < surface-2 monotonic if retuning. */
  --bg:        #14161A;
  --bg-2:      #191B20;
  --surface:   #22242A;
  --surface-2: #2B2E35;
  --line:      rgba(255, 255, 255, .10);  /* decorative hairlines only */
  --line-2:    rgba(255, 255, 255, .36);  /* VISIBLE boundaries: resting button
                            borders and link underlines. Raised from .20 on
                            2026-09-01: composited it was only 1.9:1 against the
                            page, so the outline buttons read as borderless
                            until hover. .36 lands at 3.3:1 on --bg and 3.3:1 on
                            --surface, clearing the 3:1 floor for UI edges. */
  --red:       #E73232;  /* Racing Red - the brand accent. AA-safe only at
                            LARGE sizes (4.23:1 on --bg): headlines, the
                            cycling word, icons. Use --red-hi for small text. */
  --red-hi:    #FF4A4A;  /* small-text + hover red: 5.46:1 on --bg, 5.19 on
                            --bg-2, 4.68 on --surface, so it clears AA at any
                            size. Every mono label and link hover uses it. */
  --red-deep:  #C21F1F;  /* button gradient base; white on it is 5.98:1 */
  --red-grad:  #DA2A2A;  /* button gradient TOP. Pure --red left white labels
                            at 4.29:1, just under AA; this is 4.83:1 and the
                            bottom of the ramp is darker still. */
  --text:      #FFFFFF;
  --muted:     #ABAFB6;  /* tint of the brand gray - passes as body copy on black */
  --gray:      #8E939C;  /* brand gray for small labels. Lifted again on
                            2026-08-31 after the second background lift left it
                            at 4.25:1 on --surface; now 5.03:1 there and 5.87:1
                            on --bg, with headroom if the ramp lifts again. */

  /* type */
  --f-display: 'Saira Condensed', 'Arial Narrow', sans-serif;
  --f-body:    'Hanken Grotesk', system-ui, sans-serif;
  --f-mono:    'JetBrains Mono', ui-monospace, monospace;

  /* fluid scale. step--1 floor raised 2026-08-27 so the small print stays
     readable for older visitors - don't shrink it back below .88rem. */
  --step--1: clamp(.88rem, .84rem + .18vw, .98rem);
  --step-0:  clamp(1rem, .96rem + .2vw, 1.12rem);
  --step-1:  clamp(1.2rem, 1.1rem + .5vw, 1.5rem);
  --step-2:  clamp(1.55rem, 1.3rem + 1.2vw, 2.4rem);
  --step-3:  clamp(2.2rem, 1.6rem + 3vw, 4rem);
  --step-4:  clamp(3rem, 1.9rem + 5.5vw, 6.5rem);
  --step-5:  clamp(3.8rem, 2rem + 9vw, 10rem);

  /* space */
  --gutter: clamp(1.15rem, .6rem + 2.5vw, 2.5rem);
  --section-y: clamp(4.5rem, 3rem + 7vw, 9rem);
  --maxw: 1320px;

  /* motion */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur: .7s;
}

/* ---------- Reset ----------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; } /* native OS scrolling - no smooth-scroll hijack */
body {
  font-family: var(--f-body);
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img, video, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
ul { list-style: none; padding: 0; }
/* Brighter red for the focus ring - brand red alone is a touch dim on pure black. */
:focus-visible { outline: 2px solid var(--red-hi); outline-offset: 3px; border-radius: 2px; }
::selection { background: var(--red); color: #fff; }

/* ---------- Ambient background: film grain + blueprint grid ----------- */
body::before { /* fine grain */
  content: ""; position: fixed; inset: 0; z-index: 1; pointer-events: none;
  opacity: .05; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
body::after { /* faint blueprint grid */
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: .4;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 88px 88px;
  -webkit-mask-image: radial-gradient(ellipse 90% 60% at 50% 0%, #000 10%, transparent 75%);
          mask-image: radial-gradient(ellipse 90% 60% at 50% 0%, #000 10%, transparent 75%);
}
main, .site-header, .site-footer { position: relative; z-index: 2; }

/* ---------- Layout ---------------------------------------------------- */
.container { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: clamp(3rem, 2rem + 4vw, 5rem); }

/* ---------- Type ------------------------------------------------------ */
.display, h1, h2, h3 { font-family: var(--f-display); font-weight: 800; line-height: .92;
  text-transform: uppercase; letter-spacing: .005em; }
h1, .h1 { font-size: var(--step-4); }
h2, .h2 { font-size: var(--step-3); }
h3, .h3 { font-size: var(--step-2); letter-spacing: .01em; }
p { color: var(--muted); max-width: 62ch; }
strong { color: var(--text); font-weight: 700; }

/* Eyebrow - technical label with a leading tick (schematic vernacular) */
.eyebrow {
  font-family: var(--f-mono); font-size: var(--step--1); font-weight: 500;
  letter-spacing: .32em; text-transform: uppercase; color: var(--red-hi);
  display: inline-flex; align-items: center; gap: .8em;
}
.eyebrow::before { content: ""; width: 26px; height: 1px; background: var(--red-hi); flex: none; }
.eyebrow--muted { color: var(--gray); }
.eyebrow--muted::before { background: var(--gray); }
/* The raised step--1 floor makes .32em tracking overflow narrow phones */
@media (max-width: 480px) { .eyebrow { letter-spacing: .16em; } }

.mono { font-family: var(--f-mono); letter-spacing: .02em; }
.lede { font-size: var(--step-1); color: var(--text); font-weight: 400; line-height: 1.45; max-width: 46ch; }

/* Red-hot word inside a headline */
.hot { color: var(--red); }

/* ---------- Buttons --------------------------------------------------- */
.btn {
  --pad: .95em 1.5em;
  display: inline-flex; align-items: center; gap: .7em; padding: var(--pad);
  font-family: var(--f-mono); font-size: var(--step--1); font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--text);
  border: 1px solid var(--line-2); border-radius: 2px; position: relative;
  transition: color .35s var(--ease), border-color .35s var(--ease), transform .35s var(--ease);
  will-change: transform;
}
.btn svg { width: 1em; height: 1em; }
.btn:hover { border-color: var(--text); transform: translateY(-2px); }
/* Racing-red fill. The gradient runs --red-grad -> --red-deep so the white
   label clears 4.5:1 against every band of it, not just the bottom. Starting
   it at pure --red left the top band at 4.29:1 (checked 2026-08-31). */
.btn--red {
  color: #fff; border-color: transparent;
  background: linear-gradient(180deg, var(--red-grad), var(--red-deep));
  box-shadow: 0 0 0 0 rgba(231, 50, 50, .5);
}
.btn--red:hover { border-color: transparent; box-shadow: 0 14px 40px -12px rgba(231, 50, 50, .7); }
.btn--lg { --pad: 1.15em 2em; font-size: var(--step-0); }
.btn--block { display: flex; justify-content: center; width: 100%; }

/* ---------- Schematic frame (crosshair corners + tick) ---------------- */
.frame { position: relative; }
.frame::before, .frame::after {
  content: ""; position: absolute; width: 14px; height: 14px; pointer-events: none; z-index: 3;
  border: 1px solid var(--red);
}
.frame::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; }
.frame::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0; }

/* ---------- Hairline divider with spark ------------------------------- */
.rule { height: 1px; background: var(--line); border: 0; position: relative; }
.rule::after {
  content: ""; position: absolute; left: 0; top: -1px; width: 64px; height: 3px;
  background: linear-gradient(90deg, var(--red), transparent);
}

/* ---------- Reveal (JS toggles .is-visible; reduced-motion = visible) - */
/* Timings are deliberately tight: reveals fire the moment an element enters
   the viewport (see initReveals), so scrolling never waits on content. */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity .4s var(--ease-out), transform .4s var(--ease-out); }
.reveal.is-visible { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: .04s; }
.reveal[data-delay="2"] { transition-delay: .08s; }
.reveal[data-delay="3"] { transition-delay: .12s; }
.reveal[data-delay="4"] { transition-delay: .16s; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* ===================================================================== */
/*  HEADER                                                               */
/* ===================================================================== */
.site-header {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  transition: background .4s var(--ease), backdrop-filter .4s var(--ease), border-color .4s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-scrolled {
  /* blur radius trimmed 14->10px: the header blurs the live hero video behind
     it while scrolling the top of the page, and 14px was measurably heavier */
  background: rgba(0, 0, 0, .72); backdrop-filter: blur(10px);
  border-bottom-color: var(--line);
}
.nav { display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; height: 78px; }
.site-header.is-scrolled .nav { height: 66px; }
.nav { transition: height .4s var(--ease); }

/* The logo is the white cut of the official mark: a solid badge with the
   lettering knocked out, so the page's black shows through as the type. */
.brand { display: inline-flex; align-items: center; }
.brand__logo { display: block; height: 46px; width: auto; flex: none;
  transition: height .4s var(--ease), filter .45s var(--ease); }
.site-header.is-scrolled .brand__logo { height: 38px; }
.brand:hover .brand__logo { filter: drop-shadow(0 0 16px rgba(231, 50, 50, .6)); }
@media (prefers-reduced-motion: reduce) { .brand__logo { transition: none; } }

.nav__links { display: flex; align-items: center; gap: 1.6rem; } /* tighter gap offsets the larger type */
.nav__links a { font-family: var(--f-mono); font-size: .84rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); position: relative; padding-block: .4rem; transition: color .3s var(--ease); }
.nav__links a::after { content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 0;
  background: var(--red); transition: width .4s var(--ease); }
.nav__links a:hover, .nav__links a[aria-current="page"] { color: var(--text); }
.nav__links a:hover::after, .nav__links a[aria-current="page"]::after { width: 100%; }

.nav__cta { display: inline-flex; align-items: center; gap: .55rem; }
.nav__phone { font-family: var(--f-mono); font-weight: 600; font-size: .88rem; letter-spacing: .05em; }

.nav__toggle { display: none; width: 44px; height: 44px; flex-direction: column;
  justify-content: center; gap: 5px; align-items: center; }
.nav__toggle span { width: 22px; height: 2px; background: var(--text); transition: transform .35s var(--ease), opacity .3s; }

@media (max-width: 900px) {
  .nav__toggle { display: flex; margin-left: .1rem; }
  /* No backdrop-filter on mobile: a filtered ancestor becomes the containing
     block for the fixed nav panel, clipping it to the header's height (and,
     because the filter is animated, flashing that clipped state on open). A
     solid header background gives the same look with none of that. */
  .site-header.is-scrolled {
    -webkit-backdrop-filter: none; backdrop-filter: none;
    background: rgba(0, 0, 0, .94);
  }
  .nav__links {
    position: fixed; inset: 0 0 0 auto; z-index: 40;
    width: min(80vw, 340px); flex-direction: column; justify-content: center;
    gap: 1.4rem; background: var(--bg-2); border-left: 1px solid var(--line);
    transform: translateX(100%); transition: transform .5s var(--ease); padding: 2rem;
  }
  .brand__logo, .site-header.is-scrolled .brand__logo { height: 40px; }
  .nav__links a { font-size: 1rem; }
  body.nav-open .nav__links { transform: none; }
  /* Keep the call button and the (X) close toggle above the panel so it stays
     tappable to dismiss the menu. */
  .nav__cta { position: relative; z-index: 50; }
  body.nav-open .nav__toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  body.nav-open .nav__toggle span:nth-child(2) { opacity: 0; }
  body.nav-open .nav__toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .nav__cta .nav__phone { display: none; }
}
@media (max-width: 420px) {
  .brand__logo, .site-header.is-scrolled .brand__logo { height: 34px; }
}

/* ===================================================================== */
/*  FOOTER                                                               */
/* ===================================================================== */
.site-footer { background: var(--bg-2); border-top: 1px solid var(--line); padding-block: clamp(3rem,2rem + 4vw,5rem) 2rem; }
.footer__grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 2.5rem; }
.footer__brand .brand { margin-bottom: 1rem; }
.footer__brand .brand__logo { height: 82px; }
.footer__col h4 { font-family: var(--f-mono); font-size: .8rem; letter-spacing: .2em; text-transform: uppercase;
  color: var(--gray); margin-bottom: 1.1rem; font-weight: 500; }
/* span included: the "Get a repair" column lists its hours as bare spans, which
   ran together on one line while only the links stacked. */
.footer__col a, .footer__col li, .footer__col > span { color: var(--muted); display: block; padding-block: .3rem; transition: color .3s var(--ease); }
.footer__col a:hover { color: var(--red-hi); }
.footer__phone { font-family: var(--f-display); font-size: clamp(1.8rem,1.2rem + 2vw,2.6rem); color: var(--text);
  letter-spacing: .01em; display: inline-block; margin-top: .3rem; }
.footer__phone:hover { color: var(--red); }
.footer__bottom { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem;
  margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--line);
  font-family: var(--f-mono); font-size: .8rem; letter-spacing: .08em; color: var(--gray); text-transform: uppercase; }
.footer__bottom a { transition: color .3s var(--ease); }
/* The legal links were two hardcoded anchors with a literal "·" between
   them. They come from a menu now, so the separator has to be generated, and
   it has to sit BETWEEN links rather than before each one, or the row opens
   with a stray dot. Driven off the adjacent sibling, so it scales to a third
   link without another edit. */
.footer__legal a + a::before { content: "·"; margin: 0 .5rem; color: var(--gray); }
.footer__bottom a:hover { color: var(--red-hi); }
@media (max-width: 760px) { .footer__grid { grid-template-columns: 1fr 1fr; } .footer__brand { grid-column: 1 / -1; } }

/* ===================================================================== */
/*  MARQUEE (manufacturer logos / kinetic strip)                        */
/* ===================================================================== */
.marquee { overflow: hidden; position: relative; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.marquee__track { display: flex; gap: clamp(2rem, 4vw, 4rem); width: max-content; will-change: transform;
  animation: marquee 55s linear infinite; } /* 55s: the logo strip is wider than the old text strip */
.marquee:hover .marquee__track { animation-play-state: paused; }
/* A wall of text brands runs wider per item than a wall of logos (the warranty
   list is ~12,000px against the partner strip's ~7,200), so at the shared 55s
   it swept past at 220px/s where the logos travel 132px/s. Logos are
   recognised at a glance; brand names have to be read, so the faster one was
   the one that needed to be slower. 92s puts it at 131px/s, matching the
   strip above it. Selected by content rather than by a class because both
   walls are the same block and carry the same markup hooks; browsers without
   :has() simply keep the old 55s. Under prefers-reduced-motion the shorthand
   below still sets animation-name:none, so nothing animates either way. */
.logos:has(.marquee__item:not(.marquee__item--logo)) .marquee__track {
  animation-duration: 92s;
}
.marquee__item { font-family: var(--f-display); font-weight: 700; text-transform: uppercase;
  font-size: clamp(1.3rem, 1rem + 1.6vw, 2.2rem); color: var(--gray); letter-spacing: .02em; white-space: nowrap;
  display: flex; align-items: center; gap: clamp(2rem,4vw,4rem); transition: color .3s var(--ease); }
.marquee__item::after { content: "◆"; color: var(--red); font-size: .5em; }
.marquee__item:hover { color: var(--text); }
/* Partner logos: white-knockout PNGs, dimmed at rest, full white on hover.
   Badge-shaped marks (Toyota, Harley, Suzuki, Westinghouse, Firman) get more
   height than the wordmarks or they read undersized next to them. */
.marquee__item--logo::after { font-size: .62rem; }
.marquee__item--logo img { height: 44px; width: auto; opacity: .68;
  transition: opacity .35s var(--ease); }
.marquee__item--logo img.logo--badge { height: 64px; }
.marquee__item--logo:hover img { opacity: 1; }
@media (max-width: 620px) {
  .marquee__item--logo img { height: 34px; }
  .marquee__item--logo img.logo--badge { height: 50px; }
}
@keyframes marquee { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) { .marquee__track { animation: none; flex-wrap: wrap;
  justify-content: center; row-gap: 1.6rem; padding-inline: var(--gutter); } }

/* ---------- Helpers --------------------------------------------------- */
.stack > * + * { margin-top: 1.2rem; }
.center { text-align: center; }
.grid { display: grid; gap: var(--gutter); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip-link { position: absolute; left: 1rem; top: -60px; z-index: 100; background: var(--red); color: #fff;
  padding: .6rem 1rem; font-family: var(--f-mono); font-size: .8rem; border-radius: 2px; transition: top .3s; }
.skip-link:focus { top: 1rem; }

/* ===================================================================== */
/*  HERO                                                                 */
/* ===================================================================== */
.hero { position: relative; min-height: 100svh; display: flex; align-items: flex-end;
  padding-bottom: clamp(3rem, 2rem + 5vw, 6rem); overflow: hidden; }
.hero__media { position: absolute; inset: 0; z-index: 0; }
/* The hero is the one place colour is allowed: it's the trail you ride to, and
   killing the lake and forest would defeat the shot. It's still pulled well down
   in saturation and brightness so it reads as one family with the monochrome
   shop imagery below, and so white type survives on top of a daylight sky.
   Everything else on the site stays near-greyscale - red remains the accent. */
.hero__media video, .hero__media img { width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(.45) contrast(1.08) brightness(.78); }
.hero__scrim { position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(180deg, rgba(0,0,0,.42) 0%, rgba(0,0,0,.3) 30%, rgba(0,0,0,.76) 78%, var(--bg) 100%),
    /* darkens the left column the headline sits in, leaving the machine side brighter */
    linear-gradient(90deg, rgba(0,0,0,.58) 0%, rgba(0,0,0,.24) 45%, transparent 72%),
    radial-gradient(100% 70% at 8% 100%, rgba(231,50,50,.16), transparent 62%),
    radial-gradient(120% 80% at 80% 20%, transparent 40%, rgba(0,0,0,.38) 100%); }
/* width/height 100% is required: canvas is a replaced element, so inset alone
   leaves it at its intrinsic 300x150 - it sat tiny in the corner for weeks. */
#spark-canvas { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; }
.hero .container { position: relative; z-index: 3; width: 100%; }
.hero__eyebrow { margin-bottom: clamp(1rem, 2vw, 1.6rem); }
/* Local separation from the footage. Sun glint on the lake sits at almost
   exactly racing red's luminance, which drops the cycling word to ~1.8:1
   against it; the scrim alone can't fix that without flattening the shot. */
.hero__title { font-size: var(--step-5); line-height: .86; margin-bottom: 1.4rem;
  text-shadow: 0 2px 30px rgba(0,0,0,.85), 0 0 10px rgba(0,0,0,.55); }
.hero__title-lead { display: block; }
.hero__cycle-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: .28em; }
/* Long single words ("Motorcycles", "Generators") are wider than the column at
   320-375px and there is no break opportunity inside them, so without this they
   were cropped by the page's overflow-x: hidden rather than wrapping. */
.hero__cycle { overflow-wrap: break-word; }
.hero__cycle { color: var(--red); position: relative; display: inline-block; min-width: 3ch;
  transition: transform .4s var(--ease), opacity .4s var(--ease); text-shadow: 0 0 42px rgba(231,50,50,.4); }
/* Directional swaps: the incoming word slides in from the left, right or
   bottom in turn and pushes the old one out the far side. No top entry: a
   word dropping in from above overlaps the "We Repair" lead line. Horizontal
   travel is em-based so short and long words cover the same optical
   distance; skew leans with the offset, matching the original swap (which
   remains the third step of the rotation). */
.hero__cycle.is-out-top    { transform: translateY(-38%) skewX(-6deg); opacity: 0; }
.hero__cycle.is-out-left   { transform: translateX(-.45em) skewX(-6deg); opacity: 0; }
.hero__cycle.is-out-right  { transform: translateX(.45em) skewX(6deg); opacity: 0; }
.hero__cycle.is-in-left    { animation: cycleInLeft .5s var(--ease); }
.hero__cycle.is-in-right   { animation: cycleInRight .5s var(--ease); }
.hero__cycle.is-in-bottom  { animation: cycleInBottom .5s var(--ease); }
@keyframes cycleInLeft   { from { transform: translateX(-.45em) skewX(-6deg); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes cycleInRight  { from { transform: translateX(.45em) skewX(6deg); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes cycleInBottom { from { transform: translateY(42%) skewX(6deg); opacity: 0; } to { transform: none; opacity: 1; } }
.hero__sub { max-width: 44ch; margin-bottom: 2rem; }
.hero__actions { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }
.hero__ticks { display: flex; gap: 1.6rem; flex-wrap: wrap; margin-top: 2.4rem; padding-top: 1.4rem;
  border-top: 1px solid var(--line); }
.hero__tick { font-family: var(--f-mono); font-size: var(--step--1); color: var(--muted); letter-spacing: .04em; }
.hero__tick b { color: var(--text); font-weight: 700; display: block; font-size: 1.15rem; }
.scroll-cue { position: absolute; right: var(--gutter); bottom: clamp(2rem,4vw,3rem); z-index: 3;
  font-family: var(--f-mono); font-size: .74rem; letter-spacing: .25em; text-transform: uppercase; color: var(--gray);
  writing-mode: vertical-rl; display: flex; align-items: center; gap: 1rem; }
.scroll-cue::after { content: ""; width: 1px; height: 54px; background: linear-gradient(var(--red), transparent); }
@media (max-width: 620px) { .scroll-cue { display: none; } }

/* Hero video control (WCAG 2.2.2: automatic motion needs a stop). Sits low-left
   of the hero, quiet until hovered or focused. JS unhides it, so it never
   appears when there is no script to drive it. */
.hero__videotoggle {
  position: absolute; left: var(--gutter); bottom: clamp(2rem, 4vw, 3rem); z-index: 4;
  width: 40px; height: 40px; display: grid; place-items: center;
  color: var(--text); background: rgba(0, 0, 0, .45); border: 1px solid var(--line-2);
  border-radius: 50%; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: background .3s var(--ease), border-color .3s var(--ease);
}
.hero__videotoggle:hover { background: rgba(0, 0, 0, .7); border-color: var(--text); }
.hero__videotoggle svg { width: 16px; height: 16px; }
.hero__videotoggle .hero__videotoggle-play { display: none; }
.hero__videotoggle.is-paused .hero__videotoggle-pause { display: none; }
.hero__videotoggle.is-paused .hero__videotoggle-play { display: block; }
@media (max-width: 620px) { .hero__videotoggle { width: 44px; height: 44px; } }
/* Keep the three trust ticks on one row on phones (flex-wrap dropped OEM to a
   second line); a 3-col grid with tighter type fits all three. */
@media (max-width: 600px) {
  .hero__ticks { display: grid; grid-template-columns: repeat(3, 1fr); gap: .8rem; }
  .hero__tick { font-size: .74rem; line-height: 1.3; }
  .hero__tick b { font-size: 1.04rem; margin-bottom: .1rem; }
}

/* ===================================================================== */
/*  STAT BAND                                                            */
/* ===================================================================== */
.statband { border-block: 1px solid var(--line); background: var(--bg-2); }
.statband__grid { display: grid; grid-template-columns: repeat(4, 1fr); }
.stat { padding: clamp(2rem,4vw,3.4rem) clamp(1rem,2vw,2rem); border-left: 1px solid var(--line); }
.stat:first-child { border-left: 0; }
.stat__num { font-family: var(--f-display); font-weight: 800; font-size: clamp(2.6rem,1.6rem + 3.5vw,4.6rem);
  line-height: 1; color: var(--text); }
.stat__num .u { color: var(--red); }
.stat__label { font-family: var(--f-mono); font-size: var(--step--1); letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted); margin-top: .7rem; }
@media (max-width: 760px) { .statband__grid { grid-template-columns: 1fr 1fr; }
  .stat:nth-child(-n+2) { border-bottom: 1px solid var(--line); } .stat:nth-child(odd) { border-left: 0; } }

/* ===================================================================== */
/*  SECTION HEADER                                                       */
/* ===================================================================== */
.sec-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 2rem; flex-wrap: wrap;
  margin-bottom: clamp(2.4rem, 4vw, 4rem); }
.sec-head__title { max-width: 18ch; }
.sec-head p { max-width: 40ch; }

/* ===================================================================== */
/*  SERVICES GRID (home)                                                 */
/* ===================================================================== */
/* Six-column base so a row can hold either 3 cards (span 2) or 2 (span 3).
   With 5 cards a plain 3-col grid leaves an empty cell that renders as a pale
   block, so when the last row is short its cards stretch to fill it. The
   selector matches the row-starting card that is second-from-last - true at 5
   cards, false at 6 - so adding a sixth card returns it to a clean 3+3. */
.services__grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1px; background: var(--line);
  border: 1px solid var(--line); }
.svc { grid-column: span 2; }
.svc:nth-child(3n+1):nth-last-child(2),
.svc:nth-child(3n+1):nth-last-child(2) ~ .svc { grid-column: span 3; }
.svc { position: relative; background: var(--surface); overflow: hidden; min-height: 340px; display: flex;
  flex-direction: column; justify-content: flex-end; isolation: isolate; }
.svc__img { position: absolute; inset: 0; z-index: -2; }
.svc__img img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) brightness(.9) contrast(1.06);
  transition: transform .9s var(--ease), filter .6s var(--ease); }
.svc::after { content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, transparent 36%, rgba(0,0,0,.45) 64%, rgba(0,0,0,.88) 100%);
  transition: background .5s var(--ease); }
.svc:hover .svc__img img { transform: scale(1.07); filter: grayscale(.8) brightness(1) contrast(1.12); }
/* Soft shadow keeps the index/name readable now that the tile images are
   brighter (some, like the RZR photo, have near-white sky behind the text). */
.svc__body { padding: clamp(1.4rem,2vw,2rem); position: relative;
  text-shadow: 0 1px 10px rgba(0,0,0,.65); }
.svc__index { font-family: var(--f-mono); font-size: .78rem; letter-spacing: .18em; color: var(--red-hi);
  display: block; margin-bottom: .6rem; }
.svc__name { font-family: var(--f-display); font-weight: 800; text-transform: uppercase; font-size: clamp(1.5rem,1rem + 1.6vw,2rem);
  line-height: 1; }
.svc__desc { color: var(--muted); font-size: var(--step--1); margin-top: .6rem; max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height .5s var(--ease), opacity .4s var(--ease), margin .4s var(--ease); }
.svc:hover .svc__desc, .svc:focus-within .svc__desc { max-height: 6rem; opacity: 1; }
.svc__link { position: absolute; inset: 0; z-index: 5; }
/* The overlay link fills the card exactly and .svc clips with overflow:hidden,
   so the default focus ring (2px at +3px offset) painted outside the card and
   was cropped away - keyboard users saw nothing. Pull the ring inside. */
.svc__link:focus-visible { outline-offset: -5px; }
.svc__arrow { position: absolute; top: clamp(1.4rem,2vw,2rem); right: clamp(1.4rem,2vw,2rem); color: var(--text);
  opacity: .4; transition: opacity .4s var(--ease), transform .4s var(--ease); }
.svc:hover .svc__arrow { opacity: 1; transform: translate(3px,-3px); }
@media (max-width: 900px) {
  .services__grid { grid-template-columns: repeat(2, 1fr); }
  .svc, .svc:nth-child(3n+1):nth-last-child(2), .svc:nth-child(3n+1):nth-last-child(2) ~ .svc { grid-column: span 1; }
  /* A lone final card fills the row. Scoped through the parent so it out-weighs
     the reset above - the sibling-combinator selector there is (0,4,0), so a
     bare .svc:last-child:nth-child(odd) at (0,3,0) would silently lose. */
  .services__grid > .svc:last-child:nth-child(odd) { grid-column: span 2; }
}
@media (max-width: 560px) {
  .services__grid { grid-template-columns: 1fr; }
  /* Same weight as the rule above, or the span-2 leaks into the 1-col grid and
     grid auto-creates a phantom second column. */
  .svc, .services__grid > .svc:last-child:nth-child(odd) { grid-column: span 1; }
  .svc { min-height: 260px; }
  .svc__desc { max-height: 6rem; opacity: 1; }
}

/* ===================================================================== */
/*  FEATURE / WHY-US                                                     */
/* ===================================================================== */
.feature__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem,3vw,3rem); }
.feat { padding-top: 1.6rem; border-top: 1px solid var(--line-2); position: relative; }
.feat::before { content: ""; position: absolute; top: -1px; left: 0; width: 48px; height: 2px; background: var(--red); }
.feat__k { font-family: var(--f-mono); font-size: .78rem; letter-spacing: .18em; color: var(--gray); margin-bottom: 1rem; }
.feat h3 { font-size: clamp(1.4rem,1rem + 1.4vw,1.9rem); margin-bottom: .7rem; }
@media (max-width: 820px) { .feature__grid { grid-template-columns: 1fr; } }

/* ===================================================================== */
/*  GALLERY TEASER (home)                                                */
/* ===================================================================== */
.teaser__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--line); border: 1px solid var(--line); }
.teaser__item { position: relative; overflow: hidden; aspect-ratio: 4/5; background: var(--surface); }
.teaser__item.wide { grid-column: span 2; aspect-ratio: 8/5; }
.teaser__item img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) brightness(.88) contrast(1.04);
  transition: transform .9s var(--ease), filter .5s var(--ease); }
.teaser__item:hover img { transform: scale(1.06); filter: grayscale(.8) brightness(1) contrast(1.04); }
@media (max-width: 720px) { .teaser__grid { grid-template-columns: 1fr 1fr; } .teaser__item.wide { grid-column: span 2; } }

/* ===================================================================== */
/*  LOGO MARQUEE section                                                 */
/* ===================================================================== */
.logos { padding-block: clamp(2.4rem,4vw,3.6rem); border-block: 1px solid var(--line); background: var(--bg-2); }
.logos__label { text-align: center; margin-bottom: 2rem; }

/* ===================================================================== */
/*  TESTIMONIALS                                                         */
/* ===================================================================== */
.testi__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line);
  border: 1px solid var(--line); }
.testi { background: var(--surface); padding: clamp(1.8rem,3vw,2.6rem); display: flex; flex-direction: column; gap: 1.4rem; }
.testi__stars { color: var(--red-hi); letter-spacing: .2em; font-size: .9rem; }
.testi__quote { font-family: var(--f-body); font-size: var(--step-1); line-height: 1.4; color: var(--text); font-weight: 500; }
.testi__by { margin-top: auto; font-family: var(--f-mono); font-size: .82rem; letter-spacing: .08em; color: var(--muted);
  text-transform: uppercase; }
.testi__by b { color: var(--text); }
@media (max-width: 860px) { .testi__grid { grid-template-columns: 1fr; } }

/* ===================================================================== */
/*  BIG CTA                                                              */
/* ===================================================================== */
.cta { position: relative; overflow: hidden; text-align: center; padding-block: clamp(4rem,3rem + 6vw,8rem);
  background: radial-gradient(120% 140% at 50% 120%, rgba(231,50,50,.22), transparent 55%), var(--bg-2);
  border-top: 1px solid var(--line); }
.cta h2 { font-size: var(--step-4); margin-bottom: 1.2rem; }
.cta p { margin: 0 auto 2.4rem; color: var(--muted); }
.cta__phone { font-family: var(--f-display); font-weight: 800; font-size: clamp(2.6rem,1.6rem + 5vw,6rem); line-height: 1;
  color: var(--text); display: inline-block; letter-spacing: .01em; transition: color .3s var(--ease); }
.cta__phone:hover { color: var(--red); }

/* ===================================================================== */
/*  PAGE HERO (interior pages)                                           */
/* ===================================================================== */
.page-hero { padding-top: clamp(9rem, 7rem + 6vw, 13rem); padding-bottom: clamp(3rem,2rem + 3vw,4.5rem);
  position: relative; border-bottom: 1px solid var(--line); }
.page-hero h1 { font-size: var(--step-4); margin-block: 1rem .8rem; max-width: 16ch; }
.page-hero__crumb { font-family: var(--f-mono); font-size: .8rem; letter-spacing: .16em; text-transform: uppercase; color: var(--gray); }
.page-hero__crumb .hot { color: var(--red-hi); }
/* --ignite: warmth for a page hero that would otherwise be white-on-black.
   A soft red bleed from the top corner plus a red-hot line in the h1
   (span.hot). Services uses it; added 2026-08-31 at client request. */
.page-hero--ignite { background: radial-gradient(52rem 28rem at 12% -10%, rgba(231, 50, 50, .20), transparent 62%); }
.page-hero--ignite h1 .hot { text-shadow: 0 0 42px rgba(231, 50, 50, .35); }

/* ===================================================================== */
/*  SERVICES PAGE - alternating rows                                     */
/* ===================================================================== */
.svc-row { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem,4vw,5rem); align-items: center;
  padding-block: clamp(3rem,4vw,5rem); border-bottom: 1px solid var(--line); }
.svc-row:nth-child(even) .svc-row__media { order: 2; }
.svc-row__media { position: relative; aspect-ratio: 4/3; overflow: hidden; }
.svc-row__media img { width: 100%; height: 120%; object-fit: cover;
  filter: grayscale(.85) brightness(.96) contrast(1.04); }
.svc-row__num { font-family: var(--f-mono); color: var(--red-hi); font-size: .86rem; letter-spacing: .2em; }
.svc-row h2 { font-size: var(--step-3); margin-block: .8rem 1.2rem; }
.svc-row__list { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem 1.4rem; margin: 1.6rem 0 2rem; }
.svc-row__list li { position: relative; padding-left: 1.4rem; color: var(--muted); font-size: var(--step--1); }
.svc-row__list li::before { content: "→"; position: absolute; left: 0; color: var(--red); }
@media (max-width: 820px) { .svc-row { grid-template-columns: 1fr; }
  .svc-row:nth-child(even) .svc-row__media { order: 0; } .svc-row__list { grid-template-columns: 1fr; } }

/* ===================================================================== */
/*  GALLERY PAGE                                                         */
/* ===================================================================== */
.gallery-grid { columns: 3; column-gap: 1rem; }
.gallery__item { display: block; position: relative; margin-bottom: 1rem; break-inside: avoid; overflow: hidden;
  cursor: zoom-in; background: var(--surface); }
/* Gallery sits monochrome at rest and warms back up under the cursor - the one
   place the shop's own colour is allowed through, one image at a time. */
.gallery__item img { width: 100%; filter: grayscale(1) brightness(.98) contrast(1.02);
  transition: transform .8s var(--ease), filter .5s var(--ease); }
.gallery__item:hover img { transform: scale(1.05); filter: grayscale(.35) brightness(1.04); }
.gallery__item::after { content: "⤢"; position: absolute; right: 1rem; bottom: 1rem; color: var(--text); opacity: 0;
  font-size: 1.2rem; transition: opacity .3s var(--ease); }
.gallery__item:hover::after { opacity: 1; }
@media (max-width: 900px) { .gallery-grid { columns: 2; } }
@media (max-width: 560px) { .gallery-grid { columns: 1; } }

.lightbox { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
  padding: clamp(1rem,4vw,3rem); background: rgba(0,0,0,.92); backdrop-filter: blur(6px); opacity: 0;
  transition: opacity .3s var(--ease); }
/* display:flex above would otherwise override [hidden]'s display:none, leaving
   the invisible overlay covering the page and eating every click. */
.lightbox[hidden] { display: none; }
.lightbox.is-open { opacity: 1; }
.lightbox img { max-width: 100%; max-height: 90vh; width: auto; border: 1px solid var(--line-2); }
.lightbox__close { position: absolute; top: 1.2rem; right: 1.4rem; font-size: 2.4rem; line-height: 1; color: var(--text);
  width: 48px; height: 48px; }
.lightbox__close:hover { color: var(--red); }

/* ===================================================================== */
/*  ABOUT PAGE                                                           */
/* ===================================================================== */
.about-lead { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem,5vw,5rem); align-items: start; }
.about-lead__body p + p { margin-top: 1.2rem; }
/* Links inside migrated prose. The 25 service-area pages carried this
   treatment as an inline style on all 125 of their links, a byte-for-byte copy
   of the .legal a rule further down; that prose is author-editable block
   content now, and "style" is deliberately not on any render callback's
   wp_kses() allow list, since it is the one attribute that turns an editable
   field into arbitrary CSS on a live page. So the treatment lives on the class
   instead, which also gives those links the hover state they never had. Inert
   on the about page, whose lead prose has no links at all. */
.about-lead__body a, .cta p a { color: var(--text); border-bottom: 1px solid var(--line-2); }
.about-lead__body a:hover, .cta p a:hover { color: var(--red-hi); border-bottom-color: var(--red-hi); }
.values__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); }
.value { background: var(--surface); padding: clamp(1.6rem,3vw,2.4rem); }
.value__n { font-family: var(--f-mono); color: var(--red-hi); font-size: .8rem; letter-spacing: .2em; margin-bottom: 1rem; }
.value h3 { font-size: clamp(1.3rem,1rem + 1.2vw,1.7rem); margin-bottom: .6rem; }
/* Brand grid (What We Work On). auto-fill rather than a fixed column count so
   the row reflows on its own as brands are added or removed in the Brands
   screen; a hard count would need a CSS edit every time the list changed,
   which is the opposite of the point. min() keeps the track from overflowing
   a narrow phone, where 14rem alone would exceed the viewport. */
.brands { list-style: none; display: grid; gap: .55rem;
  grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr)); }
.brands__item { background: var(--surface); border: 1px solid var(--line);
  padding: .85rem 1.1rem; font-family: var(--f-display); font-weight: 700;
  text-transform: uppercase; letter-spacing: .02em; color: var(--text);
  font-size: clamp(.95rem, .9rem + .25vw, 1.12rem); line-height: 1.25;
  border-left: 2px solid var(--red); transition: background .3s var(--ease); }
.brands__item:hover { background: var(--surface-2); }

.promo-band { position: relative; overflow: hidden; padding-block: clamp(3rem,4vw,5rem);
  background: linear-gradient(180deg, var(--bg-2), var(--bg)); border-block: 1px solid var(--line); }
@media (max-width: 800px) { .about-lead { grid-template-columns: 1fr; } .values__grid { grid-template-columns: 1fr; } }

/* ===================================================================== */
/*  GOOGLE REVIEWS (home testimonials)                                   */
/* ===================================================================== */
/* Live-rating badge in the section head; links out to the Google profile. */
.gscore { display: inline-flex; align-items: center; gap: 1.2rem; padding: 1rem 1.5rem;
  border: 1px solid var(--line-2); border-radius: 2px; transition: border-color .35s var(--ease), transform .35s var(--ease); }
.gscore:hover { border-color: var(--red); transform: translateY(-2px); }
.gscore__num { font-family: var(--f-display); font-weight: 800; font-size: clamp(2.2rem, 1.6rem + 2vw, 3.2rem); line-height: 1; }
.gscore__stars { color: var(--red-hi); letter-spacing: .18em; font-size: .85rem; display: block; }
.gscore__meta { font-family: var(--f-mono); font-size: .78rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); margin-top: .35rem; }
.gscore__meta b { color: var(--text); }

/* ===================================================================== */
/*  FAQ PAGE                                                             */
/* ===================================================================== */
/* Native <details> accordion - works with JS disabled, like everything else. */
.faq-list { max-width: 880px; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item summary { display: flex; align-items: baseline; gap: 1.2rem; padding: 1.5rem 0; cursor: pointer; list-style: none; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item__k { font-family: var(--f-mono); font-size: .8rem; letter-spacing: .2em; color: var(--red-hi); flex: none; }
.faq-item__q { font-family: var(--f-display); font-weight: 800; text-transform: uppercase; line-height: 1;
  font-size: clamp(1.35rem, 1rem + 1.4vw, 1.9rem); transition: color .3s var(--ease); }
.faq-item summary:hover .faq-item__q { color: var(--red); }
.faq-item summary::after { content: "+"; margin-left: auto; flex: none; font-family: var(--f-display); font-weight: 700;
  font-size: 1.6rem; line-height: 1; color: var(--red); transition: transform .35s var(--ease); }
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item__a { padding: 0 0 1.7rem; max-width: 68ch; color: var(--muted); }
.faq-item__a p + p { margin-top: .8rem; }
.faq-item__a a { color: var(--text); border-bottom: 1px solid var(--line-2); }
.faq-item__a a:hover { color: var(--red-hi); border-bottom-color: var(--red-hi); }

/* ===================================================================== */
/*  LEGAL PAGES (privacy / terms)                                        */
/* ===================================================================== */
.legal { max-width: 780px; }
.legal__updated { font-family: var(--f-mono); font-size: .8rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--gray); margin-bottom: 2.4rem; }
.legal h2 { font-size: clamp(1.4rem, 1rem + 1.4vw, 1.9rem); margin: 2.6rem 0 .9rem; }
.legal p { margin-bottom: 1rem; }
/* The red-arrow list treatment hangs off the element's own class, not off a
   .legal ancestor. That wrapper is emitted by the page template, so it never
   reaches the Pages editor canvas, and the arrows were invisible while editing
   even though they rendered correctly on the live page. A core list block
   carries .wp-block-list on the <ul> itself, which survives into the editor.
   Additive and safe: every core list today sits inside .legal, which sets the
   identical values, so no live page changes. A list added anywhere else now
   gets the site's treatment instead of browser-default bullets on a dark page.
   Deliberately NOT generalised to headings: .legal h2 is smaller than the site
   default BECAUSE it is legal prose, so hanging that off .wp-block-heading
   would wrongly shrink headings on any future page.
   The item spacing is `li + li { margin-top }` rather than the grid `gap` this
   used to use. In the editor each <li> is wrapped as a block element with its
   own width and max-width rules, and as grid items those collapsed to their
   content width and sat centred instead of running down the left edge. Margins
   give the identical result on the live page and survive the editor intact. */
.legal ul, .wp-block-list { margin-bottom: 1.2rem; }
.legal li + li, .wp-block-list li + li { margin-top: .5rem; }
.legal li, .wp-block-list li { position: relative; padding-left: 1.4rem; color: var(--muted); }
.legal li::before,
.wp-block-list li::before { content: "→"; position: absolute; left: 0; color: var(--red); }
.legal a { color: var(--text); border-bottom: 1px solid var(--line-2); }
.legal a:hover { color: var(--red-hi); border-bottom-color: var(--red-hi); }

/* ===================================================================== */
/*  THANK-YOU PAGE                                                       */
/* ===================================================================== */
.thanks-hero { min-height: 52svh; display: flex; align-items: flex-end;
  padding-top: clamp(9rem, 7rem + 6vw, 13rem); padding-bottom: clamp(3rem, 2rem + 3vw, 4.5rem);
  border-bottom: 1px solid var(--line); position: relative; overflow: hidden;
  background: radial-gradient(90% 110% at 15% 110%, rgba(231, 50, 50, .16), transparent 60%); }
.thanks-hero__check { font-family: var(--f-mono); color: var(--red-hi); font-size: .8rem; letter-spacing: .2em; }

/* ===================================================================== */
/*  CONTACT PAGE                                                         */
/* ===================================================================== */
.contact-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(2rem,5vw,5rem); align-items: start; }
/* The embedded form runs well past 1000px tall, so the details column rides
   along with it instead of leaving a column of empty black. */
@media (min-width: 801px) { .contact-info { position: sticky; top: clamp(6.5rem, 9vw, 8.5rem); } }
.contact-info dl { display: grid; gap: 1.6rem; }
.contact-info dt { font-family: var(--f-mono); font-size: .8rem; letter-spacing: .18em; text-transform: uppercase; color: var(--gray); margin-bottom: .3rem; }
.contact-info dd { color: var(--text); font-size: var(--step-1); }
.contact-info dd a:hover { color: var(--red-hi); }
/* HighLevel embed. The form lives in a cross-origin iframe and can't inherit
   the page tokens, so it gets a card of its own with a racing-red rule across
   the top to tie it back to the palette. form_embed.js resizes the iframe to
   its content; the height declared in the markup is the pre-load fallback. */
.gh-form { position: relative; background: var(--surface); border-radius: 3px; overflow: hidden; }
.gh-form::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; z-index: 2;
  background: linear-gradient(90deg, var(--red), var(--red-deep));
}
.gh-form iframe { display: block; width: 100%; border: 0; }
/* Shop map: Google's light map is regraded to sit on the dark page -
   grayscale, then inverted, so it reads like a schematic. Still interactive. */
.map-embed { position: relative; margin-top: 2.4rem; aspect-ratio: 4 / 3;
  background: var(--surface); overflow: hidden; }
.map-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
  filter: grayscale(1) invert(.9) contrast(.9); }
.map-note { font-family: var(--f-mono); font-size: .78rem; letter-spacing: .04em; margin-top: .9rem; }
.map-note a { color: var(--muted); }
.map-note a:hover { color: var(--red-hi); }
.form__note { font-family: var(--f-mono); font-size: .78rem; color: var(--gray); letter-spacing: .04em; margin-top: 1rem; }
.form__note a { color: var(--text); border-bottom: 1px solid var(--line-2); }
.form__note a:hover { color: var(--red-hi); border-bottom-color: var(--red-hi); }
@media (max-width: 800px) { .contact-grid { grid-template-columns: 1fr; } }
