// heritage/atoms.jsx
// Shared atoms, fonts, theming, reveal hook.

const TYPE_PAIRS = {
  classic:   { display: '"Cormorant Garamond", "EB Garamond", Georgia, serif', body: '"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif' },
  editorial: { display: '"Fraunces", "PP Editorial New", Georgia, serif',       body: '"Inter Tight", "Inter", -apple-system, system-ui, sans-serif' },
  stately:   { display: '"Cormorant Garamond", "EB Garamond", Georgia, serif',  body: '"Manrope", -apple-system, system-ui, sans-serif' },
};
const MONO = '"JetBrains Mono", ui-monospace, "SF Mono", monospace';

const DENSITY = {
  cozy:    { unit: 0.85 },
  regular: { unit: 1 },
  airy:    { unit: 1.2 },
};

const ACCENT_INTENSITY = {
  muted:    '#8a4f3f',
  standard: '#7a2e1f',
  vivid:    '#a01a08',
};

// Palette tokens for the Heritage direction. Accent overridden by tweak.
const useHeritageTheme = (tweaks) => {
  const pair = TYPE_PAIRS[tweaks.typePair] || TYPE_PAIRS.classic;
  const den = (DENSITY[tweaks.density] || DENSITY.regular).unit;
  return {
    ink:      '#1f1a14',
    cream:    '#f5efe4',
    sand:     '#e8dcc4',
    oxblood:  ACCENT_INTENSITY[tweaks.accent] || ACCENT_INTENSITY.standard,
    gilt:     '#c89a6a',
    moss:     '#3a4a36',
    serif:    pair.display,
    sans:     pair.body,
    mono:     MONO,
    den,
    // density-scaled spacing helper
    sp: (n) => Math.round(n * den),
  };
};

// ─── primitives ─────────────────────────────────────────────────

function Caps({ children, size = 11, color, ls = 0.18, weight = 500, style, font }) {
  return (
    <span style={{
      fontFamily: font || 'inherit',
      fontSize: size, fontWeight: weight,
      letterSpacing: `${ls}em`, textTransform: 'uppercase',
      color: color || 'inherit',
      ...style,
    }}>{children}</span>
  );
}

// Ornamental rule — diamond between hairlines.
function Rule({ color = '#1f1a14', w = 60, opacity = 0.5, style }) {
  return (
    <div style={{ opacity, ...style }}>
      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
        <span style={{ width: w, height: 1, background: color, display: 'block' }} />
        <svg width="6" height="6" viewBox="0 0 6 6"><polygon points="3,0.5 5.5,3 3,5.5 0.5,3" fill={color} /></svg>
        <span style={{ width: w, height: 1, background: color, display: 'block' }} />
      </span>
    </div>
  );
}

// Wordmark — three-tier emblem: "Little England" italic serif / "Grand" Pinyon Script / "—— HOTEL ——" caps
function Wordmark({ size = 22, color = '#1f1a14', accentColor, giltColor = '#c89a6a', leColor = '#f5efe4', align = 'center' }) {
  const acc = accentColor || color;
  const rule = size * 0.62;
  return (
    <div style={{ lineHeight: 1, color, display: 'inline-flex', flexDirection: 'column', alignItems: align === 'center' ? 'center' : 'flex-start' }}>
      <div style={{
        fontFamily: 'var(--font-serif)', fontSize: size * 0.7 + 10, fontWeight: 500,
        fontStyle: 'italic', letterSpacing: '0.08em', color: leColor, whiteSpace: 'nowrap',
      }}>Little England</div>
      <div style={{
        fontFamily: 'var(--font-script)', fontSize: size * 2.6,
        lineHeight: 0.86, color: acc, marginTop: size * 0.2, fontWeight: 400,
        marginLeft: '0.08em',
      }}>Grand</div>
      <div style={{ display: 'flex', alignItems: 'center', gap: size * 0.32, marginTop: size * 0.18 }}>
        <span style={{ width: rule, height: 1, background: 'currentColor', opacity: 0.4 }} />
        <span style={{
          fontFamily: 'var(--font-sans)', fontSize: size * 0.36, fontWeight: 500,
          letterSpacing: '0.42em', textIndent: '0.42em', textTransform: 'uppercase',
          color, whiteSpace: 'nowrap',
        }}>Hotel</span>
        <span style={{ width: rule, height: 1, background: 'currentColor', opacity: 0.4 }} />
      </div>
    </div>
  );
}

// ─── scroll reveal ──────────────────────────────────────────────
// Stamps a data-reveal attribute that fades up once on intersect.
// Single observer keeps cost low even with many elements.

function useRevealAll(deps = []) {
  React.useEffect(() => {
    const els = document.querySelectorAll('[data-reveal]');
    if (!els.length) return;
    els.forEach((el) => {
      if (!el.classList.contains('rv-init')) {
        el.classList.add('rv-init');
      }
    });
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add('rv-in');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, deps);
}

// Inject reveal CSS once
if (typeof document !== 'undefined' && !document.getElementById('rv-style')) {
  const s = document.createElement('style');
  s.id = 'rv-style';
  s.textContent = `
    :root { --font-script: "Pinyon Script", cursive; }
    [data-reveal].rv-init { opacity: 0; transform: translateY(18px); transition: opacity .9s cubic-bezier(.2,.7,.2,1), transform .9s cubic-bezier(.2,.7,.2,1); }
    [data-reveal][data-reveal-delay="1"].rv-init { transition-delay: 60ms; }
    [data-reveal][data-reveal-delay="2"].rv-init { transition-delay: 120ms; }
    [data-reveal][data-reveal-delay="3"].rv-init { transition-delay: 200ms; }
    [data-reveal][data-reveal-delay="4"].rv-init { transition-delay: 300ms; }
    [data-reveal].rv-in { opacity: 1; transform: translateY(0); }
    @media (prefers-reduced-motion: reduce) {
      [data-reveal].rv-init { opacity: 1; transform: none; transition: none; }
    }
  `;
  document.head.appendChild(s);
}

// Tiny utility: pretty date formatting for the booking widget.
function fmtDate(d) {
  if (!d) return '—';
  const day = d.toLocaleDateString('en-GB', { weekday: 'short' });
  const num = d.getDate();
  const mon = d.toLocaleDateString('en-GB', { month: 'short' });
  return `${day}, ${num} ${mon}`;
}

function addDays(d, n) { const x = new Date(d); x.setDate(x.getDate() + n); return x; }
function sameDay(a, b) { return a && b && a.toDateString() === b.toDateString(); }
function isBetween(d, a, b) { return d > a && d < b; }

// Small key-name badge for photo identification during demo/build phase.
function PhotoKey({ label }) {
  return null;
}

function useMobile(bp) {
  const breakpoint = bp || 768;
  const [mobile, setMobile] = React.useState(window.innerWidth < breakpoint);
  React.useEffect(() => {
    const fn = () => setMobile(window.innerWidth < breakpoint);
    window.addEventListener('resize', fn, { passive: true });
    return () => window.removeEventListener('resize', fn);
  }, [breakpoint]);
  return mobile;
}

Object.assign(window, {
  TYPE_PAIRS, DENSITY, ACCENT_INTENSITY, MONO,
  useHeritageTheme, Caps, Rule, Wordmark,
  useRevealAll, fmtDate, addDays, sameDay, isBetween, useMobile, PhotoKey,
});
