// Verticals hub — tabbed domain selector const DOMAIN_ORDER = ['legal', 'realestate', 'accounting', 'assistant', 'restauration', 'transport', 'security', 'forensics']; function VerticalsHub({ t }) { const [active, setActive] = useState('legal'); const d = t.domains[active]; return (
{/* Domain selector — horizontal scroll pills */}
{/* Fade edges */}
{DOMAIN_ORDER.map(k => { const dom = t.domains[k]; const on = active === k; return ( ); })}
{/* Content panel */}
{d.label}

{d.title}

{d.desc}

« {d.quote} »
{/* Features grid */}
{d.features.map((f, i) => ( ))}
{/* Compliance bar */}
{t.lang === 'fr' ? 'Conformité' : 'Compliance'}
{d.compliance}
); } // Per-domain visual — right column of the active panel function DomainVisual({ kind, t }) { if (kind === 'legal') return ; if (kind === 'realestate') return ; if (kind === 'accounting') return ; if (kind === 'assistant') return ; if (kind === 'restauration') return ; if (kind === 'transport') return ; if (kind === 'security') return ; if (kind === 'forensics') return ; return null; } // --- Domain visuals --------------------------------------------------------- function VisualFrame({ children, label }) { return (
{label}
{children}
); } function AccountingVisual({ t }) { const rows = t.lang === 'fr' ? [ ['Loyer reçu · Unité 204', '+1 450,00', 'Revenus location', 'classé'], ['Rona · matériaux', '−328,47', 'Entretien immeuble', 'classé'], ['Facture Hydro · 2340 St-Denis', '−612,30', 'Services publics', 'à valider'], ['Dépôt Desjardins', '+3 400,00', 'Revenus location', 'classé'], ['Repas client · Europea', '−147,82', 'Représentation (50%)', 'classé'], ] : [ ['Rent received · Unit 204', '+1,450.00', 'Rental income', 'posted'], ['Rona · materials', '−328.47', 'Building maintenance', 'posted'], ['Hydro bill · 2340 St-Denis', '−612.30', 'Utilities', 'review'], ['Desjardins deposit', '+3,400.00', 'Rental income', 'posted'], ['Client meal · Europea', '−147.82', 'Meals (50%)', 'posted'], ]; return (
{rows.map((r, i) => (
{r[0]} {r[1]} {r[2]} {r[3]}
))}
{t.lang === 'fr' ? '142 transactions · 3 à valider' : '142 transactions · 3 to review'} {t.lang === 'fr' ? 'TPS/TVQ prêt' : 'GST/QST ready'}
); } function AssistantVisual({ t }) { const briefing = t.lang === 'fr' ? { label: 'briefing · mardi 14 avril', weather: 'Montréal · 7°C · ciel dégagé', items: [ { time: '09:00', title: 'Revue stratégie Q2', who: 'Salle Rosemont · 45 min', status: 'confirmé' }, { time: '11:30', title: 'Appel J.-F. Bouchard', who: 'relance 3e · priorité', status: 'à préparer' }, { time: '12:30', title: 'Lunch · Europea', who: 'rés. pour 3 · préféré 2023', status: 'réservé' }, { time: '15:00', title: 'Signature bail commercial', who: 'Me Tremblay · Zoom', status: 'docs prêts' }, ], followups: '3 suivis aujourd’hui · 1 urgent', } : { label: 'briefing · tuesday, april 14', weather: 'Montréal · 7°C · clear', items: [ { time: '09:00', title: 'Q2 strategy review', who: 'Rosemont room · 45 min', status: 'confirmed' }, { time: '11:30', title: 'Call J.-F. Bouchard', who: '3rd follow-up · priority', status: 'prep needed' }, { time: '12:30', title: 'Lunch · Europea', who: 'table for 3 · favorite 2023', status: 'booked' }, { time: '15:00', title: 'Sign commercial lease', who: 'Me Tremblay · Zoom', status: 'docs ready' }, ], followups: '3 follow-ups today · 1 urgent', }; return (
{briefing.weather}
{briefing.items.map((it, i) => (
{it.time}
{it.title}
{it.who}
{it.status}
))}
{briefing.followups}
); } function RestoVisual({ t }) { const fr = t.lang === 'fr'; const bookings = fr ? [ { t: '18:30', p: 2, n: 'Leblanc', tag: 'régulier' }, { t: '19:00', p: 4, n: 'Gagnon', tag: 'anniv.' }, { t: '19:15', p: 6, n: 'Desjardins corp.', tag: 'VIP' }, { t: '19:45', p: 2, n: 'Tremblay', tag: 'nouveau' }, { t: '20:00', p: 3, n: 'Martin', tag: 'rappelé' }, ] : [ { t: '18:30', p: 2, n: 'Leblanc', tag: 'regular' }, { t: '19:00', p: 4, n: 'Gagnon', tag: 'birthday' }, { t: '19:15', p: 6, n: 'Desjardins corp.', tag: 'VIP' }, { t: '19:45', p: 2, n: 'Tremblay', tag: 'new' }, { t: '20:00', p: 3, n: 'Martin', tag: 'confirmed' }, ]; return (
{bookings.map((b, i) => (
{b.t} {b.p} {b.n} {b.tag}
))}
{fr ? '42 couverts · 5 relances envoyées' : '42 covers · 5 reminders sent'} {fr ? '2 no-show rebookés' : '2 no-shows rebooked'}
); } function TransportVisual({ t }) { const fr = t.lang === 'fr'; const trips = fr ? [ { id: 'TR-1182', from: 'Laval', to: 'Québec', truck: 'T-07', status: 'en route', eta: '14:42' }, { id: 'TR-1183', from: 'Montréal', to: 'Sherbrooke', truck: 'T-03', status: 'chargement', eta: '—' }, { id: 'TR-1184', from: 'Longueuil', to: 'Trois-Rivières', truck: 'T-11', status: 'assigné', eta: '15:10' }, { id: 'TR-1185', from: 'Mirabel', to: 'Gatineau', truck: 'T-05', status: 'livré', eta: '13:58' }, ] : [ { id: 'TR-1182', from: 'Laval', to: 'Québec', truck: 'T-07', status: 'en route', eta: '2:42 pm' }, { id: 'TR-1183', from: 'Montréal', to: 'Sherbrooke', truck: 'T-03', status: 'loading', eta: '—' }, { id: 'TR-1184', from: 'Longueuil', to: 'Trois-Rivières', truck: 'T-11', status: 'assigned', eta: '3:10 pm' }, { id: 'TR-1185', from: 'Mirabel', to: 'Gatineau', truck: 'T-05', status: 'delivered', eta: '1:58 pm' }, ]; return (
{trips.map((tr, i) => (
{tr.id}
{tr.from} {tr.to} {tr.truck}
{tr.status} {tr.eta}
))}
{fr ? '12 camions actifs · 4 en attente' : '12 trucks active · 4 idle'} {fr ? 'SAAQ · à jour' : 'SAAQ · current'}
); } function SecurityVisual({ t }) { const fr = t.lang === 'fr'; const events = fr ? [ { time: '14:02:03', type: 'scan', desc: 'Scan adversariel lancé · modèle GPT-4o', status: 'en cours' }, { time: '14:02:11', type: 'alert', desc: 'Injection de prompt détectée · bloquée', status: 'bloqué' }, { time: '14:02:18', type: 'scan', desc: 'Test jailbreak #47 · résistance confirmée', status: 'ok' }, { time: '14:02:24', type: 'alert', desc: 'Fuite de données PII · garde-fou actif', status: 'bloqué' }, { time: '14:02:31', type: 'scan', desc: 'Audit guardrails terminé · 12/12 passés', status: 'ok' }, ] : [ { time: '2:02:03pm', type: 'scan', desc: 'Adversarial scan started · GPT-4o model', status: 'running' }, { time: '2:02:11pm', type: 'alert', desc: 'Prompt injection detected · blocked', status: 'blocked' }, { time: '2:02:18pm', type: 'scan', desc: 'Jailbreak test #47 · resistance confirmed', status: 'ok' }, { time: '2:02:24pm', type: 'alert', desc: 'PII data leak attempt · guardrail active', status: 'blocked' }, { time: '2:02:31pm', type: 'scan', desc: 'Guardrail audit complete · 12/12 passed', status: 'ok' }, ]; return (
{events.map((ev, i) => (
{ev.time}
{ev.desc}
{ev.status}
))}
{fr ? '47 tests · 2 menaces bloquées' : '47 tests · 2 threats blocked'} {fr ? 'score: 96/100' : 'score: 96/100'}
); } function ForensicsVisual({ t }) { const fr = t.lang === 'fr'; const items = fr ? [ { id: 'DOC-0014', type: 'Courriel', source: 'Exchange', entities: 12, status: 'analysé' }, { id: 'DOC-0015', type: 'PDF contrat', source: 'SharePoint', entities: 34, status: 'analysé' }, { id: 'DOC-0016', type: 'Relevé bancaire', source: 'OSINT', entities: 8, status: 'en cours' }, { id: 'DOC-0017', type: 'Image EXIF', source: 'Forensique', entities: 3, status: 'analysé' }, { id: 'DOC-0018', type: 'Chat Slack', source: 'Export', entities: 21, status: 'en file' }, ] : [ { id: 'DOC-0014', type: 'Email', source: 'Exchange', entities: 12, status: 'analyzed' }, { id: 'DOC-0015', type: 'Contract PDF', source: 'SharePoint', entities: 34, status: 'analyzed' }, { id: 'DOC-0016', type: 'Bank statement', source: 'OSINT', entities: 8, status: 'running' }, { id: 'DOC-0017', type: 'Image EXIF', source: 'Forensic', entities: 3, status: 'analyzed' }, { id: 'DOC-0018', type: 'Slack chat', source: 'Export', entities: 21, status: 'queued' }, ]; return (
{items.map((it, i) => (
{it.id}
{it.type}
{it.source}
{it.entities} {fr ? 'entités' : 'entities'} {it.status}
))}
{fr ? '1 204 documents · 78 entités extraites' : '1,204 documents · 78 entities extracted'} {fr ? 'custody: vérifié' : 'custody: verified'}
); } function FeatureBlock({ tag, title, desc, first }) { const [hov, setHov] = useState(false); return (
setHov(true)} onMouseLeave={() => setHov(false)} style={{ padding: '30px 26px', borderRight: '1px solid var(--border)', borderBottom: '1px solid var(--border)', background: hov ? 'color-mix(in oklch, var(--brand) 2.5%, var(--bg-elev))' : 'var(--bg-elev)', transition: 'background 150ms', }}>
{tag}
{title}
{desc}
); } function CompareTable({ t }) { return (
{t.compare_them}
CASTOR
{t.compare_rows.map((row, i) => (
{row[0]}
{row[1]}
))}
); } function ConciergeMockup({ t }) { return (
Concierge Castor
BON DE TRAVAIL · #4821
Fuite · Unité 304
Plombier Tremblay · demain 9h
); } function PhoneFrame({ children }) { return (
{children}
); } function CTA({ t }) { return (
}>{t.cta_pill}

{t.cta_title_1} {t.cta_title_2}

{t.cta_sub}

{t.cta_pills.map((p, i) => ( {p} ))}
); } function Footer({ t }) { return ( ); } Object.assign(window, { VerticalsHub, CTA, Footer, PhoneFrame, FeatureBlock, CompareTable, ConciergeMockup, DomainVisual, AccountingVisual, AssistantVisual, RestoVisual, TransportVisual, SecurityVisual, ForensicsVisual });