/*
  Hero scroll-scrub structure.

  MEASURED (evidence/homepage-hero/scroll/scroll-behavior-notes.md +
  runtime/desktop-live-verification-gap-closure.json): scroll range was
  ~2x viewport height at both tested breakpoints (mobile 1255/629≈1.99x,
  desktop 1602/801≈2.00x), which is exactly what a 300vh outer wrapper
  with a 100vh sticky inner stage produces (scrollable range = wrapper
  height - viewport height = 3vh - 1vh = 2vh). The literal CSS rule
  behind the reference's content-wrapper height was never directly
  inspected (analysis/unknowns.md, "still open") - 300vh here is an
  IMPLEMENTATION RECOMMENDATION arithmetically consistent with both
  measured data points (300vh × 801px = 2403px, exactly the desktop
  figure), not a recovered literal value.

  The reference's ScrollTrigger for frame-progress uses start:"top top"/
  end:"bottom bottom" with no explicit pin:true (mechanism-hero.md,
  animation-source-mapping.md). CSS position:sticky on the inner stage
  reproduces that same pinning behavior without needing GSAP's pin
  option, matching the "plain progress read, not GSAP-scrubbed" framing
  from the evidence.
*/

.hero {
  position: relative;
  height: 300vh;
  background: var(--color-bg);
}

.hero__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

.hero__canvas-wrap {
  position: absolute;
  inset: 0;
  height: 130%;
  will-change: transform;
}

.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: #05070a;
}

.hero__scrim {
  position: absolute;
  inset: 0;
  background: var(--gradient-scrim);
  z-index: var(--z-hero-scrim);
  pointer-events: none;
}

.hero__content {
  position: absolute;
  inset: 0;
  z-index: var(--z-hero-content);
  display: flex;
  align-items: flex-end;
  padding-bottom: var(--space-9);
  pointer-events: none;
}

.hero__captions {
  /* A flex item whose only children are position:absolute (the
     .hero__caption paragraphs) has no in-flow content to size itself
     by, so it collapses to width:0 without an explicit width — an
     explicit width (not just max-width) is required here.

     font-size must be set explicitly here too: `ch` is relative to
     the element's OWN font-size, and without this the width below
     resolved against the inherited 16px body font-size rather than
     the ~68px --fs-hero the caption text actually renders at — a
     34ch/16px column is nowhere near wide enough for 34 characters of
     68px text, which wrapped to near-one-word-per-line and overflowed
     the min-height below (verified live).

     min-height is sized off this same --fs-hero for the same reason,
     covering up to 4 wrapped lines at the correct font-size context. */
  position: relative;
  font-size: var(--fs-hero);
  width: min(22ch, 100%);
  min-height: calc(var(--fs-hero) * var(--lh-tight) * 4);
}

@media (min-width: 640px) {
  .hero__captions { width: min(34ch, 100%); }
}

.hero__caption {
  position: absolute;
  inset: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-hero);
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
}

.hero__caption span.char {
  display: inline-block;
  opacity: 0;
  color: var(--color-accent);
}

.hero__scroll-hint {
  position: absolute;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%);
  z-index: var(--z-hero-content);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-text-dim);
}

.hero__scroll-hint-label {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
}

.hero__scroll-hint-line {
  width: 1px;
  height: 36px;
  background: linear-gradient(180deg, var(--color-text-dim), transparent);
}

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