// KineSuite landing — comparison table + roadmap notify form. const { useState: useNotifyS } = React; function CompStatusIcon({ kind }) { const map = { yes: { glyph: '✓', color: 'var(--semantic-green)', bg: 'var(--semantic-green-bg)' }, partial: { glyph: '~', color: 'var(--semantic-yellow)', bg: 'var(--semantic-yellow-bg)' }, no: { glyph: '×', color: 'var(--semantic-red)', bg: 'var(--semantic-red-bg)' }, }; const s = map[kind] || map.no; return ( {s.glyph} ); } function CompHeaderCell({ name, muted, highlight }) { return (
{name}
); } function CompareMobileCard({ row, t }) { const cols = [ { key: 'paper', label: t.compareColPaper }, { key: 'excel', label: t.compareColExcel }, { key: 'ks', label: 'KineSuite', highlight: true }, ]; return (

{row.label}

{cols.map(({ key, label, highlight }) => { const cell = row[key]; return (
{label}
{cell.label && ( {cell.label} )}
); })}
); } function ComparisonSection({ t }) { const rows = t.compareRows; return (
{t.compareEyebrow}

{t.compareTitle}

{t.compareSub}

{t.compareCriterion}
{rows.map((row, i) => { const last = i === rows.length - 1; const border = last ? 'none' : '1px solid var(--gray-200)'; return (
{row.label}
{row.paper.label && {row.paper.label}}
{row.excel.label && {row.excel.label}}
{row.ks.label && {row.ks.label}}
); })}
{rows.map((row, i) => ( ))}

{t.compareFootnote}

); } function NotifySection({ t }) { const [email, setEmail] = useNotifyS(''); const [scaleId, setScaleId] = useNotifyS(t.notifyScales[0].id); const [done, setDone] = useNotifyS(false); const [error, setError] = useNotifyS(false); const scale = t.notifyScales.find((s) => s.id === scaleId) || t.notifyScales[0]; const submit = (e) => { e.preventDefault(); const ok = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim()); if (!ok) { setError(true); return; } setError(false); try { localStorage.setItem('kinesuite-notify', JSON.stringify({ email: email.trim(), scaleId, at: Date.now() })); } catch {} setDone(true); }; return (
{t.notifyEyebrow}

{t.notifyTitle}

{t.notifySub}

{done ? (

{t.notifyDoneTitle}

{t.notifyDoneBody.replace('{scale}', scale.label)}

) : (
{error &&

{t.notifyError}

}

{t.notifyFinePrint}

{t.notifyTrustNoSpam}

)}
); } Object.assign(window, { ComparisonSection, NotifySection, });