// Shared primitives

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

// Reveal on scroll using IntersectionObserver
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add('is-visible');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -60px 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return ref;
}

function Reveal({ children, delay = 0, as: Tag = 'div', style = {}, ...rest }) {
  const ref = useReveal();
  return (
    <Tag
      ref={ref}
      className={(rest.className || '') + ' reveal'}
      style={{ transitionDelay: `${delay}ms`, ...style }}
      {...rest}
    >
      {children}
    </Tag>
  );
}

// Arrow glyphs
const ArrowRight = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 14 14" fill="none" aria-hidden>
    <path d="M2 7h10M8 3l4 4-4 4" stroke="currentColor" strokeWidth="1.3" strokeLinecap="square" strokeLinejoin="miter"/>
  </svg>
);
const ArrowDown = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 14 14" fill="none" aria-hidden>
    <path d="M7 2v10M3 8l4 4 4-4" stroke="currentColor" strokeWidth="1.3" strokeLinecap="square" strokeLinejoin="miter"/>
  </svg>
);

// Buttons
const btnStyles = {
  base: {
    display: 'inline-flex',
    alignItems: 'center',
    gap: 10,
    padding: '14px 22px',
    fontFamily: 'var(--sans)',
    fontSize: 14,
    letterSpacing: '0.01em',
    fontWeight: 500,
    borderRadius: 2,
    transition: 'all 200ms ease',
    whiteSpace: 'nowrap',
  },
  primary: {
    background: 'var(--ink)',
    color: 'var(--bg)',
  },
  ghost: {
    background: 'transparent',
    color: 'var(--ink)',
    border: '1px solid var(--rule-2)',
  },
  text: {
    padding: 0,
    color: 'var(--ink-2)',
    background: 'transparent',
    borderBottom: '1px solid var(--rule-2)',
    borderRadius: 0,
    paddingBottom: 4,
  },
};

function PrimaryBtn({ children, href, onClick, style, ...rest }) {
  const [hover, setHover] = useState(false);
  const s = {
    ...btnStyles.base,
    ...btnStyles.primary,
    ...(hover ? { background: 'var(--accent)', color: 'var(--bg)' } : {}),
    ...style,
  };
  const El = href ? 'a' : 'button';
  return (
    <El href={href} onClick={onClick} style={s}
        onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)} {...rest}>
      {children}
    </El>
  );
}

function GhostBtn({ children, href, onClick, style }) {
  const [hover, setHover] = useState(false);
  const s = {
    ...btnStyles.base,
    ...btnStyles.ghost,
    ...(hover ? { borderColor: 'var(--accent)', color: 'var(--accent)' } : {}),
    ...style,
  };
  const El = href ? 'a' : 'button';
  return (
    <El href={href} onClick={onClick} style={s}
        onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}>
      {children}
    </El>
  );
}

function TextLink({ children, href, onClick, style }) {
  const [hover, setHover] = useState(false);
  const s = {
    ...btnStyles.base,
    ...btnStyles.text,
    ...(hover ? { color: 'var(--accent)', borderColor: 'var(--accent)' } : {}),
    ...style,
  };
  const El = href ? 'a' : 'button';
  return (
    <El href={href} onClick={onClick} style={s}
        onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}>
      {children}
    </El>
  );
}

// Section wrapper with numeric label + eyebrow
function SectionHeader({ index, kicker, title, intro, id }) {
  return (
    <div id={id} style={{
      paddingTop: 120,
      paddingBottom: 48,
      borderTop: '1px solid var(--rule)',
    }}>
      <div>
        <Reveal>
          <div className="eyebrow" style={{ marginBottom: 28 }}>{kicker}</div>
        </Reveal>
        <Reveal delay={80}>
          <h2 style={{
            fontFamily: 'var(--serif)',
            fontWeight: 400,
            fontSize: 'clamp(40px, 5.4vw, 76px)',
            lineHeight: 1.02,
            letterSpacing: '-0.025em',
            margin: 0,
            maxWidth: '18ch',
            textWrap: 'balance',
          }}>
            {title}
          </h2>
        </Reveal>
        {intro && (
          <Reveal delay={160}>
            <p style={{
              marginTop: 28,
              maxWidth: 620,
              color: 'var(--ink-2)',
              fontSize: 17,
              lineHeight: 1.6,
            }}>{intro}</p>
          </Reveal>
        )}
      </div>
    </div>
  );
}

Object.assign(window, {
  Reveal, useReveal,
  ArrowRight, ArrowDown,
  PrimaryBtn, GhostBtn, TextLink,
  SectionHeader,
});
