// ui.jsx — primitives: custom cursor, scroll progress, marquee, reveal hook.

// ----- Custom cursor (dot + ring) ------------------------------------
function Cursor() {
  const ring = React.useRef(null);
  const dot = React.useRef(null);
  React.useEffect(() => {
    // Hide on touch / no-hover devices
    if (matchMedia('(hover: none)').matches) return;

    let mx = window.innerWidth/2, my = window.innerHeight/2;
    let rx = mx, ry = my;
    const onMove = (e) => { mx = e.clientX; my = e.clientY; if (dot.current) dot.current.style.transform = `translate(${mx}px, ${my}px) translate(-50%,-50%)`; };
    window.addEventListener('mousemove', onMove);

    let rafId;
    const tick = () => {
      rx += (mx - rx) * 0.18;
      ry += (my - ry) * 0.18;
      if (ring.current) ring.current.style.transform = `translate(${rx}px, ${ry}px) translate(-50%,-50%)`;
      rafId = requestAnimationFrame(tick);
    };
    tick();

    const setHover = (on) => {
      if (ring.current) ring.current.classList.toggle('hover', on);
      document.body.classList.toggle('hover', on);
    };
    const enterFn = () => setHover(true);
    const leaveFn = () => setHover(false);
    const bind = () => {
      document.querySelectorAll('a, button, [data-hover]').forEach(el => {
        el.addEventListener('mouseenter', enterFn);
        el.addEventListener('mouseleave', leaveFn);
      });
    };
    bind();
    // Rebind every 2s in case DOM mutates
    const iv = setInterval(bind, 1500);

    return () => {
      window.removeEventListener('mousemove', onMove);
      cancelAnimationFrame(rafId);
      clearInterval(iv);
    };
  }, []);
  return (
    <React.Fragment>
      <div ref={ring} className="cursor-ring"></div>
      <div ref={dot} className="cursor-dot"></div>
    </React.Fragment>
  );
}
window.Cursor = Cursor;

// ----- Scroll progress bar -------------------------------------------
function ScrollProgress() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement.scrollHeight - window.innerHeight;
      const p = h > 0 ? (window.scrollY / h) * 100 : 0;
      if (ref.current) ref.current.style.width = p + '%';
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return <div ref={ref} className="scroll-prog"></div>;
}
window.ScrollProgress = ScrollProgress;

// ----- Marquee --------------------------------------------------------
function Marquee({ items, dur = '38s', sep = '·', size = 16, color, bg, weight = 600, italic = false, paddingY = 14, neon = false }) {
  // Duplicate items enough to fill width even at small content
  const elements = [];
  for (let r = 0; r < 4; r++) {
    elements.push(
      <div key={r} className="marquee-track" style={{ animationDuration: dur }}>
        {items.map((it, i) => (
          <React.Fragment key={i}>
            <span style={{
              fontFamily: 'Archivo, sans-serif',
              fontWeight: weight,
              fontSize: size,
              letterSpacing: '0.02em',
              textTransform: 'uppercase',
              color: color || (neon ? 'var(--neon)' : 'var(--paper)') }}>{it}</span>
            <span style={{
              color: neon ? 'var(--neon)' : 'var(--ink-soft)',
              fontSize: size, fontFamily: 'Archivo, sans-serif', fontWeight: 800 }}>{sep}</span>
          </React.Fragment>
        ))}
      </div>
    );
  }
  return (
    <div className="marquee" style={{ background: bg || 'transparent', padding: `${paddingY}px 0` }}>
      {elements}
    </div>
  );
}
window.Marquee = Marquee;

// ----- Reveal on scroll ----------------------------------------------
function useReveal() {
  React.useEffect(() => {
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('in'); });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    document.querySelectorAll('.reveal:not(.in)').forEach(el => obs.observe(el));
    return () => obs.disconnect();
  });
}
window.useReveal = useReveal;

// ----- Section helper -------------------------------------------------
function SectionEyebrow({ num, label, color }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 18, marginBottom: 28 }}>
      <span className="mono" style={{ fontSize: 13, color: color || 'var(--neon)', fontWeight: 600, letterSpacing: '0.12em' }}>
        // {num}
      </span>
      <span style={{ height: 1, flex: 1, background: 'rgba(242,240,234,0.18)' }}></span>
      <span className="eyebrow" style={{ color: color || 'var(--ink-soft)' }}>{label}</span>
    </div>
  );
}
window.SectionEyebrow = SectionEyebrow;
