/* ═══════════════════════════════════════════════════════════
   O3BN — HOMEPAGE SAMPLE LAYER v1.0
   Every animation on this page is quantized to an 87 BPM grid.
   Nothing moves smoothly. Motion lands on the beat or it doesn't
   move at all — the visual equivalent of a chopped loop.

   Load AFTER shared.css and texture.css. Homepage only.
   Zero DOM impact. No new requests.
   ═══════════════════════════════════════════════════════════ */

:root {
  --beat:   690ms;    /* 87 BPM — 60/87 */
  --half:   345ms;
  --bar:    2760ms;   /* 4 beats  */
  --phrase: 11040ms;  /* 4 bars   */
}


/* ── THE GRID ────────────────────────────────────────────────
   Override the sitewide grain drift to land on eighth notes.
   steps(1) = no interpolation. It jumps. Like a sampler. */

body::after {
  animation: grainshift var(--bar) steps(1) infinite !important;
}


/* ── 1. SCANLINE SWEEP — ONE PER PHRASE ──────────────────────
   A CRT roll that arrives every 4 bars. Long enough that you
   forget about it, regular enough that you feel it. */

.hero-scan {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0,0,0,0) 0px,
    rgba(0,0,0,0) 2px,
    rgba(0,0,0,0.22) 3px,
    rgba(0,0,0,0) 4px
  );
  opacity: 0.55;
}

.hero-scan::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  height: 18%;
  background: linear-gradient(
    to bottom,
    rgba(127,119,221,0) 0%,
    rgba(127,119,221,0.055) 45%,
    rgba(242,240,234,0.075) 50%,
    rgba(127,119,221,0.055) 55%,
    rgba(127,119,221,0) 100%
  );
  animation: crtroll var(--phrase) linear infinite;
}

@keyframes crtroll {
  0%   { top: -20%; }
  88%  { top: 100%; }
  100% { top: 100%; }
}


/* ── 2. TRACKING DROPOUT — ON THE ONE ────────────────────────
   VHS head misalignment. Fires once per phrase, lasts an
   eighth note. The tape has been played too many times. */

.hero::before {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: 38%;
  height: 26px;
  z-index: 6;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(216,90,48,0.10) 0%,
    rgba(242,240,234,0.13) 40%,
    rgba(127,119,221,0.11) 70%,
    transparent 100%
  );
  opacity: 0;
  animation: dropout var(--phrase) steps(1) infinite;
}

@keyframes dropout {
  0%,   96%  { opacity: 0; transform: translateX(0) scaleY(1); }
  96.5%      { opacity: 1; transform: translateX(-7px) scaleY(1.7); }
  97.5%      { opacity: 1; transform: translateX(5px)  scaleY(0.7); }
  98.5%      { opacity: 1; transform: translateX(-2px) scaleY(1.2); }
  99%,  100% { opacity: 0; transform: translateX(0) scaleY(1); }
}


/* ── 3. CHROMATIC SPLIT — DETUNED SAMPLE ─────────────────────
   The sample is pitched slightly off. RGB separation on the
   display type, landing on beat 1 of each bar. */

.hero-content h1,
.hero-eyebrow {
  position: relative;
  animation: detune var(--bar) steps(1) infinite;
}

@keyframes detune {
  0%,  92%  { text-shadow: none; }
  93%       { text-shadow: -1.5px 0 rgba(216,90,48,0.65), 1.5px 0 rgba(29,158,117,0.5); }
  95%       { text-shadow:  1px 0 rgba(216,90,48,0.45), -1px 0 rgba(127,119,221,0.55); }
  97%, 100% { text-shadow: none; }
}


/* ── 4. AURA BREATH — ONE BAR ────────────────────────────────
   The Valkyrie's glow pulses on the bar. The only smooth
   motion on the page, because a pad should sustain. */

.hero-mech {
  animation: breathe var(--bar) ease-in-out infinite;
}

@keyframes breathe {
  0%, 100% { opacity: 0.94; transform: translateY(0); }
  50%      { opacity: 1;    transform: translateY(-4px); }
}


/* ── 5. TAPE WARBLE — SLOW DRIFT ─────────────────────────────
   Wow and flutter. The pitch isn't stable because the
   capstan isn't perfect. Two phrases, so it never syncs
   cleanly to anything else. */

.hero-atmos {
  animation: warble calc(var(--phrase) * 2) ease-in-out infinite;
}

@keyframes warble {
  0%,  100% { transform: skewX(0deg)     scale(1); }
  25%       { transform: skewX(0.22deg)  scale(1.004); }
  50%       { transform: skewX(-0.15deg) scale(0.998); }
  75%       { transform: skewX(0.1deg)   scale(1.002); }
}


/* ── 6. EYEBROW — SIXTEENTH-NOTE STUTTER ─────────────────────
   Chopped. The kick that got retriggered. */

.hero-eyebrow::after {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-left: 10px;
  background: var(--coral);
  vertical-align: middle;
  animation: retrigger var(--beat) steps(1) infinite;
}

@keyframes retrigger {
  0%,  49%  { opacity: 1; }
  50%, 74%  { opacity: 0.2; }
  75%, 100% { opacity: 1; }
}


/* ── 7. HERO GRAIN — DENSER, ON THE HALF ─────────────────────
   Heavier than the sitewide layer. This is the record, not
   the room. */

.hero-grain {
  position: absolute;
  inset: -30%;
  z-index: 4;
  pointer-events: none;
  opacity: 0.085;
  mix-blend-mode: screen;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='h'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23h)'/%3E%3C/svg%3E");
  animation: hgrain var(--half) steps(1) infinite;
}

@keyframes hgrain {
  0%   { transform: translate(0,0); }
  33%  { transform: translate(-4%, 3%); }
  66%  { transform: translate(3%, -4%); }
  100% { transform: translate(0,0); }
}


/* ── 8. SCROLL CUE — METRONOME ───────────────────────────────
   Marks the beat. Nothing else on the page is this literal. */

.hero-scroll {
  animation: tick var(--beat) steps(1) infinite;
}

@keyframes tick {
  0%,  74%  { opacity: 0.35; transform: translateY(0); }
  75%, 100% { opacity: 0.85; transform: translateY(3px); }
}


/* ── 9. SECTION HEADS — OFF-REGISTER ON ENTRY ────────────────
   Static misprint, no motion. The loop doesn't run down here. */

.capture-headline {
  text-shadow: 1.5px 0 0 rgba(216,90,48,0.22);
}


/* ── ACCESSIBILITY ───────────────────────────────────────────
   All of this is decoration. None of it carries meaning.
   If someone doesn't want motion, they lose nothing. */

@media (prefers-reduced-motion: reduce) {
  body::after,
  .hero-scan::after,
  .hero::before,
  .hero-content h1,
  .hero-eyebrow,
  .hero-eyebrow::after,
  .hero-mech,
  .hero-atmos,
  .hero-grain,
  .hero-scroll {
    animation: none !important;
  }
  .hero-grain { opacity: 0.06; }
}


@media (max-width: 900px) {
  /* Fewer repainting layers on mobile — battery matters more
     than texture on a phone. */
  .hero::before { display: none; }
  .hero-grain   { opacity: 0.06; animation: none; }
  .hero-scan::after { animation-duration: calc(var(--phrase) * 1.5); }
}
