// mocks.jsx — Product UI mocks shared across all three concepts.
// Renders the canonical TranscriptAgent primitives: claim cards, asset pulse rows,
// theme heatmap, tracked-question notification, speaker spectrum, etc.

const { useMemo } = React;

/* ------------------------------------------------------------------ */
/* Tiny inline icons (stroke-only, ink color). Keep extremely simple. */
/* ------------------------------------------------------------------ */
function Ico({ name, size = 14, stroke = 'currentColor', strokeWidth = 1.6 }) {
  const s = { width: size, height: size, style: { flexShrink: 0, display: 'inline-block' } };
  const p = { fill: 'none', stroke, strokeWidth, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'arrow-up': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M8 13V3M4 7l4-4 4 4" /></svg>);
    case 'arrow-down': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M8 3v10M4 9l4 4 4-4" /></svg>);
    case 'arrow-right': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M3 8h10M9 4l4 4-4 4" /></svg>);
    case 'bolt': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M9 2L4 9h3l-1 5 5-7H8l1-5z" /></svg>);
    case 'eye': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M1.5 8s2.5-4.5 6.5-4.5S14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8z" /><circle {...p} cx="8" cy="8" r="2" /></svg>);
    case 'check': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M3 8.5L6.5 12 13 5" /></svg>);
    case 'cite': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M3 4h10M3 8h10M3 12h6" /></svg>);
    case 'play': return (<svg {...s} viewBox="0 0 16 16"><path fill={stroke} d="M5 3.5v9l7-4.5z" /></svg>);
    case 'flask': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M6 2h4v3.5l3 6.5a1.5 1.5 0 01-1.4 2H4.4A1.5 1.5 0 013 12l3-6.5V2zM6 5h4" /></svg>);
    case 'bell': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M4 11V7a4 4 0 018 0v4l1 1H3l1-1zM7 13.5a1 1 0 002 0" /></svg>);
    case 'spark': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M8 2v3M8 11v3M2 8h3M11 8h3M4 4l2 2M10 10l2 2M12 4l-2 2M6 10l-2 2" /></svg>);
    case 'compass': return (<svg {...s} viewBox="0 0 16 16"><circle {...p} cx="8" cy="8" r="6" /><path {...p} d="M10 6l-1 3-3 1 1-3z" /></svg>);
    case 'plus': return (<svg {...s} viewBox="0 0 16 16"><path {...p} d="M8 3v10M3 8h10" /></svg>);
    case 'search': return (<svg {...s} viewBox="0 0 16 16"><circle {...p} cx="7" cy="7" r="4.5" /><path {...p} d="M10.5 10.5L13 13" /></svg>);
    case 'logo': return (
      <svg {...s} viewBox="0 0 16 16">
        <path {...p} d="M2 13V3l3 7 3-7 3 7 3-7v10" />
      </svg>
    );
    default: return null;
  }
}

/* ------------------------------------------------------------------ */
/* Stance pill — bullish / bearish / neutral / mixed                  */
/* ------------------------------------------------------------------ */
function Stance({ value, conviction }) {
  const map = {
    bullish: { cls: 'chip--mint', label: 'Bullish', icon: 'arrow-up' },
    bearish: { cls: 'chip--danger', label: 'Bearish', icon: 'arrow-down' },
    neutral: { cls: 'chip--info', label: 'Neutral', icon: 'arrow-right' },
    mixed:   { cls: 'chip--warm', label: 'Mixed',  icon: 'spark' },
  };
  const m = map[value] || map.neutral;
  return (
    <span className={`chip ${m.cls}`} style={{ fontSize: 11.5, fontWeight: 600 }}>
      <Ico name={m.icon} size={11} strokeWidth={2} />
      {m.label}
      {conviction != null && (
        <span style={{ display: 'inline-flex', gap: 2, marginLeft: 4, opacity: 0.85 }}>
          {[0,1,2].map(i => (
            <span key={i} style={{
              width: 4, height: 4, borderRadius: 2,
              background: i < conviction ? 'currentColor' : 'transparent',
              boxShadow: i < conviction ? 'none' : 'inset 0 0 0 1px currentColor',
            }} />
          ))}
        </span>
      )}
    </span>
  );
}

/* ------------------------------------------------------------------ */
/* Sparkline                                                          */
/* ------------------------------------------------------------------ */
function Sparkline({ points, width = 64, height = 22, color = 'var(--brand-deep)', fill = true }) {
  const min = Math.min(...points), max = Math.max(...points);
  const range = max - min || 1;
  const step = width / (points.length - 1);
  const d = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${(i*step).toFixed(2)},${(height - ((p - min) / range) * (height - 2) - 1).toFixed(2)}`).join(' ');
  const fillD = fill ? `${d} L${width},${height} L0,${height} Z` : null;
  return (
    <svg width={width} height={height} className="spark" style={{ display: 'block' }}>
      {fill && <path className="spark-fill" d={fillD} />}
      <path d={d} style={{ stroke: color }} />
    </svg>
  );
}

/* ------------------------------------------------------------------ */
/* Claim card — the atomic unit of the product                        */
/* ------------------------------------------------------------------ */
function ClaimCard({
  claim,
  speaker,
  channel,
  stance = 'bullish',
  conviction = 2,
  asset,
  horizon = '3–6 mo',
  evidence = 4,
  timestamp = '14:32',
  variant = 'default',
}) {
  const isWarm = variant === 'warm';
  return (
    <div className={`card ${isWarm ? 'card--cream' : ''}`} style={{
      padding: '14px 16px',
      display: 'flex',
      flexDirection: 'column',
      gap: 10,
    }}>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
        <Stance value={stance} conviction={conviction} />
        {asset && <span className="chip chip--cool" style={{ fontSize: 11, fontWeight: 600 }}>{asset}</span>}
        <span className="chip" style={{ fontSize: 11, color: 'var(--ink-muted)', borderColor: 'transparent', background: 'transparent', padding: '0 2px' }}>
          {horizon}
        </span>
        <span style={{ marginLeft: 'auto', display: 'inline-flex', gap: 2, color: 'var(--gold)' }}>
          {[0,1,2,3,4].map(i => (
            <span key={i} style={{
              width: 6, height: 6, borderRadius: 1,
              background: i < evidence ? 'currentColor' : 'rgba(28,51,67,0.12)',
            }} />
          ))}
        </span>
      </div>
      <p className="h-card" style={{ margin: 0, fontSize: 14, lineHeight: 1.45, textWrap: 'pretty' }}>
        “{claim}”
      </p>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--ink-muted)', marginTop: 2 }}>
        <span style={{
          width: 18, height: 18, borderRadius: 4,
          background: 'linear-gradient(135deg, #c8b58a, #7a4d0a)',
          flexShrink: 0,
        }} />
        <strong style={{ color: 'var(--ink-navy)', fontWeight: 600 }}>{speaker}</strong>
        <span>·</span>
        <span>{channel}</span>
        <span style={{ marginLeft: 'auto', display: 'inline-flex', alignItems: 'center', gap: 4 }} className="mono">
          <Ico name="play" size={10} />
          {timestamp}
        </span>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Asset Pulse row — asset / sparkline / momentum / mentions          */
/* ------------------------------------------------------------------ */
function AssetPulseRow({ rank, ticker, name, mentions, speakers, momentum, sentiment, points, accent }) {
  const sign = momentum >= 0 ? '+' : '';
  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '24px 1fr 84px 78px 72px',
      alignItems: 'center',
      gap: 12,
      padding: '10px 14px',
      borderRadius: 10,
      background: '#fff',
      border: '1px solid var(--border-pale)',
    }}>
      <span className="mono" style={{ color: 'var(--ink-faint)', fontSize: 11 }}>{String(rank).padStart(2,'0')}</span>
      <div style={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
          <span style={{ fontWeight: 600, fontSize: 13.5, color: 'var(--ink-navy)' }}>{ticker}</span>
          <span style={{ fontSize: 11.5, color: 'var(--ink-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{name}</span>
        </div>
        <div style={{ fontSize: 10.5, color: 'var(--ink-faint)', marginTop: 2, letterSpacing: '0.04em' }}>
          {mentions} mentions · {speakers} speakers
        </div>
      </div>
      <Sparkline points={points} width={80} height={20} color={accent || 'var(--brand-deep)'} />
      <span className={`chip ${momentum >= 0 ? 'chip--mint' : 'chip--danger'}`} style={{ fontSize: 11, justifyContent: 'center', fontWeight: 600 }}>
        <Ico name={momentum >= 0 ? 'arrow-up' : 'arrow-down'} size={10} strokeWidth={2.2} />
        {sign}{momentum}%
      </span>
      <span style={{ fontSize: 11, color: 'var(--ink-muted)', textAlign: 'right', textTransform: 'uppercase', letterSpacing: '0.06em' }}>
        {sentiment}
      </span>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Theme heatmap                                                       */
/* ------------------------------------------------------------------ */
function ThemeHeatmap({ themes, weeks = 8, compact = false }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {themes.map((row, i) => (
        <div key={i} style={{
          display: 'grid',
          gridTemplateColumns: `${compact ? 110 : 140}px 1fr 64px`,
          gap: 10,
          alignItems: 'center',
        }}>
          <span style={{ fontSize: compact ? 11.5 : 12.5, color: 'var(--ink-navy)', fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            {row.label}
          </span>
          <div style={{ display: 'grid', gridTemplateColumns: `repeat(${weeks}, 1fr)`, gap: 3 }}>
            {row.heat.slice(0, weeks).map((h, j) => {
              const a = Math.max(0.06, Math.min(1, h));
              const bg = row.tone === 'cool'
                ? `rgba(35,80,102, ${a})`
                : row.tone === 'mint'
                  ? `rgba(23,56,45, ${a})`
                  : `rgba(122,77,10, ${a})`;
              return (
                <div key={j} style={{
                  height: compact ? 14 : 18,
                  background: bg,
                  borderRadius: 3,
                }} />
              );
            })}
          </div>
          <span className={`chip ${row.delta >= 0 ? 'chip--mint' : 'chip--cool'}`} style={{ fontSize: 10.5, justifyContent: 'center', fontWeight: 600, padding: '3px 8px' }}>
            {row.delta >= 0 ? '+' : ''}{row.delta}
          </span>
        </div>
      ))}
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Tracked Question card                                              */
/* ------------------------------------------------------------------ */
function TrackedQuestion({ q, newCount = 2, since = 'this week', preview }) {
  return (
    <div className="card card--warm" style={{ padding: 18, display: 'flex', flexDirection: 'column', gap: 14 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <span style={{
          width: 28, height: 28, borderRadius: 8,
          background: 'var(--brand-deep)', color: 'var(--gold-bright)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <Ico name="bell" size={14} strokeWidth={1.8} />
        </span>
        <div style={{ fontSize: 10.5, letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 600, color: 'var(--brand-bronze)' }}>
          Tracked question · {newCount} new answers {since}
        </div>
      </div>
      <p style={{
        margin: 0,
        fontFamily: 'var(--font-serif)',
        fontSize: 19,
        lineHeight: 1.25,
        color: 'var(--ink-navy)',
        letterSpacing: '-0.005em',
      }}>
        “{q}”
      </p>
      {preview && (
        <div style={{
          display: 'flex',
          flexDirection: 'column',
          gap: 8,
          padding: '12px 14px',
          background: '#fff',
          border: '1px solid var(--border-warmer)',
          borderRadius: 10,
        }}>
          {preview.map((p, i) => (
            <div key={i} style={{ display: 'flex', gap: 10, alignItems: 'flex-start', fontSize: 12 }}>
              <Stance value={p.stance} />
              <div style={{ flex: 1, lineHeight: 1.4, color: 'var(--ink-slate)' }}>
                <strong style={{ color: 'var(--ink-navy)', fontWeight: 600 }}>{p.speaker}</strong> — {p.line}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Speaker Spectrum — bear→bull axis with speaker dots                */
/* ------------------------------------------------------------------ */
function SpeakerSpectrum({ asset, speakers }) {
  // speakers: [{name, x: 0..1, conviction, prevX?: 0..1}]
  return (
    <div className="card" style={{ padding: 18 }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 16 }}>
        <span className="eyebrow eyebrow--bronze">Speaker spectrum</span>
        <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-navy)' }}>· {asset}</span>
      </div>
      <div style={{ position: 'relative', height: 130, marginBottom: 14 }}>
        {/* axis */}
        <div style={{
          position: 'absolute', left: 0, right: 0, top: 65,
          height: 2, background: 'linear-gradient(90deg, #ecc6bf 0%, #f0eee9 50%, #c8e1d2 100%)',
          borderRadius: 1,
        }} />
        <div style={{ position: 'absolute', left: '50%', top: 59, width: 1, height: 14, background: 'var(--border-cool)' }} />
        {speakers.map((s, i) => {
          const top = i % 2 === 0 ? 8 : 92;
          const hasPrev = typeof s.prevX === 'number' && Math.abs(s.prevX - s.x) > 0.02;
          return (
            <React.Fragment key={i}>
              {/* ghost (prev position) + arrow */}
              {hasPrev && (
                <div style={{
                  position: 'absolute',
                  top: 60,
                  left: `${Math.min(s.prevX, s.x) * 100}%`,
                  width: `${Math.abs(s.x - s.prevX) * 100}%`,
                  height: 10,
                  pointerEvents: 'none',
                }}>
                  {/* ghost dot at prevX */}
                  <span style={{
                    position: 'absolute',
                    left: s.prevX < s.x ? 0 : '100%',
                    top: 0,
                    transform: 'translate(-50%, 0)',
                    width: 9, height: 9, borderRadius: '50%',
                    border: '1.5px dashed var(--ink-faint)',
                    background: 'transparent',
                  }} />
                  {/* connector + arrow */}
                  <svg width="100%" height="10" viewBox="0 0 100 10" preserveAspectRatio="none" style={{ position: 'absolute', inset: 0 }}>
                    {s.prevX < s.x ? (
                      <>
                        <line x1="3" y1="5" x2="93" y2="5" stroke="var(--ink-faint)" strokeWidth="0.5" strokeDasharray="2 2" vectorEffect="non-scaling-stroke" />
                        <polyline points="89,2 96,5 89,8" fill="none" stroke="var(--brand-deep)" strokeWidth="0.8" vectorEffect="non-scaling-stroke" />
                      </>
                    ) : (
                      <>
                        <line x1="7" y1="5" x2="97" y2="5" stroke="var(--ink-faint)" strokeWidth="0.5" strokeDasharray="2 2" vectorEffect="non-scaling-stroke" />
                        <polyline points="11,2 4,5 11,8" fill="none" stroke="#a7503e" strokeWidth="0.8" vectorEffect="non-scaling-stroke" />
                      </>
                    )}
                  </svg>
                </div>
              )}
              {/* speaker label + dot */}
              <div style={{
                position: 'absolute',
                left: `${s.x * 100}%`,
                top,
                transform: 'translateX(-50%)',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                gap: 4,
                width: 96,
              }}>
                {i % 2 === 0 && (
                  <>
                    <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-navy)', textAlign: 'center', lineHeight: 1.15 }}>
                      {s.name}
                      {hasPrev && <span style={{ marginLeft: 4, fontSize: 9.5, color: s.prevX < s.x ? 'var(--brand-deep)' : '#a7503e', fontWeight: 700 }}>↗</span>}
                    </div>
                    <div style={{ width: 0, height: 18, borderLeft: '1px dashed var(--border-cool)' }} />
                  </>
                )}
                <div style={{
                  width: s.conviction * 4 + 6,
                  height: s.conviction * 4 + 6,
                  borderRadius: '50%',
                  background: s.x < 0.4 ? '#a7503e' : s.x > 0.6 ? 'var(--brand-deep)' : 'var(--gold)',
                  border: '2px solid #fff',
                  boxShadow: '0 0 0 1px rgba(28,51,67,0.15)',
                  position: i % 2 === 0 ? 'relative' : 'absolute',
                  bottom: i % 2 === 0 ? 'auto' : 28,
                }} />
                {i % 2 === 1 && (
                  <>
                    <div style={{ width: 0, height: 18, borderLeft: '1px dashed var(--border-cool)' }} />
                    <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--ink-navy)', textAlign: 'center', lineHeight: 1.15 }}>
                      {s.name}
                      {hasPrev && <span style={{ marginLeft: 4, fontSize: 9.5, color: s.prevX < s.x ? 'var(--brand-deep)' : '#a7503e', fontWeight: 700 }}>↗</span>}
                    </div>
                  </>
                )}
              </div>
            </React.Fragment>
          );
        })}
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10.5, letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 600, color: 'var(--ink-muted)' }}>
        <span>Bearish</span><span>Neutral</span><span>Bullish</span>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Channel row — a “followed channel” entry                            */
/* ------------------------------------------------------------------ */
function ChannelRow({ name, kind, freq, active = true, accent = 'gold' }) {
  const colors = {
    gold:    'linear-gradient(135deg, #e7c46c, #7a4d0a)',
    mint:    'linear-gradient(135deg, #c8e1d2, #17382d)',
    bronze:  'linear-gradient(135deg, #d8b07a, #5e3c10)',
    cool:    'linear-gradient(135deg, #c5dae9, #235066)',
    slate:   'linear-gradient(135deg, #b6c1cc, #3a4a55)',
  };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '8px 12px',
      background: '#fff',
      border: '1px solid var(--border-pale)',
      borderRadius: 10,
    }}>
      <span style={{
        width: 28, height: 28, borderRadius: 7,
        background: colors[accent] || colors.gold,
        flexShrink: 0,
      }} />
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-navy)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{name}</div>
        <div style={{ fontSize: 11, color: 'var(--ink-muted)', marginTop: 1 }}>{kind} · {freq}</div>
      </div>
      <span className={`chip ${active ? 'chip--mint' : ''}`} style={{ fontSize: 10.5, fontWeight: 600 }}>
        {active ? <><span className="dot" style={{ width: 5, height: 5 }} /> Live</> : 'Paused'}
      </span>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Citation block                                                      */
/* ------------------------------------------------------------------ */
function Citation({ video, speaker, timestamp = '14:32', evidence = 4 }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 10,
      padding: '8px 12px',
      background: 'var(--surface-cool)',
      border: '1px solid var(--border-cool)',
      borderRadius: 10,
      fontSize: 12,
      color: 'var(--ink-slate)',
    }}>
      <Ico name="cite" size={13} stroke="var(--ink-muted)" />
      <span style={{ color: 'var(--ink-navy)', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1, minWidth: 0 }}>
        {video}
      </span>
      <span style={{ color: 'var(--ink-muted)' }}>· {speaker}</span>
      <span className="mono" style={{ color: 'var(--brand-bronze)' }}>{timestamp}</span>
    </div>
  );
}

/* Expose to other Babel scripts */
Object.assign(window, {
  Ico, Stance, Sparkline, ClaimCard, AssetPulseRow, ThemeHeatmap,
  TrackedQuestion, SpeakerSpectrum, ChannelRow, Citation,
});
