/* Main stylesheet. Tokens live in tokens.css. */

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

/* The UA stylesheet hides [hidden] with `display: none`, but author styles
   beat user-agent styles regardless of specificity — so any rule setting
   `display` on an element (`.beat { display: grid }`) silently un-hides it.
   This restores the attribute's meaning for every element, and needs
   !important because the rules it is guarding against are equally specific. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  /* A lit backdrop rather than flat black: the canvas is transparent, so this
     gradient IS the studio wall the car stands against. The pool of light sits
     slightly above centre, where the car sits, and falls off toward the edges
     so text over it stays readable. */
  background:
    radial-gradient(115% 75% at 50% 38%,
      var(--backdrop-glow) 0%,
      var(--backdrop-mid) 42%,
      var(--carbon-900) 78%);
  background-attachment: fixed;
  background-color: var(--carbon-900);
  color: var(--bone);
  font-family: var(--body);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* The floor line: a soft band reading as the studio's floor-to-wall
   transition, so the car stands on something instead of floating. Fixed, so
   it holds position while content scrolls over it. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      transparent 0%,
      transparent 56%,
      color-mix(in srgb, var(--backdrop-floor) 60%, transparent) 70%,
      var(--carbon-900) 100%);
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 0.94;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  margin: 0;
}

a { color: var(--m-blue); }

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

.wrap {
  width: min(1240px, 100% - var(--gutter) * 2);
  margin-inline: auto;
}

/* Eyebrow labels: instrument-panel voice, so mono and tracked out. */
.eyebrow {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--slate-dim);
  margin: 0;
}

.lede {
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  color: var(--slate);
  max-width: 58ch;
}

/* ---------------------------------------------------------------- rail
   The signature element: the M tricolour as a scroll progress rail. It is
   information, not decoration — the gradient position tracks how far you
   are through the car, and each spec section owns a tick on it.
   Hidden on small screens where it would crowd the content. */
.rail {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--rail-w);
  height: 100vh;
  background: var(--hairline);
  z-index: 40;
}

.rail__fill {
  position: absolute;
  inset: 0 0 auto 0;
  height: 0%;
  background: linear-gradient(
    to bottom,
    var(--m-blue) 0%,
    var(--m-violet) 55%,
    var(--m-red) 100%
  );
  background-size: 100% 100vh;
}

@media (max-width: 640px) {
  .rail { display: none; }
}

/* --------------------------------------------------------------- canvas
   One canvas, fixed behind everything, driven by scroll. Sections above it
   are transparent so the car stays continuously visible. */
#scene {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100svh;
  z-index: 0;
  /* Pointer events go to the hotspot buttons layered above, not the canvas. */
  pointer-events: none;
}

#scene canvas { display: block; width: 100%; height: 100%; }

.content { position: relative; z-index: 10; }

/* ----------------------------------------------------------------- hero */
.hero {
  min-height: 100svh;
  display: grid;
  align-content: end;
  padding-block: var(--gutter) clamp(3rem, 8vh, 6rem);
}

.hero__title {
  font-size: var(--t-hero);
  /* Condensed at hero size wants negative tracking to hold together. */
  letter-spacing: -0.02em;
}

.hero__title span {
  display: block;
  color: var(--slate-dim);
  font-size: 0.34em;
  letter-spacing: 0.08em;
  font-weight: 600;
}

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  margin-top: 2rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--hairline);
}

.stat__v {
  font-family: var(--display);
  font-size: clamp(1.6rem, 3.4vw, 2.4rem);
  font-weight: 700;
  line-height: 1;
}

.stat__v small {
  font-family: var(--mono);
  font-size: 0.4em;
  color: var(--slate-dim);
  margin-left: 0.35em;
}

.stat__k {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate-dim);
}

/* -------------------------------------------------------------- sections */
.beat {
  min-height: 100svh;
  display: grid;
  align-content: center;
  padding-block: var(--stack);
}

/* Beats alternate sides so the car is never fully covered. */
.beat__card {
  max-width: 34rem;
  background: color-mix(in srgb, var(--carbon-800) 82%, transparent);
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--m-blue);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  backdrop-filter: blur(14px);
}

.beat--right .beat__card { margin-left: auto; }

.beat__card h2 {
  font-size: var(--t-h2);
  margin-block: 0.5rem 0.75rem;
}

.beat__card p { color: var(--slate); margin: 0; }

/* ------------------------------------------------------------- spec grid */
.specs { padding-block: var(--stack); }

.specs__head { margin-bottom: clamp(2rem, 5vw, 3.5rem); }
.specs__head h2 { font-size: var(--t-h2); margin-block: 0.5rem 1rem; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}

.card {
  background: var(--carbon-800);
  padding: clamp(1.5rem, 2.5vw, 2rem);
  display: grid;
  align-content: start;
  gap: 0.75rem;
}

.card h3 { font-size: var(--t-h3); }

.card p { margin: 0; color: var(--slate); font-size: var(--t-small); }

.dl { display: grid; gap: 0; margin: 0.5rem 0 0; }

.dl div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--hairline);
}

.dl dt {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--slate-dim);
}

.dl dd {
  margin: 0;
  font-size: var(--t-small);
  text-align: right;
  font-weight: 500;
}

.note {
  font-size: var(--t-small);
  color: var(--slate-dim);
  border-left: 2px solid var(--m-violet);
  padding-left: 0.85rem;
  margin: 0.25rem 0 0;
}

/* ----------------------------------------------------------------- footer */
.foot {
  padding-block: var(--stack) 3rem;
  border-top: 1px solid var(--hairline);
  color: var(--slate-dim);
  font-size: var(--t-small);
}

.foot a { color: var(--slate); }

.foot__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: 2rem;
}

/* ------------------------------------------------------------ reduced motion
   Under reduced motion the scroll-driven camera is disabled entirely in JS;
   this keeps the page from smooth-scrolling on top of that. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* -------------------------------------------------------------- preloader */
.preload {
  position: fixed;
  inset: auto var(--gutter) clamp(1.5rem, 4vh, 2.5rem) var(--gutter);
  z-index: 50;
  display: grid;
  gap: 0.6rem;
  justify-items: start;
  transition: opacity 0.5s var(--ease-out);
}

.preload.is-done { opacity: 0; pointer-events: none; }

.preload__label {
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--slate-dim);
  margin: 0;
}

.preload__bar {
  width: 0%;
  height: 2px;
  min-width: 2px;
  max-width: min(22rem, 60vw);
  background: var(--m-blue);
  transition: width 0.3s var(--ease-out);
}

.preload.is-error .preload__label {
  color: var(--m-red);
  letter-spacing: 0.08em;
  text-transform: none;
  font-family: var(--body);
  font-size: var(--t-small);
  max-width: 40ch;
}

/* --------------------------------------------------------------- hotspots
   A top-level overlay on <body>, above .content (z-index 10).
   It cannot live inside #scene: that element is `position: fixed; z-index: 0`
   and therefore a stacking context, so any z-index on a child only orders it
   within that subtree — leaving the markers underneath the full-viewport
   scroll sections, which then swallowed their clicks.
   The layer itself is click-through; only the buttons take pointer events. */
.hotspots {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 30;
}

.hotspot {
  position: fixed;
  top: 0;
  left: 0;
  /* transform is set per-frame in JS; this keeps the marker centred on its
     anchor rather than hanging off its top-left corner. */
  margin: -22px 0 0 -22px;
  pointer-events: auto;

  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  /* 44px min target — these get tapped on a phone. */
  min-height: 44px;
  padding: 0 0.85rem 0 0;
  border: 0;
  background: none;
  color: var(--bone);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
}

.hotspot__dot {
  position: relative;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  flex: none;
}

.hotspot__dot::before {
  content: '';
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--m-blue);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--carbon-900) 70%, transparent);
  transition: transform 0.2s var(--ease-out);
}

/* Ring reads as a technical callout rather than a generic pin. */
.hotspot__dot::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 1px solid color-mix(in srgb, var(--m-blue) 55%, transparent);
  border-radius: 50%;
  transition: transform 0.3s var(--ease-out), opacity 0.3s var(--ease-out);
}

.hotspot__label {
  padding: 0.35rem 0.6rem;
  background: color-mix(in srgb, var(--carbon-900) 78%, transparent);
  border: 1px solid var(--hairline);
  backdrop-filter: blur(8px);
  white-space: nowrap;
}

.hotspot:hover .hotspot__dot::before,
.hotspot:focus-visible .hotspot__dot::before { transform: scale(1.25); }

.hotspot:hover .hotspot__dot::after,
.hotspot:focus-visible .hotspot__dot::after { transform: scale(1.35); opacity: 0.4; }

.hotspot:hover .hotspot__label,
.hotspot:focus-visible .hotspot__label { border-color: var(--m-blue); }

@media (max-width: 640px) {
  /* Labels collide badly at phone width — the dots stay, the names go. */
  .hotspot__label { display: none; }
}

/* ------------------------------------------------------------------ panel */
.panel {
  width: min(38rem, calc(100vw - 2rem));
  max-height: min(80vh, 44rem);
  padding: 0;
  border: 1px solid var(--hairline);
  border-top: 2px solid var(--m-blue);
  background: var(--carbon-800);
  color: var(--bone);
  overflow: auto;
}

/* The layout is scoped to [open] deliberately.
   The UA stylesheet hides a closed dialog with `dialog:not([open]) { display:
   none }`, but author styles beat user-agent styles regardless of specificity
   — so declaring `display: grid` on `.panel` unconditionally kept the dialog
   rendered after close(), dropped out of the top layer and back into normal
   flow, sitting under the markers and refusing to scroll away. */
.panel[open] {
  display: grid;
  grid-template-areas: 'close' 'body';
  grid-template-rows: auto 1fr;
  align-content: start;
}

.panel:not([open]) { display: none; }

.panel__body { grid-area: body; }

.panel::backdrop {
  background: color-mix(in srgb, var(--carbon-900) 72%, transparent);
  backdrop-filter: blur(6px);
}

.panel__close {
  grid-area: close;
  justify-self: end;
  margin: 0.75rem 0.75rem 0 0;
  min-height: 44px;
  padding: 0 1rem;
  border: 1px solid var(--hairline);
  background: var(--carbon-700);
  color: var(--slate);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
}

.panel__close:hover { color: var(--bone); border-color: var(--m-blue); }

/* The cloned card supplies its own padding; strip the grid border it had. */
.panel__body .card { background: none; border: 0; }

/* The cockpit beat is the one section whose card shares the screen with the
   hotspot markers it refers to. Centred at full width it lands right on top
   of them, so it drops to the bottom of the viewport and narrows — close
   enough to read as a caption for the markers rather than a slab over them. */
[data-beat='cockpit'] {
  align-content: end;
  padding-bottom: clamp(1.5rem, 6vh, 4rem);
}

[data-beat='cockpit'] .beat__card {
  max-width: 26rem;
  padding: clamp(1rem, 2vw, 1.4rem);
  background: color-mix(in srgb, var(--carbon-900) 88%, transparent);
}

[data-beat='cockpit'] .beat__card h2 {
  font-size: var(--t-h3);
}

@media (max-width: 640px) {
  /* On a phone the markers fill the screen; keep the caption to a strip. */
  [data-beat='cockpit'] .beat__card p:not(.eyebrow) { font-size: var(--t-small); }
}
