// app.jsx — composes the Gasless Wallet landing page.
// COPY + HEADLINES come from copy.jsx (window.COPY / window.HEADLINES).
//
// The interactive "Tweaks" panel from the design prototype (audience / theme /
// headline tone / corner radius) was a design-time control. The configuration
// the team landed on is hardcoded below.
const CONFIG = {
  audience: 'beginner',  // 'beginner' | 'pro'
  theme: 'mint',         // 'mint' | 'cobalt' | 'violet'
  headline: 'direct',    // 'direct' | 'friendly' | 'bold'
  corners: 'Soft',       // 'Sharp' | 'Soft' | 'Rounded'
};

const CORNER_R = { Sharp: 0.45, Soft: 1, Rounded: 1.5 };

function useReveal() {
  React.useEffect(() => {
    const els = Array.from(document.querySelectorAll('.reveal'));
    const show = (el) => el.classList.add('in');
    const inView = (el) => {
      const r = el.getBoundingClientRect();
      return r.top < (window.innerHeight || 800) * 0.92 && r.bottom > 0;
    };
    // 1) reveal anything already on screen immediately
    els.forEach(el => { if (inView(el)) show(el); });

    // 2) IntersectionObserver for the rest
    let io;
    try {
      io = new IntersectionObserver((entries) => {
        entries.forEach(e => { if (e.isIntersecting) { show(e.target); io.unobserve(e.target); } });
      }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
      els.forEach(el => { if (!el.classList.contains('in')) io.observe(el); });
    } catch (_) { /* no IO support */ }

    // 3) scroll fallback in case the observer never fires
    const onScroll = () => els.forEach(el => { if (!el.classList.contains('in') && inView(el)) show(el); });
    window.addEventListener('scroll', onScroll, { passive: true });

    // 4) safety net: never leave content hidden
    const safety = setTimeout(() => els.forEach(show), 1200);

    return () => { io && io.disconnect(); window.removeEventListener('scroll', onScroll); clearTimeout(safety); };
  }, []);
}

function App() {
  useReveal();

  const audience = COPY[CONFIG.audience] ? CONFIG.audience : 'beginner';
  const c = COPY[audience];
  const headline = (HEADLINES[audience] && HEADLINES[audience][CONFIG.headline]) || HEADLINES[audience].direct;

  React.useEffect(() => {
    document.documentElement.setAttribute('data-theme', CONFIG.theme);
    document.documentElement.style.setProperty('--r', String(CORNER_R[CONFIG.corners] ?? 1));
  }, []);

  return (
    <>
      <Nav />
      <Hero headline={headline} c={c} />
      <Stats />
      <HowItWorks c={c} />
      <Comparison c={c} />
      <Referral />
      <FinalCTA />
      <Footer />
    </>
  );
}

// ── client-side hash router ──────────────────────────────────────────────
// Page routes are hashes that start with '#/': '#/node' → Node page, '#/' (or
// no hash) → Wallet landing. Plain in-page anchors like '#how' / '#widget' are
// NOT routes — they keep the current page and let the browser scroll normally.
// Switching pages re-renders in place: no full reload, no asset re-fetch.
function pageFromHash() {
  const h = window.location.hash || '';
  if (h.startsWith('#/node')) return 'node';
  if (h.startsWith('#/')) return 'wallet';
  return null; // in-page anchor (or empty) → not a page change
}

function Root() {
  const [page, setPage] = React.useState(pageFromHash() || 'wallet');

  React.useEffect(() => {
    const onHashChange = () => {
      const next = pageFromHash();
      if (next === null) return; // in-page anchor: leave page, let browser scroll
      setPage((prev) => {
        if (next !== prev) window.scrollTo(0, 0);
        return next;
      });
    };
    window.addEventListener('hashchange', onHashChange);
    return () => window.removeEventListener('hashchange', onHashChange);
  }, []);

  return page === 'node' ? <NodePage /> : <App />;
}

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