/* base.css — reset, typography, layout primitives, buttons, forms.
 * Mobile-first: everything is authored at 390px, then widened at min-width.
 * No literal color/size values here — everything comes from tokens.css.
 */

/* ---------- Reset ---------- */

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

html {
  /* The page ground. On html, not body, and not fixed-attachment: it has to
     span the whole document so the colour moves as you read down it rather
     than repeating per screen. Sections paint nothing over it. */
  background: var(--gradient-canvas);
  -webkit-text-size-adjust: 100%;
  /* In-page jumps (Get started -> the doors) glide. The reduced-motion block
     at the foot of this file resets it to auto. */
  scroll-behavior: smooth;
}

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ul,
ol {
  margin: 0;
}

ul[class],
ol[class] {
  list-style: none;
  padding: 0;
}

img,
picture,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

/* ---------- Page ---------- */

body {
  background: transparent;
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

main {
  flex: 1 0 auto;
}

/* ---------- Type ---------- */

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.25rem, 7vw, 3.75rem);
  font-weight: 700;
}

h2 {
  font-size: clamp(1.75rem, 4.5vw, 2.5rem);
  font-weight: 700;
}

h3 {
  font-size: clamp(1.125rem, 2.5vw, 1.375rem);
  font-weight: 600;
}

p {
  text-wrap: pretty;
}

a {
  color: inherit;
  text-decoration-color: var(--color-accent);
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-thickness: 2px;
}

.lede {
  font-size: clamp(1.0625rem, 2.2vw, 1.25rem);
  color: var(--color-ink-soft);
  max-width: 60ch;
}

.eyebrow {
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: var(--space-3);
}

/* A figure or claim Jack hasn't approved yet. Deliberately loud — it must never
 * be mistakable for finished copy. See content/copy_facts.md. */
.tk {
  font-family: var(--font-body);
  font-weight: 600;
  /* Explicitly dark: this chip stays light on a dark page, so it cannot
     inherit the cream ink. */
  color: var(--color-accent-soft-ink);
  background: var(--color-accent-soft);
  border-bottom: 2px dashed var(--color-accent);
  padding: 0 var(--space-1);
  border-radius: var(--space-1);
  /* Deliberately NOT nowrap. A marker long enough to matter is long enough to
     push a 390px layout sideways, and these markers are meant to be
     unmissable, not to break the page they sit in. */
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* ---------- Layout primitives ---------- */

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

.section {
  padding-block: var(--space-7);
}

@media (min-width: 48rem) {
  .section {
    padding-block: var(--space-8);
  }
}

/* Sections do not paint. The page gradient underneath is what separates one
   block of text from the next, so there is no edge between them. */
.section--tint {
  background: var(--gradient-tint);
}

/* Full-bleed dark section on the signature gradient. Anything inside it
 * switches to hero ink. */
/* Full-bleed dark section on the signature gradient. */
.section--deep {
  background: var(--gradient-deep);
  background-attachment: fixed;
  color: var(--color-hero-ink);
}

.section--deep .lede,
.section--deep p {
  color: var(--color-hero-ink);
}

.section--deep .eyebrow {
  color: var(--color-accent-soft);
}

.stack > * + * {
  margin-top: var(--space-4);
}

.grid {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 48rem) {
  .grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .grid--2 {
    grid-template-columns: repeat(2, 1fr);
  }
}

.card {
  background: var(--gradient-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.04);
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-weight: 600;
  text-decoration: none;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius);
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: opacity 0.12s ease-out, transform 0.12s ease-out;
}

.btn:active {
  opacity: 0.85;
  transform: scale(0.98);
}

.btn--primary {
  background: var(--color-button-bg);
  color: var(--color-button-ink);
}

.btn--primary:hover {
  background: var(--color-button-hover);
}

.btn--secondary {
  background: var(--gradient-surface);
  color: var(--color-accent);
  border-color: var(--color-accent);
}

/* The primary CTA when it sits on the deep gradient — cream fill, dark ink,
 * so it reads as the brightest thing on the screen. */
.btn--onLight {
  background: var(--color-accent-ink);
  color: var(--color-accent-deep);
}

.btn--lg {
  font-size: 1.0625rem;
  padding: var(--space-4) var(--space-7);
}

/* On the hero's photographic backdrop the secondary button needs its own
 * treatment — a translucent fill would fail contrast over a moving frame. */
.btn--onDark {
  background: transparent;
  color: var(--color-hero-ink);
  border-color: var(--color-hero-ink);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.btn-row--center {
  justify-content: center;
}

.btn--sm {
  font-size: 0.9375rem;
  padding: var(--space-2) var(--space-4);
  border-width: 1px;
}

/* ---------- Forms ---------- */

.field {
  display: block;
  margin-bottom: var(--space-4);
}

.field > span {
  display: block;
  font-weight: 600;
  font-size: 0.9375rem;
  margin-bottom: var(--space-2);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--gradient-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  color: var(--color-ink);
}

.field input::placeholder,
.field textarea::placeholder {
  color: color-mix(in srgb, var(--color-ink) 55%, transparent);
}

/* Native dropdown menus follow the selected palette and color scheme. */
.field select option {
  color: var(--color-ink);
  background: var(--color-surface);
}

/* Netlify's honeypot — a field only a bot fills in. Hidden from people and
 * from screen readers, on purpose. */
.honey {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- Accessibility ---------- */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--space-1);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 10;
  background: var(--color-accent);
  color: var(--color-accent-ink);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: translateY(0);
}

/* ---------- Site header ---------- */

/* The header overlays the page rather than sitting above it — every page
 * opens with a full-bleed gradient, and a solid bar on top of that would
 * break the seam. It picks up a translucent wash once you've scrolled off
 * the opening, and flips to cream type while a dark section is under it
 * (see .site-header--on-dark, toggled from site.js). */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 0.3s ease, border-color 0.3s ease;
}

/* Once anything is scrolling underneath, the header separates itself from it.
 * Without that, content passing under a fixed transparent bar collides with
 * the nav — a headline sliding up through the word "Drivers".
 *
 * It separates by BLURRING the backdrop, and paints no colour of its own.
 * That matters: this one bar sits over the black film on home, the deep green
 * gradient at the end of that same page, and the cream canvas everywhere
 * else. Any fixed colour can match exactly one of those and will read as a
 * mismatched band over the other two. Blur is derived from whatever is
 * actually behind it, so it cannot mismatch — and blurring a smooth gradient
 * returns the same smooth gradient, meaning the bar is invisible until
 * something with detail passes under it, which is precisely when it's wanted.
 */
.site-header--stuck {
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}

/* A hairline only on light ground, where the page has an edge to sit against.
 * On the film and the gradient it would be the seam it is meant to prevent. */
.site-header--stuck:not(.site-header--on-dark) {
  border-bottom-color: var(--color-line);
}

.site-header--on-dark .site-nav a {
  color: color-mix(in srgb, var(--color-hero-ink) 78%, transparent);
}

.site-header--on-dark .site-nav a:hover,
.site-header--on-dark .site-nav a[aria-current='page'] {
  color: var(--color-hero-ink);
}

/* Invert the black wordmark in dark mode without a second image asset. */
:root[data-theme='dark'] .site-header__logo img {
  filter: invert(1) brightness(1.6);
}

.site-header .wrap {
  /* Keep the logo and navigation near the viewport corners. */
  max-width: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  height: var(--header-h);
}

/* Pages that open with a plain section instead of a full-bleed hero need
 * clearance under the fixed header. */
main > .section:first-child {
  padding-top: calc(var(--space-8) + var(--header-h));
}

.site-header__logo img {
  height: 26px;
  width: auto;
}

.site-header__logo {
  flex-shrink: 0;
}

.site-nav {
  margin-left: auto;
}

.site-nav ul {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.9375rem;
}

.site-nav a {
  text-decoration: none;
  color: var(--color-ink-soft);
}

.site-nav a:hover,
.site-nav a[aria-current='page'] {
  color: var(--color-ink);
}

.site-nav a[aria-current='page'] {
  font-weight: 600;
}

.site-nav a.site-nav__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--space-6) + var(--space-3));
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-accent);
  border-radius: var(--radius);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}

.site-nav a.site-nav__action--primary,
.site-header--on-dark .site-nav a.site-nav__action--primary {
  background: var(--color-button-bg);
  border-color: var(--color-button-bg);
  color: var(--color-button-ink);
}

.site-nav a.site-nav__action--primary:hover,
.site-header--on-dark .site-nav a.site-nav__action--primary:hover {
  background: var(--color-button-hover);
  border-color: var(--color-button-hover);
}

.site-nav a.site-nav__action--secondary {
  color: var(--color-accent);
}

.site-nav a.site-nav__action--secondary:hover {
  background: var(--gradient-soft);
}

.site-header--on-dark .site-nav a.site-nav__action--secondary {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.site-header--on-dark .site-nav a.site-nav__action--secondary:hover {
  background: var(--gradient-glass);
  border-color: var(--color-accent-deep);
}

/* Below 48rem the full nav collapses to the two doors that matter. */
.site-nav li[data-secondary] {
  display: none;
}

@media (min-width: 48rem) {
  .site-nav li[data-secondary] {
    display: block;
  }
}

/* Theme icon geometry and appearance are configured in site.json/theme.json. */
.theme-toggle {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: var(--control-theme-size);
  height: var(--control-theme-size);
  padding: 0;
  color: var(--color-theme-icon);
  background: var(--gradient-soft);
  border: 1px solid var(--color-line);
  border-radius: var(--control-theme-radius);
  cursor: pointer;
}

.theme-toggle[hidden] {
  display: none;
}

.theme-toggle:hover {
  border-color: var(--color-accent);
}

.theme-toggle svg {
  width: var(--control-theme-icon-size);
  height: var(--control-theme-icon-size);
  fill: none;
  stroke: currentColor;
  stroke-width: var(--control-theme-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.theme-toggle__sun,
:root[data-theme='dark'] .theme-toggle__moon {
  display: none;
}

:root[data-theme='dark'] .theme-toggle__sun {
  display: block;
}

@media (max-width: 24rem) {
  .site-header .wrap {
    padding-inline: var(--space-3);
    gap: var(--space-2);
  }

  .site-nav ul {
    gap: var(--space-2);
  }

  .site-nav a.site-nav__action {
    padding-inline: var(--space-2);
  }
}

/* ---------- Site footer ---------- */

.site-footer {
  background: var(--gradient-tint);
  border-top: 1px solid transparent;
  padding-block: var(--space-6);
  font-size: 0.9375rem;
  color: var(--color-ink-soft);
}

.site-footer__cols {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 48rem) {
  .site-footer__cols {
    grid-template-columns: 1.5fr 1fr 1fr;
  }
}

.site-footer h2 {
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink);
  margin-bottom: var(--space-3);
}

.site-footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}

.site-footer a {
  text-decoration: none;
}

.site-footer a:hover {
  text-decoration: underline;
}

.site-footer__legal {
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-line);
  font-size: 0.875rem;
}

/* ---------- Cursor fluid ---------- */

/* The gradient reacting to the pointer passing over it.
 *
 * One soft field, not a shape. An earlier version used three small blobs at
 * different lag constants, and it read exactly as what it was: circles
 * chasing the cursor. What sells "the background is reacting" instead is the
 * opposite of that — a single field, wide enough and soft enough to have no
 * perceptible edge, following closely enough that it never feels like a
 * separate object trailing behind.
 *
 * `screen` blending keeps it honest: over the deep gradient it lifts, and
 * over the cream sections screening a pale color onto near-white is
 * mathematically almost a no-op. Only transforms animate, so it composites on
 * the GPU and never repaints.
 *
 * Built in site.js. Decorative — no markup in the templates. */
.fluid {
  position: fixed;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  mix-blend-mode: screen;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.3s ease;
  /* Clipped to the green. site.js sets these to the distance from each
     viewport edge to the gradient region, so the imprint stops at the bottom
     of the gradient instead of trailing the cursor onto the light sections
     below it. */
  clip-path: inset(var(--fluid-top, 0px) 0 var(--fluid-bottom, 0px) 0);
}

/* --fluid-mask fades the whole layer with the gradient underneath it, so the
   imprint isn't sitting on the black film either. */
.fluid--on {
  opacity: var(--fluid-mask, 1);
}

/* Light ground needs the opposite operation. Screening a pale colour onto
 * cream is arithmetically almost nothing, so in light mode the field
 * darkens fractionally instead of lifting. Same gesture, inverted. */
:root:not([data-theme='dark']) .fluid {
  mix-blend-mode: multiply;
}

:root:not([data-theme='dark']) .fluid__field {
  background: radial-gradient(
    circle at 50% 50%,
    var(--color-fluid-light) 0%,
    color-mix(in srgb, var(--color-fluid-light) 55%, transparent) 32%,
    color-mix(in srgb, var(--color-fluid-light) 18%, transparent) 56%,
    transparent 76%
  );
}

/* Wide and edgeless. The multi-stop falloff matters more than the size: a
 * single `transparent 70%` stop still leaves a faint rim you can pick out as
 * a circle, and a rim is what makes it read as an object. */
.fluid__field {
  position: absolute;
  top: 0;
  left: 0;
  width: 26rem;
  height: 26rem;
  margin: -13rem 0 0 -13rem;
  background: radial-gradient(
    circle at 50% 50%,
    var(--color-fluid) 0%,
    color-mix(in srgb, var(--color-fluid) 55%, transparent) 32%,
    color-mix(in srgb, var(--color-fluid) 18%, transparent) 56%,
    transparent 76%
  );
  will-change: transform;
}

/* No cursor to follow, or motion is unwelcome — don't build the illusion. */
@media (hover: none), (pointer: coarse) {
  .fluid {
    display: none;
  }
}

/* ---------- Motion ---------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .fluid {
    display: none;
  }
}
