// Cursor-following glow blob — fades out after inactivity
function CursorGlow() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const isTouch = window.matchMedia && window.matchMedia("(pointer: coarse)").matches;
    if (isTouch) { el.style.display = "none"; return; }
    let x = -200, y = -200, cx = -200, cy = -200;
    let visible = false, raf = 0;
    const show = () => { if (!visible) { el.style.opacity = "1"; visible = true; } };
    const hide = () => { if (visible) { el.style.opacity = "0"; visible = false; } };
    const onMove = (e) => { x = e.clientX; y = e.clientY; show(); };
    const onLeave = () => { hide(); };
    const tick = () => {
      cx += (x - cx) * 0.7;
      cy += (y - cy) * 0.7;
      el.style.transform = "translate(" + (cx - 160) + "px," + (cy - 160) + "px)";
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    window.addEventListener("mousemove", onMove, { passive: true });
    document.addEventListener("mouseleave", onLeave);
    return () => { cancelAnimationFrame(raf); window.removeEventListener("mousemove", onMove); document.removeEventListener("mouseleave", onLeave); };
  }, []);
  return (
    <div ref={ref} aria-hidden="true" style={{
      position: "fixed", top: 0, left: 0, width: 320, height: 320,
      borderRadius: "50%", pointerEvents: "none", zIndex: 1,
      background: "radial-gradient(circle, rgba(31,155,255,0.10) 0%, rgba(69,226,210,0.04) 35%, transparent 65%)",
      opacity: 0, transition: "opacity .6s var(--ease-out)",
      willChange: "transform",
    }} />
  );
}

// FireTail portfolio — App shell
function App() {
  const reduced = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const [active, setActive] = React.useState(null);
  const [splash, setSplash] = React.useState(() => {
    if (reduced) return false;
    return true; /* DEBUG: always show splash */
  });

  React.useEffect(() => {
    document.body.style.overflow = active ? "hidden" : "";
  }, [active]);

  // Scroll-reveal
  React.useEffect(() => {
    if (reduced) return;
    const els = Array.from(document.querySelectorAll("[data-reveal]"));
    const io = new IntersectionObserver((entries) => {
      entries.forEach((en) => {
        if (en.isIntersecting) { en.target.classList.add("ft-in"); io.unobserve(en.target); }
      });
    }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, [splash]);

  const endSplash = React.useCallback(() => {
    try { sessionStorage.setItem("ft_splash_seen", "1"); } catch (e) { }
    setSplash(false);
  }, []);

  // Smooth in-page scrolling — scrolling happens inside #ft-scroll, not window,
  // so native hash-anchor jumps misbehave. Delegate all a[href^="#"] clicks.
  React.useEffect(() => {
    const scroller = document.querySelector("#ft-scroll");
    if (!scroller) return;
    const NAV_OFFSET = 80;
    const onClick = (e) => {
      const a = e.target.closest && e.target.closest('a[href^="#"]');
      if (!a) return;
      const hash = a.getAttribute("href");
      if (!hash || hash === "#") return;
      const id = hash.slice(1);
      let top = 0;
      if (id !== "top") {
        const el = document.getElementById(id);
        if (!el) return;
        const er = el.getBoundingClientRect();
        const sr = scroller.getBoundingClientRect();
        top = er.top - sr.top + scroller.scrollTop - NAV_OFFSET;
      }
      e.preventDefault();
      scroller.scrollTo({ top: Math.max(0, top), behavior: reduced ? "auto" : "smooth" });
    };
    scroller.addEventListener("click", onClick);
    return () => scroller.removeEventListener("click", onClick);
  }, [reduced]);

  // Proximity scroll-snap — JS-based for slow, smooth snapping
  React.useEffect(() => {
    if (reduced) return;
    const scroller = document.querySelector("#ft-scroll");
    if (!scroller) return;
    const SNAP_IDS = ["top", "work", "about", "contact"];
    const NAV_H = 48;
    const DEBOUNCE = 1250;
    const DURATION = 3000;
    const PROXIMITY = 0.35; // snap if within 35% of viewport
    let timer = 0;
    let animating = false;
    let raf = 0;

    function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }

    function cancelSnap() {
      cancelAnimationFrame(raf);
      animating = false;
      clearTimeout(timer);
      timer = setTimeout(onScrollEnd, DEBOUNCE);
    }

    function smoothScroll(target) {
      const start = scroller.scrollTop;
      const delta = target - start;
      if (Math.abs(delta) < 2) return;
      animating = true;
      let t0 = 0;
      const step = (ts) => {
        if (!t0) t0 = ts;
        const elapsed = ts - t0;
        const progress = Math.min(elapsed / DURATION, 1);
        scroller.scrollTop = start + delta * easeInOutCubic(progress);
        if (progress < 1) { raf = requestAnimationFrame(step); }
        else { animating = false; }
      };
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(step);
    }

    function getSnapTargets() {
      const sr = scroller.getBoundingClientRect();
      return SNAP_IDS.map((id) => {
        if (id === "top") return 0;
        const el = document.getElementById(id);
        if (!el) return null;
        return el.getBoundingClientRect().top - sr.top + scroller.scrollTop - NAV_H;
      }).filter((v) => v !== null);
    }

    function onScrollEnd() {
      if (animating) return;
      const y = scroller.scrollTop;
      const vh = scroller.clientHeight;
      const threshold = vh * PROXIMITY;
      const targets = getSnapTargets();
      let nearest = null;
      let nearestDist = Infinity;
      for (const t of targets) {
        const d = Math.abs(y - t);
        if (d < nearestDist) { nearestDist = d; nearest = t; }
      }
      if (nearest !== null && nearestDist > 1 && nearestDist < threshold) {
        smoothScroll(Math.max(0, nearest));
      }
    }

    const onScroll = () => {
      if (animating) return;
      clearTimeout(timer);
      timer = setTimeout(onScrollEnd, DEBOUNCE);
    };

    const onUserInput = () => { if (animating) cancelSnap(); };

    scroller.addEventListener("scroll", onScroll, { passive: true });
    scroller.addEventListener("wheel", onUserInput, { passive: true });
    scroller.addEventListener("touchstart", onUserInput, { passive: true });
    scroller.addEventListener("pointerdown", onUserInput, { passive: true });
    scroller.addEventListener("keydown", onUserInput, { passive: true });
    return () => {
      scroller.removeEventListener("scroll", onScroll);
      scroller.removeEventListener("wheel", onUserInput);
      scroller.removeEventListener("touchstart", onUserInput);
      scroller.removeEventListener("pointerdown", onUserInput);
      scroller.removeEventListener("keydown", onUserInput);
      clearTimeout(timer);
      cancelAnimationFrame(raf);
    };
  }, [reduced, splash]);

  const blob = { position: "absolute", left: 0, width: "100%", height: "60vh", pointerEvents: "none" };

  return (
    <React.Fragment>
      <div id="ft-scroll" style={{ height: "100vh", overflowY: "auto", background: "transparent" }}>
        <div style={{ position: "relative" }}>
          {/* Atmospheric blobs — absolute, covers entire page including footer */}
          {!reduced && (
            <div className="ft-atmos" aria-hidden="true" style={{ position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none", zIndex: 0 }}>
              <div className="ft-tail" style={{ ...blob, top: "2%", background: "radial-gradient(50% 60% at 78% 50%, rgba(31,155,255,0.18) 0%, rgba(69,226,210,0.06) 45%, transparent 100%)", transformOrigin: "70% 50%" }} />
              <div className="ft-plume" style={{ ...blob, top: "28%", background: "radial-gradient(45% 55% at 15% 50%, rgba(122,120,236,0.10) 0%, rgba(31,155,255,0.04) 42%, transparent 100%)" }} />
              <div className="ft-ember" style={{ ...blob, top: "52%", background: "radial-gradient(40% 50% at 80% 50%, rgba(69,226,210,0.12) 0%, rgba(122,224,255,0.04) 40%, transparent 100%)" }} />
              <div className="ft-tail" style={{ ...blob, top: "42%", background: "radial-gradient(45% 50% at 25% 50%, rgba(31,155,255,0.10) 0%, rgba(69,226,210,0.04) 44%, transparent 100%)", transformOrigin: "30% 50%" }} />
              <div className="ft-plume" style={{ ...blob, top: "72%", background: "radial-gradient(50% 55% at 70% 50%, rgba(31,155,255,0.14) 0%, rgba(69,226,210,0.05) 40%, transparent 100%)" }} />
              <div className="ft-ember" style={{ ...blob, top: "88%", background: "radial-gradient(40% 45% at 30% 50%, rgba(122,120,236,0.08) 0%, rgba(31,155,255,0.03) 42%, transparent 100%)" }} />
            </div>
          )}
          <Nav onHome={() => setActive(null)} />
          <main>
            <Hero />
            <ProjectGrid onOpen={setActive} />
            <About />
            <Contact />
          </main>
          <Footer />
        </div>
      </div>
      {!reduced && <CursorGlow />}
      <BottomDock />
      <MorphName />
      <CaseStudy project={active} onClose={() => setActive(null)} />
      {splash && <Splash onDone={endSplash} />}
    </React.Fragment>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
