// Loop MVP — Today modules (orchestrated by the AI coach layer) // Each module is a self-contained card. The orchestrator on HomeScreen // decides which to show, in what order, ranked by relevance to the day. const Dm = () => window.LOOP_DATA; // ───────────────────────────────────────────────────────────── // ModuleFrame — common chrome: agent attribution + dismiss // ───────────────────────────────────────────────────────────── function ModuleFrame({ agent, children, style = {}, onDismiss }) { return (
{agent}
{onDismiss && ( )}
{children}
); } // ───────────────────────────────────────────────────────────── // InsightsModule — people / company / industry insights with CTAs // ───────────────────────────────────────────────────────────── function InsightsModule({ persona }) { const list = Dm().insights[persona]; return (
Live}>
{/* Leading spacer aligns the first card with the section title left edge */}
); } function InsightCard({ insight }) { const [drafting, setDrafting] = React.useState(false); const [draft, setDraft] = React.useState(insight.draft || ''); const [sent, setSent] = React.useState(false); const [shared, setShared] = React.useState(false); const signalColor = { high: 'var(--loop-orange)', med: 'var(--loop-orange-light)', low: 'var(--dust)' }[insight.signal]; const handleCTA = () => { if (insight.draft) setDrafting(true); else if (insight.shareTo) setShared(true); else setSent(true); }; return (
{insight.eyebrow} {insight.person && ( w[0]).join('').slice(0, 2)} tint="var(--ink)" size={22} photo={insight.person.photo} /> )}
{insight.headline}
{insight.body}
{!drafting && !sent && !shared && ( )} {drafting && (
Draft · in your voice