// Response card components — chatbot-first treatment. const { useState: useStateR, useRef: useRefR, useEffect: useEffectR } = React; const MiniChart = ({ data }) => { const max = Math.max(...data.series.map(p => p.v)); return (
Monthly secured sales · Americas · FY27 to date {data.unit}
{data.series.map((p, i) => (
{p.v.toFixed(1)} {p.m}
))}
); }; const FilterPop = ({ onClose, filters }) => { const ref = useRefR(); useEffectR(() => { const f = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); }; document.addEventListener('mousedown', f); return () => document.removeEventListener('mousedown', f); }, []); return (
Applied filters · matches the Power BI tile
{filters.map(f => (
{f.k} {f.v}
))}
); }; const ExportPop = ({ onClose }) => { const ref = useRefR(); useEffectR(() => { const f = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); }; document.addEventListener('mousedown', f); return () => document.removeEventListener('mousedown', f); }, []); return (
); }; // Quiet byline above an AI response. Replaces the heavy "chip + verified" card-header // from the previous draft so the design reads as a chatbot first. const Byline = ({ agent, reason, filters }) => { const [showFilters, setShowFilters] = useStateR(false); const A = window.OMNI_DATA.AGENTS.find(a => a.id === agent); return (
Asked {A.name} · {reason}
{showFilters && setShowFilters(false)}/>}
); }; // Map our backend's agent short-name (registry.py) to the OMNI_DATA.AGENTS chip id. const ROUTED_AGENT_TO_CHIP = { mydashboard: 'mydash', sales: 'sales', otif: 'otif', inventory: 'inventory', ar: 'ar', agri: 'agri', orderbook: 'orderbook', lost_tree: 'lost_tree', }; const fmtCost = (c) => (c == null ? '—' : '$' + Number(c).toFixed(c < 0.01 ? 6 : 4)); const fmtTokens = (n) => (n == null ? '—' : Number(n).toLocaleString()); // Parse a $20,481,443.56 / 31.8% / 1,234 / **$69.75M** / -$1.44M style cell into a Number. const parseNumericCell = (s) => { if (s == null) return null; // Strip markdown bold/emphasis, currency, commas, spaces, leading/trailing punct let cleaned = String(s).replace(/\*+/g, '').replace(/[\s$,`_]/g, '').replace(/%$/, ''); if (!cleaned) return null; // Handle magnitude suffixes: 12.5M, 3.4K, 1.2B, 4.1T const m = cleaned.match(/^(-?\d+\.?\d*)(K|M|B|T|k|m|b|t)?$/); if (!m) { const n = Number(cleaned); return Number.isFinite(n) ? n : null; } const num = Number(m[1]); const suffix = (m[2] || '').toLowerCase(); const mult = { k: 1e3, m: 1e6, b: 1e9, t: 1e12 }[suffix] || 1; return Number.isFinite(num) ? num * mult : null; }; // Pull the first markdown table whose last column is numeric and use it as a chart. const extractChartFromMarkdown = (md) => { if (!md || !window.marked) return null; try { const tokens = window.marked.lexer(md); for (const tok of tokens) { if (tok.type !== 'table') continue; const headers = tok.header.map(h => h.text); const rows = tok.rows.map(r => r.map(c => c.text)); if (rows.length < 2 || headers.length < 2) continue; // Find a numeric column — prefer last col, fallback to scanning all let valCol = -1; for (let c = headers.length - 1; c >= 1; c--) { const nums = rows.map(r => parseNumericCell(r[c])).filter(v => v != null); if (nums.length >= rows.length - 1) { valCol = c; break; } } if (valCol === -1) continue; const stripMd = (s) => String(s || '').replace(/\*+/g, '').replace(/`+/g, '').trim(); const series = rows .map(r => ({ lbl: stripMd(r[0]), v: parseNumericCell(r[valCol]) })) .filter(p => p.v != null && p.lbl); // Skip if last row is a "Total" row — that's a summary, not a category const filtered = series[series.length - 1]?.lbl.toLowerCase().includes('total') ? series.slice(0, -1) : series; if (filtered.length < 2 || filtered.length > 12) continue; return { title: stripMd(headers[valCol]) + ' by ' + stripMd(headers[0]), series: filtered }; } } catch (e) { /* swallow */ } return null; }; const AutoChart = ({ data }) => { if (!data || !data.series || data.series.length === 0) return null; const max = Math.max(...data.series.map(p => Math.abs(p.v))); // Detect if title hints at currency or percentage const isPct = /(%|percent|rate|share|ratio)/i.test(data.title); const fmt = (n) => { if (isPct) return n.toFixed(1) + '%'; if (Math.abs(n) >= 1_000_000) return '$' + (n / 1_000_000).toFixed(1) + 'M'; if (Math.abs(n) >= 1_000) return '$' + (n / 1_000).toFixed(1) + 'K'; return '$' + n.toLocaleString(); }; return (
{data.title}
{data.series.map((p, i) => (
{fmt(p.v)} {p.lbl.length > 12 ? p.lbl.slice(0, 11) + '…' : p.lbl}
))}
); }; const RealResponseBody = ({ data }) => { const html = React.useMemo(() => { if (!data || !data.answer) return ''; try { return window.marked ? window.marked.parse(data.answer, { breaks: true, gfm: true }) : data.answer; } catch (e) { return data.answer; } }, [data && data.answer]); const chart = React.useMemo(() => extractChartFromMarkdown(data?.answer), [data?.answer]); return ( <> {chart && }
); }; const ResponseCard = ({ tweaks, onOpenTrail, realResponse }) => { const D = window.OMNI_DATA; const [showExport, setShowExport] = useStateR(false); const [feedback, setFeedback] = useStateR(null); // ─── REAL backend response branch ──────────────────────────────────────── if (realResponse) { const routedAgent = ROUTED_AGENT_TO_CHIP[realResponse.routed_to] || 'mydash'; const reason = realResponse.router_reason || 'auto-routed'; const tu = realResponse.token_usage || {}; const ragSources = (realResponse.sources || []).map((s, i) => ({ id: 's' + i, kind: s.type === 'web' ? 'web' : 'pdf', title: (s.snippet || '').slice(0, 40) || (s.type || 'source'), meta: s.snippet || '', })); return (
{tweaks.showHonesty && realResponse.honesty && (
{realResponse.honesty}
)} {tweaks.showCitations && ragSources.length > 0 && (
Also pulled from {ragSources.map(c => ( {c.title} {c.kind} ))}
)}
{tweaks.showCost && ( {fmtTokens(tu.total_tokens)} tokens · {fmtCost(tu.estimated_cost_usd)} )}
{showExport && setShowExport(false)}/>}
); } // ─── DEMO branch (preserved for the prototype look without a backend) ───── return (

Here are your exact secured sales figures for Americas, FY2027:

With Tariff
$20,481,443.56
312 orders · avg $65,646
Without Tariff
$19,002,904.70
312 orders · avg $60,907

Tariff impact: $1,478,538.86 — the difference between the two figures represents the tariff charges included in the “With Tariff” line.

{tweaks.showChart && } {tweaks.showTable && (
{D.DEMO_TABLE.rows.map((r, i) => ( ))}
Tariff Option Secured Sales Orders Avg Order
{r[0]} {fmtMoney(r[1])} {fmtInt(r[2])} {fmtMoney(r[3])}
)} {tweaks.showHonesty && (
Heads up — partial period. FY2027 is only 50 days in (Apr–Sep). Figures reflect closed orders to date; pipeline and forecast not included.
)} {tweaks.showCitations && (
Also pulled from {D.DEMO_CITATIONS.map(c => ( {c.title} {c.kind} ))}
)} {tweaks.showDrills && (
Drill into {D.DEMO_DRILLS.map(d => ( ))}
)}
{tweaks.showCost && ( 2 calls · 13,926 tokens · $0.0144 )}
{showExport && setShowExport(false)}/>}
); }; // Live "thinking" indicator — animates while the agent works. const LiveTrailCard = ({ onDone }) => { const D = window.OMNI_DATA; const steps = D.DEMO_TRAIL; const [idx, setIdx] = useStateR(0); useEffectR(() => { if (idx >= steps.length) { setTimeout(onDone, 360); return; } const t = setTimeout(() => setIdx(i => i + 1), 380 + Math.random() * 240); return () => clearTimeout(t); }, [idx]); return (
Routing to MyDashboard · because the question is about FY27 sales
{steps.map((s, i) => { const state = i < idx ? 'done' : i === idx ? 'active' : 'pending'; return (
{state === 'active' ? : } {s.tool} {s.detail}
); })}
); }; Object.assign(window, { ResponseCard, LiveTrailCard, MiniChart, Byline, ExportPop, FilterPop });