import { useState, useEffect, useCallback } from "react"; const QUESTIONS = [ { act: "Act I — The Signal", actSub: "What you actually know", q: "When a colleague or friend needs help and calls you first — what's the topic?", sub: "Not what you want to be known for. What they actually call you about.", hint: "e.g. \"Closing deals over email\" or \"Getting their first 10 clients\" or \"Fixing their supply chain\"", minChars: 30 }, { act: "Act I — The Signal", actSub: "What you actually know", q: "Tell me about the best result you've gotten for someone. What happened, and roughly how long did it take?", sub: "A real story. One person, one outcome. Ballpark timeline is fine.", hint: "e.g. \"Client went from $8k/mo to $40k/mo in 90 days after we restructured their offer\"", minChars: 50 }, { act: "Act I — The Signal", actSub: "What you actually know", q: "What's a belief or approach in your field that most people have wrong — and what do you do instead?", sub: "This is your contrarian edge. The thing that makes you roll your eyes at the standard advice.", hint: "e.g. \"Everyone says post more content. I teach people to stop posting and start conversations instead.\"", minChars: 40 }, { act: "Act II — The Person", actSub: "Who you actually serve", q: "Describe your best client or student. Not ideal — real. What were they doing (and struggling with) before they found you?", sub: "Paint the before-picture. Job title, situation, specific frustration.", hint: "e.g. \"Agency owner, 3 years in, doing $200k/yr, working 60hr weeks, couldn't figure out how to get off the tools\"", minChars: 50 }, { act: "Act II — The Person", actSub: "Who you actually serve", q: "What had they already tried that didn't work? What did those attempts cost them?", sub: "Failed solutions = market signal. This tells you where the real gap is.", hint: "e.g. \"Bought two courses, hired a VA, tried productizing services — all stalled within 60 days\"", minChars: 40 }, { act: "Act II — The Person", actSub: "Who you actually serve", q: "If they never solve this problem, what does their life or business look like in two years?", sub: "The cost of inaction. This is what you're actually saving them from.", hint: "e.g. \"Burning out, losing their A-players, eventually selling cheap or shutting down\"", minChars: 40 }, { act: "Act III — The Edge", actSub: "Why specifically you", q: "What's the one thing you know that would immediately change how someone sees this problem?", sub: "Your core insight — the thing that feels obvious to you but consistently surprises people.", hint: "e.g. \"Most people think they have a traffic problem. They actually have a conversion problem. I can tell in 10 minutes.\"", minChars: 40 }, { act: "Act III — The Edge", actSub: "Why specifically you", q: "What are people currently spending — in time, money, or both — to solve this problem? Ballpark is fine.", sub: "This is your market signal for pricing. Include courses, coaches, tools, or hours wasted.", hint: "e.g. \"$500–$2k on courses that don't deliver, 10+ hours/week on stuff I could automate in a day\"", minChars: 30 } ]; const LOADING_PHRASES = [ "Extracting your positioning from the signals...", "Mapping your edge to market demand...", "Structuring your value ladder...", "Calibrating your pricing power...", ]; const styles = { "@import": "url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&family=IBM+Plex+Sans:wght@300;400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap')", }; export default function App() { const [answers, setAnswers] = useState(Array(QUESTIONS.length).fill("")); const [current, setCurrent] = useState(0); const [phase, setPhase] = useState("questions"); const [results, setResults] = useState(null); const [errorMsg, setErrorMsg] = useState(""); const [copied, setCopied] = useState(null); const [loadingPhrase] = useState(LOADING_PHRASES[Math.floor(Math.random() * LOADING_PHRASES.length)]); const q = QUESTIONS[current]; const val = answers[current]; const canProceed = val.trim().length >= (q?.minChars || 20); const isLast = current === QUESTIONS.length - 1; const showActHeader = current === 0 || QUESTIONS[current].act !== QUESTIONS[current - 1].act; const pct = Math.round((current / QUESTIONS.length) * 100); const handleAnswer = (e) => { const next = [...answers]; next[current] = e.target.value; setAnswers(next); }; const handleNext = () => { if (!isLast) { setCurrent(c => c + 1); window.scrollTo({ top: 0, behavior: "smooth" }); } else { setPhase("loading"); synthesize(answers); } }; const handleBack = () => { setCurrent(c => c - 1); window.scrollTo({ top: 0, behavior: "smooth" }); }; const handleRestart = () => { setAnswers(Array(QUESTIONS.length).fill("")); setCurrent(0); setPhase("questions"); setResults(null); window.scrollTo({ top: 0, behavior: "smooth" }); }; const handleCopy = (text, key) => { navigator.clipboard.writeText(text).then(() => { setCopied(key); setTimeout(() => setCopied(null), 2000); }); }; const synthesize = async (ans) => { const pairs = QUESTIONS.map((q, i) => `Q${i + 1}: ${q.q}\nAnswer: ${ans[i]}`).join("\n\n"); const prompt = `You are an expert offer architect and positioning strategist. A person has answered 8 behavioral questions about their work. Your job is to synthesize their implied expertise, ideal client, and offer architecture.\n\nHere are their answers:\n\n${pairs}\n\nReturn ONLY a valid JSON object with EXACTLY this structure — no markdown, no code fences, just raw JSON:\n\n{"expertise":"2-3 sentence summary of their actual core expertise, specific and named clearly.","icp":"Specific ideal client description: role/situation, the before-state, what they're frustrated about. 2-3 sentences.","oneLiner":"I help [specific who] [do specific thing] so they [specific outcome]. Make it sharp.","fullPositioning":"3-4 sentence positioning narrative. Who they are, who they serve, what they do differently, what result they deliver.","insight":"2-3 sentences articulating their core contrarian insight. Frame it as a paradigm shift.","ladder":{"entry":{"price":"$97–$297","desc":"Specific low-barrier entry offer. 1-2 sentences."},"core":{"price":"$X,XXX","desc":"Their main monetized offer. Specific. 1-2 sentences."},"premium":{"price":"$X,XXX+","desc":"High-ticket done-with-you. Specific. 1-2 sentences."}},"pricingRationale":"2-3 sentences explaining why you priced the core offer where you did.","leveragePoint":"The single highest-leverage move they could make. Be specific and direct.","ninetyDayMove":"Concrete first 90-day action plan. 3-4 specific steps in order."}`; try { const response = await fetch("https://api.anthropic.com/v1/messages", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "claude-sonnet-4-20250514", max_tokens: 1000, messages: [{ role: "user", content: prompt }] }) }); if (!response.ok) { const err = await response.json().catch(() => ({})); throw new Error(err.error?.message || `API error ${response.status}`); } const data = await response.json(); const raw = data.content?.[0]?.text || ""; const clean = raw.replace(/^```(?:json)?\s*/i, "").replace(/```\s*$/i, "").trim(); let parsed; try { parsed = JSON.parse(clean); } catch (e) { const match = clean.match(/\{[\s\S]*\}/); if (match) { parsed = JSON.parse(match[0]); } else { throw new Error("Could not parse response. Please try again."); } } setResults(parsed); setPhase("results"); window.scrollTo({ top: 0, behavior: "smooth" }); } catch (err) { setErrorMsg(err.message || "Unknown error. Please try again."); setPhase("error"); } }; const s = { body: { fontFamily: "'IBM Plex Sans', system-ui, sans-serif", background: "#0F0F0F", color: "#e8e4de", minHeight: "100vh", margin: 0, padding: 0 }, shell: { maxWidth: 680, margin: "0 auto", padding: "0 24px 120px" }, header: { padding: "48px 0 56px", borderBottom: "1px solid rgba(255,255,255,0.07)", marginBottom: 64 }, eyebrow: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: "#C0272D", marginBottom: 16, display: "flex", alignItems: "center", gap: 12 }, eyebrowLine: { display: "block", width: 24, height: 1, background: "#C0272D" }, h1: { fontFamily: "'Cormorant Garamond', Georgia, serif", fontSize: "clamp(36px,6vw,52px)", fontWeight: 300, lineHeight: 1.1, color: "#e8e4de", marginBottom: 16, letterSpacing: "-0.01em" }, h1em: { fontStyle: "italic", color: "#C0272D" }, headerP: { fontSize: 14, color: "#7a7370", maxWidth: 480, lineHeight: 1.7 }, progressLabel: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, color: "#7a7370", letterSpacing: "0.15em", textTransform: "uppercase", marginBottom: 10, display: "flex", justifyContent: "space-between" }, progressWrap: { height: 1, background: "rgba(255,255,255,0.07)", marginBottom: 64, position: "relative", overflow: "hidden" }, progressFill: (pct) => ({ position: "absolute", left: 0, top: 0, height: "100%", background: "#C0272D", width: `${pct}%`, boxShadow: "0 0 12px #C0272D", transition: "width 0.6s cubic-bezier(0.4,0,0.2,1)" }), actHeader: { marginBottom: 40, paddingBottom: 24, borderBottom: "1px solid rgba(255,255,255,0.07)" }, actLabel: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, letterSpacing: "0.25em", color: "#7a7370", textTransform: "uppercase", marginBottom: 8 }, actTitle: { fontFamily: "'Cormorant Garamond', Georgia, serif", fontSize: 18, fontWeight: 300, color: "#b0a89e", fontStyle: "italic" }, qNumber: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, letterSpacing: "0.2em", color: "#C0272D", textTransform: "uppercase", marginBottom: 20 }, qText: { fontFamily: "'Cormorant Garamond', Georgia, serif", fontSize: "clamp(22px,4vw,30px)", fontWeight: 400, lineHeight: 1.3, color: "#e8e4de", marginBottom: 10, letterSpacing: "-0.01em" }, qSub: { fontSize: 13, color: "#7a7370", marginBottom: 28, lineHeight: 1.6 }, qHint: { fontSize: 12, color: "#7a7370", fontStyle: "italic", marginBottom: 20 }, textarea: { width: "100%", background: "#161616", border: "1px solid rgba(255,255,255,0.07)", borderRadius: 4, color: "#e8e4de", fontFamily: "'IBM Plex Sans', system-ui, sans-serif", fontSize: 15, fontWeight: 300, lineHeight: 1.7, padding: "18px 20px", resize: "none", minHeight: 120, outline: "none", caretColor: "#C0272D", boxSizing: "border-box" }, charCount: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 10, color: "#7a7370", textAlign: "right", marginTop: 6, letterSpacing: "0.05em" }, btnRow: { display: "flex", alignItems: "center", gap: 16, marginTop: 24 }, btnPrimary: (disabled) => ({ background: disabled ? "rgba(192,39,45,0.4)" : "#C0272D", color: "#fff", border: "none", borderRadius: 3, fontFamily: "'IBM Plex Sans', system-ui, sans-serif", fontSize: 13, fontWeight: 500, letterSpacing: "0.08em", textTransform: "uppercase", padding: "14px 32px", cursor: disabled ? "not-allowed" : "pointer" }), btnGhost: { background: "transparent", color: "#7a7370", border: "1px solid rgba(255,255,255,0.07)", borderRadius: 3, fontFamily: "'IBM Plex Sans', system-ui, sans-serif", fontSize: 12, letterSpacing: "0.08em", textTransform: "uppercase", padding: "13px 24px", cursor: "pointer" }, resultBlock: (featured) => ({ background: featured ? "linear-gradient(135deg,#161616,rgba(192,39,45,0.05))" : "#161616", border: featured ? "1px solid rgba(192,39,45,0.4)" : "1px solid rgba(255,255,255,0.07)", borderRadius: 4, padding: 28, marginBottom: 16, position: "relative" }), resultLabel: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 9, letterSpacing: "0.25em", textTransform: "uppercase", color: "#C0272D", marginBottom: 14 }, resultContent: { fontSize: 16, lineHeight: 1.7, color: "#e8e4de" }, copyBtn: (active) => ({ position: "absolute", top: 16, right: 16, background: "transparent", border: active ? "1px solid rgba(192,39,45,0.4)" : "1px solid rgba(255,255,255,0.07)", borderRadius: 3, color: active ? "#C0272D" : "#7a7370", fontFamily: "'IBM Plex Mono', monospace", fontSize: 9, letterSpacing: "0.15em", textTransform: "uppercase", padding: "6px 12px", cursor: "pointer" }), ladder: { display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 12, marginTop: 8 }, ladderTier: (core) => ({ background: core ? "rgba(192,39,45,0.05)" : "#1e1e1e", border: core ? "1px solid rgba(192,39,45,0.4)" : "1px solid rgba(255,255,255,0.07)", borderRadius: 4, padding: "20px 16px" }), tierName: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 9, letterSpacing: "0.2em", textTransform: "uppercase", color: "#7a7370", marginBottom: 6 }, tierPrice: (core) => ({ fontFamily: "'Cormorant Garamond', Georgia, serif", fontSize: 22, color: core ? "#C0272D" : "#e8e4de", marginBottom: 8 }), tierDesc: { fontSize: 12, color: "#7a7370", lineHeight: 1.5 }, loadingWrap: { textAlign: "center", padding: "80px 0" }, loadingOrb: { width: 48, height: 48, border: "1px solid rgba(255,255,255,0.07)", borderTop: "1px solid #C0272D", borderRadius: "50%", margin: "0 auto 32px", animation: "spin 1s linear infinite" }, loadingLabel: { fontFamily: "'IBM Plex Mono', monospace", fontSize: 11, letterSpacing: "0.2em", textTransform: "uppercase", color: "#7a7370" }, loadingSub: { fontSize: 13, color: "#7a7370", marginTop: 12, fontStyle: "italic" }, divider: { height: 1, background: "rgba(255,255,255,0.07)", margin: "32px 0" }, restartRow: { display: "flex", justifyContent: "center", marginTop: 48, paddingTop: 40, borderTop: "1px solid rgba(255,255,255,0.07)" }, synthHeader: { marginBottom: 48 }, synthH2: { fontFamily: "'Cormorant Garamond', Georgia, serif", fontSize: "clamp(28px,5vw,42px)", fontWeight: 300, lineHeight: 1.2, marginBottom: 12 }, synthP: { fontSize: 13, color: "#7a7370" }, errorBox: { background: "rgba(192,39,45,0.1)", border: "1px solid rgba(192,39,45,0.4)", borderRadius: 4, padding: "20px 24px", fontSize: 13, color: "#e8a0a2", lineHeight: 1.6, marginTop: 16 }, oneLiner: { fontFamily: "'Cormorant Garamond', Georgia, serif", fontSize: 20, fontWeight: 400, lineHeight: 1.4 }, }; return (
{/* HEADER */}
MasteryMade Labs · Offer Architect

What do you actually sell?

Answer eight behavioral questions about how you already work. We'll extract the offer, positioning, and pricing you didn't know how to name.

{/* QUESTIONS */} {phase === "questions" && (
Question {current + 1} of {QUESTIONS.length}{pct}%
{showActHeader && (
{q.act}
{q.actSub}
)}
Q{current + 1}
{q.q}
{q.sub}
{q.hint &&
{q.hint}
}