async function navigateToUrl()

in src/gemini_95/index.ts [489:749]


    async function navigateToUrl(url: string): Promise<void> {
        // Normalize URL format
        if (!url.startsWith('http://') && !url.startsWith('https://')) {
            url = 'https://' + url;
        }

        try {
            // Parse the domain to use in the prompt
            const urlObj = new URL(url);
            const domain = urlObj.hostname;

            // Show loading screen
            loadingEl.innerHTML = `
                <style>
                    .dialup-animation .dot {
                        animation: dialup-blink 1.4s infinite both;
                    }
                    .dialup-animation .dot:nth-child(2) {
                        animation-delay: 0.2s;
                    }
                    .dialup-animation .dot:nth-child(3) {
                        animation-delay: 0.4s;
                    }
                    @keyframes dialup-blink {
                        0%, 80%, 100% { opacity: 0; }
                        40% { opacity: 1; }
                    }
                    .browser-loading p { margin: 5px 0; }
                    .browser-loading .small-text { font-size: 0.8em; color: #aaa; }
                </style>
                <img src="https://d112y698adiu2z.cloudfront.net/photos/production/software_photos/000/948/341/datas/original.gif"/>
                <p>Connecting to ${domain}<span class="dialup-animation"><span class="dot">.</span><span class="dot">.</span><span class="dot">.</span></span></p>
                <!-- Sound will play via JS -->
            `;
            loadingEl.style.display = 'flex'; // Make it visible *after* setting content

            // Play dial-up sound
            try {
                if (!dialUpAudio) { // Create audio element if it doesn't exist
                    dialUpAudio = new Audio(DIAL_UP_SOUND_URL);
                    dialUpAudio.loop = true; // Loop the sound while connecting
                }
                await dialUpAudio.play(); // Play returns a promise, await it
                console.log("Playing dial-up sound");
            } catch (audioError) {
                console.error("Error playing dial-up sound:", audioError);
            }

            try {
                // Try to load or initialize Gemini
                if (!geminiInstance) {
                    if (!await initializeGeminiIfNeeded('initAiBrowser')) {
                        const errorMsg = "CRITICAL ERROR: Failed to initialize AI. Cannot generate website.";
                        alert(errorMsg);
                        iframe.src = 'data:text/plain;charset=utf-8,' + encodeURIComponent(errorMsg);
                        loadingEl.style.display = 'none';
                        return;
                    }
                }

                console.log("Generating 90s website for domain:", domain);

                // Create a comprehensive prompt for a 90s-style website with images
                const websitePrompt = `
                Create a complete 90s-style website for the domain "${domain}".

                You MUST include:
                1. One image MUST be in your response - it should be a relevant graphic for "A small graphic logo for a website like ${domain}"
                2. Generate HTML with garish 90s styling (neon colors, comic sans, tables for layout)
                3. Make the content related specifically to what "${domain}" would be about
                4. Include classic 90s web elements:
                   - Scrolling marquee text
                   - Retro emoji or ascii art
                   - Blinking elements
                   - "Best viewed in Chrome" badge
                   - Visitor counter (use 9000+)
                   - "Under Construction" signs

                Create a fun, humorous website that feels like it was made in 1996.
                The image MUST match the theme of the website.

                DO NOT use modern web design principles - embrace the chaos of 90s web!
                `;

                // Generate website with text and images using the specifically mentioned model
                const result = await geminiInstance.models.generateContent({
                    model: "gemini-2.0-flash-mmgen-rev17",
                    contents: [{ role: "user", parts: [{ text: websitePrompt }] }],
                    config: {
                        temperature: 0.9,
                        responseModalities: ["TEXT", "IMAGE"]
                    }
                });

                console.log("Response received from Gemini API");
                console.log("Full Gemini Response:", JSON.stringify(result, null, 2)); // Log the full response object

                // Process the response to extract text (HTML) and images
                let htmlContent = "";
                const images: string[] = [];

                // Extract HTML and images from the response
                if (result.candidates && result.candidates.length > 0 && result.candidates[0].content) {
                    for (const part of result.candidates[0].content.parts) {
                        if (part.text) {
                            // Extract HTML content (remove any markdown format if present)
                            const textContent = part.text.replace(/```html|```/g, '').trim();
                            htmlContent += textContent;
                        }
                        else if (part.inlineData && part.inlineData.data) {
                            // Store image data as data URLs
                            images.push(`data:${part.inlineData.mimeType || 'image/png'};base64,${part.inlineData.data}`);
                            console.log("Image extracted successfully");
                        }
                    }
                }

                console.log(`Extracted HTML content and ${images.length} images`);

                // If we don't have HTML content, generate a basic framework
                if (!htmlContent.includes("<html")) {
                    // Generate base HTML structure if needed
                    const baseHTML = `
                    <!DOCTYPE html>
                    <html>
                    <head>
                        <title>${domain} - 90s Website</title>
                        <style>
                            body {
                                background-color: #FF00FF;
                                color: black;
                                font-family: "Comic Sans MS", "Times New Roman", serif;
                                margin: 10px;
                                padding: 0;
                            }
                            .container {
                                background-color: #00FFFF;
                                border: 5px ridge #FFFFFF;
                                padding: 10px;
                                margin: 10px auto;
                                max-width: 800px;
                            }
                            h1, h2 {
                                text-align: center;
                                color: blue;
                                text-shadow: 2px 2px yellow;
                            }
                            .blink {
                                animation: blinker 1s linear infinite;
                            }
                            @keyframes blinker {
                                50% { opacity: 0; }
                            }
                            img {
                                border: 3px ridge gray;
                                display: block;
                                margin: 10px auto;
                                max-width: 90%;
                            }
                            marquee {
                                background-color: yellow;
                                color: red;
                                font-weight: bold;
                            }
                        </style>
                    </head>
                    <body>
                        <div class="container">
                            <marquee scrollamount="6" behavior="alternate">Welcome to ${domain}!</marquee>
                            <h1 class="blink">Welcome to ${domain}</h1>
                            <div id="content">${htmlContent}</div>
                        </div>
                    </body>
                    </html>
                    `;
                    htmlContent = baseHTML;
                }

                // Insert images into HTML - both methods
                if (images.length > 0) {
                    // Method 1: Replace placeholder image references in the HTML
                    if (images[0]) {
                        // Replace references to logo or first image
                        htmlContent = htmlContent.replace(/src=["']logo\.png["']/i, `src="${images[0]}"`);
                        htmlContent = htmlContent.replace(/src=["'][^"']*logo[^"']*\.(?:png|gif|jpe?g)["']/i, `src="${images[0]}"`);
                    }

                    if (images[1]) {
                        // Replace references to under construction image
                        htmlContent = htmlContent.replace(/src=["']under_construction\.gif["']/i, `src="${images[1]}"`);
                        htmlContent = htmlContent.replace(/src=["'][^"']*under[^"']*construction[^"']*\.(?:png|gif|jpe?g)["']/i, `src="${images[1]}"`);
                        // Replace any other misc image that might be the second image
                        htmlContent = htmlContent.replace(/src=["'](?!data:)[^"']*\.(?:png|gif|jpe?g)["']/i, `src="${images[1]}"`);
                    }

                    // Method 2: If no image tags were found or replaced, insert the images directly
                    if (!htmlContent.includes(images[0]) && !htmlContent.includes(images[1])) {
                        // Find appropriate places to insert the images
                        let updatedHTML = htmlContent;

                        // If we have at least one image, insert it after the first heading as a logo
                        if (images[0]) {
                            updatedHTML = updatedHTML.replace(
                                /(<h1[^>]*>.*?<\/h1>)/i,
                                `$1\n<div style="text-align:center;"><img src="${images[0]}" alt="Logo" style="max-width:80%;"></div>`
                            );
                        }

                        // If we have a second image, find a suitable place for the "Under Construction" graphic
                        if (images[1]) {
                            // Try to insert before the closing body tag or closing container div
                            if (updatedHTML.includes('</body>')) {
                                updatedHTML = updatedHTML.replace(
                                    '</body>',
                                    `<div style="text-align:center;"><img src="${images[1]}" alt="Under Construction" style="max-width:60%;"></div>\n</body>`
                                );
                            } else {
                                // Fallback insertion point
                                updatedHTML = updatedHTML.replace(
                                    '</div>',
                                    `<div style="text-align:center;"><img src="${images[1]}" alt="Under Construction" style="max-width:60%;"></div>\n</div>`
                                );
                            }
                        }

                        htmlContent = updatedHTML;
                    }
                }

                // Create a data URL from the HTML content
                const dataUrl = 'data:text/html;charset=utf-8,' + encodeURIComponent(htmlContent);

                // Set the iframe source to our generated content
                iframe.src = dataUrl;

                // Update address bar to show the URL that was entered
                addressBar.value = url;

                console.log("Website generated and displayed successfully");

            } catch (error: any) {
                console.error("Error generating website:", error);
                alert(`Error: ${error.message || "Failed to generate website"}`);
            } finally {
                // Hide loading screen
                loadingEl.style.display = 'none';

                // Stop dial-up sound
                if (dialUpAudio) {
                    dialUpAudio.pause();
                    dialUpAudio.currentTime = 0; // Reset playback position
                    console.log("Stopped dial-up sound");
                }
            }

        } catch (e) {
            console.error("Invalid URL:", e);
            alert("Please enter a valid URL");
            loadingEl.style.display = 'none';
        }
    }