Пожалуйста, сформируй полный HTML-код (ничего не пропускай), выделив его обратными тройными кавычками, для следующего запроса: "Внеси правки, но ничего не сломай: При генерации историй появляется загрузка, но она исчезает до полной загрузки картинки. Нужно, чтобы загрузка исчезала после полной загрузки картинки.". В прошлой итерации код выглядел следующим образом: "<!DOCTYPE html>
<html lang="ru">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  <title>AI Stories</title>
  <style>
    /* Reset and basic styles */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body,
    html {
      width: 100%;
      height: 100%;
      font-family: 'Arial', sans-serif;
      background-color: #f0f4f8;
      color: #333;
      overflow: hidden;
    }

    /* Language Switcher */
    .language-switcher {
      position: fixed;
      top: 20px;
      right: 20px;
      display: flex;
      gap: 10px;
      z-index: 1000;
    }

    .language-switcher button {
      background: #fff;
      border: 1px solid #ccc;
      border-radius: 5px;
      padding: 5px 10px;
      cursor: pointer;
      transition: background 0.3s;
    }

    .language-switcher button.active {
      background: #007bff;
      color: #fff;
      border-color: #007bff;
    }

    /* Home Button */
    #home-button {
      position: fixed;
      top: 20px;
      left: 20px;
      background: #007bff;
      border: 1px solid #007bff;
      border-radius: 5px;
      padding: 5px 10px;
      font-size: 0.9em;
      color: #fff;
      cursor: pointer;
      transition: background-color 0.3s;
    }

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

    /* Main Section */
    .main-section,
    .story-section {
      display: none;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
      width: 100%;
      padding: 20px;
      text-align: center;
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
      position: relative;
    }

    .main-section.active,
    .story-section.active {
      display: flex;
    }

    .main-section h1 {
      font-size: 3em;
      margin-bottom: 20px;
      color: #007bff;
    }

    .input-container {
      position: relative;
      width: 100%;
      max-width: 500px;
      margin-bottom: 20px;
    }

    .input-container input {
      width: 100%;
      padding: 15px;
      border: 2px solid #ccc;
      border-radius: 5px;
      font-size: 1em;
      transition: border-color 0.3s;
    }

    .input-container input:focus {
      border-color: #007bff;
      outline: none;
    }

    .main-section button,
    .story-section button {
      padding: 15px 30px;
      font-size: 1em;
      color: #fff;
      background-color: #007bff;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      transition: background-color 0.3s;
    }

    .main-section button:hover,
    .story-section button:hover {
      background-color: #0056b3;
    }

    /* Loading Animation */
    .loading-overlay {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(240, 244, 248, 0.9);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      z-index: 1001;
      display: none;
    }

    .loading-overlay.active {
      display: flex;
    }

    .spinner {
      border: 8px solid #f3f3f3;
      border-top: 8px solid #007bff;
      border-radius: 50%;
      width: 60px;
      height: 60px;
      animation: spin 1s linear infinite;
      margin-bottom: 20px;
    }

    @keyframes spin {
      0% {
        transform: rotate(0deg);
      }

      100% {
        transform: rotate(360deg);
      }
    }

    .loading-overlay p {
      font-size: 1.2em;
      color: #333;
    }

    /* Story Section */
    .story-text {
      max-width: 900px;
      background: rgba(255, 255, 255, 0.8);
      padding: 20px;
      border-radius: 10px;
      font-size: 1.2em;
      line-height: 1.6;
      text-align: left;
      animation: fadeIn 1s forwards;
      opacity: 0;
      overflow-y: auto;
      max-height: 70vh;
      scrollbar-width: thin;
      scrollbar-color: #007bff #f0f4f8;
    }

    .story-text::-webkit-scrollbar {
      width: 8px;
    }

    .story-text::-webkit-scrollbar-track {
      background: #f0f4f8;
    }

    .story-text::-webkit-scrollbar-thumb {
      background-color: #007bff;
      border-radius: 10px;
      border: 2px solid #f0f4f8;
    }

    @keyframes fadeIn {
      to {
        opacity: 1;
      }
    }

    .story-section .input-container {
      margin-top: 20px;
      display: flex;
      gap: 10px;
    }

    /* Background Image */
    .story-section::before,
    .main-section::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      z-index: 0;
    }

    .story-section > *,
    .main-section > * {
      position: relative;
      z-index: 1;
    }

    /* Modal */
    .modal {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      display: none;
      align-items: center;
      justify-content: center;
      z-index: 1002;
    }

    .modal.active {
      display: flex;
    }

    .modal-content {
      background: #fff;
      padding: 30px;
      border-radius: 10px;
      text-align: center;
      max-width: 400px;
      width: 90%;
    }

    .modal-content p {
      margin-bottom: 20px;
      font-size: 1.1em;
    }

    .modal-content button {
      padding: 10px 20px;
      margin: 0 10px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-size: 1em;
      transition: background-color 0.3s;
    }

    .modal-content .confirm {
      background-color: #007bff;
      color: #fff;
    }

    .modal-content .confirm:hover {
      background-color: #0056b3;
    }

    .modal-content .cancel {
      background-color: #ccc;
      color: #333;
    }

    .modal-content .cancel:hover {
      background-color: #999;
    }

    /* Responsive Design */
    @media (max-width: 600px) {
      .main-section h1 {
        font-size: 2em;
      }

      .input-container input {
        padding: 10px;
        font-size: 0.9em;
      }

      .main-section button,
      .story-section button {
        padding: 10px 20px;
        font-size: 0.9em;
      }

      .story-text {
        font-size: 1em;
        padding: 15px;
      }
    }
  </style>
</head>

<body>
  <!-- Language Switcher -->
  <div class="language-switcher">
    <button id="lang-ru" class="active">RU</button>
    <button id="lang-en">EN</button>
  </div>

  <!-- Main Section -->
  <section class="main-section active" id="main-section">
    <h1 data-translate="appTitle">AI Stories</h1>
    <div class="input-container">
      <input type="text" id="story-input" placeholder="Введите начало истории" autocomplete="off" />
    </div>
    <button id="start-story-button" data-translate="startButton">Начать историю</button>
  </section>

  <!-- Story Section -->
  <section class="story-section" id="story-section">
    <div class="story-text" id="story-text"></div>
    <button id="home-button" data-translate="homeButton">Домой</button>
    <div class="input-container" id="continue-container" style="display: none;">
      <input type="text" id="continue-input" placeholder="Сюжетный поворот?" autocomplete="off" />
      <button id="continue-story-button" data-translate="continueButton">Продолжить</button>
    </div>
  </section>

  <!-- Loading Overlay -->
  <div class="loading-overlay" id="loading-overlay">
    <div class="spinner"></div>
    <p id="loading-text">Загрузка...</p>
  </div>

  <!-- Modal -->
  <div class="modal" id="modal">
    <div class="modal-content">
      <p data-translate="modalQuestion">Вы уверены, что хотите вернуться на главную?</p>
      <button class="confirm" id="modal-confirm" data-translate="confirm">Да</button>
      <button class="cancel" id="modal-cancel" data-translate="cancel">Нет</button>
    </div>
  </div>

  <script>
    // Translation Dictionary
    const translations = {
      "appTitle": {
        "ru": "AI Stories",
        "en": "AI Stories"
      },
      "startButton": {
        "ru": "Начать историю",
        "en": "Start Story"
      },
      "continueButton": {
        "ru": "Продолжить",
        "en": "Continue"
      },
      "homeButton": {
        "ru": "Домой",
        "en": "Home"
      },
      "modalQuestion": {
        "ru": "Вы уверены, что хотите вернуться на главную?",
        "en": "Are you sure you want to return to the main page?"
      },
      "confirm": {
        "ru": "Да",
        "en": "Yes"
      },
      "cancel": {
        "ru": "Нет",
        "en": "No"
      },
      "storyPlaceholderRu": "Введите начало истории",
      "storyPlaceholderEn": "Enter the beginning of the story",
      "plotTwistPlaceholderRu": "Сюжетный поворот?",
      "plotTwistPlaceholderEn": "Plot twist?"
    };

    let currentLanguage = 'ru';
    let storyHistory = '';
    let imageGenerated = false;
    let imageUrl = '';
    let textSpeed = 50; // milliseconds per character

    // Language Switcher
    const langRuButton = document.getElementById('lang-ru');
    const langEnButton = document.getElementById('lang-en');

    langRuButton.addEventListener('click', () => switchLanguage('ru'));
    langEnButton.addEventListener('click', () => switchLanguage('en'));

    function switchLanguage(lang) {
      currentLanguage = lang;
      document.querySelectorAll('[data-translate]').forEach(elem => {
        const key = elem.getAttribute('data-translate');
        if (translations[key] && translations[key][lang]) {
          elem.textContent = translations[key][lang];
        }
      });
      // Update placeholders
      const storyInput = document.getElementById('story-input');
      const continueInput = document.getElementById('continue-input');
      if (currentLanguage === 'ru') {
        storyInput.placeholder = translations['storyPlaceholderRu'];
        continueInput.placeholder = translations['plotTwistPlaceholderRu'];
      } else {
        storyInput.placeholder = translations['storyPlaceholderEn'];
        continueInput.placeholder = translations['plotTwistPlaceholderEn'];
      }
      // Toggle active button
      if (lang === 'ru') {
        langRuButton.classList.add('active');
        langEnButton.classList.remove('active');
      } else {
        langEnButton.classList.add('active');
        langRuButton.classList.remove('active');
      }
    }

    // Generate random background image URL
    function getRandomBackground() {
      const randomNum = Math.floor(Math.random() * 10) + 1;
      return `https://file.garden/ZqyI0H6Iv3i3b0Sn/ai-stories/main/main-bg-${randomNum}.jpg`;
    }

    function setMainBackgroundImage() {
      const mainSection = document.getElementById('main-section');
      const imageUrl = getRandomBackground();

      const img = new Image();
      img.onload = () => {
        mainSection.style.backgroundImage = `url('${imageUrl}')`;
        hideLoading();
        startPreloaderTimeout();
      };
      img.onerror = () => {
        hideLoading();
        startPreloaderTimeout();
      };
      img.src = imageUrl;
    }

    function startPreloaderTimeout() {
      setTimeout(hideLoading, 30000);
    }

    document.addEventListener('DOMContentLoaded', () => {
      showLoading();
      setMainBackgroundImage();
    });

    // Event Delegation for Buttons
    document.getElementById('start-story-button').addEventListener('click', startStory);
    document.getElementById('home-button').addEventListener('click', () => showModal(true));
    document.getElementById('modal-confirm').addEventListener('click', () => {
      hideModal();
      returnToMain();
    });
    document.getElementById('modal-cancel').addEventListener('click', hideModal);
    document.getElementById('continue-story-button').addEventListener('click', continueStory);

    // Input Enter Key Handling
    document.getElementById('story-input').addEventListener('keydown', function(e) {
      if (e.key === 'Enter') startStory();
    });

    document.getElementById('continue-input').addEventListener('keydown', function(e) {
      if (e.key === 'Enter') continueStory();
    });

    // Show Modal Function
    function showModal() {
      document.getElementById('modal').classList.add('active');
    }

    function hideModal() {
      document.getElementById('modal').classList.remove('active');
    }

    // Return to Main Function
    function returnToMain() {
      document.getElementById('story-section').classList.remove('active');
      document.getElementById('main-section').classList.add('active');
      storyHistory = '';
      imageGenerated = false;
      imageUrl = '';
      document.getElementById('story-text').innerHTML = '';
      document.getElementById('story-section').style.backgroundImage = '';
      document.getElementById('continue-container').style.display = 'none';
      document.getElementById('story-input').value = '';
      document.getElementById('continue-input').value = '';
      showLoading();
      setMainBackgroundImage();
    }

    // Start Story Function
    function startStory() {
      const input = document.getElementById('story-input').value.trim();
      if (input === '') {
        storyHistory = generateStoryPrompt();
      } else {
        storyHistory = input;
      }
      document.getElementById('story-input').value = ''; // clear input field
      initiateStoryProcessing(input);
    }

    // Continue Story Function
    function continueStory() {
      const input = document.getElementById('continue-input').value.trim();
      document.getElementById('continue-input').value = ''; // clear input field
      document.getElementById('continue-container').style.display = 'none';
      initiateStoryProcessing(input, true);
    }

    // Generate Story Prompt if Empty
    function generateStoryPrompt() {
      const prompts = {
        "ru": "Начало новой захватывающей истории",
        "en": "The beginning of an exciting new story"
      };
      return currentLanguage === 'ru' ? prompts.ru : prompts.en;
    }

    // Initiate Story Processing
    async function initiateStoryProcessing(inputText, toContinue = false) {
      showLoading(currentLanguage === 'ru' ? 'Загрузка истории...' : 'Loading the history...');
      try {
        // First Request: Generate Story Text with retries
        const storyText = await fetchWithRetries(() => requestStory(inputText, storyHistory, currentLanguage, toContinue), 5, 'story');
        if (toContinue) {
          storyHistory += ` ${storyText}`;
        } else {
          storyHistory = storyText;
        }
        // Second Request: Generate Description in English
        const description = await requestDescription(storyText);
        // Third Request: Generate Image
        const generatedImageUrl = await requestImage(description);
        if (generatedImageUrl) {
          imageUrl = generatedImageUrl;
          imageGenerated = true;
        } else {
          imageGenerated = false;
        }
        // Update Story Section
        updateStorySection(storyText);
      } catch (error) {
        showError(error);
      } finally {
        hideLoading();
      }
    }

    // Fetch with Retries
    function fetchWithRetries(fetchFunction, retries, type) {
      return new Promise((resolve, reject) => {
        const attempt = (n) => {
          fetchFunction().then(resolve).catch((err) => {
            if (n > 0 && type === 'story') {
              attempt(n - 1);
            } else {
              reject(err);
            }
          });
        };
        attempt(retries);
      });
    }

    // Request Story Function
    function requestStory(prompt, storyHistory, lang, toContinue = false) {
      return new Promise((resolve, reject) => {
        const fullPrompt = toContinue ? 
          `Продолжи незаконченную историю с того же места, где она остановилась (не повторяй заново) длиной приблизительно 400 символов на языке "${lang}" с учетом запроса: "${prompt}". История: "${storyHistory}"` 
          : `Придумай незаконченную историю длиной приблизительно 400 символов на языке "${lang}" с учетом запроса: "${prompt}"`;
        requestAI(fullPrompt, {
          responseCallback: ({ message }) => {
            resolve(message);
          },
          errorCallback: ({ message }) => {
            reject(message);
          },
        });
      });
    }

    // Request Description Function
    function requestDescription(text) {
      return new Promise((resolve, reject) => {
        const prompt = `Come up with a short description in English, about 10 words long or less, that describes the query: "${text}"`;
        requestAI(prompt, {
          responseCallback: ({ message }) => {
            resolve(message);
          },
          errorCallback: () => {
            resolve(null); // Continue without image
          },
        });
      });
    }

    // Request Image Function
    function requestImage(description) {
      if (!description) return Promise.resolve(null);
      return new Promise((resolve, reject) => {
        requestAI(description, {
          type: 'image',
          responseCallback: ({ image }) => {
            const img = new Image();
            img.src = image;
            img.onload = () => {
              resolve(image);
            };
            img.onerror = () => {
              resolve(null); // Continue without image
            };
          },
          errorCallback: () => {
            resolve(null); // Continue without image
          },
        });
      });
    }

    // Update Story Section
    function updateStorySection(text = storyHistory) {
      document.getElementById('main-section').classList.remove('active');
      const storySection = document.getElementById('story-section');
      storySection.classList.add('active');
      if (imageGenerated) {
        storySection.style.backgroundImage = `url('${imageUrl}')`;
        storySection.style.opacity = 1;
      } else {
        storySection.style.backgroundColor = '#a8d0e6';
        storySection.style.opacity = 1;
      }
      // Wait for the image to be fully loaded
      if (imageGenerated) {
        const img = new Image();
        img.src = imageUrl;
        img.onload = () => {
          animateText(text);
        };
      } else {
        animateText(text);
      }
    }

    // Animate Text Function
    function animateText(text) {
      const storyTextElement = document.getElementById('story-text');
      storyTextElement.innerHTML = '';
      let index = 0;

      function type() {
        if (index < text.length) {
          storyTextElement.innerHTML += text.charAt(index);
          index++;
          setTimeout(type, textSpeed);
        } else {
          if (document.getElementById('story-section').classList.contains('active')) {
            document.getElementById('continue-container').style.display = 'flex';
          }
        }
      }

      type();
    }

    // Show Loading
    function showLoading(text) {
      text = text || currentLanguage === 'ru' ? 'Загрузка...' : 'Loading...'

      document.getElementById('loading-text').textContent = text;
      document.getElementById('loading-overlay').classList.add('active');
    }

    // Hide Loading
    function hideLoading() {
      document.getElementById('loading-overlay').classList.remove('active');
    }

    // Show Error Notification
    function showError(message) {
      console.log(message);
      alert(currentLanguage === 'ru' ? 'Произошла ошибка при создании истории.' : 'An error occurred while creating the story.');
    }

    function requestAI(prompt, {
      url = 'https://nexra.aryahcr.cc/api/chat/complements',
      model = 'gpt-4o',
      stream = false,
      markdown = false,
      type = 'text',
      messages = [], // Бывают roles: system, user, assistant
      responseCallback = () => { }, // Колбек ответа от сервера вне зависимости от стриминга
      successCallback = () => { }, // Колбек для успешного завершения
      errorCallback = () => { }, // Колбек ошибки
    } = {}) {
      if (type === 'text') { // Текст
        messages.push({ role: 'user', content: prompt });

        let body = {
          messages,
          model,
          stream,
          markdown,
        };

        if (url.indexOf('/gptweb') !== -1) {
          body = {
            prompt,
            markdown,
          };
        }

        if (messages.length > 1 && model === 'llama-3.1') {
          body.messages = [{ role: 'user', content: JSON.stringify({ messages: messages }) }];
        }

        if (model === 'Bing') {
          body['conversation_style'] = 'balanced';
        }

        if (model === 'blackbox') {
          body['websearch'] = false;
        }

        fetch(url, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(body),
        }).then(response => response.text()).then((data) => {
          const modData = JSON.parse(data.slice(data.indexOf('{')));
          const message = modData.message || modData.gpt;

          responseCallback({ data, modData, message, isStream: stream, isStreaming: false });
          successCallback({ data, modData, message, isStream: stream, isStreaming: false });
        }).catch((error) => {
          errorCallback({ message: `Ошибка в функции requestAI (type: text, stream: false): ${error}`, error });
        });
      } else if (type === 'image') { // Картинка
        model = 'emi';

        fetch("https://nexra.aryahcr.cc/api/image/complements", {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify({
            prompt,
            model,
            //response: "base64"
          })
        }).then((response) => {
          response.text().then((data) => {
            const modData = JSON.parse(data.slice(data.indexOf('{')));
            const images = modData.images;
            const imageNode = document.createElement('img');
            imageNode.className = 'image';
            imageNode.src = images[0];

            responseCallback({ data, modData, images, image: images[0], imageNode });
            successCallback({ data, modData, images, image: images[0], imageNode });
          }).catch((err) => {
            errorCallback({ message: `Ошибка в функции requestAI (type: image): ${err}`, err });
          });
        }).catch((err) => {
          errorCallback({ message: `Ошибка в функции requestAI (type: image): ${err}`, err });
        });
      }
    }

    // Initial Language Setup
    switchLanguage('ru');
  </script>

</body>

</html>". Запрос прошлой итерации был таким: "Сейчас есть проблема: Прелоадер в любом случае исчезает через 30 секунд, но при загрузки секции истории отсчет 30 секунд должен начаться только после того, как будет получена фоновая картинка, а не с самого начала. Потому что нужно ждать ответы на запросы от нейросетей, а генерация картинки происходит позже. Это 30 секунд были задуманы как раз для того, чтобы подстраховаться, если картинка не загрузится за это время".