// Shared primitives for the Schoning.com site. Exported to window (Babel scripts
// don't share scope). Built on the Franz Schoning design system tokens.

function Icon({ name, size = 20, color, stroke = 2, style = {} }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!ref.current || !window.lucide) return;
    ref.current.innerHTML = '';
    const el = document.createElement('i');
    el.setAttribute('data-lucide', name);
    ref.current.appendChild(el);
    window.lucide.createIcons({ attrs: { width: size, height: size, 'stroke-width': stroke } });
  });
  return <span ref={ref} style={{ display: 'inline-flex', alignItems: 'center', color, ...style }} />;
}

function Eyebrow({ children, dark = false, style = {} }) {
  return (
    <div style={{
      fontFamily: 'var(--fs-font-body)', fontSize: 12, fontWeight: 600,
      letterSpacing: '0.16em', textTransform: 'uppercase',
      color: dark ? 'var(--fs-gold)' : 'var(--fs-gold-deep)',
      display: 'flex', alignItems: 'center', gap: 12, ...style,
    }}>
      <span style={{ width: 24, height: 2, background: 'var(--fs-gold)', flex: 'none' }} />
      {children}
    </div>
  );
}

// Forensic data annotation — tiny mono coordinate (brand ornament)
function DataTag({ children, style = {} }) {
  return (
    <span style={{
      fontFamily: 'var(--fs-font-mono)', fontSize: 11, fontWeight: 500,
      letterSpacing: '0.06em', fontVariantNumeric: 'tabular-nums',
      color: 'var(--fs-indigo-200)', ...style,
    }}>{children}</span>
  );
}

function Button({ variant = 'primary', size = 'md', children, href, icon, onClick, target, rel, style = {} }) {
  const cls = `fs-btn fs-btn--${variant}${size !== 'md' ? ' fs-btn--' + size : ''}`;
  const inner = (<>{children}{icon && <Icon name={icon} size={16} stroke={2.25} />}</>);
  const handle = (e) => {
    if (href && href.startsWith('#')) {
      e.preventDefault();
      const t = document.querySelector(href);
      if (t) t.scrollIntoView({ behavior: 'auto', block: 'start' });
    }
    if (onClick) onClick(e);
  };
  if (href) return <a className={cls} href={href} onClick={handle} target={target} rel={rel} style={style}>{inner}</a>;
  return <button className={cls} onClick={handle} style={style}>{inner}</button>;
}

// ---- Scroll-reveal manager (rAF + scroll, no IntersectionObserver) --------
// IO callbacks are unreliable in some preview sandboxes, so we check rects on
// a shared scroll/resize listener instead — robust everywhere.
const FS_reveal = (() => {
  const nodes = new Set();
  let scheduled = false;
  const reduce = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  function check() {
    scheduled = false;
    const vh = window.innerHeight || document.documentElement.clientHeight;
    nodes.forEach((node) => {
      const r = node.getBoundingClientRect();
      if (r.top < vh * 0.92 && r.bottom > 0) {
        node.classList.add('is-in');
        nodes.delete(node);
      }
    });
  }
  function schedule() {
    if (scheduled) return;
    scheduled = true;
    requestAnimationFrame(check);
  }
  function init() {
    if (init.done) return; init.done = true;
    window.addEventListener('scroll', schedule, { passive: true });
    window.addEventListener('resize', schedule, { passive: true });
  }
  return {
    add(node, delay) {
      if (reduce()) { node.classList.add('is-in'); return; }
      node.style.transitionDelay = delay + 'ms';
      nodes.add(node);
      init();
      schedule();
    },
    remove(node) { nodes.delete(node); },
  };
})();

function Reveal({ children, delay = 0, as = 'div', className = '', style = {} }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const node = ref.current;
    if (!node) return;
    FS_reveal.add(node, delay);
    return () => FS_reveal.remove(node);
  }, [delay]);
  const Tag = as;
  return <Tag ref={ref} className={`reveal ${className}`} style={style}>{children}</Tag>;
}

// Section heading block — eyebrow + serif H2 + optional lede
function SectionHead({ eyebrow, dark = false, title, lede, align = 'left', maxWidth = 680, style = {} }) {
  return (
    <div style={{ maxWidth, marginLeft: align === 'center' ? 'auto' : 0, marginRight: align === 'center' ? 'auto' : 0, textAlign: align, ...style }}>
      <Eyebrow dark={dark} style={{ justifyContent: align === 'center' ? 'center' : 'flex-start' }}>{eyebrow}</Eyebrow>
      <h2 style={{
        fontFamily: 'var(--fs-font-display)', fontWeight: 700, fontSize: 'var(--fs-step-h2)',
        lineHeight: 1.18, letterSpacing: '-0.01em', margin: '18px 0 0',
        color: dark ? 'var(--fs-pearl)' : 'var(--fs-ink)', textWrap: 'balance',
      }}>{title}</h2>
      {lede && (
        <p style={{
          fontFamily: 'var(--fs-font-body)', fontSize: 'var(--fs-step-body-lg)', lineHeight: 1.7,
          margin: '18px 0 0', color: dark ? 'var(--fs-indigo-200)' : 'var(--fs-fg-muted)', textWrap: 'pretty',
        }}>{lede}</p>
      )}
    </div>
  );
}

Object.assign(window, { Icon, Eyebrow, DataTag, Button, Reveal, SectionHead });
