/* ========================================================================
   mvp-overrides.jsx — SaaS MVP routes, local persistence, real exports
   ====================================================================== */

const BoltKitMVP = (() => {
  if (!localStorage.getItem("boltkit.cleanWorkspaceV4")) {
    [
      "boltkit.projects",
      "boltkit.assets",
      "boltkit.exports",
      "boltkit.generatedPacks",
      "boltkit.selectedPack",
      "boltkit.currentProjectId"
    ].forEach(key => localStorage.removeItem(key));
    Object.keys(localStorage)
      .filter(key => key.startsWith("boltkit.versions."))
      .forEach(key => localStorage.removeItem(key));
    localStorage.setItem("boltkit.cleanWorkspaceV4", "true");
  }
  const saved = (() => {
    try { return JSON.parse(localStorage.getItem("boltkit.projects") || "[]"); }
    catch (e) { return []; }
  })();

  const testProject = {
    id: "boltkit-test-launch",
    name: "BoltKit",
    tagline: "AI launch-pack generator for app builders",
    icon: { letter: "B", gradient: "linear-gradient(135deg, #EFFF00, #0B0B0B)" },
    url: "http://localhost:5174/",
    status: "Ready",
    statusVariant: "blue",
    readiness: 72,
    missing: 2,
    missingAssets: [
      { name: "Real product screenshots", required: true },
      { name: "Founder demo video", required: false }
    ],
    lastPack: "Not generated yet",
    lastGen: "Never",
    packs: 0,
    audience: "Indie app founders, SaaS builders, no-code builders, agencies and solo product builders using Claude, Codex, Lovable, Cursor, Replit or no-code tools.",
    pain: "Founders finish the product but lose momentum turning screenshots, notes and brand assets into a coherent launch campaign.",
    tone: "Premium, fast, practical, high-energy, motorsport-inspired and direct.",
    summary: "BoltKit turns an app URL, screenshots, brand assets and launch notes into social posts, video scripts, paid ads, app store copy, landing page copy, SEO packs and Claude/Codex prompts.",
    brandSource: "/brand-pack/brand-pack.html",
    brandRules: [
      "Use black, off-white and electric acid yellow as the core system. Acid yellow is the only saturated brand colour.",
      "Keep the identity premium SaaS, high-energy, motorsport/esports/broadcast inspired, sharp and practical.",
      "Use Anton for the wordmark/display moments, Bebas Neue for secondary display, Inter for UI/body copy, and JetBrains Mono for technical labels.",
      "Use diagonal panels, HUD details, checker motifs and sharp lightning bolt identity cues where useful.",
      "Never tint, gradient or over-rotate the lightning bolt. Keep the logo sharp, asymmetric and high-contrast.",
      "Keep copy direct, specific and commercially useful. Avoid generic SaaS filler."
    ],
    features: ["AI project analysis", "Brand kit extraction", "Screenshot intelligence", "Social post generation", "Video ad scripts", "Paid ads", "SEO pack", "Markdown/CSV/JSON/ZIP export"],
    benefits: [
      { t: "Launch faster", s: "Convert raw app material into useful campaign assets without rebuilding the brief every time." },
      { t: "Keep the story consistent", s: "Use one brand and positioning source across every platform." },
      { t: "Ship practical outputs", s: "Generate copy, scripts and prompts that are ready to copy, improve and export." },
      { t: "Work before production setup", s: "Use local mode first, then add auth, payments, storage and production AI." }
    ],
    angles: [
      "Upload your app. Generate the launch pack.",
      "The command centre for indie app launches.",
      "Turn screenshots into launch assets.",
      "From product URL to paid ad scripts in minutes."
    ],
    colors: ["#EFFF00", "#050505", "#0B0B0B", "#F4F4F0", "#FFFFFF"],
    fonts: { heading: "Anton", secondary: "Bebas Neue", body: "Inter", mono: "JetBrains Mono" }
  };

  const legacyDemoAdditions = [
    {
      id: "nibbly",
      name: "Nibbly",
      tagline: "Smart meal planner for busy families",
      icon: { letter: "N", gradient: "linear-gradient(135deg, #EFFF00, #4ADE80)" },
      url: "nibbly.app",
      status: "Ready",
      statusVariant: "green",
      readiness: 78,
      missing: 2,
      lastPack: "Social Content Pack",
      lastGen: "Today",
      packs: 5,
      audience: "Parents and time-poor households that want realistic weekly meals.",
      tone: "Friendly, helpful and practical.",
      summary: "Nibbly turns tastes, budgets and leftovers into weekly meal plans and shopping lists.",
      features: ["Leftover planner", "Budget-aware lists", "Family preferences", "Quick dinners"]
    },
    {
      id: "shift",
      name: "SHIFT",
      tagline: "Training tracker for hybrid athletes",
      icon: { letter: "S", gradient: "linear-gradient(135deg, #EFFF00, #4DA8FF)" },
      url: "shift.training",
      status: "Generated",
      statusVariant: "yellow",
      readiness: 82,
      missing: 1,
      lastPack: "Video Script Pack",
      lastGen: "Today",
      packs: 7,
      audience: "Runners, lifters and hybrid athletes balancing strength and endurance.",
      tone: "Direct, high-energy and coach-like.",
      summary: "SHIFT gives hybrid athletes adaptive plans, recovery guidance and race-ready blocks.",
      features: ["Adaptive blocks", "Recovery score", "Race countdown", "Strength planner"]
    },
    {
      id: "campfind",
      name: "CampFind",
      tagline: "Weekend camping spots without spreadsheet chaos",
      icon: { letter: "C", gradient: "linear-gradient(135deg, #EFFF00, #FF9A33)" },
      url: "campfind.co",
      status: "Needs Analysis",
      statusVariant: "amber",
      readiness: 58,
      missing: 4,
      lastPack: "Landing Page Copy",
      lastGen: "Last week",
      packs: 2,
      audience: "Families and couples looking for quick UK camping breaks.",
      tone: "Outdoorsy, simple and reassuring.",
      summary: "CampFind helps people discover bookable camping spots by distance, amenities and weather.",
      features: ["Weather fit", "Amenity filters", "Shortlist sharing", "Route-aware search"]
    },
    {
      id: "sam-blog",
      name: "Sam vs Everything Blog",
      tagline: "Personal essays, product notes and launch diaries",
      icon: { letter: "S", gradient: "linear-gradient(135deg, #F4F4F0, #EFFF00)" },
      url: "samvseverything.blog",
      status: "Ready",
      statusVariant: "blue",
      readiness: 69,
      missing: 3,
      lastPack: "SEO Pack",
      lastGen: "Yesterday",
      packs: 3,
      audience: "Indie founders and builders following an honest build-in-public journey.",
      tone: "Sharp, candid and useful.",
      summary: "A build log and essay home for shipping apps, learning in public and turning chaos into notes.",
      features: ["Launch diaries", "Product essays", "Resource lists", "Newsletter prompts"]
    }
  ];

  if (!localStorage.getItem("boltkit.profile")) {
    localStorage.setItem("boltkit.profile", JSON.stringify({
      name: "Sam",
      email: "sam@example.com",
      tone: "Premium, punchy, practical",
      workspace: "Sam Test Workspace"
    }));
  }

  const cleanProjects = saved.length ? saved : [testProject];
  PROJECTS.splice(0, PROJECTS.length, ...cleanProjects);
  RECENT_PACKS.splice(0, RECENT_PACKS.length);
  if (!PROJECTS.some(project => project.id === localStorage.getItem("boltkit.currentProjectId"))) {
    localStorage.setItem("boltkit.currentProjectId", PROJECTS[0]?.id || "boltkit-test-launch");
  }

  const preferredOrder = ["boltkit-test-launch"];
  PROJECTS.sort((a, b) => {
    const ai = preferredOrder.indexOf(a.id);
    const bi = preferredOrder.indexOf(b.id);
    if (ai !== -1 || bi !== -1) return (ai === -1 ? 99 : ai) - (bi === -1 ? 99 : bi);
    return a.name.localeCompare(b.name);
  });
  const projectsNav = NAV[0]?.items?.find((item) => item.id === "projects");
  if (projectsNav) projectsNav.count = PROJECTS.length;
  const assetsNav = NAV.flatMap(group => group.items).find((item) => item.id === "assets");
  if (assetsNav) assetsNav.count = 0;
  const outputsNav = NAV.flatMap(group => group.items).find((item) => item.id === "outputs");
  if (outputsNav) outputsNav.count = 0;

  const persistProject = (project) => {
    const existing = JSON.parse(localStorage.getItem("boltkit.projects") || "[]");
    const next = [project, ...existing.filter((p) => p.id !== project.id)];
    localStorage.setItem("boltkit.projects", JSON.stringify(next));
  };

  const slug = (value) => String(value || "project").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "project";
  const file = (name, type, content) => new Blob([content], { type });
  const download = (name, blob) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = name;
    document.body.appendChild(a);
    a.click();
    a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };

  const getExportHistory = () => {
    try { return JSON.parse(localStorage.getItem("boltkit.exports") || "[]"); }
    catch (e) { return []; }
  };
  const recordExport = (project, format, fileName) => {
    const entry = {
      id: `${Date.now()}-${format}`,
      projectId: project?.id || "local-demo",
      projectName: project?.name || "Demo project",
      format: format.toUpperCase(),
      fileName,
      createdAt: new Date().toISOString(),
    };
    const next = [entry, ...getExportHistory()].slice(0, 20);
    try { localStorage.setItem("boltkit.exports", JSON.stringify(next)); } catch (e) {}
    return entry;
  };

  const markdownForProject = (project) => {
    const p = project || PROJECTS[0];
    const generated = (() => { try { return JSON.parse(localStorage.getItem("boltkit.generatedContent") || "{}"); } catch (e) { return {}; } })();
    const generatedSections = Object.entries(generated).map(([packId, output]) => {
      const pack = PACK_TYPES.find((item) => item.id === packId);
      return `## ${pack?.name || output.title || packId}\n${output.content_markdown || JSON.stringify(output.content_json || {}, null, 2)}`;
    }).join("\n\n");
    return `# ${p.name} Launch Pack

## App Summary
${p.summary || p.tagline || p.description || "A focused app ready for launch."}

## Audience
${p.audience || "Indie founders, app builders and early adopters."}

## Positioning
${p.pain || "The target user needs a faster, clearer way to get the job done."}

## Benefits
${(p.benefits || [{ t: "Ship faster", s: "Move from product assets to launch content in one flow." }]).map((b) => `- **${b.t || b}**${b.s ? `: ${b.s}` : ""}`).join("\n")}

## Marketing Angles
${(p.angles || ["Upload your app once. Generate every launch asset.", "Stop rewriting the same product story across channels."]).map((a) => `- ${a}`).join("\n")}

## Brand Pack
Source: ${p.brandSource || "/brand-pack/brand-pack.html"}

Colours: ${(p.colors || []).join(", ")}

Fonts: ${Object.entries(p.fonts || {}).map(([key, value]) => `${key}: ${value}`).join(", ")}

Rules:
${(p.brandRules || ["Keep the work practical, premium and specific."]).map((rule) => `- ${rule}`).join("\n")}

${generatedSections || `## Generated Packs\nNo generated packs are saved yet. Use the AI Marketing Pack Generator, then export again to include real generated content.`}

## Claude Design Prompts
${CLAUDE_PROMPTS.map((p) => `- ${p.name}: ${p.desc}`).join("\n")}

## Codex Prompts
${CODEX_PROMPTS.map((p) => `- ${p.name}: ${p.desc}`).join("\n")}
`;
  };

  const csvCalendar = () => {
    const generated = (() => { try { return JSON.parse(localStorage.getItem("boltkit.generatedContent") || "{}"); } catch (e) { return {}; } })();
    if (generated.social?.content_json?.posts?.length) {
      const rows = [["day", "channel", "hook", "body", "cta"]];
      generated.social.content_json.posts.forEach((post, i) => rows.push([i + 1, post.channel || "Social", post.hook || post.title || "Launch post", post.body || post.caption || "", post.cta || "Try BoltKit"]));
      return rows.map((row) => row.map((cell) => `"${String(cell).replaceAll('"', '""')}"`).join(",")).join("\n");
    }
    const rows = [["day", "channel", "hook", "body", "cta"]];
    [
      ["Instagram", "Upload your app. Generate the launch pack.", "Turn screenshots, brand assets and a URL into a practical launch folder.", "Start Building"],
      ["LinkedIn", "Founders need launch assets, not another blank doc.", "BoltKit generates social posts, ads, video scripts, SEO and prompts from one app brief.", "View Demo"],
      ["Video", "From product URL to ad scripts", "Show the app, the generated pack and the ZIP export in under 30 seconds.", "Generate Pack"]
    ].forEach((row, i) => rows.push([i + 1, ...row]));
    return rows.map((row) => row.map((cell) => `"${String(cell).replaceAll('"', '""')}"`).join(",")).join("\n");
  };

  const exportProject = async (project, format) => {
    const p = project || PROJECTS[0];
    const base = `${slug(p.name)}-launch-pack`;
    const md = markdownForProject(p);
    const generated = (() => { try { return JSON.parse(localStorage.getItem("boltkit.generatedContent") || "{}"); } catch (e) { return {}; } })();
    const json = JSON.stringify({
      project: p,
      packs: PACK_TYPES,
      generated,
      brandPack: {
        source: p.brandSource || "/brand-pack/brand-pack.html",
        colors: p.colors || [],
        fonts: p.fonts || {},
        rules: p.brandRules || []
      }
    }, null, 2);
    if (format === "md") {
      const name = `${base}.md`;
      recordExport(p, format, name);
      return download(name, file(name, "text/markdown", md));
    }
    if (format === "csv") {
      const name = `${base}-content-calendar.csv`;
      recordExport(p, format, name);
      return download(name, file(name, "text/csv", csvCalendar()));
    }
    if (format === "json") {
      const name = `${base}.json`;
      recordExport(p, format, name);
      return download(name, file(name, "application/json", json));
    }
    const zip = new JSZip();
    const root = zip.folder("BoltKit Export");
    const packMarkdown = (id, fallback) => generated[id]?.content_markdown || fallback;
    root.file("brand-summary.md", `# ${p.name} Brand Summary\n\nTone: ${p.tone || "Practical and premium"}\nURL: ${p.url || ""}\nBrand source: ${p.brandSource || "/brand-pack/brand-pack.html"}\n\n## Colours\n${(p.colors || []).map((colour) => `- ${colour}`).join("\n")}\n\n## Fonts\n${Object.entries(p.fonts || {}).map(([key, value]) => `- ${key}: ${value}`).join("\n")}\n\n## Rules\n${(p.brandRules || []).map((rule) => `- ${rule}`).join("\n")}\n`);
    root.file("brand-pack-source.txt", `Open the canonical uploaded guidelines at ${p.brandSource || "/brand-pack/brand-pack.html"} in the local app.`);
    root.file("launch-pack.md", md);
    root.file("instagram-posts.md", packMarkdown("instagram", packMarkdown("social", "# BoltKit Instagram Posts\n\nGenerate the Instagram or Social Content Pack to fill this file with AI content.")));
    root.file("video-scripts.md", packMarkdown("video", "# BoltKit Video Scripts\n\nGenerate the Video Script Pack to fill this file with AI content."));
    root.file("paid-ads.md", packMarkdown("ads", "# BoltKit Paid Ads\n\nGenerate the Paid Ads Pack to fill this file with AI content."));
    root.file("app-store-copy.md", packMarkdown("appstore", "# BoltKit App Store Copy\n\nGenerate the App Store Pack to fill this file with AI content."));
    root.file("landing-page-copy.md", packMarkdown("landing", "# BoltKit Landing Page Copy\n\nGenerate the Landing Page Copy Pack to fill this file with AI content."));
    root.file("seo-pack.md", packMarkdown("seo", "# BoltKit SEO Pack\n\nGenerate the SEO Pack to fill this file with AI content."));
    root.file("claude-prompts.md", CLAUDE_PROMPTS.map((x) => `# ${x.name}\n${x.desc}`).join("\n\n"));
    root.file("codex-prompts.md", CODEX_PROMPTS.map((x) => `# ${x.name}\n${x.desc}`).join("\n\n"));
    root.file("content-calendar.csv", csvCalendar());
    root.file("project-data.json", json);
    const blob = await zip.generateAsync({ type: "blob" });
    const name = `${base}.zip`;
    recordExport(p, format, name);
    download(name, blob);
  };

  return { persistProject, slug, exportProject, markdownForProject, csvCalendar, getExportHistory, recordExport };
})();

NAV[0].items.splice(1, 0, { id: "pricing", label: "Pricing", icon: "tag" }, { id: "features", label: "Features", icon: "sparkle" }, { id: "demo", label: "Demo", icon: "play" });
NAV[2].items.splice(1, 0, { id: "instagram-scheduler", label: "Instagram Scheduler", icon: "insta" });
NAV[3].items.unshift({ id: "account", label: "Account", icon: "user" }, { id: "billing", label: "Billing", icon: "card" }, { id: "usage", label: "Usage", icon: "activity" }, { id: "health", label: "System Health", icon: "shield" });

function PageShell({ eyebrow, title, sub, children, action }) {
  return (
    <div className="page">
      <div className="page-header">
        <div>
          <div className="page-eyebrow">{eyebrow}</div>
          <h1 className="page-title">{title}</h1>
          {sub && <p className="page-sub">{sub}</p>}
        </div>
        {action}
      </div>
      {children}
    </div>
  );
}

function PlaceholderNotice({ children }) {
  return <div className="mvp-notice"><Icon name="sparkle" size={16} color="var(--yellow)" />{children}</div>;
}

function AuthCard({ mode }) {
  const { go, showToast } = React.useContext(AppCtx);
  const isSignup = mode === "signup";
  return (
    <div className="auth-wrap">
      <div className="auth-panel">
        <BoltLogo />
        <h1 className="display auth-title">{isSignup ? "Create your workspace" : "Launch command login"}</h1>
        <p className="muted">{isSignup ? "Demo sign up creates a local workspace for now." : "Use demo mode while production auth is being wired."}</p>
        <div className="col gap-10 mt-18">
          <Field label="Email"><input className="input" defaultValue="sam@example.com" /></Field>
          <Field label="Password"><input className="input" type="password" defaultValue="boltkit-demo" /></Field>
          <Btn variant="primary" icon="bolt" onClick={() => { showToast("Demo workspace opened"); go("dashboard"); }}>
            {isSignup ? "Start Building" : "Continue to Dashboard"}
          </Btn>
          <Btn variant="secondary" icon="globe" onClick={() => showToast("Google login coming soon")}>Continue with Google</Btn>
          <Btn variant="secondary" icon="apple" onClick={() => showToast("Apple login coming soon")}>Continue with Apple</Btn>
        </div>
        <div className="row-between mt-16 text-sm">
          <button className="link-y" onClick={() => go(isSignup ? "login" : "signup")}>{isSignup ? "Already have an account?" : "Create an account"}</button>
          <button className="link-y" onClick={() => go("forgot")}>Forgot password?</button>
        </div>
      </div>
    </div>
  );
}

function LoginPage() { return <AuthCard mode="login" />; }
function SignupPage() { return <AuthCard mode="signup" />; }
function ForgotPasswordPage() {
  const { go, showToast } = React.useContext(AppCtx);
  return (
    <div className="auth-wrap"><div className="auth-panel">
      <BoltLogo />
      <h1 className="display auth-title">Reset access</h1>
      <p className="muted">Password emails are placeholder-only until production auth is connected.</p>
      <Field label="Email" style={{ marginTop: 18 }}><input className="input" defaultValue="sam@example.com" /></Field>
      <Btn variant="primary" icon="mail" onClick={() => showToast("Password reset coming soon")}>Send reset link</Btn>
      <Btn variant="ghost" icon="arrow_left" onClick={() => go("login")}>Back to login</Btn>
    </div></div>
  );
}

const PLAN_CATALOG = [
  { name: "Free", price: "£0", credits: 0, projects: "1 project", features: ["Basic launch pack", "Limited exports", "Video scripts only", "Demo workspace"] },
  { name: "Starter", price: "£19", credits: 2, projects: "5 projects", features: ["Social packs", "App Store packs", "ZIP export", "2 video credits / month"] },
  { name: "Pro", price: "£49", credits: 10, projects: "25 projects", features: ["Full launch packs", "Ad packs", "Claude/Codex prompts", "10 video credits / month"] },
  { name: "Agency", price: "£199", credits: 40, projects: "Client workspaces", features: ["Multiple brands", "Team features", "White-label exports", "40 video credits / month"] }
];
const plans = PLAN_CATALOG.map(plan => [plan.name, plan.price, plan.projects, ...plan.features]);
const CREDIT_PACKS = [
  { id: "credits-5", credits: 5, price: "£9", note: "Test pack for light launch videos" },
  { id: "credits-10", credits: 10, price: "£17", note: "Best for one launch week" },
  { id: "credits-25", credits: 25, price: "£39", note: "Pro founder bundle" },
  { id: "credits-50", credits: 50, price: "£75", note: "Agency client work" }
];
const VIDEO_CREDIT_COSTS = {
  "cheap": { label: "Cheap render", credits: 1, cost: "Use later provider", note: "Reserved for Runway/Replicate/fal integration." },
  "sora-2": { label: "Sora 2", credits: 2, cost: "~£1 OpenAI cost", note: "Good default for social drafts." },
  "sora-2-pro": { label: "Sora 2 Pro", credits: 5, cost: "£3-£6 OpenAI cost", note: "Premium launch/ad render." }
};

function getCreditAccount() {
  try {
    return JSON.parse(localStorage.getItem("boltkit.videoCredits") || "null") || { balance: 0, purchased: 0, monthlyIncluded: 0, used: 0, ledger: [] };
  } catch (e) {
    return { balance: 0, purchased: 0, monthlyIncluded: 0, used: 0, ledger: [] };
  }
}
function saveCreditAccount(account) {
  localStorage.setItem("boltkit.videoCredits", JSON.stringify({ ...account, ledger: (account.ledger || []).slice(0, 30) }));
}
function addVideoCredits(amount, reason) {
  const account = getCreditAccount();
  const next = {
    ...account,
    balance: account.balance + amount,
    purchased: account.purchased + amount,
    ledger: [{ id: `${Date.now()}-add`, type: "credit", amount, reason, createdAt: new Date().toISOString() }, ...(account.ledger || [])]
  };
  saveCreditAccount(next);
  return next;
}
function spendVideoCredits(amount, reason) {
  const account = getCreditAccount();
  if (account.balance < amount) return { ok: false, account };
  const next = {
    ...account,
    balance: account.balance - amount,
    used: account.used + amount,
    ledger: [{ id: `${Date.now()}-spend`, type: "debit", amount: -amount, reason, createdAt: new Date().toISOString() }, ...(account.ledger || [])]
  };
  saveCreditAccount(next);
  return { ok: true, account: next };
}
function refundVideoCredits(amount, reason) {
  const account = getCreditAccount();
  const next = {
    ...account,
    balance: account.balance + amount,
    used: Math.max(0, account.used - amount),
    ledger: [{ id: `${Date.now()}-refund`, type: "refund", amount, reason, createdAt: new Date().toISOString() }, ...(account.ledger || [])]
  };
  saveCreditAccount(next);
  return next;
}

function PricingPage() {
  const { showToast } = React.useContext(AppCtx);
  const [yearly, setYearly] = React.useState(false);
  const pay = () => showToast("Payments coming soon. You can keep using the demo workspace for now.");
  return (
    <PageShell eyebrow="Commercial SaaS shell" title={<>Pricing <span className="hl">built for launch velocity</span></>} sub="Plan UI is ready. Stripe is intentionally not connected yet.">
      <div className="seg"><button className={!yearly ? "on" : ""} onClick={() => setYearly(false)}>Monthly</button><button className={yearly ? "on" : ""} onClick={() => setYearly(true)}>Yearly</button></div>
      <div className="grid grid-4 gap-16 mt-24">
        {PLAN_CATALOG.map((p, i) => (
          <Card key={p.name} padding="lg" title={p.name} sub={i === 2 ? "Best for serious launches" : ""}>
            <div className="price">{p.price}<span>/mo</span></div>
            <Pill variant={p.credits ? "yellow" : "dark"}>{p.credits} video credits / month</Pill>
            <div className="col gap-8 mt-16">{[p.projects, ...p.features].map((f) => <div key={f} className="check-row"><Icon name="check" size={13} color="var(--yellow)" />{f}</div>)}</div>
            <Btn variant={i === 2 ? "primary" : "secondary"} icon="arrow_right" style={{ width: "100%", marginTop: 18 }} onClick={pay}>{i === 0 ? "Start Free" : "Upgrade"}</Btn>
          </Card>
        ))}
      </div>
      <Card padding="lg" title="Video credit packs" sub="Credits are the margin-protected layer for Sora and future cheaper video providers. Payment is placeholder-only for now." style={{ marginTop: 24 }}>
        <div className="grid grid-4 gap-16">
          {CREDIT_PACKS.map(pack => <div key={pack.id} className="credit-pack"><div className="fw-8 text-lg">{pack.credits} credits</div><div className="price sm">{pack.price}</div><p className="muted text-xs">{pack.note}</p><Btn variant="secondary" icon="plus" onClick={pay}>Buy credits</Btn></div>)}
        </div>
      </Card>
      <Card padding="lg" title="Credit cost rules" sub="Script/storyboard generation is free. Rendered MP4s consume credits." style={{ marginTop: 24 }}>
        <div className="grid grid-3 gap-16">{Object.values(VIDEO_CREDIT_COSTS).map(rule => <div key={rule.label} className="credit-pack"><Pill variant="yellow">{rule.credits} credit{rule.credits === 1 ? "" : "s"}</Pill><div className="fw-8 mt-10">{rule.label}</div><div className="muted text-xs mt-4">{rule.cost}</div><p className="muted text-sm mt-10">{rule.note}</p></div>)}</div>
      </Card>
      <Card padding="lg" title="Feature comparison" sub="Mobile turns this into readable rows." style={{ marginTop: 24 }}>
        <div className="compare-grid">
          {["Projects", "Exports", "Video scripts", "Video credits", "Prompt packs", "Client workspaces"].map((row) => <React.Fragment key={row}><b>{row}</b><span>Free</span><span>Starter</span><span>Pro</span><span>Agency</span></React.Fragment>)}
        </div>
      </Card>
      <FAQ />
    </PageShell>
  );
}

function FeaturesPage() {
  const features = ["Brand intelligence", "Screenshot intelligence", "Social/video pack", "Claude/Codex prompt pack", "Export centre", "URL analysis", "App Store copy", "Paid ads", "SEO pack"];
  return <PageShell eyebrow="Features" title={<>Every launch asset in <span className="hl">one command centre</span></>} sub="BoltKit turns product context into usable marketing output.">
    <div className="grid grid-3 gap-16">{features.map((f) => <Card key={f} padding="lg" title={f}><p className="muted">Generate, edit, copy and export practical launch material for this part of your go-to-market folder.</p></Card>)}</div>
  </PageShell>;
}

function DemoPage() {
  const { go, runGeneration } = React.useContext(AppCtx);
  return <PageShell eyebrow="Test workspace" title={<>BoltKit launch pack <span className="hl">preview</span></>} sub="A clean BoltKit test project is preloaded so the product can be tested without production auth, billing or database setup." action={<Pill variant="yellow">Test Workspace</Pill>}>
    <div className="grid grid-2 gap-20">
      <Card padding="lg" title="Try the product flow" sub="Open the dashboard, generate a pack, then export it.">
        <div className="row gap-8 mt-12"><Btn variant="primary" icon="grid" onClick={() => go("dashboard")}>Open Dashboard</Btn><Btn variant="secondary" icon="sparkle" onClick={() => runGeneration(PACK_TYPES[0])}>Generate Pack</Btn></div>
      </Card>
      <Card padding="lg" title="What the demo includes">
        <div className="col gap-8">{["Demo projects", "Mock AI analysis", "Editable outputs", "Clipboard actions", "Markdown/CSV/JSON/ZIP downloads"].map((x) => <div className="check-row" key={x}><Icon name="check" size={13} color="var(--yellow)" />{x}</div>)}</div>
      </Card>
    </div>
  </PageShell>;
}

function FAQ() {
  return <div className="grid grid-2 gap-16 mt-24">{[
    ["Is billing live?", "No. Payment buttons intentionally show a coming-soon placeholder."],
    ["Does AI require an API key?", "No. The MVP uses deterministic local generation unless real AI is wired later."],
    ["Can I export files?", "Yes. Markdown, CSV, JSON and ZIP downloads work in demo mode."],
    ["Is OAuth live?", "No. Google and Apple buttons are present as placeholders."]
  ].map(([q, a]) => <Card key={q} padding="lg" title={q}><p className="muted">{a}</p></Card>)}</div>;
}

function AccountSettingsPage() {
  const { showToast } = React.useContext(AppCtx);
  const [profile, setProfile] = React.useState(() => {
    try {
      return JSON.parse(localStorage.getItem("boltkit.profile") || "null") || {
        name: "Sam",
        email: "sam@example.com",
        tone: "Practical, punchy, premium",
        workspace: "Demo Workspace",
      };
    } catch (e) {
      return { name: "Sam", email: "sam@example.com", tone: "Practical, punchy, premium", workspace: "Demo Workspace" };
    }
  });
  const set = (key) => (event) => setProfile(p => ({ ...p, [key]: event.target.value }));
  const save = () => {
    localStorage.setItem("boltkit.profile", JSON.stringify(profile));
    showToast("Account settings saved locally");
  };
  return <PageShell eyebrow="Settings" title="Account Settings" sub="Demo profile fields are editable locally for now.">
    <Card padding="lg" title="Profile"><div className="grid grid-2 gap-16"><Field label="Name"><input className="input" value={profile.name} onChange={set("name")} /></Field><Field label="Email"><input className="input" value={profile.email} onChange={set("email")} /></Field><Field label="Default tone"><input className="input" value={profile.tone} onChange={set("tone")} /></Field><Field label="Workspace"><input className="input" value={profile.workspace} onChange={set("workspace")} /></Field></div><Btn variant="primary" icon="check" onClick={save} style={{ marginTop: 16 }}>Save changes</Btn></Card>
  </PageShell>;
}

function BillingSettingsPage() {
  const { showToast } = React.useContext(AppCtx);
  const [selectedPlan, setSelectedPlan] = React.useState(() => localStorage.getItem("boltkit.selectedPlan") || "Free");
  const [credits, setCredits] = React.useState(() => getCreditAccount());
  const select = (plan) => {
    localStorage.setItem("boltkit.selectedPlan", plan);
    setSelectedPlan(plan);
    showToast("Payments coming soon. You can keep using the demo workspace for now.");
  };
  const buyPack = (pack) => {
    const next = addVideoCredits(pack.credits, `${pack.price} credit pack placeholder`);
    setCredits(next);
    showToast(`Demo credit pack added · ${pack.credits} credits`);
  };
  return <PageShell eyebrow="Billing" title="Billing Settings" sub="Stripe is not connected yet. Plan controls are present for future production wiring.">
    <PlaceholderNotice>Payments coming soon. You can keep using the demo workspace for now.</PlaceholderNotice>
    <div className="grid grid-4 gap-16 mt-18">{PLAN_CATALOG.map((p) => <Card key={p.name} padding="lg" title={p.name} action={selectedPlan === p.name ? <Pill variant="yellow">Selected</Pill> : null}><div className="price sm">{p.price}<span>/mo</span></div><p className="muted text-xs">{p.credits} included video credits each month</p><Btn variant={selectedPlan === p.name ? "primary" : "secondary"} icon="card" onClick={() => select(p.name)}>{selectedPlan === p.name ? "Current plan" : "Select plan"}</Btn></Card>)}</div>
    <div className="grid grid-2 gap-20 mt-24">
      <Card padding="lg" title="Video credit wallet" sub="Local demo ledger. Production should be enforced server-side after Stripe/Supabase are connected.">
        <div className="price">{credits.balance}<span>credits</span></div>
        <div className="grid grid-3 gap-10 mt-14">
          <Pill variant="yellow">{credits.purchased} purchased</Pill>
          <Pill variant="dark">{credits.used} used</Pill>
          <Pill>{credits.monthlyIncluded} monthly</Pill>
        </div>
        <div className="hr mt-16 mb-12" />
        <div className="col gap-8">{(credits.ledger || []).slice(0, 6).map(item => <div key={item.id} className="row-between text-sm"><span>{item.reason}</span><b style={{ color: item.amount > 0 ? "var(--green)" : "var(--fg)" }}>{item.amount > 0 ? "+" : ""}{item.amount}</b></div>)}
          {!credits.ledger?.length && <p className="muted text-sm">No credit activity yet.</p>}
        </div>
      </Card>
      <Card padding="lg" title="Buy credit packs" sub="Placeholder purchase flow. Adds demo credits so you can test the business model UI.">
        <div className="grid grid-2 gap-12">{CREDIT_PACKS.map(pack => <div key={pack.id} className="credit-pack"><div className="fw-8">{pack.credits} credits</div><div className="price sm">{pack.price}</div><p className="muted text-xs">{pack.note}</p><Btn variant="secondary" icon="plus" onClick={() => buyPack(pack)}>Add demo credits</Btn></div>)}</div>
      </Card>
    </div>
  </PageShell>;
}

function UsagePage() {
  const localProjects = (() => {
    try { return JSON.parse(localStorage.getItem("boltkit.projects") || "[]").length; }
    catch (e) { return 0; }
  })();
  const generated = (() => {
    try { return JSON.parse(localStorage.getItem("boltkit.generatedPacks") || "[]").length; }
    catch (e) { return 4; }
  })();
  const exportsCount = BoltKitMVP.getExportHistory().length;
  const assetCount = (() => {
    try { return JSON.parse(localStorage.getItem("boltkit.assets") || "[]").length; }
    catch (e) { return 0; }
  })();
  const credits = getCreditAccount();
  const plan = PLAN_CATALOG.find(item => item.name === (localStorage.getItem("boltkit.selectedPlan") || "Free")) || PLAN_CATALOG[0];
  return <PageShell eyebrow="Usage" title="Usage & Limits" sub="Demo counters model the eventual metered SaaS experience.">
    <div className="grid grid-4 gap-16"><StatTile label="Projects" value={`${PROJECTS.length}`} delta={`${localProjects} local`} /><StatTile label="Packs generated" value={String(generated)} delta="Persisted locally" /><StatTile label="Exports" value={String(exportsCount)} delta="Download history" /><StatTile label="Video credits" value={String(credits.balance)} delta={`${credits.used} used`} /></div>
    <Card padding="lg" title="Current plan" sub={`${plan.name} plan · ${plan.credits} included video credits/month. Demo workspace remains unrestricted for non-video generation.`} style={{ marginTop: 20 }}><ScoreRow label="Monthly generation usage" value={Math.min(100, generated * 12)} /><ScoreRow label="Export usage" value={Math.min(100, exportsCount * 10)} /><ScoreRow label="Video credit usage" value={Math.min(100, credits.used * 10)} /><ScoreRow label="Project limit" value={100} /></Card>
    <Card padding="lg" title="Video credit economics" sub="The pricing model protects margin by charging credits only for rendered MP4s." style={{ marginTop: 20 }}>
      <div className="grid grid-3 gap-16">{Object.values(VIDEO_CREDIT_COSTS).map(rule => <div key={rule.label} className="credit-pack"><Pill variant="yellow">{rule.credits} credit{rule.credits === 1 ? "" : "s"}</Pill><div className="fw-8 mt-10">{rule.label}</div><div className="muted text-xs mt-4">{rule.cost}</div><p className="muted text-sm mt-10">{rule.note}</p></div>)}</div>
    </Card>
  </PageShell>;
}

function SystemHealthPage() {
  const localProjects = (() => { try { return JSON.parse(localStorage.getItem("boltkit.projects") || "[]").length; } catch (e) { return 0; } })();
  const localAssets = (() => { try { return JSON.parse(localStorage.getItem("boltkit.assets") || "[]").length; } catch (e) { return 0; } })();
  const exportsCount = BoltKitMVP.getExportHistory().length;
  const checks = [
    ["Demo workspace", "Ready", "green", "Local mode works without secrets."],
    ["Project persistence", localProjects ? "Active" : "Ready", "green", `${localProjects} browser-created projects saved.`],
    ["Asset staging", localAssets ? "Active" : "Ready", `${localAssets ? "green" : "blue"}`, `${localAssets} uploaded asset records saved locally.`],
    ["Export history", exportsCount ? "Active" : "Ready", `${exportsCount ? "green" : "blue"}`, `${exportsCount} downloads recorded.`],
    ["Supabase", "Not connected", "amber", "Add NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY."],
    ["AI provider", "Mock mode", "amber", "Add OPENAI_API_KEY or ANTHROPIC_API_KEY for real generation."],
    ["Payments", "Placeholder", "amber", "Stripe intentionally not wired yet."],
    ["OAuth", "Placeholder", "amber", "Google and Apple buttons are UI-only."],
  ];
  return (
    <PageShell eyebrow="Operations" title="System Health" sub="A quick production-readiness view for the local BoltKit MVP.">
      <div className="grid grid-4 gap-16 mb-24">
        <StatTile label="Projects" value={String(PROJECTS.length)} delta={`${localProjects} local`} icon="folder" />
        <StatTile label="Assets" value={String(localAssets + 8)} delta={`${localAssets} uploaded`} icon="image" />
        <StatTile label="Exports" value={String(exportsCount)} delta="Local history" icon="download" />
        <StatTile label="Mode" value="Demo" delta="No secrets needed" icon="shield" />
      </div>
      <Card padding="none" title="Readiness checks" sub="What is live now versus deliberately placeholder-only.">
        {checks.map((check, index) => (
          <div key={check[0]} className="row gap-12" style={{ padding: "13px 18px", borderTop: index === 0 ? 0 : "1px solid var(--border)" }}>
            <div style={{ width: 34, height: 34, borderRadius: 8, background: "var(--surface-2)", display: "grid", placeItems: "center", color: check[2] === "green" ? "var(--green)" : check[2] === "blue" ? "var(--blue)" : "var(--amber)" }}>
              <Icon name={check[2] === "green" ? "check_circle" : "alert"} size={15} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="fw-8 text-sm">{check[0]}</div>
              <div className="muted text-xs mt-4">{check[3]}</div>
            </div>
            <Pill variant={check[2]}>{check[1]}</Pill>
          </div>
        ))}
      </Card>
      <Card padding="lg" title="API contract" sub="Mock endpoints are present for future production wiring." style={{ marginTop: 20 }}>
        <div className="grid grid-4 gap-10">{["analyse-project", "generate-pack", "improve-output", "regenerate-output", "export-markdown", "export-csv", "export-json", "export-zip"].map(name => <Pill key={name} variant="dark">/api/{name}</Pill>)}</div>
      </Card>
    </PageShell>
  );
}

function GeneratedPackPage({ packId = "social", title = "Generated Pack" }) {
  const { currentProject, runGeneration, go } = React.useContext(AppCtx);
  const pack = PACK_TYPES.find(item => item.id === packId) || PACK_TYPES.find(item => item.name === title) || PACK_TYPES[0];
  const generated = (() => {
    try { return JSON.parse(localStorage.getItem("boltkit.generatedContent") || "{}")[pack.id]; }
    catch (e) { return null; }
  })();
  return (
    <PageShell eyebrow={`${currentProject.name} · ${pack.name}`} title={pack.name} sub="This page now uses your generated workspace content instead of bundled sample copy."
      action={<div className="row gap-8"><Btn variant="secondary" icon="sparkle" onClick={() => runGeneration(pack)}>Regenerate</Btn><Btn variant="primary" icon="download" onClick={() => go("exports")}>Export</Btn></div>}>
      {generated ? (
        <Card padding="lg" title={generated.title || pack.name} sub={`Generated via ${generated.mode || "local API"}`}>
          <pre className="generated-preview">{generated.content_markdown || JSON.stringify(generated.content_json, null, 2)}</pre>
        </Card>
      ) : (
        <Card padding="lg" title="No generated content yet" sub={`Generate ${pack.name} for ${currentProject.name}.`}>
          <p className="muted text-sm">Use the button above or the AI Marketing Pack Generator to create real content for this pack.</p>
          <Btn variant="primary" icon="sparkle" onClick={() => runGeneration(pack)} style={{ marginTop: 16 }}>Generate {pack.name}</Btn>
        </Card>
      )}
    </PageShell>
  );
}

function SocialContentPage() { return <GeneratedPackPage packId="social" title="Social Content Pack" />; }
function VideoScriptPage() {
  const { currentProject, runGeneration, go, showToast } = React.useContext(AppCtx);
  const pack = PACK_TYPES.find(item => item.id === "video") || PACK_TYPES[0];
  const [platform, setPlatform] = React.useState("all");
  const [hook, setHook] = React.useState(`I uploaded ${currentProject.name} and got a launch pack in seconds.`);
  const [cta, setCta] = React.useState("Start building");
  const [model, setModel] = React.useState("sora-2");
  const [credits, setCredits] = React.useState(() => getCreditAccount());
  const [videoState, setVideoState] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem(`boltkit.socialVideo.${currentProject.id}`) || "null"); }
    catch (e) { return null; }
  });
  const [loading, setLoading] = React.useState(false);
  const saveVideo = (next) => {
    setVideoState(next);
    localStorage.setItem(`boltkit.socialVideo.${currentProject.id}`, JSON.stringify(next));
  };
  const requestVideo = async (render = false) => {
    const creditRule = VIDEO_CREDIT_COSTS[model] || VIDEO_CREDIT_COSTS["sora-2"];
    if (render) {
      if (credits.balance < creditRule.credits) {
        showToast(`Not enough video credits · ${creditRule.credits} needed`);
        return;
      }
      const ok = window.confirm(`Render this MP4 with ${creditRule.label}? This uses ${creditRule.credits} video credits and may spend real OpenAI API credits.`);
      if (!ok) return;
      const spent = spendVideoCredits(creditRule.credits, `${creditRule.label} render · ${currentProject.name}`);
      if (!spent.ok) {
        showToast("Not enough video credits");
        return;
      }
      setCredits(spent.account);
    }
    setLoading(true);
    try {
      const res = await fetch("/api/generate-social-video", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          render,
          project: currentProject,
          options: { platform, hook, cta, model, seconds: "12", size: "720x1280" }
        })
      });
      const data = await res.json();
      if (!data.ok) throw new Error(data.error || "Video generation failed");
      const next = { ...data, savedAt: new Date().toISOString() };
      saveVideo(next);
      showToast(render ? `Sora video job created · ${data.video?.status || "queued"}` : "10-second video brief generated");
    } catch (error) {
      if (render) {
        const creditRule = VIDEO_CREDIT_COSTS[model] || VIDEO_CREDIT_COSTS["sora-2"];
        setCredits(refundVideoCredits(creditRule.credits, `Refund failed ${creditRule.label} render`));
      }
      showToast(error.message || "Video generation failed");
    } finally {
      setLoading(false);
    }
  };
  const checkStatus = async () => {
    const id = videoState?.video?.id;
    if (!id) return showToast("Create a Sora render job first");
    setLoading(true);
    try {
      const res = await fetch("/api/social-video-status", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ video_id: id })
      });
      const data = await res.json();
      if (!data.ok) throw new Error(data.error || "Status check failed");
      const next = { ...videoState, video: data.video, lastChecked: new Date().toISOString() };
      saveVideo(next);
      showToast(`Video status · ${data.video?.status || "unknown"}`);
    } catch (error) {
      showToast(error.message || "Status check failed");
    } finally {
      setLoading(false);
    }
  };
  const downloadVideo = async () => {
    const id = videoState?.video?.id;
    if (!id) return showToast("Create a Sora render job first");
    const url = URL.createObjectURL(new Blob([JSON.stringify({ video_id: id, note: "Use /api/social-video-status with download:true to proxy the MP4 once completed." }, null, 2)], { type: "application/json" }));
    const a = document.createElement("a");
    a.href = url;
    a.download = `${BoltKitMVP.slug(currentProject.name)}-sora-video-job.json`;
    document.body.appendChild(a);
    a.click();
    a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
    showToast("Video job reference downloaded");
  };
  const brief = videoState?.brief;
  const generated = (() => {
    try { return JSON.parse(localStorage.getItem("boltkit.generatedContent") || "{}").video; }
    catch (e) { return null; }
  })();
  return (
    <PageShell eyebrow={`${currentProject.name} · Video`} title={<>Video Script <span className="hl">Pack</span></>} sub="Generate short-form scripts, then create a vertical Sora-ready 10-second social video for Reels, TikTok and YouTube Shorts."
      action={<div className="row gap-8"><Btn variant="secondary" icon="sparkle" onClick={() => runGeneration(pack)}>Regenerate scripts</Btn><Btn variant="primary" icon="download" onClick={() => go("exports")}>Export</Btn></div>}>
      <div className="grid grid-2 gap-20">
        <Card padding="lg" title="10-second social video generator" sub="Builds a vertical 9:16 video prompt for Instagram Reels, TikTok and YouTube Shorts. OpenAI currently renders 4, 8 or 12 seconds, so BoltKit uses a 12-second render for a tight 10-second edit plus CTA buffer.">
          <div className="grid grid-2 gap-12">
            <Field label="Platform"><select className="select" value={platform} onChange={event => setPlatform(event.target.value)}><option value="all">Reels + TikTok + Shorts</option><option value="instagram">Instagram Reels</option><option value="tiktok">TikTok</option><option value="youtube">YouTube Shorts</option></select></Field>
            <Field label="Video model"><select className="select" value={model} onChange={event => setModel(event.target.value)}><option value="sora-2">Sora 2 · 2 credits</option><option value="sora-2-pro">Sora 2 Pro · 5 credits</option></select></Field>
            <Field label="Hook"><input className="input" value={hook} onChange={event => setHook(event.target.value)} /></Field>
            <Field label="CTA"><input className="input" value={cta} onChange={event => setCta(event.target.value)} /></Field>
          </div>
          <div className="ai-surface card-pad mt-16">
            <div className="row-between" style={{ flexWrap: "wrap", gap: 10 }}>
              <span className="ai-chip"><Icon name="card" size={11} />Video credits</span>
              <div className="row gap-8"><Pill variant="yellow">{credits.balance} available</Pill><Pill>{(VIDEO_CREDIT_COSTS[model] || VIDEO_CREDIT_COSTS["sora-2"]).credits} needed</Pill></div>
            </div>
            <p className="muted text-sm mt-10">Briefs and scripts are free. Rendered MP4s consume video credits so BoltKit can keep margin on Sora costs.</p>
            <div className="row gap-8 mt-12" style={{ flexWrap: "wrap" }}>
              {CREDIT_PACKS.slice(0, 2).map(pack => <Btn key={pack.id} size="sm" variant="ghost" icon="plus" onClick={() => { const next = addVideoCredits(pack.credits, `${pack.price} credit pack placeholder`); setCredits(next); showToast(`${pack.credits} demo credits added`); }}>Add {pack.credits} demo credits</Btn>)}
            </div>
          </div>
          <div className="row gap-8 mt-16" style={{ flexWrap: "wrap" }}>
            <Btn variant="secondary" icon="video" onClick={() => requestVideo(false)} disabled={loading}>{loading ? "Working..." : "Generate video brief"}</Btn>
            <Btn variant="primary" icon="sparkle" onClick={() => requestVideo(true)} disabled={loading || credits.balance < (VIDEO_CREDIT_COSTS[model] || VIDEO_CREDIT_COSTS["sora-2"]).credits}>{loading ? "Working..." : `Render MP4 · ${(VIDEO_CREDIT_COSTS[model] || VIDEO_CREDIT_COSTS["sora-2"]).credits} credits`}</Btn>
            <Btn variant="ghost" icon="refresh" onClick={checkStatus} disabled={loading || !videoState?.video?.id}>Check status</Btn>
            <Btn variant="ghost" icon="download" onClick={downloadVideo} disabled={!videoState?.video?.id}>Save job ref</Btn>
          </div>
          {videoState?.video && <div className="ai-surface card-pad mt-16"><span className="ai-chip"><Icon name="video" size={11} />Sora job</span><div className="grid grid-3 gap-10 mt-12"><Pill variant="dark">ID {videoState.video.id}</Pill><Pill variant={videoState.video.status === "completed" ? "green" : "amber"}>{videoState.video.status || "queued"}</Pill><Pill>{videoState.video.progress || 0}%</Pill></div><p className="muted text-sm mt-12">When the job is completed, the backend can proxy the MP4 from OpenAI. Full saved video library comes with Supabase storage.</p></div>}
        </Card>
        <Card padding="lg" title="Generated video brief" sub={brief ? `${brief.model} · ${brief.size} · ${brief.seconds}s render` : "Create a brief to see storyboard, prompt and captions."}>
          {brief ? (
            <>
              <div className="fw-8 text-lg">{brief.title}</div>
              <div className="col gap-8 mt-14">{brief.storyboard.map(scene => <div key={scene.time} className="check-row"><Icon name="video" size={13} color="var(--yellow)" /><span><b>{scene.time}</b> · {scene.shot} · <span className="muted">{scene.overlay}</span></span></div>)}</div>
              <div className="hr mt-16 mb-16" />
              <Field label="Sora prompt"><textarea className="textarea" value={brief.prompt} readOnly style={{ minHeight: 180 }} /></Field>
              <Field label="Caption"><textarea className="textarea" value={`${brief.caption}\n\n${brief.hashtags.join(" ")}`} readOnly /></Field>
            </>
          ) : <p className="muted text-sm">No social video brief yet. Generate one from the controls on the left.</p>}
        </Card>
      </div>
      <Card padding="lg" title="Video script pack" sub={generated ? `Generated ${new Date(generated.savedAt).toLocaleString()} · ${generated.mode}` : "Generate the full script pack for additional Reels, TikTok and Shorts ideas."} style={{ marginTop: 20 }}>
        {generated ? <pre className="generated-preview">{generated.content_markdown || JSON.stringify(generated.content_json, null, 2)}</pre> : <div className="row gap-8"><p className="muted text-sm" style={{ flex: 1 }}>No generated video script pack yet.</p><Btn variant="primary" icon="sparkle" onClick={() => runGeneration(pack)}>Generate script pack</Btn></div>}
      </Card>
    </PageShell>
  );
}
function AppStorePage() { return <GeneratedPackPage packId="appstore" title="App Store Pack" />; }
function AdsPage() { return <GeneratedPackPage packId="ads" title="Paid Ads Pack" />; }
function LandingPage() { return <GeneratedPackPage packId="landing" title="Landing Page Copy" />; }
function SEOPage() { return <GeneratedPackPage packId="seo" title="SEO Pack" />; }
function ClaudePromptsPage() { return <GeneratedPackPage packId="claude" title="Claude Design Prompt Pack" />; }
function CodexPromptsPage() { return <GeneratedPackPage packId="codex" title="Codex Prompt Pack" />; }

function TermsPage() { return <LegalPage title="Terms" text="Placeholder terms for the BoltKit demo MVP. Production terms should be reviewed before launch." />; }
function PrivacyPage() { return <LegalPage title="Privacy" text="Placeholder privacy page. Demo data is stored locally in your browser unless Supabase is connected later." />; }
function LegalPage({ title, text }) { return <PageShell eyebrow="Legal" title={title} sub={text}><Card padding="lg" title={`${title} placeholder`}><p className="muted">This page exists so the SaaS shell has no broken route. Replace it before public launch.</p></Card></PageShell>; }

function InstagramSchedulerPage() {
  const { currentProject, showToast } = React.useContext(AppCtx);
  const storageKey = `boltkit.instagramQueue.${currentProject.id}`;
  const aiGoalOptions = [
    { id: "clicks", label: "Clicks", desc: "Drive link taps and CTA action" },
    { id: "likes", label: "Likes", desc: "Broad appeal and quick approval" },
    { id: "comments", label: "Comments", desc: "Ask a reply-worthy question" },
    { id: "shares", label: "Shares", desc: "Make it useful to send on" },
    { id: "saves", label: "Saves", desc: "Checklist or reference value" },
    { id: "profile_visits", label: "Profile visits", desc: "Make people want context" },
    { id: "viral_hook", label: "Viral hook", desc: "Stronger first line and opener" },
    { id: "sales", label: "Sales intent", desc: "Move viewers toward buying" }
  ];
  const defaultAiGoals = ["clicks", "likes", "viral_hook"];
  const today = () => new Date().toISOString().slice(0, 10);
  const defaultPosts = () => [
    {
      id: `ig-${Date.now()}-1`,
      title: `${currentProject.name} launch teaser`,
      topic: "Launch teaser",
      type: "Carousel",
      mediaName: "Upload media",
      previewUrl: "",
      caption: "",
      hashtags: "#appfounder #indiehacker #productlaunch",
      cta: "View demo",
      firstComment: "",
      altText: "",
      date: today(),
      time: "09:00",
      status: "Draft",
      aiGoals: defaultAiGoals,
      storyEnabled: true,
      storyLink: currentProject.url || "",
      storyStatus: "Draft",
      pinned: false
    }
  ];
  const [posts, setPosts] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem(storageKey) || "null") || defaultPosts(); }
    catch (e) { return defaultPosts(); }
  });
  const [selectedId, setSelectedId] = React.useState(posts[0]?.id);
  const [dailyTime, setDailyTime] = React.useState("09:00");
  const [startDate, setStartDate] = React.useState(today());
  const [generating, setGenerating] = React.useState(false);
  const [dragId, setDragId] = React.useState(null);
  const mediaInputRef = React.useRef(null);
  const selected = posts.find((post) => post.id === selectedId) || posts[0];
  React.useEffect(() => {
    try { localStorage.setItem(storageKey, JSON.stringify(posts.map(({ previewUrl, ...post }) => post))); } catch (e) {}
  }, [posts, storageKey]);
  React.useEffect(() => {
    if (!selected && posts[0]) setSelectedId(posts[0].id);
  }, [posts, selected]);
  const updatePost = (id, patch) => setPosts(prev => prev.map(post => post.id === id ? { ...post, ...patch } : post));
  const addPost = (file) => {
    const post = {
      id: `ig-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
      title: file?.name ? file.name.replace(/\.[^.]+$/, "") : `Instagram post ${posts.length + 1}`,
      topic: "",
      type: file?.type?.startsWith("video/") ? "Reel" : "Image",
      mediaName: file?.name || "No media yet",
      previewUrl: file?.type?.startsWith("image/") || file?.type?.startsWith("video/") ? URL.createObjectURL(file) : "",
      caption: "",
      hashtags: "",
      cta: "",
      firstComment: "",
      altText: "",
      date: startDate,
      time: dailyTime,
      status: "Draft",
      aiGoals: defaultAiGoals,
      storyEnabled: true,
      storyLink: currentProject.url || "",
      storyStatus: "Draft",
      pinned: false
    };
    setPosts(prev => [...prev, post]);
    setSelectedId(post.id);
    showToast("Instagram post added to the queue");
  };
  const addBlankPost = () => addPost(null);
  const addFiles = (files) => [...files].forEach(addPost);
  const removePost = (id) => {
    const next = posts.filter(post => post.id !== id);
    setPosts(next.length ? next : defaultPosts());
    setSelectedId(next[0]?.id);
    showToast("Post removed from schedule");
  };
  const movePost = (id, direction) => {
    const index = posts.findIndex(post => post.id === id);
    const target = index + direction;
    if (index < 0 || target < 0 || target >= posts.length) return;
    const next = [...posts];
    [next[index], next[target]] = [next[target], next[index]];
    setPosts(next);
  };
  const reorderDrop = (targetId) => {
    if (!dragId || dragId === targetId) return;
    const from = posts.findIndex(post => post.id === dragId);
    const to = posts.findIndex(post => post.id === targetId);
    if (from < 0 || to < 0) return;
    const next = [...posts];
    const [item] = next.splice(from, 1);
    next.splice(to, 0, item);
    setPosts(next);
    setDragId(null);
  };
  const scheduleDaily = () => {
    const base = new Date(`${startDate}T00:00:00`);
    const next = posts.map((post, index) => {
      const date = new Date(base);
      date.setDate(base.getDate() + index);
      return { ...post, date: date.toISOString().slice(0, 10), time: dailyTime, status: post.status === "Published" ? "Published" : "Scheduled", storyStatus: post.storyEnabled ? "Scheduled" : post.storyStatus };
    });
    setPosts(next);
    showToast(`Scheduled ${next.length} post${next.length === 1 ? "" : "s"} at ${dailyTime} daily`);
  };
  const markScheduled = () => {
    if (!selected) return;
    updatePost(selected.id, { status: "Scheduled", storyStatus: selected.storyEnabled ? "Scheduled" : selected.storyStatus });
    showToast("Post scheduled locally · Instagram connection coming soon");
  };
  const schedulePost = (id) => {
    const post = posts.find(item => item.id === id);
    if (!post) return;
    updatePost(id, { status: "Scheduled", storyStatus: post.storyEnabled ? "Scheduled" : post.storyStatus });
    setSelectedId(id);
    showToast(`${post.title || "Post"} scheduled for ${post.date} at ${post.time}`);
  };
  const postGoals = (post) => post?.aiGoals?.length ? post.aiGoals : defaultAiGoals;
  const toggleGoal = (goalId) => {
    if (!selected) return;
    const current = postGoals(selected);
    const next = current.includes(goalId) ? current.filter(id => id !== goalId) : [...current, goalId];
    updatePost(selected.id, { aiGoals: next });
  };
  const publishNow = () => showToast("Instagram publishing coming soon · connect Meta/Instagram API first");
  const exportSchedule = () => {
    const rows = [["order", "title", "type", "date", "time", "status", "also_story", "story_time", "story_link", "story_status", "caption", "hashtags", "cta", "first_comment", "alt_text"]];
    posts.forEach((post, index) => rows.push([index + 1, post.title, post.type, post.date, post.time, post.status, post.storyEnabled ? "Yes" : "No", post.storyEnabled ? `${post.date} ${post.time}` : "", post.storyLink || "", post.storyEnabled ? post.storyStatus || post.status : "", post.caption, post.hashtags, post.cta, post.firstComment, post.altText]));
    const csv = rows.map(row => row.map(cell => `"${String(cell || "").replaceAll('"', '""')}"`).join(",")).join("\n");
    const blob = new Blob([csv], { type: "text/csv" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `${BoltKitMVP.slug(currentProject.name)}-instagram-schedule.csv`;
    document.body.appendChild(a);
    a.click();
    a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
    showToast("Instagram schedule CSV downloaded");
  };
  const generateAI = async () => {
    if (!selected) return;
    setGenerating(true);
    try {
      const res = await fetch("/api/generate-instagram-post", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          project: currentProject,
          post: {
            ...selected,
            optimization_goals: postGoals(selected).map(id => aiGoalOptions.find(goal => goal.id === id)?.label || id)
          }
        })
      });
      const data = await res.json();
      if (!data.ok) throw new Error(data.error || "AI generation failed");
      const generated = data.post || {};
      updatePost(selected.id, {
        caption: generated.caption || selected.caption,
        topic: generated.hook || selected.topic,
        hashtags: Array.isArray(generated.hashtags) ? generated.hashtags.join(" ") : selected.hashtags,
        cta: generated.cta || selected.cta,
        firstComment: generated.first_comment || selected.firstComment,
        altText: generated.alt_text || selected.altText,
        viralNotes: generated.viral_notes || [],
        optimizedFor: generated.optimized_for || postGoals(selected).map(id => aiGoalOptions.find(goal => goal.id === id)?.label || id),
        bestTimeReason: generated.best_time_reason || "",
        storyLink: selected.storyLink || currentProject.url || "",
        storyNotes: generated.story_notes || [],
        aiMode: data.mode
      });
      showToast(`AI Instagram copy generated · ${data.mode}`);
    } catch (error) {
      showToast(error.message || "AI generation failed");
    } finally {
      setGenerating(false);
    }
  };
  const stats = {
    scheduled: posts.filter(p => p.status === "Scheduled").length,
    drafts: posts.filter(p => p.status === "Draft").length,
    ready: posts.filter(p => p.caption && p.date && p.time).length,
    stories: posts.filter(p => p.storyEnabled).length
  };
  return (
    <PageShell eyebrow={`${currentProject.name} · Instagram`} title={<>Instagram <span className="hl">Scheduler</span></>} sub="Upload posts, generate captions, reorder the queue and schedule locally. Real Instagram publishing will turn on after Meta/Instagram is connected."
      action={<div className="row gap-8"><Btn variant="secondary" icon="settings" onClick={() => showToast("Instagram account connection coming soon")}>Connect Instagram</Btn><Btn variant="primary" icon="sparkle" onClick={generateAI} disabled={!selected || generating}>{generating ? "Writing..." : "Generate Post Info"}</Btn></div>}>
      <div className="scheduler-banner">
        <Icon name="insta" size={18} color="var(--yellow)" />
        <div><b>Demo scheduler active.</b><span> Posts can be queued 24/7 with exact dates and times. Story reposts are planned with the same media plus a link sticker field. Auto-publishing needs Instagram Graph API permissions before it can post for real.</span></div>
      </div>
      <div className="grid scheduler-stats">
        <StatTile label="Queue" value={String(posts.length)} delta="Uploaded/staged" />
        <StatTile label="Scheduled" value={String(stats.scheduled)} delta="Local schedule" />
        <StatTile label="Ready" value={String(stats.ready)} delta="Caption + time" />
        <StatTile label="Stories" value={String(stats.stories)} delta="Paired with posts" />
        <StatTile label="Drafts" value={String(stats.drafts)} delta="Needs attention" />
      </div>
      <div className="grid scheduler-layout">
        <div className="col gap-16">
          <Card padding="lg" title="Upload Instagram posts" sub="Images and videos are previewed locally in this browser.">
            <div className="drop scheduler-drop" onDragOver={event => event.preventDefault()} onDrop={event => { event.preventDefault(); addFiles(event.dataTransfer.files || []); }}>
              <Icon name="upload" size={22} color="var(--yellow)" />
              <div><div className="fw-8">Drop Instagram media here</div><div className="muted text-sm">PNG, JPG, WEBP, MP4, MOV · each file becomes a post card</div></div>
              <div className="row gap-8" style={{ flexWrap: "wrap", justifyContent: "flex-end" }}>
                <Btn variant="secondary" icon="edit" onClick={addBlankPost}>Blank post</Btn>
                <Btn variant="primary" icon="plus" onClick={() => mediaInputRef.current?.click()}>Add media</Btn>
                <input ref={mediaInputRef} type="file" multiple accept="image/*,video/*" style={{ display: "none" }} onChange={event => addFiles(event.target.files || [])} />
              </div>
            </div>
          </Card>
          <Card padding="lg" title="Bulk schedule" sub="Fast option for posting at the same time every day.">
            <div className="grid grid-3 gap-12">
              <Field label="Start date"><input className="input" type="date" value={startDate} onChange={event => setStartDate(event.target.value)} /></Field>
              <Field label="Post time"><input className="input" type="time" value={dailyTime} onChange={event => setDailyTime(event.target.value)} /></Field>
              <div style={{ display: "flex", alignItems: "flex-end" }}><Btn variant="primary" icon="calendar" onClick={scheduleDaily} style={{ width: "100%" }}>Same time daily</Btn></div>
            </div>
            <div className="row gap-8 mt-12" style={{ flexWrap: "wrap" }}>
              <Btn variant="secondary" icon="download" onClick={exportSchedule}>Export schedule CSV</Btn>
              <Btn variant="secondary" icon="insta" onClick={publishNow}>Publish now</Btn>
            </div>
          </Card>
          <Card padding="none" title="Post queue" sub="Schedule every post individually, or drag cards to change the publishing sequence.">
            <div className="scheduler-queue">
              {posts.map((post, index) => (
                <div key={post.id} draggable onDragStart={() => setDragId(post.id)} onDragOver={event => event.preventDefault()} onDrop={() => reorderDrop(post.id)} onClick={() => setSelectedId(post.id)} className={"scheduler-post-row" + (selected?.id === post.id ? " active" : "")}>
                  <div className="scheduler-order">{String(index + 1).padStart(2, "0")}</div>
                  <MediaPreview post={post} />
                  <div className="scheduler-row-copy">
                    <b>{post.title || "Untitled post"}</b>
                    <span>{post.date} · {post.time} · {post.type}{post.storyEnabled ? " · Story too" : ""}</span>
                  </div>
                  <div className="scheduler-inline-controls" onClick={event => event.stopPropagation()}>
                    <label><span>Date</span><input className="input" type="date" value={post.date} onChange={event => updatePost(post.id, { date: event.target.value, status: post.status === "Published" ? "Published" : "Draft" })} /></label>
                    <label><span>Time</span><input className="input" type="time" value={post.time} onChange={event => updatePost(post.id, { time: event.target.value, status: post.status === "Published" ? "Published" : "Draft" })} /></label>
                  </div>
                  <div className="row gap-4" style={{ flexWrap: "wrap" }}>
                    <Pill variant={post.status === "Scheduled" ? "green" : post.status === "Draft" ? "amber" : "dark"}>{post.status}</Pill>
                    {post.storyEnabled && <Pill variant={post.storyStatus === "Scheduled" ? "green" : "blue"}>Story</Pill>}
                  </div>
                  <div className="row gap-4">
                    <Btn size="sm" variant="primary" icon="calendar" onClick={(event) => { event.stopPropagation(); schedulePost(post.id); }}>Schedule</Btn>
                    <IconBtn icon="arrow_up" onClick={(event) => { event.stopPropagation(); movePost(post.id, -1); }} />
                    <IconBtn icon="arrow_down" onClick={(event) => { event.stopPropagation(); movePost(post.id, 1); }} />
                  </div>
                </div>
              ))}
            </div>
          </Card>
        </div>
        <div className="col gap-16 scheduler-editor">
          {selected ? (
            <>
              <Card padding="lg" title="Post editor" sub="Everything you would prepare before publishing to Instagram.">
                <div className="scheduler-preview-large"><MediaPreview post={selected} large /></div>
                <div className="grid grid-2 gap-12 mt-16">
                  <Field label="Title"><input className="input" value={selected.title} onChange={event => updatePost(selected.id, { title: event.target.value })} /></Field>
                  <Field label="Type"><select className="select" value={selected.type} onChange={event => updatePost(selected.id, { type: event.target.value })}><option>Image</option><option>Carousel</option><option>Reel</option><option>Story</option></select></Field>
                  <Field label="Date"><input className="input" type="date" value={selected.date} onChange={event => updatePost(selected.id, { date: event.target.value })} /></Field>
                  <Field label="Time"><input className="input" type="time" value={selected.time} onChange={event => updatePost(selected.id, { time: event.target.value })} /></Field>
                </div>
                <Card padding="lg" title="AI optimisation goals" sub="Tick what you want this post to be written for. The AI uses these goals when creating the caption, hook, CTA and hashtags." style={{ marginTop: 14 }}>
                  <div className="ai-goal-grid">
                    {aiGoalOptions.map(goal => {
                      const checked = postGoals(selected).includes(goal.id);
                      return (
                        <label key={goal.id} className={"ai-goal" + (checked ? " active" : "")}>
                          <input type="checkbox" checked={checked} onChange={() => toggleGoal(goal.id)} />
                          <span className="ai-goal-box"><Icon name={checked ? "check" : "plus"} size={12} /></span>
                          <span><b>{goal.label}</b><small>{goal.desc}</small></span>
                        </label>
                      );
                    })}
                  </div>
                </Card>
                <Field label="Caption" style={{ marginTop: 12 }}><textarea className="textarea" value={selected.caption} onChange={event => updatePost(selected.id, { caption: event.target.value })} placeholder="Write the Instagram caption here, or generate it with AI." /></Field>
                <Field label="Hashtags"><textarea className="textarea" value={selected.hashtags} onChange={event => updatePost(selected.id, { hashtags: event.target.value })} placeholder="#appfounder #productlaunch #buildinpublic" /></Field>
                <Card padding="lg" title="Story repost" sub="Optional story published with the same image/video. No caption needed, just a link sticker under the picture." style={{ marginTop: 14 }}>
                  <label className={"ai-goal" + (selected.storyEnabled ? " active" : "")} style={{ marginBottom: 12 }}>
                    <input type="checkbox" checked={Boolean(selected.storyEnabled)} onChange={event => updatePost(selected.id, { storyEnabled: event.target.checked, storyStatus: event.target.checked && selected.status === "Scheduled" ? "Scheduled" : "Draft" })} />
                    <span className="ai-goal-box"><Icon name={selected.storyEnabled ? "check" : "plus"} size={12} /></span>
                    <span><b>Post this as a Story too</b><small>Use the same media at the same date/time as the feed post.</small></span>
                  </label>
                  <Field label="Story link sticker"><input className="input" value={selected.storyLink || ""} onChange={event => updatePost(selected.id, { storyLink: event.target.value })} placeholder="https://boltkit.co.uk or product link" disabled={!selected.storyEnabled} /></Field>
                  <div className="row-between mt-12" style={{ flexWrap: "wrap", gap: 10 }}>
                    <div className="muted text-xs">Story copy: picture/video only. Link appears underneath as the sticker/link field.</div>
                    <Pill variant={selected.storyEnabled ? selected.storyStatus === "Scheduled" ? "green" : "amber" : "dark"}>{selected.storyEnabled ? `Story ${selected.storyStatus || "Draft"}` : "Story off"}</Pill>
                  </div>
                </Card>
                <div className="grid grid-2 gap-12">
                  <Field label="CTA"><input className="input" value={selected.cta} onChange={event => updatePost(selected.id, { cta: event.target.value })} placeholder="View demo" /></Field>
                  <Field label="First comment"><input className="input" value={selected.firstComment} onChange={event => updatePost(selected.id, { firstComment: event.target.value })} placeholder="Optional first comment" /></Field>
                </div>
                <Field label="Alt text"><textarea className="textarea" value={selected.altText} onChange={event => updatePost(selected.id, { altText: event.target.value })} placeholder="Describe the image/video for accessibility." /></Field>
                {selected.viralNotes?.length > 0 && <div className="ai-surface card-pad mt-16"><span className="ai-chip"><Icon name="sparkle" size={11} />AI growth notes</span>{selected.optimizedFor?.length > 0 && <div className="chip-row mt-12">{selected.optimizedFor.map(goal => <span key={goal} className="chip active">{goal}</span>)}</div>}<div className="chip-row mt-12">{selected.viralNotes.map(note => <span key={note} className="chip active chip-yellow">{note}</span>)}</div>{selected.storyNotes?.length > 0 && <div className="chip-row mt-12">{selected.storyNotes.map(note => <span key={note} className="chip active">{note}</span>)}</div>}{selected.bestTimeReason && <p className="muted text-sm mt-12">{selected.bestTimeReason}</p>}</div>}
                <div className="row-between mt-16" style={{ flexWrap: "wrap", gap: 10 }}>
                  <Btn variant="secondary" icon="trash" onClick={() => removePost(selected.id)}>Remove</Btn>
                  <div className="row gap-8"><Btn variant="secondary" icon="sparkle" onClick={generateAI} disabled={generating}>{generating ? "Generating..." : "AI caption + hashtags"}</Btn><Btn variant="primary" icon="calendar" onClick={markScheduled}>Schedule post</Btn></div>
                </div>
              </Card>
              <Card padding="lg" title="Publishing checklist" sub="Ready for real Instagram publishing once connected.">
                <div className="col gap-8">
                  <CheckLine ok={Boolean(selected.mediaName && selected.mediaName !== "No media yet")} text="Media attached" />
                  <CheckLine ok={Boolean(selected.caption)} text="Caption written" />
                  <CheckLine ok={Boolean(selected.hashtags)} text="Hashtags added" />
                  <CheckLine ok={Boolean(selected.date && selected.time)} text="Date and time selected" />
                  <CheckLine ok={!selected.storyEnabled || Boolean(selected.storyLink)} text={selected.storyEnabled ? "Story link sticker added" : "Story repost optional"} />
                  <CheckLine ok={false} text="Instagram account connected" />
                </div>
              </Card>
            </>
          ) : <Card padding="lg" title="No post selected"><p className="muted text-sm">Upload media or select a queued post to edit it.</p></Card>}
        </div>
      </div>
    </PageShell>
  );
}

function MediaPreview({ post, large = false }) {
  const isVideo = post.previewUrl && /\.(mp4|mov|webm)$/i.test(post.mediaName || "");
  return (
    <div className={"scheduler-media" + (large ? " large" : "")}>
      {post.previewUrl && isVideo && <video src={post.previewUrl} muted playsInline />}
      {post.previewUrl && !isVideo && <img src={post.previewUrl} alt="" />}
      {!post.previewUrl && <div className="scheduler-media-empty"><Icon name="image" size={large ? 30 : 16} /><span>{post.mediaName || "Media"}</span></div>}
    </div>
  );
}

function CheckLine({ ok, text }) {
  return <div className="row gap-10 text-sm"><Icon name={ok ? "check_circle" : "alert"} size={14} color={ok ? "var(--green)" : "var(--amber)"} /><span>{text}</span></div>;
}

function WizardPage() {
  const { go, showToast, runGeneration, setCurrentProjectId } = React.useContext(AppCtx);
  const [step, setStep] = React.useState(0);
  const [form, setForm] = React.useState({
    name: "", url: "", description: "", status: "In development", audience: "", pain: "", tone: "Practical, punchy, premium", features: "", primary: "#EFFF00", secondary: "#0B0B0B", accent: "#4DA8FF", brandVoice: ""
  });
  const steps = ["Basics", "Audience", "Assets", "Brand", "AI Preview"];
  const set = (key) => (event) => setForm((f) => ({ ...f, [key]: event.target.value }));
  const project = {
    id: BoltKitMVP.slug(form.name || "new-project") + "-" + Date.now().toString(36),
    name: form.name || "Untitled App",
    tagline: form.description || "New launch project",
    icon: { letter: (form.name || "B")[0].toUpperCase(), gradient: `linear-gradient(135deg, ${form.primary}, ${form.accent})` },
    url: form.url,
    status: "Ready",
    statusVariant: "blue",
    readiness: form.name && form.audience ? 76 : 48,
    missing: 3,
    lastPack: "Full Launch Pack",
    lastGen: "Just now",
    packs: 1,
    audience: form.audience,
    pain: form.pain,
    tone: form.tone,
    summary: `${form.name || "This app"} helps ${form.audience || "its audience"} by ${form.description || "turning product context into a clearer launch story"}.`,
    features: String(form.features || "").split(/\n|,/).map((x) => x.trim()).filter(Boolean),
    colors: [form.primary, form.secondary, form.accent],
    fonts: { heading: "Anton", body: "Inter" }
  };
  const save = () => {
    PROJECTS.unshift(project);
    BoltKitMVP.persistProject(project);
    setCurrentProjectId(project.id);
    showToast("Project created locally · generating first pack");
    runGeneration(PACK_TYPES[0]);
  };
  return (
    <PageShell eyebrow={`New project · Step ${step + 1} of ${steps.length}`} title={steps[step]} sub="Create a project locally, then generate a launch pack in demo mode." action={<Btn variant="ghost" icon="close" onClick={() => go("dashboard")}>Cancel</Btn>}>
      <div className="card card-pad mb-24" style={{ overflow: "auto" }}><Steps steps={steps} current={step} /></div>
      <Card padding="lg">
        {step === 0 && <div className="grid grid-2 gap-16"><Field label="Project name"><input className="input" value={form.name} onChange={set("name")} placeholder="My app" /></Field><Field label="Website/app URL"><input className="input" value={form.url} onChange={set("url")} placeholder="https://example.com" /></Field><Field label="Short description" style={{ gridColumn: "span 2" }}><textarea className="textarea" value={form.description} onChange={set("description")} placeholder="What does the app do?" /></Field><Field label="Status"><select className="select" value={form.status} onChange={set("status")}><option>Idea</option><option>In development</option><option>Beta</option><option>Launching</option><option>Live</option></select></Field></div>}
        {step === 1 && <div className="grid grid-2 gap-16"><Field label="Target audience" style={{ gridColumn: "span 2" }}><textarea className="textarea" value={form.audience} onChange={set("audience")} /></Field><Field label="Pain point"><textarea className="textarea" value={form.pain} onChange={set("pain")} /></Field><Field label="Tone of voice"><textarea className="textarea" value={form.tone} onChange={set("tone")} /></Field><Field label="Feature notes" style={{ gridColumn: "span 2" }}><textarea className="textarea" value={form.features} onChange={set("features")} placeholder="One feature per line" /></Field></div>}
        {step === 2 && <div className="grid grid-2 gap-16">{["Logo", "App icon", "Screenshots", "Brand pack"].map((x) => <div className="upload-zone" key={x}><Icon name="upload" size={22} color="var(--yellow)" /><b>{x}</b><span className="muted text-sm">Drop files here or click to preview local upload state.</span><input type="file" multiple onChange={() => showToast(`${x} staged locally`)} /></div>)}</div>}
        {step === 3 && <div className="grid grid-2 gap-16"><Field label="Primary colour"><input className="input" value={form.primary} onChange={set("primary")} /></Field><Field label="Secondary colour"><input className="input" value={form.secondary} onChange={set("secondary")} /></Field><Field label="Accent colour"><input className="input" value={form.accent} onChange={set("accent")} /></Field><Field label="Brand voice"><textarea className="textarea" value={form.brandVoice} onChange={set("brandVoice")} /></Field></div>}
        {step === 4 && <div className="grid grid-2 gap-16"><Card padding="lg" title="AI analysis preview"><ScoreRow label="Readiness score" value={project.readiness} /><p className="muted mt-12">{project.summary}</p></Card><Card padding="lg" title="Missing assets"><div className="col gap-8">{["Founder quote", "App Store screenshots", "Demo video"].map((x) => <div className="check-row" key={x}><Icon name="alert" size={13} color="var(--amber)" />{x}</div>)}</div></Card></div>}
      </Card>
      <div className="row-between mt-24" style={{ flexWrap: "wrap", gap: 12 }}><Btn variant="secondary" icon="arrow_left" onClick={() => setStep((s) => Math.max(0, s - 1))} disabled={step === 0}>Back</Btn><div className="row gap-8"><Btn variant="ghost" onClick={() => showToast("Draft saved locally")}>Save draft</Btn>{step < steps.length - 1 ? <Btn variant="primary" iconRight="arrow_right" onClick={() => setStep((s) => Math.min(steps.length - 1, s + 1))}>Continue</Btn> : <Btn variant="primary" icon="sparkle" onClick={save}>Save Project & Generate First Pack</Btn>}</div></div>
    </PageShell>
  );
}

function ExportsPage() {
  const { showToast, generatedSet, currentProject } = React.useContext(AppCtx);
  const [format, setFormat] = React.useState("zip");
  const [exporting, setExporting] = React.useState(false);
  const [history, setHistory] = React.useState(() => BoltKitMVP.getExportHistory());
  const run = async () => {
    setExporting(true);
    await BoltKitMVP.exportProject(currentProject, format);
    setExporting(false);
    setHistory(BoltKitMVP.getExportHistory());
    showToast(`Export ready · ${format.toUpperCase()} downloaded`);
  };
  return (
    <PageShell eyebrow={`${currentProject.name} · ${generatedSet.size} packs ready`} title={<>Export <span className="hl">Centre</span></>} sub="Working exports for Markdown, CSV, JSON and ZIP. PDF remains a placeholder.">
      <div className="grid grid-2 gap-20">
        <Card padding="lg" title="Choose format">
          <div className="grid grid-2 gap-10">{["md", "csv", "json", "zip"].map((f) => <button key={f} className={"format-card " + (format === f ? "active" : "")} onClick={() => setFormat(f)}><Icon name={f} size={18} /><b>{f.toUpperCase()}</b><span>{f === "zip" ? "Full folder" : "Single file"}</span></button>)}</div>
          <Btn variant="primary" icon="download" onClick={run} disabled={exporting} style={{ marginTop: 16, width: "100%" }}>{exporting ? "Packaging..." : "Download export"}</Btn>
        </Card>
        <Card padding="lg" title="ZIP folder preview" sub="Generated with real local files."><ZipTree /></Card>
      </div>
      <Card padding="lg" title="Export includes" style={{ marginTop: 20 }}><div className="grid grid-3 gap-10">{["brand-summary.md", "launch-pack.md", "instagram-posts.md", "video-scripts.md", "paid-ads.md", "app-store-copy.md", "landing-page-copy.md", "seo-pack.md", "claude-prompts.md", "codex-prompts.md", "content-calendar.csv", "project-data.json"].map((x) => <Pill key={x} variant="dark">{x}</Pill>)}</div></Card>
      <Card padding="none" title="Recent exports" sub="Stored locally in this browser" style={{ marginTop: 20 }}>
        {history.length === 0 ? (
          <div className="card-pad muted text-sm">No exports yet. Download one above to start the local history.</div>
        ) : history.slice(0, 8).map((item, index) => (
          <div key={item.id} className="row gap-12" style={{ padding: "12px 18px", borderTop: index === 0 ? 0 : "1px solid var(--border)" }}>
            <div style={{ width: 34, height: 34, borderRadius: 8, background: "var(--surface-2)", display: "grid", placeItems: "center", color: "var(--yellow)" }}>
              <Icon name={item.format.toLowerCase() === "zip" ? "zip" : item.format.toLowerCase()} size={15} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div className="fw-8 text-sm" style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{item.fileName}</div>
              <div className="muted text-xs mt-4">{item.projectName} · {item.format} · {new Date(item.createdAt).toLocaleString()}</div>
            </div>
            <Pill variant="green">Ready</Pill>
          </div>
        ))}
      </Card>
    </PageShell>
  );
}

Object.assign(window, {
  BoltKitMVP, PricingPage, FeaturesPage, DemoPage, LoginPage, SignupPage, ForgotPasswordPage,
  AccountSettingsPage, BillingSettingsPage, UsagePage, SystemHealthPage, TermsPage, PrivacyPage,
  InstagramSchedulerPage,
  WizardPage, ExportsPage, GeneratedPackPage, SocialContentPage, VideoScriptPage, AppStorePage,
  AdsPage, LandingPage, SEOPage, ClaudePromptsPage, CodexPromptsPage
});
