# Project export: MarketVerse

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2026
- Tagline: Simulate 24 months of startup reality in 60 seconds. AI agents play your customers, competitors, and investors, so you know what works before you build.
- Devpost: https://devpost.com/software/marketverse-zgjmlv
- GitHub: https://github.com/dhruvac29/marketverse
- Demo: https://marketverse-cal-hackathon.vercel.app/
- Result: winner (Best Beginner Hack)
- Team: 1 GitHub contributor(s) — dhruvac29 (2 commits)

## Devpost submission (written by the team)

### Inspiration

Most startups fail not because founders can't build but because they build the wrong thing for the wrong market at the wrong price. Validation is slow, expensive, and often comes too late. We wanted to compress years of market feedback into 60 seconds, before a single line of product code is written.

### What it does

MarketVerse is an AI-powered startup simulator. You describe your startup in one paragraph like name, market, pricing, category and within 60 seconds it: 1) Generates a living market: 20 customer personas, 5 competitors, and 3 investors, each powered by Claude AI with their own budgets, behavior patterns, and decision logic 2) Runs 24 months of simulation: MRR growth, churn, competitor moves, and market events (economic downturns, viral moments, regulatory changes) all unfold in real time via a streaming UI 3) Delivers an investor-grade verdict: confidence score, immediate actions, supporting evidence, and a ranked growth playbook 4) Lets you steer: apply a strategic decision (lower price, launch annual plan, ship mobile app, expand market) and Claude re-simulates all 24 months with that change baked in from day one.

### How we built it

Backend - FastAPI with async SSE streaming. Three Claude models run in parallel during market generation: 'claude-sonnet-4.6' for persona and competitor generation, 'claude-haiku-4.5-20251001' for month-by-month economic evaluation, and 'claude-opus-4.8' for the final verdict. The simulation engine publishes events to in-memory asyncio queues and streams them to the client as Server-Sent Events. Frontend - Next.js 16 with React 19. Four distinct UI states (form → generating → running → results) with live-updating KPI cards, an MRR area chart, a market events feed, and an interactive decision panel. Falls back to a full demo mode if the API isn't reachable. AI Architecture - Each month is evaluated by a Claude model that considers the startup's current metrics, active market modifiers, competitor actions, and persona behavior scores. The final verdict uses Claude Opus to synthesize all 24 months into a structured analysis with evidence, immediate actions, and prioritized recommendations.

### Challenges we ran into

Streaming latency: getting real-time SSE to feel smooth while actual Claude inference was happening required careful async pipelining and a sleep between months to let the UI breathe Structured output reliability: coaxing Claude to return valid JSON month-data on every call, including edge cases like month 1 with no prior data required careful prompt engineering and fallback handling Decision re-simulation UX: making "apply a decision and re-run" feel instant even though it triggers a full new 24-month Claude pipeline meant pre-computing modified startup params on the frontend before the API call

### Accomplishments we're proud of

A multi-model Claude architecture where three different models handle different layers of the simulation fast and cheap for high-volume per-month evaluation, powerful for final synthesis A streaming UI that makes a 60-second AI pipeline feel like a live market unfolding rather than a loading spinner The decision engine: being able to change one variable and immediately see 24 months of alternate history is genuinely useful for founders

### What we learned

Multi-model architectures where cheaper/faster models handle high-volume tasks (per-month evaluation) and expensive models handle synthesis (verdict) dramatically improve both cost and latency. The trick is designing clean handoffs between them. We also learned that the best AI product demos aren't chatbots they're experiences where the AI is doing something you couldn't do yourself.

### What's next

Persistent simulation history so founders can compare multiple scenarios side by side Multiplayer mode: two founders simulate competing startups in the same market Export to PDF pitch deck with simulation data as supporting evidence for investor meetings

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 32 recognized source files, 144 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- Next.js (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (41 of 41)

```
.gitignore
api/.env.example
api/agents/__init__.py
api/config.py
api/main.py
api/models/__init__.py
api/models/startup.py
api/requirements.txt
api/routers/__init__.py
api/routers/simulations.py
api/routers/stream.py
api/runtime.txt
api/services/__init__.py
api/services/claude_service.py
api/services/redis_service.py
api/services/sim_store.py
api/simulation/__init__.py
api/simulation/engine.py
api/simulation/market_gen.py
api/simulation/month_runner.py
web/.gitignore
web/AGENTS.md
web/CLAUDE.md
web/eslint.config.mjs
web/next.config.ts
web/package.json
web/postcss.config.mjs
web/README.md
web/src/app/docs/page.tsx
web/src/app/globals.css
web/src/app/how-it-works/page.tsx
web/src/app/layout.tsx
web/src/app/page.tsx
web/src/app/pricing/page.tsx
web/src/app/simulation/page.tsx
web/src/components/Nav.tsx
web/src/components/simulation/SimulationClient.tsx
web/src/lib/sse.ts
web/src/lib/types.ts
web/tailwind.config.ts
web/tsconfig.json
```

### Dependencies

- api/requirements.txt: anthropic@>=0.40.0, anyio@>=3.7.1, fastapi@>=0.115.0, httpx@>=0.27.0, pydantic@>=2.7.0, pydantic-settings@>=2.1.0, python-multipart@>=0.0.9, uvicorn@>=0.30.0
- web/package.json: @tailwindcss/postcss@^4, @types/node@^20, @types/react@^19, @types/react-dom@^19, eslint@^9, eslint-config-next@16.2.9, lucide-react@^1.21.0, next@16.2.9, react@19.2.4, react-dom@19.2.4, recharts@^3.8.1, tailwindcss@^4, typescript@^5

### Recent commits (newest first)

- Fix: pin Python 3.11 and loosen pydantic version for Render deploy
- Initial commit — MarketVerse AI startup simulator

## Key source files (fetched from GitHub, selected and truncated for size)

### web/CLAUDE.md

```markdown
@AGENTS.md

```

### web/AGENTS.md

```markdown
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->

```

### api/requirements.txt

```
fastapi>=0.115.0
uvicorn>=0.30.0
pydantic>=2.7.0
pydantic-settings>=2.1.0
anthropic>=0.40.0
python-multipart>=0.0.9
anyio>=3.7.1
httpx>=0.27.0

```

### web/package.json

```
{
  "name": "web",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {
    "lucide-react": "^1.21.0",
    "next": "16.2.9",
    "react": "19.2.4",
    "react-dom": "19.2.4",
    "recharts": "^3.8.1"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "16.2.9",
    "tailwindcss": "^4",
    "typescript": "^5"
  }
}

```

### api/main.py

```python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from routers import simulations, stream
from config import get_settings

settings = get_settings()

app = FastAPI(title="MarketVerse API", version="0.1.0")

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(simulations.router)
app.include_router(stream.router)


@app.get("/health")
async def health():
    return {"status": "ok", "version": "0.1.0"}

```

### web/src/app/layout.tsx

```typescript
import type { Metadata } from "next";
import "./globals.css";
import Nav from "@/components/Nav";

export const metadata: Metadata = {
  title: "MarketVerse — AI Startup Simulator",
  description:
    "What would happen if you launched your startup today? MarketVerse creates a living market of AI customers, competitors and investors — and runs 24 months in 60 seconds.",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" className="h-full">
      <body className="min-h-full" style={{ background: "#0e1014", color: "#e8eaed" }}>
        <Nav />
        {children}
      </body>
    </html>
  );
}

```

### web/src/app/page.tsx

```typescript
import Link from "next/link";

export default function LandingPage() {
  return (
    <div style={{ fontFamily: "'Space Grotesk',sans-serif", color: "#e8eaed", minHeight: "100vh", background: "#0e1014" }}>

      {/* HERO */}
      <div style={{ padding: "80px 64px 64px", background: "radial-gradient(110% 80% at 70% 0%, oklch(0.8 0.16 150 / 0.09), transparent 55%)" }}>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 10, padding: "7px 14px", border: "1px solid #232730", borderRadius: 40, marginBottom: 28 }}>
          <span style={{ width: 7, height: 7, borderRadius: "50%", background: "oklch(0.8 0.16 150)", boxShadow: "0 0 0 3px oklch(0.8 0.16 150 / 0.2)", display: "inline-block" }}></span>
          <span style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 11, letterSpacing: "0.08em", color: "oklch(0.8 0.16 150)" }}>AI-POWERED STARTUP SIMULATOR</span>
        </div>

        <h1 style={{ fontSize: 68, fontWeight: 700, letterSpacing: "-0.03em", lineHeight: 1.04, margin: "0 0 22px", maxWidth: 900 }}>
          What would happen if you launched your startup today?
        </h1>
        <p style={{ fontSize: 20, lineHeight: 1.55, color: "#9aa0ab", maxWidth: 600, margin: "0 0 36px" }}>
          MarketVerse creates a living market of AI customers, competitors and investors — and runs 24 months of reality in 60 seconds. Know what works before you build.
        </p>

        <div style={{ display: "flex", gap: 14, alignItems: "center", marginBottom: 72 }}>
          <Link href="/simulation" style={{ padding: "14px 28px", borderRadius: 9, background: "oklch(0.8 0.16 150)", color: "#0e1014", fontSize: 15, fontWeight: 700 }}>
            Simulate my startup — free
          </Link>
          <Link href="/how-it-works" style={{ padding: "14px 28px", borderRadius: 9, border: "1px solid #2a2e38", color: "#e8eaed", fontSize: 15 }}>
            See how it works
          </Link>
        </div>

        {/* Product preview */}
        <div style={{ background: "#14171e", border: "1px solid #232730", borderRadius: 14, overflow: "hidden", boxShadow: "0 40px 100px -30px rgba(0,0,0,.7)" }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "16px 26px", borderBottom: "1px solid #232730" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <div style={{ width: 26, height: 26, borderRadius: 7, background: "oklch(0.8 0.16 150)", color: "#0e1014", display: "flex", alignItems: "center", justifyContent: "center", fontWeight: 700, fontSize: 13 }}>S</div>
              <span style={{ fontSize: 15, fontWeight: 600 }}>SweetAI</span>
              <span style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 10, color: "#6b7280", marginLeft: 4 }}>AI OS for bakeries · $49/mo</span>
            </div>
            <span style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 10, color: "oklch(0.8 0.16 150)" }}>SIM COMPLETE · 24/24</span>
          </div>

          <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", borderBottom: "1px solid #232730" }}>
            {[
              { label: "MRR", value: "$26.4k", sub: "▲ 10.3% MoM", subColor: "oklch(0.8 0.16 150)" },
              { label: "ARR", value: "$317k", sub: "▲ on track", subColor: "oklch(0.8 0.16 150)" },
              { label: "CUSTOMERS", value: "487", sub: "▲ +41 this mo", subColor: "oklch(0.8 0.16 150)" },
              { label: "CHURN", value: "4.2%", sub: "▲ watch this", subColor: "oklch(0.8 0.14 70)" },
            ].map((kpi, i) => (
              <div key={kpi.label} style={{ padding: "18px 26px", borderRight: i < 3 ? "1px solid #232730" : undefined }}>
                <div style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 10, color: "#6b7280", letterSpacing: "0.1em" }}>{kpi.label}</div>
                <div style={{ fontSize: 28, fontWeight: 700, marginTop: 6 }}>{kpi.value}</div>
                <div style={{ fontSize: 11, color: kpi.subColor, marginTop: 3 }}>{kpi.sub}</div>
              </div>
            ))}
          </div>

          <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr" }}>
            <div style={{ padding: "22px 26px", borderRight: "1px solid #232730" }}>
              <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 14 }}>Monthly Recurring Revenue</div>
              <svg viewBox="0 0 600 200" style={{ width: "100%", height: "auto", display: "block" }}>
                <defs>
                  <linearGradient id="idx-area" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0" stopColor="oklch(0.8 0.16 150)" stopOpacity={0.28} />
                    <stop offset="1" stopColor="oklch(0.8 0.16 150)" stopOpacity={0} />
                  </linearGradient>
                </defs>
                <line x1="0" y1="50" x2="600" y2="50" stroke="#232730" />
                <line x1="0" y1="100" x2="600" y2="100" stroke="#232730" />
                <line x1="0" y1="150" x2="600" y2="150" stroke="#232730" />
                <path d="M0,175 L26,172 L52,167 L78,161 L104,153 L130,143 L157,131 L183,118 L209,113 L235,117 L261,104 L287,88 L313,72 L339,57 L365,51 L391,55 L417,44 L443,33 L470,24 L496,18 L522,13 L548,9 L574,7 L600,5 L600,195 L0,195 Z" fill="url(#idx-area)" />
                <polyline points="0,175 26,172 52,167 78,161 104,153 130,143 157,131 183,118 209,113 235,117 261,104 287,88 313,72 339,57 365,51 391,55 417,44 443,33 470,24 496,18 522,13 548,9 574,7 600,5" fill="none" stroke="oklch(0.82 0.16 150)" strokeWidth={2.5} strokeLinejoin="round" />
                <line x1="209" y1="20" x2="209" y2="195" stroke="oklch(0.8 0.14 70)" strokeWidth={1} strokeDasharray="4 3" />
                <line x1="391" y1="20" x2="391" y2="195" stroke="oklch(0.7 0.15 25)" strokeWidth={1} strokeDasharray="4 3" />
                <circle cx="600" cy="5" r="5" fill="oklch(0.82 0.16 150)" stroke="#14171e" strokeWidth={2} />
              </svg>
              <di
[truncated — 8711 more characters]
```

### web/src/app/simulation/page.tsx

```typescript
import SimulationClient from "@/components/simulation/SimulationClient";

export default function SimulationPage() {
  return <SimulationClient />;
}

```

### web/src/app/pricing/page.tsx

```typescript
import Link from "next/link";

const plans = [
  {
    tier: "STARTER",
    price: "Free",
    sub: "forever · no card required",
    cta: "Get started",
    ctaStyle: { border: "1px solid #2a2e38", color: "#e8eaed" } as React.CSSProperties,
    featured: false,
    features: [
      { yes: true, label: "1 simulation per month" },
      { yes: true, label: "5 customer personas" },
      { yes: true, label: "Basic 12-month run" },
      { yes: true, label: "Summary verdict report" },
      { yes: false, label: "Decision engine" },
      { yes: false, label: "Full market events" },
      { yes: false, label: "Export & share" },
    ],
  },
  {
    tier: "PRO",
    price: "$29",
    priceSub: "/month",
    sub: "billed monthly · cancel any time",
    cta: "Start Pro free for 14 days",
    ctaStyle: { background: "oklch(0.8 0.16 150)", color: "#0e1014" } as React.CSSProperties,
    featured: true,
    features: [
      { yes: true, label: "Unlimited simulations" },
      { yes: true, label: "20 customer personas" },
      { yes: true, label: "Full 24-month simulation" },
      { yes: true, label: "5 competitor agents" },
      { yes: true, label: "Decision engine" },
      { yes: true, label: "Full market events" },
      { yes: true, label: "Export & share reports" },
      { yes: false, label: "Team collaboration" },
      { yes: false, label: "API access" },
    ],
  },
  {
    tier: "TEAM",
    price: "$99",
    priceSub: "/month",
    sub: "up to 10 seats · annual billing saves 20%",
    cta: "Start Team trial",
    ctaStyle: { border: "1px solid #2a2e38", color: "#e8eaed" } as React.CSSProperties,
    featured: false,
    features: [
      { yes: true, label: "Everything in Pro" },
      { yes: true, label: "Up to 10 team seats" },
      { yes: true, label: "Shared simulation workspace" },
      { yes: true, label: "API access" },
      { yes: true, label: "Custom investor profiles" },
      { yes: true, label: "Priority support" },
      { yes: true, label: "SSO + audit log" },
    ],
  },
];

const faqs = [
  {
    q: "How is this different from asking ChatGPT about my startup?",
    a: "ChatGPT gives you static advice based on patterns. MarketVerse runs a living simulation where 20+ AI agents with distinct behaviors, budgets and biases interact over time. The results emerge from dynamics, not guesses.",
  },
  {
    q: "How accurate are the simulations?",
    a: "The simulations are calibrated against real market dynamics, but they're models — not predictions. The value is in identifying the levers that matter most, stress-testing your assumptions, and surfacing risks you hadn't considered. Think of it as a flight simulator, not a crystal ball.",
  },
  {
    q: "Can I use my own industry research or customer data?",
    a: "On the Team plan, yes — you can upload custom customer profiles and market data to seed the simulation. On Pro, the AI generates market archetypes based on your category and target market description.",
  },
  {
    q: "Is there a money-back guarantee?",
    a: "Yes — 14-day free trial on Pro and Team, no questions asked. If the first simulation doesn't give you something useful to act on, we'll refund the first month.",
  },
];

export default function PricingPage() {
  return (
    <div style={{ fontFamily: "'Space Grotesk',sans-serif", color: "#e8eaed", background: "#0e1014", minHeight: "100vh" }}>

      {/* HERO */}
      <div style={{ padding: "72px 64px 56px", textAlign: "center", borderBottom: "1px solid #1c1f27" }}>
        <div style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 11, letterSpacing: "0.12em", color: "oklch(0.8 0.16 150)", marginBottom: 14 }}>PRICING</div>
        <h1 style={{ fontSize: 54, fontWeight: 700, letterSpacing: "-0.025em", margin: "0 0 16px" }}>Simple, founder-friendly pricing</h1>
        <p style={{ fontSize: 18, color: "#9aa0ab", margin: "0 auto", maxWidth: 520 }}>Start free. Upgrade when the insights start paying for themselves — which usually happens on the first simulation.</p>
      </div>

      {/* PRICING CARDS */}
      <div style={{ padding: "64px 64px", display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 24, maxWidth: 1100, margin: "0 auto" }}>
        {plans.map((plan) => (
          <div key={plan.tier} style={{ background: "#14171e", border: plan.featured ? "2px solid oklch(0.8 0.16 150)" : "1px solid #232730", borderRadius: 16, padding: 32, display: "flex", flexDirection: "column", position: "relative" }}>
            {plan.featured && (
              <div style={{ position: "absolute", top: -13, left: "50%", transform: "translateX(-50%)", background: "oklch(0.8 0.16 150)", color: "#0e1014", padding: "5px 14px", borderRadius: 40, fontSize: 12, fontWeight: 700, whiteSpace: "nowrap" }}>Most popular</div>
            )}
            <div style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 11, letterSpacing: "0.1em", color: plan.featured ? "oklch(0.8 0.16 150)" : "#6b7280", marginBottom: 12 }}>{plan.tier}</div>
            <div style={{ display: "flex", alignItems: "baseline", gap: 6, marginBottom: 4 }}>
              <span style={{ fontSize: 42, fontWeight: 700, letterSpacing: "-0.02em" }}>{plan.price}</span>
              {plan.priceSub && <span style={{ fontSize: 16, color: "#9aa0ab" }}>{plan.priceSub}</span>}
            </div>
            <div style={{ fontSize: 13, color: "#9aa0ab", marginBottom: 28 }}>{plan.sub}</div>
            <Link href="/simulation" style={{ display: "block", padding: 13, borderRadius: 9, fontSize: 14, fontWeight: plan.featured ? 700 : 600, textAlign: "center", marginBottom: 28, ...plan.ctaStyle }}>{plan.cta}</Link>
            <div style={{ borderTop: "1px solid #1c1f27", paddingTop: 24, display: "flex", flexDirection: "column", gap: 12 }}>
              {plan.features.map((f) => (
                <div key={f.label} style={{ display: "flex", gap: 10, fontSize: 14, color: f.yes ? (plan.featured ? "#e8eaed" : "#9aa0ab") : "#5b616b" }}>
                  <span style
[truncated — 1420 more characters]
```

### web/src/app/how-it-works/page.tsx

```typescript
import Link from "next/link";

export default function HowItWorksPage() {
  return (
    <div style={{ fontFamily: "'Space Grotesk',sans-serif", color: "#e8eaed", background: "#0e1014", minHeight: "100vh" }}>

      {/* HERO */}
      <div style={{ padding: "72px 64px 56px", borderBottom: "1px solid #1c1f27" }}>
        <div style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 11, letterSpacing: "0.12em", color: "oklch(0.8 0.16 150)", marginBottom: 14 }}>HOW IT WORKS</div>
        <h1 style={{ fontSize: 58, fontWeight: 700, letterSpacing: "-0.025em", margin: "0 0 18px", maxWidth: 860 }}>Everything that happens inside MarketVerse</h1>
        <p style={{ fontSize: 18, lineHeight: 1.6, color: "#9aa0ab", maxWidth: 640, margin: 0 }}>From a one-line idea to a 24-month market simulation with real AI agents, live events, and a clear verdict on whether your startup would succeed.</p>
      </div>

      {/* STEP 1 */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 64, alignItems: "center", padding: "72px 64px", borderBottom: "1px solid #1c1f27" }}>
        <div>
          <div style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 12, color: "oklch(0.8 0.16 150)", marginBottom: 12 }}>STEP 01</div>
          <h2 style={{ fontSize: 38, fontWeight: 700, letterSpacing: "-0.02em", margin: "0 0 16px" }}>Describe your startup</h2>
          <p style={{ fontSize: 16, lineHeight: 1.65, color: "#9aa0ab", margin: "0 0 24px" }}>Give MarketVerse the basics: your startup name, what it does, who it&apos;s for, how you price it, and what category it sits in. A paragraph is enough — the AI fills in the nuance.</p>
          <div style={{ display: "flex", flexDirection: "column", gap: 10, fontSize: 14, color: "#9aa0ab" }}>
            {["Startup name + one-line description", "Target market and customer segment", "Pricing model and monthly price", "Business category"].map((item) => (
              <div key={item} style={{ display: "flex", gap: 10 }}><span style={{ color: "oklch(0.8 0.16 150)" }}>→</span>{item}</div>
            ))}
          </div>
        </div>
        <div style={{ background: "#14171e", border: "1px solid #232730", borderRadius: 14, padding: 28 }}>
          <div style={{ fontSize: 13, fontWeight: 600, color: "#9aa0ab", marginBottom: 20 }}>Startup details</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {[
              { label: "STARTUP NAME", value: "SweetAI", style: { fontSize: 15, fontWeight: 500 } },
              { label: "DESCRIPTION", value: "AI-powered operating system for sweet shops and bakeries", style: { fontSize: 14, color: "#9aa0ab", lineHeight: 1.5 } },
            ].map((f) => (
              <div key={f.label}>
                <div style={{ fontSize: 11, color: "#6b7280", marginBottom: 6, fontFamily: "'IBM Plex Mono',monospace", letterSpacing: "0.06em" }}>{f.label}</div>
                <div style={{ background: "#0e1014", border: "1px solid #232730", borderRadius: 8, padding: "12px 14px", ...f.style }}>{f.value}</div>
              </div>
            ))}
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
              {[{ label: "TARGET MARKET", value: "Small food businesses" }, { label: "PRICING", value: "$49 / month" }].map((f) => (
                <div key={f.label}>
                  <div style={{ fontSize: 11, color: "#6b7280", marginBottom: 6, fontFamily: "'IBM Plex Mono',monospace", letterSpacing: "0.06em" }}>{f.label}</div>
                  <div style={{ background: "#0e1014", border: "1px solid #232730", borderRadius: 8, padding: "12px 14px", fontSize: 14 }}>{f.value}</div>
                </div>
              ))}
            </div>
            <Link href="/simulation" style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 8, padding: 13, borderRadius: 9, background: "oklch(0.8 0.16 150)", color: "#0e1014", fontSize: 14, fontWeight: 700 }}>Generate market →</Link>
          </div>
        </div>
      </div>

      {/* STEP 2 */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 64, alignItems: "start", padding: "72px 64px", borderBottom: "1px solid #1c1f27", background: "#0b0d11" }}>
        <div style={{ background: "#14171e", border: "1px solid #232730", borderRadius: 14, overflow: "hidden" }}>
          <div style={{ padding: "18px 22px", borderBottom: "1px solid #232730", fontSize: 13, fontWeight: 600 }}>Generated customers <span style={{ fontFamily: "'IBM Plex Mono',monospace", fontSize: 11, color: "oklch(0.8 0.16 150)", marginLeft: 10 }}>20 personas</span></div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
            {[
              { name: "Maria Chen", role: "Artisan Bakery · $200/mo budget", score: 87, color: "oklch(0.8 0.16 150)" },
              { name: "Priya Patel", role: "Patisserie Founder · $300/mo", score: 91, color: "oklch(0.8 0.16 150)" },
              { name: "James O'Brien", role: "Café Chain Manager · $450/mo", score: 72, color: "oklch(0.8 0.14 70)" },
              { name: "Tom Wheeler", role: "Street Vendor · $40/mo budget", score: 45, color: "#4b515c" },
              { name: "Mei Zhang", role: "Upscale Confectionery · $500/mo", score: 88, color: "oklch(0.8 0.16 150)" },
            ].map((p, i) => (
              <div key={p.name} style={{ padding: "14px 18px", borderRight: i % 2 === 0 ? "1px solid #232730" : undefined, borderBottom: i < 4 ? "1px solid #232730" : undefined }}>
                <div style={{ fontSize: 13, fontWeight: 600 }}>{p.name}</div>
                <div style={{ fontSize: 11, color: "#9aa0ab", marginTop: 2 }}>{p.role}</div>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 8 }}>
                  <div style={{ flex: 1, height: 4, background: "#232730", borderRadius: 2 }}>
                    <div style={{ width: `${p.score}%`, height: "100%", background: p.color, borderRadius: 2 }
[truncated — 4562 more characters]
```

[17 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]