/* =====================================================================
   AI-COS — Global search results + rebuilt AI Compliance Intelligence
   (overrides window.AIModule defined earlier; loaded after modules2)
   ===================================================================== */

/* ---------------- Global search results page ---------------------- */
function SearchResults({ query, onBack }) {
  const DB = window.DB;
  const q = (query || '').toLowerCase();
  const match = (s) => (s || '').toString().toLowerCase().includes(q);
  const groups = [
    { label: 'Calibration jobs', icon: 'workflow', type: null, items: DB.jobs.filter((j) => match(j.id) || match(DB.custById(j.customer).name) || match(j.type)).map((j) => ({ id: j.id, sub: `${DB.custById(j.customer).short} · ${j.type} · ${j.stage}`, open: () => window._openJob && window._openJob(j.id) })) },
    { label: 'Certificates', icon: 'certificate', items: DB.certificates.filter((c) => match(c.id) || match(c.model) || match(c.monitor)).map((c) => ({ id: c.id, sub: `${c.model} · ${c.status}`, open: () => window.openDetail('cert', c) })) },
    { label: 'Equipment & assets', icon: 'cpu', items: DB.monitors.filter((m) => match(m.id) || match(m.model) || match(m.serial)).map((m) => ({ id: m.id, sub: `${m.model} · ${m.dueRel}`, open: () => window.openDetail('asset', m) })) },
    { label: 'Cylinders & standards', icon: 'cylinder', items: DB.cylinders.filter((c) => match(c.id) || match(c.mix)).map((c) => ({ id: c.id, sub: `${c.mix} · ${c.status}`, open: () => window.openDetail('cylinder', c) })) },
    { label: 'Customers', icon: 'building', items: DB.customers.filter((c) => match(c.name) || match(c.short) || match(c.sector)).map((c) => ({ id: c.name, sub: c.sector, open: () => window.openDetail('customer', c) })) },
    { label: 'Documents', icon: 'documents', items: DB.docReg.filter((d) => match(d.code) || match(d.title)).map((d) => ({ id: d.code, sub: d.title, open: () => window.openDetail('document', d) })) },
    { label: 'CAPA / NCR', icon: 'check-shield', items: DB.capa.filter((x) => match(x.id) || match(x.title)).map((x) => ({ id: x.id, sub: x.title, open: () => window.openDetail('capa', x) })) },
  ].filter((g) => g.items.length);
  const total = groups.reduce((a, g) => a + g.items.length, 0);
  return (
    <div className="page page-wide rise">
      <div className="row" style={{ gap: 10, marginBottom: 18 }}>
        <button className="icon-btn" onClick={onBack}><Icon name="chevL" size={17} /></button>
        <div><div className="h-page" style={{ fontSize: 20 }}>Search</div><div className="h-sub">{total} result{total !== 1 ? 's' : ''} for “{query}”</div></div>
      </div>
      {total === 0 ? (
        <div className="card" style={{ padding: 48, textAlign: 'center' }}><Icon name="search" size={28} style={{ color: 'var(--text-3)' }} /><div className="h-sec" style={{ marginTop: 12 }}>No matches</div><div className="muted" style={{ fontSize: 13 }}>Try an asset ID, certificate number, customer or document code.</div></div>
      ) : groups.map((g) => (
        <div key={g.label} className="card" style={{ marginBottom: 14 }}>
          <div className="card-head"><Icon name={g.icon} size={16} style={{ color: 'var(--primary-600)' }} /><div className="h-sec" style={{ fontSize: 13.5 }}>{g.label}</div><span className="badge b-neutral" style={{ marginLeft: 'auto' }}>{g.items.length}</span></div>
          <div className="card-body" style={{ paddingTop: 4, paddingBottom: 4 }}>
            {g.items.slice(0, 6).map((it, i) => (
              <div key={i} className="lrow" style={{ cursor: 'pointer' }} onClick={it.open}>
                <span className="mono cell-strong" style={{ fontSize: 12, width: 170, flex: 'none' }}>{it.id}</span>
                <span style={{ flex: 1, fontSize: 12.5, color: 'var(--text-2)' }}>{it.sub}</span>
                <Icon name="chevR" size={15} style={{ color: 'var(--text-3)' }} />
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

/* ---------------- AI Compliance & Calibration Intelligence -------- */
const AI_QA = [
  { q: 'What does ISO 17025 require for measurement uncertainty?', a: 'A documented uncertainty budget per method/range with combined and expanded uncertainty (k-factor), attached to results and stated on certificates where relevant. Your lab implements this via the Measurement Uncertainty Procedure and per-method budgets.', cites: ['ISO 17025 §7.6', 'ADAM-QSP-L2-P-019'] },
  { q: 'Can an expired calibration gas be used?', a: 'No. An expired calibration gas invalidates the result. The system hard-blocks expired or below-minimum-pressure cylinders from worksheet selection, enforcing equipment validity at the point of work.', cites: ['ISO 17025 §6.4', 'ADAM-TECH-L3-P-009'] },
  { q: 'Who can approve and sign a certificate?', a: 'Only an authorized signatory with valid competency for the method and scope, who did not execute the worksheet (segregation of duties). Approval is a deliberate, re-authenticated e-sign action.', cites: ['ISO 17025 §7.7 / 7.8', 'ADAM-QSP-L2-P-009'] },
  { q: 'What happens on an unsatisfactory proficiency-test result?', a: 'An NCR opens automatically and a CAPA is tracked to closure. AI flags likely correlated causes (e.g. reference-cylinder bias) for the Technical Manager to confirm.', cites: ['ISO 17025 §7.7', 'ADAM-QSP-L2-P-005'] },
];

function AIModule({ onNav }) {
  const DB = window.DB;
  const [tab, setTab] = useState('overview');
  const tabs = [['overview', 'Overview'], ['assistant', 'Standards assistant'], ['docsearch', 'Document search'], ['predict', 'Predictions & drift'], ['log', 'AI decision log']];
  return (
    <div className="page page-wide rise">
      <PageHead title="AI Compliance &amp; Calibration Intelligence" sub="Advisory · labelled · logged · human-confirmed — assistance at the point of work, never an autonomous record" />
      <div className="tabs" style={{ marginBottom: 16 }}>{tabs.map(([id, l]) => <div key={id} className={`tab${tab === id ? ' on' : ''}`} onClick={() => setTab(id)}>{l}</div>)}</div>
      {tab === 'overview' && <AIOverview onNav={onNav} />}
      {tab === 'assistant' && <AIAssistantChat />}
      {tab === 'docsearch' && <AIDocSearch onNav={onNav} />}
      {tab === 'predict' && <AIPredictions onNav={onNav} />}
      {tab === 'log' && <AILog />}
    </div>
  );
}

function AIOverview({ onNav }) {
  const DB = window.DB;
  const caps = [
    ['Audit-readiness scoring', 'Continuously computed from open items & expiries', 'check-shield', 'var(--ok)', 'P1'],
    ['Overdue-risk ranking', 'Ranks equipment likely to miss due dates', 'trend', 'var(--primary-600)', 'P1'],
    ['CAPA suggestions', 'Recurring-issue detection & root-cause candidates', 'refresh', 'var(--ai)', 'P1'],
    ['Drift analysis', 'Per-sensor as-found trend toward tolerance', 'gauge', 'var(--warn)', 'P2'],
    ['Sensor-failure prediction', 'Age + drift + repair history → replacement', 'cpu', 'var(--bad)', 'P2'],
    ['Standards assistant', 'Clause answers citing your own SOPs', 'documents', 'var(--primary-600)', 'P2'],
  ];
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: 16, alignItems: 'start' }}>
      <div className="card card-pad" style={{ textAlign: 'center' }}>
        <div className="eyebrow" style={{ marginBottom: 10 }}>Live audit readiness</div>
        <Ring value={DB.readiness.score} size={150} color="var(--ok)"><div><div style={{ fontSize: 38, fontWeight: 800, letterSpacing: '-1px' }}>{DB.readiness.score}</div><div className="faint" style={{ fontSize: 11 }}>/ 100</div></div></Ring>
        <div style={{ marginTop: 14, textAlign: 'left', display: 'flex', flexDirection: 'column', gap: 8 }}>
          {DB.readiness.factors.map((f, i) => (
            <div key={i} className="row" style={{ gap: 8 }}>
              <span style={{ flex: 1, fontSize: 12, color: 'var(--text-2)', fontWeight: 600 }}>{f.label}</span>
              <span className="mono" style={{ fontSize: 12, fontWeight: 700, color: f.value < 0 ? 'var(--warn)' : 'var(--ok)' }}>{f.value === 0 ? '✓' : f.value}</span>
            </div>
          ))}
        </div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 12 }}>
          {caps.map(([t, d, ic, col, ph], i) => (
            <div key={i} className="card hover-lift card-pad">
              <div className="row" style={{ justifyContent: 'space-between', marginBottom: 9 }}><span className="kpi-ico" style={{ width: 34, height: 34, background: 'var(--bg)', color: col }}><Icon name={ic} size={17} /></span><Badge kind="neutral">Phase {ph.replace('P', '')}</Badge></div>
              <div style={{ fontWeight: 700, fontSize: 13 }}>{t}</div><div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{d}</div>
            </div>
          ))}
        </div>
        <div className="card">
          <div className="card-head" style={{ background: 'linear-gradient(120deg, var(--ai-bg), #fff)' }}><span className="ai-badge-ico"><Icon name="sparkles" size={15} fill /></span><div className="h-sec" style={{ fontSize: 14 }}>Live signals</div><span className="spacer" /><Badge kind="ai">{DB.aiAlerts.length} active</Badge></div>
          <div className="card-body" style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            {DB.aiAlerts.map((a) => <AINote key={a.id} title={a.title} clause={a.clause} action={a.action} onAction={() => onNav(a.kind === 'doc' ? 'documents' : a.kind === 'risk' ? 'schedule' : 'iso')}>{a.body}</AINote>)}
          </div>
        </div>
      </div>
    </div>
  );
}

function AIAssistantChat() {
  const [msgs, setMsgs] = useState([{ role: 'ai', text: 'Hello — I can answer questions about ISO/IEC 17025 and ISO 9001, citing your own controlled documents. Everything I say is advisory. Try a question below.' }]);
  const [input, setInput] = useState('');
  const endRef = useRef(null);
  const ask = (text) => {
    if (!text.trim()) return;
    const found = AI_QA.find((x) => x.q.toLowerCase() === text.toLowerCase()) || AI_QA.find((x) => text.toLowerCase().split(' ').some((w) => w.length > 3 && x.q.toLowerCase().includes(w)));
    const ans = found || { a: 'I can help with measurement uncertainty, calibration gas validity, signatory rules, proficiency testing, document control and competency. I cite your controlled documents and never create records on my own.', cites: ['ADAM-QMS-L1-M-01'] };
    setMsgs((m) => [...m, { role: 'user', text }, { role: 'ai', text: ans.a, cites: ans.cites }]);
    setInput('');
    setTimeout(() => endRef.current && endRef.current.scrollIntoView({ block: 'nearest' }), 50);
  };
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 280px', gap: 16, alignItems: 'start' }}>
      <div className="card" style={{ display: 'flex', flexDirection: 'column', height: 520 }}>
        <div className="card-head" style={{ background: 'linear-gradient(120deg, var(--ai-bg), #fff)' }}><span className="ai-badge-ico"><Icon name="sparkles" size={15} fill /></span><div className="h-sec" style={{ fontSize: 14 }}>Standards Assistant</div><span className="spacer" /><Badge kind="ai">Advisory · cites SOPs</Badge></div>
        <div style={{ flex: 1, overflowY: 'auto', padding: 18, display: 'flex', flexDirection: 'column', gap: 12 }}>
          {msgs.map((m, i) => (
            <div key={i} style={{ display: 'flex', justifyContent: m.role === 'user' ? 'flex-end' : 'flex-start' }}>
              <div style={{ maxWidth: '80%', padding: '10px 13px', borderRadius: 13, fontSize: 13, lineHeight: 1.5, background: m.role === 'user' ? 'var(--primary-600)' : 'var(--bg)', color: m.role === 'user' ? '#fff' : 'var(--text)', border: m.role === 'user' ? 'none' : '1px solid var(--border)' }}>
                {m.text}
                {m.cites && <div className="row wrap" style={{ gap: 5, marginTop: 8 }}>{m.cites.map((c) => <span key={c} className="tag" style={{ fontSize: 10.5, background: 'var(--ai-bg)', color: '#5b3fd6', borderColor: 'var(--ai-line)' }}><Icon name="documents" size={10} />{c}</span>)}</div>}
              </div>
            </div>
          ))}
          <div ref={endRef} />
        </div>
        <div style={{ padding: 12, borderTop: '1px solid var(--border)' }}>
          <div className="searchbox" style={{ width: '100%' }}><Icon name="sparkles" size={15} style={{ color: 'var(--ai)' }} /><input value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && ask(input)} placeholder="Ask about a clause, method, or finding…" /><Btn variant="ai" size="sm" onClick={() => ask(input)}>Ask</Btn></div>
        </div>
      </div>
      <div className="card card-pad">
        <div className="eyebrow" style={{ marginBottom: 10 }}>Suggested questions</div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {AI_QA.map((x, i) => <button key={i} className="btn btn-ghost" style={{ textAlign: 'left', justifyContent: 'flex-start', fontSize: 12, height: 'auto', padding: '9px 11px', whiteSpace: 'normal' }} onClick={() => ask(x.q)}>{x.q}</button>)}
        </div>
      </div>
    </div>
  );
}

function MiniSpark({ data, color, limit }) {
  const w = 100, h = 30, min = Math.min(...data) - 1, max = Math.max(...data, limit || 0) + 1;
  const pts = data.map((v, i) => `${(i / (data.length - 1)) * w},${h - ((v - min) / (max - min)) * h}`).join(' ');
  const ly = limit != null ? h - ((limit - min) / (max - min)) * h : null;
  return <svg viewBox={`0 0 ${w} ${h}`} style={{ width: '100%', height: 34 }} preserveAspectRatio="none">{ly != null && <line x1="0" y1={ly} x2={w} y2={ly} stroke="var(--bad)" strokeWidth="1" strokeDasharray="3 3" vectorEffect="non-scaling-stroke" />}<polyline points={pts} fill="none" stroke={color} strokeWidth="1.6" vectorEffect="non-scaling-stroke" /></svg>;
}

function AIPredictions({ onNav }) {
  const DB = window.DB;
  const drift = [
    { id: 'PDO-MON-001', sensor: 'CO', data: [48, 49, 50, 51, 53, 55], tol: 60, risk: 'Watch' },
    { id: 'SA-MON-005', sensor: 'H₂S', data: [24.9, 24.6, 24.2, 23.7, 23.1, 22.4], tol: 22.5, risk: 'High' },
    { id: 'OLNG-MON-002', sensor: 'LEL', data: [50, 50, 49, 51, 50, 49], tol: 45, risk: 'Stable' },
  ];
  const overdueRisk = DB.monitors.filter((m) => m.status !== 'Active').slice(0, 6);
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, alignItems: 'start' }}>
      <div className="card">
        <div className="card-head"><Icon name="gauge" size={16} style={{ color: 'var(--warn)' }} /><div className="h-sec" style={{ fontSize: 14 }}>Calibration drift analysis</div><span className="spacer" /><Badge kind="ai">AIX-06</Badge></div>
        <div className="card-body" style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
          {drift.map((d) => (
            <div key={d.id} className="lrow" style={{ cursor: 'pointer' }} onClick={() => { const m = DB.monitors.find((x) => x.id === d.id); m && window.openDetail('asset', m); }}>
              <div style={{ width: 110, flex: 'none' }}><div className="mono cell-strong" style={{ fontSize: 11.5 }}>{d.id}</div><div className="faint" style={{ fontSize: 10.5 }}>{d.sensor} channel</div></div>
              <div style={{ flex: 1 }}><MiniSpark data={d.data} color={d.risk === 'High' ? 'var(--bad)' : d.risk === 'Watch' ? 'var(--warn)' : 'var(--ok)'} limit={d.tol} /></div>
              <Badge kind={d.risk === 'High' ? 'bad' : d.risk === 'Watch' ? 'warn' : 'ok'}>{d.risk}</Badge>
            </div>
          ))}
        </div>
        <div className="card-body" style={{ borderTop: '1px solid var(--border)' }}>
          <AINote title="H₂S sensor on SA-MON-005 approaching tolerance" clause="AIX-07" action="Add replacement to job" onAction={() => onNav('inventory')}>Drift + sensor age match a pre-failure pattern — proactive replacement suggested before next due.</AINote>
        </div>
      </div>
      <div className="card">
        <div className="card-head"><Icon name="trend" size={16} style={{ color: 'var(--primary-600)' }} /><div className="h-sec" style={{ fontSize: 14 }}>Overdue-risk ranking</div><span className="spacer" /><Badge kind="ai">AIX-01</Badge></div>
        <table className="tbl">
          <thead><tr><th>Asset</th><th>Customer</th><th>Risk</th><th>Due</th></tr></thead>
          <tbody>
            {overdueRisk.map((m, i) => { const c = DB.custById(m.customer); const risk = ['92%', '88%', '81%', '74%', '67%', '60%'][i]; return (
              <tr key={m.id} className="clickable" onClick={() => window.openDetail('asset', m)}>
                <td className="mono cell-strong" style={{ fontSize: 11.5 }}>{m.id}</td>
                <td><span className="avatar avatar-sm" style={{ background: c.color, borderRadius: 6 }}>{c.short}</span></td>
                <td style={{ width: 100 }}><div className="row" style={{ gap: 6 }}><div style={{ width: 44 }}><Bar pct={parseInt(risk)} color={parseInt(risk) > 80 ? 'var(--bad)' : 'var(--warn)'} /></div><b className="mono" style={{ fontSize: 11 }}>{risk}</b></div></td>
                <td><Badge kind={m.status === 'Overdue' ? 'bad' : 'warn'}>{m.dueRel}</Badge></td>
              </tr>
            ); })}
          </tbody>
        </table>
        <div className="card-body" style={{ borderTop: '1px solid var(--border)' }}>
          <Btn variant="ai" icon="bell" onClick={() => window.toast('Outreach list generated · 7 customers', 'ai')}>Generate proactive outreach list</Btn>
        </div>
      </div>
    </div>
  );
}

function AILog() {
  const log = [
    ['09:41', 'Drift flag raised', 'LEL channel above expected band on WS-26-3187', 'Confirmed by technician'],
    ['08:22', 'CAPA root-cause suggested', 'Gas-store handover linked to 3 NCRs', 'Accepted by QM'],
    ['Yesterday', 'Overdue-risk list proposed', '11 assets ranked; 7 under AMC', 'Outreach sent'],
    ['Yesterday', 'Sensor-failure prediction', 'H₂S on SA-MON-005 flagged', 'Replacement scheduled'],
    ['2d ago', 'Readiness score recomputed', '87/100 — 2 documents overdue', 'Reviewed'],
  ];
  return (
    <div className="card">
      <div className="card-head"><Icon name="history" size={16} style={{ color: 'var(--ai)' }} /><div className="h-sec" style={{ fontSize: 14 }}>AI decision log</div><span className="spacer" /><span className="faint" style={{ fontSize: 11.5 }}>Every suggestion + human outcome, audit-logged</span></div>
      <table className="tbl">
        <thead><tr><th>When</th><th>AI action</th><th>Detail</th><th>Human outcome</th></tr></thead>
        <tbody>{log.map((l, i) => (
          <tr key={i}><td className="faint mono" style={{ fontSize: 11.5 }}>{l[0]}</td><td><span className="row" style={{ gap: 7 }}><Icon name="sparkles" size={13} style={{ color: 'var(--ai)' }} /><b style={{ fontSize: 12.5 }}>{l[1]}</b></span></td><td className="faint" style={{ fontSize: 12 }}>{l[2]}</td><td><Badge kind="ok" icon="check">{l[3]}</Badge></td></tr>
        ))}</tbody>
      </table>
    </div>
  );
}

/* ---- AIX-05: natural-language document search ---- */
function AIDocSearch({ onNav }) {
  const DB = window.DB;
  const [q, setQ] = useState('');
  const [run, setRun] = useState('');
  const suggestions = ['uncertainty budget', 'calibration gas expiry', 'signatory authorization', 'internal audit', 'control of records', 'corrective action'];
  const SNIP = {
    'CAL-MD': 'Defines the calibration procedure, test points, acceptance tolerances and the measurement-uncertainty budget applied to results.',
    'L2-P-001': 'Controlled-document lifecycle: draft → review → approve → publish, with revision control and obsolete handling.',
    'L2-P-002': 'Identification, storage, protection, retention and disposition of quality and technical records.',
    'L2-P-004': 'Internal audit programme, auditor independence, findings classification and follow-up to closure.',
    'L2-P-005': 'Control of non-conforming work — containment, disposition and the link to corrective action.',
    'L2-P-007': 'Corrective-action workflow: root-cause analysis, action plan, effectiveness verification and closure.',
    'L2-P-009': 'Personnel competency — assessment criteria and separate authorization to execute, review and sign.',
    'L2-P-010': 'Handling, transport, storage and use of measuring equipment to preserve calibration status.',
    'L1-M-01': 'Top-level quality manual mapping ISO/IEC 17025 and ISO 9001 requirements to the laboratory’s processes.',
  };
  const snippetFor = (d) => { const k = Object.keys(SNIP).find((kk) => d.code.includes(kk)); return k ? SNIP[k] : `Controlled ${(d.type || 'document').toLowerCase()} — ${d.title}.`; };
  const words = run.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
  const results = run ? DB.docReg.map((d) => {
    const hay = (d.code + ' ' + d.title + ' ' + (d.type || '') + ' ' + snippetFor(d)).toLowerCase();
    const score = words.reduce((n, w) => n + (hay.includes(w) ? 1 : 0), 0);
    return { d, score };
  }).filter((r) => r.score > 0).sort((a, b) => b.score - a.score).slice(0, 6) : [];
  const ask = (text) => { setQ(text); setRun(text); };
  return (
    <div className="card">
      <div className="card-head" style={{ background: 'linear-gradient(120deg, var(--ai-bg), #fff)' }}><span className="ai-badge-ico"><Icon name="search" size={15} /></span><div className="h-sec" style={{ fontSize: 14 }}>AI document search</div><span className="spacer" /><Badge kind="ai">AIX-05</Badge></div>
      <div className="card-body">
        <div className="searchbox" style={{ width: '100%' }}><Icon name="sparkles" size={15} style={{ color: 'var(--ai)' }} /><input value={q} onChange={(e) => setQ(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && setRun(q)} placeholder="Search controlled documents, methods & records in natural language…" autoFocus /><Btn variant="ai" size="sm" onClick={() => setRun(q)}>Search</Btn></div>
        <div className="row wrap" style={{ gap: 7, marginTop: 10 }}>{suggestions.map((s) => <button key={s} className="tag" style={{ cursor: 'pointer', border: '1px solid var(--border)' }} onClick={() => ask(s)}>{s}</button>)}</div>
        <div className="faint" style={{ fontSize: 11, marginTop: 10 }}><Icon name="lock" size={11} /> Results limited to documents you are authorized to view; AI is advisory and cites the controlled source.</div>
      </div>
      {run && (
        <div className="card-body" style={{ borderTop: '1px solid var(--border)' }}>
          <div className="eyebrow" style={{ marginBottom: 10 }}>{results.length} result{results.length !== 1 ? 's' : ''} for “{run}”</div>
          {results.length === 0 ? <div className="muted" style={{ fontSize: 13 }}>No authorized documents match. Try a clause, method code, or topic.</div> :
            results.map((r) => (
              <div key={r.d.code} className="lrow" style={{ cursor: 'pointer', padding: '11px 0', alignItems: 'flex-start' }} onClick={() => window.openDetail('document', r.d)}>
                <span className="kpi-ico" style={{ width: 32, height: 32, flex: 'none', background: 'var(--ai-bg)', color: 'var(--ai)' }}><Icon name="documents" size={15} /></span>
                <div style={{ flex: 1 }}>
                  <div className="row" style={{ gap: 8 }}><span style={{ fontSize: 13, fontWeight: 700 }}>{r.d.title}</span><Badge kind="neutral">{r.d.level}</Badge></div>
                  <div className="faint" style={{ fontSize: 12, marginTop: 3, lineHeight: 1.45 }}>{snippetFor(r.d)}</div>
                  <div className="row" style={{ gap: 8, marginTop: 5 }}><span className="mono faint" style={{ fontSize: 10.5 }}>{r.d.code} · {r.d.ver}</span><StatusBadge status={r.d.status} /></div>
                </div>
                <Icon name="chevR" size={16} style={{ color: 'var(--text-3)', marginTop: 8 }} />
              </div>
            ))}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { SearchResults, AIModule, AIDocSearch });
