Files
sparkvault/public/index.html
T

972 lines
48 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" data-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SparkVault — Idea Tracker & Visual Mockup Studio</title>
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<link rel="stylesheet" href="/styles.css" />
</head>
<body>
<!-- TOP HEADER & QUICK CAPTURE BAR -->
<header class="topbar">
<div class="topbar-brand">
<div class="brand-logo" aria-hidden="true">⚡</div>
<div>
<div class="brand-title-row">
<h1 class="brand-title">SparkVault</h1>
<span class="brand-badge">Idea Studio</span>
</div>
<p class="brand-subtitle">Capture sparks, attach inspirations, and generate product & apparel mockups</p>
</div>
</div>
<!-- Instant Quick Capture Command Bar -->
<form id="quick-capture-form" class="quick-capture-bar" autocomplete="off">
<span class="qc-icon" title="Quick Capture (Ctrl+K)">✨</span>
<input
id="quick-capture-input"
type="text"
placeholder="Quick capture an idea... e.g. Retro Ski Club Tee @creative #tshirt !high (Ctrl+K)"
aria-label="Quick capture idea"
/>
<select id="quick-capture-category" aria-label="Idea category">
<option value="spark">⚡ Spark</option>
<option value="creative">🎨 Creative / Merch</option>
<option value="project">🛠️ Project / App</option>
<option value="research">🔬 Research</option>
</select>
<button type="submit" class="btn btn-primary btn-sm">Capture</button>
<button
type="button"
id="btn-generate-random-idea"
class="btn btn-secondary btn-sm"
title="Generate a personalized random idea tailored to your background"
>
🎲 Random Idea
</button>
<button
type="button"
id="btn-open-external-clip"
class="btn btn-ghost btn-sm"
title="Attach external notes, clipboard screenshots, photos, or image URLs to a spark"
>
📎 Clip / Attach
</button>
</form>
<div class="topbar-actions">
<button type="button" id="btn-open-settings" class="btn btn-ghost btn-sm" title="Configure AI Generator & Personal Background">
⚙️ <span id="api-key-status-dot" class="status-dot"></span> AI Settings
</button>
<div class="dropdown">
<button type="button" id="btn-export-menu" class="btn btn-ghost btn-sm">⬇️ Export</button>
<div id="export-dropdown-menu" class="dropdown-menu hidden">
<a href="/api/export?format=json" download="sparkvault-ideas.json" class="dropdown-item">📦 Export JSON Vault</a>
<a href="/api/export?format=markdown" download="sparkvault-ideas.md" class="dropdown-item">📝 Export Markdown Book</a>
</div>
</div>
<button type="button" id="btn-theme-toggle" class="btn btn-ghost btn-sm" title="Switch Dark / Warm Paper Theme">
☀️ Theme
</button>
</div>
</header>
<!-- OPTIONAL QUICK WHACK SPARK BANNER -->
<section id="quick-whack-banner" class="whack-prompt-banner hidden" aria-live="polite">
<div class="whack-banner-inner">
<img id="qwb-card-img" src="" alt="Whack Card" class="qwb-thumb" />
<div class="qwb-content">
<div class="qwb-meta">
<span id="qwb-suit-badge" class="suit-pill">Explorer</span>
<strong id="qwb-card-title">Card #1</strong>
</div>
<p id="qwb-card-question" class="qwb-question"></p>
</div>
<div class="qwb-actions">
<button type="button" id="btn-qwb-use" class="btn btn-primary btn-sm">✨ Create Idea from Card</button>
<button type="button" id="btn-qwb-redraw" class="btn btn-ghost btn-sm">🔄 Draw Another</button>
<button type="button" id="btn-qwb-close" class="btn btn-ghost btn-sm">✕</button>
</div>
</div>
</section>
<!-- NAVIGATION & STATS STRIP -->
<nav class="subnav">
<div class="subnav-top-row">
<div class="view-tabs" role="tablist">
<button type="button" class="view-tab active" data-view="board" role="tab">
📋 Pipeline
</button>
<button type="button" class="view-tab" data-view="grid" role="tab">
🗂️ Explorer
</button>
<button type="button" class="view-tab" data-view="review" role="tab">
⚔️ Arena & Triage
</button>
<button type="button" class="view-tab view-tab-subtle" data-view="whack" role="tab" title="Creative Prompts & Whack Pack Deck">
💡 Prompts
</button>
</div>
<button type="button" id="btn-mobile-filter-toggle" class="btn btn-ghost btn-sm mobile-only">
🔍 Filters
</button>
</div>
<div class="filter-bar" id="global-filter-bar">
<input
type="search"
id="filter-search"
class="filter-input"
placeholder="Search ideas, notes, #tags..."
/>
<select id="filter-category" class="filter-select" aria-label="Filter by category">
<option value="all">All Categories</option>
<option value="creative">🎨 Creative / Merch</option>
<option value="project">🛠️ Project / Product</option>
<option value="spark">⚡ Quick Spark</option>
<option value="research">🔬 Research</option>
</select>
<select id="filter-tag" class="filter-select" aria-label="Filter by tag">
<option value="all">All #Tags</option>
</select>
<label class="filter-checkbox">
<input type="checkbox" id="filter-has-mockup" />
<span>🖼️ Has Mockup (<span id="stat-mockups-count">0</span>)</span>
</label>
<select id="filter-sort" class="filter-select" aria-label="Sort ideas">
<option value="score">Sort: Priority Score</option>
<option value="excitement">Sort: Excitement</option>
<option value="arena">Sort: Arena Wins</option>
<option value="updated">Sort: Recently Updated</option>
<option value="newest">Sort: Newest First</option>
</select>
<button type="button" id="btn-clear-filters" class="btn btn-ghost btn-sm hidden" title="Clear active filters">
✕ Reset
</button>
</div>
</nav>
<!-- MAIN WORKSPACE -->
<main class="workspace">
<!-- VIEW 1: PIPELINE KANBAN BOARD -->
<section id="view-board" class="view-section active">
<!-- Mobile Stage Switcher Pills -->
<div class="mobile-stage-switcher mobile-only" id="mobile-stage-switcher">
<button type="button" class="stage-tab active" data-mobile-stage="spark">
✨ Spark <span class="stage-tab-count" id="mcount-spark">0</span>
</button>
<button type="button" class="stage-tab" data-mobile-stage="exploring">
🔍 Exploring <span class="stage-tab-count" id="mcount-exploring">0</span>
</button>
<button type="button" class="stage-tab" data-mobile-stage="building">
🛠️ Building <span class="stage-tab-count" id="mcount-building">0</span>
</button>
<button type="button" class="stage-tab" data-mobile-stage="shipped">
🚀 Shipped <span class="stage-tab-count" id="mcount-shipped">0</span>
</button>
<button type="button" class="stage-tab" data-mobile-stage="archived">
📦 Archived <span class="stage-tab-count" id="mcount-archived">0</span>
</button>
<button type="button" class="stage-tab" data-mobile-stage="all">
All
</button>
</div>
<div class="kanban-board" id="kanban-board" data-mobile-active-stage="spark">
<div class="kanban-column" data-status="spark">
<div class="kanban-col-header">
<div>
<span class="status-dot status-spark"></span>
<h2>✨ Spark</h2>
<span class="role-hint">Raw Ideas</span>
</div>
<span class="col-count" id="count-spark">0</span>
</div>
<div class="kanban-dropzone" data-status="spark" id="col-spark"></div>
</div>
<div class="kanban-column" data-status="exploring">
<div class="kanban-col-header">
<div>
<span class="status-dot status-exploring"></span>
<h2>🔍 Exploring</h2>
<span class="role-hint">Research & Mockups</span>
</div>
<span class="col-count" id="count-exploring">0</span>
</div>
<div class="kanban-dropzone" data-status="exploring" id="col-exploring"></div>
</div>
<div class="kanban-column" data-status="building">
<div class="kanban-col-header">
<div>
<span class="status-dot status-building"></span>
<h2>🛠️ Building</h2>
<span class="role-hint">In Progress</span>
</div>
<span class="col-count" id="count-building">0</span>
</div>
<div class="kanban-dropzone" data-status="building" id="col-building"></div>
</div>
<div class="kanban-column" data-status="shipped">
<div class="kanban-col-header">
<div>
<span class="status-dot status-shipped"></span>
<h2>🚀 Shipped</h2>
<span class="role-hint">Launched</span>
</div>
<span class="col-count" id="count-shipped">0</span>
</div>
<div class="kanban-dropzone" data-status="shipped" id="col-shipped"></div>
</div>
<div class="kanban-column" data-status="archived">
<div class="kanban-col-header">
<div>
<span class="status-dot status-archived"></span>
<h2>📦 Archived</h2>
<span class="role-hint">Parked Vault</span>
</div>
<span class="col-count" id="count-archived">0</span>
</div>
<div class="kanban-dropzone" data-status="archived" id="col-archived"></div>
</div>
</div>
</section>
<!-- VIEW 2: EXPLORER GRID & MOCKUP GALLERY -->
<section id="view-grid" class="view-section hidden">
<div class="grid-toolbar">
<div class="status-pills" id="grid-status-pills">
<button type="button" class="pill-btn active" data-status="all">All Stages</button>
<button type="button" class="pill-btn" data-status="spark">✨ Spark</button>
<button type="button" class="pill-btn" data-status="exploring">🔍 Exploring</button>
<button type="button" class="pill-btn" data-status="building">🛠️ Building</button>
<button type="button" class="pill-btn" data-status="shipped">🚀 Shipped</button>
<button type="button" class="pill-btn" data-status="archived">📦 Archived</button>
</div>
<button type="button" id="btn-new-idea-modal" class="btn btn-primary btn-sm">+ New Detailed Idea</button>
</div>
<div id="explorer-grid" class="explorer-grid"></div>
</section>
<!-- VIEW 3: CREATIVE WHACK PACK STUDIO (64 CARDS) -->
<section id="view-whack" class="view-section hidden">
<div class="whack-studio-header">
<div>
<h2>🃏 Creative Whack Pack Catalyst Studio</h2>
<p>64 lateral-thinking strategies by Roger von Oech across 4 creative roles: <strong>🧭 Explorer (1–16)</strong>, <strong>🎨 Artist (17–32)</strong>, <strong>⚖️ Judge (33–48)</strong>, and <strong>⚔️ Warrior (49–64)</strong>.</p>
</div>
<div class="whack-mode-tabs">
<button type="button" class="pill-btn active" data-whack-mode="collider">⚡ Idea Collider (Card + Idea)</button>
<button type="button" class="pill-btn" data-whack-mode="spread">🎴 4-Role Creative Spread</button>
<button type="button" class="pill-btn" data-whack-mode="browser">📚 Browse All 64 Cards</button>
</div>
</div>
<!-- SUB-MODE A: IDEA COLLIDER -->
<div id="whack-submode-collider" class="whack-submode">
<div class="collider-controls">
<div class="collider-control-group">
<label for="collider-suit-select">Filter Suit:</label>
<select id="collider-suit-select" class="filter-select">
<option value="">Stage-Matched / Any Suit</option>
<option value="explorer">🧭 Explorer (1–16: Gather & Discover)</option>
<option value="artist">🎨 Artist (17–32: Play & Transform)</option>
<option value="judge">⚖️ Judge (33–48: Evaluate & Test)</option>
<option value="warrior">⚔️ Warrior (49–64: Act & Ship)</option>
</select>
</div>
<div class="collider-control-group">
<label for="collider-idea-select">Target Idea:</label>
<select id="collider-idea-select" class="filter-select"></select>
</div>
<button type="button" id="btn-deal-collider" class="btn btn-primary">
🎲 Collide Card + Idea
</button>
<button type="button" id="btn-collider-random-both" class="btn btn-ghost">
🔀 Random Card & Random Spark
</button>
</div>
<div id="collider-stage" class="collider-stage"></div>
</div>
<!-- SUB-MODE B: 4-ROLE SPREAD -->
<div id="whack-submode-spread" class="whack-submode hidden">
<div class="spread-bar">
<p>Deal one card from each role (<strong>Explorer → Artist → Judge → Warrior</strong>) to walk an idea from raw spark to shipped execution.</p>
<button type="button" id="btn-deal-spread" class="btn btn-primary">🎴 Deal Fresh 4-Role Spread</button>
</div>
<div id="spread-grid" class="spread-grid"></div>
</div>
<!-- SUB-MODE C: 64-CARD DECK BROWSER -->
<div id="whack-submode-browser" class="whack-submode hidden">
<div class="deck-filter-bar">
<div class="suit-filter-buttons" id="deck-suit-filters">
<button type="button" class="pill-btn active" data-suit="all">All 64 Cards</button>
<button type="button" class="pill-btn suit-explorer-btn" data-suit="explorer">🧭 Explorer (1–16)</button>
<button type="button" class="pill-btn suit-artist-btn" data-suit="artist">🎨 Artist (17–32)</button>
<button type="button" class="pill-btn suit-judge-btn" data-suit="judge">⚖️ Judge (33–48)</button>
<button type="button" class="pill-btn suit-warrior-btn" data-suit="warrior">⚔️ Warrior (49–64)</button>
</div>
<input type="search" id="deck-search-input" class="filter-input" placeholder="Search 64 cards by title, number, or prompt..." />
</div>
<div id="deck-cards-grid" class="deck-cards-grid"></div>
</div>
</section>
<!-- VIEW 4: REVIEW & HEAD-TO-HEAD ARENA -->
<section id="view-review" class="view-section hidden">
<div class="review-header">
<div>
<h2>⚔️ Idea Resurfacing & Prioritization Studio</h2>
<p>Prevent the idea graveyard: pit ideas head-to-head to find what excites you most, or triage older sparks one card at a time.</p>
</div>
<div class="review-mode-tabs">
<button type="button" class="pill-btn active" data-review-mode="arena">⚔️ Head-to-Head Arena</button>
<button type="button" class="pill-btn" data-review-mode="triage">🃏 Stale Spark Triage Deck</button>
</div>
</div>
<div id="review-submode-arena" class="review-submode">
<div class="arena-instructions">
<span>Which idea excites you more to work on or prototype next?</span>
<button type="button" id="btn-skip-arena" class="btn btn-ghost btn-sm">🔀 Skip / Deal New Pair</button>
</div>
<div id="arena-stage" class="arena-stage"></div>
</div>
<div id="review-submode-triage" class="review-submode hidden">
<div id="triage-stage" class="triage-stage"></div>
</div>
</section>
</main>
<!-- SLIDE-OVER RICH IDEA WORKBENCH & NANO BANANA MOCKUP STUDIO -->
<div id="drawer-backdrop" class="drawer-backdrop hidden"></div>
<aside id="idea-drawer" class="idea-drawer hidden" aria-label="Idea Workbench">
<div class="drawer-header">
<div class="drawer-title-group">
<div class="drawer-title-row">
<input type="text" id="drawer-title-input" class="drawer-title-input" placeholder="Idea Title" />
<button type="button" id="btn-suggest-names" class="btn btn-secondary btn-xs" title="Brainstorm 6 creative names & taglines for this idea">
✨ Suggest Names
</button>
</div>
<div id="drawer-name-suggestions-panel" class="name-suggestions-panel hidden"></div>
<div class="drawer-meta-row">
<select id="drawer-status-select" class="drawer-select">
<option value="spark">✨ Spark</option>
<option value="exploring">🔍 Exploring</option>
<option value="building">🛠️ Building</option>
<option value="shipped">🚀 Shipped</option>
<option value="archived">📦 Archived</option>
</select>
<select id="drawer-category-select" class="drawer-select">
<option value="creative">🎨 Creative / Merch</option>
<option value="project">🛠️ Project / Product</option>
<option value="spark">⚡ Quick Spark</option>
<option value="research">🔬 Research</option>
</select>
<button type="button" id="drawer-pin-btn" class="btn btn-ghost btn-sm" title="Pin Idea">📌 Pin</button>
<span id="drawer-score-badge" class="score-badge">Score: 75</span>
</div>
</div>
<div class="drawer-header-actions">
<button type="button" id="btn-open-dev-handoff" class="btn btn-primary btn-sm" title="Submit all Spark info, specs, and mockups to Antigravity or OpenAI Codex for development">
🚀 Send to Dev
</button>
<button type="button" id="drawer-delete-btn" class="btn btn-danger-ghost btn-sm" title="Delete Idea">🗑️</button>
<button type="button" id="drawer-close-btn" class="btn btn-ghost btn-sm" title="Close (Esc)">✕ Close</button>
</div>
</div>
<!-- DRAWER SUB-TABS -->
<div class="drawer-tabs">
<button type="button" class="drawer-tab active" data-drawer-tab="details">
📝 Workbench & Notes
</button>
<button type="button" class="drawer-tab" data-drawer-tab="mockup">
🖼️ Image Mockup Studio <span id="drawer-mockup-count" class="tab-pill">0</span>
</button>
<button type="button" class="drawer-tab" data-drawer-tab="whack">
💡 Brainstorm Prompts <span id="drawer-whack-count" class="tab-pill">0</span>
</button>
</div>
<div class="drawer-body">
<!-- TAB 1: DETAILS, NOTES, CHECKLIST, PROS/CONS, RATINGS -->
<div id="drawer-tab-details" class="drawer-tab-panel active">
<!-- Main Spark Cover Thumbnail & Elevator Pitch Hero -->
<div class="spark-main-hero">
<div id="drawer-main-thumb-box" class="spark-main-thumb-box"></div>
<div class="spark-main-pitch-col">
<div class="field-group">
<label for="drawer-pitch-input">Elevator Pitch (One-sentence essence)</label>
<input type="text" id="drawer-pitch-input" class="text-input" placeholder="What makes this idea compelling in one sentence?" />
</div>
<!-- Markdown Notes -->
<div class="field-group">
<div class="field-header-row">
<label for="drawer-notes-input">Specs, Brainstorm & Markdown Notes</label>
<button type="button" id="btn-toggle-md-preview" class="btn btn-ghost btn-xs">👁️ Toggle Preview</button>
</div>
<textarea id="drawer-notes-input" rows="6" class="textarea-input" placeholder="Write specs, architecture notes, concept details, or markdown lists..."></textarea>
<div id="drawer-notes-preview" class="markdown-preview hidden"></div>
</div>
</div>
</div>
<!-- Action Checklist -->
<div class="field-group">
<div class="field-header-row">
<label>Action Checklist</label>
<span id="drawer-checklist-progress" class="muted-label">0/0 completed</span>
</div>
<div id="drawer-checklist-items" class="checklist-container"></div>
<form id="drawer-add-checklist-form" class="inline-add-form">
<input type="text" id="drawer-new-checklist-input" class="text-input input-sm" placeholder="Add next concrete step..." />
<button type="submit" class="btn btn-secondary btn-sm">+ Add Step</button>
</form>
</div>
<!-- Pros & Cons Matrix -->
<div class="pros-cons-grid">
<div class="field-group">
<label>✅ Pros / Why It Works</label>
<ul id="drawer-pros-list" class="bullet-list pros-list"></ul>
<form id="drawer-add-pro-form" class="inline-add-form">
<input type="text" id="drawer-new-pro-input" class="text-input input-sm" placeholder="Add a pro..." />
<button type="submit" class="btn btn-ghost btn-sm">+</button>
</form>
</div>
<div class="field-group">
<label>⚠️ Cons / Risks & Constraints</label>
<ul id="drawer-cons-list" class="bullet-list cons-list"></ul>
<form id="drawer-add-con-form" class="inline-add-form">
<input type="text" id="drawer-new-con-input" class="text-input input-sm" placeholder="Add a risk or constraint..." />
<button type="submit" class="btn btn-ghost btn-sm">+</button>
</form>
</div>
</div>
<!-- External Attachments: Clipped Notes, Screenshots & Reference Images -->
<div class="field-group">
<div class="field-header-row">
<label>📎 Attached External Notes & Reference Images (<span id="drawer-attachments-count">0</span>)</label>
<span class="muted-label">Paste (Ctrl+V), drop files, or clip from URL</span>
</div>
<div id="drawer-attachment-dropzone" class="attachment-dropzone">
<div class="dropzone-header">
<span>📥 <strong>Drop image here</strong>, press <kbd>Ctrl+V</kbd> to paste a screenshot, or attach a note/URL below:</span>
<label class="btn btn-secondary btn-xs" style="cursor:pointer;">
📷 Choose Image / Camera
<input type="file" id="drawer-attach-file-input" accept="image/*" hidden />
</label>
</div>
<div id="drawer-attach-preview-row" class="attach-preview-row hidden">
<img id="drawer-attach-preview-img" src="" alt="Staged attachment" />
<div style="flex:1;">
<strong style="font-size:0.82rem;">Staged Image Ready to Attach</strong>
<p class="muted-label">Add an optional caption or note below and click Attach.</p>
</div>
<button type="button" id="btn-drawer-clear-staged-img" class="btn btn-ghost btn-xs">✕ Remove</button>
</div>
<div class="form-row-2">
<input type="text" id="drawer-attach-title" class="text-input input-sm" placeholder="Title / Caption (e.g. Concept Sketch Ref)" />
<input type="url" id="drawer-attach-url" class="text-input input-sm" placeholder="External Image URL or Source Link (https://...)" />
</div>
<textarea id="drawer-attach-text" rows="2" class="textarea-input" placeholder="Paste external note, quote, spec snippet, or commentary..."></textarea>
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:0.5rem;">
<div style="display:flex;gap:0.85rem;flex-wrap:wrap;">
<label class="filter-checkbox">
<input type="checkbox" id="drawer-attach-append-notes" />
<span>Also append text to Markdown Notes</span>
</label>
<label class="filter-checkbox">
<input type="checkbox" id="drawer-attach-set-cover" />
<span>Set image as Spark Cover</span>
</label>
</div>
<button type="button" id="btn-drawer-save-attachment" class="btn btn-primary btn-sm">
📎 Attach to Spark
</button>
</div>
</div>
<div id="drawer-attachments-list" class="attachments-grid"></div>
</div>
<!-- Reference Links -->
<div class="field-group">
<label>🔗 Reference Links & Inspiration</label>
<div id="drawer-links-list" class="links-list"></div>
<form id="drawer-add-link-form" class="inline-add-form">
<input type="text" id="drawer-link-title" class="text-input input-sm" placeholder="Label (e.g. Spec Doc)" />
<input type="url" id="drawer-link-url" class="text-input input-sm" placeholder="https://..." />
<button type="submit" class="btn btn-ghost btn-sm">+ Add Link</button>
</form>
</div>
<!-- Tags (Moved down the page) -->
<div class="field-group">
<label>Tags</label>
<div class="tags-editor">
<div id="drawer-tags-list" class="tags-list"></div>
<form id="drawer-add-tag-form" class="inline-add-form">
<input type="text" id="drawer-new-tag-input" class="text-input input-sm" placeholder="Add #tag..." />
<button type="submit" class="btn btn-ghost btn-sm">+ Add</button>
</form>
</div>
</div>
<!-- Prioritization Sliders (Moved down the page) -->
<div class="field-group">
<label>Prioritization Ratings</label>
<div class="ratings-card">
<div class="rating-control">
<label for="slider-excitement">🔥 Excitement: <strong id="val-excitement">3</strong>/5</label>
<input type="range" id="slider-excitement" min="1" max="5" step="1" value="3" />
</div>
<div class="rating-control">
<label for="slider-impact">🎯 Impact: <strong id="val-impact">3</strong>/5</label>
<input type="range" id="slider-impact" min="1" max="5" step="1" value="3" />
</div>
<div class="rating-control">
<label for="slider-ease">⚡ Ease / Feasibility: <strong id="val-ease">3</strong>/5</label>
<input type="range" id="slider-ease" min="1" max="5" step="1" value="3" />
</div>
</div>
</div>
</div>
<!-- TAB 2: IMAGE MOCKUP STUDIO -->
<div id="drawer-tab-mockup" class="drawer-tab-panel hidden">
<div class="mockup-studio-layout">
<!-- Left: Generator & Interactive T-Shirt / Product Compositor -->
<div class="mockup-controls-pane">
<div class="studio-card">
<div class="studio-card-header">
<h3>🖼️ Image Mockup Studio</h3>
<button type="button" id="btn-studio-auto-prompt" class="btn btn-ghost btn-xs">✨ Auto-Prompt from Idea</button>
</div>
<div class="field-group">
<label for="nb-generator-select">AI Image Generator Engine</label>
<select id="nb-generator-select" class="filter-select full-width">
<option value="codex-image-gen">🤖 OpenAI Codex (gpt-5.6-sol / Built-in image_gen) — High-Res PNG</option>
<option value="gemini-nano-banana-2.1">✨ Google Gemini (Nano Banana 2.1 / Flash-Lite Vector Fallback)</option>
<option value="gemini-3-pro-image">🎨 Google Gemini Pro Image (Studio Detail)</option>
<option value="gemini-3.1-flash-lite-image">⚡ Google Gemini Flash-Lite Image (Fast Sketch)</option>
</select>
</div>
<div class="form-row-2">
<div>
<label for="nb-template-select">Product / Surface Preset</label>
<select id="nb-template-select" class="filter-select full-width">
<option value="tshirt-front">👕 T-Shirt (Full-Front Graphic)</option>
<option value="tshirt-left-chest">👕 T-Shirt (5-in Left-Chest Emblem)</option>
<option value="isolated-graphic">🎨 Isolated Screenprint Vector Artwork</option>
<option value="sticker">🏷️ Die-Cut Vinyl Sticker / Patch</option>
<option value="poster">🖼️ Framed Art Poster</option>
<option value="app-ui">💻 Product / App Interface</option>
</select>
</div>
<div>
<label for="nb-whack-twist-select">Optional Prompt Twist</label>
<select id="nb-whack-twist-select" class="filter-select full-width">
<option value="">None (Direct Concept)</option>
</select>
</div>
</div>
<!-- Garment / Surface Color Swatches (Only shown when product is a T-Shirt) -->
<div id="nb-garment-color-group" class="field-group hidden">
<label>T-Shirt Garment Color: <strong id="nb-selected-color-label">Vintage Cream (#F5E8D3)</strong></label>
<div class="color-swatch-row" id="nb-color-swatches">
<button type="button" class="color-swatch active" data-color="#F5E8D3" data-name="Vintage Cream" style="background:#F5E8D3" title="Vintage Cream (#F5E8D3)"></button>
<button type="button" class="color-swatch" data-color="#1C1B1A" data-name="Vintage Black" style="background:#1C1B1A" title="Vintage Black (#1C1B1A)"></button>
<button type="button" class="color-swatch" data-color="#1B2A4A" data-name="Midnight Navy" style="background:#1B2A4A" title="Midnight Navy (#1B2A4A)"></button>
<button type="button" class="color-swatch" data-color="#1E3F2B" data-name="Forest Pine" style="background:#1E3F2B" title="Forest Pine (#1E3F2B)"></button>
<button type="button" class="color-swatch" data-color="#A8422B" data-name="Terracotta Rust" style="background:#A8422B" title="Terracotta Rust (#A8422B)"></button>
<button type="button" class="color-swatch" data-color="#C8C9CC" data-name="Heather Grey" style="background:#C8C9CC" title="Heather Grey (#C8C9CC)"></button>
<button type="button" class="color-swatch" data-color="#FFFFFF" data-name="Crisp White" style="background:#FFFFFF" title="Crisp White (#FFFFFF)"></button>
</div>
</div>
<div class="field-group">
<label for="nb-prompt-input">Visual Description / Artwork Prompt</label>
<textarea id="nb-prompt-input" rows="3" class="textarea-input" placeholder="Describe the visual concept, product UI, illustration, or mockup scene..."></textarea>
</div>
<!-- Iterative Image-to-Image Edit Banner (Active when a mockup is selected for refinement) -->
<div id="nb-edit-mode-box" class="nb-edit-box hidden">
<div class="nb-edit-header">
<span>✨ <strong>Iterative Edit Mode:</strong> Refining <em id="nb-edit-target-label">Selected Mockup</em></span>
<button type="button" id="btn-nb-clear-edit" class="btn btn-ghost btn-xs">Cancel Edit Mode</button>
</div>
<input
type="text"
id="nb-edit-instruction-input"
class="text-input"
placeholder="Describe what to change (e.g. 'Switch to dark mode layout' or 'Use bolder vintage typography')"
/>
</div>
<div class="studio-action-row">
<button type="button" id="btn-generate-nano-banana" class="btn btn-primary">
🖼️ Generate Image Mockup
</button>
<span id="nb-generation-status" class="muted-label"></span>
</div>
</div>
<!-- Interactive T-Shirt & Emblem Compositor (Only shown when product is a T-Shirt) -->
<div id="tshirt-compositor-card" class="studio-card hidden">
<div class="studio-card-header">
<h3>👕 Interactive T-Shirt & Emblem Compositor</h3>
<span class="muted-label">Instant apparel layout & print proof</span>
</div>
<div class="form-row-3">
<div>
<label for="comp-surface-select">Mockup Surface</label>
<select id="comp-surface-select" class="filter-select full-width">
<option value="tshirt">👕 Crewneck T-Shirt</option>
<option value="sticker">🏷️ Die-Cut Sticker / Badge</option>
<option value="poster">🖼️ Framed Print</option>
</select>
</div>
<div>
<label for="comp-placement-select">Print Placement</label>
<select id="comp-placement-select" class="filter-select full-width">
<option value="center-chest">Full Center Chest</option>
<option value="left-chest">5-inch Left-Chest Pocket</option>
<option value="oversized">Oversized Vintage Front</option>
</select>
</div>
<div>
<label for="comp-emblem-select">Vector Emblem</label>
<select id="comp-emblem-select" class="filter-select full-width">
<option value="mountains">🏔️ Mountain & Sun</option>
<option value="espresso">☕ Espresso Cup</option>
<option value="lightbulb">💡 Lightbulb Boxer</option>
<option value="compass">🧭 Explorer Compass</option>
<option value="lightning">⚡ Spark Bolt</option>
<option value="none">No Icon (Text/Image Only)</option>
</select>
</div>
</div>
<div class="form-row-2">
<div>
<div class="field-header-row">
<label for="comp-top-text">Top Headline / Club Name</label>
<button type="button" id="btn-comp-suggest-names" class="btn btn-ghost btn-xs">✨ Suggest Names</button>
</div>
<input type="text" id="comp-top-text" class="text-input input-sm" placeholder="HIGH ALTITUDE CLUB" />
</div>
<div>
<label for="comp-bottom-text">Bottom Tagline / Est.</label>
<input type="text" id="comp-bottom-text" class="text-input input-sm" placeholder="EST. 1984 • COLORADO" />
</div>
</div>
<div class="form-row-2">
<div>
<label for="comp-ink-color">Primary Screenprint Ink</label>
<input type="color" id="comp-ink-color" value="#BC4921" class="color-picker-input" />
</div>
<div>
<label for="comp-upload-art">Overlay Custom PNG/JPG Graphic</label>
<input type="file" id="comp-upload-art" accept="image/*" class="file-input" />
</div>
</div>
<div class="canvas-preview-wrapper">
<canvas id="mockup-compositor-canvas" width="680" height="680"></canvas>
</div>
<div class="studio-action-row">
<button type="button" id="btn-save-canvas-mockup" class="btn btn-secondary">
📸 Save Canvas Mockup to Idea
</button>
<button type="button" id="btn-download-canvas-png" class="btn btn-ghost btn-sm">
⬇️ Download PNG
</button>
<button type="button" id="btn-clear-uploaded-art" class="btn btn-ghost btn-sm">
Clear Overlay Image
</button>
</div>
</div>
</div>
<!-- Right: Saved Mockup Gallery for this Idea -->
<div class="mockup-gallery-pane">
<div class="studio-card">
<div class="studio-card-header">
<h3>🖼️ Idea Mockup Gallery</h3>
<span class="muted-label">Click '✨ Refine' to iterate on any mockup</span>
</div>
<div id="drawer-mockup-gallery" class="drawer-mockup-gallery"></div>
</div>
</div>
</div>
</div>
<!-- TAB 3: WHACK THIS IDEA -->
<div id="drawer-tab-whack" class="drawer-tab-panel hidden">
<div class="drawer-whack-controls">
<div>
<h3>🃏 Give This Idea a Creative Whack</h3>
<p class="muted-label">Draw a stage-matched card from your 64-card deck to challenge assumptions or spark a new visual direction.</p>
</div>
<div class="drawer-whack-actions">
<select id="drawer-whack-suit-select" class="filter-select">
<option value="">Stage-Matched Suit (Recommended)</option>
<option value="explorer">🧭 Explorer (1–16)</option>
<option value="artist">🎨 Artist (17–32)</option>
<option value="judge">⚖️ Judge (33–48)</option>
<option value="warrior">⚔️ Warrior (49–64)</option>
</select>
<button type="button" id="btn-drawer-draw-whack" class="btn btn-primary btn-sm">
🃏 Draw Whack Card
</button>
</div>
</div>
<div id="drawer-active-whack-stage" class="drawer-whack-stage"></div>
<div class="field-group">
<h4>📜 Whack Breakthrough Log for This Idea</h4>
<div id="drawer-whack-history-list" class="whack-history-list"></div>
</div>
</div>
</div>
</aside>
<!-- MODAL: AI GENERATOR & PROFILE SETTINGS -->
<div id="settings-modal" class="modal-backdrop hidden">
<div class="modal-card">
<div class="modal-header">
<h3>⚙️ AI Mockup Generator & Profile Settings</h3>
<button type="button" id="btn-close-settings" class="btn btn-ghost btn-sm">✕</button>
</div>
<form id="settings-form" class="modal-body">
<p class="muted-label">
Choose which AI generator powers the <strong>Image Mockup Studio</strong> (you can also switch generators anytime directly inside the Studio tab).
</p>
<div class="field-group">
<label for="settings-model-select">Default Image Mockup Generator</label>
<select id="settings-model-select" class="filter-select full-width">
<option value="codex-image-gen">🤖 OpenAI Codex (gpt-5.6-sol + Built-in image_gen) [Recommended]</option>
<option value="gemini-nano-banana-2.1">✨ Google Gemini (Nano Banana 2.1 / Flash-Lite Vector Fallback)</option>
<option value="gemini-3-pro-image">🎨 Google Gemini Pro Image (High-Detail Studio)</option>
<option value="gemini-3.1-flash-lite-image">⚡ Google Gemini Flash-Lite Image (Fast Sketch)</option>
</select>
</div>
<div class="field-group">
<label for="settings-api-key">Optional Google Gemini API Key (`GEMINI_API_KEY`)</label>
<input
type="password"
id="settings-api-key"
class="text-input"
placeholder="Only needed if using Google Gemini models (AIza...)"
autocomplete="off"
/>
<small id="settings-key-status" class="muted-label"></small>
</div>
<div class="field-group">
<label for="settings-user-background">🎲 Personal Background & Tastes (Used by '🎲 Random Idea')</label>
<textarea
id="settings-user-background"
rows="5"
class="textarea-input"
placeholder="Describe your interests, aesthetic tastes, homelab stack, apparel preferences..."
></textarea>
<small class="muted-label">When you click <strong>🎲 Random Idea</strong>, SparkVault combines this profile with a random Creative Whack Pack card to invent a tailored idea.</small>
</div>
<div class="modal-footer">
<button type="button" id="btn-cancel-settings" class="btn btn-ghost">Cancel</button>
<button type="submit" class="btn btn-primary">Save Settings</button>
</div>
</form>
</div>
</div>
<!-- MODAL: EXTERNAL CLIPPER / ATTACH TO SPARK -->
<div id="external-clip-modal" class="modal-backdrop hidden">
<div class="modal-card" style="max-width:600px;">
<div class="modal-header">
<h3>📎 Attach External Note or Image to Spark</h3>
<button type="button" id="btn-close-clip-modal" class="btn btn-ghost btn-sm">✕</button>
</div>
<form id="external-clip-form" class="modal-body">
<p class="muted-label">
Clip a screenshot (<kbd>Ctrl+V</kbd> anywhere in this dialog), upload a photo from your phone, fetch an external image URL, or attach notes/links to an existing Spark (or create a new one).
</p>
<div class="field-group">
<label for="clip-target-idea">Target Spark / Idea</label>
<select id="clip-target-idea" class="filter-select full-width"></select>
</div>
<div id="clip-new-idea-group" class="field-group hidden">
<label for="clip-new-idea-title">New Spark Title</label>
<input type="text" id="clip-new-idea-title" class="text-input" placeholder="e.g. Vintage Campfire Enamel Mug #merch @creative" />
</div>
<div class="field-group">
<label for="clip-title-input">Attachment Title / Caption</label>
<input type="text" id="clip-title-input" class="text-input" placeholder="e.g. Field Notes Photo / Competitor Spec / Article Excerpt" />
</div>
<div class="field-group">
<label>Image Source (File / Camera, Clipboard Paste, or Direct Image URL)</label>
<div id="clip-dropzone" class="attachment-dropzone">
<div style="display:flex;justify-content:space-between;align-items:center;gap:0.5rem;flex-wrap:wrap;">
<span class="muted-label">📋 Paste image (<kbd>Ctrl+V</kbd>) or drop file here</span>
<label class="btn btn-secondary btn-xs" style="cursor:pointer;">
📷 Select Photo / File
<input type="file" id="clip-file-input" accept="image/*" hidden />
</label>
</div>
<div id="clip-preview-row" class="attach-preview-row hidden">
<img id="clip-preview-img" src="" alt="Clip preview" />
<span class="muted-label" style="flex:1;">Image staged for attachment</span>
<button type="button" id="btn-clip-clear-img" class="btn btn-ghost btn-xs">✕ Clear</button>
</div>
<input type="url" id="clip-external-img-url" class="text-input input-sm" placeholder="Or paste an external image URL (https://example.com/photo.jpg)..." />
</div>
</div>
<div class="field-group">
<label for="clip-text-input">External Note / Excerpt / Markdown</label>
<textarea id="clip-text-input" rows="3" class="textarea-input" placeholder="Paste notes, thoughts, article quotes, or garment/project details..."></textarea>
</div>
<div class="field-group">
<label for="clip-source-url">Source Webpage URL (Optional)</label>
<input type="url" id="clip-source-url" class="text-input input-sm" placeholder="https://..." />
</div>
<div style="display:flex;gap:1rem;flex-wrap:wrap;">
<label class="filter-checkbox">
<input type="checkbox" id="clip-append-notes" checked />
<span>Append note text to Spark's Markdown Notes</span>
</label>
<label class="filter-checkbox">
<input type="checkbox" id="clip-set-cover" checked />
<span>Set image as Spark cover</span>
</label>
</div>
<div class="modal-footer">
<button type="button" id="btn-cancel-clip-modal" class="btn btn-ghost">Cancel</button>
<button type="submit" class="btn btn-primary">📎 Save Attachment to Spark</button>
</div>
</form>
</div>
</div>
<!-- MODAL: SUBMIT SPARK TO ANTIGRAVITY OR CODEX FOR DEVELOPMENT -->
<div id="dev-handoff-modal" class="modal-backdrop hidden">
<div class="modal-card modal-card-wide">
<div class="modal-header">
<h3>🚀 Submit Spark for Development</h3>
<button type="button" id="btn-close-dev-modal" class="btn btn-ghost btn-sm">✕</button>
</div>
<form id="dev-handoff-form" class="modal-body">
<p class="muted-label">
Packages all Spark information (title, pitch, markdown specs, checklist, pros/cons, reference links, and mockup/attachment URLs) and sends it to <strong>Antigravity</strong> or <strong>OpenAI Codex</strong>.
</p>
<div class="form-row-2">
<div class="field-group">
<label>1. Target Coding App</label>
<div class="dev-target-pills" id="dev-target-pills">
<button type="button" class="pill-btn active" data-dev-target="antigravity">
🛸 Google Antigravity
</button>
<button type="button" class="pill-btn" data-dev-target="codex">
🤖 OpenAI Codex
</button>
</div>
</div>
<div class="field-group">
<label for="dev-model-select">2. Select AI Model</label>
<select id="dev-model-select" class="filter-select full-width"></select>
</div>
</div>
<div class="dev-options-row">
<label class="filter-checkbox">
<input type="checkbox" id="dev-include-homelab" checked />
<span>Include Homelab Stack Spec (vloser Docker + Gitea + Traefik + Homepage)</span>
</label>
<label class="filter-checkbox">
<input type="checkbox" id="dev-move-building" checked />
<span>Move Spark to 🛠️ Building stage</span>
</label>
<label class="filter-checkbox hidden" id="dev-server-codex-wrap">
<input type="checkbox" id="dev-run-server-codex" />
<span>⚡ Also run autonomous Codex blueprint on server</span>
</label>
</div>
<div class="field-group">
<div class="field-header-row">
<label for="dev-spec-preview-textarea">3. Complete Development Specification Payload (Editable)</label>
<div style="display:flex;gap:0.35rem;">
<button type="button" id="btn-copy-dev-spec" class="btn btn-ghost btn-xs">📋 Copy Prompt</button>
<button type="button" id="btn-download-dev-spec" class="btn btn-ghost btn-xs">⬇️ Download SPEC.md</button>
</div>
</div>
<textarea id="dev-spec-preview-textarea" rows="11" class="textarea-input dev-spec-textarea"></textarea>
</div>
<div id="dev-handoff-result-box" class="nb-edit-box hidden"></div>
<div id="dev-handoff-instruction-note" class="muted-label" style="font-size:0.8rem; padding:0.4rem 0.6rem; background:rgba(76,140,245,0.08); border-radius:6px; border-left:3px solid var(--accent-primary); margin-top:0.4rem;">
🛸 Submitting switches focus to Antigravity and copies the complete project specification to your clipboard. Simply press <kbd>Ctrl+V</kbd> in Antigravity's chat to start coding.
</div>
<div class="modal-footer">
<button type="button" id="btn-cancel-dev-modal" class="btn btn-ghost">Cancel</button>
<button type="submit" id="btn-submit-dev-handoff" class="btn btn-primary">
🚀 Submit & Launch in Antigravity
</button>
</div>
</form>
</div>
</div>
<!-- MODAL: CARD / MOCKUP LIGHTBOX INSPECTOR -->
<div id="lightbox-modal" class="modal-backdrop hidden">
<div class="lightbox-card">
<div class="modal-header">
<h3 id="lightbox-title">Card Preview</h3>
<button type="button" id="btn-close-lightbox" class="btn btn-ghost btn-sm">✕</button>
</div>
<div class="lightbox-body">
<img id="lightbox-img" src="" alt="Preview" />
<div id="lightbox-meta" class="lightbox-meta"></div>
</div>
</div>
</div>
<div id="toast-container" class="toast-container" aria-live="polite"></div>
<script type="module" src="/app.js"></script>
</body>
</html>