/* global React */

// ─────────────────────────────────────────────────────────────
// FadeIn — Intersection-observer fade + rise (40px, 800ms)
// ─────────────────────────────────────────────────────────────
function FadeIn({ children, delay = 0, y = 40, style = {}, as: Tag = 'div' }) {
  const [shown, setShown] = React.useState(false);

  React.useEffect(() => {
    const t = setTimeout(() => setShown(true), delay + 40);
    return () => clearTimeout(t);
  }, [delay]);

  return (
    <Tag style={{
      ...style,
      opacity: shown ? 1 : 0,
      transform: shown ? 'translateY(0)' : `translateY(${y}px)`,
      transition: `opacity 900ms cubic-bezier(.19,1,.22,1), transform 900ms cubic-bezier(.19,1,.22,1)`,
      willChange: 'opacity, transform',
    }}>
      {children}
    </Tag>
  );
}

// ─────────────────────────────────────────────────────────────
// KenBurns — slow scale + drift on a background-image div.
// ─────────────────────────────────────────────────────────────
function KenBurns({ src, duration = 24, from = 'scale(1) translate(0,0)', to = 'scale(1.08) translate(-1.5%, -1%)', style = {} }) {
  const animName = React.useMemo(() => 'kb_' + Math.random().toString(36).slice(2, 9), []);
  return (
    <>
      <style>{`
        @keyframes ${animName} {
          0%   { transform: ${from}; }
          100% { transform: ${to}; }
        }
      `}</style>
      <div style={{
        position: 'absolute', inset: 0,
        background: `url(${src}) center/cover no-repeat`,
        animation: `${animName} ${duration}s ease-out forwards`,
        willChange: 'transform',
        ...style,
      }}/>
    </>
  );
}

// ─────────────────────────────────────────────────────────────
// Parallax — slow vertical drift on scroll.
// ─────────────────────────────────────────────────────────────
function Parallax({ children, speed = 0.15, style = {} }) {
  const ref = React.useRef(null);
  const [offset, setOffset] = React.useState(0);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        raf = 0;
        const rect = el.getBoundingClientRect();
        const vh = window.innerHeight || 900;
        // Distance of element center from viewport center, normalized
        const centerDelta = (rect.top + rect.height / 2) - vh / 2;
        setOffset(-centerDelta * speed);
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => {
      window.removeEventListener('scroll', onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, [speed]);

  return (
    <div ref={ref} style={{ overflow: 'hidden', position: 'relative', ...style }}>
      <div style={{
        position: 'absolute', inset: '-8% 0', // overflow top/bottom to allow drift
        transform: `translate3d(0, ${offset}px, 0)`,
        willChange: 'transform',
      }}>
        {children}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// InkRule — the SIGNATURE detail. A hand-drawn-feeling hairline
// with a tiny "D" monogram cartouche at the break. Appears between
// sections and inside section headers. This is the thing readers
// will remember.
// ─────────────────────────────────────────────────────────────
function InkRule({ color = 'var(--ink-900)', opacity = 1, width = '100%', align = 'center' }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 18,
      width: width, justifyContent: align === 'center' ? 'center' : align,
      opacity,
    }}>
      <div style={{
        flex: 1, height: 1, background: color,
        maxWidth: 240,
      }}/>
      <svg width="28" height="28" viewBox="0 0 28 28" style={{ flexShrink: 0 }}>
        {/* Thin cartouche diamond around D */}
        <g stroke={color} strokeWidth="0.8" fill="none">
          <path d="M14 2 L26 14 L14 26 L2 14 Z" />
        </g>
        <text x="14" y="18.2" textAnchor="middle"
          style={{
            fontFamily: 'var(--font-display)', fontStyle: 'italic',
            fontSize: 13, fontWeight: 400,
          }}
          fill={color}>D</text>
      </svg>
      <div style={{
        flex: 1, height: 1, background: color,
        maxWidth: 240,
      }}/>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SectionHeader — a reusable editorial header with the InkRule + eyebrow + big serif.
// ─────────────────────────────────────────────────────────────
function SectionHeader({ eyebrow, children, dark = false, align = 'center' }) {
  const titleColor = dark ? 'var(--cream-50)' : 'var(--ink-900)';
  const italicColor = dark ? 'rgba(251,248,242,0.62)' : 'var(--clay-700)';
  const eyebrowColor = dark ? 'rgba(251,248,242,0.55)' : 'var(--bronze-500)';
  const ruleColor = dark ? 'rgba(251,248,242,0.34)' : 'rgba(28,26,23,0.34)';
  return (
    <FadeIn style={{ textAlign: align }}>
      <div style={{ marginBottom: 28 }}>
        <InkRule color={ruleColor} align={align === 'left' ? 'flex-start' : 'center'}/>
      </div>
      {eyebrow && (
        <div style={{
          fontFamily: 'var(--font-body)', fontSize: 11,
          letterSpacing: '0.36em', textTransform: 'uppercase',
          color: eyebrowColor, marginBottom: 24,
        }}>{eyebrow}</div>
      )}
      <h2 style={{
        fontFamily: 'var(--font-display)',
        fontSize: 'clamp(2.2rem, 4vw, 3.6rem)',
        fontWeight: 300, lineHeight: 1.06, letterSpacing: '-0.022em',
        color: titleColor, margin: 0, textWrap: 'balance',
        fontFeatureSettings: '"ss02", "liga"',
      }}>
        {children}
      </h2>
    </FadeIn>
  );
}

// Helper: italic span for counter-lines
function I({ children, dark = false }) {
  return <span style={{
    fontStyle: 'italic',
    color: dark ? 'rgba(251,248,242,0.62)' : 'var(--clay-700)',
  }}>{children}</span>;
}

// ─────────────────────────────────────────────────────────────
// useIsMobile — viewport-width hook. Single 768px breakpoint.
// ─────────────────────────────────────────────────────────────
function useIsMobile(breakpoint = 768) {
  const [isMobile, setIsMobile] = React.useState(
    typeof window !== 'undefined' ? window.innerWidth < breakpoint : false
  );
  React.useEffect(() => {
    const onResize = () => setIsMobile(window.innerWidth < breakpoint);
    window.addEventListener('resize', onResize, { passive: true });
    return () => window.removeEventListener('resize', onResize);
  }, [breakpoint]);
  return isMobile;
}

Object.assign(window, { FadeIn, KenBurns, Parallax, InkRule, SectionHeader, I, useIsMobile });
