// Shared components & icons for TeachCue
// Exports to window so other scripts can use.

const { useState, useEffect, useRef, useMemo } = React;

// ─────────────────────────────────────────────────────────────
// Icons — minimal SF-style strokes
// ─────────────────────────────────────────────────────────────
const I = {
  plus: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M12 5v14M5 12h14"/></svg>,
  back: (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||2} strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>,
  close: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M6 6l12 12M18 6l-12 12"/></svg>,
  chevR: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||2} strokeLinecap="round" strokeLinejoin="round"><path d="M9 6l6 6-6 6"/></svg>,
  chevD: (p) => <svg width={p.s||16} height={p.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||2} strokeLinecap="round"><path d="M6 9l6 6 6-6"/></svg>,
  record: (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="12" r="7"/></svg>,
  play: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>,
  pause: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="5" width="4" height="14" rx="1"/><rect x="14" y="5" width="4" height="14" rx="1"/></svg>,
  stop: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>,
  mic: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="3" width="6" height="12" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3"/></svg>,
  camera: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M4 7h3l2-2h6l2 2h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1z"/><circle cx="12" cy="13" r="4"/></svg>,
  flip: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M4 12a8 8 0 0 1 14-5l2 2M20 12a8 8 0 0 1-14 5l-2-2"/><path d="M20 4v5h-5M4 20v-5h5"/></svg>,
  image: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="9" cy="10" r="1.6"/><path d="M5 17l4.5-4.5 3 3L16 12l3 3"/></svg>,
  sparkle: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="currentColor"><path d="M12 3l1.8 4.2L18 9l-4.2 1.8L12 15l-1.8-4.2L6 9l4.2-1.8z"/><circle cx="19" cy="5" r="1.2"/><circle cx="5" cy="19" r="1.2"/></svg>,
  text: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||2} strokeLinecap="round"><path d="M5 7V5h14v2M12 5v14M9 19h6"/></svg>,
  folder: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z"/></svg>,
  share: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M12 3v13M7 8l5-5 5 5"/><path d="M5 13v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6"/></svg>,
  download: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M12 4v13M7 12l5 5 5-5"/><path d="M5 21h14"/></svg>,
  check: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||2.2} strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l4 4 10-10"/></svg>,
  dot: (p) => <svg width={p.s||4} height={p.s||4} viewBox="0 0 4 4"><circle cx="2" cy="2" r="2" fill="currentColor"/></svg>,
  more: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg>,
  wand: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M4 20l10-10M14 6l4 4"/><path d="M18 3l.5 1.5L20 5l-1.5.5L18 7l-.5-1.5L16 5l1.5-.5z"/></svg>,
  grid: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8}><rect x="4" y="4" width="7" height="7" rx="1.5"/><rect x="13" y="4" width="7" height="7" rx="1.5"/><rect x="4" y="13" width="7" height="7" rx="1.5"/><rect x="13" y="13" width="7" height="7" rx="1.5"/></svg>,
  list: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>,
  search: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.5-3.5"/></svg>,
  aspect916: (p) => <svg width={p.s||18} height={p.s||26} viewBox="0 0 18 26" fill="none" stroke="currentColor" strokeWidth={p.w||1.8}><rect x="1" y="1" width="16" height="24" rx="2.5"/></svg>,
  aspect169: (p) => <svg width={p.s||26} height={p.s||18} viewBox="0 0 26 18" fill="none" stroke="currentColor" strokeWidth={p.w||1.8}><rect x="1" y="1" width="24" height="16" rx="2.5"/></svg>,
  aspect11:  (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth={p.w||1.8}><rect x="1" y="1" width="18" height="18" rx="2.5"/></svg>,
  rotate: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M21 12a9 9 0 0 1-15.3 6.3L3 16"/><path d="M3 21v-5h5"/></svg>,
  duplicate: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3"/></svg>,
  trash: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M4 7h16M10 11v6M14 11v6"/><path d="M6 7l1 12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-12M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>,
  sliders: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M4 6h8M16 6h4M4 12h4M12 12h8M4 18h12M18 18h2"/><circle cx="14" cy="6" r="2" fill="currentColor" stroke="none"/><circle cx="10" cy="12" r="2" fill="currentColor" stroke="none"/><circle cx="16" cy="18" r="2" fill="currentColor" stroke="none"/></svg>,
  layer: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><path d="M12 3l9 5-9 5-9-5 9-5z"/><path d="M3 13l9 5 9-5M3 17l9 5 9-5"/></svg>,
  globe: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8}><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>,
  book: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round" strokeLinejoin="round"><path d="M4 5a2 2 0 0 1 2-2h13v16H7a3 3 0 0 0-3 3V5z"/><path d="M4 19a3 3 0 0 1 3-3h12"/></svg>,
  tiktok: (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="currentColor"><path d="M16.5 3c.2 1.6 1.1 3 2.5 3.8.7.4 1.5.7 2.3.7v3.2a8 8 0 0 1-4.8-1.6v6.7a6.1 6.1 0 1 1-6.1-6.1c.3 0 .6 0 .9.1v3.3a2.9 2.9 0 1 0 2 2.8V3h3.2z"/></svg>,
  youtube: (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="currentColor"><path d="M22 7.3c-.2-1.4-.9-2.1-2.3-2.3C17.3 4.6 12 4.6 12 4.6s-5.3 0-7.7.4C2.9 5.2 2.2 5.9 2 7.3 1.6 9.6 1.6 12 1.6 12s0 2.4.4 4.7c.2 1.4.9 2.1 2.3 2.3 2.4.4 7.7.4 7.7.4s5.3 0 7.7-.4c1.4-.2 2.1-.9 2.3-2.3.4-2.3.4-4.7.4-4.7s0-2.4-.4-4.7zM10 15.4V8.6l5.8 3.4-5.8 3.4z"/></svg>,
  instagram: (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.9} strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.3" cy="6.7" r="1" fill="currentColor" stroke="none"/></svg>,
  airdrop: (p) => <svg width={p.s||22} height={p.s||22} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M12 3a9 9 0 0 1 9 9"/><path d="M7.5 7.5a6 6 0 0 1 9 0"/><path d="M12 12l-4 8h8l-4-8z" fill="currentColor" stroke="none"/></svg>,
  copy: (p) => <svg width={p.s||20} height={p.s||20} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V5a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3"/></svg>,
  furigana: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M6 6h3m-3 0v8a2 2 0 0 0 2 2h1M15 4v4M13 6h4"/><path d="M13 14h6M16 14v6"/></svg>,
  palette: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><path d="M12 3a9 9 0 1 0 0 18 2 2 0 0 0 2-2c0-1-1-1.5-1-2.5s.5-1.5 1.5-1.5h2.5a3 3 0 0 0 3-3A9 9 0 0 0 12 3z"/><circle cx="7.5" cy="10" r="1.2" fill="currentColor" stroke="none"/><circle cx="10" cy="6.5" r="1.2" fill="currentColor" stroke="none"/><circle cx="14" cy="6.5" r="1.2" fill="currentColor" stroke="none"/><circle cx="17" cy="10" r="1.2" fill="currentColor" stroke="none"/></svg>,
  type: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M4 7V5h10v2M9 5v14M7 19h4"/><path d="M15 12V10h6v2M18 10v9M16.5 19h3"/></svg>,
  align: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><path d="M4 6h16M7 12h10M4 18h16"/></svg>,
  pip: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><rect x="13" y="12" width="6" height="5" rx="1" fill="currentColor" stroke="none" opacity="0.8"/></svg>,
  card: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><rect x="6" y="14" width="12" height="3" rx="0.8" fill="currentColor" stroke="none" opacity="0.8"/></svg>,
  full: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/></svg>,
  tweaks: (p) => <svg width={p.s||18} height={p.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={p.w||1.8} strokeLinecap="round"><circle cx="8" cy="8" r="2.5"/><circle cx="16" cy="16" r="2.5"/><path d="M10 8h10M4 16h10"/></svg>,
};

// ─────────────────────────────────────────────────────────────
// Primitives
// ─────────────────────────────────────────────────────────────
function Chip({ children, active, onClick, icon, tone="default" }) {
  const bg = active
    ? (tone === "accent" ? 'color-mix(in oklab, var(--accent) 22%, transparent)' : 'rgba(255,255,255,0.08)')
    : 'transparent';
  const bd = active
    ? (tone === "accent" ? 'var(--accent)' : 'var(--border-strong)')
    : 'var(--border)';
  const fg = active && tone === "accent" ? 'var(--accent)' : 'var(--text)';
  return (
    <button onClick={onClick} style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '7px 11px', borderRadius: 999,
      background: bg, border: `1px solid ${bd}`, color: fg,
      fontSize: 12.5, fontWeight: 600, letterSpacing: -0.1,
      transition: 'all .18s',
    }}>
      {icon && <span style={{display:'inline-flex'}}>{icon}</span>}
      {children}
    </button>
  );
}

function Pill({ children, color="var(--accent)" }) {
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      padding: '3px 7px', borderRadius: 999,
      background: `color-mix(in oklab, ${color} 14%, transparent)`,
      color, fontSize: 10.5, fontWeight: 700, letterSpacing: 0.3, textTransform: 'uppercase',
    }}>{children}</span>
  );
}

function SectionHead({ label, trailing }) {
  return (
    <div style={{display:'flex', alignItems:'center', justifyContent:'space-between', padding:'0 var(--pad)', marginBottom:10}}>
      <div style={{fontSize:10.5, fontWeight:700, letterSpacing:1.2, color:'var(--text-muted)', textTransform:'uppercase'}}>{label}</div>
      {trailing}
    </div>
  );
}

function PrimaryBtn({ children, onClick, disabled, icon, style={} }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      width: '100%', padding: '14px 18px', borderRadius: 14,
      background: disabled ? 'var(--bone-2)' : 'var(--ink)',
      color: disabled ? 'var(--text-muted)' : 'var(--bone)',
      fontSize: 15.5, fontWeight: 600, letterSpacing: -0.2,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      boxShadow: disabled ? 'none' : '0 10px 24px -12px rgba(30,26,21,0.5), inset 0 1px 0 rgba(255,255,255,0.1)',
      transition: 'transform .12s, filter .18s',
      ...style,
    }}
    onMouseDown={e=>!disabled && (e.currentTarget.style.transform='scale(0.98)')}
    onMouseUp={e=>!disabled && (e.currentTarget.style.transform='scale(1)')}
    onMouseLeave={e=>!disabled && (e.currentTarget.style.transform='scale(1)')}
    >
      {icon}{children}
    </button>
  );
}

function GhostBtn({ children, onClick, icon, style={}, flex }) {
  return (
    <button onClick={onClick} style={{
      padding: '12px 14px', borderRadius: 12,
      background: 'var(--cream)',
      border: '1px solid var(--border)',
      color: 'var(--text)',
      fontSize: 14, fontWeight: 500,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 7,
      flex: flex ? 1 : 'initial',
      ...style,
    }}>
      {icon}{children}
    </button>
  );
}

// Striped placeholder (for AI imagery, hero slots)
function StripePlaceholder({ label="IMAGE", h=120, rounded=10, hint }) {
  return (
    <div style={{
      height: h, borderRadius: rounded,
      position: 'relative', overflow: 'hidden',
      background: 'repeating-linear-gradient(135deg, rgba(30,26,21,0.04) 0 8px, rgba(30,26,21,0.015) 8px 16px)',
      border: '1px dashed var(--border-strong)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <div style={{textAlign:'center'}}>
        <div style={{fontFamily:'ui-monospace, "SF Mono", monospace', fontSize:10, letterSpacing:1.5, color:'var(--text-muted)'}}>{label}</div>
        {hint && <div style={{fontSize:10, color:'var(--text-muted)', marginTop:4, opacity:0.7}}>{hint}</div>}
      </div>
    </div>
  );
}

// Ruby-text rendering (furigana above base)
function RubyText({ pairs, baseSize=22, color="#fff" }) {
  // pairs: [{b: base, r: ruby}]
  return (
    <span style={{display:'inline-flex', flexWrap:'wrap', gap:'0 2px', alignItems:'flex-end', color, lineHeight:1.1}}>
      {pairs.map((p, i) => (
        <span key={i} style={{display:'inline-flex', flexDirection:'column', alignItems:'center', padding:'0 1px'}}>
          {p.r && <span style={{fontSize: baseSize*0.45, opacity:0.85, letterSpacing:-0.2, lineHeight:1, marginBottom:2}}>{p.r}</span>}
          {!p.r && <span style={{fontSize: baseSize*0.45, opacity:0, lineHeight:1, marginBottom:2}}>⠀</span>}
          <span style={{fontSize: baseSize, fontWeight:600, lineHeight:1}}>{p.b}</span>
        </span>
      ))}
    </span>
  );
}

// Tiny animated waveform
function Waveform({ bars=28, height=22, color="var(--accent)" }) {
  const arr = Array.from({length: bars});
  return (
    <div style={{display:'flex', alignItems:'center', gap:2, height}}>
      {arr.map((_, i) => (
        <div key={i} style={{
          width: 2, borderRadius: 2, background: color,
          height: height,
          animation: `waveform ${0.6 + (i%5)*0.15}s ease-in-out ${(i%7)*0.08}s infinite`,
          transformOrigin: 'center',
        }} />
      ))}
    </div>
  );
}

// Haptic feedback (visual only — brief scale)
function useHaptic() {
  return () => {
    if (navigator.vibrate) navigator.vibrate(8);
  };
}

Object.assign(window, {
  I, Chip, Pill, SectionHead, PrimaryBtn, GhostBtn, StripePlaceholder, RubyText, Waveform, useHaptic
});
