Files
vibn-agent-runner/justine/06_architect.html
mawkone 99deb546c8 Rip out Theia, bump submodules, retire platform/ scaffold, snapshot docs + design assets
Theia rip-out (parent):
- Remove theia submodule entry (the local fork, Gitea repo, Coolify app,
  Cloud Run services, and Artifact Registry image are all gone)
- Drop README.md + INFRASTRUCTURE.md (obsolete "Project OS" snapshots
  that also leaked API tokens) and setup.sh (Theia clone bootstrap)
- Delete UI-DESIGN-GUIDE.md, BACKEND_AGENTS_PLAN.md, VIBN_BUILD_PLAN.md,
  VISUAL_EDITOR_PLAN.md, core-packages.md, ai-packages.md, tools-list.md
  (all 100% Theia-specific or superseded)
- Surgical scrubs of remaining Theia mentions in
  AGENT_EXECUTION_ARCHITECTURE.md and TURBOREPO_MIGRATION_PLAN.md

Submodule bumps:
- vibn-agent-runner: Theia rip-out + MCP refactor (api/wrapper/server
  pattern across shell/file/git/memory/prd/search/agent/gitea/coolify)
- vibn-frontend: Theia rip-out + P5.1 attach E2E + Justine UI WIP

Retire platform/ scaffold:
- Remove platform/backend/ (control-plane, executors, mcp-adapter),
  platform/client-ide/ (gcp-productos extension), platform/contracts/,
  platform/infra/terraform/, platform/scripts/templates/turborepo/
  (replaced by vibn-agent-runner + vibn-frontend + Coolify direct)
- Drop architecture.md, technical_spec.md, vision-ext.md,
  "1.Generate Control Plane API scaffold.md" (same era)

Docs / planning snapshots (new):
- AI_CAPABILITIES.md, AI_CAPABILITIES_ROADMAP.md
- AGENT_TELEMETRY_STREAMING_PROJECT.md
- VIBN_PRD.md, product-idea-a.md

Design assets (new):
- branding/{coolify,gitea,ux-testing}/ static brand collateral
- justine/ HTML mockups for the new onboarding/build flows
- preview-assist-ui/ Vite scratch app
- master-ai.code-workspace

Infra helpers (new):
- setup-coolify-montreal.sh provisioner
- gitea-docker-compose.yml
- vibn-coolify-schema.sql for the Coolify Postgres extensions
- prd-agent-prompt.pdf, prompt, root.txt, remixed-9edec9e9.tsx scratch
- flatten.sh helper

.gitignore: ignore **/node_modules, **/.next, **/.turbo, **/coverage

Made-with: Cursor
2026-04-22 18:06:37 -07:00

590 lines
42 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="icon" href="favicon_clean.ico">
<title>vibn — Architect</title>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
*{box-sizing:border-box;margin:0;padding:0;}
:root{
--ink:#1A1A1A;--mid:#6B7280;--muted:#9CA3AF;
--border:#E5E7EB;--cream:#FAFAFF;--paper:#F5F3FF;--white:#FFFFFF;
--indigo:#6366F1;--indigo-dark:#4338CA;--indigo-deep:#2E2A5E;
--indigo-soft:rgba(99,102,241,0.08);--indigo-ring:rgba(99,102,241,0.12);
}
body{font-family:'Plus Jakarta Sans',sans-serif;background:linear-gradient(to bottom,#FAFAFA,#F5F3FF);display:flex;flex-direction:column;height:100vh;overflow:hidden;}
.f{font-family:'Plus Jakarta Sans',sans-serif;}
/* ── Dark mode — exact match to Describe ── */
[data-theme="dark"]{
--ink:#ECE9F5;--ink2:#C8C4D8;--ink3:#A0A0B8;
--mid:#9AA3BC;--muted:#6A7490;--border:#3A4260;
--cream:#2A3250;--paper:#2A3250;--white:#2A3250;
--indigo:#818CF8;--indigo-dark:#A5B4FC;--indigo-deep:#6366F1;
--indigo-soft:rgba(99,102,241,0.12);--indigo-ring:rgba(99,102,241,0.2);
}
[data-theme="dark"] body{background:#1A1F2E;}
/* Structural panels — same hierarchy as Describe: sidebar & main = mid, right panel = darkest */
[data-theme="dark"] .arch-sidebar{background:#2A3250!important;border-right-color:#3A4260!important;}
[data-theme="dark"] .arch-main{background:#212840!important;}
[data-theme="dark"] [style*="background:#f5f3ff"]{background:#1A1F2E!important;}
/* White & near-white backgrounds (cards float above panels) */
[data-theme="dark"] [style*="background:var(--white)"]{background:#2A3250!important;}
[data-theme="dark"] [style*="background:#fafaff"]{background:#212840!important;}
[data-theme="dark"] [style*="background:#FAFAFA"]{background:#212840!important;}
[data-theme="dark"] [style*="background:#f0f4ff"]{background:#2A3250!important;}
[data-theme="dark"] [style*="background:#eef2ff"]{background:rgba(99,102,241,0.18)!important;}
[data-theme="dark"] [style*="background:#F3F4F6"]{background:#3A4260!important;}
/* Borders */
[data-theme="dark"] [style*="border-bottom:1px solid #c7d2fe"]{border-bottom-color:#3A4260!important;}
[data-theme="dark"] [style*="border:1px solid #e0e7ff"]{border-color:#3A4260!important;}
[data-theme="dark"] [style*="border:1px solid rgba(99,102,241"]{border-color:rgba(99,102,241,0.06)!important;}
/* Sidebar-specific */
[data-theme="dark"] .arch-sidebar [style*="border-top:1px solid #e5e7eb"]{border-top-color:#3A4260!important;}
[data-theme="dark"] .arch-sidebar [style*="background:#e5e7eb"]{background:#3A4260!important;}
[data-theme="dark"] .arch-sidebar [style*="color:#1a1a1a"]{color:#ECE9F5!important;}
[data-theme="dark"] .arch-sidebar [style*="color:#6b7280"]{color:#9AA3BC!important;}
[data-theme="dark"] .arch-sidebar [style*="color:#444441"]{color:#6A7490!important;}
[data-theme="dark"] .arch-sidebar [style*="color:#9ca3af"]{color:#6A7490!important;}
/* Phase & progress dots: filled indigo → light lavender (matching Describe's --accent-primary in dark) */
[data-theme="dark"] .arch-sidebar [style*="background:#6366F1"]{background:#A5B4FC!important;color:#1A1F2E!important;}
[data-theme="dark"] [style*="color:#4338ca"]{color:#A5B4FC!important;}
[data-theme="dark"] .sidebar-phase.active{background:rgba(165,180,252,0.12)!important;}
/* Blueprint rows */
[data-theme="dark"] .blueprint-row:hover{background:#323C5E!important;}
[data-theme="dark"] .blueprint-row.locked{background:#242B48!important;}
[data-theme="dark"] .blueprint-row.locked:hover{background:#2E3A5A!important;}
/* Option buttons */
[data-theme="dark"] .opt-btns{border-color:#3A4260!important;}
[data-theme="dark"] .opt-btn{color:#C8D0E8!important;border-right-color:#3A4260!important;}
[data-theme="dark"] .opt-btn:hover{background:#2E3A5A!important;color:#A5B4FC!important;}
[data-theme="dark"] .opt-btn.selected{background:rgba(99,102,241,0.15)!important;color:#A5B4FC!important;}
[data-theme="dark"] .opt-btn.why-btn{color:#A5B4FC!important;}
[data-theme="dark"] .why-btn{color:#9AA3BC!important;border-color:#3A4260!important;}
/* Right panel */
[data-theme="dark"] .deliverable-row{color:#9AA3BC!important;}
[data-theme="dark"] .deliverable-row:hover{background:#2E3A5A!important;}
/* Popups & modals */
[data-theme="dark"] #why-popup>div{background:#242B48!important;box-shadow:0 0 0 1px rgba(165,180,252,0.18),0 24px 64px rgba(0,0,0,0.55),0 0 48px rgba(99,102,241,0.14)!important;}
[data-theme="dark"] #save-exit-box{background:#242B48!important;box-shadow:0 0 0 1px rgba(165,180,252,0.18),0 24px 64px rgba(0,0,0,0.55),0 0 48px rgba(99,102,241,0.14)!important;}
[data-theme="dark"] .modal-card{background:#242B48!important;box-shadow:0 0 0 1px rgba(165,180,252,0.18),0 24px 64px rgba(0,0,0,0.55),0 0 48px rgba(99,102,241,0.14)!important;}
/* Buttons */
[data-theme="dark"] #sidebar-project-name{color:#6A7490!important;}
[data-theme="dark"] #dark-toggle{background:#2A3250!important;border-color:#3A4260!important;color:var(--mid)!important;}
[data-theme="dark"] button[onclick="saveAndExit()"]{background:#1E2640!important;border-color:#3A4260!important;}
[data-theme="dark"] button[onclick="saveAndExit()"] span{color:#A5B4FC!important;}
/* Next button — same gradient as Describe's next button */
[data-theme="dark"] button[onclick="openWhy()"]{color:#A5B4FC!important;}
[data-theme="dark"] .btn-primary{background:linear-gradient(135deg,#4338CA,#6366F1)!important;color:#FFFFFF!important;box-shadow:0 4px 14px rgba(99,102,241,0.25)!important;}
/* Scrollbar */
[data-theme="dark"] ::-webkit-scrollbar{width:6px;height:6px;}
[data-theme="dark"] ::-webkit-scrollbar-track{background:#1A1F2E;}
[data-theme="dark"] ::-webkit-scrollbar-thumb{background:#3A4260;border-radius:3px;}
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover{background:#5865A0;}
[data-theme="dark"] *{scrollbar-color:#3A4260 #1A1F2E;scrollbar-width:thin;}
[data-theme="dark"] .vibn-avatar{background:#6366F1!important;}
/* Sidebar */
.sidebar-phase{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:8px;}
.sidebar-phase.active{background:#fafaff;}
.phase-dot{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:10px;}
/* Blueprint row */
.blueprint-row{display:grid;grid-template-columns:36px 1fr 248px;align-items:center;gap:16px;padding:15px 22px;border-bottom:1px solid var(--border);transition:background 0.15s;}
.blueprint-row:last-child{border-bottom:none;border-radius:0 0 14px 14px;}
.blueprint-row:hover{background:#FAFAFF;}
.blueprint-row.locked{background:#FAFAFA;}
.blueprint-row.locked:hover{background:#F5F5F5;}
/* Option toggle buttons */
.opt-btns{display:flex;gap:0;flex-shrink:0;border:1.5px solid var(--border);border-radius:8px;overflow:visible;}
.opt-btn{flex:1;text-align:center;font-size:12px;font-weight:500;color:var(--mid);background:transparent;border:none;border-right:1.5px solid var(--border);border-radius:0;padding:6px 13px;cursor:pointer;font-family:'Plus Jakarta Sans',sans-serif;transition:all 0.15s;white-space:nowrap;position:relative;}
.opt-btn:first-child{border-radius:7px 0 0 7px;}
.opt-btn:last-child{border-right:none;border-radius:0 7px 7px 0;}
.opt-btn:hover{background:#F5F5FF;color:var(--indigo);}
.opt-btn.selected{background:var(--indigo-soft);color:var(--indigo-dark);font-weight:600;}
/* Why button (hosting) */
.why-btn{font-size:11.5px;font-weight:600;color:var(--mid);background:transparent;border:1px solid var(--border);border-radius:6px;padding:5px 11px;cursor:pointer;font-family:'Plus Jakarta Sans',sans-serif;transition:border-color 0.15s,color 0.15s;white-space:nowrap;}
.why-btn:hover{border-color:var(--indigo);color:var(--indigo);}
/* Primary button */
.btn-primary{background:linear-gradient(135deg,var(--indigo-deep),var(--indigo-dark));color:#FFFFFF;border:none;border-radius:8px;padding:10px 22px;font-family:'Plus Jakarta Sans',sans-serif;font-size:13px;font-weight:600;cursor:pointer;box-shadow:0 10px 25px rgba(30,27,75,0.15);transition:box-shadow 0.2s,transform 0.2s;}
.btn-primary:hover{box-shadow:0 10px 25px rgba(30,27,75,0.15),0 0 0 6px var(--indigo-ring);transform:translateY(-1px);}
/* What you're getting panel */
.deliverable-row{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:7px;font-size:12px;color:var(--mid);transition:background 0.12s;}
.deliverable-row:hover{background:var(--cream);}
/* Modal */
.modal-bg{display:none;position:fixed;inset:0;background:rgba(15,14,26,0.45);backdrop-filter:blur(2px);z-index:100;align-items:center;justify-content:center;}
.modal-bg.open{display:flex;}
.modal-card{background:var(--white);border-radius:16px;width:400px;overflow:hidden;box-shadow:0 24px 64px rgba(30,27,75,0.18);}
/* Option buttons in modal */
.option-btn{display:flex;align-items:center;gap:12px;padding:12px 16px;border-radius:10px;border:1px solid var(--border);background:var(--white);cursor:pointer;text-align:left;margin-bottom:8px;transition:all 0.15s;}
.option-btn:hover{border-color:var(--indigo);background:var(--cream);}
.option-btn.selected{border-color:var(--indigo);background:var(--cream);box-shadow:0 0 0 3px var(--indigo-ring);}
/* Save popup */
#save-exit-popup{display:none;position:fixed;inset:0;background:rgba(15,14,26,0.45);backdrop-filter:blur(2px);z-index:700;align-items:center;justify-content:center;padding:24px;}
#save-exit-popup.visible{display:flex;}
#save-exit-box{background:#FFFFFF;border-radius:16px;box-shadow:0 24px 64px rgba(30,27,75,0.18);padding:32px;width:100%;max-width:380px;text-align:center;}
#save-exit-box .save-icon{width:48px;height:48px;background:#f0f4ff;border:1px solid #e0e7ff;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:20px;margin:0 auto 16px;}
#save-exit-box h3{font-size:18px;font-weight:700;color:var(--ink);margin-bottom:8px;}
#save-exit-box p{font-size:13px;color:var(--muted);line-height:1.6;margin-bottom:20px;}
#save-exit-box .save-cancel{font-size:12px;color:var(--muted);cursor:pointer;text-decoration:underline;background:none;border:none;font-family:'Plus Jakarta Sans',sans-serif;}
#save-exit-box .save-cancel:hover{color:var(--ink);}
/* Why accordion */
/* ── Mobile tab bar (hidden on desktop) ── */
.mob-tabs{display:none;flex-shrink:0;background:#EEF0FF;border-top:1px solid #D4D8FA;padding-bottom:env(safe-area-inset-bottom);}
[data-theme="dark"] .mob-tabs{background:#212840!important;}
.mob-tab-btn{flex:1;padding:11px 8px;border:none;background:transparent;font-family:'Plus Jakarta Sans',sans-serif;font-size:13px;font-weight:500;color:var(--muted);cursor:pointer;border-top:2px solid transparent;transition:color 0.15s,border-color 0.15s;}
.mob-tab-btn.active{color:#6366F1;border-top-color:#6366F1;font-weight:600;}
.mob-dash-btn{background:none;border:none;font-family:'Plus Jakarta Sans',sans-serif;font-size:11.5px;font-weight:500;color:var(--muted);cursor:pointer;padding:11px 12px;white-space:nowrap;flex:none;transition:color 0.15s;}
.mob-dash-btn:hover{color:var(--ink);}
[data-theme="dark"] .mob-tab-btn{color:#6A7490!important;}
[data-theme="dark"] .mob-tab-btn.active{color:#A5B4FC!important;border-top-color:#A5B4FC!important;}
/* ── Responsive ── */
/* Tablet (641px 1024px): top tab bar, full-height panels */
@media (min-width:641px) and (max-width:1024px){
body{height:100dvh;overflow:hidden;}
.arch-layout{flex-direction:column!important;height:100dvh!important;overflow:hidden!important;}
.arch-sidebar{display:none!important;}
.mob-tabs{display:flex!important;order:0;border-top:none!important;border-bottom:1px solid #D4D8FA!important;padding-bottom:0!important;}
.mob-tab-btn{border-top:none;border-bottom:2px solid transparent;}
.mob-tab-btn.active{border-top-color:transparent;border-bottom-color:#6366F1;}
[data-theme="dark"] .mob-tab-btn.active{border-bottom-color:#A5B4FC!important;border-top-color:transparent!important;}
.arch-main{display:none!important;order:1;overflow:hidden!important;flex:1 1 0%!important;height:0!important;min-height:0!important;}
.arch-main.tab-active{display:flex!important;}
.arch-scroll{flex:1 1 0%!important;height:0!important;min-height:0!important;overflow-y:auto!important;-webkit-overflow-scrolling:touch;}
.arch-right{display:none!important;order:1;width:100%!important;border-left:none!important;flex:1 1 0%!important;height:0!important;min-height:0!important;}
.arch-right.tab-active{display:flex!important;}
.arch-right-scroll{flex:1 1 0%!important;height:0!important;min-height:0!important;overflow-y:auto!important;-webkit-overflow-scrolling:touch;}
.arch-right-footer{padding:12px 16px 20px!important;}
.arch-right-footer a{width:80%;display:block;}
.blueprint-row{grid-template-columns:36px 1fr!important;row-gap:10px;padding:13px 18px!important;}
.blueprint-row .opt-btns{grid-column:1 / -1;width:100%;}
}
/* Mobile (≤ 640px): tabbed layout, tabs at bottom */
@media (max-width:640px){
body{height:100dvh;overflow:hidden;}
.arch-layout{flex-direction:column!important;height:100dvh!important;overflow:hidden!important;}
.arch-sidebar{display:none!important;}
.mob-tabs{display:flex!important;order:2;}
.arch-main{display:none!important;order:1;overflow:hidden!important;flex:1 1 0%!important;height:0!important;min-height:0!important;}
.arch-main.tab-active{display:flex!important;}
.arch-scroll{flex:1 1 0%!important;height:0!important;min-height:0!important;overflow-y:auto!important;-webkit-overflow-scrolling:touch;}
.arch-right{display:none!important;order:1;width:100%!important;border-left:none!important;flex:1 1 0%!important;height:0!important;min-height:0!important;}
.arch-right.tab-active{display:flex!important;}
.arch-right-scroll{flex:1 1 0%!important;height:0!important;min-height:0!important;overflow-y:auto!important;-webkit-overflow-scrolling:touch;}
.blueprint-row{grid-template-columns:36px 1fr!important;row-gap:10px;padding:13px 16px!important;}
.blueprint-row .opt-btns{grid-column:1 / -1;width:100%;}
.opt-btn{flex:1;padding:7px 8px!important;font-size:11.5px!important;}
.arch-topbar{padding:14px 16px 12px!important;}
.arch-right-footer{padding:12px 16px 20px!important;}
.arch-right-footer a{width:100%!important;display:block!important;}
.modal-card{width:calc(100vw - 32px)!important;}
#why-popup>div{max-width:calc(100vw - 32px)!important;}
}
/* Mobile with trackpad (laptop narrow): tabs at top */
@media (max-width:640px) and (hover:hover) and (pointer:fine){
.mob-tabs{order:0!important;border-top:none!important;border-bottom:1px solid #D4D8FA!important;padding-bottom:0!important;}
.mob-tab-btn{border-top:none;border-bottom:2px solid transparent;}
.mob-tab-btn.active{border-top-color:transparent;border-bottom-color:#6366F1;}
[data-theme="dark"] .mob-tab-btn.active{border-bottom-color:#A5B4FC!important;}
.arch-main{order:1!important;}
.arch-right{order:1!important;}
}
</style>
</head>
<body>
<div class="arch-layout" style="display:flex;height:100%;overflow:hidden;">
<!-- Mobile tab bar (hidden on desktop, shown on ≤ 640px) -->
<div class="mob-tabs" id="mob-tabs">
<button onclick="saveAndExit()" class="mob-dash-btn">Dashboard</button>
<div style="width:1px;background:var(--border);margin:8px 0;flex-shrink:0;"></div>
<button class="mob-tab-btn active" id="tab-blueprint" onclick="switchArchTab('blueprint')">Blueprint</button>
<button class="mob-tab-btn" id="tab-scope" onclick="switchArchTab('scope')">Scope</button>
</div>
<!-- ── SIDEBAR ── -->
<div class="arch-sidebar" style="width:200px;background:#ffffff;border-right:1px solid #e5e7eb;display:flex;flex-direction:column;padding:18px 12px;flex-shrink:0;">
<div style="padding:0 6px;margin-bottom:26px;">
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px;">
<div class="vibn-avatar" style="width:26px;height:26px;background:linear-gradient(135deg,#2E2A5E,#4338CA);border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;"><span class="f" style="font-size:13px;font-weight:700;color:#FFFFFF;">V</span></div>
<span class="f" style="font-size:16px;font-weight:700;color:#1a1a1a;letter-spacing:-0.02em;">vibn</span>
</div>
<div id="sidebar-project-name" style="font-size:11px;font-weight:500;color:#9ca3af;padding-left:34px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:none;"></div>
</div>
<div style="font-size:9.5px;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:#9ca3af;padding:0 6px;margin-bottom:8px;">MVP Setup</div>
<div style="display:flex;flex-direction:column;gap:2px;flex:1;">
<div class="sidebar-phase">
<div class="phase-dot" style="background:#6366F1;color:#ffffff;"></div>
<div style="font-size:12.5px;color:#6b7280;">Describe</div>
</div>
<div class="sidebar-phase active">
<div class="phase-dot" style="background:#6366F1;color:#ffffff;"></div>
<div><div style="font-size:12.5px;font-weight:600;color:#1a1a1a;">Architect</div><div style="font-size:10px;color:#9ca3af;">What gets built</div></div>
</div>
<div class="sidebar-phase">
<div class="phase-dot" style="background:#e5e7eb;color:#9ca3af;"></div>
<div style="font-size:12.5px;color:#9ca3af;">Design</div>
</div>
<div class="sidebar-phase">
<div class="phase-dot" style="background:#e5e7eb;color:#9ca3af;"></div>
<div style="font-size:12.5px;color:#9ca3af;">Market</div>
</div>
<div class="sidebar-phase">
<div class="phase-dot" style="background:#e5e7eb;color:#9ca3af;"></div>
<div style="font-size:12.5px;color:#9ca3af;">Build MVP</div>
</div>
</div>
<div style="border-top:1px solid #e5e7eb;margin-top:14px;padding-top:12px;">
<button onclick="saveAndExit()" style="display:flex;align-items:center;justify-content:center;gap:7px;width:100%;background:#eef2ff;border:1px solid #e0e7ff;border-radius:8px;padding:9px 10px;cursor:pointer;font-family:'Plus Jakarta Sans',sans-serif;transition:background 0.15s;" onmouseover="this.style.background='#e0e7ff'" onmouseout="this.style.background='#eef2ff'">
<span style="font-size:12px;font-weight:600;color:#6366F1;">Save & go to dashboard</span>
</button>
<button id="dark-toggle" onclick="toggleTheme()" style="margin-top:8px;display:flex;align-items:center;justify-content:center;width:100%;background:transparent;border:1px solid var(--border);border-radius:8px;padding:8px 10px;cursor:pointer;font-family:'Plus Jakarta Sans',sans-serif;font-size:12px;font-weight:500;color:var(--mid);transition:background 0.15s,border-color 0.15s;" onmouseover="this.style.borderColor='#6366F1';this.style.color='#6366F1';" onmouseout="this.style.borderColor='var(--border)';this.style.color='var(--mid)';">🌙 Dark mode</button>
</div>
</div>
<!-- ── MAIN ── -->
<div class="arch-main" style="flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0;position:relative;z-index:1;">
<!-- Top bar -->
<div class="arch-topbar" style="padding:18px 28px 14px;background:var(--white);border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;">
<div>
<div class="f" style="font-size:17px;font-weight:700;color:var(--ink);margin-bottom:3px;">Your product blueprint</div>
<div style="font-size:12.5px;color:var(--muted);">We set everything up — review and confirm to continue.</div>
</div>
</div>
<!-- Scrollable body -->
<div class="arch-scroll" style="flex:1;overflow-y:auto;padding:24px 28px;display:flex;flex-direction:column;gap:12px;">
<!-- Intro message -->
<div style="display:flex;align-items:flex-start;gap:10px;">
<div class="vibn-avatar" style="width:26px;height:26px;background:linear-gradient(135deg,#2E2A5E,#4338CA);border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;"><span style="font-size:12px;font-weight:700;color:#FFFFFF;">V</span></div>
<div style="max-width:84%;background:#f0f4ff;border:1px solid #e0e7ff;border-radius:4px 12px 12px 12px;padding:11px 14px;font-size:13px;color:var(--ink);line-height:1.65;">
Here's the technical stack we've set up for <strong id="intro-project-name" style="font-weight:600;">your product</strong>. These are the best defaults for an idea like yours — review each decision below and change anything that doesn't feel right.
</div>
</div>
<!-- Blueprint card -->
<div style="background:var(--white);border:1px solid var(--border);border-radius:14px;overflow:visible;box-shadow:0 4px 20px rgba(30,27,75,0.05);">
<!-- Card header -->
<div style="padding:14px 22px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;">
<div style="width:8px;height:8px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>
<span style="font-size:13px;font-weight:600;color:var(--ink);">How vibn will build it</span>
<button onclick="openWhy()" style="margin-left:auto;background:none;border:none;cursor:pointer;font-family:'Plus Jakarta Sans',sans-serif;font-size:12px;color:#6366F1;font-weight:600;padding:0;display:flex;align-items:center;gap:5px;">💡 Why these choices?</button>
</div>
<!-- Frontend -->
<div class="blueprint-row">
<div style="width:32px;height:32px;border-radius:9px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--indigo);"></div>
<div>
<div style="font-size:13px;font-weight:600;color:var(--ink);margin-bottom:2px;">Frontend</div>
<div style="font-size:11.5px;color:var(--muted);">Where will your users mostly be when they use your product — at a desk, or on the go? This shapes every screen we design.</div>
</div>
<div class="opt-btns">
<button class="opt-btn selected" data-group="frontend" data-tip="Runs in any browser, desktop & mobile" onclick="selectOpt('frontend',this)">Web app</button>
<button class="opt-btn" data-group="frontend" data-tip="Optimised for phones, still works on desktop" onclick="selectOpt('frontend',this)">Mobile-first</button>
</div>
</div>
<!-- Backend -->
<div class="blueprint-row">
<div style="width:32px;height:32px;border-radius:9px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--indigo);"></div>
<div>
<div style="font-size:13px;font-weight:600;color:var(--ink);margin-bottom:2px;">Backend & Database</div>
<div style="font-size:11.5px;color:var(--muted);">The invisible part that stores your users' data and makes everything work behind the scenes</div>
</div>
<div class="opt-btns">
<button class="opt-btn selected" data-group="backend" data-tip="Standard setup, works for almost everything" onclick="selectOpt('backend',this)">API + database</button>
<button class="opt-btn" data-group="backend" data-tip="Live updates between users — great for collaboration" onclick="selectOpt('backend',this)">Real-time</button>
</div>
</div>
<!-- Auth -->
<div class="blueprint-row">
<div style="width:32px;height:32px;border-radius:9px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--indigo);"></div>
<div>
<div style="font-size:13px;font-weight:600;color:var(--ink);margin-bottom:2px;">Sign up & Login</div>
<div style="font-size:11.5px;color:var(--muted);">How people create an account and get back in — fewer steps means more people actually sign up</div>
</div>
<div class="opt-btns">
<button class="opt-btn selected" data-group="auth" data-tip="Google & GitHub sign-in — less friction, more sign-ups" onclick="selectOpt('auth',this)">Email + social</button>
<button class="opt-btn" data-group="auth" data-tip="Simpler setup, no third-party login" onclick="selectOpt('auth',this)">Email only</button>
</div>
</div>
<!-- Payments -->
<div class="blueprint-row">
<div style="width:32px;height:32px;border-radius:9px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--indigo);"></div>
<div>
<div style="font-size:13px;font-weight:600;color:var(--ink);margin-bottom:2px;">Payments</div>
<div style="font-size:11.5px;color:var(--muted);">How you get paid — Stripe handles the card processing so you never touch sensitive data</div>
</div>
<div class="opt-btns">
<button class="opt-btn selected" data-group="payments" data-tip="Monthly or annual recurring payments" onclick="selectOpt('payments',this)">Subscription</button>
<button class="opt-btn" data-group="payments" data-tip="Pay once, own forever" onclick="selectOpt('payments',this)">One-time</button>
</div>
</div>
<!-- Email -->
<div class="blueprint-row">
<div style="width:32px;height:32px;border-radius:9px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--indigo);"></div>
<div>
<div style="font-size:13px;font-weight:600;color:var(--ink);margin-bottom:2px;">Email</div>
<div style="font-size:11.5px;color:var(--muted);">Automated messages sent to your users — from welcome emails on day one to newsletters later</div>
</div>
<div class="opt-btns">
<button class="opt-btn selected" data-group="email" data-tip="Welcome emails, resets & marketing newsletters" onclick="selectOpt('email',this)">Full suite</button>
<button class="opt-btn" data-group="email" data-tip="Just transactional emails — resets and confirmations" onclick="selectOpt('email',this)">Essentials only</button>
</div>
</div>
<!-- Hosting — locked -->
<div class="blueprint-row locked">
<div style="width:32px;height:32px;border-radius:9px;background:#F3F4F6;display:flex;align-items:center;justify-content:center;font-size:15px;color:var(--muted);"></div>
<div>
<div style="font-size:13px;font-weight:600;color:var(--ink);margin-bottom:2px;">Hosting</div>
<div style="font-size:11.5px;color:var(--muted);">Where your product lives — on your own servers, so no one else controls your data or your costs</div>
</div>
<div class="opt-btns">
<button class="opt-btn selected" style="cursor:default;">Your servers 🔒</button>
<button class="opt-btn why-btn" onclick="openHostingWhy()" style="border-radius:0 7px 7px 0;border-right:none;color:#6366F1;font-weight:600;">Why?</button>
</div>
</div>
</div>
<!-- Reassurance note -->
<div style="display:flex;align-items:center;gap:10px;padding:11px 16px;background:#f0f4ff;border:1px solid #e0e7ff;border-radius:10px;">
<span style="font-size:16px;flex-shrink:0;">💬</span>
<p style="font-size:12px;color:var(--mid);line-height:1.55;margin:0;">Not sure about any of these? Don't worry — you can change them anytime before we start building.</p>
</div>
</div>
</div>
<!-- ── RIGHT PANEL ── -->
<div class="arch-right" style="width:384px;border-left:1px solid var(--border);background:#f5f3ff;display:flex;flex-direction:column;flex-shrink:0;">
<!-- Panel header — matches Describe PRD style -->
<div style="flex-shrink:0;padding:18px 0 0;">
<div style="margin:0 16px;padding-bottom:14px;border-bottom:1px solid #c7d2fe;">
<div style="font-size:15px;font-weight:800;letter-spacing:0.04em;text-transform:uppercase;color:#4338ca;margin-bottom:5px;">What your users will be able to do</div>
<div style="font-size:12px;color:var(--ink3);line-height:1.5;">10 screens covering the full user journey, ready to design.</div>
</div>
</div>
<!-- Scrollable content -->
<div class="arch-right-scroll" style="flex:1;overflow-y:auto;padding:16px;">
<!-- Pages -->
<div style="font-size:9.5px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--muted);margin-bottom:8px;">Pages</div>
<div style="background:var(--white);border:1px solid var(--border);border-radius:10px;overflow:hidden;margin-bottom:16px;">
<div style="padding:5px 12px;background:#fafaff;border-bottom:1px solid var(--border);">
<span style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);">Public</span>
</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Discover your product</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>See your pricing</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Learn about you</div>
<div style="padding:5px 12px;background:#fafaff;border-top:1px solid var(--border);border-bottom:1px solid var(--border);">
<span style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);">Auth</span>
</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Create an account</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Sign back in</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Reset their password</div>
<div style="padding:5px 12px;background:#fafaff;border-top:1px solid var(--border);border-bottom:1px solid var(--border);">
<span style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);">App</span>
</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Use the dashboard</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Manage their settings</div>
<div style="padding:5px 12px;background:#fafaff;border-top:1px solid var(--border);border-bottom:1px solid var(--border);">
<span style="font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);">Payments</span>
</div>
<div class="deliverable-row"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Subscribe and pay</div>
<div class="deliverable-row" style="border-bottom:none;"><div style="width:5px;height:5px;border-radius:50%;background:#10B981;flex-shrink:0;"></div>Manage their plan</div>
</div>
<!-- Infrastructure -->
<div style="font-size:9.5px;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:var(--muted);margin-bottom:8px;">Infrastructure</div>
<div style="background:var(--white);border:1px solid var(--border);border-radius:10px;overflow:hidden;">
<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;border-bottom:1px solid var(--border);">
<div style="width:28px;height:28px;border-radius:7px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0;">🖥</div>
<div><div style="font-size:12px;font-weight:600;color:var(--ink);">Your own servers</div><div style="font-size:11px;color:var(--muted);">No platform lock-in, ever</div></div>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;border-bottom:1px solid var(--border);">
<div style="width:28px;height:28px;border-radius:7px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0;">🔁</div>
<div><div style="font-size:12px;font-weight:600;color:var(--ink);">Auto-deploy via Coolify</div><div style="font-size:11px;color:var(--muted);">Every push goes live instantly</div></div>
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;">
<div style="width:28px;height:28px;border-radius:7px;background:var(--indigo-soft);display:flex;align-items:center;justify-content:center;font-size:13px;flex-shrink:0;">🔒</div>
<div><div style="font-size:12px;font-weight:600;color:var(--ink);">Code stored in Gitea</div><div style="font-size:11px;color:var(--muted);">Private repo, yours alone</div></div>
</div>
</div>
<!-- Timeline / cost signal -->
<div style="display:flex;align-items:center;justify-content:center;gap:16px;padding:10px 0 2px;">
<span style="font-size:11px;color:var(--muted);display:flex;align-items:center;gap:5px;"><span>~34 weeks to build</span></span>
<span style="font-size:11px;color:var(--muted);">·</span>
<span style="font-size:11px;color:var(--muted);display:flex;align-items:center;gap:5px;">💰 <span>No platform fees</span></span>
</div>
</div>
<!-- Footer -->
<div class="arch-right-footer" style="border-top:1px solid var(--border);padding:9px 0 13px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;">
<p style="font-size:11.5px;color:var(--muted);text-align:center;margin:0 0 10px;line-height:1.5;">All set — let's decide how it looks.</p>
<a href="07_design.html" style="text-decoration:none;display:block;width:80%;">
<button class="btn-primary" style="width:100%;padding:12px 14px;border-radius:8px;">Next: Design</button>
</a>
</div>
</div>
</div>
<!-- ── WHY POPUP ── -->
<div id="why-popup" style="display:none;position:fixed;inset:0;background:rgba(15,14,26,0.45);backdrop-filter:blur(2px);z-index:200;align-items:center;justify-content:center;padding:24px;" onclick="closeWhy()">
<div style="background:var(--white);border-radius:16px;width:100%;max-width:480px;box-shadow:0 24px 64px rgba(30,27,75,0.18);padding:32px;" onclick="event.stopPropagation()">
<div style="display:flex;align-items:center;gap:10px;margin-bottom:20px;">
<span style="font-size:20px;">💡</span>
<h3 style="font-size:17px;font-weight:700;color:var(--ink);letter-spacing:-0.02em;">Why we chose this for your product</h3>
</div>
<p style="font-size:13px;color:var(--mid);line-height:1.8;margin-bottom:12px;">Based on your idea, vibn picked a <strong style="color:var(--ink);font-weight:600;">web app with subscription billing</strong> — the fastest path to recurring revenue for a SaaS product.</p>
<p style="font-size:13px;color:var(--mid);line-height:1.8;margin-bottom:12px;"><strong style="color:var(--ink);font-weight:600;">Email + social login</strong> keeps sign-up friction low. Most people won't create a password for something they haven't tried yet — one click with Google removes that barrier.</p>
<p style="font-size:13px;color:var(--mid);line-height:1.8;margin-bottom:24px;"><strong style="color:var(--ink);font-weight:600;">Your own hosting</strong> means you own the infrastructure outright. No platform lock-in, no surprise price hikes. Coolify + Gitea are already configured to your account.</p>
<button onclick="closeWhy()" class="btn-primary" style="width:100%;padding:12px;">Got it</button>
</div>
</div>
<!-- ── SAVE POPUP ── -->
<div id="save-exit-popup">
<div id="save-exit-box">
<div class="save-icon"></div>
<h3>Your progress is saved.</h3>
<p>You can come back to this project anytime from your dashboard — everything will be exactly where you left it.</p>
<button onclick="window.location.href='03_dashboard.html'" style="width:100%;background:linear-gradient(135deg,#2e2a5e,#4338ca);color:#fff;border:none;border-radius:10px;padding:12px;font-family:'Plus Jakarta Sans',sans-serif;font-size:14px;font-weight:600;cursor:pointer;margin-bottom:10px;">Got it, go to dashboard</button>
<button class="save-cancel" onclick="cancelSaveExit()">Stay on this page</button>
</div>
</div>
<!-- ── MODAL ── -->
<div id="modal" class="modal-bg" onclick="closeModal()">
<div class="modal-card" onclick="event.stopPropagation()">
<div style="padding:18px 22px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;">
<span id="modal-title" class="f" style="font-size:15px;font-weight:700;color:var(--ink);"></span>
<button onclick="closeModal()" style="background:transparent;border:none;color:var(--muted);cursor:pointer;font-size:18px;line-height:1;">×</button>
</div>
<div style="padding:16px 22px;" id="modal-options"></div>
<div style="padding:10px 22px 18px;">
<button onclick="closeModal()" class="btn-primary" style="width:100%;padding:12px;border-radius:9px;">Got it</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function(){
try {
var name = localStorage.getItem('vibn_project_name') || 'My project';
var el = document.getElementById('sidebar-project-name');
el.textContent = name;
el.style.display = 'block';
var intro = document.getElementById('intro-project-name');
if(intro) intro.textContent = name;
} catch(e){}
// Init Blueprint tab on tablet + mobile
if(window.innerWidth <= 1024){
document.querySelector('.arch-main').classList.add('tab-active');
}
});
function switchArchTab(tab){
var main = document.querySelector('.arch-main');
var right = document.querySelector('.arch-right');
var btnBlueprint = document.getElementById('tab-blueprint');
var btnScope = document.getElementById('tab-scope');
if(tab === 'blueprint'){
main.classList.add('tab-active');
right.classList.remove('tab-active');
btnBlueprint.classList.add('active');
btnScope.classList.remove('active');
} else {
right.classList.add('tab-active');
main.classList.remove('tab-active');
btnScope.classList.add('active');
btnBlueprint.classList.remove('active');
}
}
function saveAndExit(){ document.getElementById('save-exit-popup').classList.add('visible'); }
function cancelSaveExit(){ document.getElementById('save-exit-popup').classList.remove('visible'); }
function openWhy(){ document.getElementById('why-popup').style.display='flex'; }
function closeWhy(){ document.getElementById('why-popup').style.display='none'; }
function selectOpt(group, el){
document.querySelectorAll('[data-group="'+group+'"]').forEach(function(b){ b.classList.remove('selected'); });
el.classList.add('selected');
}
function openHostingWhy(){
document.getElementById('modal-title').textContent = 'Why your own servers?';
document.getElementById('modal-options').innerHTML =
'<p style="font-size:13px;color:var(--mid);line-height:1.8;margin-bottom:12px;"><strong style="color:var(--ink)">Most platforms rent you server space</strong> — which means they control your data, your uptime, and your bill. The day they raise prices or shut down, your product goes with it.</p>' +
'<p style="font-size:13px;color:var(--mid);line-height:1.8;margin-bottom:12px;"><strong style="color:var(--ink)">With vibn, your product lives on your own servers.</strong> You own the infrastructure outright. Nobody can lock you out, hike your costs, or access your users\u2019 data without your permission.</p>' +
'<p style="font-size:13px;color:var(--mid);line-height:1.8;">We handle the hard part: <a href="https://coolify.io" target="_blank" style="color:var(--indigo);font-weight:600;text-decoration:none;">Coolify</a> auto-deploys your code every time you push an update, and <a href="https://gitea.com" target="_blank" style="color:var(--indigo);font-weight:600;text-decoration:none;">Gitea</a> stores your codebase securely. You get full control of your infrastructure \u2014 without needing to know how any of it works.</p>';
document.getElementById('modal').classList.add('open');
}
function openModal(title, opt1, desc1, opt2, desc2){
document.getElementById('modal-title').textContent = title;
document.getElementById('modal-options').innerHTML = '<p style="font-size:13px;color:var(--mid);line-height:1.6;">'+desc1+'</p>';
document.getElementById('modal').classList.add('open');
}
function closeModal(){ document.getElementById('modal').classList.remove('open'); }
function showTip(el){
hideTip();
var tip=document.createElement('div');
tip.id='vibn-tip';
tip.textContent=el.dataset.tip;
tip.style.cssText='position:fixed;background:linear-gradient(135deg,#2E2A5E,#4338CA);color:#fff;font-size:11px;font-weight:500;line-height:1.5;padding:6px 10px;border-radius:6px;white-space:nowrap;z-index:9999;pointer-events:none;box-shadow:0 4px 16px rgba(67,56,202,0.35);font-family:Plus Jakarta Sans,sans-serif;transition:opacity 0.1s;';
document.body.appendChild(tip);
var r=el.getBoundingClientRect();
tip.style.left=(r.left+r.width/2-tip.offsetWidth/2)+'px';
tip.style.top=(r.top-tip.offsetHeight-9)+'px';
var arrow=document.createElement('div');
arrow.id='vibn-tip-arrow';
arrow.style.cssText='position:fixed;border:5px solid transparent;border-top-color:#4338CA;z-index:9999;pointer-events:none;';
document.body.appendChild(arrow);
arrow.style.left=(r.left+r.width/2-5)+'px';
arrow.style.top=(r.top-9)+'px';
}
function hideTip(){
var t=document.getElementById('vibn-tip');
var a=document.getElementById('vibn-tip-arrow');
if(t)t.remove();
if(a)a.remove();
}
document.addEventListener('mouseover',function(e){var b=e.target.closest('.opt-btn[data-tip]');if(b)showTip(b);});
document.addEventListener('mouseout',function(e){var b=e.target.closest('.opt-btn[data-tip]');if(b)hideTip();});
function toggleTheme(){const html=document.documentElement;const isDark=html.dataset.theme==='dark';html.dataset.theme=isDark?'':'dark';document.getElementById('dark-toggle').textContent=isDark?'🌙 Dark mode':'☀️ Light mode';localStorage.setItem('vibn-theme',isDark?'':'dark');}
(function(){const saved=localStorage.getItem('vibn-theme');if(saved==='dark'){document.documentElement.dataset.theme='dark';document.addEventListener('DOMContentLoaded',function(){const btn=document.getElementById('dark-toggle');if(btn)btn.textContent='☀️ Light mode';});}})();
</script>
</body></html>