/* JustVitamin × QuikCue — Live AI Demos */ const $ = s => document.querySelector(s); const esc = s => { if (!s) return ''; const d = document.createElement('div'); d.textContent = s; return d.innerHTML; }; function setStep(id, cls, text) { const el = $(id); if (!el) return; el.parentElement.className = `step ${cls}`; el.innerHTML = text; } function setBtn(id, loading, text) { const btn = $(id); btn.disabled = loading; btn.classList.toggle('loading', loading); btn.textContent = text; } // ═══════════════════════════════════════════════════════════════ // DEMO A — One Product → 12 Assets + Images // ═══════════════════════════════════════════════════════════════ let demoA_product = null; async function runDemoA() { const url = $('#demoA-url').value.trim(); if (!url) return; setBtn('#demoA-btn', true, 'Working...'); $('#demoA-output').classList.add('hidden'); ['#a-s1','#a-s2','#a-s3'].forEach(s => setStep(s, '', 'Waiting')); // Step 1: Scrape setStep('#a-s1', 'active', ' Scraping...'); try { const r = await fetch('/api/scrape', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({url}) }); const product = await r.json(); if (product.error) throw new Error(product.error); demoA_product = product; setStep('#a-s1', 'done', `✓ ${esc(product.title.substring(0,35))}...`); } catch(e) { setStep('#a-s1', 'error', `✗ ${esc(e.message)}`); setBtn('#demoA-btn', false, '🔴 Generate the Whole Pack'); return; } // Step 2: AI pack + Step 3: Images (parallel) setStep('#a-s2', 'active', ' Gemini generating 12 assets...'); setStep('#a-s3', 'active', ' Nano Banana generating images...'); const packP = fetch('/api/generate-pack', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify(demoA_product) }).then(r => r.json()); const imgP = fetch('/api/generate-images', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify(demoA_product) }).then(r => r.json()); // Handle pack try { const pack = await packP; if (pack.error) throw new Error(pack.error); setStep('#a-s2', 'done', `✓ 12 assets generated (${pack._generation_time})`); renderAssetPack(pack); $('#demoA-output').classList.remove('hidden'); } catch(e) { setStep('#a-s2', 'error', `✗ ${esc(e.message)}`); } // Handle images try { const imgs = await imgP; if (imgs.error) throw new Error(imgs.error); setStep('#a-s3', 'done', `✓ Images generated (${imgs._generation_time})`); renderImages(imgs); } catch(e) { setStep('#a-s3', 'error', `✗ ${esc(e.message)}`); } setBtn('#demoA-btn', false, '✓ Done — Run Again'); } function renderAssetPack(pack) { const meta = $('#demoA-meta'); meta.innerHTML = ` 🧠 Model: Gemini 2.5 Flash Time: ${esc(pack._generation_time)} 📦 Product: ${esc(pack._product_title)} `; const grid = $('#demoA-assets'); let cards = ''; let n = 0; // Hero angles (pack.hero_angles || []).forEach((a, i) => { n++; cards += assetCard('hero', `Hero Angle`, n, `"${esc(a.headline)}"`, i*80); }); // PDP Copy if (pack.pdp_copy) { n++; const bullets = (pack.pdp_copy.bullets||[]).map(b => `
  • ${esc(b)}
  • `).join(''); cards += assetCard('pdp', 'PDP Copy', n, `${esc(pack.pdp_copy.headline)}`, n*80); n++; const faqs = (pack.pdp_copy.faq||[]).map(f => `Q: ${esc(f.q)}
    A: ${esc(f.a)}

    `).join(''); cards += assetCard('pdp', 'FAQ Block', n, faqs, n*80); } // Ad hooks if (pack.ad_hooks) { n++; const hooks = pack.ad_hooks.map(h => `
  • ${esc(h)}
  • `).join(''); cards += assetCard('ad', '5 Ad Hooks', n, ``, n*80); } // Email subjects if (pack.email_subjects) { n++; const emails = pack.email_subjects.map(e => `${esc(e.subject)}
    ${esc(e.preview)}

    `).join(''); cards += assetCard('email', 'Email Subjects', n, emails, n*80); } // TikTok if (pack.tiktok_script) { n++; const t = pack.tiktok_script; cards += assetCard('video', 'TikTok Script', n, ` ${esc(t.title)}

    [0-3s] ${esc(t.hook_0_3s)}
    [3-12s] ${esc(t.body_3_12s)}
    [12-15s] ${esc(t.cta_12_15s)}

    ${esc(t.why_it_works)} `, n*80); } // Blog if (pack.blog_outline) { n++; const b = pack.blog_outline; const secs = (b.sections||[]).map(s => `
  • ${esc(s)}
  • `).join(''); cards += assetCard('blog', 'Blog Outline', n, ` ${esc(b.title)} SEO: "${esc(b.seo_keyword)}" — ${esc(b.monthly_searches)} mo/searches `, n*80); } // Meta SEO if (pack.meta_seo) { n++; const m = pack.meta_seo; cards += assetCard('seo', 'Meta SEO', n, ` Title: ${esc(m.title)}

    Description: ${esc(m.description)}

    ${m.title_chars || '?'} chars title / ${m.desc_chars || '?'} chars desc `, n*80); } // Alt text if (pack.alt_text) { n++; const alts = pack.alt_text.map(a => `${esc(a.image_type)}:
    Alt: ${esc(a.alt)}
    File: ${esc(a.filename)}

    `).join(''); cards += assetCard('a11y', 'Alt Text + Filenames', n, alts, n*80); } // A/B Variants if (pack.ab_variants) { n++; const vars = pack.ab_variants.map(v => `${esc(v.label)}: ${esc(v.copy)}

    `).join(''); cards += assetCard('ad', 'A/B Variants', n, vars + 'Test all — let data pick the winner', n*80); } grid.innerHTML = cards; } function assetCard(type, label, num, content, delay) { return `
    ${label}#${num}
    ${content}
    `; } function renderImages(imgs) { const grid = $('#demoA-img-grid'); const section = $('#demoA-images'); let html = ''; const styles = [ {key:'hero', label:'Hero Banner', desc:'Nano Banana Pro', wide:true}, {key:'lifestyle', label:'Lifestyle Shot', desc:'Nano Banana'}, {key:'benefits', label:'Benefits Visual', desc:'Nano Banana Pro'}, ]; styles.forEach(s => { const data = imgs[s.key]; if (data && data.filename) { html += `
    ${s.label}
    ${s.label} — ${s.desc} · ${data.model||''}
    `; } }); if (html) { grid.innerHTML = html; section.classList.remove('hidden'); } } // ═══════════════════════════════════════════════════════════════ // DEMO B — Competitor X-Ray // ═══════════════════════════════════════════════════════════════ async function runDemoB() { const url = $('#demoB-url').value.trim(); if (!url) return; setBtn('#demoB-btn', true, 'Scanning...'); $('#demoB-output').classList.add('hidden'); setStep('#b-s1', 'active', ' Scraping competitor...'); setStep('#b-s2', '', 'Waiting'); try { const r = await fetch('/api/competitor-xray', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({url}) }); const data = await r.json(); if (data.error) throw new Error(data.error); setStep('#b-s1', 'done', `✓ Scraped: ${esc((data._scrape_data?.title||'').substring(0,30))}...`); setStep('#b-s2', 'done', `✓ Analysis complete (${data._generation_time})`); renderXray(data); $('#demoB-output').classList.remove('hidden'); setBtn('#demoB-btn', false, '✓ Done — Try Another'); } catch(e) { setStep('#b-s1', 'error', `✗ ${esc(e.message)}`); setBtn('#demoB-btn', false, '🔍 X-Ray This Competitor'); } } function renderXray(data) { // Left — competitor analysis const tactics = (data.top_5_tactics||[]).map(t => `
  • ${esc(t.tactic)} — ${esc(t.explanation)}
  • ` ).join(''); $('#demoB-left').innerHTML = ` ❌ ${esc(data.competitor_name || 'Competitor')}
    What they're really selling
    ${esc(data.what_theyre_selling)}
    Top 5 Persuasion Tactics
      ${tactics}
    Weakest Claim / Gap
    ⚠️ ${esc(data.weakest_claim)}
    `; // Right — JV improved const hero = data.jv_hero_section || {}; const diffs = (data.differentiators||[]).map(d => `
  • 🎯${esc(d.point)} — ${esc(d.proof_idea)}
  • ` ).join(''); const donts = (data.do_not_say||[]).map(d => `
  • ${esc(d)}
  • `).join(''); $('#demoB-right').innerHTML = ` ✓ Just Vitamins — Upgraded

    ${esc(hero.headline)}

    ${esc(hero.body)}

    ${esc(hero.value_prop)}

    3 Differentiators + Proof Ideas
    ⚠️ Do Not Say — Compliance
    `; } // ═══════════════════════════════════════════════════════════════ // DEMO C — PDP Surgeon // ═══════════════════════════════════════════════════════════════ let demoC_product = null; let demoC_cache = {}; async function runDemoC() { const url = $('#demoC-url').value.trim(); if (!url) return; setBtn('#demoC-btn', true, 'Working...'); $('#demoC-output').classList.add('hidden'); demoC_cache = {}; setStep('#c-s1', 'active', ' Scraping product...'); setStep('#c-s2', '', 'Waiting'); // Step 1: Scrape try { const r = await fetch('/api/scrape', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({url}) }); const product = await r.json(); if (product.error) throw new Error(product.error); demoC_product = product; setStep('#c-s1', 'done', `✓ ${esc(product.title.substring(0,35))}...`); } catch(e) { setStep('#c-s1', 'error', `✗ ${esc(e.message)}`); setBtn('#demoC-btn', false, '🎨 Scrape & Rewrite'); return; } // Step 2: AI rewrite (default style) const active = document.querySelector('#demoC-toggles .toggle.active'); const style = active?.dataset.style || 'balanced'; await rewriteStyle(style); setBtn('#demoC-btn', false, '✓ Done — Change URL'); } async function switchDemoC(style, btn) { document.querySelectorAll('#demoC-toggles .toggle').forEach(t => t.classList.remove('active')); btn.classList.add('active'); if (!demoC_product) return; await rewriteStyle(style); } async function rewriteStyle(style) { if (demoC_cache[style]) { renderSurgeon(demoC_product, demoC_cache[style]); return; } setStep('#c-s2', 'active', ` Gemini rewriting as ${style}...`); try { const r = await fetch('/api/pdp-surgeon', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({product: demoC_product, style}) }); const result = await r.json(); if (result.error) throw new Error(result.error); demoC_cache[style] = result; setStep('#c-s2', 'done', `✓ ${style} rewrite (${result._generation_time})`); renderSurgeon(demoC_product, result); $('#demoC-output').classList.remove('hidden'); } catch(e) { setStep('#c-s2', 'error', `✗ ${esc(e.message)}`); } } function renderSurgeon(product, result) { // Left — current const bullets = (product.benefits||[]).map(b => `
  • ${esc(b)}
  • `).join(''); $('#demoC-left').innerHTML = ` ✕ Current PDP

    ${esc(product.title)}

    ${esc(product.subtitle)}

    ${esc(product.price)} ${esc(product.quantity)}

    ${esc((product.description||'').substring(0,400))}...

    `; // Right — rewritten const rBullets = (result.bullets||[]).map(b => `
    ${esc(b.text)}
    ↑ ${esc(b.annotation)}` ).join(''); $('#demoC-right').innerHTML = ` ✓ AI-Rewritten — ${esc(result.style||'balanced').toUpperCase()}

    ${esc(result.title)}

    ↑ SEO-optimised title

    ${esc(result.subtitle)}

    ${esc(result.hero_copy)}
    ↑ ${esc(result.hero_annotation)}
    ${rBullets}
    ⭐ ${esc(result.social_proof)}
    ↑ ${esc(result.social_proof_annotation)}
    ${esc(result.price_reframe)}
    ↑ ${esc(result.price_annotation)}

    ${esc(result.usage_instruction)}

    ↑ ${esc(result.usage_annotation)}
    `; } // Smooth scroll nav document.querySelectorAll('a[href^="#"]').forEach(a => { a.addEventListener('click', e => { const t = document.querySelector(a.getAttribute('href')); if (t) { e.preventDefault(); t.scrollIntoView({behavior:'smooth'}); } }); });