/* ═══════════════════════════════════════════════════════════
   GEXHAUST — BASE
   The shared layer. Every page on the site links this file first.

   What lives here:
     §1  token layer      (single source of truth, moved out of style.css)
     §2  reset + document
     §3  brand lockup     (.brand-logo — the real wordmark)
     §4  type primitives  (display headings, mono labels)
     §5  button system    (.btn / .btn-hot / .btn-line)
     §6  sticky mobile CTA (.mcta)
     §7  motion           (.reveal + a real reduced-motion path)
     §8  a11y             (.sr-only, .skip-link, focus)

   What does NOT live here: page layout. index.html adds style.css on top,
   the five lite pages add a short page-specific <style> after this link.
   Cascade order is always base.css -> page CSS, so pages win on ties.
   ═══════════════════════════════════════════════════════════ */

/* ── §1 TOKEN LAYER ─────────────────────────────────────── */
:root {
  /* surface ramp */
  --ink: #0a0a0b;
  --ink-2: #101013;
  --ink-3: #17171b;
  --ink-4: #1d1d22;
  --ink-rgb: 10, 10, 11;

  /* text ramp */
  --bone: #f2efe9;
  --bone-2: rgba(242, 239, 233, .82);
  --mute: #8a8782;
  --bone-rgb: 242, 239, 233;

  /* borders */
  --line: rgba(247, 247, 246, 0.12);
  --line-2: rgba(247, 247, 246, 0.22);

  /* titanium — REAL metal gradient. Reserved for literal titanium moments
     only (Craft "Ti" bar, .fit-pill.ti). Never used as a generic accent. */
  --ti-1: #c9c2b8;
  --ti-2: #e8e2d6;
  --ti-3: #9a938a;
  --ti-4: #d8d2c6;
  --ti-5: #b3aca1;
  --ti-grad: linear-gradient(135deg, var(--ti-1), var(--ti-2), var(--ti-3), var(--ti-4), var(--ti-5));

  /* accent — the red heat ramp. CTAs, hover, focus, urgency, emphasis. */
  --accent-1: #b00020;
  --accent-2: #ed1c24;
  --accent-3: #ff4438;
  --accent-4: #ff8a80;
  --accent-grad: linear-gradient(100deg, var(--accent-1) 0%, var(--accent-2) 35%, var(--accent-3) 65%, var(--accent-4) 100%);

  /* one-off metal + rating colors, still tokenized */
  --ss-grad: linear-gradient(90deg, var(--mute), var(--bone-2));
  --gold: #e8c14a;

  /* spacing scale — 4px base */
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: .75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;

  /* type scale — shared by mono labels + body copy */
  --fs-1: .62rem;
  --fs-2: .68rem;
  --fs-3: .78rem;
  --fs-4: .85rem;
  --fs-5: .95rem;
  --fs-6: 1.05rem;
  --fs-7: 1.2rem;
  --fs-8: 1.6rem;

  /* Anton display steps */
  --fs-d1: 1.3rem;
  --fs-d2: clamp(1.6rem, 3vw, 2rem);
  --fs-d3: clamp(2rem, 4vw, 2.6rem);
  --fs-d4: clamp(2.6rem, 6vw, 3.6rem);
  --fs-d5: clamp(3rem, 7vw, 6rem);
  --fs-d6: clamp(4.2rem, 15vw, 13rem);

  /* mono-label tracking */
  --track-tight: .12em;
  --track-wide: .28em;

  /* motion */
  --dur-1: 120ms;
  --dur-2: 240ms;
  --dur-3: 420ms;
  --dur-4: 700ms;
  --ease-out: cubic-bezier(.2, .6, .2, 1);
  --ease-in-out: cubic-bezier(.4, 0, .2, 1);
  --ease-out-strong: cubic-bezier(.2, .7, .2, 1);

  /* section rhythm */
  --sec-pad: clamp(3.25rem, 6vw, 5.5rem);

  /* page gutter — one value, every page */
  --gutter: clamp(1.2rem, 4vw, 3rem);

  /* brand lockup height — pages override per context */
  --logo-h: 28px;

  /* stacking order */
  --z-bg: -1;
  --z-menu: 90;
  --z-nav: 100;
  --z-sticky: 150;
  --z-modal: 200;
  --z-skip: 1000;

  --font-display: "Anton", Impact, sans-serif;
  --font-body: "Archivo", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", monospace;
}

/* ── §2 RESET + DOCUMENT ────────────────────────────────── */
* { margin: 0; padding: 0; box-sizing: border-box; }
/* overflow-x: clip, not hidden. `hidden` would turn <html> into a scroll
   container and break position: sticky on descendants (the shop's filter
   bar). `clip` just clips. Kills the 5px of sideways drift the homepage
   had at 375 without touching anything else. */
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: clip; }
body {
  background: var(--ink);
  color: var(--bone);
  font-family: var(--font-body);
}
img, svg, video { max-width: 100%; }
/* <picture> is only a format-negotiation wrapper. display:contents removes its
   box so every existing selector (.fit-photo img, .coll-card img, ...) and every
   width/height:100% rule keeps resolving against the real parent exactly as it
   did before the AVIF/WebP conversion. Without this, picture's default inline
   box changes layout. */
picture { display: contents; }
a, button, summary, input, select { cursor: pointer; }
input[type="text"], input[type="tel"], input[type="search"], input[type="email"] { cursor: text; }
::selection { background: var(--accent-3); color: var(--ink); }

/* the red heat wash, for the one word per page that earns it */
.flare {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-style: normal;
}

/* ── §3 BRAND LOCKUP ────────────────────────────────────────
   The wordmark is an image now, not a text hack. It always ships with a
   real alt so the brand name stays in the accessibility tree and in the
   crawlable text. width/height attributes on the <img> hold the aspect
   ratio, so height + width:auto reserves the box and nothing shifts. */
.brand-logo {
  display: inline-flex; align-items: center;
  text-decoration: none; line-height: 0;
  transition: opacity var(--dur-2) var(--ease-out);
}
.brand-logo img {
  display: block;
  height: var(--logo-h);
  width: auto;
}
@media (hover: hover) and (pointer: fine) {
  .brand-logo:hover { opacity: .78; }
}
.brand-logo:active { opacity: .6; }

/* ── §4 TYPE PRIMITIVES ─────────────────────────────────── */
.display { font-family: var(--font-display); text-transform: uppercase; line-height: 1.02; }
.mono-label {
  font-family: var(--font-mono); font-size: var(--fs-2);
  letter-spacing: var(--track-wide); text-transform: uppercase;
  color: var(--mute);
}

/* ── §5 BUTTON SYSTEM ───────────────────────────────────────
   .btn-hot is the red one. There is one per screen, and it is the thing
   we want tapped. .btn-line is everything else. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5em;
  font-family: var(--font-mono); font-weight: 700;
  font-size: var(--fs-3); letter-spacing: var(--track-tight);
  text-transform: uppercase; text-decoration: none;
  padding: .95rem 1.4rem;
  min-height: 48px;              /* thumb target, every page */
  border: 1px solid transparent;
  background: transparent; color: var(--bone);
  transition: background var(--dur-3) var(--ease-out),
              border-color var(--dur-3) var(--ease-out),
              color var(--dur-3) var(--ease-out);
}
.btn-hot { background: var(--accent-grad); color: #fff; border-color: transparent; }
.btn-line { border-color: var(--line-2); color: var(--bone); }
@media (hover: hover) and (pointer: fine) {
  .btn-hot:hover { filter: brightness(1.12); }
  .btn-line:hover { border-color: var(--accent-3); color: var(--accent-3); }
}
.btn:active { transform: scale(.97); transition: transform var(--dur-1) var(--ease-out); }

/* ── §6 STICKY MOBILE CTA ───────────────────────────────────
   "Just Call G" one tap away. Phone-width only. */
.mcta {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
  display: flex; gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.mcta a, .mcta button {
  flex: 1; display: grid; place-items: center;
  min-height: 54px; padding: .9rem .5rem;
  font-family: var(--font-mono); font-size: var(--fs-2); font-weight: 700;
  letter-spacing: var(--track-tight); text-transform: uppercase;
  text-decoration: none; border: none;
  background: rgba(var(--ink-rgb), .96); color: var(--bone);
}
.mcta a.hot { background: var(--accent-grad); color: #fff; }
.mcta a:active, .mcta button:active { transform: scale(.97); transition: transform var(--dur-1) var(--ease-out); }
@media (min-width: 761px) { .mcta { display: none; } }

/* ── §7 MOTION ──────────────────────────────────────────────
   Start states only apply under html.js-motion, which page.js sets as its
   very first statement. If the script never runs, the page is fully
   readable with zero opacity-0 orphans. */
.reveal { opacity: 1; transform: none; }
html.js-motion .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--dur-4) var(--ease-out-strong) var(--rd, 0ms),
              transform var(--dur-4) var(--ease-out-strong) var(--rd, 0ms);
  will-change: opacity, transform;
}
html.js-motion .reveal.in {
  opacity: 1; transform: none;
  will-change: auto;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto !important; }
  .reveal, html.js-motion .reveal {
    opacity: 1 !important; transform: none !important;
  }
  /* press feedback survives — it is confirmation, not decoration */
  .btn:active, .mcta a:active, .mcta button:active {
    transition: transform var(--dur-1) var(--ease-out) !important;
    transform: scale(.97);
  }
}

/* ── §8 ACCESSIBILITY ───────────────────────────────────── */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: var(--z-skip);
  background: var(--bone); color: var(--ink);
  padding: .8rem 1.2rem; font-family: var(--font-mono); font-size: var(--fs-3);
}
.skip-link:focus { left: 0; }
:focus-visible { outline: 2px solid var(--accent-3); outline-offset: 3px; }
