// UI primitives & icons -------------------------------------------------
const { useState, useEffect, useRef, useMemo } = React;

// Tiny icon set (stroke-based, matches lucide weight)
const Icon = {
  Check:    (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 6 9 17l-5-5"/></svg>,
  X:        (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M18 6 6 18M6 6l12 12"/></svg>,
  ChevDown: (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m6 9 6 6 6-6"/></svg>,
  ChevRight:(p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m9 6 6 6-6 6"/></svg>,
  ArrowL:   (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 12H5M12 19l-7-7 7-7"/></svg>,
  ArrowRight:(p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M12 5l7 7-7 7"/></svg>,
  Search:   (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  Filter:   (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 5h18M6 12h12M10 19h4"/></svg>,
  Brain:    (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 4a3 3 0 0 0-3 3v0a3 3 0 0 0-3 3 3 3 0 0 0 2 2.82V14a3 3 0 0 0 3 3 3 3 0 0 0 3 3V4a2 2 0 0 0-2 0z"/><path d="M15 4a3 3 0 0 1 3 3v0a3 3 0 0 1 3 3 3 3 0 0 1-2 2.82V14a3 3 0 0 1-3 3 3 3 0 0 1-3 3"/></svg>,
  Edit:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M11 4H4v16h16v-7"/><path d="M18.5 2.5a2.1 2.1 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>,
  Trash:    (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/></svg>,
  Plus:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 5v14M5 12h14"/></svg>,
  Globe:    (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/></svg>,
  Mail:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></svg>,
  User:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M20 21a8 8 0 1 0-16 0"/><circle cx="12" cy="8" r="4"/></svg>,
  Info:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M12 8h.01M11 12h1v4h1"/></svg>,
  Sparkle:  (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 3v4M12 17v4M3 12h4M17 12h4M5.5 5.5l2.8 2.8M15.7 15.7l2.8 2.8M5.5 18.5l2.8-2.8M15.7 8.3l2.8-2.8"/></svg>,
  Star:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 2 15 9l7 1-5 5 1 7-6-3-6 3 1-7-5-5 7-1z"/></svg>,
  List:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><circle cx="4" cy="6" r="1"/><circle cx="4" cy="12" r="1"/><circle cx="4" cy="18" r="1"/></svg>,
  News:     (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 4h12a2 2 0 0 1 2 2v14H6a2 2 0 0 1-2-2Z"/><path d="M18 8h2a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2"/><line x1="8" y1="9" x2="14" y2="9"/><line x1="8" y1="13" x2="14" y2="13"/><line x1="8" y1="17" x2="12" y2="17"/></svg>,
  Shield:   (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 2 4 5v6c0 5 3.5 9 8 11 4.5-2 8-6 8-11V5Z"/></svg>,
  Brain:    (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 5a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V8a3 3 0 0 0-3-3Z"/><path d="M9 8a3 3 0 0 1-3 3M15 8a3 3 0 0 0 3 3M9 16a3 3 0 0 0-3-3M15 16a3 3 0 0 1 3-3"/></svg>,
  ExtLink:  (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M7 17 17 7"/><path d="M8 7h9v9"/></svg>,
  Columns:  (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16M15 4v16"/></svg>,
  Download: (p) => <svg width={p.size||16} height={p.size||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 3v12m0 0 4-4m-4 4-4-4"/><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"/></svg>,
};

// Button
function Button({ variant='default', size='md', className='', children, ...rest }) {
  const base = 'inline-flex items-center justify-center gap-1.5 font-medium rounded-md transition-colors disabled:opacity-50 disabled:pointer-events-none whitespace-nowrap';
  const sizes = { sm: 'text-sm px-3 py-1.5', md: 'text-sm px-3.5 py-2', lg: 'text-base px-4 py-2.5' };
  const variants = {
    default: 'bg-ink text-white hover:bg-black',
    ghost:   'text-ink hover:bg-gray-100',
    outline: 'border border-line text-ink hover:bg-gray-50',
    subtle:  'bg-gray-100 text-ink hover:bg-gray-200',
    brand:   'bg-brand-500 text-white hover:bg-brand-700',
    danger:  'text-red-700 hover:bg-red-50 border border-transparent hover:border-red-200',
    quiet:   'text-ink-muted hover:text-ink hover:bg-gray-100',
  };
  return <button className={`${base} ${sizes[size]} ${variants[variant]} ${className}`} {...rest}>{children}</button>;
}

// Sparkline — for match-rate trend. Renders line + area.
function Sparkline({ values = [], width = 480, height = 120, showAxis = true, stroke = '#3465E3', fill = 'rgba(52,101,227,0.08)' }) {
  if (values.length < 2) return null;
  const min = Math.min(...values) * 0.9;
  const max = Math.max(...values) * 1.05;
  const pad = 8;
  const w = width - pad*2;
  const h = height - pad*2;
  const pts = values.map((v, i) => {
    const x = pad + (i/(values.length-1)) * w;
    const y = pad + (1 - (v-min)/(max-min)) * h;
    return [x, y];
  });
  const path = pts.map((p,i) => (i===0?`M${p[0]},${p[1]}`:`L${p[0]},${p[1]}`)).join(' ');
  const area = `${path} L${pts[pts.length-1][0]},${pad+h} L${pts[0][0]},${pad+h} Z`;
  return (
    <svg width={width} height={height} className="overflow-visible">
      {showAxis && (
        <g>
          {[0,.25,.5,.75,1].map(t => (
            <line key={t} x1={pad} x2={pad+w} y1={pad + t*h} y2={pad + t*h} stroke="hsl(0 0% 92%)" strokeDasharray={t===0||t===1 ? '' : '2 3'} />
          ))}
        </g>
      )}
      <path d={area} fill={fill} />
      <path d={path} fill="none" stroke={stroke} strokeWidth="1.75" strokeLinejoin="round" strokeLinecap="round"/>
      {pts.map((p,i) => (
        <circle key={i} cx={p[0]} cy={p[1]} r={i===pts.length-1?3.5:2} fill={i===pts.length-1?stroke:'#fff'} stroke={stroke} strokeWidth="1.25"/>
      ))}
    </svg>
  );
}

// Bar series — for feedback counts
function BarSeries({ values = [], width = 480, height = 60, color = 'hsl(0 0% 82%)' }) {
  if (!values.length) return null;
  const max = Math.max(...values);
  const pad = 8;
  const w = width - pad*2;
  const barGap = 3;
  const barW = (w - barGap*(values.length-1)) / values.length;
  return (
    <svg width={width} height={height}>
      {values.map((v,i) => {
        const x = pad + i*(barW+barGap);
        const bh = (v/max) * (height - pad*2);
        const y = height - pad - bh;
        return <rect key={i} x={x} y={y} width={barW} height={bh} rx="1.5" fill={color}/>;
      })}
    </svg>
  );
}

// Toast
function useToasts() {
  const [toasts, setToasts] = useState([]);
  const push = (text, tone='default') => {
    const id = Math.random().toString(36).slice(2);
    setToasts(t => [...t, { id, text, tone }]);
    setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 3600);
  };
  const node = (
    <div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 flex flex-col gap-2 items-center pointer-events-none">
      {toasts.map(t => (
        <div key={t.id} className={`toast-in pointer-events-auto flex items-center gap-2 text-sm rounded-md border px-3.5 py-2.5 shadow-sm ${
          t.tone === 'positive' ? 'bg-white border-line text-ink' :
          t.tone === 'negative' ? 'bg-white border-line text-ink' :
          'bg-ink text-white border-ink'
        }`} style={{minWidth:280}}>
          {t.tone === 'positive' && <span className="h-1.5 w-1.5 rounded-full bg-emerald-500"/>}
          {t.tone === 'negative' && <span className="h-1.5 w-1.5 rounded-full bg-amber-500"/>}
          <span>{t.text}</span>
        </div>
      ))}
    </div>
  );
  return { push, node };
}

// Modal
function Modal({ open, onClose, children, width = 'max-w-lg' }) {
  if (!open) return null;
  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 fade-in" onClick={onClose}>
      <div className="absolute inset-0 bg-ink/30"/>
      <div className={`relative bg-white rounded-lg shadow-xl border border-line w-full ${width}`} onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>
  );
}

Object.assign(window, { Icon, Button, Sparkline, BarSeries, useToasts, Modal });
