// waiv-home.jsx — homepage shell: Direction-B hero + scroll-reveal + nav stick.

const { useState: useStateH, useRef: useRefH, useEffect: useEffectH } = React;

function HomeHero() {
  const [finish, setFinish] = useStateH('midnightgold');
  const [revealed, setRevealed] = useStateH(false);
  const tiltRef = useRefH(null);
  const revealedRef = useRefH(false);
  revealedRef.current = revealed;

  // cursor-driven 3D tilt with spring easing
  useEffectH(() => {
    const el = tiltRef.current; if (!el) return;
    const cur = { rx: 7, ry: -23 }, tgt = { rx: 7, ry: -23 };
    let raf;
    const onMove = (e) => {
      const nx = e.clientX / window.innerWidth - 0.5;
      const ny = e.clientY / window.innerHeight - 0.5;
      tgt.ry = (revealedRef.current ? -12 : -23) + nx * 17;
      tgt.rx = (revealedRef.current ? 5 : 7) - ny * 13;
    };
    const loop = () => {
      cur.rx += (tgt.rx - cur.rx) * 0.08; cur.ry += (tgt.ry - cur.ry) * 0.08;
      el.style.transform = `rotateX(${cur.rx.toFixed(2)}deg) rotateY(${cur.ry.toFixed(2)}deg) rotateZ(2deg)`;
      raf = requestAnimationFrame(loop);
    };
    window.addEventListener('pointermove', onMove); raf = requestAnimationFrame(loop);
    return () => { window.removeEventListener('pointermove', onMove); cancelAnimationFrame(raf); };
  }, []);

  useEffectH(() => {
    const ev = new PointerEvent('pointermove', { clientX: window.innerWidth / 2, clientY: window.innerHeight / 2 });
    window.dispatchEvent(ev);
  }, [revealed]);

  const cfg = WAIV_FINISHES[finish];
  return (
    <header className="hb-hero" id="top">
      <div className="hb-field" aria-hidden="true">
        <div className="hb-glow hb-glow-1" data-parallax="0.12" />
        <div className="hb-glow hb-glow-2" data-parallax="0.08" />
        <div className="hb-grain" />
      </div>

      <div className="hb-wrap">
        <div className="hb-copy">
          <div className="hb-eyebrow"><span className="hb-eyebrow-mark" />SHARE YOUR STORY · NFC</div>
          <h1 className="hb-display">Make the<br />first move<br /><em>unforgettable.</em></h1>
          <p className="hb-lede">One premium, UV-printed card with a secure NFC chip inside. Tap any phone and your whole world arrives — contacts, socials, payments, portfolio. No app required.</p>
          <div className="hb-cta-row">
            <button className="wv-btn wv-btn-primary wv-magnetic">Design your card</button>
            <a href="#how" className="wv-btn wv-btn-ghost wv-magnetic">See how it works <span className="wv-arrow">→</span></a>
          </div>

          <div className="hb-controls">
            <div className="hb-finishes">
              {WAIV_FINISH_ORDER.map(id => (
                <button key={id} className={`hb-finish-btn ${id === finish ? 'is-active' : ''}`}
                  style={{ background: WAIV_FINISHES[id].grad }} onClick={() => setFinish(id)}
                  aria-label={WAIV_FINISHES[id].name} title={WAIV_FINISHES[id].name} />
              ))}
            </div>
            <div className="hb-finish-meta">
              <span className="hb-finish-label">Finish</span>
              <span className="hb-finish-name">{cfg.name}</span>
            </div>
          </div>

          <div style={{ marginTop: 20 }}>
            <button className={`hb-reveal ${revealed ? 'is-on' : ''}`} onClick={() => setRevealed(v => !v)}>
              <span className="hb-reveal-dot" />{revealed ? 'Hide internals' : 'See inside the card'}
            </button>
          </div>
        </div>

        <div className="hb-stage-wrap" data-parallax="0.05" data-parallax-base="translateY(-50%)">
          <WaivCard3D ref={tiltRef} w={620} finish={finish} revealed={revealed} />
        </div>
      </div>

      <div className="hb-scrollcue">Scroll<div className="hb-scrollcue-line" /></div>
    </header>
  );
}

function Nav() {
  const [stuck, setStuck] = useStateH(false);
  const progRef = useRefH(null);
  useEffectH(() => {
    const onScroll = () => {
      setStuck(window.scrollY > 40);
      const max = document.documentElement.scrollHeight - window.innerHeight;
      if (progRef.current) progRef.current.style.width = (max > 0 ? (window.scrollY / max) * 100 : 0) + '%';
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <nav className={`hb-nav ${stuck ? 'is-stuck' : ''}`}>
              <a href="#top"><img className="hb-nav-logo" src={(window.__resources&&window.__resources.logoLight)||"assets/waiv-light.png"} alt="waiv" /></a>
      <div className="hb-nav-links">
        <a href="#cards">Cards</a><a href="#how">How it works</a><a href="#onelynk">Onelynk</a><a href="#business">For business</a>
      </div>
      <button className="wv-btn wv-btn-primary wv-magnetic" style={{ fontSize: 14, padding: '11px 20px' }}>Get your waiv</button>
      <div className="hb-nav-progress" ref={progRef} />
    </nav>
  );
}

function App() {
  // scroll reveal
  useEffectH(() => {
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); } });
    }, { threshold: 0.12, rootMargin: '0px 0px -6% 0px' });
    const observeAll = () => document.querySelectorAll('[data-reveal]:not(.is-in)').forEach(el => io.observe(el));
    observeAll();
    // re-scan for elements mounted later (e.g. gallery Wall, modal content)
    const mo = new MutationObserver(observeAll);
    mo.observe(document.body, { childList: true, subtree: true });
    return () => { io.disconnect(); mo.disconnect(); };
  }, []);

  // scroll parallax — gentle drift on decorative layers
  useEffectH(() => {
    const els = [...document.querySelectorAll('[data-parallax]')].map(el => ({
      el, speed: parseFloat(el.getAttribute('data-parallax')) || 0.08,
      base: el.getAttribute('data-parallax-base') || '',
    }));
    if (!els.length || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    let raf;
    const loop = () => {
      const h = window.innerHeight;
      els.forEach(({ el, speed, base }) => {
        const r = el.getBoundingClientRect();
        const rel = (r.top + r.height / 2) - h / 2;
        el.style.transform = `${base} translate3d(0, ${(-rel * speed).toFixed(1)}px, 0)`.trim();
      });
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);

  // magnetic buttons
  useEffectH(() => {
    const onMove = (e) => {
      document.querySelectorAll('.wv-magnetic').forEach(b => {
        const r = b.getBoundingClientRect();
        const dx = e.clientX - (r.left + r.width / 2), dy = e.clientY - (r.top + r.height / 2);
        const d = Math.hypot(dx, dy), radius = 130;
        if (d < radius) { const p = (1 - d / radius) * 10; b.style.transform = `translate(${(dx / d) * p || 0}px, ${(dy / d) * p - 2 || -2}px)`; }
        else b.style.transform = '';
      });
    };
    window.addEventListener('pointermove', onMove);
    return () => window.removeEventListener('pointermove', onMove);
  }, []);

  // custom cursor: lagging ring + dot, reacts to links & draggables
  useEffectH(() => {
    if (!window.matchMedia('(hover:hover) and (pointer:fine)').matches) return;
    document.body.classList.add('wv-cursor-on');
    const wrap = document.createElement('div'); wrap.className = 'wv-cur';
    const ring = document.createElement('div'); ring.className = 'wv-cur-ring';
    const dot = document.createElement('div'); dot.className = 'wv-cur-dot';
    wrap.append(ring, dot); document.body.appendChild(wrap);
    let mx = innerWidth / 2, my = innerHeight / 2, rx = mx, ry = my, raf;
    const linkSel = 'a, button, .wv-btn, .pg-card, .pg-dot, .so-bubble, .iw-step, .iw-replay, .ol-feat, .hb-finish-btn, .wv-finish-chip, .coll-arrow, [role="button"]';
    const onMove = (e) => {
      mx = e.clientX; my = e.clientY;
      dot.style.left = mx + 'px'; dot.style.top = my + 'px';
      const t = e.target.closest ? e.target.closest(linkSel) : null;
      const grab = e.target.closest ? e.target.closest('.bud') : null;
      ring.classList.toggle('is-link', !!t && !grab);
      dot.classList.toggle('is-link', !!t && !grab);
      ring.classList.toggle('is-grab', !!grab);
    };
    const onLeave = () => wrap.classList.add('is-hidden');
    const onEnter = () => wrap.classList.remove('is-hidden');
    const loop = () => { rx += (mx - rx) * 0.18; ry += (my - ry) * 0.18; ring.style.left = rx + 'px'; ring.style.top = ry + 'px'; raf = requestAnimationFrame(loop); };
    window.addEventListener('pointermove', onMove);
    document.addEventListener('mouseleave', onLeave);
    document.addEventListener('mouseenter', onEnter);
    raf = requestAnimationFrame(loop);
    return () => { window.removeEventListener('pointermove', onMove); document.removeEventListener('mouseleave', onLeave); document.removeEventListener('mouseenter', onEnter); cancelAnimationFrame(raf); wrap.remove(); document.body.classList.remove('wv-cursor-on'); };
  }, []);

  return (
    <div className="wv-home">
      <Nav />
      <WaivJourney />
      <TrustStrip />
      <HowItWorks />
      <ProductGallery />
      <FactoryScene />
      <ShareGrid />
      <Onelynk />
      <ForBusiness />
      <FinalCTA />
      <Footer />
      <WaivBuddy />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
