const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

const nav = document.getElementById('nav');
const heroVideo = document.querySelector('.hero__video');
const heroContent = document.querySelector('.hero__content');
const scrollCue = document.querySelector('.scroll-cue');
const altValue = document.getElementById('altValue');

// Split headlines into words for staggered "caught by the wind" reveals
document.querySelectorAll('.reveal-words').forEach((el) => {
  const frag = document.createDocumentFragment();
  el.childNodes.forEach((node) => {
    if (node.nodeType === Node.TEXT_NODE) {
      node.textContent.split(/(\s+)/).forEach((part) => {
        if (!part) return;
        if (/^\s+$/.test(part)) {
          frag.appendChild(document.createTextNode(' '));
        } else {
          const span = document.createElement('span');
          span.className = 'word';
          span.textContent = part;
          frag.appendChild(span);
        }
      });
    } else {
      frag.appendChild(node.cloneNode(true));
    }
  });
  el.textContent = '';
  el.appendChild(frag);
  el.querySelectorAll('.word').forEach((w, i) => {
    w.style.transitionDelay = `${i * 75}ms`;
  });
});

// Scroll-triggered reveals (plain blocks, word headlines, feature rows)
const observer = new IntersectionObserver(
  (entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) {
        entry.target.classList.add('is-visible');
        observer.unobserve(entry.target);
      }
    }
  },
  { threshold: 0.15, rootMargin: '0px 0px -40px 0px' }
);
document.querySelectorAll('.reveal, .reveal-words, .feature').forEach((el) => observer.observe(el));

// ------------------------------------------------------------------
// Single rAF ticker drives everything scroll-linked. More reliable
// than scroll events (which some embedded browsers skip for
// programmatic scrolls) and cheap: work only runs when scrollY moves.
// ------------------------------------------------------------------
let lastY = -1;

// self-healing: also recovers from the browser's own occlusion auto-pause
const syncVideo = (y) => {
  const covered = y > window.innerHeight + 60;
  if (covered && !heroVideo.paused) heroVideo.pause();
  else if (!covered && heroVideo.paused) heroVideo.play().catch(() => {});
};

const update = (y) => {
  const h = window.innerHeight;
  const p = Math.min(1, y / h);

  // nav: dark glass once past the hero
  nav.classList.toggle('nav--scrolled', y > h * 0.6);

  // hero parallax: the island drifts upward as the page slides over
  if (!reducedMotion) {
    heroVideo.style.transform = `translateY(${y * -0.3}px) scale(${1 + p * 0.1})`;
    heroContent.style.setProperty('--hero-drift', `${y * -0.22}px`);
    heroContent.style.opacity = Math.max(0, 1 - p * 1.6);
    if (scrollCue) scrollCue.style.opacity = Math.max(0, 1 - p * 4);
  }

  // altitude meter: descend from 1,000 ft to touchdown at the footer
  const max = document.documentElement.scrollHeight - h;
  const progress = max > 0 ? Math.min(1, y / max) : 1;
  const alt = Math.round(1000 * (1 - progress));
  altValue.textContent = alt === 0 ? 'touchdown' : `${alt.toLocaleString('en-US')} ft`;
};

const step = () => {
  try {
    const y = window.scrollY;
    syncVideo(y);
    if (y !== lastY) {
      lastY = y;
      update(y);
    }
  } catch (_) {
    /* never let one bad frame stop the loop */
  }
};

// driven by scroll events (primary) AND a rAF ticker (covers anything
// that moves scroll without firing events, e.g. some embedded browsers)
window.addEventListener('scroll', step, { passive: true });
window.addEventListener('resize', step, { passive: true });
const tick = () => {
  requestAnimationFrame(tick);
  step();
};
requestAnimationFrame(tick);
update(window.scrollY);

// Golden pollen drifting through the dark sections
document.querySelectorAll('.seeds').forEach((field) => {
  for (let i = 0; i < 14; i++) {
    const seed = document.createElement('span');
    seed.className = 'seed';
    seed.style.left = `${Math.random() * 100}%`;
    seed.style.top = `${15 + Math.random() * 80}%`;
    seed.style.setProperty('--size', `${2 + Math.random() * 2.5}px`);
    seed.style.setProperty('--dur', `${10 + Math.random() * 14}s`);
    seed.style.setProperty('--delay', `${Math.random() * -20}s`);
    seed.style.setProperty('--sx', `${20 + Math.random() * 60}px`);
    seed.style.setProperty('--o', `${0.15 + Math.random() * 0.3}`);
    field.appendChild(seed);
  }
});

// Email capture — placeholder until a mailing-list backend is wired up
document.querySelectorAll('.capture').forEach((form) => {
  form.addEventListener('submit', (e) => {
    e.preventDefault();
    const btn = form.querySelector('.capture__btn');
    const original = btn.textContent;
    btn.textContent = 'You’re on the list ✓';
    form.querySelector('.capture__input').value = '';
    setTimeout(() => (btn.textContent = original), 3000);
  });
});
