/* dev.NoNames — app shell: tweaks, scroll reveal, nav state, progress */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "heroStyle": "split",
  "accent": "#22c08a",
  "motion": "lively",
  "headingFont": "Space Grotesk"
}/*EDITMODE-END*/;

function useScrollReveal(deps) {
  React.useEffect(() => {
    const gsap = window.gsap, ST = window.ScrollTrigger;
    // Fallback if GSAP isn't available: just show everything.
    if (!gsap || !ST) { document.querySelectorAll(".reveal").forEach((el) => { el.style.opacity = "1"; }); return; }
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    gsap.registerPlugin(ST);

    const ctx = gsap.context(() => {
      // Standard reveal-on-scroll via ScrollTrigger.batch — staggers elements that
      // enter the viewport together. Each element animates only when actually
      // scrolled into view (pin-proof), the way real sites do it.
      const general = gsap.utils.toArray(".reveal:not(.plan)");
      gsap.set(general, { opacity: 0, y: 46 });
      ST.batch(general, {
        start: "top 86%",
        onEnter: (b) => gsap.to(b, { opacity: 1, y: 0, duration: 0.7, ease: "power3.out", stagger: 0.12, overwrite: true }),
      });

      // Pricing cards: their transform is locked by the 3D stack, so reveal them with
      // opacity + a clip-path wipe instead of a y-slide.
      const plans = gsap.utils.toArray(".plan.reveal");
      gsap.set(plans, { opacity: 0, clipPath: "inset(0 0 100% 0)" });
      ST.batch(plans, {
        start: "top 92%",
        onEnter: (b) => gsap.to(b, { opacity: 1, clipPath: "inset(0 0 0 0)", duration: 1.15, ease: "expo.out", stagger: 0.16, overwrite: true }),
      });

      ST.refresh();
    });

    return () => ctx.revert();
  }, deps);
}

function App() {
  const [t] = useTweaks(TWEAK_DEFAULTS);
  const [scrolled, setScrolled] = React.useState(false);
  const [prog, setProg] = React.useState(0);

  // apply accent + motion + font to the document
  React.useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty("--accent", t.accent);
    r.setAttribute("data-motion", t.motion);
    r.style.setProperty("--font-display", `'${t.headingFont}', system-ui, sans-serif`);
  }, [t.accent, t.motion, t.headingFont]);

  // nav scroll state + progress bar
  React.useEffect(() => {
    const onScroll = () => {
      setScrolled(window.scrollY > 24);
      const h = document.documentElement.scrollHeight - window.innerHeight;
      setProg(h > 0 ? (window.scrollY / h) * 100 : 0);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // re-run reveal observer when hero variant changes (DOM swaps)
  useScrollReveal([t.heroStyle, t.motion]);

  return (
    <React.Fragment>
      <div className="progress" style={{ width: prog + "%" }}></div>
      <Nav scrolled={scrolled} />
      <main>
        <Hero heroStyle={t.heroStyle} motion={t.motion} />
        <Services />
        <Stats />
        <Process />
        <Marquee />
        <Work />
        <Pricing />
        <Faq />
        <Contact />
      </main>
      <Footer />
    </React.Fragment>
  );
}

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