// Shared primitives
const { useEffect, useRef, useState, useMemo, useCallback } = React;

function useIsMobile(breakpoint = 768) {
  const [isMobile, setIsMobile] = useState(() => window.innerWidth < breakpoint);
  useEffect(() => {
    const on = () => setIsMobile(window.innerWidth < breakpoint);
    window.addEventListener('resize', on, { passive: true });
    return () => window.removeEventListener('resize', on);
  }, [breakpoint]);
  return isMobile;
}

// Reveal on scroll
function Reveal({ children, delay = 0, as: Tag = 'div', className = '', style = {}, threshold = 0.14 }) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { setSeen(true); io.unobserve(el); }});
    }, { threshold, rootMargin: '0px 0px -60px 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <Tag ref={ref}
      className={`reveal ${seen ? 'in' : ''} ${className}`}
      style={{ transitionDelay: (delay || 0) + 'ms', ...style }}>
      {children}
    </Tag>
  );
}

// Placeholder image — striped diagonal with monospace label
function Placeholder({ label, tint, tall, ratio = '4/5', rounded = false, dark = false, style = {}, parallax = false, className = '' }) {
  const ref = useRef(null);
  useEffect(() => {
    if (!parallax) return;
    const el = ref.current; if (!el) return;
    let raf;
    function update() {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight;
      const mid = r.top + r.height/2;
      const off = (mid - vh/2) / vh; // -1..1 ish
      const img = el.querySelector('.ph-inner');
      if (img) img.style.transform = `translateY(${off * -24}px) scale(1.06)`;
      raf = requestAnimationFrame(update);
    }
    raf = requestAnimationFrame(update);
    return () => cancelAnimationFrame(raf);
  }, [parallax]);
  const bg = tint || '#e8d6c3';
  return (
    <div ref={ref} className={`ph ${dark?'ph-dark':''} ${className}`} style={{
      width: '100%',
      aspectRatio: ratio,
      overflow: 'hidden',
      position: 'relative',
      borderRadius: rounded ? '4px' : 0,
      background: `linear-gradient(135deg, ${bg} 0%, ${shade(bg,-6)} 100%)`,
      ...style
    }}>
      <div className="ph-inner" style={{
        position:'absolute', inset:'-6%',
        backgroundImage: `repeating-linear-gradient(135deg, ${shade(bg,-4)} 0 1px, transparent 1px 24px)`,
        transition: 'transform 0.4s ease-out',
      }}/>
      <div style={{
        position:'absolute', inset: 16,
        border: `1px solid ${shade(bg,-15)}`,
        opacity: 0.6,
      }}/>
      <span style={{position:'relative', zIndex: 1, color: dark ? '#a89a8f' : shade(bg,-40)}}>
        {label}
      </span>
    </div>
  );
}

function shade(hex, pct) {
  // simple hex shift
  const h = hex.replace('#','');
  const n = h.length === 3 ? h.split('').map(c=>c+c).join('') : h;
  const r = parseInt(n.slice(0,2),16), g = parseInt(n.slice(2,4),16), b = parseInt(n.slice(4,6),16);
  const f = (v) => Math.max(0, Math.min(255, Math.round(v + (pct*255/100))));
  return `#${[f(r),f(g),f(b)].map(v=>v.toString(16).padStart(2,'0')).join('')}`;
}

// Marquee / scroll strip
function Marquee({ items, speed = 40 }) {
  const list = [...items, ...items, ...items];
  return (
    <div style={{overflow:'hidden', borderTop:'1px solid var(--rule)', borderBottom:'1px solid var(--rule)', padding:'20px 0'}}>
      <div style={{
        display:'flex', gap: '72px',
        whiteSpace:'nowrap',
        animation: `marquee ${speed}s linear infinite`
      }}>
        {list.map((it, i) => (
          <span key={i} className="eyebrow" style={{display:'inline-flex', alignItems:'center', gap:'72px'}}>
            {it}
            <span style={{display:'inline-block', width:6, height:6, borderRadius:'50%', background:'var(--ink-3)'}}/>
          </span>
        ))}
      </div>
      <style>{`@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-33.33%); } }`}</style>
    </div>
  );
}

// Scroll progress
function ScrollProgress() {
  const [p, setP] = useState(0);
  useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement.scrollHeight - window.innerHeight;
      setP(Math.min(1, Math.max(0, window.scrollY / Math.max(1,h))));
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return (
    <div style={{position:'fixed', top:0, left:0, right:0, height:'2px', zIndex: 100, pointerEvents:'none'}}>
      <div style={{height:'100%', width: (p*100)+'%', background:'var(--ink)', transition:'width .1s linear'}}/>
    </div>
  );
}

// Use hash-based routing
function useHashRoute() {
  const [route, setRoute] = useState(() => parseHash(window.location.hash));
  useEffect(() => {
    const on = () => setRoute(parseHash(window.location.hash));
    window.addEventListener('hashchange', on);
    return () => window.removeEventListener('hashchange', on);
  }, []);
  const navigate = useCallback((path) => {
    window.location.hash = path;
    window.scrollTo({ top: 0, behavior: 'instant' });
  }, []);
  return [route, navigate];
}
function parseHash(h) {
  const s = (h || '').replace(/^#\/?/, '');
  if (!s) return { name: 'home' };
  const [page, slug] = s.split('/');
  return { name: page, slug };
}

Object.assign(window, { Reveal, Placeholder, Marquee, ScrollProgress, useHashRoute, shade, useIsMobile });
