add formatting to the text inside the chat bubbles 

<!DOCTYPE html>
<html>
<head>
  <title>Google</title>
  <style>
    /* Existing Styles */
    body {
      font-family: sans-serif;
      margin: 0;
      padding: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      background-color: #f0f0f0;
    }

    .container {
      display: flex;
      flex-direction: column;
      width: 90%;
      max-width: 600px;
      height: 80vh;
      background-color: #fff;
      border: 1px solid #ccc;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.1);
      overflow: hidden;
    }

    /* Header for Toggle Buttons */
    .header {
      padding: 10px 20px;
      background-color: #f9f9f9;
      border-bottom: 1px solid #ddd;
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
      align-items: center;
    }

    .toggle-container {
      display: flex;
      align-items: center;
      margin: 5px 0;
    }

    .toggle-container label {
      margin-right: 10px;
      font-size: 14px;
    }

    /* Toggle switch styles */
    .switch {
      position: relative;
      display: inline-block;
      width: 50px;
      height: 28px;
      margin-left: 10px;
    }

    .switch input {
      opacity: 0;
      width: 0;
      height: 0;
    }

    .slider {
      position: absolute;
      cursor: pointer;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: #ccc;
      transition: .4s;
      border-radius: 28px;
    }

    .slider:before {
      position: absolute;
      content: "";
      height: 22px;
      width: 22px;
      left: 3px;
      bottom: 3px;
      background-color: white;
      transition: .4s;
      border-radius: 50%;
    }

    input:checked + .slider {
      background-color: #2196F3;
    }

    input:checked + .slider:before {
      transform: translateX(22px);
    }

    /* Chat Container */
    #chat-container {
      flex: 1;
      padding: 15px;
      overflow-y: auto;
      background-color: #fafafa;
    }

    .message {
      padding: 10px 15px;
      margin-bottom: 10px;
      border-radius: 18px;
      max-width: 80%;
      word-wrap: break-word;
      position: relative;
      clear: both;
    }

    .user-message {
      background-color: #e0f7fa;
      align-self: flex-end;
      margin-left: auto;
      text-align: right;
    }

    .bot-message {
      background-color: #f1f8e9;
      align-self: flex-start;
      margin-right: auto;
    }

    /* Input Area */
    #input-area {
      display: flex;
      flex-direction: column;
      padding: 10px 20px;
      border-top: 1px solid #ddd;
      background-color: #f9f9f9;
    }

    .message-input-row {
      display: flex;
      align-items: center;
    }

    #input-box {
      flex-grow: 1;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 20px;
      resize: none;
      font-size: 14px;
      outline: none;
    }

    #send-button {
      padding: 10px 20px;
      margin-left: 10px;
      background-color: #007bff;
      color: #fff;
      border: none;
      border-radius: 20px;
      cursor: pointer;
      font-size: 14px;
      transition: background-color 0.3s;
    }

    #send-button:hover {
      background-color: #0056b3;
    }

    /* File Attach Area */
    #file-attach-row {
      display: flex;
      align-items: center;
      margin-top: 10px;
    }

    #file-input {
      flex-grow: 1;
      padding: 5px;
      border: 1px solid #ccc;
      border-radius: 20px;
      font-size: 14px;
      outline: none;
    }

    /* Typing Indicator */
    #typing-indicator {
      padding: 5px 20px;
      font-style: italic;
      color: #999;
      background-color: #f9f9f9;
      border-top: 1px solid #ddd;
      display: none;
    }

    /* Progress Bar */
    #progress-container {
      width: 100%;
      background-color: #e0e0e0;
      border-radius: 5px;
      margin-top: 10px;
      display: none;
    }

    #progress-bar {
      width: 0%;
      height: 10px;
      background-color: #28a745;
      border-radius: 5px;
    }

    /* Responsive Adjustments */
    @media (max-width: 768px) {
      .container {
        width: 95%;
        height: 90vh;
      }
    }

    @media (max-width: 480px) {
      .header {
        flex-direction: column;
        align-items: flex-start;
      }

      .toggle-container {
        width: 100%;
        justify-content: space-between;
      }

      #send-button {
        padding: 10px;
        margin-left: 5px;
      }
    }
  </style>
</head>

<body>
  <div class="container">
    <!-- Header with Toggle Buttons -->
    <div class="header">
      <!-- Toggle Button for Super Smart Mode -->
      <div class="toggle-container">
        <label for="superSmartToggle">Super Smart Mode</label>
        <label class="switch">
          <input type="checkbox" id="superSmartToggle">
          <span class="slider"></span>
        </label>
      </div>

      <!-- Toggle Button for Fast/Smart Model Switching -->
      <div class="toggle-container">
        <label for="modelToggle">Fast Mode</label>
        <label class="switch">
          <input type="checkbox" id="modelToggle">
          <span class="slider"></span>
        </label>
      </div>
    </div>

    <!-- Chat Messages -->
    <div id="chat-container"></div>

    <!-- Typing Indicator -->
    <div id="typing-indicator">Gemini is typing...</div> 

    <!-- Input Area -->
    <div id="input-area">
      <!-- Message Input Row -->
      <div class="message-input-row">
        <textarea id="input-box" placeholder="Enter your message..." rows="1"></textarea>
        <button id="send-button">Send</button>
      </div>
      
      <!-- File Attach Row -->
      <div id="file-attach-row">
        <input type="file" id="file-input" accept=".pdf, image/*, video/*, audio/*">
      </div>

      <!-- Progress Bar -->
      <div id="progress-container">
        <div id="progress-bar"></div>
      </div>
    </div>
  </div>

  <script>
    // List of API keys. Replace these with your actual API keys.
    const API_KEYS = [
      'AIzaSyBdc_A8VxExwO6-0LY1--r2-Ym73lMg-h4',
      'AIzaSyBydeCpaNOIPSk794CpTGnfKrxbjCgJLu4',
      'AIzaSyCQ7tBHtctxlNs61Zm2Y__7KYeDLfz5dms',
      'AIzaSyAip_DFfKNC35MFIorEoNK4y6czP9P65-c'
    ];

    const chatContainer = document.getElementById('chat-container');
    const inputBox = document.getElementById('input-box');
    const sendButton = document.getElementById('send-button');
    const typingIndicator = document.getElementById('typing-indicator');
    const superSmartToggle = document.getElementById('superSmartToggle');
    const modelToggle = document.getElementById('modelToggle');
    const fileInput = document.getElementById('file-input');
    const progressContainer = document.getElementById('progress-container');
    const progressBar = document.getElementById('progress-bar');

    // Initialize messageHistory based on toggles' initial state
    let messageHistory = "";

    // Current model variable
    let currentModel = 'gemini-1.5-pro-exp-0827'; // Default model

    // Event listener for the Super Smart Mode toggle switch
    superSmartToggle.addEventListener('change', () => {
      if (superSmartToggle.checked) {
        messageHistory = "bock bock\n" + messageHistory;
      } else {
        // If disabling, remove "bock bock" from the history
        messageHistory = messageHistory.replace("bock bock\n", "");
      }
    });

    // Event listener for the Fast/Smart Model toggle switch
    modelToggle.addEventListener('change', () => {
      if (modelToggle.checked) {
        currentModel = 'gemini-1.5-flash';
      } else {
        currentModel = 'gemini-1.5-pro-exp-0827';
      }
      console.log(`Model switched to: ${currentModel}`);
    });

    sendButton.addEventListener('click', sendMessage);
    inputBox.addEventListener('keydown', (event) => {
      if (event.key === 'Enter' && !event.shiftKey) {
        event.preventDefault();
        sendMessage();
      }
    });

    /**
     * Fetch with API Key
     * Attempts to fetch a response using the provided API key.
     * @param {string} apiKey - The API key to use for the request.
     * @param {object} payload - The payload to send in the request.
     * @param {string} model - The model to use.
     * @returns {Promise<Object>} - The response data from the API.
     */
    async function fetchWithKey(apiKey, payload, model = currentModel) {
      const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      });

      if (!response.ok) {
        // Extract error message from response
        const errorData = await response.json();
        throw new Error(errorData.error?.message || 'Unknown API error');
      }

      const data = await response.json();
      return data;
    }

    /**
     * Send Message
     * Sends the user's message along with any attached file and handles the bot's response using multiple API keys.
     */
    async function sendMessage() {
      const userMessageText = inputBox.value.trim();
      const file = fileInput.files[0];

      if (userMessageText === '' && !file) return; // Do nothing if no message and no file

      // Display user's message
      const userMessage = document.createElement('div');
      userMessage.classList.add('message', 'user-message');
      userMessage.textContent = userMessageText || (file ? `📁 Attached File: ${file.name}` : '');
      chatContainer.appendChild(userMessage);
      chatContainer.scrollTop = chatContainer.scrollHeight;      
      
      inputBox.value = '';
      fileInput.value = ''; // Reset file input
      typingIndicator.style.display = 'block';
      progressContainer.style.display = file ? 'block' : 'none';
      progressBar.style.width = '0%';

      let botMessageText = '';
      let success = false;

      let fileUri = null;
      let mimeType = null;

      try {
        if (file) {
          // Step 1: Initiate Resumable Upload
          const uploadUrl = await initiateResumableUpload(file);

          // Step 2: Upload File Data
          const fileInfo = await uploadFileData(uploadUrl, file, (progressEvent) => {
            const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            progressBar.style.width = `${percentCompleted}%`;
          });

          // Retrieve file_uri and mime_type
          fileUri = fileInfo.file.uri;
          mimeType = fileInfo.file.mime_type;

          // Hide progress bar after upload
          progressContainer.style.display = 'none';

          // Optionally, display a success message or icon
          const uploadSuccessMessage = document.createElement('div');
          uploadSuccessMessage.classList.add('message', 'bot-message');
          uploadSuccessMessage.textContent = `✅ File uploaded: ${file.name}`;
          chatContainer.appendChild(uploadSuccessMessage);
          chatContainer.scrollTop = chatContainer.scrollHeight;
        }

        // Prepare the prompt based on the current messageHistory and Super smart mode
        // If a file is attached, include it in the prompt
        let prompt = userMessageText;
        if (fileUri) {
          prompt += ` [Attached File: ${file.name}]`;
        }

        // Display a system message indicating content generation
        const systemMessage = document.createElement('div');
        systemMessage.classList.add('message', 'bot-message');
        systemMessage.textContent = `🔍 Generating response...`;
        chatContainer.appendChild(systemMessage);
        chatContainer.scrollTop = chatContainer.scrollHeight;

        // Prepare the payload
        let payload = {};

        if (fileUri) {
          payload = {
            contents: [{
              parts: [
                { text: prompt },
                { file_data: { mime_type: mimeType, file_uri: fileUri } }
              ]
            }],
            "generationConfig": {
              "temperature": 0.5,
              "topK": 64,
              "topP": 0.95,
              "maxOutputTokens": 8192,
              "responseMimeType": "text/plain"
            }
          };
        } else {
          payload = {
            contents: [{
              parts: [
                { text: prompt }
              ]
            }],
            "generationConfig": {
              "temperature": 0.5,
              "topK": 64,
              "topP": 0.95,
              "maxOutputTokens": 8192,
              "responseMimeType": "text/plain"
            }
          };
        }

        // Loop through API keys to find a successful response
        for (const apiKey of API_KEYS) {
          try {
            const data = await fetchWithKey(apiKey, payload); // Add user message and file if any

            const fullResponse = data?.candidates[0]?.content?.parts[0]?.text; // Optional chaining

            if (!fullResponse) {
              throw new Error("Invalid response format: Missing content."); // Better error handling
            }

            if (superSmartToggle.checked) {
              // Parse response between <final_answer> and </final_answer>
              const finalAnswerStartIndex = fullResponse.indexOf("<final_answer>");
              const finalAnswerEndIndex = fullResponse.indexOf("</final_answer>");

              if (finalAnswerStartIndex !== -1 && finalAnswerEndIndex !== -1) {
                botMessageText = fullResponse.substring(finalAnswerStartIndex + "<final_answer>".length, finalAnswerEndIndex).trim();
              } else {
                botMessageText = "Error: Could not extract final answer. Invalid response format.";
                console.error("Final answer tags not found in response:", fullResponse);
              }
            } else {
              // When Super smart mode is off, use the entire response
              botMessageText = fullResponse.trim();
            }

            if (botMessageText) {
              // Update history *after* successful response
              messageHistory += `Gemini (${currentModel}): ${botMessageText}\n`;
            }

            success = true;
            break; 
          } catch (error) {
            console.error(`Error with API key:`, error.message);
          }
        }

        if (success) {
          const botMessage = document.createElement('div');
          botMessage.classList.add('message', 'bot-message');
          botMessage.textContent = botMessageText;
          chatContainer.appendChild(botMessage);
          chatContainer.scrollTop = chatContainer.scrollHeight;
        } else {
          const botErrorMessage = document.createElement('div');
          botErrorMessage.classList.add('message', 'bot-message');
          botErrorMessage.textContent = "❌ I'm sorry, I'm currently unable to process your request. Please try again later.";
          chatContainer.appendChild(botErrorMessage);
          chatContainer.scrollTop = chatContainer.scrollHeight;
        }

      } catch (error) {
        console.error("Error in sendMessage:", error);
        const botErrorMessage = document.createElement('div');
        botErrorMessage.classList.add('message', 'bot-message');
        botErrorMessage.textContent = `❌ Error: ${error.message}`;
        chatContainer.appendChild(botErrorMessage);
        chatContainer.scrollTop = chatContainer.scrollHeight;
      } finally {
        typingIndicator.style.display = 'none';
        progressContainer.style.display = 'none';
        progressBar.style.width = '0%';
      }
    }

    /**
     * Initiate Resumable Upload
     * Initiates the resumable upload session and retrieves the upload URL.
     * @param {File} file - The file to upload.
     * @returns {Promise<string>} - The resumable upload URL.
     */
    async function initiateResumableUpload(file) {
      const apiKey = selectAPIKey();
      const baseUrl = "https://generativelanguage.googleapis.com";

      const uploadMetadata = {
        file: {
          display_name: file.name,
          mime_type: file.type
        }
      };

      const response = await fetch(`${baseUrl}/upload/v1beta/files?key=${apiKey}`, {
        method: 'POST',
        headers: {
          'X-Goog-Upload-Protocol': 'resumable',
          'X-Goog-Upload-Command': 'start',
          'X-Goog-Upload-Header-Content-Length': file.size,
          'X-Goog-Upload-Header-Content-Type': file.type,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(uploadMetadata)
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.error?.message || 'Failed to initiate upload.');
      }

      const uploadUrl = response.headers.get('X-Goog-Upload-Url');
      if (!uploadUrl) {
        throw new Error('Upload URL not found in response headers.');
      }

      return uploadUrl;
    }

    /**
     * Upload File Data
     * Uploads the file data to the provided upload URL.
     * @param {string} uploadUrl - The resumable upload URL.
     * @param {File} file - The file to upload.
     * @param {function} onProgress - Callback for progress updates.
     * @returns {Promise<Object>} - The response JSON containing file information.
     */
    function uploadFileData(uploadUrl, file, onProgress) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('PUT', uploadUrl, true);
        xhr.setRequestHeader('Content-Length', file.size);
        xhr.setRequestHeader('X-Goog-Upload-Offset', '0');
        xhr.setRequestHeader('X-Goog-Upload-Command', 'upload, finalize');
        xhr.setRequestHeader('Content-Type', file.type);

        xhr.upload.onprogress = onProgress;

        xhr.onload = function () {
          if (xhr.status >= 200 && xhr.status < 300) {
            try {
              const responseJson = JSON.parse(xhr.responseText);
              resolve(responseJson);
            } catch (e) {
              reject(new Error('Failed to parse upload response.'));
            }
          } else {
            try {
              const errorData = JSON.parse(xhr.responseText);
              reject(new Error(errorData.error?.message || 'Failed to upload file data.'));
            } catch (e) {
              reject(new Error('Failed to upload file data.'));
            }
          }
        };

        xhr.onerror = function () {
          reject(new Error('Network error during file upload.'));
        };

        xhr.send(file);
      });
    }

    /**
     * Select API Key
     * Selects an API key from the list. This can be enhanced to implement better key rotation strategies.
     * @returns {string} - The selected API key.
     */
    function selectAPIKey() {
      // Simple round-robin strategy
      const apiKey = API_KEYS.shift();
      API_KEYS.push(apiKey);
      return apiKey;
    }
  </script>
</body>
</html>