/* TapeDeck: the hero stage, scroll progress, reveals and the overview's rise.
   Classes on <html>, all set by script:
     js       scripts run (the hero tape is drawn on a canvas; reduced motion gets one still frame)
     motion   no reduced-motion preference: the tape rolls, reveals and the progress bar run
     io       js/site.js reveals sections with IntersectionObserver
     pointer  a mouse is over the page (cursor aura)
   Without any of them the page is complete and still; without JS the hero shows a still image. */

body::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; background: var(--ambient); }

/* ── Scroll progress, along the bottom edge of the nav: warm off-white, like a tape counter ── */
.progress {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; pointer-events: none; transform-origin: 0 50%;
  transform: scaleX(var(--scroll, 0)); background: linear-gradient(90deg, rgba(242, 237, 228, .35), var(--text));
  box-shadow: 0 0 10px rgba(242, 237, 228, .5);
}
@supports (animation-timeline: scroll()) {
  .progress { animation: progress linear both; animation-timeline: scroll(root block); }
}
@keyframes progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* ── Cursor aura (desktop) ── */
.aura {
  position: fixed; left: 0; top: 0; z-index: 0; width: 560px; height: 560px; margin: -280px 0 0 -280px;
  border-radius: 50%; pointer-events: none; opacity: 0; transition: opacity .8s; will-change: transform;
  background: radial-gradient(closest-side, rgba(242, 237, 228, .06), rgba(207, 200, 188, .02) 55%, transparent);
}
html.pointer .aura { opacity: 1; }

/* ── The hero stage: the tape behind the name ── */
.hero { position: relative; z-index: 2; margin-top: calc(-1 * var(--nav-h)); }
.hero-stage {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end; isolation: isolate; overflow: hidden;
  height: 100vh; height: 100svh; min-height: 640px; max-height: 1100px;
}
.hero-sky { position: absolute; inset: 0; z-index: -3; background: var(--sky); }
html:not(.js) .hero-sky::before { /* the still of the tape, without JS */
  content: ""; position: absolute; inset: 0; background: url("img/hero-still.webp") center top / cover no-repeat;
}
@media (max-aspect-ratio: 4/5) { html:not(.js) .hero-sky::before { background-image: url("img/hero-still-m.webp"); } }
.hero-canvas { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; }
html.motion .hero-canvas { opacity: 0; transition: opacity 1.4s var(--ease); }
html.motion .hero-canvas.on { opacity: 1; }
.hero-stage::after { /* keeps the copy readable and fades the stage into the page */
  content: ""; position: absolute; inset: auto 0 0; height: 48%; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(18, 17, 16, .72) 45%, var(--bg));
}
.hero-copy { padding-bottom: clamp(52px, 10vh, 108px); }
.hero-note, .scroll-cue {
  position: absolute; bottom: 30px; font-family: var(--mono); font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.hero-note { left: var(--gutter); bottom: 44px; }
.scroll-cue { right: var(--gutter); display: inline-flex; align-items: center; gap: 12px; text-decoration: none; letter-spacing: .22em; }
.scroll-cue:hover { color: var(--text); }
.scroll-cue i { width: 1px; height: 42px; background: linear-gradient(var(--text), transparent); transform-origin: top; }
html.motion .scroll-cue i { animation: cue 2.4s var(--ease) infinite; }
@keyframes cue { 0% { transform: scaleY(0); opacity: 1; } 60% { transform: scaleY(1); opacity: 1; } 100% { opacity: 0; } }

/* ── Reveals: IntersectionObserver adds .in (only once js/site.js has set html.io) ── */
html.io .reveal { opacity: 0; translate: 0 34px; transition: opacity .9s var(--ease), translate .9s var(--ease); }
html.io .reveal.in { opacity: 1; translate: none; }
html.io .reveal.d1 { transition-delay: .08s; }
html.io .reveal.d2 { transition-delay: .16s; }
html.io .reveal.d3 { transition-delay: .24s; }

/* ── Overview: the three screens rise and spread as they scroll in (where CSS can tie it to scroll) ── */
@supports (animation-timeline: view()) {
  html.motion .trio .phone--main { animation: rise linear both; animation-timeline: view(); animation-range: entry 0% cover 34%; }
  html.motion .trio .phone--left { animation: spread-l linear both; animation-timeline: view(); animation-range: entry 10% cover 40%; }
  html.motion .trio .phone--right { animation: spread-r linear both; animation-timeline: view(); animation-range: entry 10% cover 40%; }
}
@media (max-width: 640px) { html.motion .trio .phone--side { animation: none; } } /* the small fan stays put */
@keyframes rise { from { transform: perspective(1600px) translateY(90px) rotateX(24deg) scale(.9); opacity: .35; } to { transform: none; opacity: 1; } }
@keyframes spread-l { from { translate: 70% 12%; rotate: 0deg; opacity: 0; } to { translate: 18% 6%; rotate: -5deg; opacity: .92; } }
@keyframes spread-r { from { translate: -70% 12%; rotate: 0deg; opacity: 0; } to { translate: -18% 6%; rotate: 5deg; opacity: .92; } }

@media (max-width: 920px), (max-height: 800px) {
  .hero-note, .scroll-cue { display: none; }
}
@media (max-width: 640px) {
  .hero-stage { min-height: 600px; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .progress, .aura { display: none; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
@media print {
  .reveal { opacity: 1 !important; translate: none !important; }
  .nav { position: static; }
  .hero-sky, .hero-canvas, .aura, .media::before, .trio::before { display: none !important; }
}
