// The interactive product demo — 3 styles: chat, timeline, workflow, terminal function DemoPanel({ demo, t }) { if (demo === 'timeline') return ; if (demo === 'workflow') return ; if (demo === 'terminal') return ; return ; } function PanelFrame({ children, label, status = 'live' }) { return (
{label}
{status === 'live' ? 'agent·actif' : 'idle'}
{children}
); } // ============ CHAT ============ function ChatDemo({ t }) { const [step, setStep] = useState(0); const messages = t.chat_messages; useEffect(() => { if (step >= messages.length) return; const d = messages[step].role === 'user' ? 1200 : 1800; const id = setTimeout(() => setStep(s => s + 1), d); return () => clearTimeout(id); }, [step]); useEffect(() => { const id = setInterval(() => setStep(0), 18000); return () => clearInterval(id); }, []); return (
{messages.slice(0, step).map((m, i) => ( ))} {step < messages.length && messages[step].role === 'agent' && (
)}
); } function ChatBubble({ role, text, meta }) { const isUser = role === 'user'; return (
{text}
{meta && {meta}}
); } function Dot({ delay = 0 }) { return ; } // ============ TIMELINE ============ function TimelineDemo({ t }) { const [active, setActive] = useState(0); useEffect(() => { const id = setInterval(() => setActive(a => (a + 1) % t.timeline.length), 2200); return () => clearInterval(id); }, [t.timeline.length]); return (
TRACE · {new Date().toLocaleDateString('fr-CA')} · 14:02:11 EST
{t.timeline.map((step, i) => { const done = i < active; const running = i === active; return (
{done && } {running && }
{step.title}
{step.desc}
{step.meta &&
{step.meta}
}
); })}
); } // ============ WORKFLOW ============ function WorkflowDemo({ t }) { return (
CASTOR · AGENT {t.wf_agent_t1} {t.wf_agent_t2} {t.wf_agent_t3} ▢ chiffré · anonymisé · QC {[60, 150, 240].map((y, i) => ( ))} {[60, 150, 240].map((y, i) => ( ))} ● LIVE · 7 DERNIERS JOURS {[['142', t.wf_m1], ['3.2min', t.wf_m2], ['98%', t.wf_m3], ['0', t.wf_m4]].map(([v, l], i) => ( {v} {l} ))}
); } function WFNode({ x, y, w, label, sub }) { return ( {label} {sub} ); } // ============ TERMINAL ============ function TerminalDemo({ t }) { const [idx, setIdx] = useState(0); const lines = t.terminal; useEffect(() => { if (idx >= lines.length) { const r = setTimeout(() => setIdx(0), 4000); return () => clearTimeout(r); } const id = setTimeout(() => setIdx(i => i + 1), 600 + Math.random() * 500); return () => clearTimeout(id); }, [idx]); return (
{lines.slice(0, idx).map((line, i) => (
{line.type === 'cmd' && <> castor {line.text}} {line.type === 'out' && {line.text}} {line.type === 'ok' && ✓ {line.text}} {line.type === 'tag' && [ {line.text} ]}
))} {idx < lines.length && }
); } Object.assign(window, { DemoPanel, ChatDemo, TimelineDemo, WorkflowDemo, TerminalDemo, PanelFrame, ChatBubble });