Superhero Story Generator!
Forge an epic saga of heroes and villains with a few clicks!
Heroic Blueprints
Awaiting Signal...
Provide the story details to answer the call to action!
Assembling heroes...
Mission Failure!
The story couldn't be generated. Check the console.
No content available.
'; } } function showTab(index) { const tabs = tabsContainer.querySelectorAll('.tab'); const contents = tabContentsContainer.querySelectorAll('.tab-content'); tabs.forEach(tab => tab.classList.remove('active')); contents.forEach(content => content.classList.remove('active')); if(tabs[index]) tabs[index].classList.add('active'); if(contents[index]) contents[index].classList.add('active'); currentTabIndex = index; updateNavButtons(); } function navigateTabs(direction) { const newIndex = currentTabIndex + direction; if (newIndex >= 0 && newIndex < tabConfig.length) showTab(newIndex); } function updateNavButtons() { prevTabBtn.disabled = currentTabIndex === 0; nextTabBtn.disabled = currentTabIndex === tabConfig.length - 1; } function generatePdf() { if (!window.jspdf || !latestGeneratedData) { alert("Please generate a story before downloading the case file."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); const pageHeight = doc.internal.pageSize.getHeight(); const pageWidth = doc.internal.pageSize.getWidth(); const margin = 40; const contentWidth = pageWidth - margin * 2; let cursorY = 0; // Background doc.setFillColor(241, 245, 249); // Slate-100 doc.rect(0, 0, pageWidth, pageHeight, 'F'); // Header cursorY = margin; doc.setFillColor(51, 65, 85); // Slate-700 doc.rect(0, cursorY, pageWidth, 40, 'F'); doc.setFont("Helvetica", "bold"); doc.setFontSize(16); doc.setTextColor(255, 255, 255); doc.text("TOP SECRET // HERO INITIATIVE CASE FILE", pageWidth/2, cursorY + 25, { align: 'center'}); cursorY += 70; const drawField = (label, value) => { if (!value) return; doc.setFont("Helvetica", "bold"); doc.setFontSize(9); doc.setTextColor(100, 116, 139); // Slate-500 doc.text(`${label.toUpperCase()}:`, margin, cursorY); doc.setFont("Helvetica", "normal"); doc.setFontSize(11); doc.setTextColor(30, 41, 59); // Slate-800 const valueLines = doc.splitTextToSize(value, contentWidth - 60); doc.text(valueLines, margin + 70, cursorY); cursorY += (valueLines.length * 12) + 15; doc.setDrawColor(226, 232, 240); // Slate-200 doc.line(margin, cursorY - 8, pageWidth - margin, cursorY - 8); }; drawField("Case Title", latestGeneratedData.title); drawField("Logline", latestGeneratedData.logline); drawField("Asset", latestGeneratedData.hero_name); drawField("Threat", latestGeneratedData.villain_name); drawField("Associate", latestGeneratedData.key_supporting_character); const drawSection = (title, content) => { if (!content) return; if (cursorY > pageHeight - 100) { doc.addPage(); cursorY = margin; } doc.setFillColor(226, 232, 240); // Slate-200 doc.rect(margin, cursorY, contentWidth, 20, 'F'); doc.setFont("Helvetica", "bold"); doc.setFontSize(10); doc.setTextColor(51, 65, 85); // Slate-700 doc.text(title.toUpperCase(), margin + 5, cursorY + 14); cursorY += 35; doc.setFont("Helvetica", "normal"); doc.setFontSize(11); doc.setTextColor(30, 41, 59); const lines = doc.splitTextToSize(content, contentWidth); if (cursorY + (lines.length * 12) > pageHeight - margin) { doc.addPage(); cursorY = margin; } doc.text(lines, margin, cursorY); cursorY += lines.length * 12 + 20; }; drawSection("Origin Report", latestGeneratedData.origin_story); drawSection("Mission Synopsis", latestGeneratedData.synopsis); drawSection("Initial Engagement", latestGeneratedData.opening_scene); // Footer const footerY = pageHeight - 25; doc.setFillColor(51, 65, 85); doc.rect(0, footerY - 10, pageWidth, 35, 'F'); doc.setFont("Helvetica", "normal"); doc.setFontSize(8); doc.setTextColor(255, 255, 255); doc.text("FOR AUTHORIZED EYES ONLY", pageWidth/2, footerY, {align: 'center'}); const safeFileName = (latestGeneratedData.title || 'superhero_story').replace(/[^a-z0-9]/gi, '_').toLowerCase(); doc.save(`${safeFileName}_case_file.pdf`); } setUIState('placeholder'); });