// Cascade reveal primitive — fade-up + light blur-in, staggered.
// Uses IntersectionObserver so each section's entrance triggers when it scrolls into view.
const { useEffect, useRef, useState, createContext, useContext } = React;

const RevealCtx = createContext({ register: () => 0 });

function RevealGroup({ children, stagger = 120, baseDelay = 0, threshold = 0.15, once = true, style, ...rest }) {
  const ref = useRef(null);
  const [active, setActive] = useState(false);
  const counter = useRef(0);

  useEffect(() => {
    if (!ref.current) return;
    const node = ref.current;

    // Synchronous check: if already in viewport at mount, activate immediately.
    const rect = node.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (rect.top < vh && rect.bottom > 0) {
      setActive(true);
      if (once) return;
    }

    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setActive(true);
            if (once) io.disconnect();
          } else if (!once) {
            setActive(false);
          }
        });
      },
      { threshold, rootMargin: "0px 0px -10% 0px" }
    );
    io.observe(node);

    // Belt-and-braces fallback in case IO never fires (some browsers / edge cases).
    const fallback = setTimeout(() => setActive(true), 800);

    return () => { io.disconnect(); clearTimeout(fallback); };
  }, [threshold, once]);

  // Reset child counter on each render
  counter.current = 0;
  const register = () => {
    const i = counter.current;
    counter.current += 1;
    return baseDelay + i * stagger;
  };

  return (
    <RevealCtx.Provider value={{ active, register }}>
      <div ref={ref} style={style} {...rest}>{children}</div>
    </RevealCtx.Provider>
  );
}

function Reveal({ children, as: Tag = "div", delay, distance = 16, blur = 6, duration = 1100, style, ...rest }) {
  const ctx = useContext(RevealCtx);
  const myDelay = useRef(null);
  if (myDelay.current === null) {
    myDelay.current = typeof delay === "number" ? delay : ctx.register();
  }
  const active = ctx.active;
  const s = {
    transition: `opacity ${duration}ms ${BM.ease}, transform ${duration}ms ${BM.ease}, filter ${duration}ms ${BM.ease}`,
    transitionDelay: `${myDelay.current}ms`,
    opacity: active ? 1 : 0,
    transform: active ? "translateY(0)" : `translateY(${distance}px)`,
    filter: active ? "blur(0px)" : `blur(${blur}px)`,
    willChange: "opacity, transform, filter",
    ...style,
  };
  return <Tag style={s} {...rest}>{children}</Tag>;
}

window.RevealGroup = RevealGroup;
window.Reveal = Reveal;
