// VibeAlchemy Marketing · shared components const { useState, useEffect, useRef } = React; // ── Navigation helpers ──────────────────────────────────────────────────── function go(route, e) { if (e) e.preventDefault(); window.location.hash = route; window.scrollTo({ top: 0, behavior: 'instant' }); } function useRoute() { const [route, setRoute] = useState(() => window.location.hash.replace(/^#/, '') || '/'); useEffect(() => { const onHash = () => setRoute(window.location.hash.replace(/^#/, '') || '/'); window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); return route; } // ── Brand: Forged V mark + wordmark ─────────────────────────────────────── // CANONICAL SOURCE: ui/src/components/brand/Logo.jsx. This is a hand-kept // mirror because the marketing pages run via in-browser Babel (not the Vite // module graph) and cannot import from src/. If the mark geometry or wordmark // changes, update BOTH this block and Logo.jsx. // Raw half + seam use theme vars so the mark flips on light surfaces. let _vaMarkUid = 0; function LogoMark({ size = 22 }) { const gid = `va-mk-${++_vaMarkUid}`; return ( ); } function BrandWord() { return ( VibeAlchemy ); } // ── Top nav ─────────────────────────────────────────────────────────────── function TopNav({ route, theme, onToggleTheme }) { const active = (r) => route === r || (r !== '/' && route.startsWith(r)); const nextTheme = theme === 'dark' ? 'light' : 'dark'; const [mobileOpen, setMobileOpen] = useState(false); const close = () => setMobileOpen(false); const navLink = (path, label) => ( { close(); go(path, e); }}>{label} ); return ( ); } // ── Footer ─────────────────────────────────────────────────────────────── function Footer() { return ( ); } // ── Section wrappers ───────────────────────────────────────────────────── function Section({ eyebrow, headline, sub, children, bg, narrow, id, className = '' }) { return (
{(eyebrow || headline || sub) && (
{eyebrow &&
{eyebrow}
} {headline &&

{headline}

} {sub &&

{sub}

}
)} {children}
); } // ── Decision Memo artifact (hero visual) ───────────────────────────────── function MemoArtifact({ verdict = 'cond', verdictLabel = 'Conditional Go', score = 73, title, insight, assumption, redline, meta }) { return (
Real run · Anonymized
{title || 'Decision Memo'}
{meta || 'D2C Subscription · 2026-05-22 · Run #017'}
{verdictLabel}
Composite Score
{score} / 100
Confidence
Moderate · 3 / 5
Key Insight
"{insight || 'Premium home coffee enthusiasts seek diverse, fresh, single-origin beans from specific regions — a $20B market currently underserved by subscriptions that lack true curation and independent roaster focus.'}"
Riskiest Assumption
{assumption || 'Home coffee enthusiasts will readily switch from their existing "meticulously curated system" to a new subscription service for convenience.'}
{redline || 'Test before scaling · 15–20 enthusiast interviews · <20% switch willingness kills it'}
); } // ── Doc preview (deliverable tile artifact) ─────────────────────────────── function DocPreview({ kind, pill, pillText }) { if (kind === 'memo') { return (
Conditional Go
); } if (kind === 'market') { return (
TAM $2.4B
); } if (kind === 'red') { return (
Red Team · 3 objections
); } if (kind === 'pivot') { return (
3 adjacent angles
01
02
03
); } return null; } // ── Pipeline stage icons (line-art) ─────────────────────────────────────── const StageIcons = { Frame: ( ), Research: ( ), Analyse: ( ), Challenge: ( ), Decide: ( ), }; // ── Final CTA block ─────────────────────────────────────────────────────── function FinalCTA({ headline, sub, kicker, source }) { const isBeta = window.PRIVATE_BETA !== false; const defaultSub = isBeta ? "Private beta — invitation only. We're inviting founders in small batches. Founding pricing held for invitees." : 'Free first run. First 100 paying customers lock in 50% off year 1. No card required.'; return (
{kicker &&
{kicker}
}

{headline || "You don't need another framework. You need a verdict you can defend."}

{sub || defaultSub}

{isBeta ? ( { e.preventDefault(); openWaitlist({ source: source || 'marketing' }); }}>Request access → ) : ( Start free → )}

{isBeta ? 'Invite-only · We reply within a few days · No spam' : 'No card · No commitment · No spam'}

); } // ── Trust strip ─────────────────────────────────────────────────────────── function TrustStrip() { return (
Built solo by an{' '} go('/about', e)} style={{ cursor: 'pointer' }}>AI researcher Creator of PyTorch Tabular ·{' '} 1.6k stars Author of a{' '} best-selling AI book 6 papers {' · '}2 patents · ∞ ideas
); } // ── FAQ Accordion ───────────────────────────────────────────────────────── function FAQAccordion({ items }) { const [open, setOpen] = useState(0); return (
{items.map((it, i) => (
setOpen(open === i ? -1 : i)}>
{it.q} +
{it.a}
))}
); } // ── Page hero (compact, for inner pages) ────────────────────────────────── function PageHero({ eyebrow, headline, sub }) { return (
{eyebrow}

{headline}

{sub &&

{sub}

}
); } // ── Waitlist modal (private beta) ───────────────────────────────────────── // Public API: window.openWaitlist({ source, tier_interest }) dispatches a // custom event picked up by (mounted once in App). // `source` should be one of the values accepted by /api/waitlist: // 'marketing' | 'all_in_page' | 'footer'. `tier_interest` is optional and // only used as a hint when the user opened the modal from a tier card. function openWaitlist(detail) { window.dispatchEvent(new CustomEvent('va:waitlist-open', { detail: detail || {} })); try { window.track && window.track('waitlist_open', { source: (detail && detail.source) || 'marketing' }); } catch (_) {} } function WaitlistRoot() { const [open, setOpen] = useState(false); const [meta, setMeta] = useState({ source: 'marketing', tier_interest: null }); const [email, setEmail] = useState(''); const [stage, setStage] = useState(''); const [status, setStatus] = useState('idle'); // idle | submitting | ok | err const [errMsg, setErrMsg] = useState(''); useEffect(() => { const onOpen = (e) => { const d = (e && e.detail) || {}; setMeta({ source: d.source || 'marketing', tier_interest: d.tier_interest || null }); setStatus('idle'); setErrMsg(''); setEmail(''); setStage(''); setOpen(true); }; window.addEventListener('va:waitlist-open', onOpen); const onKey = (e) => { if (e.key === 'Escape') setOpen(false); }; window.addEventListener('keydown', onKey); return () => { window.removeEventListener('va:waitlist-open', onOpen); window.removeEventListener('keydown', onKey); }; }, []); if (!open) return null; const submit = async (e) => { e.preventDefault(); if (!email || !/.+@.+\..+/.test(email)) { setErrMsg('Enter a valid email.'); return; } setStatus('submitting'); setErrMsg(''); try { const res = await fetch('/api/waitlist', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email.trim(), tier_interest: meta.tier_interest, idea_stage: stage || null, source: meta.source, }), }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error((body && body.detail && body.detail.message) || 'Couldn\'t reach the waitlist. Try again shortly.'); } setStatus('ok'); try { window.track && window.track('waitlist_submit', { source: meta.source, tier_interest: meta.tier_interest, idea_stage: stage || null }); } catch (_) {} } catch (err) { setStatus('err'); setErrMsg(err.message || 'Something went wrong.'); } }; return (
{ if (e.target === e.currentTarget) setOpen(false); }} style={{ position: 'fixed', inset: 0, zIndex: 1000, background: 'rgba(8, 6, 4, 0.72)', backdropFilter: 'blur(4px)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20, }} >
{status === 'ok' ? (
YOU'RE IN

Thanks — we'll be in touch.

We're inviting beta users in small batches. You'll hear from us at {email} when your invite is ready. Founding pricing is held for invitees.

) : (
PRIVATE BETA · INVITATION ONLY

Request access

We're letting beta users in batches. Drop your email and the stage you're at — we'll prioritise serious founders first.

setEmail(e.target.value)} placeholder="you@company.com" style={{ width: '100%', padding: '10px 12px', fontSize: 14, background: 'var(--obsidian)', color: 'var(--parchment)', border: '1px solid var(--line-2)', borderRadius: 2, fontFamily: 'inherit', marginBottom: 14, boxSizing: 'border-box', }} /> {meta.tier_interest && (

Interested in: {meta.tier_interest === 'all_in' ? 'All-In' : meta.tier_interest}

)} {errMsg && (

{errMsg}

)}

No spam · We invite in small batches

)}
); } // Make available globally to other scripts Object.assign(window, { go, useRoute, TopNav, Footer, Section, MemoArtifact, DocPreview, StageIcons, FinalCTA, TrustStrip, FAQAccordion, PageHero, openWaitlist, WaitlistRoot, });