Initial commit: SparkVault Idea Tracker, 64-card Creative Whack Pack & Nano Banana 2.1 Mockup Studio

This commit is contained in:
airent106 committed 2026-10-29 10:41:37 -06:00
commit 49e3134758
82 files changed
+6312

No files matched your search

+1925
View File
File diff suppressed because it is too large. Load diff
+32
View File
@@ -0,0 +1,32 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="SparkVault">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#1E2536"/>
<stop offset="100%" stop-color="#0E121B"/>
</linearGradient>
<linearGradient id="spark" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#FDE047"/>
<stop offset="50%" stop-color="#F59E0B"/>
<stop offset="100%" stop-color="#EA580C"/>
</linearGradient>
</defs>
<!-- Rounded Studio Badge -->
<rect width="64" height="64" rx="16" fill="url(#bg)"/>
<rect x="1" y="1" width="62" height="62" rx="15" fill="none" stroke="#FFFFFF" stroke-opacity="0.1" stroke-width="1"/>
<!-- 4 Whack Pack Suit Accent Dots (Explorer, Artist, Judge, Warrior) -->
<circle cx="14" cy="14" r="3" fill="#2B7EC1"/>
<circle cx="50" cy="14" r="3" fill="#D95F3B"/>
<circle cx="14" cy="50" r="3" fill="#2A9158"/>
<circle cx="50" cy="50" r="3" fill="#B8335A"/>
<!-- Tilted Creative Whack Card Silhouette behind the Spark -->
<g transform="rotate(-10 32 32)">
<rect x="17" y="12" width="28" height="38" rx="4" fill="#FBF8F1" stroke="#D8CCB8" stroke-width="1.5"/>
<line x1="21" y1="19" x2="39" y2="19" stroke="#2B7EC1" stroke-width="2.2" stroke-linecap="round"/>
<line x1="21" y1="43" x2="35" y2="43" stroke="#D95F3B" stroke-width="2" stroke-linecap="round"/>
</g>
<!-- Central Glowing Idea Spark / Lightning Bulb -->
<polygon points="36,11 21,34 31,34 27,53 45,28 34,28" fill="url(#spark)" stroke="#FFFBEB" stroke-width="1.2" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+694
View File
@@ -0,0 +1,694 @@
<!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, Creative Whack Pack & Nano Banana 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">Whack Pack + 🍌 Nano Banana 2.1</span>
</div>
<p class="brand-subtitle">Capture sparks, break blocks with 64 Creative Whack cards, and mock up visuals</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-quick-whack-prompt"
class="btn btn-ghost btn-sm"
title="Draw a random Creative Whack Pack card to spark a new idea"
>
🃏 Whack Prompt
</button>
</form>
<div class="topbar-actions">
<button type="button" id="btn-open-settings" class="btn btn-ghost btn-sm" title="Configure Nano Banana 2.1 API Key & Model">
🍌 <span id="api-key-status-dot" class="status-dot"></span> Nano Banana
</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="view-tabs" role="tablist">
<button type="button" class="view-tab active" data-view="board" role="tab">
📋 Pipeline Board
</button>
<button type="button" class="view-tab" data-view="grid" role="tab">
🗂️ Explorer & Mockup Gallery
</button>
<button type="button" class="view-tab" data-view="whack" role="tab">
🃏 Creative Whack Pack <span class="tab-pill">64 Cards</span>
</button>
<button type="button" class="view-tab" data-view="review" role="tab">
⚔️ Review & Head-to-Head Arena
</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>
</div>
</nav>
<!-- MAIN WORKSPACE -->
<main class="workspace">
<!-- VIEW 1: PIPELINE KANBAN BOARD -->
<section id="view-board" class="view-section active">
<div class="kanban-board" id="kanban-board">
<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">🧭 Explorer 1–16</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">🎨 Artist & ⚖️ Judge</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">⚔️ Warrior 49–64</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">
<input type="text" id="drawer-title-input" class="drawer-title-input" placeholder="Idea Title" />
<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="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">
🍌 Nano Banana Mockup Studio <span id="drawer-mockup-count" class="tab-pill">0</span>
</button>
<button type="button" class="drawer-tab" data-drawer-tab="whack">
🃏 Whack This Idea <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">
<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>
<!-- Prioritization Sliders -->
<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>
<!-- Tags -->
<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>
<!-- 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, fabric/ink colors, architecture notes, or markdown lists..."></textarea>
<div id="drawer-notes-preview" class="markdown-preview hidden"></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>
<!-- 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. Blank Shirt Spec)" />
<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>
</div>
<!-- TAB 2: NANO BANANA 2.1 VISUAL 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>🍌 Nano Banana 2.1 AI Mockup Generator</h3>
<button type="button" id="btn-studio-auto-prompt" class="btn btn-ghost btn-xs">✨ Auto-Prompt from Idea</button>
</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 Whack Pack 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 -->
<div class="field-group">
<label>Garment / Surface 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 graphic, emblem, ink colors, typography, 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="Tell Nano Banana what to change (e.g. 'Move graphic to left-chest pocket on a forest green shirt')"
/>
</div>
<div class="studio-action-row">
<button type="button" id="btn-generate-nano-banana" class="btn btn-primary">
🍌 Generate with Nano Banana 2.1
</button>
<span id="nb-generation-status" class="muted-label"></span>
</div>
</div>
<!-- Interactive T-Shirt & Product Canvas Compositor -->
<div class="studio-card">
<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>
<label for="comp-top-text">Top Headline / Club Name</label>
<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 with 🍌' 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: NANO BANANA 2.1 SETTINGS -->
<div id="settings-modal" class="modal-backdrop hidden">
<div class="modal-card">
<div class="modal-header">
<h3>🍌 Nano Banana 2.1 (Gemini Image API) 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">
SparkVault uses Google's <strong>Nano Banana 2.1 (`gemini-nano-banana-2.1`)</strong> via the official `@google/genai` Interactions API for text-to-image product mockups and multi-turn conversational image editing.
</p>
<div class="field-group">
<label for="settings-api-key">Gemini API Key (`GEMINI_API_KEY`)</label>
<input
type="password"
id="settings-api-key"
class="text-input"
placeholder="Paste your AI Studio / Gemini API key (AIza...)"
autocomplete="off"
/>
<small id="settings-key-status" class="muted-label"></small>
</div>
<div class="field-group">
<label for="settings-model-select">Nano Banana Model</label>
<select id="settings-model-select" class="filter-select full-width">
<option value="gemini-nano-banana-2.1">gemini-nano-banana-2.1 — Nano Banana 2.1 (Default High-Efficiency)</option>
<option value="gemini-3-pro-image">gemini-3-pro-image — Nano Banana Pro (High-Detail Studio)</option>
<option value="gemini-3.1-flash-lite-image">gemini-3.1-flash-lite-image — Nano Banana 2 Lite (Ultra-Fast)</option>
</select>
</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: 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>
+1373
View File
File diff suppressed because it is too large. Load diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB