console.log("Script execution started."); // --- Global Variables --- let generatedCode = []; let currentCleanedCode = []; let evolutionTimeline = []; let activeTimelineIndex = -1; let selectedVariationGridIndex = -1; let currentFullscreenHistoryIndex = -1; let originalUserPromptForCurrentGeneration = ''; let lastPreviewUpdateTime = []; let previewUpdateInterval = 500; let numVariationsToGenerate = 4; let activeApiControllers = []; let lastGenerationConfig = { prompt: '', isRefinement: false, numVariations: 4, refinedTimelineIndex: -1, thinkingBudget: 0 }; // --- DOM Element References --- let apiKeyEl, codeOutputEl, errorMessageEl; let modelSelEl; let selectButtons = []; let fullscreenButtons = []; let previewItems = []; let refinementLoadingIndicator; let mainContentEl, configButtonEl; let intervalSliderEl, intervalValueDisplayEl; let fullscreenOverlayEl, fullscreenIframeEl, exitFullscreenBtnEl; let perspectiveViewportEl, previewGridWrapperEl; let historyPanelEl, historyPanelPlaceholderEl; let selectedCodeTitleH3El; let mainContentTitleH1El, mainContentSubtitleH2El; let fullscreenHistoryNavEl, historyNavPrevBtnEl, historyNavNextBtnEl; let promptModalOverlayEl, promptModalContentEl, modalUserPromptEl, modalGenerateBtnEl, modalCancelBtnEl, modalLoadingIndicatorEl; let modalRefinementCheckboxEl, numVariationsSliderEl, numVariationsValueDisplayEl; let configModalOverlayEl, configModalContentEl, configModalCloseBtnEl, copyCodeButtonEl; let historyToggleButtonEl, historyArrowDownEl, historyArrowUpEl; let exportCodeButtonEl; let newButtonEl; let confirmModalOverlayEl, confirmModalMessageEl, confirmModalConfirmBtnEl, confirmModalCancelBtnEl; let currentConfirmCallback = null; let historyNavLeftBtnEl, historyNavRightBtnEl; let modalThinkingBudgetSliderEl, modalThinkingBudgetValueDisplayEl; let promptDisplayModalOverlayEl, promptDisplayModalContentEl, fullPromptTextEl, promptDisplayModalCloseBtnEl; let showPromptModalButtonEl; // Added for the new button let variationNavLeftBtnEl, variationNavRightBtnEl; // Buttons for variation scrolling // --- Elements for Initial Setup CTA --- let initialSetupCtaEl; let initialApiKeyInputEl; let examplePromptsContainerEl; // --- Constants --- const API_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/models/'; // --- Helper Function to Process Stream for One Variation --- async function processStreamForVariation(apiKey, prompt, variationIndex, modelName, signal) { console.log(`[Variation ${variationIndex + 1}] Starting generation with model ${modelName}...`); const previewFrame = document.getElementById(`preview-frame-${variationIndex + 1}`); const loader = document.getElementById(`preview-loader-${variationIndex + 1}`); const selectBtn = selectButtons[variationIndex]; const fullscreenBtn = fullscreenButtons[variationIndex]; const currentThinkingBudget = parseInt(lastGenerationConfig.thinkingBudget, 10); if (!previewFrame) { console.error(`[Variation ${variationIndex + 1}] Preview frame missing.`); return false; } if (!loader) { console.warn(`[Variation ${variationIndex + 1}] Loader missing.`); } if (loader) loader.classList.remove('hidden'); if (selectBtn) selectBtn.disabled = true; if (fullscreenBtn) fullscreenBtn.disabled = true; if (previewFrame) updateLivePreviewInGrid(variationIndex, '

Generating...

', false); if(lastPreviewUpdateTime[variationIndex] !== undefined) lastPreviewUpdateTime[variationIndex] = 0; const API_ENDPOINT = `${API_BASE_URL}${modelName}:streamGenerateContent?key=${apiKey}&alt=sse`; let rawGeneratedCode = ''; let htmlBlockStarted = false; let accumulatedStreamData = ''; let success = false; try { const requestBody = { contents: [{ parts: [{ text: prompt }] }] }; if (currentThinkingBudget > 0) { requestBody.generationConfig = { thinkingConfig: { thinkingBudget: currentThinkingBudget } }; console.log(`[Variation ${variationIndex + 1}] Thinking Mode ENABLED. Budget: ${currentThinkingBudget}`); } const response = await fetch(API_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestBody), signal: signal }); if (!response.ok) { let errorDetails = `HTTP Error: ${response.status} ${response.statusText}`; try { const errorData = await response.json(); errorDetails += ` - ${errorData?.error?.message || 'No msg.'}`; } catch (e) { /* Ignore */ } throw new Error(errorDetails); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let sseBuffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; sseBuffer += decoder.decode(value, { stream: true }); let eolIndex; while ((eolIndex = sseBuffer.indexOf('\n')) >= 0) { const line = sseBuffer.substring(0, eolIndex).trim(); sseBuffer = sseBuffer.substring(eolIndex + 1); if (line.startsWith('data: ')) { try { const jsonData = JSON.parse(line.substring(5).trim()); if (jsonData.candidates?.[0]?.content?.parts?.[0]?.text) { const textPart = jsonData.candidates[0].content.parts[0].text; if (!htmlBlockStarted) { accumulatedStreamData += textPart; const marker = "```html"; const markerIndex = accumulatedStreamData.indexOf(marker); if (markerIndex !== -1) { htmlBlockStarted = true; let codeStartIndex = markerIndex + marker.length; if (accumulatedStreamData[codeStartIndex] === '\n') { codeStartIndex++; } rawGeneratedCode = accumulatedStreamData.substring(codeStartIndex); } } else { rawGeneratedCode += textPart; } if (htmlBlockStarted) { const now = Date.now(); if (lastPreviewUpdateTime[variationIndex] !== undefined && (now - lastPreviewUpdateTime[variationIndex] >= previewUpdateInterval)) { updateLivePreviewInGrid(variationIndex, rawGeneratedCode, true); lastPreviewUpdateTime[variationIndex] = now; } } } } catch (e) { console.warn(`[Var ${variationIndex + 1}] JSON parse error:`, e, "Problematic Line:", line); } } } } console.log(`[Variation ${variationIndex + 1}] Streaming finished. HTML Block Started: ${htmlBlockStarted}. Raw content after marker: ${(rawGeneratedCode || "").substring(0, 200)}`); let finalExtractedHtml = null; let processingErrorMessage = null; if (htmlBlockStarted) { let tempHtml = rawGeneratedCode.trim(); if (tempHtml.endsWith("```")) { tempHtml = tempHtml.substring(0, tempHtml.length - 3).trim(); } else if (tempHtml.endsWith("```html")) { tempHtml = tempHtml.substring(0, tempHtml.length - 7).trim(); } if (tempHtml.length > 0) { finalExtractedHtml = tempHtml; const minLength = 20; const hasStructuralTag = /]*>|]*>|]*>/i.test(finalExtractedHtml); const hasAnyTag = /<[a-zA-Z][^>]*>/.test(finalExtractedHtml); if (finalExtractedHtml.length >= minLength && (hasStructuralTag || hasAnyTag)) { success = true; console.log(`[Variation ${variationIndex + 1}] HTML validation SUCCEEDED.`); } else { success = false; console.warn("[Variation " + (variationIndex + 1) + "] HTML validation FAILED (length: " + finalExtractedHtml.length + ", structural: " + hasStructuralTag + ", anyTag: " + hasAnyTag + "). Review content manually."); } } else { processingErrorMessage = "// Error: No meaningful content found after '```html' marker."; console.warn(`[Variation ${variationIndex + 1}] ${processingErrorMessage}`); success = false; } } else { processingErrorMessage = `// Error: '\`\`\`html' code block marker not found. Received:\n${(accumulatedStreamData || rawGeneratedCode || "").substring(0, 200)}`; console.warn(`[Variation ${variationIndex + 1}] ${processingErrorMessage}`); success = false; } if (success && finalExtractedHtml) { let processedHtml = finalExtractedHtml; const requiredHeadContent = ` blocks (that are not JSON-LD or other non-executable script types). If no functional