/* =============================================================================
 * styles.css — XAT RACING storefront theme.
 *
 * Brand tokens live here and ONLY here (knox reskin lesson: one config, not
 * 24 files). Chrome-blue + high-vis chartreuse pulled from the mark that
 * scripts/gen-logo.mjs builds; dark pit-lane surfaces; the italic slant of
 * the logo (−14°/skew) echoes through headings and accents.
 * ===========================================================================*/

:root {
  --bg: #0b0d10;
  --panel: #14171b;
  --panel-2: #191d22;
  --line: #262b31;
  --ink: #e8ecef;
  --muted: #8a939e;
  --chrome: #8fd2ea;        /* logo's bottom-skid blue  */
  --chrome-deep: #26479c;   /* logo's sky navy          */
  --teal: #79cbb1;          /* logo's ground band       */
  --accent: #d9f024;        /* wordmark chartreuse      */
  --red: #e5372e;           /* redline                  */
  /* Same red, lifted just enough to clear WCAG AA as TEXT. The redline colour
     is right for rules, borders and glows — none of which have a contrast
     requirement — but as type on a card panel it measures 4.21:1 against the
     required 4.5:1, and it is carrying the word SOLD on 43 listings. #ea4a41
     is the nearest step that passes (4.75:1 on panel, 5.15:1 on the page). */
  --red-text: #ea4a41;
  --font-display: 'Barlow Semi Condensed', 'Arial Narrow', system-ui, sans-serif;
  --font-body: 'Barlow', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;
  --slant: -12deg;
}

* { box-sizing: border-box; }
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
body {
  margin: 0; background: var(--bg); color: var(--ink);
  overflow-x: hidden;   /* decorative absolutes must never widen the page */
  font: 15px/1.55 var(--font-body);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 22px; }

/* ---------- header ---------- */
.topnav {
  position: sticky; top: 0; z-index: 50;
  background: rgba(11, 13, 16, .92); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
.topnav .wrap { display: flex; align-items: center; gap: 26px; height: 64px; }
.brand img { height: 40px; width: auto; }
.topnav nav { display: flex; gap: 20px; margin-left: auto; }
.topnav nav a {
  font: 600 12px/1 var(--font-display); letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); padding: 8px 2px; border-bottom: 2px solid transparent;
  transition: color .18s, border-color .18s;
}
.topnav nav a:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- "More" dropdown ----------
 * The nav can only carry so many tabs before it stops being navigation and
 * starts being a wall. Departments with real volume sit up top; the rest live
 * here until the sales data says otherwise.
 *
 * Two rules govern this menu, and both exist because it was broken on phones
 * twice before:
 *
 * 1. THE MENU IS NOT IN THE NAV. enhance.js portals it to <body> at startup
 *    and positions it from the button's rect. It used to be a descendant of
 *    <nav>, which below 1080px is an `overflow-x: auto` scroll strip — and a
 *    scroll strip clips BOTH axes, because CSS computes a `visible` axis to
 *    `auto` the moment its partner isn't visible. A 562px menu inside a 44px
 *    clipped box is invisible whatever `position` it carries. `position:
 *    fixed` escapes that clip only while no ancestor establishes itself as
 *    the containing block — and .topnav carries `backdrop-filter`, which does
 *    exactly that in browsers that implement it. That made the previous fix
 *    depend on an engine difference we cannot test here. Portaling to <body>
 *    removes the dependency instead of betting on it.
 *
 * 2. HOVER OPENS IT ONLY ON A REAL POINTER. A touch browser applies a sticky
 *    :hover on tap, so the CSS-hover version opened the menu without a click:
 *    iOS then swallows that first tap, and the second tap can't close it
 *    because :hover is still stuck on. Measured, in Chromium, at every phone
 *    width: "second tap closes it: false". Behind (hover: hover) touch has
 *    exactly one path — the click handler — and it toggles honestly. */
.navdrop { display: flex; align-items: center; }
.navdrop__btn {
  font: 600 12px/1 var(--font-display); letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); background: none; border: 0; cursor: pointer;
  padding: 8px 2px; border-bottom: 2px solid transparent;
  transition: color .18s, border-color .18s;
}
.navdrop__btn span {
  font-size: 9px; opacity: .7; margin-left: 3px; display: inline-block;
  transition: transform .18s;
}
.navdrop.open .navdrop__btn { color: var(--accent); border-color: var(--accent); }
.navdrop.open .navdrop__btn span { transform: rotate(180deg); }
@media (hover: hover) and (pointer: fine) {
  .navdrop:hover .navdrop__btn { color: var(--accent); border-color: var(--accent); }
}

/* Portaled to <body>: left/top/width/max-height are set inline by enhance.js.
   z-index clears the sticky header (50), the sticky toolbar (40) and the
   floating cart button (60); the drawer (70) is the only thing above it. */
.navdrop__menu {
  position: fixed; top: 0; left: 0; z-index: 90;
  min-width: 244px; display: grid; padding: 8px 0;
  background: rgba(11, 13, 16, .97); backdrop-filter: blur(10px);
  border: 1px solid var(--line); border-top: 2px solid var(--accent);
  border-radius: 8px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .6), 0 0 30px rgba(38, 71, 156, .18);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(-6px);
  transition: opacity .16s, transform .16s, visibility .16s;
}
.navdrop__menu.open { opacity: 1; visibility: visible; pointer-events: auto; transform: none; }
/* Out of the nav, so nothing is inherited any more — the type that used to
   come from `.topnav nav a` is restated here in full. */
.navdrop__menu a {
  display: block; padding: 9px 16px; border-left: 2px solid transparent;
  font: 600 11.5px/1.35 var(--font-display); letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
  transition: color .18s, border-color .18s, background .18s;
}
.navdrop__menu a:hover,
.navdrop__menu a:focus-visible {
  color: var(--accent); border-left-color: var(--accent);
  background: rgba(217, 240, 36, .06); outline: 0;
}
.navdrop__sep { height: 1px; background: var(--line); margin: 7px 12px; }

/* Tap targets belong to the INPUT, not to the width. The 44px floor used to
   live in the ≤720px block, so a 768px tablet — every pixel of it a touch
   screen — got 30px nav tabs and 30px menu rows. Keyed off (pointer: coarse)
   it follows the finger onto tablets and touch laptops, and leaves a mouse
   the compact row it can actually hit. */
@media (pointer: coarse) {
  .topnav nav a,
  .navdrop__btn { display: flex; align-items: center; min-height: 44px; padding-top: 0; padding-bottom: 0; }
  .navdrop__menu a { display: flex; align-items: center; min-height: 44px; padding: 0 16px; }
}

/* ---------- hero ---------- */
.hero {
  position: relative; overflow: hidden;
  padding: 84px 0 70px;
  background:
    radial-gradient(90% 120% at 70% -10%, rgba(38, 71, 156, .32) 0%, transparent 55%),
    radial-gradient(70% 90% at 15% 110%, rgba(121, 203, 177, .10) 0%, transparent 60%),
    var(--bg);
  border-bottom: 1px solid var(--line);
}
.hero::after {  /* horizon streak, echoes the intro's road line */
  content: ''; position: absolute; left: 0; right: 0; top: 62%; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(143, 210, 234, .35), transparent);
}
.hero h1 {
  margin: 0 0 10px; font-family: var(--font-display); font-weight: 800;
  font-style: italic; font-size: clamp(30px, 5.4vw, 56px); line-height: 1.04;
  text-transform: uppercase; letter-spacing: .01em;
}
.hero h1 em { color: var(--accent); font-style: inherit; }
.hero p.lead { max-width: 560px; color: var(--muted); font-size: 16.5px; margin: 0 0 26px; }
.hero .cta { display: flex; gap: 14px; flex-wrap: wrap; }

.btn {
  display: inline-block; font: 700 13px/1 var(--font-display);
  letter-spacing: .12em; text-transform: uppercase;
  padding: 14px 22px; border-radius: 4px; border: 1px solid transparent;
  transform: skewX(var(--slant)); transition: filter .15s, border-color .15s;
}
.btn > span { display: inline-block; transform: skewX(calc(-1 * var(--slant))); }
.btn--primary { background: var(--accent); color: #14170a; }
.btn--primary:hover { filter: brightness(1.1); }
.btn--ghost { border-color: var(--line); color: var(--ink); }
.btn--ghost:hover { border-color: var(--chrome); color: var(--chrome); }

/* ---------- sections ---------- */
section { padding: 58px 0; }
/* the horizon streak between sections — one motif, everywhere, quietly */
section + section::before {
  content: ''; display: block; height: 1px; max-width: 1180px;
  margin: 0 auto 52px;
  background: linear-gradient(90deg, transparent, rgba(143, 210, 234, .16) 35%,
    rgba(143, 210, 234, .3) 50%, rgba(143, 210, 234, .16) 65%, transparent);
}
section .wrap { position: relative; }
/* ghost livery numbers behind section heads — procedurally fill bottom-up
 * with neon green -> teal -> chrome blue as the section scrolls through
 * (enhance.js drives --fill 0..1; static outline without JS) */
.livery {
  position: absolute; top: -68px; right: 0; z-index: 0;
  /* line-height 1.3, NOT 1: the font's ascent+descent is ~1.22em, so at
   * line-height 1 the glyph ink overflows the box top by ~0.11em — and
   * background-clip:text can only paint inside the box, which left the cap
   * tops permanently unfilled. The taller line box contains all the ink. */
  font: 800 italic clamp(90px, 14vw, 170px)/1.3 var(--font-display);
  letter-spacing: -.02em; pointer-events: none; user-select: none;
  color: transparent;
  --fill: 0;
  background: linear-gradient(0deg,
    rgba(217, 240, 36, .5) 0%,      /* racing neon at the bottom of the tank */
    rgba(121, 203, 177, .38) 45%,
    rgba(143, 210, 234, .28) 75%,
    rgba(38, 71, 156, .22) 100%);   /* deep chrome blue up top */
  -webkit-background-clip: text;
  background-clip: text;
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% calc(var(--fill) * 100%);
  /* small right padding: the italic tops also overhang the advance width */
  padding-right: .12em;
}
/* outline on its OWN layer behind the fill (a stroke on the fill element
 * straddles the glyph edge and reads as an unfilled rim); same box metrics
 * so both texts share an origin */
.livery::before {
  content: attr(data-n);
  position: absolute; inset: 0;
  padding-right: .12em;
  -webkit-text-stroke: 1px rgba(143, 210, 234, .14);
  color: transparent;
}
@media (prefers-reduced-motion: reduce) { .livery { --fill: 1; } }
.sec-head { position: relative; z-index: 1; display: flex; align-items: baseline; gap: 16px; margin-bottom: 26px; }
/* .85, not .65. aria-hidden keeps these decorative labels out of the
   accessibility tree, but it does NOT hide them from eyes — --muted at 65%
   over the page blends to #5e646c, which is 3.26:1 against the background and
   fails WCAG AA's 4.5:1 for text this size. Measured: .85 blends to #777f89 at
   4.80:1. Still clearly secondary, now actually readable. */
.sec-head .jp {
  color: var(--muted); opacity: .85; font-size: 12px; letter-spacing: .3em;
  font-weight: 400;
}
.sec-head h2 {
  margin: 0; font-family: var(--font-display); font-style: italic; font-weight: 800;
  font-size: clamp(21px, 3vw, 30px); text-transform: uppercase; letter-spacing: .03em;
}
.sec-head h2::before { content: '// '; color: var(--accent); }
.sec-head .sub { color: var(--muted); font-size: 13px; }

/* Discreet results-side sort — left-aligned above the grid, quiet until
   touched. Mirrors the toolbar's #f-sort (the two stay in sync). */
.sortbar {
  display: flex; align-items: center; gap: 8px; margin: -8px 0 14px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted);
}
.sortbar label { opacity: .85; }
.sortbar select {
  background: transparent; color: inherit; font: inherit; letter-spacing: .1em;
  border: 1px solid transparent; border-bottom-color: color-mix(in srgb, var(--muted) 45%, transparent);
  border-radius: 0; padding: 3px 2px; cursor: pointer; outline: none;
  transition: color .15s, border-color .15s;
}
.sortbar select:hover, .sortbar select:focus-visible {
  color: var(--accent); border-bottom-color: var(--accent);
}
.sortbar select option { background: var(--bg, #0b0d10); color: var(--ink, #e8ecef); }

/* ---------- category rail — side tabs instead of an endless scroll ----------
 * Desktop: a sticky left column of department tabs; pick one and the grid
 * shows just that department (same state as the toolbar's part-type select).
 * Phone: tabs must NEVER wrap into a wall that pushes
 * the first product off screen — they become ONE swipeable row, scrollbar
 * hidden, pinned under the nav. */
.cat-layout { display: grid; grid-template-columns: 172px minmax(0, 1fr); gap: 24px; align-items: start; }
.cat-rail {
  position: sticky; top: 74px; display: flex; flex-direction: column; gap: 2px;
  max-height: calc(100vh - 96px); overflow-y: auto; scrollbar-width: thin;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
}
.cat-rail button {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  text-align: left; background: none; border: 0; border-left: 2px solid var(--line);
  color: var(--muted); padding: 7px 10px; cursor: pointer; font: inherit;
  letter-spacing: inherit; text-transform: inherit;
  transition: color .15s, border-color .15s, background .15s;
}
.cat-rail button .n { opacity: .55; font-size: 10px; }
.cat-rail button:hover, .cat-rail button:focus-visible { color: var(--ink); outline: none; }
.cat-rail button.on { color: var(--accent); border-left-color: var(--accent); }
@media (max-width: 900px) {
  .cat-layout { display: block; }
  .cat-rail {
    position: sticky; top: 0; z-index: 6; flex-direction: row; gap: 6px;
    max-height: none; overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
    padding: 8px 2px 10px; margin: 0 0 12px;
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: blur(6px);
  }
  .cat-rail::-webkit-scrollbar { display: none; }
  .cat-rail button { flex: 0 0 auto; border: 1px solid var(--line); border-radius: 999px; padding: 8px 13px; }
  .cat-rail button.on { border-color: var(--accent); }
  /* two tight columns beat one huge card per screen —
     id-scoped so it outranks the base .grid rule that appears later on */
  #catalog-grid .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  /* Part names run long ("XAT Racing Billet 1UZ 3UZ 2JZ Engine Mounts SC430,
     2GS 1IS, GS400…"). Unclamped they reached 151px — eight lines — and ate
     the card, pushing price and ADD below the fold. Clamp to three lines, the
     and tighten the type for two columns. */
  #catalog-grid .card h4 {
    font-size: 12.5px; line-height: 1.28;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden;
  }
  #catalog-grid .card .body { padding: 10px 10px 12px; gap: 6px; }
  #catalog-grid .tag { font-size: 8.5px; padding: 3px 5px; }
  /* At 168px per card the price and its button can't share one line, and the
     kit-upgrade link's nowrap ran its price straight off the card edge
     ("COMPLETE REAR KIT $" clipped mid-figure). Let both wrap. */
  #catalog-grid .card .foot { flex-wrap: wrap; gap: 6px; justify-content: flex-start; }
  #catalog-grid .card .price { font-size: 14px; }
  #catalog-grid .kitlink {
    white-space: normal; font-size: 9.5px; line-height: 1.3;
    padding: 6px 8px; gap: 4px;
  }
  #catalog-grid .kitlink b { font-size: 10.5px; }
  #catalog-grid .kitlink i { margin-left: 0; }
}

/* ---------- back to top (phones-first) ----------
 * The catalog is long; bottom-LEFT mirrors the cart FAB on the right so the
 * two never collide. Fades in only once you're deep enough to want it. */
#totop {
  position: fixed; left: 12px; bottom: calc(14px + env(safe-area-inset-bottom, 0px)); z-index: 70;
  display: flex; align-items: center; gap: 6px; height: 42px; padding: 0 15px; border-radius: 999px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: .14em;
  color: var(--accent); background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line); box-shadow: 0 10px 30px rgba(0, 0, 0, .55);
  cursor: pointer; opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
#totop.show { opacity: 1; transform: none; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { #totop { transition: none; } }

/* ---------- axis chips (engine / chassis) ---------- */
.chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.chip {
  position: relative; background: var(--panel); border: 1px solid var(--line);
  border-radius: 6px; padding: 15px 16px 13px; cursor: pointer;
  transition: border-color .18s, transform .18s, box-shadow .18s;
}
.chip:hover, .chip.on {
  border-color: var(--chrome);
  transform: translateY(-2px);
  box-shadow: 0 6px 22px rgba(38, 71, 156, .25);
}
.chip.on { border-color: var(--accent); }
.chip b {
  display: block; font-family: var(--font-display); font-style: italic;
  font-weight: 800; font-size: 19px; letter-spacing: .02em;
}
.chip small { color: var(--muted); font-size: 11.5px; display: block; margin-top: 2px; }
.chip .count {
  position: absolute; top: 10px; right: 12px;
  font: 700 11px/1 var(--font-display); color: var(--accent);
}

/* ---------- store tiles (the live store's homepage grid) ---------- */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 16px;
}
.tile { display: grid; gap: 8px; justify-items: center; text-align: center; }
.tile__thumb {
  width: 100%; aspect-ratio: 1; border-radius: 8px; overflow: hidden;
  display: grid; place-items: center; background: var(--panel-2);
  border: 2px solid transparent;
  /* the live store's blue gradient tile frames, in our chrome */
  background-image:
    linear-gradient(var(--panel-2), var(--panel-2)),
    linear-gradient(160deg, var(--chrome) 0%, var(--chrome-deep) 60%, var(--teal) 100%);
  background-origin: border-box; background-clip: padding-box, border-box;
  transition: transform .18s, box-shadow .18s;
}
.tile__thumb img { width: 100%; height: 100%; object-fit: cover; }
.tile__thumb .ph {
  font: 800 italic 22px var(--font-display);
  background: linear-gradient(180deg, #26479c, #8fd2ea 46%, #fff 52%, #79cbb1 60%, #3f9d82);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.tile:hover .tile__thumb { transform: translateY(-3px); box-shadow: 0 8px 24px rgba(38, 71, 156, .35); }
.tile__label { font: 600 12px/1.35 var(--font-body); color: var(--muted); }
.tile:hover .tile__label { color: var(--chrome); }

/* ---------- pit wall (gauge cluster) ---------- */
.pitwall { padding: 34px 0 10px; }
.gauges { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 18px; }
.gauge {
  display: grid; justify-items: center; gap: 2px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 18px 12px 14px;
}
.gauge svg { width: min(46vw, 130px); display: block; }
.gauge__needle {
  transform-origin: 60px 60px;
  transform: rotate(-210deg);
  transition: transform 1s cubic-bezier(.34, 1.3, .5, 1);
}
.gauges.go .gauge__needle { transform: rotate(var(--needle)); }
@media (prefers-reduced-motion: reduce) {
  .gauge__needle { transform: rotate(var(--needle)); transition: none; }
}
.gauge__num { font: 700 26px var(--font-mono); color: var(--accent); margin-top: -30px; }
.gauge small {
  font: 600 10px var(--font-display); letter-spacing: .2em; color: var(--muted);
}

/* ---------- RPM scroll bar ---------- */
.rpm-progress {
  /* anchored to the STICKY nav's bottom edge (enhance.js mounts it inside
     .topnav), not fixed at a hard-coded 64px — the header's height now
     includes the toggle strip, and one anchor can't drift from the other */
  position: absolute; top: 100%; left: 0; right: 0; height: 3px; z-index: 49;
  background: rgba(255, 255, 255, .04); pointer-events: none;
}
.rpm-progress i {
  display: block; height: 100%;
  background: linear-gradient(90deg, #2ea86b 0%, #9fd23a 45%, var(--accent) 70%, #f0a824 86%, var(--red) 97%);
  transform: scaleX(0); transform-origin: left center;
}

/* ---------- finder deck (top-of-page organization solver) ---------- */
.finder { padding: 26px 0 6px; }
.finder + section::before { display: none; }   /* no streak right under the deck */

/* ---------- YMM / VIN picker ---------- */
.ymm {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); padding: 11px 14px; margin-bottom: 10px;
}
.ymm select, .ymm input {
  background: var(--bg); color: var(--ink); border: 1px solid var(--line);
  border-radius: 4px; padding: 8px 10px; font: 500 13px var(--font-body);
}
.ymm input { font-family: var(--font-mono); text-transform: uppercase; width: 200px; }
.ymm__or { color: var(--muted); font-size: 12px; }
.tag--core { color: #7dd3fc; border-color: rgba(125, 211, 252, .4); font-weight: 700; }
.tag--sold { color: var(--red); border-color: rgba(229, 55, 46, .55); font-weight: 700; }
.card .price.sold { color: var(--red-text); }
.card .add--inquire { color: var(--chrome); }
.card .add--inquire:hover { background: var(--chrome); color: #0b0d10; border-color: var(--chrome); }
.cart-line__meta .core { color: #7dd3fc; }
.gallery-cta { margin-top: 22px; text-align: center; }
.gallery-card .thumb .ph { font-size: 34px; }

/* ---------- my garage ---------- */
.garage {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  border: 1px dashed rgba(217, 240, 36, .35); border-radius: 8px;
  padding: 11px 14px; margin-bottom: 14px;
}
.garage__label {
  font: 800 italic 13px var(--font-display); letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent);
}
.garage select {
  background: var(--bg); color: var(--ink); border: 1px solid var(--line);
  border-radius: 4px; padding: 8px 10px; font: 500 13px var(--font-body);
}
.garage__only {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: 4px; padding: 8px 12px; cursor: pointer;
  font: 600 11px var(--font-display); letter-spacing: .12em; text-transform: uppercase;
}
.garage__only[aria-pressed="true"] { color: #14170a; background: var(--accent); border-color: var(--accent); }
.garage__clear {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: 4px; padding: 8px 11px; cursor: pointer;
  font: 600 11px var(--font-display); letter-spacing: .1em; text-transform: uppercase;
}
.garage__clear:hover { color: var(--red); border-color: var(--red); }
.garage__clear[hidden] { display: none; }
.garage__hint { color: var(--muted); font-size: 12px; }
.fits {
  font: 700 9.5px var(--font-mono); letter-spacing: .06em;
  color: #14170a; background: var(--accent); border-radius: 3px; padding: 4px 6px;
}

/* ---------- catalog toolbar ---------- */
.toolbar {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 14px; margin-bottom: 26px;
  position: sticky; top: 72px; z-index: 40;
}
.toolbar input[type="search"], .toolbar select {
  background: var(--bg); color: var(--ink); border: 1px solid var(--line);
  border-radius: 4px; padding: 9px 11px; font: 500 13px var(--font-body);
}
.toolbar input[type="search"] { flex: 1 1 190px; min-width: 150px; }
.toolbar select { flex: 0 0 auto; }
.toolbar .count { margin-left: auto; color: var(--muted); font-size: 12.5px; white-space: nowrap; }
/* The count string gets long ("6,559 of 6,632 parts (top 1,891 baked of …)").
   nowrap on a 390px phone pushed the whole DOCUMENT 97px wide — the page
   scrolled sideways, which reads as broken before anyone sees a product.
   Below the toolbar breakpoint it takes its own line and wraps. */
@media (max-width: 720px) {
  .toolbar .count { margin-left: 0; flex: 1 0 100%; white-space: normal; line-height: 1.4; }
}
.toolbar button.clear {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: 4px; padding: 8px 12px; cursor: pointer; font: 600 12px var(--font-display);
  letter-spacing: .1em; text-transform: uppercase;
}
.toolbar button.clear:hover { color: var(--red); border-color: var(--red); }

/* ---------- catalog groups + cards ---------- */
.group-head {
  margin: 34px 0 14px; display: flex; align-items: baseline; gap: 12px;
}
.group-head h3 {
  margin: 0; font-family: var(--font-display); font-style: italic; font-weight: 800;
  font-size: 17px; letter-spacing: .08em; text-transform: uppercase; color: var(--chrome);
}
.group-head .rule { flex: 1; height: 1px; background: var(--line); }
.subfilter { display: inline-flex; gap: 6px; }
.subfilter button {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: 3px; padding: 4px 10px; cursor: pointer;
  font: 600 10.5px var(--font-display); letter-spacing: .12em; text-transform: uppercase;
}
.subfilter button:hover { color: var(--chrome); border-color: var(--chrome); }
.subfilter button.on { color: #14170a; background: var(--accent); border-color: var(--accent); }
.group-head .n { color: var(--muted); font-size: 12px; }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; }
.card {
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  overflow: hidden; transition: border-color .18s, transform .18s, box-shadow .18s;
  /* The full grid is ~1,900 cards ≈ 27k DOM nodes; laying them ALL out is
     what made filter transitions take seconds. content-visibility lets the
     browser skip layout+paint for offscreen cards (viewport-only work), and
     the intrinsic-size placeholder keeps the scrollbar honest. Browsers
     without support simply ignore both lines — nothing breaks. */
  content-visibility: auto;
  contain-intrinsic-size: auto 360px;
}
.card:hover {
  border-color: var(--chrome); transform: translateY(-3px);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
}
.card .thumb {
  aspect-ratio: 4 / 3; background: var(--panel-2);
  display: grid; place-items: center; overflow: hidden;
}
.card .thumb img { width: 100%; height: 100%; object-fit: cover; }
.card .thumb .ph {   /* attribute-driven placeholder (knox pattern) */
  font: 800 italic 26px var(--font-display); letter-spacing: .04em;
  background: linear-gradient(180deg, #26479c 0%, #8fd2ea 46%, #fff 52%, #79cbb1 60%, #3f9d82 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  transform: skewX(var(--slant));
}
.card .body { padding: 13px 14px 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.card h4 { margin: 0; font: 700 14.5px/1.3 var(--font-body); }
.card .meta { display: flex; flex-wrap: wrap; gap: 5px; }
.tag {
  font: 600 9.5px/1 var(--font-mono); letter-spacing: .04em;
  border: 1px solid var(--line); color: var(--muted);
  border-radius: 3px; padding: 4px 6px; text-transform: uppercase;
}
.tag--engine { color: var(--chrome); border-color: rgba(143, 210, 234, .35); }
/* staged in the back office, visible only in the operator's own browser */
.tag--staged { color: var(--accent); border-color: rgba(217, 240, 36, .5); border-style: dashed; }
.tag--chassis { color: var(--teal); border-color: rgba(121, 203, 177, .35); }
.tag--trans { color: #c9a7e8; border-color: rgba(201, 167, 232, .35); }
.card .foot {
  margin-top: auto; display: flex; align-items: center; justify-content: space-between;
}
.card .price { font: 700 15px var(--font-mono); color: var(--accent); }
.card .price.inquire { color: var(--muted); font-weight: 500; font-size: 12px; }
.card .brand { color: var(--muted); font-size: 11.5px; }
.toolbar .count { font-family: var(--font-mono); font-size: 11.5px; }

/* ---------- slat-reveal thumbs (the intro's louver, as a scroll treatment) --
 * Two interleaved striped covers fly out in opposite directions when the card
 * first scrolls into view; on hover a chrome sheen sweeps the photo. */
.card .thumb { position: relative; }
/* covers exist ONLY when enhance.js stamps .slat-reveal on <html> — if the
 * script never runs (or reduced motion), thumbs are simply visible */
.slat-reveal .card .thumb::before, .slat-reveal .card .thumb::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  transition: transform .55s cubic-bezier(.3, .9, .3, 1), opacity .4s ease .2s;
}
.slat-reveal .card .thumb::before {
  background: repeating-linear-gradient(180deg,
    var(--panel-2) 0 14px, transparent 14px 28px);
}
.slat-reveal .card .thumb::after {
  background: repeating-linear-gradient(180deg,
    transparent 0 14px, var(--panel-2) 14px 28px);
  transition-delay: .06s, .26s;
}
.slat-reveal .card.in .thumb::before { transform: translateX(-104%); opacity: 0; }
.slat-reveal .card.in .thumb::after { transform: translateX(104%); opacity: 0; }
.card .thumb .sheen {
  position: absolute; inset: 0; z-index: 3; pointer-events: none; overflow: hidden;
}
.card .thumb .sheen::before {
  content: ''; position: absolute; top: -20%; bottom: -20%; left: -45%; width: 26%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .22), transparent);
  transform: skewX(-18deg);
}
.card:hover .thumb .sheen::before { transition: left .55s ease; left: 125%; }

.tag--wt { color: #d9b96a; border-color: rgba(217, 185, 106, .35); }
/* estimated weight: dashed border + muted tone so it never reads as a
   published figure at a glance */
.tag--est {
  color: #a9906a; border-style: dashed; border-color: rgba(217, 185, 106, .45);
  font-style: italic;
}
.cart-line__meta .est, .cart-ship__row .mono.est { color: #a9906a; font-style: italic; }
.cart-ship__row em.est { font-size: 11px; color: #a9906a; font-style: italic; }
.est-note { border-left: 2px solid rgba(217, 185, 106, .5); padding-left: 9px; }
.tag--freight { color: #f0a824; border-color: rgba(240, 168, 36, .5); font-weight: 700; }
.card .add {
  background: none; border: 1px solid var(--line); color: var(--accent);
  border-radius: 4px; padding: 6px 10px; cursor: pointer;
  font: 700 11px var(--font-display); letter-spacing: .1em; text-transform: uppercase;
  transition: background .15s, color .15s, border-color .15s;
}
.card .add:hover { background: var(--accent); color: #14170a; border-color: var(--accent); }
.card .brandline { color: var(--muted); font-size: 11px; margin-top: -4px; }

.empty { color: var(--muted); text-align: center; padding: 60px 0; }

/* ---------- cart ---------- */
.cart-fab {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  background: var(--panel); color: var(--muted);
  border: 1px solid var(--line); border-radius: 6px;
  font: 800 italic 13px var(--font-display); letter-spacing: .12em;
  padding: 12px 16px; cursor: pointer;
  transition: color .2s, border-color .2s, box-shadow .2s;
}
.cart-fab.has-items { color: var(--accent); border-color: rgba(217, 240, 36, .5);
  box-shadow: 0 6px 24px rgba(0, 0, 0, .5); }
.cart-fab__n {
  display: inline-block; min-width: 20px; margin-left: 6px; padding: 2px 5px;
  background: var(--accent); color: #14170a; border-radius: 10px;
  font: 700 11px var(--font-mono); font-style: normal; text-align: center;
}
.cart-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 70;
  width: min(92vw, 380px); overflow-y: auto;
  background: var(--panel); border-left: 1px solid var(--line);
  padding: 18px 18px 26px;
  transform: translateX(105%);
  /* visibility, not just transform. A fixed element is NOT clipped by the
     body's overflow-x, so the closed drawer sitting 105% to the right still
     counted toward document width and gave every page a phantom horizontal
     scrollbar. Transitioned so it still slides rather than blinking. */
  visibility: hidden;
  transition: transform .35s cubic-bezier(.2, .9, .3, 1), visibility .35s;
  box-shadow: -18px 0 50px rgba(0, 0, 0, .5);
}
.cart-drawer.open { transform: none; visibility: visible; }
.cart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cart-head h3 {
  margin: 0; font: 800 italic 18px var(--font-display);
  text-transform: uppercase; letter-spacing: .08em;
}
.cart-head h3::before { content: '// '; color: var(--accent); }
.cart-x {
  background: none; border: none; color: var(--muted); font-size: 22px;
  cursor: pointer; line-height: 1; padding: 4px 8px;
}
.cart-x:hover { color: var(--red); }
.cart-empty { color: var(--muted); }
.cart-line { border-top: 1px solid var(--line); padding: 12px 0 10px; }
.cart-line__name { font: 600 13.5px/1.3 var(--font-body); }
.cart-line__meta {
  display: flex; gap: 14px; color: var(--muted); font-size: 12px; margin: 5px 0;
}
.mono { font-family: var(--font-mono); }
.cart-line__qty { display: flex; align-items: center; gap: 8px; }
.cart-line__qty button {
  background: var(--bg); border: 1px solid var(--line); color: var(--ink);
  border-radius: 4px; width: 26px; height: 26px; cursor: pointer; line-height: 1;
}
.cart-line__qty b { font: 700 13px var(--font-mono); min-width: 18px; text-align: center; }
.cart-line__qty [data-rm] {
  width: auto; padding: 0 8px; color: var(--muted);
  font: 600 10px var(--font-display); letter-spacing: .1em; text-transform: uppercase;
}
.cart-line__qty [data-rm]:hover { color: var(--red); border-color: var(--red); }
.cart-ship { border-top: 1px solid var(--line); margin-top: 8px; padding-top: 12px; }
.cart-ship__row {
  display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 6px;
}
.cart-ship__row.dim { color: var(--muted); }
.cart-ship__freight {
  margin: 8px 0; padding: 9px 11px; border: 1px dashed rgba(240, 168, 36, .5);
  border-radius: 6px; color: #f0a824; font-size: 12.5px;
}
.cart-foot { border-top: 1px solid var(--line); margin-top: 8px; padding-top: 14px; }
.cart-checkout { display: block; text-align: center; margin: 12px 0 8px; }
.cart-note { color: var(--muted); font-size: 11.5px; margin: 6px 0 0; }

/* ---------- footer ---------- */
footer {
  border-top: 1px solid var(--line); padding: 44px 0 60px; margin-top: 40px;
  color: var(--muted); font-size: 13.5px;
}
footer .cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 26px; }
footer h5 {
  margin: 0 0 10px; font: 700 12px var(--font-display); letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink);
}
footer a:hover { color: var(--accent); }
/* .9, not .75 — same trap as .sec-head .jp: --muted dimmed to 75% blends to
   #6a727b, 3.98:1, under AA's 4.5:1 for 12px text. */
footer .note { margin-top: 30px; font-size: 12px; opacity: .9; }

/* The nav carries nine items. It needs to become a scrolling strip well
 * before phone width — at 768px it laid out a 765px row and pushed the
 * document sideways. */
@media (max-width: 1080px) {
  .topnav .wrap { gap: 16px; }
  .topnav nav {
    gap: 14px; min-width: 0; overflow-x: auto;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  .topnav nav::-webkit-scrollbar { display: none; }
  .topnav nav a, .navdrop__btn { white-space: nowrap; }
  /* The menu is portaled to <body> and placed by enhance.js, so it no longer
     cares that this strip clips — see the note at .navdrop above. All that is
     left to say here is that a narrow screen gets a narrower menu. */
  .navdrop__menu { min-width: 224px; }
}

@media (max-width: 720px) {
  /* =========================================================================
   * PHONE. Everything here is about thumbs and vertical budget.
   * ======================================================================= */

  /* keep the nav — compact and side-scrollable, never gone */
  .topnav .wrap { gap: 14px; }
  .topnav nav {
    gap: 12px; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .topnav nav::-webkit-scrollbar { display: none; }
  .topnav nav a { white-space: nowrap; font-size: 11px; }

  /* The ghost livery number hangs 8px past the right edge by design on
     desktop, where the page is wider than the content. At 390px that 8px IS
     the whole overflow, and a storefront that scrolls sideways on a phone
     reads as broken before anyone looks at a product. */
  .livery { top: -44px; }

  /* A menu anchored to the "More" button would land off the right edge of a
     side-scrolling strip, so on phones enhance.js spans it gutter to gutter
     instead. min-width has to yield for that to be possible. */
  .navdrop__btn { white-space: nowrap; font-size: 11px; }
  .navdrop__menu { min-width: 0; }
  .toolbar { position: static; }

  /* Tap targets. Apple's floor is 44px; these were 30px, which is a coin-flip
     whether a thumb lands on the right control. Height comes from padding so
     the text stays where it sits. (The nav strip and the More menu are handled
     by the (pointer: coarse) block up top — a tablet is a touch screen at
     768px too, and width was the wrong thing to key them off.) */
  select, .finder select, .toolbar select { min-height: 44px; }
  .garage__only, .garage__clear, .chip { min-height: 44px; display: inline-flex; align-items: center; }
  .card .add, .kitlink { min-height: 44px; }
  .kitlink { justify-content: flex-start; }

  /* Hero: reclaim the vertical budget, and make the three CTAs a single
     full-width stack. Skewed inline-blocks at three different widths read as
     ragged on a narrow screen — same buttons, one column, aligned edges. */
  .hero { padding: 40px 0 44px; }
  .hero p.lead { font-size: 15.5px; margin-bottom: 22px; }
  .hero .cta { gap: 10px; }
  .hero .cta .btn { width: 100%; transform: none; padding: 15px 18px; text-align: center; }
  .hero .cta .btn > span { transform: none; }
  .btn--core::after { inset: -4px; }

  /* The cart button floated over the Year/Make/Model selects — a fixed
     element parked on top of the first thing a customer touches. */
  .cart-fab { right: 12px; bottom: 12px; padding: 10px 13px; font-size: 12px; }

  /* Section rhythm — 58px between every section is a lot of scrolling when
     each one is a single column. */
  section { padding: 38px 0; }
  section + section::before { margin-bottom: 32px; }

  .onlyxat { padding: 15px 16px; gap: 12px; }
  .onlyxat__cta { white-space: normal; }

  /* Product page: the option dropdowns ARE the demo. Give them room. */
  .pd-opt select { min-height: 48px; font-size: 15px; }
  .pd-actions .btn { width: 100%; transform: none; text-align: center; }
  .pd-actions .btn > span { transform: none; }
  .pd-kit { padding: 14px; }

  /* Cart drawer full-bleed. Pin BOTH edges and force the box width — a
     fixed element with `width:auto` let the long configured-option label
     ("Roll Center Adjusters / Calipers / Brake Line / ...") stretch it to
     603px on a 390px screen, dragging the whole document sideways. */
  .cart-drawer {
    left: 0; right: 0; width: 100vw; max-width: 100vw;
    border-left: 0;
  }
  .cart-line__name, .cart-line__opt, .cart-line { overflow-wrap: anywhere; min-width: 0; }
}

/* ---------- swap builder (combo kits) ---------- */
.bld-pick {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  border: 1px solid rgba(217, 240, 36, .35); border-radius: 8px;
  background: linear-gradient(180deg, rgba(217, 240, 36, .05), transparent 70%), var(--panel);
  padding: 12px 15px; margin-bottom: 16px;
}
.bld-pick select {
  background: var(--bg); color: var(--ink); border: 1px solid var(--line);
  border-radius: 4px; padding: 9px 11px; font: 500 13px var(--font-body); min-width: 190px;
}
.bld-hint { color: var(--muted); font-size: 13.5px; margin: 0; }
.bld-grid { display: grid; gap: 9px; }
.bld-slot {
  display: flex; align-items: center; gap: 13px; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--line); border-left-width: 3px;
  border-radius: 7px; padding: 11px 14px;
  transition: border-color .18s, background .18s;
}
.bld-slot.must { border-left-color: rgba(143, 210, 234, .5); }
.bld-slot.on {
  border-color: rgba(217, 240, 36, .4); border-left-color: var(--accent);
  background: linear-gradient(90deg, rgba(217, 240, 36, .07), transparent 40%), var(--panel);
}
.bld-slot__label {
  min-width: 168px; font: 700 12px var(--font-display); letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink);
}
.bld-slot__label b {
  display: block; font: 600 9.5px var(--font-mono); letter-spacing: .08em;
  color: var(--chrome); text-transform: none; margin-top: 2px;
}
.bld-slot select {
  flex: 1; min-width: 220px; background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 4px; padding: 8px 10px;
  font: 500 13px var(--font-body);
}
.bld-slot__thumb {
  width: 42px; height: 42px; object-fit: cover; border-radius: 4px;
  border: 1px solid var(--line);
}
.bld-none { color: var(--muted); font-size: 12.5px; font-style: italic; }
.bld-sum {
  margin-top: 16px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); padding: 15px 17px;
}
.bld-sum__row {
  display: flex; justify-content: space-between; font-size: 14px; margin-bottom: 7px;
}
.bld-sum__row.dim { color: var(--muted); font-size: 12.5px; }
.bld-sum__row .mono { font-family: var(--font-mono); }
.bld-sum__row .mono.est { color: #a9906a; font-style: italic; }
.bld-add { width: 100%; text-align: center; margin-top: 10px; }
.bld-add[disabled] { opacity: .45; pointer-events: none; }
.card .add--opts { color: var(--chrome); border-color: rgba(143, 210, 234, .4); cursor: pointer; }
.card:hover .add--opts { background: var(--chrome); color: #0b0d10; border-color: var(--chrome); }

/* ---------- "made nowhere else" band ----------
 * One product, one line, high contrast. This exists because the single most
 * commercially important fact about this shop — that it is the only source
 * on earth for a particular bracket — was previously indistinguishable from
 * 1,291 other tiles in a grid. */
/* Sits directly under the gauge cluster, so it needs no top padding of its
   own and no horizon rule on either side — it reads as the last line of the
   masthead, not as a section floating between two others. */
#onlyxat { padding: 4px 0 0; }
#onlyxat::before,
#onlyxat + section::before { display: none; }
.onlyxat {
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  padding: 18px 24px; border-radius: 10px;
  border: 1px solid rgba(217, 240, 36, .32);
  background:
    linear-gradient(100deg, rgba(217, 240, 36, .10) 0%, transparent 46%),
    linear-gradient(260deg, rgba(38, 71, 156, .30) 0%, transparent 52%),
    var(--panel);
  box-shadow: 0 0 34px rgba(217, 240, 36, .07), inset 0 1px 0 rgba(255, 255, 255, .03);
  transition: border-color .2s, box-shadow .2s, transform .2s;
}
.onlyxat:hover {
  border-color: var(--accent); transform: translateY(-2px);
  box-shadow: 0 0 46px rgba(217, 240, 36, .18);
}
.onlyxat__tag {
  flex: 0 0 auto; align-self: flex-start;
  font: 800 10.5px var(--font-display); letter-spacing: .18em; text-transform: uppercase;
  color: #14170a; background: var(--accent);
  padding: 7px 12px; border-radius: 3px;
  transform: skewX(var(--slant));
}
.onlyxat__body { flex: 1 1 320px; display: grid; gap: 5px; }
.onlyxat__body b {
  font: 800 italic 20px var(--font-display); text-transform: uppercase;
  letter-spacing: .02em; color: var(--ink);
}
.onlyxat__body span { color: var(--muted); font-size: 14px; line-height: 1.55; }
.onlyxat__cta {
  flex: 0 0 auto;
  font: 700 12px var(--font-display); letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); white-space: nowrap;
}
@media (max-width: 700px) {
  .onlyxat { gap: 14px; padding: 16px 18px; }
  .onlyxat__body b { font-size: 17px; }
  .onlyxat__cta { font-size: 11px; }
}

/* ---------- kit upgrade link on a card ----------
 * A span, not an anchor — the card itself is already an <a>, and nested
 * anchors are invalid HTML that browsers silently unnest, breaking both.
 * catalog.js gives it link behaviour and keyboard support. */
.kitlink {
  display: flex; align-items: center; gap: 6px; margin-top: 9px;
  padding: 7px 10px; border-radius: 5px; cursor: pointer;
  border: 1px solid rgba(143, 210, 234, .28);
  background: linear-gradient(100deg, rgba(38, 71, 156, .18), transparent 70%);
  font: 600 10.5px var(--font-display); letter-spacing: .06em; text-transform: uppercase;
  color: var(--chrome); white-space: nowrap;
  transition: border-color .16s, color .16s, background .16s;
}
.kitlink b { font-family: var(--font-mono); font-size: 12px; color: var(--ink); }
.kitlink i { margin-left: auto; font-style: normal; opacity: .7; }
.kitlink:hover, .kitlink:focus-visible {
  border-color: var(--accent); color: var(--accent);
  background: linear-gradient(100deg, rgba(217, 240, 36, .12), transparent 70%);
  outline: none;
}
.kitlink:hover b, .kitlink:focus-visible b { color: var(--accent); }

/* shipping breakdown: the total line separates parcel + freight from their sum */
.cart-ship__row--total {
  border-top: 1px solid var(--line); margin-top: 6px; padding-top: 8px;
  font-weight: 700;
}
.cart-ship__row--total .mono { color: var(--accent); }
.cart-ship__row em { font-style: normal; opacity: .65; font-size: 11px; }

/* ---------- core-program CTA ----------
 * A third hero button has to earn its place without competing with the first
 * two. So: no fill, teal rather than chartreuse, and a slow aura that breathes
 * instead of a static glow — visible in peripheral vision, not shouting. The
 * diamond marks it as the "new capability" affordance rather than navigation. */
.btn--core {
  position: relative;
  border-color: rgba(121, 203, 177, .45);
  color: var(--teal);
  background: linear-gradient(100deg, rgba(121, 203, 177, .08), transparent 70%);
  box-shadow: 0 0 18px rgba(121, 203, 177, .14);
  transition: color .18s, border-color .18s, box-shadow .25s, background .18s;
}
.btn--core i { font-style: normal; font-size: 9px; margin-left: 7px; opacity: .8; }
.btn--core::after {          /* the aura — a soft bloom BEHIND the button */
  content: ''; position: absolute; inset: -6px; border-radius: 8px;
  background: radial-gradient(60% 120% at 50% 50%, rgba(121, 203, 177, .30), transparent 70%);
  filter: blur(10px); z-index: -1; pointer-events: none;
  animation: core-breathe 4.5s ease-in-out infinite;
}
@keyframes core-breathe {
  0%, 100% { opacity: .35; }
  50%      { opacity: .85; }
}
.btn--core:hover {
  color: #bff0df; border-color: var(--teal);
  background: linear-gradient(100deg, rgba(121, 203, 177, .16), transparent 70%);
  box-shadow: 0 0 34px rgba(121, 203, 177, .34);
}
@media (prefers-reduced-motion: reduce) {
  .btn--core::after { animation: none; opacity: .55; }
}

/* Reserve every mount JS fills after first paint — see the note in product.css.
   Measured layout-shift sources named exactly two culprits on the storefront:
   SECTION.pitwall (the gauge cluster is built by enhance.js into an empty div)
   and the toolbar SELECTs, which are sized by their longest OPTION and so grow
   the moment catalog.js populates them. Both are reserved rather than animated
   into place. */
#catalog-grid:empty { min-height: 60vh; }
#br-mount:empty { min-height: 50vh; }
#gauge-cluster { min-height: 168px; }
.toolbar select { flex: 0 0 auto; min-width: 132px; max-width: 200px; }

/* =============================================================================
 * UNDERGLOW — the storefront's second palette.
 *
 * Neon night mode: pit-lane surfaces go violet-black, the chartreuse hands the
 * accent to electric cyan, the skid blue to magenta, and a rainbow light bar
 * breathes under the viewport like underglow pooling on asphalt. Everything is
 * driven by the same tokens the day palette defines — this block only swaps
 * their values plus the handful of decorations that hard-code brand rgba()
 * (hero radials, horizon streaks, livery tank-fill, RPM bar), so both palettes
 * stay one source of truth. State + the injected road layer live in
 * assets/js/toggles.js; the switch is the UNDERGLOW chip in the top nav.
 *
 * Two colours deliberately DON'T change: --red and --red-text. The redline is
 * the redline in any palette, and --red-text's 4.5:1 SOLD-label contrast was
 * measured against panels this dark — the new panels are darker still, so the
 * ratio only improves.
 *
 * Motion is hue-rotation, not background-position: an animated filter runs on
 * the compositor as one re-rasterized layer, while sliding a 300%-wide blurred
 * gradient repaints it every frame. Card glows are hover-only for the same
 * reason — a page can hold 600 cards and 600 animated box-shadows is a slide
 * show on a phone.
 * ===========================================================================*/
html[data-underglow] {
  --bg: #0a0714;
  --panel: #130e20;
  --panel-2: #181231;
  --line: #2d2452;
  --muted: #9b91b6;
  --chrome: #ff5ee7;        /* skid blue → neon magenta   */
  --chrome-deep: #7b2ff7;   /* sky navy  → ultraviolet    */
  --teal: #4dffc4;          /* ground band → neon mint    */
  --accent: #35f0ff;        /* chartreuse → electric cyan */
}
html[data-underglow] ::selection { background: #ff5ee7; color: #0a0714; }

/* nav: the bottom hairline becomes a slow-cycling rainbow tube */
html[data-underglow] .topnav::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: linear-gradient(90deg, #ff2d55, #ff9600, #f0ff28, #3cff8c, #2daaff, #aa3cff, #ff2d55);
  animation: ug-hue 12s linear infinite;
}

/* hero: navy/teal ambience re-lit ultraviolet/magenta; streak goes spectrum */
html[data-underglow] .hero {
  background:
    radial-gradient(90% 120% at 70% -10%, rgba(123, 47, 247, .30) 0%, transparent 55%),
    radial-gradient(70% 90% at 15% 110%, rgba(255, 94, 231, .12) 0%, transparent 60%),
    var(--bg);
}
html[data-underglow] .hero::after {
  background: linear-gradient(90deg, transparent, #ff2d55, #f0ff28, #3cff8c, #2daaff, #aa3cff, transparent);
  opacity: .45; animation: ug-hue 12s linear infinite;
}
html[data-underglow] section + section::before {
  background: linear-gradient(90deg, transparent, rgba(255, 94, 231, .3) 35%,
    rgba(53, 240, 255, .38) 50%, rgba(255, 94, 231, .3) 65%, transparent);
}

/* livery ghost numbers: tank fills with the rainbow instead of the racing ramp */
html[data-underglow] .livery {
  background-image: linear-gradient(0deg,
    rgba(255, 45, 85, .5) 0%,
    rgba(240, 255, 40, .4) 30%,
    rgba(60, 255, 140, .34) 55%,
    rgba(45, 170, 255, .3) 78%,
    rgba(170, 60, 255, .26) 100%);
}
html[data-underglow] .livery::before { -webkit-text-stroke-color: rgba(255, 94, 231, .16); }

/* RPM scroll bar: full spectrum instead of green→redline */
html[data-underglow] .rpm-progress i {
  background: linear-gradient(90deg, #ff2d55, #ff9600, #f0ff28, #3cff8c, #2daaff, #aa3cff);
}

/* hover glows — magenta + cyan double halo (hover-only; see header note) */
html[data-underglow] .card:hover {
  border-color: rgba(53, 240, 255, .55);
  box-shadow: 0 12px 34px rgba(0, 0, 0, .5), 0 0 26px rgba(255, 94, 231, .26),
    0 0 46px rgba(53, 240, 255, .18);
}
html[data-underglow] .tile:hover .tile__thumb { box-shadow: 0 8px 24px rgba(255, 94, 231, .38); }
html[data-underglow] .btn--primary { box-shadow: 0 0 20px rgba(53, 240, 255, .4), 0 0 54px rgba(255, 94, 231, .2); }

/* chartreuse/blue rgba() strays that would clash with the neon accents */
html[data-underglow] .cart-fab.has-items { border-color: rgba(53, 240, 255, .5); }
html[data-underglow] .tag--staged { border-color: rgba(53, 240, 255, .5); }
html[data-underglow] .tag--engine { border-color: rgba(255, 94, 231, .35); }
html[data-underglow] .navdrop__menu a:hover,
html[data-underglow] .navdrop__menu a:focus-visible { background: rgba(53, 240, 255, .06); }

/* ---------- the road layer (injected by underglow.js only while ON) ----------
 * Six blurred neon pools screen-blended over the viewport bottom — light on
 * asphalt, not a panel, so it must never eat a tap (pointer-events) and must
 * sit under the cart FAB (60) and drawer (70) but over plain content: z 55.
 * The base filter is duplicated in @keyframes ug-road because an animation
 * REPLACES the filter list while running — without the base copy, reduced
 * motion (animation: none) would drop the blur entirely. */
.uglow-road {
  /* -6vh, not deeper: the pool CORES sit at the layer's bottom edge, and a
     deeper offset hides exactly the bright part that makes the effect read */
  position: fixed; left: -8vw; right: -8vw; bottom: -6vh; height: 36vh;
  z-index: 55; pointer-events: none; mix-blend-mode: screen;
  transform-origin: 50% 100%; opacity: .5;
  filter: blur(34px) saturate(1.35);
  background:
    radial-gradient(42% 68% at 6% 100%,  rgba(255, 45, 85, .75), transparent 70%),
    radial-gradient(40% 66% at 25% 100%, rgba(255, 150, 10, .7),  transparent 70%),
    radial-gradient(38% 64% at 44% 100%, rgba(240, 255, 40, .62), transparent 70%),
    radial-gradient(40% 66% at 62% 100%, rgba(60, 255, 140, .7),  transparent 70%),
    radial-gradient(42% 68% at 80% 100%, rgba(45, 170, 255, .75), transparent 70%),
    radial-gradient(44% 70% at 97% 100%, rgba(170, 60, 255, .75), transparent 70%);
  animation: ug-road 18s linear infinite, ug-breathe 5.5s ease-in-out infinite;
}
@keyframes ug-road {
  from { filter: blur(34px) saturate(1.35) hue-rotate(0deg); }
  to   { filter: blur(34px) saturate(1.35) hue-rotate(360deg); }
}
@keyframes ug-breathe {
  0%, 100% { opacity: .38; transform: scaleY(.92); }
  50%      { opacity: .68; transform: scaleY(1.05); }
}
@keyframes ug-hue {
  from { filter: hue-rotate(0deg); }
  to   { filter: hue-rotate(360deg); }
}

/* ---------- the toggle strip (top right, injected by toggles.js) ----------
 * UNDERGLOW and 日本語 live in a slim utility band ABOVE the nav row — the
 * only placement that costs nothing, because the 64px row was already exactly
 * full: at the wrap's 1180px cap the last link runs flush to the right edge,
 * so chips beside the links could only wrap the menu or force it to scroll.
 * A utility band over the main nav is also where every store on earth puts
 * its language/display switches, so it reads as furniture, not clutter.
 *
 * The band's 30px is RESERVED here in .topnav's padding whether or not JS has
 * booted, because the cluster is injected at DOMContentLoaded and a header
 * that grows after first paint is exactly the layout shift the reserved-mount
 * rules at the foot of this file exist to prevent. */
.topnav { padding-top: 30px; }
.nav-toggles {
  position: absolute; top: 0; left: 0; right: 0; height: 30px;
  max-width: 1180px; margin: 0 auto; padding: 6px 22px 0;
  display: flex; justify-content: flex-end; align-items: center; gap: 8px;
}
.nav-toggles--float {   /* a page without a topnav still gets the switches */
  position: fixed; top: 10px; right: 12px; left: auto; z-index: 60; height: auto; padding: 0;
}
.tgl-chip {
  display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 10px;
  border-radius: 999px; cursor: pointer;
  font: 700 9px/1 var(--font-mono); letter-spacing: .14em;
  color: var(--muted); background: linear-gradient(180deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line);
  transition: color .2s, border-color .2s, box-shadow .2s;
}
.tgl-chip:hover { color: var(--ink); border-color: var(--chrome); }
.uglow-toggle i {
  font-style: normal; width: 8px; height: 8px; border-radius: 50%;
  background: conic-gradient(#ff2d55, #ff9600, #f0ff28, #3cff8c, #2daaff, #aa3cff, #ff2d55);
}
.uglow-toggle[aria-pressed="true"] {
  color: var(--accent); border-color: rgba(53, 240, 255, .55);
  box-shadow: 0 0 14px rgba(53, 240, 255, .25);
}
html[data-underglow] .uglow-toggle i {
  animation: ug-hue 6s linear infinite;
  box-shadow: 0 0 8px rgba(255, 255, 255, .35);
}
/* CJK glyphs at mono-9px with wide tracking turn to gravel — the JP chip
 * gets a real size and the system's own Japanese faces */
.jp-toggle span {
  font: 700 10.5px/1 var(--font-body);
  font-family: 'Hiragino Kaku Gothic ProN', 'Yu Gothic', 'Noto Sans JP', Meiryo, var(--font-body);
  letter-spacing: .08em;
}
.jp-toggle[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }

/* the Japanese accent trim itself — every .jp span sitewide is decorative
 * (aria-hidden beside an English heading), so off is a clean display:none */
html[data-jp="off"] .jp { display: none; }

@media (prefers-reduced-motion: reduce) {
  .uglow-road,
  html[data-underglow] .topnav::after,
  html[data-underglow] .hero::after,
  html[data-underglow] .uglow-toggle i { animation: none; }
}
