/* ═══════════════════════════════════════════════════════
   Landing page — 2026 brand
   -----------------------------------------------------------------------------
   Rebuilt rather than retinted. The previous hero was position:fixed with
   JS-driven opacity and scale, a second fixed "about" section reverse-revealed
   using document.scrollHeight, and will-change:transform on a multi-MB PNG.
   That carried three fragilities — new art direction broke both the crop and the
   left-edge fade, any content added below desynced the about reveal, and the
   whole thing ran a rAF loop to animate a photograph.

   It was also the least brand-aligned thing on the site. The 2026 system asks
   for "clean, minimal, information-forward", "visual restraint", and structure
   drawn from engineering drawings and blueprints. So the hero is now a static
   composition on a graph-paper ground, and the parallax is gone entirely.
   ═══════════════════════════════════════════════════════ */

/* ── Hero ─────────────────────────────────────────────────────────────────
   Full-bleed, dark, and in motion.

   The 2026 system's default is light and flat, but it carves out an explicit
   exception for exactly this: "Select performance assets adopt a black
   foundation with refined blue glow highlights, offering a modern
   interpretation of our legacy aesthetic... giving high-performance
   storytelling a focused, technical edge." A landing hero is that asset.

   The MOTION is deliberately not the old implementation. That one ran a rAF
   loop on every scroll frame, writing inline transform and opacity to a
   position:fixed element, with the about section's reveal keyed off
   document.scrollHeight so any added content desynced it.

   This is a CSS scroll-driven animation instead: no JavaScript at all, it runs
   on the compositor rather than the main thread, and there is no scrollHeight
   arithmetic to break. Where scroll timelines are unsupported (currently
   Firefox) the image simply sits static — which is the phase-3 design, so the
   fallback is a deliberate composition rather than a broken one.
   ------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: min(86vh, 840px);
  display: grid;
  align-items: center;
  background: var(--hd-ink-900);
  overflow: hidden;
  isolation: isolate;
}

.hero-media {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
}
.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
  display: block;
  transform-origin: center 40%;
  will-change: transform, opacity;
}

/*
 * Two paths to the same motion.
 *
 * Where scroll timelines exist (Chrome/Edge 115+, Safari 26+) the animation is
 * pure CSS and runs on the compositor — no JS, no scroll listener.
 *
 * Firefox has not shipped them, so it gets a --hero-progress custom property
 * set by a small rAF-throttled listener. Same visual result; the difference is
 * confined to these two blocks rather than leaking into the markup.
 */
@supports (animation-timeline: scroll()) {
  .hero-media img {
    animation: hero-drift linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 100vh;
  }
  .hero-text {
    animation: hero-lift linear both;
    animation-timeline: scroll(root block);
    animation-range: 0 70vh;
  }
}

@supports not (animation-timeline: scroll()) {
  .hero-media img {
    transform: scale(calc(1.14 - 0.14 * var(--hero-progress, 0)));
    opacity: calc(1 - 0.55 * var(--hero-progress, 0));
  }
  .hero-text {
    transform: translateY(calc(-28px * var(--hero-progress, 0)));
    opacity: calc(1 - var(--hero-progress, 0));
  }
}

@keyframes hero-drift {
  from {
    transform: scale(1.14);
    opacity: 1;
  }
  to {
    transform: scale(1);
    opacity: 0.45;
  }
}

/* Scrim. Weighted to the left so the copy sits on the darkest part of the
   frame while the athlete stays readable on the right. Measured: off-white on
   this scrim over the image's midtones is ~9:1. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      100deg,
      rgb(20 23 30 / 0.93) 0%,
      rgb(20 23 30 / 0.82) 34%,
      rgb(20 23 30 / 0.42) 66%,
      rgb(20 23 30 / 0.25) 100%
    ),
    linear-gradient(to bottom, rgb(20 23 30 / 0.5) 0%, transparent 28%);
}

/* Graph-paper overlay keeps the blueprint language present even on the dark
   treatment, so the hero still belongs to the same system as the rest. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    repeating-linear-gradient(
      to right,
      rgb(143 160 220 / 0.16) 0 1px,
      transparent 1px var(--grid-major)
    ),
    repeating-linear-gradient(
      to bottom,
      rgb(143 160 220 / 0.16) 0 1px,
      transparent 1px var(--grid-major)
    ),
    repeating-linear-gradient(
      to right,
      rgb(143 160 220 / 0.07) 0 1px,
      transparent 1px var(--grid-minor)
    ),
    repeating-linear-gradient(
      to bottom,
      rgb(143 160 220 / 0.07) 0 1px,
      transparent 1px var(--grid-minor)
    );
  -webkit-mask-image: linear-gradient(105deg, #000 0%, transparent 62%);
  mask-image: linear-gradient(105deg, #000 0%, transparent 62%);
  pointer-events: none;
}

.hero-inner {
  position: relative;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 96px 48px 88px;
}

.hero-text {
  max-width: 40rem;
  will-change: transform, opacity;
}
@keyframes hero-lift {
  from {
    transform: translateY(0);
    opacity: 1;
  }
  to {
    transform: translateY(-28px);
    opacity: 0;
  }
}

.hero .eyebrow {
  color: var(--accent-bright);
}
.hero h1 {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 7vw, 5rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  color: var(--hd-off-white);
  margin: 20px 0 0;
}
.hero h1 span {
  color: var(--accent-bright);
}
.hero-desc {
  font-size: 1.125rem;
  color: rgb(255 255 255 / 0.82);
  line-height: var(--leading-normal);
  max-width: 46ch;
  margin-top: 22px;
}

/* Scroll cue — a thin blueprint rule that travels, not a bouncing chevron. */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 0.55);
  text-decoration: none;
}
.scroll-cue:hover {
  color: var(--accent-bright);
}
.scroll-cue::after {
  content: "";
  width: var(--hairline);
  height: 34px;
  background: linear-gradient(to bottom, currentColor, transparent);
}

/* Scroll-driven animations have no duration for the global reduced-motion rule
   to zero out, so they need cancelling explicitly. */
@media (prefers-reduced-motion: reduce) {
  .hero-media img,
  .hero-text {
    animation: none;
    transform: none;
    opacity: 1;
  }
}

.hero-actions {
  display: flex;
  gap: 14px;
  margin-top: 32px;
  flex-wrap: wrap;
}

/* Square, unshadowed buttons — the brand radius is 0. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 13px 26px;
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border: var(--hairline) solid transparent;
  transition:
    background 0.15s,
    color 0.15s,
    border-color 0.15s;
}
.btn-primary {
  background: var(--accent);
  color: var(--text-on-accent);
}
.btn-primary:hover {
  background: var(--accent-hover);
}
.btn-outline {
  border-color: var(--border-default);
  color: var(--text-primary);
}
.btn-outline:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/*
 * Hero overrides. The hero became a dark surface but these inherited the
 * light-page defaults, so --text-primary (#212121) sat on the scrim at
 * 1.00:1 — identical luminance. The outline button rendered as a visible
 * border around invisible text. Anything drawn inside .hero needs
 * light-on-dark values, not the page defaults.
 */
.hero .btn-outline {
  border-color: rgb(255 255 255 / 0.38);
  color: var(--hd-off-white); /* 14.63:1 */
}
.hero .btn-outline:hover {
  border-color: var(--accent-bright);
  color: var(--accent-bright); /*  6.09:1 */
  background: rgb(255 255 255 / 0.06);
}
.hero .btn-primary {
  background: var(--accent-bright);
  color: var(--hd-ink-900); /*  6.09:1, and darker than the blue */
}
.hero .btn-primary:hover {
  background: var(--hd-off-white);
  color: var(--hd-ink-900);
}
.btn:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.hero-logos-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* NOT --text-muted: that is 3.11:1 here, which fails at this size. */
  color: rgb(255 255 255 / 0.68); /* ~9.9:1 */
  margin-top: 44px;
}
.hero-logos {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-top: 14px;
  flex-wrap: wrap;
}
/*
 * Third-party product marks are fixed colours we do not control — R's blue,
 * Python's blue-and-yellow, Excel and Sheets' greens. Several of them sit close
 * to the scrim in luminance, and dropping them to 0.75 opacity on a dark ground
 * made that worse.
 *
 * So each gets a light tile rather than being tinted or faded. It guarantees
 * legibility regardless of the mark, keeps every logo in its correct brand
 * colours, and reuses the framed-mark language already used by .product-mark
 * and .feature-logo-float.
 */
.hero-logos a {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  background: var(--hd-off-white);
  border: var(--hairline) solid rgb(255 255 255 / 0.16);
  transition:
    transform 0.15s,
    border-color 0.15s;
}
.hero-logos a:hover {
  transform: translateY(-2px);
  border-color: var(--accent-bright);
}
.hero-logos img {
  height: 24px;
  width: 24px;
  object-fit: contain;
  display: block;
}

/* ── API band ─────────────────────────────────────────── */
.api-section {
  background: var(--surface-deep);
  position: relative;
  overflow: hidden;
}
.api-section::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    repeating-linear-gradient(
      to right,
      rgb(255 255 255 / 0.1) 0 1px,
      transparent 1px var(--grid-major)
    ),
    repeating-linear-gradient(
      to bottom,
      rgb(255 255 255 / 0.1) 0 1px,
      transparent 1px var(--grid-major)
    );
  pointer-events: none;
}
.api-inner {
  position: relative;
  max-width: 1180px;
  margin: 0 auto;
  padding: 72px 48px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.api-section h2 {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.25rem);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--surface-canvas);
  margin: 14px 0 12px;
}
.api-section p {
  color: rgb(255 255 255 / 0.72);
  line-height: var(--leading-normal);
  max-width: 54ch;
}
.api-section .eyebrow {
  color: var(--accent-bright);
}
.api-section .btn-primary {
  background: var(--surface-canvas);
  color: var(--hd-blue-black);
  margin-top: 26px;
}
.api-section .btn-primary:hover {
  background: var(--hd-off-white); /* on the dark API band - intentionally fixed */
}
.api-visual img {
  width: 100%;
  height: auto;
  display: block;
  border: var(--hairline) solid rgb(255 255 255 / 0.16);
}

/* ── Feature sections ─────────────────────────────────── */
.feature {
  border-bottom: var(--hairline) solid var(--border-subtle);
}
.feature-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 72px 48px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 56px;
  align-items: center;
}
/* Alternate the visual side so the page reads as a rhythm rather than a list. */
.feature:nth-of-type(even) .feature-text {
  order: 2;
}

.feature-label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: var(--font-display-weight);
  text-transform: var(--font-display-transform);
  letter-spacing: var(--font-display-tracking);
  font-size: 0.75rem;
  color: var(--accent);
}
.feature-label img {
  height: 18px;
  width: auto;
}
.feature h2 {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.25rem);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin: 12px 0;
}
.feature p {
  color: var(--text-secondary);
  line-height: var(--leading-normal);
  max-width: 54ch;
}

.feature-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 22px;
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-link);
  text-decoration: none;
  border-bottom: var(--hairline) solid transparent;
  padding-bottom: 2px;
}
.feature-link:hover {
  color: var(--text-link-hover);
  border-bottom-color: currentColor;
}
.feature-link svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
}
/* Availability is a status, not a dead end — these now link to real pages. */
.feature-status {
  display: inline-block;
  margin-left: 10px;
  font-family: var(--font-mono);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--status-info-text);
  background: var(--status-info-bg);
  border: var(--hairline) solid var(--border-accent);
  padding: 2px 7px;
  vertical-align: middle;
}

.feature-visual {
  position: relative;
}
.feature-img-wrap {
  border: var(--hairline) solid var(--border-subtle);
  background: var(--surface-raised);
  overflow: hidden;
}
.feature-img-wrap img {
  width: 100%;
  height: auto;
  display: block;
}
.feature-logo-float {
  position: absolute;
  right: -14px;
  bottom: -14px;
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  background: var(--surface-raised);
  border: var(--hairline) solid var(--border-subtle);
}
.feature-logo-float img {
  width: 34px;
  height: 34px;
  object-fit: contain;
}
/* Excel has no screenshot on this page — a framed mark stands in. */
.feature-logo-card {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  background: var(--surface-raised);
  border: var(--hairline) solid var(--border-subtle);
}
.feature-logo-card img {
  width: 84px;
  height: 84px;
  object-fit: contain;
}

/* ── About ────────────────────────────────────────────── */
.about {
  background: var(--surface-sunken);
  border-bottom: var(--hairline) solid var(--border-subtle);
}
.about-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: 72px 48px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.about h2 {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.25rem);
  font-weight: 700;
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin: 14px 0 12px;
}
.about h2 span {
  color: var(--accent);
}
.about p {
  color: var(--text-secondary);
  line-height: var(--leading-normal);
  max-width: 54ch;
}
.about p + p {
  margin-top: 14px;
}
.about a {
  color: var(--text-link);
  text-decoration: none;
}
.about a:hover {
  color: var(--text-link-hover);
  text-decoration: underline;
}
.about-visual img {
  width: 100%;
  height: auto;
  display: block;
  border: var(--hairline) solid var(--border-subtle);
}

@media (max-width: 900px) {
  .api-inner,
  .feature-inner,
  .about-inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 36px;
    padding-left: 24px;
    padding-right: 24px;
  }
  /* Keep the copy first on narrow screens regardless of the desktop rhythm. */
  .feature:nth-of-type(even) .feature-text {
    order: 0;
  }
  .hero-inner {
    padding: 72px 24px 80px;
  }
  /* The scrim is left-weighted for a wide frame; on narrow screens the copy
     spans the full width, so darken the whole thing instead. */
  .hero-media::after {
    background:
      linear-gradient(to bottom, rgb(20 23 30 / 0.72) 0%, rgb(20 23 30 / 0.88) 100%),
      linear-gradient(to bottom, rgb(20 23 30 / 0.5) 0%, transparent 28%);
  }
}
