/* =============================================================================
   PAGONI — HERO
   Landscape slides crossing a dark plate, with wind behind them.

   Composition is the 1440 x 800 frame with a uniform 24px inset. Because the
   root font-size scales with the viewport (see base.css), a rem is a fixed
   fraction of the frame at every width — `63.5rem` means the same place in the
   composition on a laptop and on a 27".

   The flight runs as independent CSS animations. They stay on the compositor,
   the page can carry them alongside everything else without a frame of JS.
   ============================================================================= */

.hero {
  position: relative;
  /* Open ground before the product title. */
  --hero-gap: 35vh;
  height: calc(100vh + var(--hero-gap));
  height: calc(100dvh + var(--hero-gap));
  padding-block: 0;
  overflow: clip;

  /* Written by js/sections/hero.js every frame. Declared here so the block is
     composed correctly before a single frame has run. */
  --g-card: 1; --g-titles: 1; --g-wordmark: 1;
  --g-nav: 1; --g-action: 1; --g-hint: 1;
  --assembly-travel: 1.25rem;
  --hero-exit: 0;
}

.hero__pin {
  position: relative;
  height: 100vh;
  height: 100dvh;
  display: flex;
  align-items: stretch;
  overflow: clip;
}

[data-assembly] {
  opacity: var(--g, 1);
  transform: translate3d(0, calc((1 - var(--g, 1)) * var(--assembly-travel)), 0);
}
[data-assembly="card"]     { --g: var(--g-card); }
[data-assembly="titles"]   { --g: var(--g-titles); }
[data-assembly="wordmark"] { --g: var(--g-wordmark); }
[data-assembly="nav"]      { --g: var(--g-nav); }
[data-assembly="action"]   { --g: var(--g-action); }
[data-assembly="hint"]     { --g: var(--g-hint); }

/* -----------------------------------------------------------------------------
   GROUND
   ----------------------------------------------------------------------------- */
.hero__ground {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  /* The plate dissolves into the field over its last quarter rather than
     stopping at the section's edge. Without this there is a hard horizontal
     line across the page where the hero ends. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 72%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0, #000 72%, transparent 100%);
}

.hero__plate,
.hero__plate img { width: 100%; height: 100%; object-fit: cover; }
.hero__ground .hero__plate { position: absolute; inset: 0; opacity: 0.5; }

/* The plate is now scenery behind moving cards rather than the subject, so it
   is pushed further back than the fan needed it. */
.hero__veil { position: absolute; inset: 0; background: rgb(4 16 13 / 0.42); }

.hero__ground::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(138% 98% at 50% 44%, transparent 52%, var(--raw-void-a62) 100%),
    linear-gradient(to bottom, var(--raw-void-a38) 0%, transparent 26%, transparent 66%, var(--raw-void-a62) 100%);
}

/* -----------------------------------------------------------------------------
   THE FLIGHT

   Positions and tilts are written every frame by hero-flight.js as one 2D
   transform per slide, so the flight stays on the compositor. This file owns
   what a slide looks like in the air: the face, its rim, its light shadow.
   ----------------------------------------------------------------------------- */
.hero__flight {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: calc(1 - var(--hero-exit, 0) * 0.85);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 6%, #000 90%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 6%, #000 90%, transparent 100%);
}

.hero__layer {
  position: absolute;
  inset: 0;
  will-change: transform;
}
.hero__layer--near { z-index: 2; }
/* Atmosphere, not content: the sky sits back so the headline leads. Opacity on
   the two layers is one cheap composite, not one per slide. */
.hero__layer--near { opacity: 0.55; }
.hero__layer--far  { opacity: 0.3; }

.hero__flyer {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
  backface-visibility: hidden;
}

.hero__flyerCard {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 0.5rem;
  overflow: hidden;
  background: rgb(4 16 13);
  box-shadow:
    0 0 0 1px rgb(238 243 232 / 0.10),
    0 1rem 2rem -1rem rgb(1 6 5 / 0.8);
}
.hero__layer--far .hero__flyerCard {
  border-radius: 0.3125rem;
  box-shadow: 0 0 0 1px rgb(238 243 232 / 0.08);
}

/* The product export is the whole face. */
.hero__slideImage {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
}

/* Far slides sit back into the air rather than merely being smaller. */
.hero__layer--far .hero__flyerCard::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgb(3 14 11 / 0.36);
  pointer-events: none;
}


/* -----------------------------------------------------------------------------
   LAYOUT
   ----------------------------------------------------------------------------- */
.hero__layout {
  position: relative;
  z-index: 2;
  flex: 1;
  padding: var(--raw-spacing-page);
  /* The hero's own interface thins out as the next block arrives, so the two
     share the overlap instead of one sitting on top of the other. */
  opacity: calc(1 - var(--hero-exit, 0) * 0.92);
}

.hero__titles {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.hero__title {
  /* Cormorant, drawn in crayon by its canvas over this transparent text. */
  margin: 0;
  padding-inline: 4vw;
  font-size: 7.25rem;
  line-height: 0.98;
  text-align: center;
  text-wrap: balance;
  pointer-events: auto;
}

/* A quiet plate behind the words, part of the ground: it gives the headline
   its contrast against the photograph, and sits under the crayon headline and
   the flight so it can never dim either. */
.hero__hush {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 66rem;
  height: 22rem;
  margin: -11rem 0 0 -33rem;
  pointer-events: none;
  background: radial-gradient(closest-side ellipse at 50% 50%, rgb(3 12 11 / 0.78) 0%, rgb(3 12 11 / 0.42) 52%, transparent 100%);
}

/* -----------------------------------------------------------------------------
   SLIDE CHROME
   The opening slide's own furniture. Label left, count right, a rule between —
   where a presenter tool puts them, which is the point.
   ----------------------------------------------------------------------------- */
.hero__slug {
  position: absolute;
  left: var(--raw-spacing-page);
  right: var(--raw-spacing-page);
  top: 7.5rem;
  display: flex;
  align-items: center;
  gap: var(--raw-spacing-md);
  color: var(--foreground-faint);
}
.hero__slugLabel { color: var(--raw-chart-400); }
.hero__slugRule {
  flex: 1;
  height: 1px;
  background: linear-gradient(to right, var(--raw-ink-050-a16), var(--raw-ink-050-a08) 60%, transparent);
}

/* -----------------------------------------------------------------------------
   THE ADVANCE CUE
   The hero ends on something deliberate, which is how the next block's heading
   stopped peeking over the fold.
   ----------------------------------------------------------------------------- */
.hero__cue {
  position: absolute;
  left: 50%;
  /* Clear of the presenter bar along the bottom edge, which owns the last
     40px of the viewport. */
  bottom: 4rem;
  /* The cue is centred AND carries the assembly rise. [data-assembly] writes a
     bare translate3d, which would replace the centering outright — so this
     element does both itself and the generic rule never gets to apply. */
  transform:
    translateX(-50%)
    translateY(calc((1 - var(--g-action, 1)) * var(--assembly-travel, 1.25rem)));
  display: flex;
  align-items: center;
  gap: var(--raw-spacing-sm);
  padding: 0.5rem 0.5rem 0.5rem 1.125rem;
  border-radius: var(--raw-radius-pill);
  border: 1px solid var(--raw-mint-a24);
  /* Solid rather than a live blur: blurring the moving sky behind it cost a
     full re-blur every frame. */
  background: rgb(3 12 11 / 0.86);
  color: var(--foreground-muted);
  text-decoration: none;
  white-space: nowrap;
  transition:
    color var(--raw-duration-normal) var(--raw-ease-soft),
    border-color var(--raw-duration-normal) var(--raw-ease-soft),
    background-color var(--raw-duration-normal) var(--raw-ease-soft);
}
.hero__cue:hover,
.hero__cue:focus-visible {
  color: var(--raw-chart-400);
  border-color: var(--raw-chart-a20);
  background: rgb(3 12 11 / 0.78);
}
.hero__cue:active { transform: translateX(-50%) translateY(1px); }   /* pressed */

.hero__cueArrow {
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--raw-ink-050-a08);
  color: inherit;
  animation: hero-nudge 2.6s ease-in-out infinite;
}
.hero__cue:hover .hero__cueArrow { background: var(--raw-chart-a20); }
@keyframes hero-nudge {
  0%, 68%, 100% { transform: translateY(0); }
  82%           { transform: translateY(0.3rem); }
}

/* -----------------------------------------------------------------------------
   BELOW 1024 — the composition unstacks
   ----------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  .hero__layout {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--raw-spacing-sm);
    padding-block: 8rem 7rem;
  }

  .hero__titles {
    position: static;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .hero__title { font-size: 5.25rem; }

  .hero__hush { width: 90%; margin-left: -45%; }
}

@media (max-width: 640px) {
  .hero__title { font-size: 3.5rem; }
  .hero__slug { top: 6.5rem; }
  .hero__cue { bottom: 2.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  /* The cards stay — they are the picture — but they stop crossing. Each one
     holds at the point of its own animation it happened to be at. */
  .hero__cueArrow { animation-play-state: paused; }
}
