// Primitives — icons, small UI atoms
const { useState, useEffect, useRef, useCallback, useMemo } = React;

const Icon = ({ name, size = 16 }) => {
  const s = size;
  const stroke = { fill: 'none', stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'arrow':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><path d="M5 12h14M13 5l7 7-7 7"/></svg>);
    case 'arrow-left':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><path d="M19 12H5M11 5l-7 7 7 7"/></svg>);
    case 'arrow-right':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><path d="M5 12h14M13 5l7 7-7 7"/></svg>);
    case 'check':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><path d="M5 12l5 5L20 7"/></svg>);
    case 'instagram':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><rect x="3" y="3" width="18" height="18" rx="4"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r=".6" fill="currentColor"/></svg>);
    case 'mail':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><rect x="3" y="5" width="18" height="14" rx="1"/><path d="M3 7l9 6 9-6"/></svg>);
    case 'phone':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><path d="M5 4h3l2 5-2 1a11 11 0 0 0 6 6l1-2 5 2v3a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2z"/></svg>);
    case 'map':
      return (<svg width={s} height={s} viewBox="0 0 24 24" {...stroke}><path d="M12 22s8-7.5 8-13a8 8 0 1 0-16 0c0 5.5 8 13 8 13z"/><circle cx="12" cy="9" r="3"/></svg>);
    case 'whatsapp':
      return (<svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><path d="M12.02 2C6.5 2 2.02 6.48 2.02 12c0 1.85.5 3.58 1.36 5.07L2 22l5.08-1.33A9.94 9.94 0 0 0 12.02 22C17.53 22 22 17.52 22 12S17.53 2 12.02 2zm0 18.2c-1.62 0-3.13-.44-4.43-1.2l-.32-.19-3.02.79.81-2.94-.2-.3A8.17 8.17 0 0 1 3.82 12c0-4.53 3.68-8.2 8.2-8.2 4.52 0 8.2 3.67 8.2 8.2 0 4.52-3.68 8.2-8.2 8.2zm4.5-6.13c-.25-.12-1.47-.72-1.69-.81-.23-.08-.4-.12-.56.12-.17.25-.64.81-.78.97-.15.17-.29.19-.53.06-.25-.12-1.05-.39-2-1.23-.74-.66-1.24-1.47-1.39-1.72-.14-.25-.02-.38.11-.5.11-.11.25-.29.37-.43.12-.15.16-.25.25-.41.08-.17.04-.31-.02-.43-.06-.12-.56-1.35-.77-1.85-.2-.48-.4-.42-.56-.42-.14-.01-.31-.01-.48-.01a.93.93 0 0 0-.67.31c-.23.25-.87.85-.87 2.07 0 1.22.89 2.4 1.01 2.56.12.17 1.75 2.67 4.24 3.74.59.26 1.05.41 1.41.52.59.19 1.13.16 1.56.1.48-.07 1.47-.6 1.67-1.18.21-.58.21-1.08.15-1.18-.06-.1-.23-.16-.48-.28z"/></svg>);
    default: return null;
  }
};

const Reveal = ({ children, delay = 0, className = '' }) => {
  const ref = useRef(null);
  const [v, setV] = useState(false);
  useEffect(() => {
    if (typeof IntersectionObserver === 'undefined') { setV(true); return; }
    const el = ref.current;
    if (!el) { setV(true); return; }
    // If element is already in viewport on mount, reveal immediately
    const r = el.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (r.top < vh && r.bottom > 0) { setV(true); return; }
    const obs = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setV(true); obs.disconnect(); }
    }, { threshold: 0, rootMargin: '0px 0px -80px 0px' });
    obs.observe(el);
    // Safety fallback: always show after 1.2s
    const t = setTimeout(() => setV(true), 1200);
    return () => { obs.disconnect(); clearTimeout(t); };
  }, []);
  return (
    <div ref={ref} className={className} style={{
      opacity: v ? 1 : 0,
      transform: v ? 'translateY(0)' : 'translateY(24px)',
      transition: `opacity .9s var(--ease) ${delay}ms, transform .9s var(--ease) ${delay}ms`
    }}>{children}</div>
  );
};

const Logo = ({ color = 'var(--forest)' }) => (
  <div className="logo" style={{ color }}>
    <span>Face</span><span className="ital">by</span><span>OXY</span><span className="dot"></span>
  </div>
);

Object.assign(window, { Icon, Reveal, Logo, useState, useEffect, useRef, useCallback, useMemo });
