// Root app: scroll reveal, mount. Nav lives in sections.jsx so subpages
// (FAQ, case studies) can reuse the same component.

const { useEffect: useE } = React;

// Bidirectional reveal observer.
// - Items fade/translate IN when they enter the viewport
// - Items fade/translate OUT when they leave (so scroll-up replays the motion)
// - Survives React re-renders by re-applying `.in` if class attributes get
//   clobbered (e.g. FAQ open/close)
// - rAF-throttled MutationObserver sync to avoid scroll jank
function useRevealObserver() {
  useE(() => {
    const visible = new Set();
    const observed = new WeakSet();

    const io = new IntersectionObserver(
      (entries) => {
        for (const e of entries) {
          if (e.isIntersecting) {
            visible.add(e.target);
            e.target.classList.add('in');
          } else {
            visible.delete(e.target);
            e.target.classList.remove('in');
          }
        }
      },
      { threshold: 0, rootMargin: '0px 0px -8% 0px' }
    );

    const sync = () => {
      document.querySelectorAll('.reveal').forEach(el => {
        if (!observed.has(el)) {
          observed.add(el);
          io.observe(el);
        }
        // Re-apply `.in` if React's re-render stripped it
        if (visible.has(el) && !el.classList.contains('in')) {
          el.classList.add('in');
        }
      });
    };

    let rafId = 0;
    const scheduleSync = () => {
      if (rafId) return;
      rafId = requestAnimationFrame(() => { rafId = 0; sync(); });
    };

    sync();
    const mo = new MutationObserver(scheduleSync);
    mo.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['class'],
    });
    return () => {
      io.disconnect();
      mo.disconnect();
      if (rafId) cancelAnimationFrame(rafId);
    };
  }, []);
}

// When the homepage loads with a hash (e.g. /#work from the FAQ page nav),
// the browser's native anchor jump runs before React mounts the section, so
// the target doesn't exist yet. Poll until it does, then smooth-scroll.
function useScrollToHashOnMount() {
  useE(() => {
    const hash = window.location.hash;
    if (!hash || hash === '#' || hash === '#top') return;
    const id = hash.slice(1);
    let attempts = 0;
    const tryScroll = () => {
      const el = document.getElementById(id);
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'start' });
        history.replaceState(null, '', window.location.pathname + window.location.search);
        return;
      }
      if (attempts++ < 60) requestAnimationFrame(tryScroll);
    };
    tryScroll();
  }, []);
}

function App() {
  useRevealObserver();
  useScrollToHashOnMount();
  return (
    <>
      <Nav />
      <Hero />
      <Marquee />
      <Demo />
      <Pitch />
      <Work />
      <Process />
      <About />
      <Contact />
      <Footer />
    </>
  );
}

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