Story to Strategy Visibility Workshop: March 31st @7pm EST

$97.00

What you will takeaway:

  • How to turn real moments into meaningful content

  • The difference between personal vs positioned storytelling

  • How your story leads to opportunities (rooms, media, clients)

  • What to share vs what to protect

Additional takeaways:

  • How to document life in real time

  • How to turn moments into content later

  • Your personal method strategy

  • And more!

** This will be recorded

What you will takeaway:

  • How to turn real moments into meaningful content

  • The difference between personal vs positioned storytelling

  • How your story leads to opportunities (rooms, media, clients)

  • What to share vs what to protect

Additional takeaways:

  • How to document life in real time

  • How to turn moments into content later

  • Your personal method strategy

  • And more!

** This will be recorded

import { useState } from "react";

const STEPS = [
  { id: "spark",      question: "What moment first sparked your journey?",                             placeholder: "e.g. I lost my job and realized I had a gift for helping others rebuild...", hint: "Think of the turning point that set everything in motion." },
  { id: "struggle",   question: "What's the biggest challenge you had to overcome?",                   placeholder: "e.g. I had no network, no budget, and no one believed in my vision...",    hint: "The struggle is where your story gets its power." },
  { id: "superpower", question: "What unique strength did that journey reveal in you?",                placeholder: "e.g. I discovered I could translate complex ideas into simple stories...",  hint: "This becomes the core of your brand." },
  { id: "serve",      question: "Who do you serve, and what transformation do you help them create?",  placeholder: "e.g. I help women entrepreneurs go from invisible to influential...",       hint: "Your mission is rooted in your story." }
];

const AVATAR_STYLES = [
  { label: "Visionary Leader",   desc: "Bold, confident, forward-facing" },
  { label: "Creative Innovator", desc: "Expressive, artistic, dynamic"   },
  { label: "Warm Connector",     desc: "Approachable, genuine, inviting"  },
  { label: "Bold Disruptor",     desc: "Edgy, powerful, unapologetic"     }
];

async function callClaude(systemPrompt, userMessage) {
  const res = await fetch("https://api.anthropic.com/v1/messages", {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "anthropic-version": "2023-06-01",
      "anthropic-dangerous-direct-browser-access": "true"
    },
    body: JSON.stringify({
      model: "claude-haiku-4-5-20251001",
      max_tokens: 1024,
      system: systemPrompt,
      messages: [{ role: "user", content: userMessage }]
    })
  });
  const json = await res.json();
  if (!res.ok) throw new Error(json?.error?.message || `HTTP ${res.status}`);
  return json.content.map(b => b.text || "").join("").trim();
}

const C = {
  bg: "#0d0b09", bgCard: "rgba(28,20,16,0.85)",
  border: "rgba(107,76,54,0.35)", accent: "#a67c5b",
  accentD: "#6b4c36", cream: "#d6c4ae", white: "#f5f0ea", muted: "#6b4c36"
};

const btnStyle = (extra = {}) => ({
  background: `linear-gradient(135deg, ${C.accentD}, ${C.accent})`,
  border: "none", borderRadius: "11px", padding: "12px 26px",
  color: C.white, fontSize: "14px", fontWeight: "600",
  cursor: "pointer", fontFamily: "Georgia, serif",
  boxShadow: "0 4px 16px rgba(0,0,0,0.35)", ...extra
});

const cardStyle = (extra = {}) => ({
  background: C.bgCard, border: `1px solid ${C.border}`,
  borderRadius: "14px", padding: "18px 20px", ...extra
});

export default function App() {
  const [step,        setStep]        = useState("intro");
  const [answers,     setAnswers]     = useState({});
  const [currentQ,    setCurrentQ]    = useState(0);
  const [styleChoice, setStyleChoice] = useState(null);
  const [result,      setResult]      = useState(null);
  const [avatarUrl,   setAvatarUrl]   = useState(null);
  const [busy,        setBusy]        = useState(false);
  const [avatarBusy,  setAvatarBusy]  = useState(false);
  const [errorMsg,    setErrorMsg]    = useState("");
  const [debugMsg,    setDebugMsg]    = useState("");

  const generate = async () => {
    setBusy(true);
    setErrorMsg("");
    setDebugMsg("");
    setStep("generating");
    try {
      const raw = await callClaude(
        `Respond with a single valid JSON object only. No markdown. No backticks. No explanation. Start with { end with }.`,
        `Brand story strategist task. Given these origin story answers:
- Spark: ${answers.spark}
- Struggle: ${answers.struggle}
- Superpower: ${answers.superpower}
- Who they serve: ${answers.serve}

Return this JSON:
{"headline":"1-line brand headline under 12 words","tagline":"5-7 word tagline","story":"3-sentence first-person origin story","archetype":"2-3 word brand archetype","coreMessage":"single most powerful brand message","visibilityStrategy":"2-3 sentences on visibility"}`
      );

      setDebugMsg(raw.slice(0, 100));
      const match = raw.match(/\{[\s\S]*\}/);
      if (!match) throw new Error(`Could not find JSON in response. Got: ${raw.slice(0, 150)}`);
      const parsed = JSON.parse(match[0]);
      setResult(parsed);
      setStep("result");
    } catch (e) {
      setErrorMsg(e.message);
      setStep("style");
    } finally {
      setBusy(false);
    }
  };

  const generateAvatar = async () => {
    setAvatarBusy(true);
    setErrorMsg("");
    try {
      const imgPrompt = await callClaude(
        "You write image generation prompts. Respond with plain text only, no quotes, no JSON.",
        `Write a 35-word photorealistic portrait prompt for a ${styleChoice} professional whose brand archetype is "${result?.archetype}".`
      );
      const encoded = encodeURIComponent(imgPrompt.slice(0, 200));
      setAvatarUrl(`https://image.pollinations.ai/prompt/${encoded}?width=400&height=400&nologo=true`);
    } catch (e) {
      setErrorMsg(e.message);
    } finally {
      setAvatarBusy(false);
    }
  };

  const reset = () => {
    setStep("intro"); setAnswers({}); setCurrentQ(0);
    setStyleChoice(null); setResult(null); setAvatarUrl(null);
    setErrorMsg(""); setDebugMsg("");
  };

  const ErrorBanner = () => errorMsg ? (
    <div style={{ background: "rgba(160,40,20,0.15)", border: "1px solid rgba(200,80,60,0.4)",
      borderRadius: "10px", padding: "11px 15px", marginBottom: "16px",
      color: "#e8a090", fontSize: "12px", wordBreak: "break-word" }}>
      ⚠️ {errorMsg}
    </div>
  ) : null;

  return (
    <div style={{
      minHeight: "100vh",
      background: `linear-gradient(155deg, ${C.bg} 0%, #1c1410 55%, ${C.bg} 100%)`,
      fontFamily: "Georgia, serif", color: C.white,
      display: "flex", flexDirection: "column",
      alignItems: "center", justifyContent: "center",
      padding: "24px"
    }}>
      <style>{`
        @keyframes spin { to { transform: rotate(360deg); } }
        textarea:focus { outline: none; border-color: ${C.accent} !important; box-shadow: 0 0 0 3px rgba(166,124,91,0.18) !important; }
        textarea::placeholder { color: ${C.muted}; opacity: 1; }
      `}</style>

      <div style={{ position: "fixed", top: 0, left: 0, right: 0, height: "3px",
        background: `linear-gradient(90deg, transparent, ${C.accentD}, ${C.cream}, ${C.accentD}, transparent)` }} />

      {/* Header */}
      <div style={{ textAlign: "center", marginBottom: "32px" }}>
        <div style={{ fontSize: "10px", letterSpacing: "5px", textTransform: "uppercase", color: C.accent, marginBottom: "12px" }}>
          Story to Strategy Workshop
        </div>
        <h1 style={{
          fontSize: "clamp(28px,5vw,46px)", fontWeight: "300", margin: 0, lineHeight: 1.15,
          background: `linear-gradient(135deg,#fff 0%,${C.cream} 55%,${C.accent} 100%)`,
          WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent"
        }}>Your Brand Avatar</h1>
        <p style={{ color: C.muted, fontSize: "14px", marginTop: "8px", fontStyle: "italic" }}>
          From your origin story to your brand identity
        </p>
      </div>

      {/* Main card */}
      <div style={{ ...cardStyle(), maxWidth: "660px", width: "100%",
        backdropFilter: "blur(14px)", boxShadow: "0 40px 80px rgba(0,0,0,0.55)" }}>

        {/* INTRO */}
        {step === "intro" && (
          <div style={{ textAlign: "center" }}>
            <div style={{ fontSize: "38px", marginBottom: "18px" }}>✦</div>
            <h2 style={{ fontSize: "22px", fontWeight: "400", marginBottom: "12px" }}>Let's Build Your Brand Avatar</h2>
            <p style={{ color: C.accent, lineHeight: 1.75, marginBottom: "28px", fontSize: "15px" }}>
              Answer 4 questions about your origin story and we'll generate your complete brand identity.
            </p>
            <div style={{ display: "flex", gap: "8px", justifyContent: "center", flexWrap: "wrap", marginBottom: "28px" }}>
              {["Your Spark","Your Struggle","Your Superpower","Your Mission"].map(s => (
                <span key={s} style={{ padding: "6px 14px", borderRadius: "20px",
                  border: "1px solid rgba(166,124,91,0.3)", fontSize: "12px", color: C.cream }}>{s}</span>
              ))}
            </div>
            <button style={btnStyle()} onClick={() => setStep("questions")}>Begin My Story →</button>
          </div>
        )}

        {/* QUESTIONS */}
        {step === "questions" && (
          <div>
            <div style={{ display: "flex", gap: "6px", marginBottom: "26px" }}>
              {STEPS.map((_, i) => (
                <div key={i} style={{ height: "3px", flex: 1, borderRadius: "2px",
                  background: i <= currentQ ? `linear-gradient(90deg,${C.accentD},${C.cream})` : "rgba(255,255,255,0.08)",
                  transition: "background 0.3s" }} />
              ))}
            </div>
            <div style={{ fontSize: "10px", letterSpacing: "3px", textTransform: "uppercase", color: C.muted, marginBottom: "8px" }}>
              Question {currentQ + 1} of {STEPS.length}
            </div>
            <h2 style={{ fontSize: "20px", fontWeight: "400", marginBottom: "6px", lineHeight: 1.45 }}>
              {STEPS[currentQ].question}
            </h2>
            <p style={{ color: C.muted, fontSize: "13px", marginBottom: "16px", fontStyle: "italic" }}>
              {STEPS[currentQ].hint}
            </p>
            <textarea
              rows={4}
              value={answers[STEPS[currentQ].id] || ""}
              onChange={e => setAnswers(p => ({ ...p, [STEPS[currentQ].id]: e.target.value }))}
              placeholder={STEPS[currentQ].placeholder}
              style={{ width: "100%", background: "rgba(13,11,9,0.7)",
                border: `1px solid ${C.border}`, borderRadius: "11px",
                padding: "14px", color: C.white, fontSize: "15px",
                fontFamily: "Georgia,serif", resize: "vertical",
                boxSizing: "border-box", lineHeight: 1.65 }}
            />
            <div style={{ display: "flex", justifyContent: "flex-end", marginTop: "18px" }}>
              <button
                onClick={() => currentQ < STEPS.length - 1 ? setCurrentQ(q => q + 1) : setStep("style")}
                disabled={!answers[STEPS[currentQ].id]?.trim()}
                style={btnStyle({ opacity: answers[STEPS[currentQ].id]?.trim() ? 1 : 0.35,
                  cursor: answers[STEPS[currentQ].id]?.trim() ? "pointer" : "not-allowed" })}>
                {currentQ < STEPS.length - 1 ? "Next →" : "Choose My Style →"}
              </button>
            </div>
          </div>
        )}

        {/* STYLE PICKER */}
        {step === "style" && (
          <div>
            <h2 style={{ fontSize: "20px", fontWeight: "400", marginBottom: "6px" }}>Choose your brand presence</h2>
            <p style={{ color: C.muted, fontSize: "14px", marginBottom: "20px" }}>Which style best reflects how you show up?</p>
            <ErrorBanner />
            {debugMsg && (
              <div style={{ background: "rgba(0,0,0,0.3)", borderRadius: "8px", padding: "8px 12px",
                marginBottom: "14px", fontSize: "11px", color: "#888", wordBreak: "break-all" }}>
                Debug: {debugMsg}
              </div>
            )}
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "10px", marginBottom: "24px" }}>
              {AVATAR_STYLES.map(s => (
                <div key={s.label} onClick={() => setStyleChoice(s.label)} style={{
                  padding: "15px", borderRadius: "12px", cursor: "pointer",
                  border: styleChoice === s.label ? `2px solid ${C.accent}` : `1px solid ${C.border}`,
                  background: styleChoice === s.label ? "rgba(107,76,54,0.18)" : "rgba(13,11,9,0.45)",
                  transition: "all 0.2s"
                }}>
                  <div style={{ fontWeight: "500", fontSize: "14px", marginBottom: "3px" }}>{s.label}</div>
                  <div style={{ color: C.muted, fontSize: "12px" }}>{s.desc}</div>
                </div>
              ))}
            </div>
            <button onClick={generate} disabled={!styleChoice || busy}
              style={btnStyle({ width: "100%", opacity: styleChoice ? 1 : 0.35,
                cursor: styleChoice ? "pointer" : "not-allowed" })}>
              Generate My Brand Identity ✦
            </button>
          </div>
        )}

        {/* GENERATING */}
        {step === "generating" && (
          <div style={{ textAlign: "center", padding: "48px 0" }}>
            <div style={{ width: "52px", height: "52px", borderRadius: "50%",
              border: "2px solid rgba(107,76,54,0.25)", borderTop: `2px solid ${C.accent}`,
              animation: "spin 1s linear infinite", margin: "0 auto 22px" }} />
            <h2 style={{ fontWeight: "300", fontSize: "20px", marginBottom: "8px" }}>Crafting your brand identity…</h2>
            <p style={{ color: C.muted, fontSize: "14px", fontStyle: "italic" }}>Turning your origin story into strategy</p>
          </div>
        )}

        {/* RESULT */}
        {step === "result" && result && (
          <div>
            <ErrorBanner />
            <div style={{ textAlign: "center", marginBottom: "22px", paddingBottom: "20px", borderBottom: `1px solid ${C.border}` }}>
              <div style={{ fontSize: "10px", letterSpacing: "4px", color: C.accent, textTransform: "uppercase", marginBottom: "8px" }}>
                Your Brand Identity
              </div>
              <h2 style={{ fontSize: "clamp(18px,4vw,26px)", fontWeight: "300", lineHeight: 1.3, marginBottom: "10px",
                background: `linear-gradient(135deg,#fff,${C.cream})`,
                WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" }}>
                {result.headline}
              </h2>
              <span style={{ padding: "5px 18px", border: "1px solid rgba(166,124,91,0.4)",
                borderRadius: "20px", fontSize: "13px", color: C.cream, fontStyle: "italic" }}>
                "{result.tagline}"
              </span>
            </div>

            {/* Avatar */}
            <div style={{ ...cardStyle({ background: "rgba(13,11,9,0.6)", marginBottom: "18px", textAlign: "center" }) }}>
              {avatarUrl ? (
                <>
                  <img src={avatarUrl} alt="avatar" onError={() => setAvatarUrl(null)}
                    style={{ width: "144px", height: "144px", borderRadius: "50%", objectFit: "cover",
                      border: "3px solid rgba(166,124,91,0.5)", boxShadow: "0 8px 28px rgba(0,0,0,0.5)", marginBottom: "10px" }} />
                  <p style={{ margin: 0, color: C.muted, fontSize: "12px" }}>Your {styleChoice} avatar</p>
                </>
              ) : (
                <>
                  <div style={{ width: "90px", height: "90px", borderRadius: "50%", margin: "0 auto 14px",
                    background: "rgba(107,76,54,0.2)", border: `2px solid ${C.border}`,
                    display: "flex", alignItems: "center", justifyContent: "center", fontSize: "32px" }}>👤</div>
                  <button onClick={generateAvatar} disabled={avatarBusy}
                    style={btnStyle({ fontSize: "13px", padding: "9px 20px" })}>
                    {avatarBusy ? "Generating…" : `Generate ${styleChoice} Avatar`}
                  </button>
                </>
              )}
            </div>

            {[
              { label: "Brand Archetype",     value: result.archetype,           icon: "✦" },
              { label: "Your Origin Story",   value: result.story,               icon: "◈" },
              { label: "Core Message",        value: result.coreMessage,         icon: "◉" },
              { label: "Visibility Strategy", value: result.visibilityStrategy,  icon: "▲" }
            ].map(item => (
              <div key={item.label} style={{ ...cardStyle({ marginBottom: "12px", borderLeft: `3px solid ${C.accentD}` }) }}>
                <div style={{ fontSize: "10px", letterSpacing: "2.5px", textTransform: "uppercase", color: C.accent, marginBottom: "6px" }}>
                  {item.icon} {item.label}
                </div>
                <p style={{ margin: 0, color: C.cream, lineHeight: 1.75, fontSize: "14px" }}>{item.value}</p>
              </div>
            ))}

            <button onClick={reset} style={btnStyle({
              width: "100%", marginTop: "6px", background: "transparent",
              border: "1px solid rgba(107,76,54,0.4)", color: C.accent, boxShadow: "none"
            })}>Start Over</button>
          </div>
        )}
      </div>

      <p style={{ marginTop: "22px", color: "rgba(107,76,54,0.4)", fontSize: "11px", letterSpacing: "2px", textTransform: "uppercase" }}>
        Story to Strategy Visibility Workshop
      </p>
    </div>
  );
}