/* Vooice — extra screens: audit log (ticker tape), reminders (sticky notes),
pricing (service menu), onboarding mobile, and how-it-works marketing. */
// ── Audit log: ticker tape / receipt printer ─────────────────────────────────
function AuditLog({ width = 1320, height = 880, onNavigate }) {
const ENTRIES = [
{ t: '15:51:04', kind: 'CALL.START', id: 'c_3F2A8B', body: 'OUTBOUND → +1 (415) 555-0142 · "Bayview Hair Studio"' },
{ t: '15:51:09', kind: 'TOOL.calendar.read', body: 'check_availability(window=Wed-Thu, 13:00-17:00) → 3 slots' },
{ t: '15:51:18', kind: 'LLM.turn', body: 'Claude · 612 tokens in / 88 out · 920ms' },
{ t: '15:51:30', kind: 'SAFETY.readback', body: '"Thursday at 2 with Marcus Wu, 45 minutes" · awaited 4s' },
{ t: '15:51:38', kind: 'HONESTY.flag', body: 'Callee asked: "are you a real person?"' },
{ t: '15:51:39', kind: 'POLICY.honesty', body: 'rule=disclose_ai · response=truthful + offer_handoff' },
{ t: '15:51:46', kind: 'CALL.add_party', body: 'Dialed +1 (415) 555-0188 (Jordan) · joined at 39.5s' },
{ t: '15:52:24', kind: 'CALL.drop_party', body: 'Jordan dropped · 4.5s on the line' },
{ t: '15:52:48', kind: 'TOOL.calendar.write', body: 'create_event(Thu Apr 9 14:00-14:45, "Haircut · Marcus")' },
{ t: '15:52:50', kind: 'TOOL.contacts.upsert', body: 'Marcus Wu · +1 (415) 555-0142 · tag=barber,haircut' },
{ t: '15:52:58', kind: 'TOOL.message.send', body: 'Telegram → Jordan: "Booked Thu 2pm w/ Marcus"' },
{ t: '15:53:04', kind: 'CALL.END', body: 'Duration 2:00 · cost $0.026 · audit=lograg/c/3F2A8B' },
{ t: '15:53:06', kind: 'EGRESS.recording', body: 'Sealed · vooice-recordings/c_3F2A8B.opus · sha256:9f2…' },
];
return (
EVERY TOOL CALL · EVERY DIAL · EVERY MESSAGE
Audit log
Receipt-style. Read by humans, signed by machines. Nothing she did is hidden.
{/* The receipt */}
VOOICE · CALL c_3F2A8B · 2026-04-08
SIGNED · ed25519/2F:8B…:9A
{ENTRIES.map((e, i) => (
{e.t}
{e.kind}
{e.body}
))}
END · 13 events · 2.0 min · $0.026 · all rules satisfied
POLICY THIS CALL
{[
{ p:'disclose_ai', d:'Honest about being AI when asked' },
{ p:'no_voice_clone', d:'Never speak in your voice' },
{ p:'readback_before_write', d:'Repeat slot before writing' },
{ p:'audit_all_tool_calls', d:'Log every tool invocation' },
{ p:'rate_limit_outbound', d:'Max 8 outbound calls / hour' },
].map(r => (
{r.p.toUpperCase()}
{r.d}
))}
onNavigate && onNavigate('outbound-call')} style={{
width:'100%', padding:'14px', background: VC_TOKENS.ink, color: VC_TOKENS.paper,
border:'none', cursor:'pointer',
fontFamily:"'JetBrains Mono', monospace", fontWeight:700, fontSize:11, letterSpacing:'.14em',
}}>← BACK TO LIVE CALL
);
}
// ── Reminders: sticky notes pinned ───────────────────────────────────────────
function Reminders({ width = 1320, height = 880, onNavigate }) {
// Grouped by horizon, in chronological order. Each item has a person, a
// verb-led label, an optional channel/source, and a state.
const GROUPS = [
{
label: 'Today',
sub: 'Apr 8',
items: [
{ time: '6:30 PM', who: 'Lina', text: 'Pick up Pickle on the way home', via: 'Telegram', fire: 'Vooice will ping you 30 min before' },
{ time: '9:00 PM', who: 'Self', text: 'Start fasting — physical tomorrow', via: 'iCal', fire: 'Silent — confirmation only', pinned: true },
],
},
{
label: 'This week',
sub: 'Apr 9 – Apr 14',
items: [
{ time: 'Wed PM', who: 'Lina', text: 'Check in about the lease — let her vent', via: 'Voice', fire: 'Soft nudge if you haven\u2019t called by 5 PM' },
{ time: 'Fri 9:00', who: 'Self', text: 'Call the dentist re: cleaning', via: 'Vooice', fire: 'Vooice will offer to place the call' },
{ time: 'Mon EOD', who: 'David', text: 'Send the Q3 deck', via: 'Email', fire: 'Reminder at 3 PM Monday' },
],
},
{
label: 'Later',
sub: 'After Apr 14',
items: [
{ time: 'Apr 21', who: 'Eli', text: 'Kindergarten play — RSVP yes', via: 'Calendar', fire: '24h advance notice' },
{ time: 'Apr 22', who: 'Mom', text: 'Sunday dinner — bring the bread', via: 'Telegram', fire: 'Saturday morning reminder' },
{ time: 'Apr 24', who: 'Jared', text: 'Follow up — hasn\u2019t replied in 11 days', via: 'SMS', fire: 'Vooice will draft a check-in' },
],
},
];
return (
{/* Header strip */}
8 OPEN · 3 FIRING THIS WEEK · LAST UPDATED 2 MIN AGO
Reminders
Vooice will surface each one at the right moment — by call, text, or a quiet ping. Never naggy.
FILTER
ALL · ANY CHANNEL
+ NEW REMINDER
{/* Summary metrics */}
{[
{ k: 'OPEN', v: '8', s: 'across 3 horizons' },
{ k: 'FIRING TODAY', v: '2', s: '6:30 PM · 9:00 PM' },
{ k: 'AWAITING REPLY', v: '1', s: 'Jared · 11 days' },
{ k: 'COMPLETED · WK', v: '14', s: '+3 vs. last week' },
].map((m, i) => (
))}
{/* Ledger groups */}
{GROUPS.map((g, gi) => (
{g.label}
{g.sub.toUpperCase()}
{g.items.length} ITEM{g.items.length === 1 ? '' : 'S'}
{g.items.map((it, i) => (
))}
))}
);
}
function ReminderRow({ item, last }) {
return (
{/* Time */}
{item.pinned && (
)}
{item.time.toUpperCase()}
{/* Who */}
{/* Body */}
{/* Channel */}
VIA
{item.via.toUpperCase()}
{/* Action */}
);
}
// ── Pricing: restaurant service menu ─────────────────────────────────────────
function Pricing({ width = 1320, height = 880, onNavigate }) {
return (
EST. 2026 · ONE NUMBER · ONE PERSON
The Service Menu
Plain prices. No seats, no surprises. Cancel any time.
Tax & gratuity not included. Honesty included.
);
}
function PriceRow({ name, price, sub, details = [], featured, tail }) {
return (
{name}
{featured && HOUSE PICK }
{sub}
{price}
{details.length > 0 && (
{details.map(d => (
· {d}
))}
)}
);
}
// ── Onboarding mobile flow ──────────────────────────────────────────────────
function MobileOnboarding() {
const [step, setStep] = React.useState(0);
const STEPS = [
{ title: 'Hi.', sub: 'Vooice is the assistant you call. Let\u2019s set you up — about 90 seconds.', cta:'BEGIN' },
{ title: 'Your number.', sub: 'We assigned you +1 (415) 555-0188. Save it as "Vooice" in your contacts.', cta:'SAVED', code: '+1 (415) 555-0188' },
{ title: 'Connect Telegram?', sub: 'So you can text her too — voice and written. We recommend it.', cta:'CONNECT' },
{ title: 'Calendar?', sub: 'So she can read your week and book without checking with you.', cta:'CONNECT GOOGLE' },
{ title: 'One promise.', sub: 'Vooice will never impersonate you, never train on your data, and will say she\u2019s AI when asked.', cta:'GOT IT' },
{ title: 'Try her.', sub: 'Call your Vooice number now. Ask her anything — "what\u2019s on my calendar today" is a good start.', cta:'CALL VOOICE', call: true },
];
const s = STEPS[step];
return (
STEP {step+1} / {STEPS.length}
SKIP
{STEPS.map((_, i) => (
))}
{s.title}
{s.sub}
{s.code && (
{s.code}
)}
{s.call && (
TAP TO DIAL · ALWAYS FREE
)}
setStep(s2 => Math.min(STEPS.length - 1, s2 + 1))} style={{
width:'100%', padding: 18, background: VC_TOKENS.signal, color: VC_TOKENS.paper, border:'none',
fontFamily:"'JetBrains Mono', monospace", fontWeight:700, letterSpacing:'.14em', fontSize: 12,
}}>{s.cta} →
);
}
// ── Shared header for new screens ──────────────────────────────────────────
function Header({ onNavigate, crumbs = [], dark }) {
const fg = dark ? VC_TOKENS.paper : VC_TOKENS.ink;
const bg = dark ? VC_TOKENS.ink : VC_TOKENS.paper;
return (
onNavigate && onNavigate('home')} style={{ cursor:'pointer' }}>
{crumbs.map((c, i) => (
{c}{i < crumbs.length - 1 ? ' /' : ''}
))}
);
}
Object.assign(window, { AuditLog, Reminders, Pricing, MobileOnboarding });