// Scroll-reveal + tiny motion helpers used throughout the site.

const { useEffect, useRef, useState } = React;

// ── Hook: detect when element scrolls into view ─────────────────────
function useInView(options = {}) {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    if (!ref.current) return;
    if (visible) return; // sticky — once revealed, stay revealed
    const io = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) setVisible(true);
    }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px', ...options });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [visible]);

  return [ref, visible];
}

// ── Reveal wrapper: fade + translate up on scroll ───────────────────
function Reveal({ children, as = 'div', direction = 'up', delay = 0, className = '', style = {}, ...rest }) {
  const [ref, vis] = useInView();
  const Tag = as;
  const dirClass =
    direction === 'left'  ? 'reveal reveal--left' :
    direction === 'right' ? 'reveal reveal--right' :
    direction === 'scale' ? 'reveal reveal--scale' :
    direction === 'fade'  ? 'reveal reveal--fade' :
                            'reveal';
  return (
    <Tag
      ref={ref}
      className={`${dirClass} ${vis ? 'is-visible' : ''} ${className}`}
      style={{ transitionDelay: `${delay}ms`, ...style }}
      {...rest}
    >{children}</Tag>
  );
}

// ── Stagger a list of children with incrementing delays ─────────────
function Stagger({ children, step = 90, direction = 'up', className = '', ...rest }) {
  return (
    <div className={className} {...rest}>
      {React.Children.map(children, (child, i) =>
        <Reveal direction={direction} delay={i * step}>{child}</Reveal>
      )}
    </div>
  );
}

// ── Animated counter (for stats like "80+") ─────────────────────────
function CountUp({ to = 100, suffix = '', duration = 1400, start = 0 }) {
  const [ref, vis] = useInView();
  const [n, setN] = useState(start);

  useEffect(() => {
    if (!vis) return;
    const t0 = performance.now();
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - t0) / duration);
      // ease-out cubic
      const eased = 1 - Math.pow(1 - p, 3);
      setN(Math.round(start + (to - start) * eased));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [vis, to, duration, start]);

  return <span ref={ref}>{n}{suffix}</span>;
}

Object.assign(window, { useInView, Reveal, Stagger, CountUp });
