/* ==========================================================================
   Kepgon — Race Your Ghost
   --------------------------------------------------------------------------
   The hero photograph is 1536x1024 (3:2). It is NEVER distorted: every rule
   below either scales it uniformly or crops it. Four aspect-ratio bands
   decide how it meets the viewport:

     BAND 1  ratio >= 2.10   ultra-wide.  Full height, letterboxed left/right
                             on the blurred backdrop. Cropping to full width
                             here would eat >35% of the frame.
     BAND 2  ratio >= 1.50   wider than the photo. Edge to edge, overflowing
                             top and bottom; the crop is split 42/58 so the
                             riders' heads stay clear of the top edge.
     BAND 3  ratio >= 0.90   taller than the photo. Edge to edge, TOP ALIGNED,
                             dissolving into black across its bottom edge.
     BAND 4  ratio <  0.90   phones and very tall windows. The photo becomes a
                             top band of fixed height and crops left/right,
                             centred on the two riders.

   Switch <html data-backdrop="blur"> to "black" to trade the blurred
   backdrop for flat #000 everywhere. Nothing else needs to change.
   ========================================================================== */

/* --------------------------------------------------------------- tokens -- */
:root {
  --vh: 100vh;                    /* upgraded to 100svh below where supported */
  --photo-ratio: 1.5;             /* 1536 / 1024 */
  --photo-w-height: calc(100vw / var(--photo-ratio));  /* height at full width */

  --crop-bias: 0.36;              /* band 2: share of the overflow taken off the top */
  --band-height: min(calc(var(--vh) * 0.68),  /* band 4: height of the photo band, */
                    calc(var(--vh) - 13rem)); /* never at the copy's expense */

  --ink: #f4f7f8;
  --ink-dim: rgba(244, 247, 248, 0.74);
  --ink-faint: rgba(244, 247, 248, 0.42);
  --ghost: #a8dcee;

  /* Display face, used for the wordmark and the headline. */
  --display: "Space Grotesk", system-ui, sans-serif;

  --gutter: clamp(1.5rem, 5.5vw, 6.5rem);

  /* 32px-wide copy of the hero, inlined. Blown up and blurred it becomes the
     backdrop, so it costs no extra request and cannot pop in late. */
  --blur-src: url("data:image/jpeg;base64,/9j/2wBDAAwICQsJCAwLCgsODQwOEh4UEhEREiUbHBYeLCcuLisnKyoxN0Y7MTRCNCorPVM+QkhKTk9OLztWXFVMW0ZNTkv/2wBDAQ0ODhIQEiQUFCRLMisyS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0v/wAARCAAVACADASIAAhEBAxEB/8QAGgAAAQUBAAAAAAAAAAAAAAAAAAIDBQYHBP/EACoQAAIBAwIEBAcAAAAAAAAAAAECAwAEERIhBSIxUQYTQcEUMkJhcYGh/8QAFwEAAwEAAAAAAAAAAAAAAAAAAQIDBP/EABoRAAMBAAMAAAAAAAAAAAAAAAABAjERQWH/2gAMAwEAAhEDEQA/AKiOG3FtLykFSy6WRumdw1WDwz4oHnSwcSkDIzcsr55T2JFMrLGAd/mGCO2DtiuGwsLZnnkTUscjnYMMd/f+Vnh0i1TPRpMV/wAJ0Kfio1zjBDE+1Sls9jNpxPCR6YYb1l4tVjjdLeZlJIGWOR0pD3t3YDLxtpH1ocg/sdKe+Vgs+kYJzFAJMBiTgA9BSLSRgGKnTqxqxtk0UVRoRMfkuHUAA4A+9Orfyx2rkAHXykHcY/HrRRQaCnp//9k=");
}

@supports (height: 100svh) {
  :root { --vh: 100svh; }
}

/* ------------------------------------------------------------ webfont -- */
/* Self-hosted latin subset: one ~13KB request, no third-party dependency and
   no layout shift from a late-arriving stylesheet. */
@font-face {
  font-family: "Space Grotesk";
  src: url("assets/fonts/SpaceGrotesk.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: var(--vh);
  overflow-x: hidden;
  background: #000;
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* =========================================================== the stage == */
/* Pinned to the viewport so the artwork never scrolls away from the copy. */
.stage {
  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

/* Layer 1 — blurred fill. Only ever visible where the photo does not reach. */
.stage__blur {
  position: absolute;
  inset: -8%;                     /* overscan so the blur has no soft edges */
  background: var(--blur-src) center / cover no-repeat;
  filter: blur(56px) saturate(1.15) brightness(0.44);
  transform: scale(1.06);
}

/* Layer 2 — sinks the backdrop toward true black, hardest at the bottom. */
.stage__wash {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.30) 0%,
    rgba(0, 0, 0, 0.46) 40%,
    rgba(0, 0, 0, 0.74) 72%,
    rgba(0, 0, 0, 0.93) 100%
  );
}

/* Layer 3 — the photograph. Position is set per band further down. */
.stage__frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.stage__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;              /* inert unless band 4 constrains the height */
  object-position: 47% 50%;       /* midpoint between the two riders */
}

/* Layer 4 — legibility scrim, anchored to the bottom-left corner where the
   copy sits. A radial pool does the heavy lifting so the sunset and the ghost
   rider on the right stay clean; a gentle full-width wash seats the footer. */
.stage__vignette {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(134% 104% at 0% 100%,
      rgba(0, 0, 0, 0.90) 0%,
      rgba(0, 0, 0, 0.66) 27%,
      rgba(0, 0, 0, 0.36) 45%,
      rgba(0, 0, 0, 0.11) 60%,
      rgba(0, 0, 0, 0) 75%),
    linear-gradient(to top,
      rgba(0, 0, 0, 0.74) 0%,
      rgba(0, 0, 0, 0.36) 15%,
      rgba(0, 0, 0, 0) 45%);
}

/* ===================================================== aspect-ratio bands = */

/* --- BAND 3 (default) — viewport taller than the photo -------------------
   Edge to edge and flush to the top; the bottom edge dissolves into the
   backdrop over the last 20% of the photo rather than stopping on a hard line. */
.stage__frame {
  height: auto;
  -webkit-mask-image: linear-gradient(to bottom,
    #000 0%, #000 80%, rgba(0, 0, 0, 0.55) 91%, transparent 100%);
          mask-image: linear-gradient(to bottom,
    #000 0%, #000 80%, rgba(0, 0, 0, 0.55) 91%, transparent 100%);
}

.stage__frame > picture { display: block; width: 100%; height: 100%; }

/* --- BAND 2 — viewport wider than the photo -------------------------------
   The photo overflows vertically. Slide it up by 42% of the overflow so the
   crop is shared between sky and road, leaving the riders untouched.
   No mask: both edges are already past the viewport. */
@media (min-aspect-ratio: 3 / 2) {
  .stage__frame {
    top: calc((var(--vh) - var(--photo-w-height)) * var(--crop-bias));
    -webkit-mask-image: none;
            mask-image: none;
  }
}

/* --- BAND 1 — ultra-wide ---------------------------------------------------
   Past 2.10 the vertical crop would exceed a third of the frame, so stop
   cropping: fit the full height and let the blurred backdrop carry the sides. */
@media (min-aspect-ratio: 5 / 2) {
  .stage__frame {
    top: 0;
    left: 50%;
    width: auto;
    height: 100%;
    aspect-ratio: 3 / 2;
    transform: translateX(-50%);
  }

  .stage__photo { object-fit: contain; }

  /* Soften the two vertical seams where photo meets backdrop. */
  .stage__frame::before,
  .stage__frame::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 7%;
    pointer-events: none;
  }
  .stage__frame::before {
    left: 0;
    background: linear-gradient(to right, rgba(0, 0, 0, 0.55), transparent);
  }
  .stage__frame::after {
    right: 0;
    background: linear-gradient(to left, rgba(0, 0, 0, 0.55), transparent);
  }
}

/* --- BAND 4 — portrait phones and very tall windows -------------------------
   Full width leaves the photo a thin strip up top, so give it a fixed band and
   crop the sides instead. object-position keeps both riders in shot. */
@media (max-aspect-ratio: 9 / 10) {
  .stage__frame {
    height: var(--band-height);
  }
}

/* ========================================================== the content == */
.content {
  position: relative;
  z-index: 1;
  min-height: var(--vh);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;      /* bands 1 & 2: sit on the road */
  padding: 0 var(--gutter) clamp(3.5rem, 8vh, 5.5rem);  /* lower strip is the eta's */
}

/* Band 1: the photo no longer spans the viewport, so pull the copy in to sit
   over it rather than floating in the blurred pillar. */
@media (min-aspect-ratio: 5 / 2) {
  .content {
    width: min(100%, calc(var(--vh) * 1.5));   /* == the photo's width */
    margin-inline: auto;
  }
}

/* Bands 3 & 4: reserve the photo's height, then centre the copy in what is
   left so it is never stranded against the very bottom edge. */
@media (max-aspect-ratio: 3 / 2) {
  .content {
    justify-content: center;
    padding-top: min(var(--photo-w-height), calc(var(--vh) * 0.66));
  }
}

@media (max-aspect-ratio: 9 / 10) {
  .content { padding-top: calc(var(--band-height) - var(--vh) * 0.03); }
}

/* ------------------------------------------------------------ wordmark -- */
.wordmark {
  margin: 0 0 clamp(0.9rem, 1.8vh, 1.5rem);
  font-family: var(--display);
  font-size: clamp(0.82rem, 1.02vw, 1.02rem);
  font-weight: 700;
  letter-spacing: 0.44em;
  text-indent: 0.44em;            /* balances the trailing letter-space */
  color: var(--ink-dim);
  text-shadow: 0 1px 16px rgba(0, 0, 0, 0.65);
}

/* ------------------------------------------------------------ headline -- */
.headline {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(2.75rem, 6.4vw, 5.5rem);
  font-weight: 700;
  line-height: 0.96;
  letter-spacing: -0.035em;
  text-wrap: balance;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.55);
}

/* The ghost rider, in type: a cool cast with a tight trail off its right edge.
   Drawn as text-shadow rather than a duplicated pseudo-element. A pseudo
   element is laid out from the inline box's top edge, which line-height: 0.96
   pushes off the baseline, so the copy sat visibly high no matter how it was
   anchored. Shadows come off the glyphs themselves and cannot drift.
   The dark shadow repeats .headline's, since setting text-shadow here
   replaces the inherited one rather than adding to it. */
.headline__ghost {
  color: var(--ghost);
  text-shadow:
    0.04em 0 5px rgba(168, 220, 238, 0.55),   /* trail */
    0 0 34px rgba(168, 220, 238, 0.28),       /* ambient glow */
    0 2px 30px rgba(0, 0, 0, 0.55);           /* legibility, matches .headline */
}

/* ----------------------------------------------------------------- eta -- */
/* Centred on the viewport rather than on the copy above it, the way a poster
   sets its release line. */
.eta {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: clamp(1.4rem, 3vh, 2.5rem);
  margin: 0;
  text-align: center;
  font-size: clamp(0.74rem, 0.9vw, 0.92rem);
  font-weight: 600;
  letter-spacing: 0.36em;
  text-indent: 0.36em;
  text-transform: uppercase;
  color: rgba(244, 247, 248, 0.66);
  text-shadow: 0 1px 16px rgba(0, 0, 0, 0.7);
}

/* ============================================== short landscape windows == */
@media (max-height: 520px) and (min-aspect-ratio: 3 / 2) {
  .wordmark { margin-bottom: 0.7rem; }
  .headline { font-size: clamp(1.9rem, 4.4vw, 2.6rem); }
  .content  { padding-bottom: 3.4rem; }
}

/* Short portrait screens: tighten so the release line stays above the fold. */
@media (max-aspect-ratio: 9 / 10) and (max-height: 730px) {
  .wordmark { margin-bottom: 0.75rem; }
  .headline { font-size: clamp(1.9rem, 8.5vw, 2.5rem); }
  .content  { padding-bottom: 3rem; }
}

/* ====================================================== entrance motion == */
@media (prefers-reduced-motion: no-preference) {
  .stage__photo {
    animation: photo-in 1400ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  .wordmark, .headline, .eta {
    animation: rise-in 900ms cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  .wordmark { animation-delay: 200ms; }
  .headline { animation-delay: 340ms; }
  .eta      { animation-delay: 520ms; }
}

/* Scale only, never opacity: the hero is the LCP element, so it must be painted
   on the first frame rather than fading up from nothing. */
@keyframes photo-in {
  from { transform: scale(1.045); }
  to   { transform: scale(1); }
}

@keyframes rise-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================== flat-black backdrop mode == */
/* <html data-backdrop="black"> — no blurred fill, just the void. */
[data-backdrop="black"] .stage__blur { display: none; }

[data-backdrop="black"] .stage__wash {
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 55%,
    rgba(0, 0, 0, 0.35) 80%,
    rgba(0, 0, 0, 0.6) 100%
  );
}
