/* My Vital Cell β€” Floating "Get in Touch" CTA Self-contained overlay: animated dot-grid-headset agent icon, popup with Contact Us + Custom Plan Builder (persona-aware), inline captcha in chat, markdown rendering, plan-context handoff to AI. */ (function () { const { useState, useEffect, useRef, useMemo } = React; /* ---------- Mobile popup fix (viewport-safe, keyboard-safe) ---------- */ if (typeof document !== 'undefined' && !document.getElementById('mvc-cta-mobile-css')) { const s = document.createElement('style'); s.id = 'mvc-cta-mobile-css'; s.textContent = ` @media (max-width: 720px) { .mvc-cta-popup { width: 96vw !important; height: min(88vh, 88dvh) !important; min-width: 0 !important; min-height: 0 !important; max-width: 96vw !important; border-radius: 20px !important; } .mvc-cta-popup > div { border-radius: 18px !important; } } @supports (height: 100dvh) { @media (max-width: 720px) { .mvc-cta-popup { height: 88dvh !important; } } } `; document.head.appendChild(s); } /* ---------- Client-side mirror of src/lib/mvc-agent (personas + catalog) ---------- */ const PERSONAS = [ { key: 'biohacker', label: 'The Biohacker', desc: 'Quantified-self, stack optimizer, reads the papers.', color: '#7A5CC6', emoji: '🧬', goals: ['longevity', 'cognitive', 'metabolic'] }, { key: 'athlete', label: 'The Athlete', desc: 'Trains hard, needs recovery and edge.', color: '#0F5B60', emoji: 'πŸ‹οΈ', goals: ['recovery', 'metabolic', 'longevity'] }, { key: 'aesthetic', label: 'Skin & Hair', desc: 'Focused on visible results β€” glow, thickness, post-procedure.', color: '#E24A63', emoji: '✨', goals: ['regeneration'] }, { key: 'founder', label: 'The Executive', desc: 'High-output, cognitive edge, resilient sleep.', color: '#3A6EA5', emoji: '⚑', goals: ['cognitive', 'longevity', 'metabolic'] }, { key: 'longevity', label: 'Healthy Aging', desc: 'Playing the long game β€” mitochondria, resilience, prevention.', color: '#C9A84C', emoji: '🌿', goals: ['longevity', 'regeneration', 'metabolic'] }, { key: 'recovery-injury', label: 'Injury Recovery', desc: 'Rehabbing something specific and want it healed right.', color: '#2F855A', emoji: '🩹', goals: ['recovery'] }, ]; const CATALOG = [ { slug: 'ghk-cu', name: 'GHK-Cu Copper Peptide', cat: 'regeneration', catLabel: 'Regeneration', route: 'topical', price: 79, beginner: true, blurb: 'Copper tripeptide β€” signals repair and remodeling.', protocol: '2mg/mL serum, AM/PM to clean skin', timing: 'Daily; visible change by week 6.', rationale: 'Studied for collagen synthesis and follicle stimulation.' }, { slug: 'bpc-blend', name: 'BPC-157 + TB-500 Blend', cat: 'regeneration', catLabel: 'Regeneration', route: 'inj', price: 189, blurb: 'Synergy blend for skin/hair regeneration.', protocol: '250mcg SC daily, 4 weeks on / 2 off', timing: 'Morning, empty stomach.', rationale: 'Repair vascularization + tissue remodeling.' }, { slug: 'bpc-157', name: 'BPC-157', cat: 'recovery', catLabel: 'Recovery', route: 'inj', price: 99, beginner: true, blurb: 'The most-studied tissue-repair peptide.', protocol: '250–500mcg SC daily near site, 4–6 weeks', timing: 'Post-training or bedtime.', rationale: 'Angiogenic; tendon/ligament/gut healing pathways.' }, { slug: 'tb-500', name: 'TB-500 (Thymosin Ξ²4)', cat: 'recovery', catLabel: 'Recovery', route: 'inj', price: 149, blurb: 'Slower-acting recovery peptide.', protocol: '2mg 2Γ—/wk Γ— 4 weeks, then 2mg weekly', timing: 'Split doses across the week.', rationale: 'Actin modulation β€” cell migration and repair.' }, { slug: 'kpv', name: 'KPV Anti-Inflammatory', cat: 'recovery', catLabel: 'Recovery', route: 'oral', price: 89, beginner: true, blurb: 'Oral tripeptide for systemic + gut inflammation.', protocol: '500mcg oral daily', timing: 'Morning with water.', rationale: 'Ξ±-MSH fragment β€” NF-ΞΊB pathway.' }, { slug: 'aod-9604', name: 'AOD-9604', cat: 'metabolic', catLabel: 'Metabolic', route: 'inj', price: 109, beginner: true, blurb: 'GH fragment β€” fat metabolism without GH side effects.', protocol: '300mcg SC daily, fasted AM', timing: '30 min before food.', rationale: 'Targets lipolysis without affecting IGF-1.' }, { slug: 'tesofensine', name: 'Tesofensine Research Kit', cat: 'metabolic', catLabel: 'Metabolic', route: 'oral', price: 179, blurb: 'Advanced-only appetite research compound.', protocol: 'Micro-doses, 4 weeks on / 4 off, HR monitoring', timing: 'Morning only.', rationale: 'Triple monoamine reuptake β€” cardio caution.' }, { slug: 'epithalon', name: 'Epithalon', cat: 'longevity', catLabel: 'Longevity', route: 'inj', price: 129, beginner: true, blurb: 'Pineal peptide β€” telomerase + circadian regulation.', protocol: '10mg SC daily Γ— 10 days, twice yearly', timing: 'Evening before sleep.', rationale: 'Studied for telomerase and melatonin rhythm.' }, { slug: 'mots-c', name: 'MOTS-c', cat: 'longevity', catLabel: 'Longevity', route: 'inj', price: 149, blurb: 'Mitochondrial-derived β€” metabolic + longevity.', protocol: '10mg SC 2–3Γ—/wk Γ— 6 weeks', timing: 'Pre-training days.', rationale: 'AMPK activator; improves insulin sensitivity.' }, { slug: 'semax', name: 'Semax Nasal', cat: 'cognitive', catLabel: 'Cognitive', route: 'topical', price: 89, beginner: true, blurb: 'Intranasal nootropic β€” focus + neuroprotection.', protocol: '300–600mcg intranasal, AM only', timing: 'Up to 5 days/week.', rationale: 'Increases BDNF; no HPA activation.' }, { slug: 'selank', name: 'Selank Nasal', cat: 'cognitive', catLabel: 'Cognitive', route: 'topical', price: 89, beginner: true, blurb: 'Anxiolytic nootropic β€” calm focus.', protocol: '300mcg intranasal 1–2Γ—/day', timing: 'AM + midday if needed.', rationale: 'GABA + enkephalin modulation.' }, ]; const BUDGET_CAP = { low: 175, mid: 425, high: 900 }; /* ---------- Minimal Markdown β†’ JSX (bold, bullets, line breaks, headers) ---------- */ function Markdown({ text }) { const lines = String(text || '').split('\n'); const blocks = []; let list = null; const flush = () => { if (list) { blocks.push(list); list = null; } }; lines.forEach((raw, i) => { const line = raw.replace(/\s+$/, ''); if (/^\s*[-β€’]\s+/.test(line)) { if (!list) list = { type: 'ul', items: [] }; list.items.push(line.replace(/^\s*[-β€’]\s+/, '')); } else if (/^#{1,3}\s+/.test(line)) { flush(); const level = line.match(/^#+/)[0].length; blocks.push({ type: 'h', level, text: line.replace(/^#+\s+/, '') }); } else if (line.trim() === '') { flush(); blocks.push({ type: 'br' }); } else { flush(); blocks.push({ type: 'p', text: line }); } }); flush(); const inline = (s) => { // **bold** then `code` β€” safe minimal parser const parts = []; const re = /\*\*(.+?)\*\*/g; let last = 0, m; while ((m = re.exec(s))) { if (m.index > last) parts.push(s.slice(last, m.index)); parts.push({m[1]}); last = m.index + m[0].length; } if (last < s.length) parts.push(s.slice(last)); return parts; }; return (
{blocks.map((b, i) => { if (b.type === 'h') return React.createElement('div', { key: i, style: { fontWeight: 700, fontSize: 14, margin: '4px 0' } }, inline(b.text)); if (b.type === 'ul') return ; if (b.type === 'br') return
; return
{inline(b.text)}
; })}
); } /* ---------- Animated Dot-Grid + Headset Agent Icon ---------- */ function AgentIcon({ size = 22, tone = 'auto' }) { const ref = useRef(null); useEffect(() => { let raf = 0; const dots = ref.current?.querySelectorAll('circle.dot') || []; const start = performance.now(); const tick = (t) => { const dt = (t - start) / 1000; dots.forEach((d, i) => { const r = parseFloat(d.dataset.br); const col = i % 5, row = (i / 5) | 0; const wave = 0.5 + 0.5 * Math.sin(dt * 1.6 + (col + row) * 0.55); d.setAttribute('r', (r * (0.75 + wave * 0.5)).toFixed(2)); d.setAttribute('opacity', (0.45 + wave * 0.55).toFixed(2)); }); raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, []); const stroke = tone === 'light' ? '#fff' : 'currentColor'; const s = size; return ( {Array.from({ length: 25 }).map((_, i) => { const col = i % 5, row = (i / 5) | 0; const br = row === 2 && (col === 1 || col === 3) ? 1.5 : 0.95; return ; })} ); } /* ---------- Plan builder (mirrors src/lib/mvc-agent/planner.ts) ---------- */ function buildPlan({ persona, goals, experience, route, budget, safetyFlags }) { if (safetyFlags.length) return { blocked: true, reasons: safetyFlags }; const p = PERSONAS.find(x => x.key === persona) || null; const gs = goals.length ? goals : (p?.goals ?? []); let pool = CATALOG.filter(c => gs.includes(c.cat)); if (route === 'inj') pool = pool.filter(c => c.route !== 'oral'); if (route === 'oral') pool = pool.filter(c => c.route !== 'inj'); if (experience === 'new') pool = pool.filter(c => c.beginner); const goalOrder = p?.goals ?? gs; pool.sort((a, b) => { const ai = goalOrder.indexOf(a.cat), bi = goalOrder.indexOf(b.cat); if (ai !== bi) return (ai < 0 ? 99 : ai) - (bi < 0 ? 99 : bi); if (experience === 'new') return (b.beginner ? 1 : 0) - (a.beginner ? 1 : 0); return a.price - b.price; }); const cap = budget ? BUDGET_CAP[budget] : 425; const items = []; let spent = 0; for (const c of pool) { if (spent + c.price > cap) continue; items.push(c); spent += c.price; if (items.length >= 3) break; } return { blocked: false, persona: p?.label ?? null, items, monthly: spent }; } /* ---------- Builder wizard ---------- */ function Builder({ onAddToCart, onOpenAI, onPlanChange }) { const [step, setStep] = useState(0); const [state, setState] = useState({ persona: null, personas: [], goals: [], experience: null, route: null, budget: null, age: null, pregnant: null, condition: null, onMed: null, }); const set = (k, v) => setState(s => ({ ...s, [k]: v })); const toggle = (k, v) => setState(s => { const arr = s[k] || []; return { ...s, [k]: arr.includes(v) ? arr.filter(x => x !== v) : [...arr, v] }; }); const safetyFlags = []; if (state.pregnant === 'yes') safetyFlags.push('Pregnancy / breastfeeding β€” peptide research protocols are not appropriate. Please consult a physician.'); if (state.condition === 'yes') safetyFlags.push('Active serious condition β€” plan requires physician oversight before proceeding.'); if (state.onMed === 'yes' && state.goals.includes('metabolic')) safetyFlags.push('Already on a GLP-1 or similar β€” stacking is unsafe without medical supervision.'); if (state.age === 'under') safetyFlags.push('Under 21 β€” our research protocols require adult (21+) participation.'); const steps = [ { title: 'Which of these fit your research goals?', subtitle: 'Pick as many as apply β€” we\'ll tune the whole plan around them.', kind: 'persona' }, { title: 'Which other fields are you interested to incorporate?', subtitle: 'Pick one or more β€” we\'ll balance the plan.', kind: 'goals' }, { title: 'What is your experience with peptides?', field: 'experience', kind: 'chips', opts: [['new', 'Totally New'], ['some', 'Done Some Research'], ['adv', 'Experienced Researcher']] }, { title: 'Monthly budget?', field: 'budget', kind: 'chips', opts: [['low', '$100–250'], ['mid', '$250–500'], ['high', '$500+']] }, { title: 'Disclaimer', kind: 'disclaimer' }, { title: 'Your custom plan', kind: 'result' }, ]; const cur = steps[step]; const canAdvance = (() => { if (cur.kind === 'persona') return (state.personas || []).length > 0; if (cur.kind === 'goals') return state.goals.length > 0; if (cur.kind === 'chips') return !!state[cur.field]; if (cur.kind === 'disclaimer') return !!state.ack; return true; })(); const plan = step === steps.length - 1 ? buildPlan({ ...state, safetyFlags }) : null; // Bubble the current plan context up so the AI has it even before "add to cart" useEffect(() => { if (!onPlanChange) return; onPlanChange({ persona: state.persona, personas: state.personas, goals: state.goals, experience: state.experience, route: state.route, budget: state.budget, health: { age: state.age, pregnant: state.pregnant, condition: state.condition, onMed: state.onMed }, }); }, [state.persona, state.personas, state.goals, state.experience, state.route, state.budget, state.age, state.pregnant, state.condition, state.onMed]); return (
{steps.map((_, i) => (
))}
{cur.title}
{cur.subtitle &&
{cur.subtitle}
} {cur.kind === 'persona' && (
{PERSONAS.map(p => { const sel = state.personas || []; const on = sel.includes(p.key); const pick = () => setState(s => { const cursel = s.personas || []; const next = cursel.includes(p.key) ? cursel.filter(x => x !== p.key) : [...cursel, p.key]; const goals = []; next.forEach(k => { const pp = PERSONAS.find(x => x.key === k); (pp?.goals || []).slice(0, 2).forEach(g => { if (!goals.includes(g)) goals.push(g); }); }); return { ...s, personas: next, persona: next[0] || null, goals }; }); return ( ); })}
)} {cur.kind === 'goals' && (
{[ { k: 'regeneration', t: 'Skin & Aesthetics', d: 'Glow, hair, post-procedure', color: '#E24A63' }, { k: 'recovery', t: 'Recovery & Performance', d: 'Joints, tendons, training', color: '#0F5B60' }, { k: 'metabolic', t: 'Metabolic & Weight', d: 'Appetite, glucose, body comp', color: '#C9A84C' }, { k: 'longevity', t: 'Longevity & Energy', d: 'Mitochondria, healthy aging', color: '#3A6EA5' }, { k: 'cognitive', t: 'Focus & Mood', d: 'Clarity, resilience, sleep', color: '#7A5CC6' }, ].map(g => { const on = state.goals.includes(g.k); return ( ); })}
)} {cur.kind === 'chips' && (
{cur.opts.map(([k, l]) => ( ))}
)} {cur.kind === 'disclaimer' && (
)} {cur.kind === 'result' && plan && ( plan.blocked ? (
Let's talk to a specialist first.
    {plan.reasons.map((r, i) =>
  • {r}
  • )}
) : (
{plan.persona ? <>Tuned for {plan.persona} Β· : null} Estimated monthly: ${plan.monthly}
{plan.items.map(p => (
{p.name}
{p.catLabel} Β· ${p.price}/mo
{p.blurb}
Protocol{p.protocol}
Timing{p.timing}
Why: {p.rationale}
))}
{plan.items.length === 0 &&
No compounds match your filters β€” try loosening budget or route.
}
) )}
{step < steps.length - 1 && ( )}
); } function YesNoRow({ label, val, onSet }) { return (
{label}
{['no', 'yes'].map(v => ( ))}
); } /* ---------- Chat pane with inline captcha + markdown + final synthesis + plan β†’ cart ---------- */ function ChatPane({ context, onAddToCart }) { const [messages, setMessages] = useState([ { role: 'assistant', text: "Hey β€” before I open the floodgates, one **carbon-based** check:", captcha: true }, ]); const [passed, setPassed] = useState(false); const [input, setInput] = useState(''); const [busy, setBusy] = useState(false); const [remaining, setRemaining] = useState(10); const [finalPlan, setFinalPlan] = useState(null); const scrollRef = useRef(null); useEffect(() => { scrollRef.current?.scrollTo({ top: 1e9, behavior: 'smooth' }); }, [messages, busy]); const onCaptchaPass = () => { setPassed(true); setMessages(m => [ ...m, { role: 'user', text: "🐝 not a robot" }, { role: 'assistant', text: context?.goals?.length ? `Nice β€” human confirmed. I've got your plan context (${context.persona || 'no persona set'}, goals: ${context.goals.join(', ') || 'β€”'}). What do you want to dig into?` : "Nice β€” human confirmed. Tell me what you're optimizing for and I'll get specific." }, ]); }; const send = async () => { const q = input.trim(); if (!q || busy || remaining <= 0 || !passed) return; setInput(''); setBusy(true); const next = [...messages, { role: 'user', text: q }]; setMessages(next); try { const agent = window.MVC_AGENT; const reply = agent ? await agent.ask(q, next, context) : { text: "AI specialist is warming up β€” try Contact Us for a human.", counted: false }; setMessages(m => [...m, { role: 'assistant', text: reply.text, final: reply.final }]); if (reply.counted !== false) setRemaining(r => Math.max(0, r - 1)); if (reply.final) { setRemaining(0); setFinalPlan(reply.text); } } catch (e) { setMessages(m => [...m, { role: 'assistant', text: "I hit a snag reaching my server. Please try Contact Us for a human specialist." }]); } finally { setBusy(false); } }; return (
Vital Cell Specialist
{context?.items?.length > 0 && ( )}
{remaining} msgs left
{messages.map((m, i) => (
{m.role === 'user' ? m.text : } {m.captcha && !passed && } {m.final && (
)}
))} {busy && (
thinking…
)} {remaining === 0 && (
Session complete β€” for deeper personalization, book a call with a human specialist.
)}
setInput(e.target.value)} onKeyDown={e => e.key === 'Enter' && send()} placeholder={!passed ? 'Prove you\'re human first ↑' : remaining === 0 ? 'Session complete' : 'Ask about a compound, dose, stack…'} disabled={remaining === 0 || !passed} style={{ flex: 1, padding: '11px 14px', borderRadius: 10, border: '1px solid var(--color-border)', fontSize: 13, outline: 'none', background: '#fff' }} />
); } /* ---------- Inline captcha bubble (charming, low-friction) ---------- */ function InlineCaptcha({ onPass }) { const [pick, setPick] = useState(null); const opts = ['🐝', 'πŸ€–', '🐝']; return (
Tap the one that's not a robot:
{opts.map((e, i) => ( ))}
{pick !== null && opts[pick] !== '🐝' && (
Close β€” the bees are the humans here.
)}
); } /* ---------- Styles ---------- */ const primaryBtn = { padding: '11px 20px', borderRadius: 10, border: 'none', cursor: 'pointer', background: 'var(--color-ink-strong)', color: '#fff', fontSize: 13, fontWeight: 600, letterSpacing: '0.06em', transition: 'background 160ms', }; const ghostBtn = { padding: '11px 18px', borderRadius: 10, cursor: 'pointer', background: 'transparent', color: 'var(--color-ink-strong)', border: '1px solid var(--color-border)', fontSize: 13, fontWeight: 500, }; const inputStyle = { padding: '12px 14px', borderRadius: 10, border: '1px solid var(--color-border)', fontSize: 14, outline: 'none', background: '#fff', fontFamily: 'inherit', color: 'var(--color-ink-strong)', }; /* ---------- Main CTA ---------- */ function CTA() { const [open, setOpen] = useState(false); const [view, setView] = useState('onboard'); const [iconAtBottom, setIconAtBottom] = useState(false); const [planContext, setPlanContext] = useState(null); const [toast, setToast] = useState(null); const [cartOpen, setCartOpen] = useState(false); const goChat = () => { if (!iconAtBottom) { setIconAtBottom(true); setTimeout(() => setView('chat'), 550); } else setView('chat'); }; const startBuilder = () => { setView('builder'); setIconAtBottom(true); }; const addToCart = (items) => { try { if (window.VC_CART && Array.isArray(items)) { items.forEach((it) => { const name = typeof it === 'string' ? it : (it?.name || it?.title || 'Custom item'); window.VC_CART.add({ name, catLabel: it?.catLabel || 'Custom plan', formula: it?.formula || '' }); }); } } catch {} setPlanContext(pc => ({ ...(pc || {}), items })); setToast(`Added ${items.length} item${items.length > 1 ? 's' : ''} to cart`); setTimeout(() => setToast(null), 2400); }; const reset = () => { setView('onboard'); setIconAtBottom(false); }; const onPlanChange = (ctx) => setPlanContext(pc => ({ ...ctx, items: pc?.items })); useEffect(() => { const openFromEvent = (event) => { const nextView = event?.detail?.view || 'builder'; setOpen(true); if (nextView === 'builder' || nextView === 'start') { setView('builder'); setIconAtBottom(true); } else if (nextView === 'contact') { setView('contact'); setIconAtBottom(false); } else if (nextView === 'chat') { setView('chat'); setIconAtBottom(true); } else { setView('onboard'); setIconAtBottom(false); } }; window.addEventListener('mvc-cta-open', openFromEvent); return () => window.removeEventListener('mvc-cta-open', openFromEvent); }, []); useEffect(() => { const updateCartVisibility = (event) => setCartOpen(Boolean(event?.detail?.open)); window.addEventListener('vc-cart-visibility', updateCartVisibility); return () => window.removeEventListener('vc-cart-visibility', updateCartVisibility); }, []); return ( <>
{toast && (
βœ“ {toast}
)} {open && (
{ if (e.target === e.currentTarget) { setOpen(false); reset(); } }} style={{ position: 'fixed', inset: 0, zIndex: 65, background: 'rgba(20,20,28,0.28)', backdropFilter: 'blur(8px)', display: 'flex', alignItems: 'center', justifyContent: 'center', animation: 'mvcFadeIn 200ms ease-out', }}>
{view === 'onboard' && (
How can we help?
Choose the path that fits β€” we'll take it from there.
setView('contact')} full />
)} {view === 'contact' && (
Talk to a specialist
setView('schedule')} /> setView('message')} />
)} {view === 'schedule' && (
Pick a time
{['Mon 10:00', 'Mon 14:30', 'Tue 09:00', 'Tue 15:00', 'Wed 11:00', 'Thu 13:30'].map(s => ( ))}
)} {view === 'message' && (
Send a message