/* ============================================================
   v2 app — root component, tweaks, cursor effects, reveals
   ============================================================ */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#ff5a1f",
  "toy": "lattice",
  "motion": 6
}/*EDITMODE-END*/;

function useGlobalEffects(motion) {
  // Reveal-on-scroll
  React.useEffect(() => {
    const els = Array.from(document.querySelectorAll("[data-rev]"));
    if (!("IntersectionObserver" in window)) {
      els.forEach((el) => el.classList.add("in"));
      return;
    }
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            e.target.classList.add("in");
            io.unobserve(e.target);
          }
        });
      },
      { threshold: 0.12, rootMargin: "0px 0px -6% 0px" }
    );
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);

  // Spotlight cards — track cursor into CSS vars
  React.useEffect(() => {
    const onMove = (e) => {
      const card = e.target.closest && e.target.closest(".spot");
      if (!card) return;
      const r = card.getBoundingClientRect();
      card.style.setProperty("--mx", `${e.clientX - r.left}px`);
      card.style.setProperty("--my", `${e.clientY - r.top}px`);
    };
    document.addEventListener("pointermove", onMove, { passive: true });
    return () => document.removeEventListener("pointermove", onMove);
  }, []);

  // Magnetic buttons
  React.useEffect(() => {
    const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced || motion === 0) return;
    const strength = 0.22 + (motion / 10) * 0.18;
    const onMove = (e) => {
      document.querySelectorAll(".magnetic").forEach((el) => {
        const r = el.getBoundingClientRect();
        const cx = r.left + r.width / 2, cy = r.top + r.height / 2;
        const dx = e.clientX - cx, dy = e.clientY - cy;
        const dist = Math.hypot(dx, dy);
        const range = Math.max(r.width, 90);
        if (dist < range) {
          const f = (1 - dist / range) * strength;
          el.style.transform = `translate(${dx * f}px, ${dy * f}px)`;
        } else if (el.style.transform) {
          el.style.transform = "";
        }
      });
    };
    document.addEventListener("pointermove", onMove, { passive: true });
    return () => {
      document.removeEventListener("pointermove", onMove);
      document.querySelectorAll(".magnetic").forEach((el) => { el.style.transform = ""; });
    };
  }, [motion]);
}

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

  React.useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty("--acc", t.accent);
    r.style.setProperty("--mi", String(Math.max(0.05, t.motion / 10)));
    if (t.motion === 0) r.setAttribute("data-motion", "none");
    else r.removeAttribute("data-motion");
  }, [t.accent, t.motion]);

  useGlobalEffects(t.motion);

  return (
    <>
      <HeroV2 toy={t.toy} motion={t.motion} />
      <StatsV2 />
      <WorkV2 />
      <TimelineV2 />
      <WritingV2 />
      <ContactV2 />
      <TweaksPanel>
        <TweakSection label="Theme" />
        <TweakColor
          label="Accent"
          value={t.accent}
          options={["#ff5a1f", "#27e0a6", "#6f8dff", "#e6fb45"]}
          onChange={(v) => setTweak("accent", v)}
        />
        <TweakSection label="Hero field" />
        <TweakRadio
          label="Variant"
          value={t.toy}
          options={["lattice", "glyphs", "off"]}
          onChange={(v) => setTweak("toy", v)}
        />
        <TweakSection label="Motion" />
        <TweakSlider
          label="Intensity"
          value={t.motion}
          min={0} max={10} step={1}
          onChange={(v) => setTweak("motion", v)}
        />
      </TweaksPanel>
    </>
  );
}

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