1const { Section: CSection, Eyebrow: CEyebrow, Button: CButton, Card: CCard, Badge: CBadge, Input: CInput, Select: CSelect, Toast: CToast, Checkbox: CCheckbox } = window.BrettLovinsDesignSystem_c58f11; 2 3/* Booking card: links out to Brett's Cal.com page instead of embedding the calendar. */ 4function SchedulerEmbed() { 5 return ( 6 <CCard padding="32px"> 7 <h3 style={{ fontSize: "var(--text-h4)", fontWeight: 700, margin: 0 }}>Pick a time</h3> 8 <p style={{ margin: "6px 0 0", fontSize: 13.5, color: "var(--text-muted)" }}> 9 Booking takes about a minute. 10 </p> 11 <div style={{ background: "var(--surface-brand-soft)", border: "1px solid var(--blue-100)", borderRadius: "var(--radius-lg)", padding: "24px", marginTop: 22 }}> 12 <p style={{ margin: 0, fontSize: 15.5, lineHeight: 1.65, color: "var(--text-body)" }}> 13 A 20 minute call, on my real calendar. Pick any open slot that works for you and 14 you'll get a confirmation with the video link right away. 15 </p> 16 <CButton variant="primary" size="lg" href="https://cal.com/sober-curious-consulting/free-consulting-20-min-meeting" target="_blank" rel="noopener" style={{ marginTop: 20 }}> 17 See available times 18 </CButton> 19 </div> 20 <p style={{ margin: "18px 0 0", fontSize: 14, color: "var(--text-muted)" }}> 21 Scheduling is handled by Cal.com. No account needed on your end. 22 </p> 23 </CCard> 24 ); 25} 26 27function ContactPage() { 28 const [sent, setSent] = React.useState(false); 29 const [sending, setSending] = React.useState(false); 30 const [fields, setFields] = React.useState({ name: "", email: "", company: "", interest: "Not sure yet", message: "" }); 31 const [joinList, setJoinList] = React.useState(false); 32 const set = (k) => (e) => setFields({ ...fields, [k]: e && e.target && e.target.value !== undefined ? e.target.value : e }); 33 34 /* Netlify Forms: posts to "/" on the live site (detected via the hidden static form in 35 index.html). Anywhere Netlify isn't handling it (like this preview), falls back to 36 opening an email draft so no message is ever silently lost. */ 37 const submit = async () => { 38 if (sending) return; 39 setSending(true); 40 /* Opted into the list: subscribe via MailerLite (same form as the site's signup bands) */ 41 if (joinList && fields.email.includes("@")) { 42 try { 43 const fd = new FormData(); 44 fd.append("fields[email]", fields.email.trim()); 45 fd.append("ml-submit", "1"); 46 fd.append("anticsrf", "true"); 47 fetch("https://assets.mailerlite.com/jsonp/1997282/forms/192614282274277149/subscribe", { method: "POST", body: fd }); 48 } catch (err) { /* best effort */ } 49 } 50 try { 51 const r = await fetch("/", { 52 method: "POST", 53 headers: { "Content-Type": "application/x-www-form-urlencoded" }, 54 body: new URLSearchParams({ "form-name": "contact", ...fields, "join-list": joinList ? "Yes" : "No" }).toString(), 55 }); 56 if (!r.ok) throw new Error("form endpoint not active"); 57 setSent(true); 58 } catch (err) { 59 const body = encodeURIComponent( 60 "Name: " + fields.name + "\nEmail: " + fields.email + "\nCompany: " + fields.company + 61 "\nInterested in: " + fields.interest + "\n\n" + fields.message 62 );
63 window.location.href = "mailto:[email protected]?subject=" + encodeURIComponent("Website inquiry") + "&body=" + body; 64 } finally { 65 setSending(false); 66 } 67 }; 68 return ( 69 <main> 70 <CSection style={{ padding: "72px 0 40px" }}> 71 <div style={{ maxWidth: 640 }}> 72 <CEyebrow>Book a call</CEyebrow> 73 <h1 className="site-h1" style={{ fontSize: "var(--text-h1)" }}>Twenty minutes, no pitch.</h1> 74 <p className="site-lede"> 75 Tell me what's going on in your workplace and I'll tell you honestly whether I can 76 help. If I'm not the right fit, I'll point you to someone who is. 77 </p> 78 </div> 79 </CSection> 80 81 <CSection style={{ padding: "0 0 96px" }}> 82 <div className="bl-2col" style={{ display: "grid", gridTemplateColumns: "1.25fr 1fr", gap: 32, alignItems: "start" }}> 83 <SchedulerEmbed /> 84 <CCard padding="32px"> 85 <h3 style={{ fontSize: "var(--text-h4)", fontWeight: 700, margin: 0 }}>Prefer to write</h3> 86 <p style={{ margin: "6px 0 0", fontSize: 13.5, color: "var(--text-muted)" }}> 87 I reply within one business day. 88 </p> 89 <div style={{ display: "flex", flexDirection: "column", gap: 16, marginTop: 22 }}> 90 <CInput label="Name" placeholder="Your name" value={fields.name} onChange={set("name")} /> 91 <CInput label="Work email" placeholder="[email protected]" value={fields.email} onChange={set("email")} /> 92 <CInput label="Company or organization" placeholder="Company" value={fields.company} onChange={set("company")} /> 93 <CSelect label="What are you interested in?" value={fields.interest} onChange={set("interest")} options={["Peer training, co-delivered", "QPR suicide prevention training", "A solo workshop or toolbox talk", "Speaking", "Not sure yet"]} /> 94 <CInput label="Anything I should know?" multiline placeholder="Crew size, industry, timing, budgetâ¦" value={fields.message} onChange={set("message")} /> 95 <CCheckbox label="Join my email list" checked={joinList} onChange={(v) => setJoinList(v && v.target ? v.target.checked : !!v)} /> 96 <CButton variant="primary" size="lg" onClick={submit} disabled={sending}>{sending ? "Sendingâ¦" : "Send message"}</CButton> 97 </div> 98 <p style={{ marginTop: 18, marginBottom: 0, fontSize: 14, color: "var(--text-muted)" }}> 99 Or email me directly: <a href="mailto:brett@brettlovins.
99com">[email protected]</a> 100 </p> 101 </CCard> 102 </div> 103 {sent && ( 104 <div style={{ position: "fixed", bottom: 24, right: 24, zIndex: 90 }}> 105 <CToast tone="success" title="Message sent" description="Thanks. I'll reply within one business day." /> 106 </div> 107 )} 108 </CSection> 109 </main> 110 ); 111} 112 113window.ContactPage = ContactPage;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.