/* Axon.ps website kit — shared primitives. Exported to window for cross-file use. */

const AXON_PRODUCTS = [
  { id: 'plexus', name: 'Plexus', tagline: 'AI-powered scientific research platform',
    line: 'A workflow platform for researchers — AI-assisted writing, reference verification, and citation accuracy.',
    features: ['AI-assisted paper writing', 'Reference verification', 'Citation accuracy checking'], status: 'live' },
  { id: 'nowah', name: 'Nowah', tagline: 'Smart platform for municipalities & local councils',
    line: 'AI-powered updates on projects, grants and initiatives across Palestinian municipalities, with a full institution directory.',
    features: ['Municipality project tracking', 'Grant notifications', 'Institution database'], status: 'live' },
  { id: 'synap', name: 'Synap', tagline: 'Local AI infrastructure & workflow solutions',
    line: 'Run AI models on your own hardware. We supply specialized machines and build custom, sovereign workflows.',
    features: ['Local model deployment', 'Specialized hardware', 'Custom automation'], status: 'live' },
  { id: 'madar', name: 'Madar', tagline: 'Privacy-first VPN for mobile & desktop',
    line: 'A next-generation VPN built with privacy and performance at its core. Madar means "orbit".',
    features: ['Mobile & desktop apps', 'No-logs policy', 'High-speed servers'], status: 'soon' },
];

function Eyebrow({ children }) { return <span className="eyebrow">{children}</span>; }

function StatusChip({ status }) {
  return status === 'live'
    ? <span className="chip chip-live"><span className="dot"></span>Live</span>
    : <span className="chip chip-soon">Coming soon</span>;
}

function Button({ variant = 'signal', children, href = '#', onClick, type }) {
  const cls = 'btn btn-' + variant;
  if (type === 'submit' || onClick) return <button type={type || 'button'} className={cls} onClick={onClick}>{children}</button>;
  return <a className={cls} href={href}>{children}</a>;
}

/* Axon mark — recreation of components/AxonLogo.tsx, re-pigmented for the
   manuscript palette. Signal waveform replays on hover + on an idle cycle. */
function AxonMark({ size = 40, wordmark = false, theme = 'paper', tone }) {
  const ref = React.useRef(null);
  const onPaper = theme === 'paper';
  const ink = tone || (onPaper ? 'var(--ink-0)' : 'var(--night-text)');
  const play = () => {
    const el = ref.current; if (!el) return;
    el.style.transition = 'none'; el.style.strokeDashoffset = '180';
    void el.getBoundingClientRect();
    el.style.transition = 'stroke-dashoffset 0.9s var(--ease)';
    el.style.strokeDashoffset = '0';
  };
  React.useEffect(() => {
    const t = setTimeout(play, 300);
    const iv = setInterval(play, 9000);
    return () => { clearTimeout(t); clearInterval(iv); };
  }, []);
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: size * 0.32, cursor: 'pointer' }} onMouseEnter={play} aria-label="Axon">
      <svg width={size} height={size} viewBox="0 0 200 200" fill="none" style={{ flexShrink: 0 }} aria-hidden="true">
        {onPaper
          ? <circle cx="100" cy="100" r="88" fill="#1E1B16" />
          : <circle cx="100" cy="100" r="88" fill="none" stroke="#3A3225" strokeWidth="1.5" />}
        <circle cx="100" cy="100" r="80" fill="none" stroke={onPaper ? '#B0852E' : '#CDA24A'} strokeWidth="1.25" opacity="0.85" />
        <polyline ref={ref} points="20,100 36,100 46,100 56,78 66,122 76,60 86,116 96,100"
          stroke="#C24038" strokeWidth="7" strokeLinejoin="round" strokeLinecap="round" fill="none"
          style={{ strokeDasharray: 180, strokeDashoffset: 180 }} />
        <circle cx="96" cy="100" r="4.5" fill="#CDA24A" />
        <text x="132" y="120" fontSize="62" fontWeight="500" fill={onPaper ? '#F8F3E9' : '#EFE7D6'}
          fontFamily="var(--font-display)" textAnchor="middle" letterSpacing="1">AX</text>
      </svg>
      {wordmark && (
        <span style={{ display: 'inline-flex', alignItems: 'baseline', gap: size * 0.01 }}>
          <span style={{ fontFamily: 'var(--font-brand)', fontWeight: 800, fontSize: size * 0.6,
            letterSpacing: '-0.045em', color: ink, lineHeight: 1 }}>axon</span>
          <span style={{ fontFamily: 'var(--font-brand)', fontWeight: 700, fontSize: size * 0.6,
            letterSpacing: '-0.045em', color: 'var(--signal)', lineHeight: 1 }}>.ps</span>
        </span>
      )}
    </span>
  );
}

/* Open a product detail sheet from anywhere — decoupled event so hero, orbit and
   ecosystem (separate script files) all drive the same overlay. */
function openProduct(id, originEl) {
  window.dispatchEvent(new CustomEvent('axon:product', { detail: { id, origin: originEl || null } }));
}

/* Product lens — the real product logo unified inside one Axon frame.
   The img is zoomed slightly to crop each logo's mismatched native ring, then a
   single consistent ink hairline (+ faint gold inner) is drawn on top. This is
   how four different marks read as one coherent product system.
   Interactive by default: click / Enter / Space opens the product sheet. */
function ProductLens({ id, size = 64, live = true, dim = false, interactive = true, name }) {
  const Tag = interactive ? 'button' : 'span';
  const handlers = interactive ? {
    onClick: (e) => openProduct(id, e.currentTarget),
    'aria-haspopup': 'dialog',
    'aria-label': 'View ' + (name || id) + ' details',
    type: 'button',
  } : { 'aria-label': id + ' logo' };
  return (
    <Tag className={'plens' + (interactive ? ' plens-btn' : '')} {...handlers}
      style={{ position: 'relative', display: 'inline-flex', width: size, height: size, flexShrink: 0, opacity: dim ? 0.5 : 1 }}>
      <span style={{ position: 'absolute', inset: 0, borderRadius: '50%', overflow: 'hidden', background: '#fff' }}>
        <img src={'assets/products/' + id + '.svg'} alt="" style={{ width: '116%', height: '116%', margin: '-8%', display: 'block', filter: 'saturate(0.9)' }} />
      </span>
      <span className="plens-ring" style={{ position: 'absolute', inset: 0, borderRadius: '50%', border: '1.5px solid var(--ink-0)', pointerEvents: 'none' }}></span>
      <span style={{ position: 'absolute', inset: 3, borderRadius: '50%', border: '1px solid color-mix(in srgb, var(--gold) 55%, transparent)', pointerEvents: 'none' }}></span>
      {live && <span style={{ position: 'absolute', top: '6%', right: '6%', width: Math.max(7, size * 0.12), height: Math.max(7, size * 0.12), borderRadius: '50%', background: 'var(--signal)', border: '1.5px solid var(--paper-0)' }}></span>}
    </Tag>
  );
}

/* legacy letterform sigil — kept for the brand specimen card */
function Sigil({ id, letter, size = 56, live = true }) {
  return (
    <svg width={size} height={size} viewBox="0 0 200 200" aria-label={id + ' sigil'}>
      <circle cx="100" cy="100" r="88" fill="var(--paper-1)" stroke="var(--ink-0)" strokeWidth="2.5" />
      <circle cx="100" cy="100" r="78" fill="none" stroke="var(--gold)" strokeWidth="1.2" opacity="0.8" />
      <text x="100" y="130" fontFamily="var(--font-display)" fontSize="98" fontWeight="400"
        fill="var(--ink-0)" textAnchor="middle">{letter}</text>
      <circle cx="150" cy="64" r="7" fill={live ? 'var(--signal)' : 'var(--ink-2)'} />
    </svg>
  );
}

/* Signal divider — a hairline with a traveling crimson pulse */
function SignalDivider() {
  return (
    <div style={{ position: 'relative', height: 1, background: 'var(--ink-line)', margin: 'var(--sp-7) 0', overflow: 'visible' }}>
      <span style={{ position: 'absolute', top: -2, width: 5, height: 5, borderRadius: '50%',
        background: 'var(--signal)', boxShadow: '0 0 6px var(--signal-bright)',
        animation: 'travel 7s linear infinite' }}></span>
      <style>{`@keyframes travel { 0%{left:0;opacity:0} 8%{opacity:1} 92%{opacity:1} 100%{left:100%;opacity:0} }`}</style>
    </div>
  );
}

/* reveal-on-scroll hook — content is ALWAYS visible by default; JS only adds a
   subtle entrance. Bulletproof: if IO never fires (e.g. inside a scroll
   container), a failsafe timer reveals everything so nothing is ever stuck. */
function useReveal() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const nodes = Array.prototype.slice.call(el.querySelectorAll('.fade-up'));
    if (!nodes.length) return;
    // opt into the hidden pre-state only now that JS is running
    nodes.forEach(n => n.classList.add('pre'));
    const reveal = (n) => { n.classList.remove('pre'); n.classList.add('in'); };
    let io = null;
    if ('IntersectionObserver' in window) {
      io = new IntersectionObserver((es) => es.forEach(e => {
        if (e.isIntersecting) { reveal(e.target); io.unobserve(e.target); }
      }), { threshold: 0.08, rootMargin: '0px 0px -5% 0px' });
      nodes.forEach(n => io.observe(n));
    } else {
      nodes.forEach(reveal);
    }
    // failsafe — never leave content invisible
    const t = setTimeout(() => nodes.forEach(reveal), 1600);
    return () => { if (io) io.disconnect(); clearTimeout(t); };
  }, []);
  return ref;
}

/* canonical product detail copy (factual, no invented claims) */
const PRODUCT_DETAIL = {
  plexus: { name: 'Plexus', category: 'Scientific research platform',
    desc: 'AI-powered scientific research platform for researchers — writing support, reference verification, and citation accuracy.',
    soon: false, href: '/products/plexus' },
  nowah: { name: 'Nowah', category: 'Municipalities & local councils',
    desc: 'A platform for municipalities and local councils — project updates, grant tracking, and institutional information.',
    soon: false, reveal: true, href: '/products/nowah' },
  synap: { name: 'Synap', category: 'Local AI infrastructure',
    desc: 'Local AI infrastructure and workflow solutions — private model deployment, specialized hardware, and custom automation.',
    soon: false, href: '/products/synap' },
  madar: { name: 'Madar', category: 'Privacy-first VPN',
    desc: 'Privacy-first VPN for mobile and desktop — built around private, reliable access and performance.',
    soon: true, reveal: true, href: '/products/madar' },
};

Object.assign(window, { AXON_PRODUCTS, PRODUCT_DETAIL, Eyebrow, StatusChip, Button, AxonMark, Sigil, ProductLens, openProduct, SignalDivider, useReveal });
