/* global React, ReactDOM, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakSelect,
   Nav, Hero, HowItWorks, TheCraft, Meaning, FinalCta, Footer */
const { useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "headline": "didone",
  "accent": "#c4622d",
  "density": "airy"
}/*EDITMODE-END*/;

const DENSITY = { compact: "clamp(4.5rem,9vh,8rem)", regular: "clamp(6rem,12vh,11rem)", airy: "clamp(7rem,14vh,13rem)" };

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // apply tweaks to :root
  useEffect(() => {
    const r = document.documentElement;
    r.dataset.headline = t.headline;
    r.style.setProperty("--ember", t.accent);
    r.style.setProperty("--section-y", DENSITY[t.density] || DENSITY.airy);
  }, [t.headline, t.accent, t.density]);

  // scroll reveals + sticky nav — progressive enhancement, never a hard gate
  useEffect(() => {
    const items = Array.from(document.querySelectorAll(".reveal, .line-mask"));
    const reveal = (el) => el.classList.add("in");
    const checkInView = () => {
      const vh = window.innerHeight || document.documentElement.clientHeight;
      for (const el of items) {
        if (el.classList.contains("in")) continue;
        const r = el.getBoundingClientRect();
        if (r.top < vh * 0.92 && r.bottom > 0) reveal(el);
      }
    };

    // 1) reveal whatever is already in view right now (don't wait on async IO)
    checkInView();

    // 2) IntersectionObserver as an enhancement (may be a no-op in some runtimes)
    let io = null;
    if ("IntersectionObserver" in window) {
      io = new IntersectionObserver((entries) => {
        entries.forEach((e) => { if (e.isIntersecting) { reveal(e.target); io.unobserve(e.target); } });
      }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
      items.forEach((el) => { if (!el.classList.contains("in")) io.observe(el); });
    }

    // 3) scroll/resize fallback in case IO never fires
    const onScroll = () => {
      checkInView();
      const nav = document.getElementById("nav");
      if (nav) nav.classList.toggle("scrolled", window.scrollY > 40);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);

    // 4) failsafe: nothing stays hidden even if both IO and scroll never run
    const failsafe = setTimeout(() => items.forEach(reveal), 1400);

    return () => {
      if (io) io.disconnect();
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      clearTimeout(failsafe);
    };
  }, []);

  return (
    <React.Fragment>
      <Nav />
      <main>
        <Hero />
        <HowItWorks />
        <TheCraft />
        <Meaning />
        <FinalCta />
      </main>
      <Footer />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Typography" />
        <TweakSelect label="Headline" value={t.headline}
          options={[
            { value: "didone", label: "Editorial Didone" },
            { value: "transitional", label: "Literary serif" },
            { value: "grotesque", label: "Grotesque caps" },
          ]}
          onChange={(v) => setTweak("headline", v)} />
        <TweakSection label="Color" />
        <TweakColor label="Accent" value={t.accent}
          options={["#c4622d", "#a84b2a", "#c0892f", "#5a4632"]}
          onChange={(v) => setTweak("accent", v)} />
        <TweakSection label="Rhythm" />
        <TweakRadio label="Spacing" value={t.density}
          options={["compact", "regular", "airy"]}
          onChange={(v) => setTweak("density", v)} />
      </TweaksPanel>
    </React.Fragment>
  );
}

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