/* CONTACT view — interactive form with validation */ const { useState: useStateC } = React; function Contact({ go }){ const S = window.SITE; const [f, setF] = useStateC({ name:'', email:'', topic:'', msg:'' }); const [touched, setTouched] = useStateC({}); const [sent, setSent] = useStateC(false); const [time, setTime] = useStateC(''); React.useEffect(() => { const tick = () => { const d = new Date(); setTime(d.toUTCString().split(' ')[4] + ' UTC'); }; tick(); const id = setInterval(tick, 1000); return () => clearInterval(id); }, []); const errs = { name: f.name.trim().length < 2 ? 'Tell me your name' : '', email: !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(f.email) ? 'A valid email, please' : '', msg: f.msg.trim().length < 10 ? 'A little more detail (10+ chars)' : '', }; const valid = !errs.name && !errs.email && !errs.msg; const set = (k) => (e) => setF(s => ({...s, [k]:e.target.value})); const blur = (k) => () => setTouched(s => ({...s, [k]:true})); const submit = (e) => { e.preventDefault(); setTouched({name:true,email:true,msg:true}); if (valid) setSent(true); }; const topics = ['Policy research', 'Mission operations', 'Speaking / writing', 'Just saying hi']; return (
{/* left — invite + methods */}
Contact — 03 Let’s talk
policy, ops, or
orbit.
Open to policy research and governance work where operational insight and structured thinking add value. Reach out — I read everything. Email {S.email} LinkedIn {S.linkedin}
Based {S.location} {time}
{/* right — form */}
{!sent ? (
TRANSMIT MESSAGE
{touched.name&&errs.name && {errs.name}}
{touched.email&&errs.email && {errs.email}}
{topics.map(t => ( ))}
{touched.msg&&errs.msg && {errs.msg}}
) : (

Transmission received.

Thanks, {f.name.split(' ')[0]}. Your message is in the queue — I’ll reply to {f.email} soon.

)}
); } window.Contact = Contact;