// Shared.jsx — Rune, animation hooks, common primitives
const { useEffect, useRef, useState } = React;

// ── Rune mark ───────────────────────────────────────────────
function Rune({ size = 28, color = '#C94A1A', spin = false }) {
  const r = size / 2;
  const style = spin ? { animation: 'runeSpinAnim 12s linear infinite', transformOrigin: 'center' } : {};
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} fill="none" style={style}>
      <style>{`@keyframes runeSpinAnim { from{transform:rotate(0deg)} to{transform:rotate(360deg)} }`}</style>
      <circle cx={r} cy={r} r={r - 2} stroke={color} strokeWidth="1.5"/>
      <circle cx={r} cy={r} r={r * 0.62} stroke={color} strokeWidth="1.5"/>
      <circle cx={r} cy={r} r={r * 0.3} stroke={color} strokeWidth="1.5"/>
      <circle cx={r} cy={r} r={r * 0.1} fill={color}/>
      <line x1={r} y1={1.5} x2={r} y2={r * 0.38} stroke={color} strokeWidth="1.5"/>
      <line x1={r} y1={r * 1.62} x2={r} y2={size - 1.5} stroke={color} strokeWidth="1.5"/>
      <line x1={1.5} y1={r} x2={r * 0.38} y2={r} stroke={color} strokeWidth="1.5"/>
      <line x1={r * 1.62} y1={r} x2={size - 1.5} y2={r} stroke={color} strokeWidth="1.5"/>
    </svg>
  );
}

// ── Scroll-reveal hook ───────────────────────────────────────
function useReveal(threshold = 0.15) {
  const ref = useRef(null);
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (!('IntersectionObserver' in window)) {
      setVisible(true);
      return;
    }

    // Once the desktop columns collapse, some reveal wrappers become taller
    // than a phone viewport. A 15% intersection ratio can then be impossible,
    // leaving the homepage content permanently transparent after the film.
    const mobile = window.matchMedia('(max-width: 720px), (pointer: coarse)').matches;
    const effectiveThreshold = mobile ? Math.min(threshold, 0.01) : threshold;
    const obs = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) { setVisible(true); obs.unobserve(el); } },
      { threshold: effectiveThreshold, rootMargin: mobile ? '0px 0px 12% 0px' : '0px' }
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, []);
  return [ref, visible];
}

// ── Reveal wrapper ───────────────────────────────────────────
function Reveal({ children, delay = 0, direction = 'up', threshold = 0.15 }) {
  const [ref, visible] = useReveal(threshold);
  const translateMap = { up: 'translateY(32px)', down: 'translateY(-32px)', left: 'translateX(32px)', right: 'translateX(-32px)', none: 'none' };
  return (
    <div ref={ref} style={{
      transition: `opacity 0.7s ease ${delay}s, transform 0.7s ease ${delay}s`,
      opacity: visible ? 1 : 0,
      transform: visible ? 'none' : translateMap[direction],
    }}>{children}</div>
  );
}

// ── Orange divider band ──────────────────────────────────────
function Band() {
  return <div style={{ height: '4px', background: '#C94A1A', width: '100%', flexShrink: 0 }}></div>;
}

// ── Pre-headline label ───────────────────────────────────────
function PreHeadline({ children, light = false }) {
  return (
    <div style={{
      fontFamily: "'Syne','Lato',sans-serif", fontWeight: 600, fontSize: '11px',
      letterSpacing: '0.2em', textTransform: 'uppercase',
      color: light ? 'rgba(240,223,160,0.6)' : '#C94A1A',
      marginBottom: '14px',
    }}>{children}</div>
  );
}

// ── Section heading ──────────────────────────────────────────
function SectionHeading({ line1, line2, light = false }) {
  return (
    <div>
      <div style={{ fontFamily: "'Noto Serif JP',serif", fontWeight: 700, fontSize: 'clamp(30px,3vw,44px)', lineHeight: 1.15, color: light ? '#F0DFA0' : '#1A1410', marginBottom: line2 ? '4px' : 0 }}>{line1}</div>
      {line2 && <div style={{ fontFamily: "'Noto Serif JP',serif", fontWeight: 700, fontSize: 'clamp(30px,3vw,44px)', lineHeight: 1.15, color: '#C94A1A' }}>{line2}</div>}
    </div>
  );
}

// ── Kanji watermark ──────────────────────────────────────────
function Kanji({ char, style: extra = {}, size = 280 }) {
  return (
    <div style={{
      fontFamily: "'Noto Sans JP',sans-serif", fontWeight: 900, fontSize: `${size}px`,
      opacity: 0.055, pointerEvents: 'none', userSelect: 'none', lineHeight: 1,
      position: 'absolute', color: 'inherit',
      ...extra,
    }}>{char}</div>
  );
}

// ── Grain overlay class applied via inline pseudo-before trick ──
// We rely on the .grain class defined in index.html

// ── Button components ────────────────────────────────────────
function BtnPrimary({ children, onClick, small = false }) {
  const [hover, setHover] = useState(false);
  return (
    <button
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      onClick={onClick}
      style={{
        background: hover ? '#a83a12' : '#C94A1A', color: '#fff',
        fontFamily: "'Syne','Lato',sans-serif", fontWeight: 600,
        fontSize: small ? '11px' : '13px', letterSpacing: '0.06em',
        textTransform: 'uppercase', padding: small ? '10px 18px' : '14px 26px',
        border: 'none', borderRadius: 0, cursor: 'pointer',
        transition: 'background 0.2s',
      }}>{children}</button>
  );
}

function BtnOutline({ children, onClick, light = false, small = false }) {
  const [hover, setHover] = useState(false);
  const c = light ? '#F0DFA0' : '#C94A1A';
  return (
    <button
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      onClick={onClick}
      style={{
        background: hover ? (light ? 'rgba(240,223,160,0.1)' : 'rgba(201,74,26,0.08)') : 'transparent',
        color: c, fontFamily: "'Syne','Lato',sans-serif", fontWeight: 600,
        fontSize: small ? '11px' : '13px', letterSpacing: '0.06em',
        textTransform: 'uppercase', padding: small ? '8px 16px' : '12px 24px',
        border: `2px solid ${hover ? c : (light ? 'rgba(240,223,160,0.4)' : '#C94A1A')}`,
        borderRadius: 0, cursor: 'pointer', transition: 'all 0.2s',
      }}>{children}</button>
  );
}

// ── Pull quote ───────────────────────────────────────────────
function PullQuote({ children, light = false }) {
  return (
    <div style={{
      borderLeft: '3px solid #C94A1A', paddingLeft: '24px',
      fontFamily: "'Noto Serif JP',serif", fontSize: '18px',
      lineHeight: 1.6, color: light ? '#F0DFA0' : '#1A1410',
      fontStyle: 'italic',
    }}>{children}</div>
  );
}

// ── Stats strip ──────────────────────────────────────────────
function StatsRow({ stats, orange = false }) {
  return (
    <div className="stats-row" style={{ display: 'grid', gridTemplateColumns: `repeat(${stats.length},1fr)`, borderTop: orange ? 'none' : '1px solid #EDE8D8' }}>
      {stats.map((s, i) => (
        <div key={i} style={{
          padding: '40px 24px', textAlign: 'center',
          borderRight: i < stats.length - 1 ? `2px solid ${orange ? 'rgba(255,255,255,0.2)' : '#EDE8D8'}` : 'none',
          display: 'flex', flexDirection: 'column', alignItems: 'center',
        }}>
          <div style={{ fontFamily: "'Noto Serif JP',serif", fontWeight: 700, fontSize: 'clamp(36px,4vw,56px)', color: orange ? '#fff' : '#C94A1A', lineHeight: 1 }}>{s.num}</div>
          <div style={{ fontFamily: "'Syne','Lato',sans-serif", fontWeight: 500, fontSize: '12px', color: orange ? 'rgba(255,255,255,0.75)' : '#7A6F65', marginTop: '8px', letterSpacing: '0.04em', textTransform: 'uppercase' }}>{s.label}</div>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { Rune, useReveal, Reveal, Band, PreHeadline, SectionHeading, Kanji, BtnPrimary, BtnOutline, PullQuote, StatsRow });
