CatWar UwU

Визуальное обновление CatWar'а, и не только...

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         CatWar UwU
// @namespace    http://tampermonkey.net/
// @version      v1.32.0-10.24
// @description  Визуальное обновление CatWar'а, и не только...
// @author       Ibirtem / Затменная ( https://catwar.net/cat1477928 )
// @copyright    2024, Ibirtem (https://openuserjs.org/users/Ibirtem)
// @supportURL   https://catwar.net/cat1477928
// @homepageURL  https://openuserjs.org/scripts/Ibirtem/CatWar_UwU
// @match        http*://*.catwar.net/*
// @license      MIT
// @iconURL      https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/partly_sunny_rain.png
// ==/UserScript==

"use strict"; // Делаю вид что крутой.

// ====================================================================================================================
//   . . . DEFAULT НАСТРОЙКИ . . .
// ====================================================================================================================
const current_uwu_version = "1.32.0";
// ✨🦐✨🦐✨
const uwuDefaultSettings = {
  settingsTheme: "dark",

  weatherEnabled: false,
  weatherDrops: false,
  lowPerformanceMode: false,
  minecraftStyle: false,
  alwaysDay: false,
  manualWeatherPanel: false,
  skyInHeader: false,
  auroraPos: "1",

  backgroundRepeat: false,
  backgroundUser: false,
  backgroundUserImageURL: "",
  gameFieldBackgroundUser: false,
  gameFieldBackgroundUserImageURL: "",
  userTheme: false,
  showOtherCatsList: "2",
  commentsAvatars: false,

  chatHeight: "275",
  newChat: false,
  reverseChat: false, 
  newChatInput: false,
  namesForNotification: "",

  notificationPM: false,
  notificationActionEnd: false,
  notificationInMouth: false,
  notificationInFightMode: false,
  showHintWhenToSniff: false,
  duplicateTimeInBrowserTab: false,


  cellsBorders: false,
  cellsBordersThickness: "1",
  cellsBordersColor: "#ffffff",
  cellsNumbers: false,
  fastStyles: false,
  displayParametersPercentages: false,
  compactMouth: false,
  showMoreCatInfo: false,
  showParametersDetails: false,

  draggingFightPanel: false,
  compactFightLog: false,
  fightPanelAdjustableHeight: false,
  fightPanelHeight: "70",
  fightTeams: false,
  fightTeamsColors: {
    team1: ["#41cd70", "#cd4141"],
    team2: ["#c968ff", "#cd4141"],
    team3: ["#44bcff", "#cd4141"],
    team4: ["#FFFF00", "#cd4141"],
  },
  fightTeamsPanelHight: "100",

  highlightResources: false,
  highlightResourcesStyle: "background",

  showClock: false,
  clockStyle: "compact",
  clockFontSize: "14",
  clockPosition: "fly",

  describeHuntingSmell: false,
  huntingVirtualJoystick: false,
  sizeHuntingVirtualJoystick: "150",

  climbingPanel: false,
  climbingPanelOrientation: "vertical",
  climbingNotificationsNumbers: false,
  climbingRefreshNotification: false,
  climbingRefreshNotificationSound: "notificationSound1",
  climbingRefreshNotificationVolume: "5",

  myNameNotificationSound: "notificationSound2",
  notificationMyNameVolume: "5",

  userQuickLinks: "",
  historyHeight: "215",

  parametersColors: {
    dream: ["#008000", "#008000", "#ff0000", "#ff0000"],
    hunger: ["#008000", "#008000", "#ff0000", "#ff0000"],
    thirst: ["#008000", "#008000", "#ff0000", "#ff0000"],
    need: ["#008000", "#008000", "#ff0000", "#ff0000"],
    health: ["#008000", "#008000", "#ff0000", "#ff0000"],
    clean: ["#008000", "#008000", "#ff0000", "#ff0000"],

    smell: ["#008000", "#008000", "#cccccc", "#cccccc"],
    dig: ["#008000", "#008000", "#cccccc", "#cccccc"],
    swim: ["#008000", "#008000", "#cccccc", "#cccccc"],
    might: ["#008000", "#008000", "#cccccc", "#cccccc"],
    tree: ["#008000", "#008000", "#cccccc", "#cccccc"],
    observ: ["#008000", "#008000", "#cccccc", "#cccccc"],

    other: ["#008000", "#008000", "#cccccc", "#cccccc"],
  },
  parametersBackgroundImage: false,
  parametersUserBackgroundImage: false,
  parametersUserBackgroundImageURL: "",

  restoreBlogCreation: false,
  moreBBCodes: false,
  commentPreview: false,
  moreCommentButtons: false,
  lsWrapPreview: false,
  calculators: false,

  extendedSettingsPanel: false,
  showUpdateNotification: false,
  showSplashScreens: false,
  extendedHints: true,
  GMbetaTest: false,
};

// ====================================================================================================================
//   . . . ТАРГЕТНЫЕ ССЫЛКИ . . .
// ====================================================================================================================
const targetSettings = /^https:\/\/catwar\.net\/settings/;
const targetCW3 = "https://catwar.net/cw3/";
const targetCW3Hunt = "https://catwar.net/cw3/jagd";
const targetMainProfile = /^https:\/\/catwar\.net\/$/;
const targetProfile = /^https:\/\/catwar\.net\/cat\d+$/;
const targetLs = /^https:\/\/catwar\.net\/ls/;
const targetLsNew = /^https:\/\/catwar\.net\/ls\?new(=.*)?$/;
const targetChats = /^https:\/\/catwar\.net\/chat/;
const targetBlog = /^https:\/\/catwar\.net\/(?:blog\d+|blogs)(?:$|[/?#])/i;
const targetBlogsCreation = /^https:\/\/catwar\.net\/blogs\?creation/;
const targetSniff = /^https:\/\/catwar\.net\/sniff(?:\d+|)(?:$|[/?#])/i;
const targetSniffCreation = /^https:\/\/catwar\.net\/sniff\?creation/;

// ====================================================================================================================
//   . . . СТАНДАРТНЫЕ ЦВЕТОВЫЕ ТЕМЫ . . .
// ====================================================================================================================
const defaultThemes = {
  "Тёмная Тема": {
    colors: {
      backgroundColor: "#161616",
      blocksColor: "#242424",
      chatColor: "#242424",
      textColor: "#d5d5d5",
      catTooltipBackground: "#242424",
      fightPanelBackground: "#242424",
      linkColor: "#d5d5d5",
      accentColor1: "#111111",
      accentColor2: "#2e2e2e82",
      accentColor3: "#fc872a",
      moveNameColor: "#d5d5d5",
      moveNameBackground: "#242424",
    },
  },
};

// ====================================================================================================================
//   . . . HTML ПАНЕЛЬ НАСТРОЕК . . .
// ====================================================================================================================
const uwusettings = // html
`
<div id="uwusettings">

  <div id="uwusettings-header">
    <div id="uwusettings-header-glass">
      <div class="main-settings-container">
        <div id="settingsTheme" class="custom-select">
          <label for="settingsTheme">Тема настроек:</label>
          <div class="select-selected">Классическая</div>
          <div class="select-items">
            <!-- Опции будут добавлены сюда -->
          </div>
        </div>

          <h1>Настройки CatWar UwU</h1>
        <div class="link-container" title="ВК Группа по Скрипту/Моду.">
          <a href="https://vk.com/catwar_uwu" target="_blank" rel="noopener noreferrer">
            <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/VK_logo.png" alt="Иконка" width="36" height="36">
          </a>
        </div>
      </div>

      <hr id="uwu-hr" class="uwu-hr-head">
      <div id="button-container">
        <button id="effects-button" class="active">
          <h2>
            Природные эффекты
            <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/partly_sunny_rain.png" alt="Иконка"
              width="24" height="24" />
          </h2>
        </button>
        <button id="theme-button">
          <h2>
            Оформление
            <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/sparkles.png" alt="Иконка" width="24"
              height="24" />
          </h2>
        </button>
        <button id="utility-button">
          <h2>
            Инструментарий
            <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/flashlight.png" alt="Иконка" width="24"
              height="24" />
          </h2>
        </button>
        <button id="modules-button">
          <h2>
            Надстройки
            <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/construction.png" alt="Иконка" width="24"
              height="24" />
          </h2>
        </button>
      </div>
      <hr id="uwu-hr" class="uwu-hr-head">
    </div>
  </div>

  <div id="uwusettings-main">
    <div id="effects-panel">

    <h2>Природа и окружение</h2>

      <div>
        <p>
          Включает генерацию Динамичной погоды в Игровой, такие как дождь, снегопады или Северные Сияния.
        </p>
        <input type="checkbox" id="weather-enabled" data-setting="weatherEnabled" />
        <label for="weather-enabled">Показывать природные эффекты</label>
      </div>

      <div>
        <p>
        Сокращает количество частиц динамичной погоды, увеличивая тем самым производительность на слабых устройствах.
        </p>
      <input type="checkbox" id="low-Performance-Mode" data-setting="lowPerformanceMode" />
      <label for="low-Performance-Mode">Режим низкой производительности</label>
      </div>

      <div>
        <p>Может немного повлиять на производительность из-за возрастания количества частиц на экране.</p>
        <input type="checkbox" id="weather-drops" data-setting="weatherDrops" />
        <label for="weather-drops">Эффекты приземления частиц</label>
      </div>

      <div>
        <p>Замена стандартных частиц на знакомые всеми пиксельные частицы.</p>
        <input type="checkbox" id="minecraft-style" data-setting="minecraftStyle" />
        <label for="minecraft-style-enabled">Minecraft частицы</label>
      </div>

      <div>
        <p>Убирает затемнение Игрового поля.</p>
        <input type="checkbox" id="always-day" data-setting="alwaysDay" />
        <label for="always-day">Всегда день/ярко</label>
      </div>

      <div>
        <p>Отображает панель Ручного управления погодой в ⚙️Панели Расширенных Настройках Игровой. Выключает натуральную генерацию погоды.</p>
        <input type="checkbox" id="manual-Weather-Panel" data-setting="manualWeatherPanel" />
        <label for="manual-Weather-Panel">Ручное управление погоды</label>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <p>Расположение Северного Сияния</p>
      <div id="auroraPanel">
        <input type="range" min="1" max="2" value="1" class="uwu-range-slider" id="aurora-pos" list="auroraStep"
          data-setting="auroraPos">
        <datalist id="auroraStep">
          <option value="1">Верх</option>
          <option value="2">Низ</option>
        </datalist>
      </div>

      <div>
        <p>Делает небо шапкой страницы, пряча под игровую, а так же по факту чинит его потерю при Редизайне игровой. Будет
          выглядеть не очень на широкоформатных мониторах из-за растягивания изображения.</p>
        <input type="checkbox" id="sky-in-the-sky" data-setting="skyInHeader" />
        <label for="sky-in-the-sky">Небо в небе.</label>
      </div>

    </div>

    <div id="theme-panel">

    <h2>Поле Игровой</h2>

    <div>
      <p> Заменяет все фоны игровых локаций на выбранный вами фон. Помните, что для правильного отображения нужно изображение 1000х1000 px.</p>
      <input type="checkbox" id="game-Field-background-User" data-setting="gameFieldBackgroundUser" />
      <label for="game-Field-background-User-enabled">Статичный фон локации:</label>
      <input type="text" id="gameFieldSettingImageURLField" placeholder="Вставьте URL" data-setting="gameFieldBackgroundUserImageURL" />
      <button id="SettingSaveButton1" class="uwu-button install-button">Сохранить</button>
    </div>

    <div>
      <p>Отрисовывает границы клеток Игрового поля.</p>
      <input type="checkbox" id="cells-Borders" data-setting="cellsBorders" />
      <label for="cells-Borders">Границы клеток</label>
    </div>
    <p>Толщина/Яркость границ</p>
    <div id="step-slider">
      <input type="range" min="1" max="9" value="1" id="cells-Borders-Thickness" class="uwu-range-slider" list="ThicknessStep" data-setting="cellsBordersThickness">
      <datalist id="ThicknessStep">
      <option value="1">0.1</option>
      <option value="5">0.5</option>
      <option value="9">0.9</option>
      </datalist>
    </div>
    <div>
      <label for="cells-Borders-Color">Цвет границы клеток</label>
      <input type="color" id="cells-Borders-Color" data-setting="cellsBordersColor" value="#ffffff">
    </div>
    
    <div>
    <p>Обозначает клетки Игрового поля числами.</p>
      <input type="checkbox" id="cells-Numbers" data-setting="cellsNumbers" />
      <label for="cells-Numbers">Нумерация клеток</label>
    </div>

      <div>
        <p>
          Ставит на страницу фон, повторяющий фон Игровой локации, а так же
          размывает и затемняет его.
        </p>
        <input type="checkbox" id="background-repeat" data-setting="backgroundRepeat" />
        <label for="weather-enabled">Фон страницы из локации</label>
      </div>

      <div>
        <p>Ставит на страницу фон из предоставленной ссылки.</p>
        <input type="checkbox" id="background-user" data-setting="backgroundUser" />
        <label for="background-user-enabled">Свой фон страницы:</label>
        <input type="text" id="SettingImageURLField" placeholder="Вставьте URL" data-setting="backgroundUserImageURL" />
        <button id="SettingSaveButton1" class="uwu-button install-button">Сохранить</button>
      </div>

      <div>
        <p>Позволяет быстро сменять стили в ⚙️Панели Расширенных настроек в Игровой.</p>
        <input type="checkbox" id="fast-Styles" data-setting="fastStyles" />
        <label for="fast-Styles">Быстрые стили</label>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Темы и цвета Игровой</h2>

      <p>
        Здесь вы можете выставить собственные цвета для игровой. Принимаются "HEX"
        значения (Пример: #000) с поддержкой прозрачности. Будьте аккуратны и
        не забывайте выключать другие цвета/темы в других скриптах/модах. Очистите поле
        чтобы вернуться к стандартным цветам.
      </p>
      <input type="checkbox" id="user-theme" data-setting="userTheme" />
      <label for="user-theme-enabled">Использовать свои цвета</label>

    <div id="theme-selector" class="uwu-select">
      <label for="theme-select">Выберите тему:</label>
      <select id="theme-select" class="uwu-select-selected"></select>
      <button id="addThemeButton" class="uwu-button install-button">Добавить тему</button>
      <button id="removeThemeButton" style="display: none;" class="uwu-button remove-button">Удалить тему</button>
    </div>

      <div id="color-picker">
        <div id="color-picker-input">
          <input type="text" id="backgroundColorField" placeholder="Вставьте HEX код"
            data-color="backgroundColor" />
          <label>Цвет фона</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="blocksColorField" placeholder="Вставьте HEX код"
            data-color="blocksColor" />
          <label>Основной цвет блоков</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="chatColorField" placeholder="Вставьте HEX код" data-color="chatColor" />
          <label>Основной цвет чата</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="SettingTextColorField" placeholder="Вставьте HEX код" data-color="textColor" />
          <label>Цвет текста</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="colorField" placeholder="Вставьте HEX код" data-color="linkColor" />
          <label>Цвет ссылок</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="catTooltipBackgroundField" placeholder="Вставьте HEX код"
            data-color="catTooltipBackground" />
          <label>Цвет фона подсказки "О Коте"</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="settingFightPanelBackgroundField" placeholder="Вставьте HEX код"
            data-color="fightPanelBackground" />
          <label>Цвет панели Боевого режима</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="settingsMoveNameColorField" placeholder="Вставьте HEX код"
            data-color="moveNameColor" />
          <label>Цвет текста перехода</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="settingsMoveNameBackgroundField" placeholder="Вставьте HEX код"
            data-color="moveNameBackground" />
          <label>Цвет фона перехода</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="accentColorField1" placeholder="Вставьте HEX код"
            data-color="accentColor1" />
          <label
            title="В основном всякие кнопки, слайдеры и строки ввода + цвет букв упоминания вас в Чате. Старайтесь пока делать просто оттенки чёрного цвета.">[?]
            Акценты 1</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="accentColorField2" placeholder="Вставьте HEX код"
            data-color="accentColor2" />
          <label title="Линии в чате и некоторых других частях, кружочек слайдера громкости.">[?] Акценты 2</label>
        </div>
        <div id="color-picker-input">
          <input type="text" id="accentColorField3" placeholder="Вставьте HEX код"
            data-color="accentColor3" />
          <label title="Цвет уведомлений. Например ЛС и вашего имени в Чате">[?] Акценты 3</label>
        </div>

        <div style="flex: 0 0 100%">
          <button id="saveThemeButton" class="uwu-button install-button">Сохранить</button>
          <p>
            Отличный сайт для выбора цветов с поддержкой прозрачности:
            <a href="https://get-color.ru/transparent/" target="_blank">https://get-color.ru/transparent/</a>
          </p>
        </div>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Шрифты и текст</h2>
      
      <div>
        <p>Кастомная настройка шрифтов в Игровой</p>
        <input type="checkbox" id="use-User-Fonts" data-setting="useUserFonts" />
        <label for="use-User-Fonts">Свой шрифт</label>
      </div>

      <div>
        <input type="text" id="font-Size-Body" placeholder="14" data-font-size="fontSizeBody" />
        <label for="font-Size-Body">px; Размер общего шрифт</label>
      </div>

      <div>
        <input type="text" id="font-Size-Small" placeholder="12" data-font-size="fontSizeSmall" />
        <label for="font-Size-Small">px; Размер шрифта быстрых ссылок</label>
      </div>

      <div>
        <input type="text" id="font-Size-Location" placeholder="14" data-font-size="fontSizeLocation" />
        <label for="font-Size-Location">px; Размер шрифта локации</label>
      </div>

      <div>
        <input type="text" id="font-Family-Body" placeholder="Verdana" data-font-size="fontFamilyBody" />
        <label for="font-Family-Body">Название вида шрифта</label>
      </div>

      <details>
        <summary style="cursor: pointer; font-size: 16px; font-weight: bold;">Настройка шрифта громкости сообщений в чате</summary>
        <div>
          <input type="text" id="vlm0" placeholder="10" data-font-size="vlm0" />
          <label for="vlm0">px; Громкость 0 (Самый тихий)</label>
        </div>
        <div>
          <input type="text" id="vlm1" placeholder="11" data-font-size="vlm1" />
          <label for="vlm1">px; Громкость 1</label>
        </div>
        <div>
          <input type="text" id="vlm2" placeholder="11.5" data-font-size="vlm2" />
          <label for="vlm2">px; Громкость 2</label>
        </div>
        <div>
          <input type="text" id="vlm3" placeholder="12" data-font-size="vlm3" />
          <label for="vlm3">px; Громкость 3</label>
        </div>
        <div>
          <input type="text" id="vlm4" placeholder="12.5" data-font-size="vlm4" />
          <label for="vlm4">px; Громкость 4</label>
        </div>
        <div>
          <input type="text" id="vlm5" placeholder="13" data-font-size="vlm5" />
          <label for="vlm5">px; Громкость 5 (Стандартная громкость)</label>
        </div>
        <div>
          <input type="text" id="vlm6" placeholder="15" data-font-size="vlm6" />
          <label for="vlm6">px; Громкость 6</label>
        </div>
        <div>
          <input type="text" id="vlm7" placeholder="17" data-font-size="vlm7" />
          <label for="vlm7">px; Громкость 7</label>
        </div>
        <div>
          <input type="text" id="vlm8" placeholder="19" data-font-size="vlm8" />
          <label for="vlm8">px; Громкость 8</label>
        </div>
        <div>
          <input type="text" id="vlm9" placeholder="21" data-font-size="vlm9" />
          <label for="vlm9">px; Громкость 9</label>
        </div>
        <div>
          <input type="text" id="vlm10" placeholder="23" data-font-size="vlm10" />
          <label for="vlm10">px; Громкость 10 (Самая громкая)</label>
        </div>
      </details>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Редизайны Игровой</h2>

      <p>Тот самый знаменитный редизайн, но с почти более расширенной кастомизацией.</p>
      <input type="checkbox" id="custom-layout" data-setting="customLayout" />
      <label for="custom-layout">Компактный редизайн</label>

      <div id="layout-customizer">
        <div id="layout-preview">
          <div class="column left">
            <!-- Левая колонка -->
          </div>
          <div class="column center">
            <!-- Центральная колонка -->
            <div class="block center-block">Поле Игровой</div>
          </div>
          <div class="column right">
            <!-- Правая колонка -->
          </div>
          <ul id="block-list">
            <!-- Элементы списка блоков -->
          </ul>
        </div>
      </div>
      <button id="SettingSaveButton4" class="uwu-button install-button">Сохранить</button>

      <div>
        <input type="text" id="chat-height" placeholder="Вставьте значение" data-setting="chatHeight" />
        <label for="chat-height">px; Высота Чата</label>
      </div>

      <div>
        <input type="text" id="history-height" placeholder="Вставьте значение" data-setting="historyHeight" />
        <label for="history-height">px; Высота Истории</label>
      </div>

      <label>Отображать Душевых котов:</label>
      <div class="custom-select" id="showOtherCatsList">
        <div class="select-selected">Выберите стиль отображения Душевых котов</div>
        <div class="select-items">
          <!-- Опции будут добавлены сюда -->
        </div>
      </div>

      <div>
        <p>Визуальное разделение блока "Информация" на меньшие блоки "Параметров, Истории и Родственные связи".</p>
        <input type="checkbox" id="slice-info-block" data-setting="sliceInfoBlock" />
        <label for="slice-info-block">Разделить блок Информации</label>
      </div>

      <div>
        <p>Скругляет края блоков в Игровой.</p>
        <input type="checkbox" id="edge-trim-blocks" data-setting="edgeTrimBlocks" />
        <label for="edge-trim-blocks">Скругление блоков</label>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Общение</h2>

      <div>
        <p>Добавляет аватар с профиля отправителя на его комментарий в лентах и блогах.</p>
        <input type="checkbox" id="comments-avatars" data-setting="commentsAvatars" />
        <label for="comments-avatars">Аватарки в комментариях</label>
      </div>

      <div>
        <p>Более функциональный Чат: допись ID отправителя и звуковое уведомление при вашем упоминании.
        </p>
        <input type="checkbox" id="new-chat" data-setting="newChat" />
        <label for="new-chat">Современный Чат</label>
      </div>

      <div>
        <p>Работает только с "Современным чатом". Отображет чат снизу вверх, а так же смещает окно ввода сообщения под чат.</p>
        <input type="checkbox" id="reverse-Chat" data-setting="reverseChat" />
        <label for="reverse-Chat">Инверсия чата</label>
      </div>

      <div id="myNameNotificationSoundContainer">
        <div class="custom-select" id="myNameNotificationSound">
          <div class="select-selected">Выберите звук</div>
          <div class="select-items">
            <!-- Опции будут добавлены сюда -->
        </div>
      </div>
    
      <div id="notification-volume">
      <p>Громкость</p>
        <input type="range" min="1" max="10" value="5" class="uwu-range-slider" id="notification-MyName-Volume" list="volumeStep"
          data-setting="notificationMyNameVolume">
        <datalist id="volumeStep">
          <option value="1">10%</option>
          <option value="5">50%</option>
          <option value="10">100%</option>
        </datalist>
      </div>
    </div>

    <div>
      <p>Ваши собственные имена и клички на упоминания в чате. Просто пропишите их через запятую. Пример: Мяу, Мяуич, МяуВкин</p>
      <input type="text" id="names-For-Notification" placeholder=". . ." data-setting="namesForNotification" />
    </div>

      <div>
        <p>Более удобная строка ввода сообщений над чатом с возможностью растягивания. Пока что насильно берёт цвета с "Использовать свои цвета".</p>
        <input type="checkbox" id="new-chat-input" data-setting="newChatInput" />
        <label for="new-chat-input">Альтернативная строка ввода сообщений</label>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Параметры и навыки</h2>
      
      <div>
        <p>Параметр наглядно отображает рядом с собой свой процент.</p>
        <input type="checkbox" id="display-Parameters-Percentages" data-setting="displayParametersPercentages" />
        <label for="display-Parameters-Percentages">Отображать проценты Параметров</label>
      </div>

      <div>
        <p>Заменяет стандартное оформление Параметров и Навыков на ваш.</p>
        <input type="checkbox" id="user-Parameters-Theme" data-setting="userParametersTheme" />
        <label for="user-Parameters-Theme">Использовать своё оформление</label>
      </div>

  <div id="parameters-color-settings" class="parameters-color-settings">
    <table class="parameters-color-table">
      <thead>
        <tr>
          <th class="parameters-color-table--header">Градиент</th>
          <th class="parameters-color-table--header">От</th>
          <th class="parameters-color-table--header">До</th>
          <th class="parameters-color-table--header">От</th>
          <th class="parameters-color-table--header">До</th>
        </tr>
      </thead>
      <tbody id="color-settings-body" class="parameters-color-table--body">
        <tr>
          <th class="parameters-color-table--cell" colspan="5">Параметры</th>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Сон</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dream" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dream" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dream" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dream" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Голод</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="hunger" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="hunger" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="hunger" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="hunger" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Жажда</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="thirst" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="thirst" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="thirst" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="thirst" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Нужда</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="need" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="need" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="need" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="need" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Здоровье</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="health" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="health" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="health" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="health" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Чистота</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="clean" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="clean" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="clean" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="clean" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <th class="parameters-color-table--cell" colspan="5">Навыки</th>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Запах</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="smell" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="smell" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="smell" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="smell" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Копание</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dig" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dig" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dig" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="dig" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Плавание</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="swim" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="swim" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="swim" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="swim" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">БУ</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="might" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="might" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="might" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="might" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Лазание</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="tree" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="tree" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="tree" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="tree" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <td class="parameters-color-table--cell">Зоркость</td>
          <td class="parameters-color-table--cell"><input type="color" data-param="observ" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="observ" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="observ" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="observ" data-color-type="bg-to"></td>
        </tr>
        <tr>
          <th class="parameters-color-table--cell" colspan="5">Уникальные навыки</th>
        </tr>
        <tr>
          <td class="parameters-color-table--cell"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="other" data-color-type="bar-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="other" data-color-type="bar-to"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="other" data-color-type="bg-from"></td>
          <td class="parameters-color-table--cell"><input type="color" data-param="other" data-color-type="bg-to"></td>
        </tr>
      </tbody>
    </table>
  </div>

      <div>
        <p>Накладывает поверх цветов изображение с узорами.</p>
        <input type="checkbox" id="parameters-Background-Image" data-setting="parametersBackgroundImage" />
        <label for="parameters-Background-Image">Узоры</label>
      </div>

      <div>
        <p>Накладывает поверх уже ваше изображение.</p>
        <input type="checkbox" id="parameters-User-Background-Image" data-setting="parametersUserBackgroundImage" />
        <label for="parameters-User-Background-Image">Свои узоры:</label>
        <input type="text" id="parametersUserBackgroundImageField" placeholder="Вставьте URL" data-setting="parametersUserBackgroundImageURL" />
        <button id="SettingSaveButton1" class="uwu-button install-button">Сохранить</button>
      </div>

    </div>

    <div id="utility-panel">

      <h2>Подсветка</h2>

      <div>
        <p>Подсвечивает обводкой клетки полезные, и не очень, ресурсы</p>
        <input type="checkbox" id="highlight-Resources" data-setting="highlightResources" />
        <label for="highlight-Resources">Подсветка ресурсов</label>
      </div>

      <label>Стиль подсветки предметов:</label>
      <div class="custom-select" id="highlightResourcesStyle">
        <div class="select-selected">Выберите стиль подсветки предметов</div>
        <div class="select-items">
          <!-- Опции будут добавлены сюда -->
        </div>
      </div>
      <label id="uwu-what-this" title="Стиль 'Фон' подсвечивает всю клетку и не нагружает Игровую. Стиль 'Свечение' дублирует содержимое ячейки и стилизует его, что может нагружать Игровую.">[?]</label>

      <table class="uwu-table-highlight-Resources">
        <thead>
            <tr>
                <th>Название</th>
                <th>Цвет</th>
                <th>Подсвечивать?</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Травы</td>
                <td><input type="color" class="uwu-color-picker" data-resource="Травы" value="#90EE90"></td>
                <td class="uwu-checkbox-cell"><input type="checkbox" class="uwu-highlight-checkbox" data-resource="Травы"></td>
            </tr>
            <tr>
                <td>Мох</td>
                <td><input type="color" class="uwu-color-picker" data-resource="Мох" value="#90EE90"></td>
                <td class="uwu-checkbox-cell"><input type="checkbox" class="uwu-highlight-checkbox" data-resource="Мох"></td>
            </tr>
            <tr>
                <td>Паутина</td>
                <td><input type="color" class="uwu-color-picker" data-resource="Паутина" value="#90EE90"></td>
                <td class="uwu-checkbox-cell"><input type="checkbox" class="uwu-highlight-checkbox" data-resource="Паутина"></td>
            </tr>
            <tr>
                <td>Пыль</td>
                <td><input type="color" class="uwu-color-picker" data-resource="Пыль" value="#DDA0DD"></td>
                <td class="uwu-checkbox-cell"><input type="checkbox" class="uwu-highlight-checkbox" data-resource="Пыль"></td>
            </tr>
            <tr>
                <td>Ветки, вьюнки, костоправы</td>
                <td><input type="color" class="uwu-color-picker" data-resource="Ветки, вьюнки, костоправы" value="#90EE90"></td>
                <td class="uwu-checkbox-cell"><input type="checkbox" class="uwu-highlight-checkbox" data-resource="Ветки, вьюнки, костоправы"></td>
            </tr>
            <tr>
                <td>Травящие предметы</td>
                <td><input type="color" class="uwu-color-picker" data-resource="Травящие предметы" value="#FF0000"></td>
                <td class="uwu-checkbox-cell"><input type="checkbox" class="uwu-highlight-checkbox" data-resource="Травящие предметы"></td>
            </tr>
        </tbody>
      </table>

      <hr class="uwu-hr-head" />

      <h2>Шаблоны</h2>

      <div>
        <p>Позволяет создавать и быстро использовать собственные шаблоны сообщений.</p>
        <input type="checkbox" id="show-Templates" data-setting="showTemplates" />
        <label for="show-Templates">Отображать шаблоны</label>
      </div>

      <table id="uwu-table-templates">
      <thead>
          <tr>
              <th>Сообщения</th>
              <th>Чаты</th>
              <th>Блоги и Лента</th>
          </tr>
        </thead>
        <tbody>
          <tr>
              <td class="uwu-checkbox-cell"><input type="checkbox" data-setting="templatesInLs"></td>
              <td class="uwu-checkbox-cell"><input type="checkbox" data-setting="templatesInChats"></td>
              <td class="uwu-checkbox-cell"><input type="checkbox" data-setting="templatesInBlogsAndSniffs"></td>
          </tr>
        </tbody>
        </table>

      <hr class="uwu-hr-head" />

      <h2>Боевой режим</h2>

      <div>
        <p>Позволяет перетаскивать панель Боевого режима за штучку.</p>
        <input type="checkbox" id="dragging-Fight-Panel" data-setting="draggingFightPanel" />
        <label for="dragging-Fight-Panel">Перетаскивание панели Боевого режима</label>
      </div>

      <div>
        <p>Сокращает и прописывает количество повторяющихся ударов.</p>
        <input type="checkbox" id="compact-Fight-Log" data-setting="compactFightLog" />
        <label for="compact-Fight-Log">Компактный боевой лог</label>
      </div>

      <div>
        <p>Возможность растягивать высоту панели и её начальная высота.</p>
        <input type="checkbox" id="fight-Panel-Adjustable-Height" data-setting="fightPanelAdjustableHeight" />
        <label for="fight-Panel-Adjustable-Height">Настраиваемая высота панели</label>
        <input type="text" id="fightPanelHeightField" placeholder=". . ." data-setting="fightPanelHeight" />
        <label>px; - Начальная высота панели</label>
      </div>

      <div>
        <p>Возможность перекрашивать и создавать команды в Панели Боевого Режима.</p>
        <input type="checkbox" id="Fight-Teams" data-setting="fightTeams" />
        <label for="fight-Teams">Команды в Боевом Режиме</label>
        <input type="text" id="fightTeamsPanelHightField" placeholder=". . ." data-setting="fightTeamsPanelHight" />
        <label>px; - Начальная высота панели Командного Боя</label>
      </div>

  <table id="colorSettingsTable">
    <thead>
      <tr>
        <th></th>
        <th>Энергия</th>
        <th>Снесено</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Команда 1</td>
        <td><input type="color" data-team="1" data-part="green" value="#41cd70"></td>
        <td><input type="color" data-team="1" data-part="red" value="#cd4141"></td>
      </tr>
      <tr>
        <td>Команда 2</td>
        <td><input type="color" data-team="2" data-part="green" value="#c968ff"></td>
        <td><input type="color" data-team="2" data-part="red" value="#cd4141"></td>
      </tr>
      <tr>
        <td>Команда 3</td>
        <td><input type="color" data-team="3" data-part="green" value="#44bcff"></td>
        <td><input type="color" data-team="3" data-part="red" value="#cd4141"></td>
      </tr>
      <tr>
        <td>Команда 4</td>
        <td><input type="color" data-team="4" data-part="green" value="#FFFF00"></td>
        <td><input type="color" data-team="4" data-part="red" value="#cd4141"></td>
      </tr>
    </tbody>
  </table>
    
    <hr id="uwu-hr" class="uwu-hr">
    <h2>Часы</h2>

    <div>
      <p>Показывать ли часы в Игровой?</p>
      <input type="checkbox" id="describe-show-clock" data-setting="showClock" />
      <label for="describe-show-clock">Часы в Игровой</label>
    </div>

    <label>Стиль часов:</label>
    <div class="custom-select" id="clockStyle">
      <div class="select-selected">Выберите стиль часов</div>
      <div class="select-items">
        <!-- Опции будут добавлены сюда -->
      </div>
    </div>

    <div><!-- Деление --></div>

    <label>Где вставлять часы:</label>
    <div class="custom-select" id="clockPosition">
      <div class="select-selected">Выберите положение часов</div>
      <div class="select-items">
        <!-- Опции будут добавлены сюда -->
      </div>
    </div>

    <div>
      <input type="checkbox" id="describe-clock-Moscow-Time" data-setting="clockMoscowTime" />
      <label for="describe-clock-Moscow-Time">Московское время</label>
    </div>

    <div>
      <p>Размер шрифта часов</p>
      <input type="text" id="clock-Font-Size" placeholder=". . ." data-setting="clockFontSize" />
    </div>

    <div>
      <button id="resetClockPosition" class="uwu-button remove-button">Сброс позиции часов</button>
    </div>

    <hr id="uwu-hr" class="uwu-hr">
    <h2>Охота</h2>

      <div>
        <p>Дописывает на запахе, во время охоты, приближаетесь вы или отдаляетесь от цели, а так же включает таймер.</p>
        <input type="checkbox" id="describe-Hunting-Smell" data-setting="describeHuntingSmell" />
        <label for="describe-Hunting-Smell">Подсказки на запахе</label>
      </div>

    <hr id="uwu-hr" class="uwu-hr">
    <h2>Джойстики</h2>

      <div>
        <p>Отображает Виртуальную сенсорную Джойстиковую кнопку для мобильных устройств во время охоты для более удобного управления.</p>
        <input type="checkbox" id="hunting-Virtual-Joystick" data-setting="huntingVirtualJoystick" />
        <label for="hunting-Virtual-Joystick">Виртуальный джойстик для охоты</label>
        <input type="text" id="sizeHuntingVirtualJoystickField" placeholder=". . ." data-setting="sizeHuntingVirtualJoystick" />
        <label>px; - Размер Джойстика. Стандартный размер - 150 px;</label>
      </div>

    <hr id="uwu-hr" class="uwu-hr">
    <h2>"О котах"</h2>

      <div>
        <p>Добавляет во всплывающее окно "О коте" кнопку "Подробнее" для просмотра большей полезной информации.</p>
        <input type="checkbox" id="show-More-Cat-Info" data-setting="showMoreCatInfo" />
        <label for="show-More-Cat-Info">Больше информации о Коте</label>
      </div>

      <div>
        <p>Сокращает и прописывает количество повторяющихся предметов в "О коте".</p>
        <input type="checkbox" id="compact-Mouth" data-setting="compactMouth" />
        <label for="compact-Mouth">Компактные инвентари</label>
      </div>

      <div>
        <p>Добавляет над собственными параметрами кнопку "Подробнее" для просмотра большей полезной информации.</p>
        <input type="checkbox" id="show-Parameter-Details" data-setting="showParametersDetails" />
        <label for="show-Parameter-Details">Подробные параметры</label>
      </div>

      <div>
        <p>Показывает дополнительную информацию в профиле кота, например БУ цифрой.</p>
        <input type="checkbox" id="more-Profile-Info" data-setting="moreProfileInfo" />
        <label for="more-Profile-Info">Больше информации в профиле</label>
      </div>

      <div>
        <p>Добавляет полезные калькуляторы для вычислений в профиля.</p>
        <input type="checkbox" id="calculators" data-setting="calculators" />
        <label for="calculators">Калькуляторы активностей и лун.</label>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Минное поле</h2>

      <div>
      <p>ЛКМ - выбрать клетку. С клавиатуры мины ставятся от "0" до "7". Знак "минус" ( - ) равняется красной клетке, а "равно" ( = ) ставит более яркую клетку, например для переходов,
      которая не будет очищаться при "Очистить всё поле/таблицу". Два раза ЛКМ на ячейку, чтобы очистить её значение.</p>
        <p>Включает окно для расчерчивания минного поля в Игровой.</p>
        <input type="checkbox" id="climbing-panel" data-setting="climbingPanel" />
        <label for="climbing-panel">Минное поле</label>
        <p>Здесь вы можете добавить/удалить Вкладки для хранения Таблиц и количество самих таблиц в выбранной вкладке.</p>
          <h4>Вкладки</h4>
          <div id="uwu-buttonRow1-settings"></div>
          <h4>Локации / Таблицы</h4>
          <div id="uwu-buttonRow2-settings"></div>
      </div>

      <label>Дизайн окна минного поля:</label>
      <div class="custom-select" id="climbingPanelOrientation">
        <div class="select-selected">Вертикальный</div>
        <div class="select-items">
          <!-- Опции будут добавлены сюда -->
        </div>
      </div>

      <div>
        <p>Дописывает в чате громкость уведомлений числом. В случае с лазательными локациями - количество опасных клеток вокруг вас.</p>
        <input type="checkbox" id="climbing-Notifications-Numbers" data-setting="climbingNotificationsNumbers" />
        <label for="climbing-Notifications-Numbers">Подписывать громкость уведомления</label>
      </div>

      <div>
        <p>Звуковое уведомление, когда карта локации обновляется.</p>
        <input type="checkbox" id="climbing-Refresh-Notification" data-setting="climbingRefreshNotification" />
        <label for="climbing-Refresh-Notification">Уведомлять об перестановке</label>
      </div>

      <div id="climbingRefreshNotificationSoundContainer">
        <div class="custom-select" id="climbingRefreshNotificationSound">
          <div class="select-selected">Выберите звук</div>
        <div class="select-items">
          <!-- Опции будут добавлены сюда -->
        </div>
      </div>
    
      <div id="notification-volume">
      <p>Громкость</p>
        <input type="range" min="1" max="10" value="5" class="uwu-range-slider" id="climbing-Refresh-Notification-Volume" list="volumeStep"
          data-setting="climbingRefreshNotificationVolume">
        <datalist id="volumeStep">
          <option value="1">10%</option>
          <option value="5">50%</option>
          <option value="10">100%</option>
        </datalist>
      </div>
    </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Быстрые ссылки</h2>

      <p>Быстрые ссылки в Игровой.</p>
      <div>
        <input type="checkbox" id="quick-Link1" data-setting="quickLink1" />
        <label for="quick-Link1">Настройки</label>
      </div>

      <div>
        <input type="checkbox" id="quick-Link2" data-setting="quickLink2" />
        <label for="quick-Link2">Памятка</label>
      </div>

      <div>
        <input type="checkbox" id="quick-Link3" data-setting="quickLink3" />
        <label for="quick-Link3">Блоги</label>
      </div>

      <div>
        <input type="checkbox" id="quick-Link4" data-setting="quickLink4" />
        <label for="quick-Link4">Лента</label>
      </div>

      <div>
        <p>Ваши ссылки. Вставляете ссылку, пробел и пишите название. Для множества просто пишите через запятую. Пример:
          https://мяу Котики, https://мяу2 Больше-котиков</p>
        <input type="text" id="users-quick-Links" placeholder=". . ." data-setting="userQuickLinks" />
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <div>
        <h2>Уведомления</h2>
        <p>Уведомлять звуком, когда:</p>
      </div>
      
      <div>
        <input type="checkbox" id="notification-PM" data-setting="notificationPM" />
        <label for="notification-PM">Новое Личное Сообщение</label>
      </div>

      <div>
        <input type="checkbox" id="notification-Action-End" data-setting="notificationActionEnd" />
        <label for="notification-Action-End">Действие закончилось</label>
      </div>

      <div>
        <input type="checkbox" id="notification-In-Mouth" data-setting="notificationInMouth" />
        <label for="notification-In-Mouth">Кто-то меня поднял</label>
      </div>

      <div>
        <input type="checkbox" id="notification-In-Fight-Mode" data-setting="notificationInFightMode" />
        <label for="notification-In-Fight-Mode">Ввели в боевую стойку через Т+2 или Т+3</label>
      </div>

      <div>
        <p>Дублирует время действий на название браузерной вкладки.</p>
        <input type="checkbox" id="duplicate-Time-In-Browser-Tab" data-setting="duplicateTimeInBrowserTab" />
        <label for="duplicate-Time-In-Browser-Tab">Показывать время действия на вкладке</label>
      </div>

      <div>
        <p>Подсказывает оставшееся время до возможности понюхать.</p>
        <input type="checkbox" id="show-Hint-When-To-Sniff" data-setting="showHintWhenToSniff" />
        <label for="show-Hint-When-To-Sniff">Когда нюхать?</label>
      </div>

      <hr id="uwu-hr" class="uwu-hr">
      <h2>Общение</h2>

      <div>
        <p>Автоматически сохраняет и восстанавливает редактируемый текст блога. Теперь вы не потеряете его случайно.</p>
        <input type="checkbox" id="restore-Blog-Creation" data-setting="restoreBlogCreation" />
        <label for="restore-Blog-Creation">Восстановление содержимого Блога</label>
      </div>

      <div>
        <p>Говорит само за себя.</p>
        <input type="checkbox" id="more-BB-Codes" data-setting="moreBBCodes" />
        <label for="more-BB-Codes">Дополнительные BB-Коды</label>
      </div>

      <div>
        <p>Позволяет предпросматривать отправляемые сообщения в лентах и блогах.</p>
        <input type="checkbox" id="comment-Preview" data-setting="commentPreview" />
        <label for="comment-Preview">Предпросмотр сообщений</label>
      </div>

      <div>
        <p>Позволяет "отвечать" и "цитировать" сообщения в лентах и блогах. При цитировании вы можете выделить кусочек 
        текста на который хотите ответить.</p>
        <input type="checkbox" id="more-Comment-Buttons" data-setting="moreCommentButtons" />
        <label for="more-Comment-Buttons">Кнопки "Отправить" и "Цитировать"</label>
      </div>

      <div>
        <p>Оборачивает предпросмотр письма в оболочку, похожую на ту которая во "Входящие".</p>
        <input type="checkbox" id="ls-Wrap-Preview" data-setting="lsWrapPreview" />
        <label for="ls-Wrap-Preview">Наглядный предпросмотр письма</label>
      </div>

    </div>

    <div id="modules-panel">

      <h2>Главное</h2>
      <div>
        <p>Постоянное отображание Панели Расширенных Настроек в Игровой. Сама по себе пустая.</p>
        <input type="checkbox" id="extended-settings-Panel" data-setting="extendedSettingsPanel" />
        <label for="extended-settings-Panel">⚙️Панель Расширенных Настроек</label>
      </div>

      <div>
        <p>Отображает уведомление в ⚙️Панели Расширенных настроек в Игровой.</p>
        <input type="checkbox" id="show-Update-Notification" data-setting="showUpdateNotification" />
        <label for="show-Update-Notification">Уведомлять об обновлении Скрипта/Мода UwU</label>
      </div>

      <div>
        <p>⚙️Панели Расширенных Настроек не будет так скучно с рандомными фразами.</p>
        <input type="checkbox" id="show-Splash-Screens" data-setting="showSplashScreens" />
        <label for="show-Splash-Screens">Показывать Splash надписи.</label>
      </div>

      <div>
        <p>Скрывать или отображать расширенные подсказки к настройкам. Привет, я та самая расширенная подсказка. Делает Настройки CatWar UwU очень компактным на вид.</p>
        <input type="checkbox" id="extended-Hints" data-setting="extendedHints" />
        <label for="extended-Hints">Расширенные подсказки</label>
      </div>

    <hr id="uwu-hr" class="uwu-hr">
      <h2>Сборник стилей</h2>
      <p>Онлайн сборник стилей от Разработчика.</p>
    <hr id="uwu-hr" class="uwu-hr">
      <div id="module-info">
        <!-- Сюда модули -->
      </div>

    <hr id="uwu-hr" class="uwu-hr">
      <h2>Импорт/Экспорт</h2>

      <div>
        <p>Импорт/Экспорт всех настроек (Пока без расставленных блоков Компактной Игровой, Сборника Стилей и Минного поля).</p>
        <input type="text" id="exportSettings" placeholder="Экспорт"/>
        <input type="text" id="importSettings" placeholder="Импорт"/>
        <button id="importSettingsButton" class="uwu-button install-button">Вставить</button>
      </div>
      
      <div>
        <p>Удаляет все настройки. В очень редких случаях может помочь при проблемных проблемах.</p>
        <button id="resetAllSaves" class="uwu-button remove-button">Сброс сохранений</button>
      </div>

    </div>

  </div>
  <hr id="uwu-hr" class="uwu-hr-head">
</div>
`;
// ====================================================================================================================
//   . . . HTML БЛОК НОВОСТЕЙ . . .
// ====================================================================================================================
const newsPanel = // html
`
<div id="news-panel">
    <button id="news-button">
        v${current_uwu_version} - 🎃 Полировочка.
    </button>
    <div id="news-list" style="display: none">
        <h3>Главное</h3>
        <p>— Ба бу бэ)) Часы теперь можно вставлять в блок Погоды, это затычка на крайняк.</p>
        <hr id="uwu-hr" class="uwu-hr">
        <h3>Внешний вид</h3>
        <p>— Текст в информации в "О коте" сдвинута к левому краю и сделалась чуть компактнее.</p>
        <p>— При выборе московского времени, "MSK" теперь пишется около значка откуда берётся время. 
        Ну те самые 🌍︎ или ⌨.</p>
        <p>— Небольшой редизайн кнопки разворачивания Минного Поля.</p>
        <p>— Цвет текста в Шаблонах стал белым. Извените кому нравилось цветное, как нибудь потом.</p>
        <hr id="uwu-hr" class="uwu-hr">
        <h3>Изменения кода</h3>
        <p>— Немного почистил и чёта там поменял с высотами панели БР. 
        Надеюсь кому-то чёта починило если нет то хихи хаха.</p>
        <p>— Починина подсветка ресурсов в режиме "Подсветка".</p>
        <p>— Теперь не будет использовать последний цвет из сохранения для подсветки всех ресурсов.</p>
        <p>— Немного переписан код Дублирования действий на вкладку, а так же + ...</p>
        <p>— ... теперь на название вкладки дублируется подняли ли вас, и кто поднял.</p>
        <p>— Убраны console.warn от установок прослушок из-за как таковой ненадобности в общем пользовании. 
        Консоль браузера теперь чистенькая 😊</p>
        <p>— Чуть переписаны handleCommentActions и toggleAurora афигеть как круто сделано вау надо чаще так делать.</p>
        <hr id="uwu-hr" class="uwu-hr">
        <p>Дата выпуска: 10.10.24</p>
    </div>
</div>
`;
// ====================================================================================================================
//   . . . HTML ПАНЕЛЬ РАСШИРЕННЫХ НАСТРОЕК . . .
// ====================================================================================================================
const extendedSettingsButton = // html
`
<div id="uwu-extended-settings">
  <button type="button" id="extended-settings-button">
    <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/partly_sunny_rain.png" alt="Иконка"
      width="36" height="36">
  </button>

  <div id="extended-settings-container">
    <div id="splash-screen-panel"></div>

  </div>
</div>
`;
// ====================================================================================================================
//   . . . HTML БЛОК РУЧНОГО УПРАВЛЕНИЯ ПОГОДЫ . . .
// ====================================================================================================================
const manualWeatherPanel = // html
`
<div id="manual-weather-panel">
<p>Изменения, сделанные в этой панели, носят временный характер и не сохраняются.</p>
<h3>Переключить погоду</h3>
<input type="range" min="1" max="3" value="1" class="uwu-range-slider" id="manualWeather" list="WeatherStep">
<datalist id="WeatherStep">
  <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/sunny.png" width="36" height="36" option
    value="1"></option>
  <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/rain_cloud.png" width="36" height="36"
    option value="2"></option>
  <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/snow_cloud.png" width="36" height="36"
    option value="3"></option>
</datalist>
<div id="temperature-container">
  <p id="temperature"
    title="На это умножается скорость частиц и делится их размер. В будущем будет возможность сохранять и изменять это значение под свой вкус.">
    [?] Текущий модификатор: ...уточнение...</p>
</div>

<h3>Северное Сияние</h3>
<div class="button-container-1">
  <button type="button" id="manualAurora-Off" class="uwu-button-round">
    <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/icons8-nothern-lights-96.png"
      alt="Иконка" width="48" height="48">
  </button>
  <button type="button" id="manualAurora-B" class="uwu-button-round">
    <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/icons8-nothern-lights-96_blue.png"
      alt="Иконка" width="48" height="48">
  </button>
  <button type="button" id="manualAurora-G" class="uwu-button-round">
    <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/icons8-nothern-lights-96_green.png"
      alt="Иконка" width="48" height="48">
  </button>
</div>

<h3>Светлячки</h3>
<div class="button-container-2">
  <button type="button" id="manualFirefly-On" class="uwu-button-round">
    <img src="https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/firefly.png" alt="Иконка" width="48"
      height="48" title="Включает/Выключает">
  </button>
</div>

</div>
<div id="aurora-settings-panel">
<p>Изменения, сделанные в этой панели, сохранятся!</p>
<h5>Здесь будет возможность переместить Северное Сияние в реальном времени, исключать локации из генерации погоды,
  либо запрещать
  определённой погоде существовать на выбранной локации. Но это всё пока что лишь мечта...</h5>
</div>
`;
// ====================================================================================================================
//   . . . ГЛАВНЫЙ CSS СТИЛЬ . . .
// ====================================================================================================================
// TODO - Унифицировать шрифты, цвета текстов, прозрачность, закруглённость штучек ну кароче всё как надо чтобы не сделать в итоге лабиринт.
const css_uwu_main =
`
#uwu-settings {
    margin-top: 10px;
    margin-bottom: 10px;
}

#uwusettings {
  font-family: "Montserrat", sans-serif;
  margin: 0 auto;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}
.main-settings-container {
  padding: 10px 15px 10px 15px;
}

#uwusettings-main {
  padding: 0px 15px 0px 15px;
}

#news-panel {
  padding: 5px 15px 15px 15px;
}

#uwu-what-this {
  color: #83e5ff;
  font: caption;
}

.main-settings-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
}

#uwusettings h1,
#uwusettings h2 {
  font-family: "Montserrat", sans-serif;
  margin-top: 10px;
  margin-bottom: 15px;
  text-align: center;
}

#uwusettings h4 {
  margin-top: 5px;
  margin-left: 5px;
  margin-bottom: 5px;
}

#uwusettings p {
  margin-bottom: 0px;
}

#uwusettings label {
  font-size: 16px;
}

#uwusettings ul {
  font-family: "Montserrat", sans-serif;
  list-style-type: "+ ";
}

.uwu-hr-head {
  border: rgba(255, 255, 255, 0.1) solid;
  border-radius: 0px;
}

.uwu-hr {
  border: rgba(255, 255, 255, 0.1) solid;
  border-radius: 15px;
}

#uwusettings .parameters-color-table,
#uwusettings .parameters-color-table tr,
#uwusettings .parameters-color-table td {
  border: 1px #383838 solid;
}

#colorSettingsTable,
#colorSettingsTable tr,
#colorSettingsTable td {
  border: 1px #383838 solid;
}

.uwu-table-highlight-Resources,
#uwu-table-templates {
  margin-top: 5px;
}
.uwu-table-highlight-Resources th, .uwu-table-highlight-Resources td,
#uwu-table-templates th, #uwu-table-templates td {
  border: 1px solid #383838;
}

.uwu-color-picker {
  border: none;
  vertical-align: middle;
}

.uwu-checkbox-cell {
  text-align: center;
  vertical-align: middle;
}

#uwusettings .parameters-color-table,
#colorSettingsTable {
  margin-top: 8px;
}

.header-rounded-image {
  background-repeat: repeat;
  background-attachment: fixed;
  border-radius: 20px 20px 0px 0px;
}

.main-rounded-image {
  background-repeat: repeat;
  background-attachment: fixed;
  border-radius: 20px;
}

#button-container-1 {
  display: flex;
  justify-content: space-evenly;
  width: 100%;
}

#button-container button {
  background-color: transparent;
  border: none;

  color: #ffffff57;

  padding: 10px 20px;
  cursor: pointer;
  transition: box-shadow 0.4s ease;
}

#button-container button.active {
  box-shadow: inset 0 -2px 0 0 #ffffff4d;
  transition: box-shadow 0.4s ease;
}

#button-container button.active h2 {
  color: #ffffff;
  transition: color 0.4s ease;
}

#modules-panel {
  display: none;
}

.module-container {
  width: 300px;
  min-height: 150px;
  position: relative;

  box-sizing: border-box;
  margin: 10px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 15px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background-color: rgba(255, 255, 255, 0.03);
}

.module-info {
  flex-grow: 1;
  margin-bottom: 10px;
}

.module-panel {
  display: flex;
  justify-content: space-between;
  align-items: center;

  position: absolute;
  bottom: 10px;
  left: 10px;
  right: 10px;
}

#module-info {
  flex-grow: 1;
  margin-bottom: 10px;

  display: flex;
  flex-wrap: wrap;
  flex-basis: 100%;
}

.module-container label {
  margin-top: 10px;
}

#private-module-input {
  margin: 10px;
}

.module-container button {
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 5px 10px;
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin: 5px;
}

.install-button {
  background-color: #78c8ff87 !important;
}

.remove-button {
  background-color: #ff787887 !important;
}

#module-info input[type="checkbox"] {
  margin: 10px;
}

#color-picker {
  display: flex;
  flex-wrap: wrap;
}

#color-picker-input {
  flex: 30%;
}

#auroraPanel {
  width: 120px;
}

#notification-volume,
#step-slider {
  width: 150px;
}

#layout-preview button {
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 5px 10px;
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin: 5px;
}

#layout-customizer #layout-preview {
  display: flex;
  justify-content: center;
  margin-bottom: 1rem;
}

#layout-customizer .column {
  width: 200px;
  border: 1px solid #ffffff1a;
  border-radius: 10px;
  padding: 5px;
  margin: 0 5px;
}

#layout-customizer .block {
  border-radius: 10px;
  background-color: #ffffff08;
  padding: 5px;
  margin-bottom: 5px;
}

#layout-customizer .center-block {
  height: 100%;
  box-sizing: border-box;

  border-radius: 10px;
  background-color: #ffffff08;
}

#uwu-buttonRow1-settings,
#uwu-buttonRow2-settings {
  display: flex;
  margin-top: 3px;
}

#uwu-buttonRow1-settings button,
#uwu-buttonRow2-settings button  {
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 2px 10px;
  border-radius: 10px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin: 3px;
  margin-left: 0px;
}

#uwu-buttonRow1-settings > div > button.tab-button.active, #uwu-buttonRow2-settings > div > button.table-button.active {
  background-color: #abf6ffb0;
}

#uwu-buttonRow1-settings > .tab-container,
#uwu-buttonRow2-settings > .table-container {
  border-radius: 15px;
  background-color: #54545473;
  margin-right: 5px;
  padding-left: 4px;
  padding-right: 2px;
  padding-top: 2px;
  border-bottom-width: 2px;
  padding-bottom: 2px;
}

#uwu-global-container {
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
}

#uwu-main-container {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  pointer-events: none;
}

.weatherCanvas {
  pointer-events: none;
  position: fixed;
}

#extended-settings-button {
  position: fixed;
  bottom: 30px;
  right: 30px;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  backdrop-filter: blur(16px);
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: auto;
  cursor: pointer;

  background-color: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 2em;
  font-weight: bold;
  color: #ff00ff;
}

#extended-settings-container {
  font-family: "Montserrat", sans-serif;
  color: white;
  font-size: 15px;
  text-align: center;

  position: fixed;
  bottom: 100px;
  right: 30px;
  width: 400px;
  height: 400px;
  backdrop-filter: blur(16px);
  border-radius: 10px;
  display: none;
  pointer-events: auto;

  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);

  display: grid;
  place-items: center;
  padding: 15px;
  box-sizing: border-box;
  overflow-y: auto;
}

.extended-settings-block {
  border-radius: 10px;
  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 5px;
  margin-bottom: 8px;
}

#news {
  margin-top: 20px;
}

#manual-weather-panel,
#news,
#news-button {
  width: 100%;
  border-radius: 10px;

  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);

  padding: 15px;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  box-sizing: border-box;
}

#color-picker {
  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);

  margin-top: 10px;
  padding: 15px;
  border-radius: 10px;
}

#news-button,
#news-list {
  font-family: "Montserrat", sans-serif;
  font-size: 15px;
  cursor: pointer;
}

#news-list h3 {
  margin-left: 40px;
}

#news-list p {
  margin-top: 3px;
  margin-bottom: 3px;
  margin-left: 20px;
}

#aurora-settings-panel {
  width: 100%;
  border-radius: 10px;

  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);

  padding: 15px;
  margin-top: 20px;
  box-sizing: border-box;
}

#WeatherStep,
#auroraStep,
#volumeStep,
#ThicknessStep,
.uwu-range-step {
  margin-top: 10px;
  display: flex;
  justify-content: space-between;
  width: 100%;
}

#extended-settings-container::-webkit-scrollbar {
  width: 10px;
}

#extended-settings-container::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
}

#extended-settings-container::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.3);
  border-radius: 4px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  cursor: pointer;
}

#extended-settings-container::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.4);
}

#button-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  width: 100%;
}

.button-container-1 {
  display: flex;
  justify-content: space-between;
  width: 100%;
}

.button-container-2 {
  display: flex;
  justify-content: space-evenly;
  width: 100%;
}

.uwu-button-round {
  width: 60px;
  height: 60px;
  cursor: pointer;
  border-radius: 50%;

  background-color: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

#extended-settings-button:hover,
.uwu-button-round:hover {
  background-color: rgba(255, 255, 255, 0.15);
}

@property --gradient-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes aurora-spin {
  0% {
    --gradient-angle: 0deg;
  }

  100% {
    --gradient-angle: 360deg;
  }
}

@keyframes auroraFadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes auroraFadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.firefly {
  position: fixed;
  background-color: rgba(255, 255, 153, 1);
  border-radius: 50%;
  filter: blur(5px);
  pointer-events: none;

  animation: fadeIn 6s ease-in-out;
}

.firefly-glow {
  position: fixed;
  background-color: rgba(255, 255, 153, 0.2);
  border-radius: 50%;
  filter: blur(40px);
  pointer-events: none;

  animation: fadeIn 6s ease-in-out;
}

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

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.firefly-disappearing {
  animation: fadeOut 6s ease-in-out forwards;
}

.custom-select {
  position: relative;
  display: inline-block;
}

.select-selected, .uwu-select-selected {
  margin-top: 10px;
  width: fit-content;
  border-radius: 10px;
  color: white;
  background-color: #5c5c5c;
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px); 
  padding: 10px;
  cursor: pointer;
}

.uwu-select-selected {
  width: fit-content;
}

.select-items, uwu-select-items {
  margin-top: 5px;
  display: none;
  position: absolute;
  border-radius: 10px;
  width: max-content;
  color: white;
  background-color: #5c5c5c;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px); 
  z-index: 1;
}

.select-items div {
  padding: 8px 16px;
  cursor: pointer;
}

.select-items div:hover {
  background-color: #757575;
}

.custom-select.active .select-items {
  display: block;
}

#climbingRefreshNotificationSoundContainer button,
#myNameNotificationSoundContainer button {
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 2px 10px;
  border-radius: 10px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin: 3px;
  margin-left: 0px;
}

#climbingRefreshNotificationSoundContainer,
#myNameNotificationSoundContainer {
  gap: 5px;
  display: flex;
  align-items: center;
}

.update-notification {
  background-color: #78c8ff69;
  padding: 10px;
  border-radius: 10px;
  margin-bottom: 10px;
}

.new-update::before {
  content: "•";
  color: #78c8ff;
  font-size: 2em;
  position: absolute;
  top: -20px;
  right: -5px;
}

.random-phrase-block {
  margin-bottom: 10px;
  width: 100%;
  border-radius: 10px;

  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);

  box-sizing: border-box;
  padding: 5px;
}

`;

document.head.insertAdjacentHTML(
  "beforeend",
  `<style id="css-uwu-main">${css_uwu_main}</style>`
);

// ====================================================================================================================
//   . . . ПРОЗРАЧНЫЙ CSS СТИЛЬ . . .
// ====================================================================================================================
// Glassmorphism вперёд Glassmorphism вперёд Glassmorphism вперёд Glassmorphism вперёд Glassmorphism вперёд
const css_uwu_glass = // css
`
#uwusettings {
  backdrop-filter: blur(16px);
  background-color: rgba(255, 255, 255, 0.03);
}

.uwu-button {
  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 8px 15px;
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin: 5px;
  margin-left: 0px;
  color: #d5d5d5;
}

.uwu-button:hover {
  background-color: rgba(255, 255, 255, 0.2);
}

.uwu-range-slider {
  width: 100%;
  cursor: pointer;
  -webkit-appearance: none;
  background-color: rgba(255, 255, 255, 0.06) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  border-radius: 10px;
  height: 10px;
  outline: none;
}

.uwu-range-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  cursor: pointer;
}

.uwu-range-slider::-webkit-slider-thumb {
  transform: translateY(-35%);
}

#uwusettings input[type="checkbox"] {
  margin-right: 8px;
  appearance: none;
  transform: translate(-10%, 30%);
  width: 35px;
  height: 18px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.2s ease-in-out;
}

#uwusettings input[type="checkbox"]:checked {
  background-color: #90ff78a8;
}

#uwusettings input[type="checkbox"]:not(:checked) {
  background-color: rgba(255, 255, 255, 0.1);
}

#uwusettings input[type="checkbox"]:before {
  content: "";
  position: absolute;
  top: 50%;
  left: 4px;
  transform: translate(-50%, -50%);
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.1);
  transition: background-color 0.2s ease-in-out, left 0.2s ease-in-out;
}

#uwusettings input[type="checkbox"]:checked:before {
  left: calc(100% - 4px);
}

#uwusettings input[type="text"] {
  width: 150px;
  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 8px;
  border-radius: 10px;
  outline: none;
  margin: 5px;
  margin-left: 0px;
}
`;
// ====================================================================================================================
//   . . . ТЁМНАЯ ТЕМА . . .
// ====================================================================================================================
const css_uwu_dark = // css
`
#uwusettings {
  background-color: #242424;
  color: #dddddd;
}

#uwusettings-header-glass {
  border-radius: 20px 20px 0px 0px;
  backdrop-filter: blur(16px) brightness(0.9);
}

#news-button {
  color: #dddddd;
}

.uwu-button {
  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 8px 15px;
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin: 5px;
  margin-left: 0px;
}

.uwu-button:hover {
  background-color: rgba(255, 255, 255, 0.2);
}

.uwu-range-slider {
  width: 100%;
  cursor: pointer;
  -webkit-appearance: none;
  background-color: rgba(255, 255, 255, 0.06) !important;
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
  border-radius: 10px;
  height: 10px;
  outline: none;
}

.uwu-range-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  background: rgba(255, 255, 255, 0.3);
  border-radius: 50%;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  cursor: pointer;
}

.uwu-range-slider::-webkit-slider-thumb {
  transform: translateY(-35%);
}

#uwusettings input[type="checkbox"] {
  margin-right: 8px;
  appearance: none;
  transform: translate(-10%, 30%);
  width: 35px;
  height: 18px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 20px;
  cursor: pointer;
  transition: background-color 0.2s ease-in-out;
}

#uwusettings input[type="checkbox"]:checked {
  background-color: #90ff78a8;
}

#uwusettings input[type="checkbox"]:not(:checked) {
  background-color: rgba(255, 255, 255, 0.1);
}

#uwusettings input[type="checkbox"]:before {
  content: "";
  position: absolute;
  top: 50%;
  left: 4px;
  transform: translate(-50%, -50%);
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.1);
  transition: background-color 0.2s ease-in-out, left 0.2s ease-in-out;
}

#uwusettings input[type="checkbox"]:checked:before {
  left: calc(100% - 4px);
}

#uwusettings input[type="text"] {
  width: 150px;
  background-color: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 8px;
  border-radius: 10px;
  outline: none;
  margin: 5px;
  margin-left: 0px;
}
`;
// ====================================================================================================================
//   . . . КЛАССИЧЕСКАЯ ТЕМА . . .
// ====================================================================================================================
// лол а где
const css_uwu_classic = `

`;
// ====================================================================================================================
//   . . . топовой шрифт кто не согласен тому в глаз 👅👅👅👅👅👅бе бе бе мяу мяу мяу мяу мяу мяу . . .
// ====================================================================================================================
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://fonts.googleapis.com/css?family=Montserrat';
document.head.appendChild(link);
// TODO - автоматически подкачивать шрифты нужные пользователю по названию в "Название вида шрифта" в Настройках
// ====================================================================================================================
//  . . . СОХРАНЕНИЯ И ЗАГРУЗКА НАСТРОЕК . . .
// ====================================================================================================================
let settings;

function saveSettings() {
  try {
    localStorage.setItem("uwu_settings", JSON.stringify(settings));
    // console.log("Настройки сохранены:", settings);
  } catch (error) {
    console.error("Не удалось сохранить настройки:", error);
  }
}

function loadSettings() {
  const storedSettings = localStorage.getItem("uwu_settings");
  if (storedSettings && typeof storedSettings === "string") {
    const loadedSettings = JSON.parse(storedSettings);
    settings = { ...uwuDefaultSettings, ...loadedSettings };
  } else {
    settings = { ...uwuDefaultSettings };
    console.log("Нет сохраненных настроек");
  }
}
// ====================================================================================================================
//   . . . ДИНАМИЧНЫЕ ОБОЗРЕВАТЕЛИ . . .
// ====================================================================================================================
function debounce(func, wait) {
  let timeout;
  return function (...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

// Когда нужно вставить прослушку на какой-то элемент, который ещё не успел появиться.
async function setupMutationObserver(
  selector,
  callback,
  options = { attributes: true, attributeFilter: ["style"] },
  maxAttempts = 8,
  delay = 500,
  debounceTime = 100,
) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const element = document.querySelector(selector);
    if (element) {
      const observer = new MutationObserver(debounce(callback, debounceTime));
      observer.observe(element, options);
      // console.log(`Наблюдатель установлен для элемента с селектором "${selector}".`);
      callback();
      return;
    }
    await new Promise((resolve) => setTimeout(resolve, delay));
  }
  // console.warn(
  //   `Элемент с селектором "${selector}" не найден после ${maxAttempts} попыток.`
  // );
}

// Когда нужно вставить что-то в какой-то элемент, который ещё не успел появиться.
async function setupSingleCallback(
  selector,
  callback,
  maxAttempts = 8,
  delay = 500,
) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const element = document.querySelector(selector);
    if (element) {
      callback();
      return;
    }
    await new Promise((resolve) => setTimeout(resolve, delay));
  }
  // console.warn(
  //   `Элемент с селектором "${selector}" не найден после ${maxAttempts} попыток.`
  // );
}
// ====================================================================================================================
//   . . . СОХРАНЕНИЕ И РАБОТА С ЦВЕТОВЫМИ ТЕМАМИ . . .
// ====================================================================================================================
function getThemes() {
  const storedThemes = localStorage.getItem("uwu_colorThemes");
  const userThemes = storedThemes ? JSON.parse(storedThemes) : {};
  return { ...userThemes, ...defaultThemes };
}

function saveThemes(themes) {
  const themesToSave = Object.keys(themes)
    .filter(themeName => !isDefaultTheme(themeName))
    .reduce((obj, key) => {
      obj[key] = themes[key];
      return obj;
    }, {}); 

  localStorage.setItem("uwu_colorThemes", JSON.stringify(themesToSave));
}

function getCurrentThemeName() {
  return localStorage.getItem("uwu_currentTheme") || "Тёмная Тема";
}

function setCurrentThemeName(themeName) {
  localStorage.setItem("uwu_currentTheme", themeName);
}

function isDefaultTheme(themeName) {
  return Object.keys(defaultThemes).includes(themeName);
}

function updateSaveButtonState() {
  saveThemeButton.disabled = isDefaultTheme(currentThemeName);
}

// ====================================================================================================================
//  . . . ВНЕШНИЙ ВИД ПАНЕЛИ НАСТРОЕК . . .
// ====================================================================================================================
function applyBackgroundImage(element, backgroundImage) {
  element.style.backgroundImage = backgroundImage;
}

function createSettingsBlock(blockId, content) {
  const siteTable = document.querySelector("#site_table");
  const isMobile = siteTable.getAttribute("data-mobile") === "0";

  const settingsElement = document.createElement("div");
  settingsElement.id = blockId;
  settingsElement.innerHTML = content;

  const settingsContainer = isMobile
    ? document.querySelector("#branch")
    : siteTable;
  settingsContainer.appendChild(settingsElement);
}
// ====================================================================================================================
//  . . . РАБОТА ПАНЕЛИ НАСТРОЕК . . .
// ====================================================================================================================
if (targetSettings.test(window.location.href)) {
  createSettingsBlock("uwu-settings", uwusettings);

  const uwuSettingsElement = document.getElementById("uwusettings");
  if (uwuSettingsElement) {
    uwuSettingsElement.insertAdjacentHTML("beforeend", newsPanel);
  }

  loadSettings();

  if (!settings.extendedHints) {
    const uwuHideHints = document.createElement("style");
    uwuHideHints.innerHTML = `
    #uwusettings p {
      display: none;
    }
    `;
    document.head.appendChild(uwuHideHints);
  }

  document
    .querySelectorAll("#uwusettings [data-setting]")
    .forEach((element) => {
      const setting = element.dataset.setting;
      if (element.type === "checkbox") {
        element.checked = settings[setting];
      } else {
        element.value = settings[setting];
      }
    });

  // ====================================================================================================================
  //  . . . ТЕМА UWU . . .
  // ====================================================================================================================
  function applySettingsTheme(theme) {
    let css;
    const settingsBlock = document.getElementById("uwu-settings");
    const settingsHeader = document.getElementById("uwusettings-header");
  
    switch (theme) {
      case "classic":
        css = css_uwu_classic;
        break;
      case "dark":
        css = css_uwu_dark;
        const backgroundImageDark = window.getComputedStyle(document.body).backgroundImage;
        applyBackgroundImage(settingsHeader, backgroundImageDark);
        settingsHeader.classList.add("header-rounded-image");
        break;
      case "glass":
        css = css_uwu_glass;
        const backgroundImageGlass = window.getComputedStyle(document.body).backgroundImage;
        applyBackgroundImage(settingsBlock, backgroundImageGlass);
        settingsBlock.classList.add("main-rounded-image");
        break;
      default:
        css = css_uwu_classic;
        break;
    }
  
    const oldStyle = document.getElementById("css-uwu-theme");
    if (oldStyle) {
      oldStyle.remove();
    }
  
    document.head.insertAdjacentHTML(
      "beforeend",
      `<style id="css-uwu-theme">${css}</style>`
    );
  }
  
  applySettingsTheme(settings.settingsTheme);
  // ====================================================================================================================
  //  . . . ШРИФТ ГРОМКОСТИ ЧАТА . . .
  // ====================================================================================================================
  function saveFontSettings() {
    let fontSize = {};
  
    document.querySelectorAll('input[data-font-size]').forEach(input => {
      fontSize[input.dataset.fontSize] = input.value;
    });
  
    localStorage.setItem('uwu_fontSize', JSON.stringify(fontSize));
  }
  
  function loadFontSettings() {
    let defaultFontSize = {
      vlm0: '10',
      vlm1: '11',
      vlm2: '11.5',
      vlm3: '12',
      vlm4: '12.5',
      vlm5: '13',
      vlm6: '15',
      vlm7: '17',
      vlm8: '19',
      vlm9: '21',
      vlm10: '23',
      fontSizeBody: '14',
      fontSizeSmall: '12',
      fontSizeLocation: '14',
      fontFamilyBody: 'Verdana'
    };
  
    let fontSize = JSON.parse(localStorage.getItem('uwu_fontSize')) || defaultFontSize;
  
    document.querySelectorAll('input[data-font-size]').forEach(input => {
      input.value = fontSize[input.dataset.fontSize] || ''; 
    });

    saveFontSettings();
  }
  
  document.querySelectorAll('input[data-font-size]').forEach(input => {
    input.addEventListener('input', saveFontSettings); 
  });
  
  loadFontSettings();
  // ====================================================================================================================
  //  . . . ТЕМЫ И ЦВЕТА ИГРОВОЙ . . .
  // ====================================================================================================================
  const colorInputs = document.querySelectorAll("#color-picker input[type='text']");
  const saveThemeButton = document.getElementById("saveThemeButton");
  const themeSelect = document.getElementById("theme-select");
  const addThemeButton = document.getElementById("addThemeButton");
  const removeThemeButton = document.getElementById("removeThemeButton");
  
  let currentThemeName = getCurrentThemeName();
  let allThemes = getThemes();
  
  function loadThemeToInputs(themeName) {
    const theme = allThemes[themeName]?.colors;
    colorInputs.forEach((input) => {
      const colorKey = input.dataset.color;
      input.value = theme?.[colorKey] || "";
    });
  }
  
  function saveThemeFromInputs() {
    const themeData = { colors: {} };
    colorInputs.forEach((input) => {
      const colorKey = input.dataset.color;
      themeData.colors[colorKey] = input.value;
    });
    allThemes[currentThemeName] = themeData; 
    saveThemes(allThemes);
    console.log(`Тема "${currentThemeName}" сохранена!`);
  }
  
  function updateThemeSelect() {
    themeSelect.innerHTML = "";
    Object.keys(allThemes).forEach((name) => {
      const option = document.createElement("option");
      option.value = name;
      option.textContent = name;
      themeSelect.appendChild(option);
    });
    themeSelect.value = currentThemeName;
    removeThemeButton.style.display = Object.keys(defaultThemes).includes(currentThemeName) ? "none" : "inline";
  }
  
  themeSelect.addEventListener("change", (event) => {
    currentThemeName = event.target.value;
    setCurrentThemeName(currentThemeName);
    loadThemeToInputs(currentThemeName);
    updateThemeSelect(); 
    updateSaveButtonState();
  });
  
  addThemeButton.addEventListener("click", () => {
    const newThemeName = prompt("Введите название новой темы:");
    if (newThemeName && !allThemes[newThemeName]) {
      allThemes[newThemeName] = { colors: {} };
      saveThemes(allThemes);
      updateThemeSelect();
      themeSelect.value = newThemeName;
      currentThemeName = newThemeName;
      setCurrentThemeName(currentThemeName);
      loadThemeToInputs(currentThemeName);
    }
  });
  
  removeThemeButton.addEventListener("click", () => {
    if (!Object.keys(defaultThemes).includes(currentThemeName)) {
      delete allThemes[currentThemeName];
      saveThemes(allThemes);
      currentThemeName = "Тёмная Тема";
      setCurrentThemeName(currentThemeName);
      updateThemeSelect();
      loadThemeToInputs(currentThemeName);
    }
  });
  
  saveThemeButton.addEventListener("click", () => {
    if (isDefaultTheme(currentThemeName)) {
      alert("Вы не можете изменять стандартные темы. Пожалуйста, создайте свою собственную тему.");
    } else {
      saveThemeFromInputs();
    }
  });
  
  colorInputs.forEach((input) => {
    input.addEventListener("input", () => {
      if (isDefaultTheme(currentThemeName)) {
        alert("Вы не можете изменять стандартные темы. Пожалуйста, создайте свою собственную тему.");
        loadThemeToInputs(currentThemeName); 
      } else {
        saveThemeFromInputs(); 
      }
    });
  });
  
  updateThemeSelect();
  loadThemeToInputs(currentThemeName);
  // ====================================================================================================================
  //  . . . РАБОТА ЦВЕТОВ НАВЫКОВ И ПАРАМЕТРОВ . . .
  // ====================================================================================================================
  document
    .querySelectorAll('#parameters-color-settings input[type="color"]')
    .forEach((element) => {
      element.addEventListener("change", () => {
        const paramId = element.dataset.param;
        const colorType = element.dataset.colorType;
        const colorValue = element.value;

        if (!settings.parametersColors[paramId]) {
          settings.parametersColors[paramId] = [];
        }
        const colorIndex =
          colorType === "bar-from"
            ? 0
            : colorType === "bar-to"
            ? 1
            : colorType === "bg-from"
            ? 2
            : 3;
        settings.parametersColors[paramId][colorIndex] = colorValue;

        saveSettings();
      });
    });

  function restoreColorPickers() {
    for (const paramId in settings.parametersColors) {
      const colors = settings.parametersColors[paramId];

      const barFromInput = document.querySelector(
        `#parameters-color-settings input[type="color"][data-param="${paramId}"][data-color-type="bar-from"]`
      );
      const barToInput = document.querySelector(
        `#parameters-color-settings input[type="color"][data-param="${paramId}"][data-color-type="bar-to"]`
      );
      const bgFromInput = document.querySelector(
        `#parameters-color-settings input[type="color"][data-param="${paramId}"][data-color-type="bg-from"]`
      );
      const bgToInput = document.querySelector(
        `#parameters-color-settings input[type="color"][data-param="${paramId}"][data-color-type="bg-to"]`
      );

      if (barFromInput) barFromInput.value = colors[0];
      if (barToInput) barToInput.value = colors[1];
      if (bgFromInput) bgFromInput.value = colors[2];
      if (bgToInput) bgToInput.value = colors[3];
    }
  }
  restoreColorPickers();
  // ====================================================================================================================
  //  . . . ПОДСВЕТКА РЕСУРСОВ . . .
  // ====================================================================================================================
  function saveHighlightSettings() {
    const highlightResources = [];
  
    document.querySelectorAll('.uwu-table-highlight-Resources tbody tr').forEach(row => {
      const resourceName = row.querySelector('.uwu-color-picker').dataset.resource;
      const colorPicker = row.querySelector('.uwu-color-picker');
      const checkbox = row.querySelector('.uwu-highlight-checkbox');
  
      const resource = {
        name: resourceName,
        color: colorPicker.value,
        highlight: checkbox.checked
      };
  
      highlightResources.push(resource);
    });
  
    localStorage.setItem('uwu_highlightResources', JSON.stringify(highlightResources));
  }
  
  function restoreHighlightSettings() {
    const savedSettings = localStorage.getItem('uwu_highlightResources');
    if (savedSettings) {
      const highlightResources = JSON.parse(savedSettings);
  
      highlightResources.forEach(resource => {
        const colorPicker = document.querySelector(`.uwu-color-picker[data-resource="${resource.name}"]`);
        const checkbox = document.querySelector(`.uwu-highlight-checkbox[data-resource="${resource.name}"]`);
  
        if (colorPicker) colorPicker.value = resource.color;
        if (checkbox) checkbox.checked = resource.highlight;
      });
    }
  }

restoreHighlightSettings();

document.querySelectorAll('.uwu-color-picker').forEach(element => {
  element.addEventListener('input', saveHighlightSettings);
});

document.querySelectorAll('.uwu-highlight-checkbox').forEach(element => {
  element.addEventListener('change', saveHighlightSettings);
});

  // ====================================================================================================================
  //  . . . ЦВЕТА КОМАНДНЫХ БОЁВ . . .
  // ====================================================================================================================
  document
    .querySelectorAll('#colorSettingsTable input[type="color"]')
    .forEach((element) => {
      element.addEventListener("change", () => {
        const team = `team${element.dataset.team}`;
        const part = element.dataset.part === "green" ? 0 : 1;
        const colorValue = element.value;
        settings.fightTeamsColors[team][part] = colorValue;
        saveSettings();
      });
    });

  function restoreColorTeamsPickers() {
    document
      .querySelectorAll('#colorSettingsTable input[type="color"]')
      .forEach((element) => {
        element.addEventListener("change", () => {
          const team = `team${element.dataset.team}`;
          const part = element.dataset.part === "green" ? 0 : 1;
          const colorValue = element.value;
          settings.fightTeamsColors[team][part] = colorValue;
          saveSettings();
        });
      });
  }

  restoreColorTeamsPickers();
  // ====================================================================================================================
  //   . . . СБРОС НАСТРОЕК . . .
  // ====================================================================================================================
  const settingsKeys = [
    "uwu_settings",
    "uwu_version",
    "uwu_layoutSettings",
    "uwu_climbingPanelState",
    "uwu_moduleStates",
    "uwu_fightPanelPosition",
    "uwu_climbingPanelStatus",
    "uwu_privateModules",
    "uwu_colorThemes",
    "uwu_currentTheme",
    "uwu_fontSize",
    "uwu_clock",
  ];

  function resetAllSaves() {
    const confirmReset = confirm(
      "Точно сбросить все UwU Настройки? Это удалить даже ваши карты Минных полей, темы и многое другое!"
    );
    if (confirmReset) {
      settingsKeys.forEach((key) => {
        localStorage.removeItem(key);
        console.log(`Удалено ${key}`);
      });
      console.log("Все настройки сброшены");
    } else {
      console.log("Сброс настроек отменен");
    }
  }

  document
    .getElementById("resetAllSaves")
    .addEventListener("click", resetAllSaves);
  // ====================================================================================================================
  //  . . . ВЗАИМОИСКЛЮЧАЮЩИЕСЯ ЧЕКБОКСЫ . . .
  // ====================================================================================================================
  const exclusiveCheckboxGroups = [
    ["backgroundRepeat", "backgroundUser"],
    ["parametersBackgroundImage", "parametersUserBackgroundImage"],
  ];

  document
    .querySelectorAll("#uwusettings [data-setting]")
    .forEach((element) => {
      const setting = element.dataset.setting;
      element.addEventListener("change", () => {
        if (element.type === "checkbox") {
          const group = exclusiveCheckboxGroups.find((g) =>
            g.includes(setting)
          );
          if (group) {
            group.forEach((s) => {
              if (s !== setting) {
                settings[s] = false;
                document.querySelector(
                  `#uwusettings [data-setting="${s}"]`
                ).checked = false;
              }
            });
          }
          settings[setting] = element.checked;
        } else {
          settings[setting] = element.value;
        }
        saveSettings();
      });
    });
  // ====================================================================================================================
  //  . . . СОЗДАНИЕ ВЫПАДАЮЩИХ СПИСКОВ ПРИ ПОМОЩИ ФУНКЦИИ createCustomSelect . . .
  // ====================================================================================================================
  loadSettings();
  // Звуки звуки звуки, вуху.
  const notificationSounds = [
    { name: "Звук 1", id: "notificationSound1" },
    { name: "Звук 2", id: "notificationSound2" },
    { name: "Звук 3", id: "notificationSound3" },
  ];

  createCustomSelect("climbingRefreshNotificationSound", notificationSounds);
  createCustomSelect("myNameNotificationSound", notificationSounds);
  // ==============================================================================
  const howShowOtherCatsList = [
    { name: "Не отображать", id: "1" },
    { name: "Компактно", id: "2" },
    { name: "Целиком", id: "3" },
  ];

  createCustomSelect("showOtherCatsList", howShowOtherCatsList);
  // ==============================================================================
  const themeOptions = [
    { id: "classic", name: "Классическая" },
    { id: "dark", name: "Тёмная" },
    { id: "glass", name: "Стеклянная" },
  ];
  
  createCustomSelect("settingsTheme", themeOptions);
  // ==============================================================================
  const climbingPanelOrientations = [
    { id: "vertical", name: "Вертикальный" },
    { id: "horizontal", name: "Горизонтальный" },
  ]

  createCustomSelect("climbingPanelOrientation", climbingPanelOrientations);
    // ==============================================================================
    const clockStyles = [
      { id: "compact", name: "Компактный" },
      { id: "standard", name: "Стандартный" },
    ]
  
    createCustomSelect("clockStyle", clockStyles);
    // ==============================================================================
    const clockPositions = [
      { id: "fly", name: "Свободно" },
      { id: "tos", name: "В блоке погоды" },
    ]
  
    createCustomSelect("clockPosition", clockPositions);
    // ==============================================================================
    const highlightResourcesStyles = [
      { id: "background", name: "Фон / Быстро" },
      { id: "glow", name: "Свечение / Медленно" },
    ]
    
    createCustomSelect("highlightResourcesStyle", highlightResourcesStyles);
  // ====================================================================================================================
  //   . . . СОЗДАНИЕ ВЫПАДАЮЩИХ СПИСКОВ . . .
  // ====================================================================================================================
  function createCustomSelect(selectId, options) {
  
    const selectContainer = document.getElementById(selectId);
    const selectedElement = selectContainer.querySelector(".select-selected");
    const optionsContainer = selectContainer.querySelector(".select-items");
  
    if (settings && settings[selectId] !== undefined) {
      const selectedOption = options.find(
        (option) => option.id === settings[selectId]
      );
      if (selectedOption) {
        selectedElement.textContent = selectedOption.name;
      }
    }
  
    options.forEach((option, index) => {
      const optionElement = document.createElement("div");
      optionElement.textContent = option.name;
      optionElement.dataset.id = option.id;
  
      optionElement.addEventListener("click", () => {
        selectedElement.textContent = option.name;
        settings[selectId] = option.id;
        saveSettings();
        selectContainer.classList.remove("active");
      });
  
      optionsContainer.appendChild(optionElement);
    });
  
    selectedElement.addEventListener("click", () => {
      selectContainer.classList.toggle("active");
    });
  }
  // ====================================================================================================================
  //  . . . КНОПКА НОВОСТЕЙ . . .
  // ====================================================================================================================
  window.addEventListener("load", () => {
    const newsButton = document.getElementById("news-button");
    const newsList = document.getElementById("news-list");

    if (newsButton && newsList) {
      newsButton.addEventListener("click", () => {
        if (newsList.style.display === "none") {
          newsList.style.display = "block";
        } else {
          newsList.style.display = "none";
        }
      });
    }
  });
  // ====================================================================================================================
  //   . . . КНОПКА ТЕСТА ЗВУКОВ . . .
  // ====================================================================================================================
  function addSoundTestButton(
    containerId,
    settingsKeyForSound,
    settingsKeyForVolume
  ) {
    const container = document.getElementById(containerId);
    if (!container) {
      console.error(`Контейнер с ID ${containerId} не найден.`);
      return;
    }

    const testButton = document.createElement("button");
    testButton.textContent = "Тест звука";
    testButton.addEventListener("click", () => {
      const selectedSoundId = settings[settingsKeyForSound];
      const volume = settings[settingsKeyForVolume] || 5;
      if (selectedSoundId) {
        soundManager.playSound(selectedSoundId, volume);
      } else {
        console.error(
          `Выбранный звук для контейнера ${containerId} не найден.`
        );
      }
    });

    container.appendChild(testButton);
  }

  addSoundTestButton(
    "climbingRefreshNotificationSoundContainer",
    "climbingRefreshNotificationSound",
    "climbingRefreshNotificationVolume"
  );
  addSoundTestButton(
    "myNameNotificationSoundContainer",
    "myNameNotificationSound",
    "notificationMyNameVolume"
  );
  // ====================================================================================================================
  //  . . . СБРОС ПОЗИЦИИ ЧАСИКОВ . . .
  // ====================================================================================================================
  document.getElementById('resetClockPosition').addEventListener('click', () => {
    const defaultPosition = { x: 10, y: 10 };
    localStorage.setItem("uwu_clock", JSON.stringify(defaultPosition));
  });
  // ====================================================================================================================
  //  . . . ИМПОРТ / ЭКСПОРТ НАСТРОЕК . . .
  // ====================================================================================================================
  const importButton = document.getElementById("importSettingsButton");
  const importSettingsInput = document.getElementById("importSettings");
  const exportSettingsInput = document.getElementById("exportSettings");

  importButton.addEventListener("click", () => {
    const importedSettings = importSettingsInput.value;

    try {
      const parsedSettings = JSON.parse(importedSettings);
      settings = { ...settings, ...parsedSettings };
      localStorage.setItem("uwu_settings", JSON.stringify(settings));
      console.log("Настройки импортированы:", settings);
    } catch (error) {
      console.error("Ошибка при импорте настроек:", error);
    }
    updateExportField();
  });

  function updateExportField() {
    const settingsToExport = JSON.stringify(settings);
    exportSettingsInput.value = settingsToExport;
  }

  loadSettings();
  updateExportField();
  // ====================================================================================================================
  //  . . . МАКЕТ КАСТОМИЗАЦИИ ИГРОВОЙ . . .
  // ====================================================================================================================
  const blockNames = {
    tr_info: "Информация",
    tr_tos: "Погода",
    tr_chat: "Чат",
    tr_actions: "Действия",
    tr_mouth: "Во рту",
    // 'tr_sky': 'Небо',
  };
  const leftColumn = document.querySelector("#layout-customizer .column.left");
  const rightColumn = document.querySelector(
    "#layout-customizer .column.right"
  );

  function createBlockElement(blockId) {
    const blockElement = document.createElement("div");
    blockElement.classList.add("block", blockId);

    const blockName = document.createElement("span");
    blockName.textContent = blockNames[blockId];
    blockElement.appendChild(blockName);

    const controlsWrapper = document.createElement("div");
    controlsWrapper.classList.add("controls");

    if (blockId === "tr_info") {
      const moveInfoButton = document.createElement("button");
      moveInfoButton.textContent = "⏪Переместить⏩";
      moveInfoButton.classList.add("move-info", "install-button");
      moveInfoButton.addEventListener("click", () => {
        swapColumns(blockElement);
      });
      controlsWrapper.appendChild(moveInfoButton);
    } else {
      const moveUpButton = document.createElement("button");
      moveUpButton.textContent = "🔼Вверх";
      moveUpButton.classList.add("move-up", "install-button");
      moveUpButton.addEventListener("click", () => {
        const previousBlock = blockElement.previousElementSibling;
        if (previousBlock) {
          blockElement.parentNode.insertBefore(blockElement, previousBlock);
        }
      });
      controlsWrapper.appendChild(moveUpButton);

      const moveDownButton = document.createElement("button");
      moveDownButton.textContent = "🔽Вниз";
      moveDownButton.classList.add("move-down", "install-button");
      moveDownButton.addEventListener("click", () => {
        const nextBlock = blockElement.nextElementSibling;
        if (nextBlock) {
          blockElement.parentNode.insertBefore(nextBlock, blockElement);
        }
      });
      controlsWrapper.appendChild(moveDownButton);
    }

    blockElement.appendChild(controlsWrapper);
    return blockElement;
  }

  function swapColumns(blockElement) {
    if (blockElement.parentNode === leftColumn) {
      const rightColumnBlocks = Array.from(rightColumn.children);
      rightColumn.innerHTML = "";
      rightColumn.appendChild(blockElement);
      rightColumnBlocks.forEach((block) => leftColumn.appendChild(block));
    } else {
      const leftColumnBlocks = Array.from(leftColumn.children);
      leftColumn.innerHTML = "";
      leftColumn.appendChild(blockElement);
      leftColumnBlocks.forEach((block) => rightColumn.appendChild(block));
    }
  }

  const saveButton = document.getElementById("SettingSaveButton4");

  saveButton.addEventListener("click", () => {
    const leftBlocks = Array.from(leftColumn.querySelectorAll(".block")).map(
      (block) => block.classList[1]
    );
    const rightBlocks = Array.from(rightColumn.querySelectorAll(".block")).map(
      (block) => block.classList[1]
    );

    const layoutSettings = {
      leftBlocks,
      rightBlocks,
    };

    localStorage.setItem("uwu_layoutSettings", JSON.stringify(layoutSettings));
  });

  function loadLayoutSettings() {
    const savedSettings = localStorage.getItem("uwu_layoutSettings");
    if (savedSettings) {
      const { leftBlocks, rightBlocks } = JSON.parse(savedSettings);

      leftColumn.innerHTML = "";
      rightColumn.innerHTML = "";

      leftBlocks.forEach((blockId) => {
        const blockElement = createBlockElement(blockId);
        leftColumn.appendChild(blockElement);
      });

      rightBlocks.forEach((blockId) => {
        const blockElement = createBlockElement(blockId);
        rightColumn.appendChild(blockElement);
      });
    } else {
      const defaultLeftBlocks = ["tr_info"];
      const defaultRightBlocks = [
        "tr_tos",
        "tr_chat",
        "tr_actions",
        "tr_mouth",
      ];

      defaultLeftBlocks.forEach((blockId) => {
        leftColumn.appendChild(createBlockElement(blockId));
      });

      defaultRightBlocks.forEach((blockId) => {
        rightColumn.appendChild(createBlockElement(blockId));
      });

      const layoutSettings = {
        leftBlocks: defaultLeftBlocks,
        rightBlocks: defaultRightBlocks,
      };
      localStorage.setItem(
        "uwu_layoutSettings",
        JSON.stringify(layoutSettings)
      );
    }
  }

  window.addEventListener("load", loadLayoutSettings);
  // ====================================================================================================================
  //  . . . РЕДАКТОР ВКЛАДОК И ТАБЛИЦ МИННОГО ПОЛЯ . . .
  // ====================================================================================================================
  // как же я ненавижу минное поле как же я ненавижу минное поле как же я ненавижу минное поле
  const tabManager = {
    tabs: [],
    currentTabIndex: 0,
  
    createTab(name) {
      const newTab = {
        name: name,
        tables: [],
        currentTableId: 0,
      };
  
      this.tabs.push(newTab);
      this.render();
      this.switchTab(this.tabs.length - 1);
    },
  
    createTable(
      tableName = `Локация ${this.tabs[this.currentTabIndex].tables.length + 1}`
    ) {
      const currentTab = this.tabs[this.currentTabIndex];
      currentTab.tables.push({ name: tableName });
      this.saveState();
      this.render();
    },
  
    removeTable(tableIndex) {
      const currentTab = this.tabs[this.currentTabIndex];
      if (currentTab && currentTab.tables[tableIndex]) {
        currentTab.tables.splice(tableIndex, 1);
        if (currentTab.currentTableId === tableIndex) {
          currentTab.currentTableId = Math.max(
            0,
            currentTab.currentTableId - 1
          );
        }
        this.saveState();
        this.render();
      }
    },
  
    removeTab(index) {
      this.tabs.splice(index, 1);
      if (index === this.currentTabIndex) {
        this.currentTabIndex = Math.max(0, this.currentTabIndex - 1);
      }
      this.saveState();
      this.render();
    },
  
    switchTab(index) {
      this.currentTabIndex = index;
      this.render();
    },
  
    switchTable(tableIndex) {
      const currentTab = this.tabs[this.currentTabIndex];
      if (currentTab) {
        currentTab.currentTableId = tableIndex;
        this.saveState();
        this.render();
      }
    },
  
    renameTab(index) {
      const newName = prompt("Введите новое имя вкладки:", this.tabs[index].name);
      if (newName) {
        this.tabs[index].name = newName;
        this.saveState();
        this.render();
      }
    },
  
    renameTable(tableIndex) {
      const currentTab = this.tabs[this.currentTabIndex];
      if (currentTab) {
        const newName = prompt("Введите новое имя поля:", currentTab.tables[tableIndex].name);
        if (newName) {
          currentTab.tables[tableIndex].name = newName;
          this.saveState();
          this.render();
        }
      }
    },
  
    saveState() {
      localStorage.setItem("uwu_climbingPanelState", JSON.stringify(this));
    },
  
    render() {
      this.renderTabs();
      this.renderTables();
    },
  
    renderTabs() {
      const tabRow = document.getElementById("uwu-buttonRow1-settings");
      tabRow.innerHTML = "";
  
      this.tabs.forEach((tab, index) => {
        const tabButton = document.createElement("button");
        tabButton.textContent = tab.name;
        tabButton.classList.add("tab-button");
  
        if (index === this.currentTabIndex) {
          tabButton.classList.add("active");
        }
  
        tabButton.addEventListener("click", () => this.switchTab(index));
  
        const removeButton = document.createElement("button");
        removeButton.textContent = "X";
        removeButton.classList.add("remove-button");
  
        removeButton.addEventListener("click", () => this.removeTab(index));
  
        const renameButton = document.createElement("button");
        renameButton.textContent = "✎";
        renameButton.classList.add("rename-button");
  
        renameButton.addEventListener("click", () => this.renameTab(index));
  
        const tabContainer = document.createElement("div");
        tabContainer.classList.add("tab-container");
        tabContainer.appendChild(tabButton);
        tabContainer.appendChild(renameButton);
        tabContainer.appendChild(removeButton);
  
        tabRow.appendChild(tabContainer);
      });
  
      const addTabButton = document.createElement("button");
      addTabButton.textContent = "+";
      addTabButton.classList.add("add-button");
      addTabButton.addEventListener("click", () => {
        const tabName = prompt("Введите имя вкладки:");
        if (tabName) {
          this.createTab(tabName);
        }
      });
      tabRow.appendChild(addTabButton);
    },
  
    renderTables() {
      const tableRow = document.getElementById("uwu-buttonRow2-settings");
      tableRow.innerHTML = "";
  
      const currentTab = this.tabs[this.currentTabIndex];
  
      if (currentTab) {
        currentTab.tables.forEach((table, index) => {
          const tableButton = document.createElement("button");
          tableButton.textContent = table.name;
          tableButton.classList.add("table-button");
  
          tableButton.addEventListener("click", () => this.switchTable(index));
  
          const removeButton = document.createElement("button");
          removeButton.textContent = "X";
          removeButton.classList.add("remove-button");
  
          removeButton.addEventListener("click", () => this.removeTable(index));
  
          const renameButton = document.createElement("button");
          renameButton.textContent = "✎";
          renameButton.classList.add("rename-button");
  
          renameButton.addEventListener("click", () => this.renameTable(index));
  
          const tableContainer = document.createElement("div");
          tableContainer.classList.add("table-container");
          tableContainer.appendChild(tableButton);
          tableContainer.appendChild(renameButton);
          tableContainer.appendChild(removeButton);
  
          tableRow.appendChild(tableContainer);
        });
  
        const addTableButton = document.createElement("button");
        addTableButton.textContent = "+";
        addTableButton.classList.add("add-button");
  
        addTableButton.addEventListener("click", () => {
          const tableName = prompt("Введите имя поля:");
          if (tableName) {
            this.createTable(tableName);
          }
        });
  
        tableRow.appendChild(addTableButton);
      }
    },
  };
  
  const savedState = localStorage.getItem("uwu_climbingPanelState");
  if (!savedState) {
    tabManager.createTab("Вкладка 1");
    for (let i = 0; i < 5; i++) {
      tabManager.createTable(`Поле ${i + 1}`);
    }
  
    tabManager.createTab("Вкладка 2");
    for (let i = 0; i < 5; i++) {
      tabManager.createTable(`Поле ${i + 1}`);
    }
  
    tabManager.saveState();
  } else {
    const state = JSON.parse(savedState);
    Object.assign(tabManager, state);
  }
  
  tabManager.render();
}
// ====================================================================================================================
//  . . . ВКЛАДКИ ГЛАВНЫХ НАСТРОЕК . . .
// ====================================================================================================================
if (targetSettings.test(window.location.href)) {
  const buttonContainer = document.getElementById("button-container");

  buttonContainer.addEventListener("click", (event) => {
    const clickedElement = event.target;
    const clickedButton = clickedElement.closest("button");
    if (!clickedButton) return;

    const panelId = clickedButton.id.replace("button", "panel");
    const targetPanel = document.getElementById(panelId);

    buttonContainer.querySelectorAll("button").forEach((button) => {
      const correspondingPanelId = button.id.replace("button", "panel");
      const correspondingPanel = document.getElementById(correspondingPanelId);

      correspondingPanel.style.display =
        correspondingPanel === targetPanel ? "block" : "none";
      button.classList.toggle("active", button === clickedButton);
    });
  });

  const defaultButton = buttonContainer.querySelector("button");
  const defaultPanelId = defaultButton.id.replace("button", "panel");
  const defaultPanel = document.getElementById(defaultPanelId);

  buttonContainer.querySelectorAll("button").forEach((button) => {
    const correspondingPanelId = button.id.replace("button", "panel");
    const correspondingPanel = document.getElementById(correspondingPanelId);

    if (correspondingPanel !== defaultPanel) {
      correspondingPanel.style.display = "none";
    }
  });

  defaultPanel.style.display = "block";
  defaultButton.classList.add("active");
}
// ====================================================================================================================
//  . . . ОНЛАЙН МАГАЗИН СТИЛЕЙ . . .
// ====================================================================================================================
// буду вечно задаваться вопросом, а зачем я это вообще сделал..................
const moduleStates = {};
const defaultModules = [
  // "style.css",
  // ...
];
const privateModules = {};

function loadModuleStates() {
  const storedModuleStates = localStorage.getItem("uwu_moduleStates");
  if (storedModuleStates) {
    const loadedModuleStates = JSON.parse(storedModuleStates);
    Object.assign(moduleStates, loadedModuleStates);
  } else {
    for (const moduleName of defaultModules) {
      moduleStates[moduleName] = true;
    }
  }

  const storedPrivateModules = localStorage.getItem("uwu_privateModules");
  if (storedPrivateModules) {
    Object.assign(privateModules, JSON.parse(storedPrivateModules));
  }
}

async function loadModuleListOnSettings() {
  const url =
    "https://raw.githubusercontent.com/Ibirtem/CatWar/main/modules/modules.txt";

  const targetSettings = /^https:\/\/catwar\.net\/settings/;
  if (!targetSettings.test(window.location.href)) {
    return;
  }

  try {
    const response = await fetch(url);
    const moduleList = await response.text();
    const modules = moduleList.split("\n").filter((line) => line.trim() !== "");

    const moduleInfoContainer = document.getElementById("module-info");

    if (!moduleInfoContainer) {
      console.error("Контейнер модулей не найден!");
      return;
    }

    for (const moduleInfo of modules) {
      const [moduleName, description, version] = moduleInfo.split("|");
      const isOnlineModule = !localStorage.getItem(moduleName);
      const moduleContainer = createModuleContainer(
        moduleName,
        description,
        version,
        isOnlineModule
      );
      moduleInfoContainer.appendChild(moduleContainer);

      if (moduleStates[moduleName]) {
        loadModule(moduleName, description, version);
      }
    }

    for (const [moduleName, moduleInfo] of Object.entries(privateModules)) {
      const { description, version } = moduleInfo;
      const isPrivateModule = true;
      const moduleContainer = createModuleContainer(
        moduleName,
        description,
        version,
        false,
        isPrivateModule
      );
      moduleInfoContainer.appendChild(moduleContainer);

      if (moduleStates[moduleName]) {
        loadModule(moduleName, description, version);
      }
    }
  } catch (error) {
    console.error("Ошибка при загрузке списка модулей:", error);
  }
}

async function activateModules() {
  const url =
    "https://raw.githubusercontent.com/Ibirtem/CatWar/main/modules/modules.txt";

  try {
    const response = await fetch(url);
    const moduleList = await response.text();
    const modules = moduleList.split("\n").filter((line) => line.trim() !== "");

    for (const moduleInfo of modules) {
      const [moduleName, description, version] = moduleInfo.split("|");
      const isOnlineModule = !localStorage.getItem(moduleName);

      if (moduleStates[moduleName]) {
        loadModule(moduleName, description, version);
      }
    }

    for (const [moduleName, moduleInfo] of Object.entries(privateModules)) {
      const { description, version } = moduleInfo;

      if (moduleStates[moduleName]) {
        loadModule(moduleName, description, version);
      }
    }
  } catch (error) {
    console.error("Ошибка при активации модулей:", error);
  }
}

function createModuleContainer(
  moduleName,
  description,
  version,
  isOnlineModule = false,
  isPrivateModule = false
) {
  const moduleContainer = document.createElement("div");
  moduleContainer.classList.add("module-container");

  const moduleInfo = document.createElement("div");
  moduleInfo.classList.add("module-info");
  moduleInfo.textContent = `${description}`;

  const modulePanel = document.createElement("div");
  modulePanel.classList.add("module-panel");

  const versionInfo = document.createElement("span");
  versionInfo.textContent = `Версия: ${version}`;
  modulePanel.appendChild(versionInfo);

  if (isOnlineModule) {
    const installButton = document.createElement("button");
    installButton.textContent = "Установить";
    installButton.classList.add("install-button");
    installButton.addEventListener("click", () => {
      loadModule(moduleName, description, version);
      moduleContainer.remove();
      createModuleContainer(
        moduleName,
        description,
        version,
        false,
        isPrivateModule
      );
    });
    modulePanel.appendChild(installButton);
  } else {
    const checkboxContainer = document.createElement("div");
    checkboxContainer.classList.add("checkbox-container");

    const checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    checkbox.id = moduleName;
    checkbox.checked = moduleStates[moduleName] || false;
    checkboxContainer.appendChild(checkbox);

    const removeButton = document.createElement("button");
    removeButton.textContent = "Удалить";
    removeButton.classList.add("remove-button");
    removeButton.addEventListener("click", () => {
      unloadModule(moduleName);
      moduleContainer.remove();
    });
    modulePanel.appendChild(removeButton);

    checkbox.addEventListener("change", () => {
      moduleStates[moduleName] = checkbox.checked;
      localStorage.setItem("uwu_moduleStates", JSON.stringify(moduleStates));

      if (checkbox.checked) {
        loadModule(moduleName, description, version);
      }
    });

    moduleInfo.appendChild(checkboxContainer);
  }

  moduleContainer.appendChild(moduleInfo);
  moduleContainer.appendChild(modulePanel);

  return moduleContainer;
}

async function loadModule(moduleName, description, version) {
  const cachedModule = localStorage.getItem(moduleName);

  if (cachedModule) {
    activateModule(cachedModule, moduleName, description, version);
  } else {
    const url = `https://raw.githubusercontent.com/Ibirtem/CatWar/main/modules/${moduleName}`;
    try {
      const response = await fetch(url);
      if (response.ok) {
        const data = await response.text();
        localStorage.setItem(moduleName, data);
        activateModule(data, moduleName, description, version);

        moduleStates[moduleName] = true;
        localStorage.setItem("uwu_moduleStates", JSON.stringify(moduleStates));

        createModuleContainer(moduleName, description, version, false);

        loadModuleStates();
        clearModuleInfoContainer();
        loadModuleListOnSettings();
      } else {
        console.error(
          `Ошибка при загрузке модуля "${moduleName}": ${response.status} ${response.statusText}`
        );
      }
    } catch (error) {
      console.error("Ошибка при загрузке модуля:", error);
    }
  }
}

function addStyle(css) {
  const style = document.createElement('style');
  style.appendChild(document.createTextNode(css));
  document.head.appendChild(style);
}

function activateModule(data, moduleName, description, version) {
  if (moduleName.endsWith(".css")) {
    addStyle(data);
  } else if (moduleName.endsWith(".js")) {
    try {
      new Function(data);
      eval(data);
    } catch (error) {
      console.error(`Ошибка при активации модуля "${moduleName}":`, error);
    }
  }
}

function unloadModule(moduleName) {
  localStorage.removeItem(moduleName);
  delete moduleStates[moduleName];
  localStorage.setItem("uwu_moduleStates", JSON.stringify(moduleStates));

  if (privateModules[moduleName]) {
    delete privateModules[moduleName];
    localStorage.setItem("uwu_privateModules", JSON.stringify(privateModules));
  }

  loadModuleStates();
  clearModuleInfoContainer();
  loadModuleListOnSettings();
}

function clearModuleInfoContainer() {
  const moduleInfoContainer = document.getElementById("module-info");
  while (moduleInfoContainer.firstChild) {
    moduleInfoContainer.removeChild(moduleInfoContainer.firstChild);
  }
}

loadModuleStates();
loadModuleListOnSettings();
window.addEventListener("load", activateModules);
// ====================================================================================================================
//   . . . ЗАГРУЗКА НАСТРОЕК . . .
// ====================================================================================================================
loadSettings();
// ====================================================================================================================
//   . . . АВАТАРЫ В КОММЕНТАРИЯХ . . .
// ====================================================================================================================
if (window.location.href !== targetCW3) {
  if (settings.commentsAvatars) {
    const styleElement = document.createElement("style");
    styleElement.textContent = `
      .avatar-img {
        width: 100px;
        height: 100px;
        object-fit: cover;
        float: left;
        margin: 5px;
        border: black solid 1px;
      }
    `;
    document.head.appendChild(styleElement);

    startCheckingForComments();
  }

  function startCheckingForComments() {
    setupMutationObserver("#view_comments", insertAvatars, {
      childList: true,
    });
  }

  function insertAvatars() {
    const comments = document.querySelectorAll(".view-comment");
    comments.forEach((comment) => {
      if (!comment.querySelector('.avatar-img')) {
        const authorLink = comment.querySelector(".author");
        const catId = authorLink ? authorLink.getAttribute("href").match(/\/cat(\d+)/)?.[1] : null;

        const avatarImg = document.createElement("img");
        avatarImg.alt = "Аватар пользователя";
        avatarImg.classList.add("avatar-img");

        if (!catId) {
          avatarImg.src = "https://e.catwar.net/avatar/0.jpg";
        } else {
          loadAvatar(catId, (avatarUrl) => {
            avatarImg.src = avatarUrl || "https://e.catwar.net/avatar/0.jpg";
          });
        }

        comment.insertBefore(avatarImg, comment.firstChild);
      }
    });
  }

  function loadAvatar(catId, callback) {
    const formats = ["png", "jpg", "gif"];
    let currentFormat = 0;

    function tryNextFormat() {
      const url = `https://e.catwar.net/avatar/${catId}.${formats[currentFormat]}`;
      const img = new Image();

      img.onload = () => callback(url);
      img.onerror = () => {
        currentFormat++;
        if (currentFormat < formats.length) {
          tryNextFormat();
        } else {
          callback(null);
        }
      };

      img.src = url;
    }

    tryNextFormat();
  }
}
// ====================================================================================================================
//   . . . МЕНЕДЖЕР ЗВУКОВ . . .
// ====================================================================================================================
function createSoundManager() {
  const sounds = {};
  let isUserInteracted = false;
  let lastPendingSound = null;

  function loadSound(id, url) {
    const audio = new Audio(url);
    sounds[id] = audio;
  }

  function playSound(id, volume) {
    return new Promise((resolve, reject) => {
      if (sounds[id]) {
        sounds[id].currentTime = 0;
        sounds[id].volume = volume / 10;
        sounds[id]
          .play()
          .then(resolve)
          .catch((error) => {
            if (!isUserInteracted) {
              console.warn(
                "Политика браузера заблокировала звук. Ждём взаимодействия со стороны пользователя для новой попытки."
              );
              lastPendingSound = { id, volume, resolve };
            } else {
              reject(error);
            }
          });
      } else {
        reject(new Error(`Звук с ID ${id} не найден.`));
      }
    });
  }

  function playSoundNow(id, volume, resolve) {
    sounds[id]
      .play()
      .then(resolve)
      .catch((error) => {
        console.error(`Не удалось воспроизвести звук с ID ${id}:`, error);
        resolve();
      });
  }

  function handleUserInteraction() {
    isUserInteracted = true;
    document.removeEventListener("click", handleUserInteraction);
    document.removeEventListener("touchstart", handleUserInteraction);
    document.removeEventListener("keydown", handleUserInteraction);

    if (lastPendingSound) {
      const { id, volume, resolve } = lastPendingSound;
      playSoundNow(id, volume, resolve);
      lastPendingSound = null;
    }
  }

  document.addEventListener("click", handleUserInteraction);
  document.addEventListener("touchstart", handleUserInteraction);
  document.addEventListener("keydown", handleUserInteraction);

  return {
    loadSound,
    playSound,
  };
}

const soundManager = createSoundManager();

// ===================== СПИСОК ДОСТУПНЫХ ЗВУКОВ =====================

soundManager.loadSound(
  "notificationSound1",
  "https://github.com/Ibirtem/CatWar/raw/main/sounds/notification_1.mp3"
);
soundManager.loadSound(
  "notificationSound2",
  "https://github.com/Ibirtem/CatWar/raw/main/sounds/notification_2.mp3"
);
soundManager.loadSound(
  "notificationSound3",
  "https://github.com/Ibirtem/CatWar/raw/main/sounds/notification_3.mp3"
);

// ====================================================================================================================
//  . . . ЗАГРУЗКА КОДА В ИГРОВОЙ . . .
// ====================================================================================================================
// Игровая ли... Я чё знаю?
if (window.location.href === targetCW3) {
  const containerElement = document.querySelector("body");
  const globalContainerElement = document.createElement("div");
  globalContainerElement.id = "uwu-global-container";
  containerElement.appendChild(globalContainerElement);

  const mainContainerElement = document.createElement("div");
  mainContainerElement.id = "uwu-main-container";
  globalContainerElement.appendChild(mainContainerElement);

  // ====================================================================================================================
  //  . . . ПОДГРУЗКА ЦВЕТОВЫХ ТЕМ . . .
  // ====================================================================================================================
  const currentThemeName = getCurrentThemeName();
  const allThemes = getThemes();
  const theme = allThemes[currentThemeName]?.colors || {};
  // ====================================================================================================================
  //  . . . РАСШИРЕННЫЕ НАСТРОЙКИ . . .
  // ====================================================================================================================
  const extendedSettingsButtonElement = document.createElement("div");
  extendedSettingsButtonElement.innerHTML = extendedSettingsButton;
  mainContainerElement.appendChild(extendedSettingsButtonElement);

  const panel = extendedSettingsButtonElement.querySelector(
    "#uwu-extended-settings"
  );
  const extendedSettingsContainer = extendedSettingsButtonElement.querySelector(
    "#extended-settings-container"
  );
  const button = extendedSettingsButtonElement.querySelector(
    "#extended-settings-button"
  );

  extendedSettingsContainer.style.display = "none";

  const shouldShowPanel = () => {
    return (
      settings.extendedSettingsPanel ||
      settings.showSplashScreens ||
      settings.showUpdateNotification ||
      settings.manualWeatherPanel ||
      settings.fastStyles
    );
  };

  if (shouldShowPanel()) {
    panel.style.display = "block";
  } else {
    panel.style.display = "none";
  }

  button.addEventListener("click", () => {
    extendedSettingsContainer.style.display =
      extendedSettingsContainer.style.display === "none" ? "block" : "none";

    button.classList.remove("new-update");
  });
  // ====================================================================================================================
  //  . . . СПЛЕШ СКРИН . . .
  // ====================================================================================================================
  if (settings.showSplashScreens) {
    const randomPhraseBlock = document.createElement("div");
    const splashPanel = extendedSettingsButtonElement.querySelector(
      "#splash-screen-panel"
    );
    randomPhraseBlock.classList.add("random-phrase-block");
    splashPanel.appendChild(randomPhraseBlock);

    function loadRandomPhrase(url) {
      fetch(url)
        .then((response) => {
          if (!response.ok) {
            throw new Error(`Ошибка загрузки: ${response.status}`);
          }
          return response.text();
        })
        .then((text) => {
          const phrases = text.split("\n").filter((line) => line.trim() !== "");
          const randomIndex = Math.floor(Math.random() * phrases.length);
          randomPhraseBlock.innerHTML = parseColorCodes(phrases[randomIndex]);
        })
        .catch((error) => {
          console.error("Ошибка при загрузке случайной фразы:", error);
          randomPhraseBlock.textContent = "Не удалось загрузить фразу :(";
        });
    }

    function parseColorCodes(text) {
      const colorMap = {
        "&0": "</span>", // - Сброс -
        "&1": "<span style='color: blue;'>", // Синий
        "&2": "<span style='color: green;'>", // Зеленый
        "&3": "<span style='color: aqua;'>", // Бирюзовый
        "&4": "<span style='color: red;'>", // Красный
        "&5": "<span style='color: #dc00dc;'>", // Фиолетовый
        "&6": "<span style='color: gold;'>", // Золотой
        "&7": "<span style='color: pink;'>", // Розовый
        "&8": "<span style='color: white;'>", // Белый
        "&9": "<span style='color: black;'>", // Черный
      };

      text = "<b>" + text;

      for (const code in colorMap) {
        text = text.replace(new RegExp(code, "g"), colorMap[code]);
      }

      return text;
    }

    window.addEventListener("load", () => {
      loadRandomPhrase(
        "https://raw.githubusercontent.com/Ibirtem/CatWar/main/texts/text.txt"
      );
    });
  }
  // ====================================================================================================================
  //  . . . УВЕДОМЛЕНИЕ ОБ ОБНОВЛЕНИИ . . .
  // ====================================================================================================================
  function showUpdateNotification(oldVersion) {
    const panel = document.getElementById("extended-settings-container");
    const notificationBlock = document.createElement("div");
    notificationBlock.classList.add("update-notification");
    notificationBlock.innerHTML = `
          <p>Скрипт/Мод UwU был обновлен с версии v${
            oldVersion || "неизвестной"
          } до версии v${current_uwu_version}!</p>
          <p>Можете посетить <a href="https://catwar.net/settings" target="_blank">Настройки</a> для ознакомления с изменениями.</p>
        `;
    panel.appendChild(notificationBlock);
    const button = extendedSettingsButtonElement.querySelector("button");
    button.classList.add("new-update");
  }

  window.addEventListener("load", () => {
    const savedVersion = localStorage.getItem("uwu_version");
    if (savedVersion !== current_uwu_version) {
      localStorage.setItem("uwu_version", current_uwu_version);
    }
    if (
      settings.showUpdateNotification &&
      savedVersion !== current_uwu_version
    ) {
      showUpdateNotification(savedVersion);
    }
  });

  // ====================================================================================================================
  //  . . . РУЧНОЕ УПРАВЛЕНИЕ ПОГОДОЙ . . .
  // ====================================================================================================================
  if (settings.manualWeatherPanel) {
    const panel = extendedSettingsButtonElement.querySelector(
      "#extended-settings-container"
    );
    panel.innerHTML += manualWeatherPanel;

    const manualAuroraOffButton = document.getElementById("manualAurora-Off");
    const manualAuroraBButton = document.getElementById("manualAurora-B");
    const manualAuroraGButton = document.getElementById("manualAurora-G");

    const fireflyOnButton = document.getElementById("manualFirefly-On");

    manualAuroraOffButton.addEventListener("click", () => {
      for (const auroraElement of auroras) {
        removeAurora(auroraElement);
      }
    });

    manualAuroraBButton.addEventListener("click", () => {
      createAurora("blue");
    });

    manualAuroraGButton.addEventListener("click", () => {
      createAurora("green");
    });

    fireflyOnButton.addEventListener("click", () => {
      toggleFireflies();
    });
  }
  // ====================================================================================================================
  //   . . . ЧАСЫ . . .
  // ====================================================================================================================
  if (settings.showClock) {
    const style = document.createElement("style");
    style.textContent = // css
    `
        #uwu-clock {
          border-radius: 10px;
          width: min-content;
          height: min-content;
          background-color: ${theme?.blocksColor || "#242424"};
          color: ${theme?.textColor || "#d5d5d5"};
          border: 1px solid #ffffff1a;
          display: grid;
          grid-template-columns: auto 1fr;
          grid-template-rows: auto auto;
          align-items: center;
          justify-content: space-between;
          font-family: Arial, sans-serif;
          text-align: center;
          cursor: move;
          pointer-events: auto;
          position: absolute;
          z-index: 10;
          padding: 5px;
          font-size: ${settings.clockFontSize || 14}px;
        }

        #uwu-clock .time {
          font-size: 2em;
        }

        #uwu-clock .icon {
          cursor: help;
        }

        .compact #uwu-clock {
          column-gap: 5px;
          grid-template-columns: auto 1fr;
          grid-template-rows: auto auto;
        }

        .compact #uwu-clock .time {
          grid-column: 1 / 2;
          grid-row: 1 / 3;
        }

        .compact #uwu-clock .icon {
          grid-column: 2 / 3;
          grid-row: 1 / 2;
        }

        .compact #uwu-clock .date {
          grid-column: 2 / 3;
          grid-row: 2 / 3;
        }

        .standard #uwu-clock {
          grid-template-columns: auto auto;
          grid-template-rows: auto auto;
        }

        .standard #uwu-clock .time {
          text-align: start;
          grid-column: 1 / 2;
          grid-row: 1 / 2;
        }

        .standard #uwu-clock .icon {
          grid-column: 2 / 3;
          grid-row: 1 / 2;
        }

        .standard #uwu-clock .date {
          font-size: 1.2em;
          grid-column: 1 / 3;
          grid-row: 2 / 3;
          width: max-content;
        }
    `;
    document.head.appendChild(style);

    const tosStyle = document.createElement("style");
    tosStyle.textContent = `
      #uwu-clock {
        position: relative;
      }
    `;
    
    const flyStyle = document.createElement("style");
    flyStyle.textContent = `

    `;

    const container = document.getElementById("uwu-global-container");
    const clockElement = document.createElement("div");
    clockElement.id = "uwu-clock";

    const timeElement = document.createElement("span");
    timeElement.className = "time";
    clockElement.appendChild(timeElement);

    const iconElement = document.createElement("span");
    iconElement.className = "icon";
    clockElement.appendChild(iconElement);

    const dateElement = document.createElement("span");
    dateElement.className = "date";
    clockElement.appendChild(dateElement);

    if (settings.clockPosition === "fly") {
      container.appendChild(clockElement);
      document.head.appendChild(flyStyle);
  } else if (settings.clockPosition === "tos") {
      const trTos = document.getElementById("tr_tos").querySelector("tbody tr");
      const newTd = document.createElement("td");
      newTd.appendChild(clockElement);
      trTos.appendChild(newTd);
      document.head.appendChild(tosStyle);
  }

    let useInternetTime = false;
    let isDragging = false;
    let offsetX, offsetY;
    let internetTime = null;
    let timerInterval = null;

    function updateClock(timeSource = new Date()) {
      const hours = String(timeSource.getHours()).padStart(2, "0");
      const minutes = String(timeSource.getMinutes()).padStart(2, "0");
      const seconds = String(timeSource.getSeconds()).padStart(2, "0");
      const day = String(timeSource.getDate()).padStart(2, "0");
      const month = String(timeSource.getMonth() + 1).padStart(2, "0");
      const year = String(timeSource.getFullYear());
  
      timeElement.textContent = `${hours}:${minutes}:${seconds}`;
  
      if (settings.clockStyle === "compact") {
          dateElement.textContent = `${day}.${month}.${year.slice(-2)}`;
      } else if (settings.clockStyle === "standard") {
          const dayOfWeek = ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"][timeSource.getDay()];
          const monthNames = ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"];
          const monthName = monthNames[timeSource.getMonth()];
          dateElement.textContent = `${day} (${dayOfWeek}), ${monthName}, ${year}`;
      }
  
      if (useInternetTime) {
          iconElement.textContent = "🌍︎";
          iconElement.title = "Точное онлайн время";
          if (settings.clockMoscowTime) {
              iconElement.textContent += " MSK";
          }
      } else {
          iconElement.textContent = "⌨";
          iconElement.title =
              "Не удалось получить точное онлайн время! Используется локальное время устройства";
      }
  }

    async function fetchInternetTime() {
        try {
            const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
            const url = settings.clockMoscowTime
                ? "https://timeapi.io/api/Time/current/zone?timeZone=Europe/Moscow"
                : `https://timeapi.io/api/Time/current/zone?timeZone=${userTimezone}`;
            const response = await fetch(url);
            if (!response.ok) throw new Error(`Онлайн ответ выдал ошибку: ${response.status} ${response.statusText}`);
            const data = await response.json();
            internetTime = new Date(data.dateTime);
            useInternetTime = true;
            updateClockWithInternetTime();
        } catch (error) {
            console.error('Ошибка при получении онлайн времени:', error);
            useInternetTime = false;
            updateClock();
        }
        startTimer();
    }

    function updateClockWithInternetTime() {
      if (internetTime) {
          internetTime.setSeconds(internetTime.getSeconds() + 1);
          updateClock(internetTime);
          if (settings.clockMoscowTime) {
              iconElement.textContent = "🌍︎ MSK";
          }
      }
  }

    function startTimer() {
        if (timerInterval) {
            clearInterval(timerInterval);
        }
        timerInterval = setInterval(() => {
            if (useInternetTime) {
                updateClockWithInternetTime();
            } else {
                updateClock();
            }
        }, 1000);
    }

    if (settings.clockPosition === "fly") {
        clockElement.addEventListener("mousedown", (e) => {
            isDragging = true;
            offsetX = e.clientX - clockElement.offsetLeft;
            offsetY = e.clientY - clockElement.offsetTop;
            document.body.style.userSelect = "none";
        });

        document.addEventListener("mousemove", (e) => {
            if (isDragging) {
                clockElement.style.left = `${e.clientX - offsetX}px`;
                clockElement.style.top = `${e.clientY - offsetY}px`;
            }
        });

        document.addEventListener("mouseup", () => {
            isDragging = false;
            document.body.style.userSelect = "auto";
            saveClockPosition();
        });
    }

    function saveClockPosition() {
        const clockPosition = {
            x: clockElement.offsetLeft,
            y: clockElement.offsetTop,
        };
        localStorage.setItem("uwu_clock", JSON.stringify(clockPosition));
    }

    function loadClockPosition() {
        const storedPosition = localStorage.getItem("uwu_clock");
        if (storedPosition) {
            const clockPosition = JSON.parse(storedPosition);
            clockElement.style.left = `${clockPosition.x}px`;
            clockElement.style.top = `${clockPosition.y}px`;
        }
    }

    document.addEventListener("visibilitychange", () => {
        if (!document.hidden) {
            fetchInternetTime();
        }
    });

    window.addEventListener("focus", () => {
        fetchInternetTime();
    });

    fetchInternetTime();
    if (settings.clockPosition === "fly") {
        loadClockPosition();
    }

    document.body.classList.add(settings.clockStyle);
}
  // ====================================================================================================================
  //  . . . ДЕЙСТВИЯ ПРИ НАВОДКЕ НА .cat . . .
  // ====================================================================================================================
  document.addEventListener("mouseover", (event) => {
    const catElement = event.target.closest(".cat");

    if (catElement) {
      const catTooltip = catElement.querySelector(".cat_tooltip");

      if (
        settings.showMoreCatInfo &&
        !catTooltip.querySelector(".more-info-link")
      ) {
        const moreInfoLink = document.createElement("a");
        moreInfoLink.classList.add("more-info-link");
        moreInfoLink.textContent = "Подробнее";
        moreInfoLink.addEventListener("click", () => {
          showCatInfo(catElement);
        });

        const moreInfoContainer = document.createElement("div");
        moreInfoContainer.classList.add("more-info-container");
        moreInfoContainer.appendChild(moreInfoLink);

        const onlineSpan = catTooltip.querySelector("span.online");
        onlineSpan.parentNode.insertBefore(moreInfoContainer, onlineSpan);
      }

      if (settings.compactMouth) {
        compactInventory(catElement);
      }
    }
  });
  // ====================================================================================================================
  //  . . . КОМПАКТНЫЙ РОТ АХХАХХА . . .
  // ====================================================================================================================
  function compactInventory(cat) {
    const originalMouth = cat.querySelector(".cat_tooltip .mouth");

    if (originalMouth) {
      const existingSortedMouths = cat.querySelectorAll(".mouth.uwu-sorted");
      existingSortedMouths.forEach((mouth) => mouth.remove());

      const newMouth = document.createElement("ol");
      newMouth.classList.add("mouth", "uwu-sorted");
      originalMouth.parentNode.insertBefore(
        newMouth,
        originalMouth.nextSibling
      );

      originalMouth.style.display = "none";

      const inventory = new Map();
      const cats = [];

      [...originalMouth.querySelectorAll("li img")].forEach((img) => {
        const itemSrc = img.getAttribute("src");
        inventory.set(itemSrc, (inventory.get(itemSrc) || 0) + 1);
      });

      [...originalMouth.querySelectorAll("li")].forEach((item) => {
        if (!item.querySelector("img")) {
          cats.push(item.innerHTML);
        }
      });

      newMouth.innerHTML = "";
      for (const [itemSrc, count] of inventory) {
        const listItem = document.createElement("li");
        const itemImage = document.createElement("img");
        itemImage.setAttribute("src", itemSrc);
        listItem.appendChild(itemImage);

        if (count > 1) {
          const countSpan = document.createElement("span");
          countSpan.textContent = `x${count}`;
          listItem.appendChild(countSpan);
        }

        newMouth.appendChild(listItem);
      }

      cats.forEach((catHtml) => {
        const listItem = document.createElement("li");
        listItem.innerHTML = catHtml;
        newMouth.appendChild(listItem);
      });
    }
  }
  // ====================================================================================================================
  //  . . . ИНФОРМАЦИОННЫЙ КОНТЕЙНЕР . . .
  // ====================================================================================================================
  let globalContainer = document.getElementById("uwu-global-container");
  if (!globalContainer) {
    globalContainer = document.createElement("div");
    globalContainer.id = "uwu-global-container";
    globalContainer.style.display = "none";
    document.body.appendChild(globalContainer);
  }

  function createCatInfoContainer() {
    const catInfoElement = document.createElement("div");
    catInfoElement.classList.add("cat-info");

    const contentContainer = document.createElement("div");
    contentContainer.classList.add("content-container");
    catInfoElement.appendChild(contentContainer);

    const closeButton = document.createElement("button");
    closeButton.textContent = "Закрыть";
    closeButton.classList.add("close-info");
    closeButton.addEventListener("click", () => {
      globalContainer.removeChild(catInfoElement);
    });
    catInfoElement.appendChild(closeButton);

    const css_catDefects = document.createElement("style");
    css_catDefects.innerHTML = // css
    `
      .cat-info {
        pointer-events: auto;
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        padding: 20px;
        border-radius: 5px;
        box-shadow: 0 0 10px #00000033;
        z-index: 5;
        width: 300px;
        text-align: center;
        display: block;
        background-color: white;
        color: black;
      }

      .other-cat-info-container {
      display: grid;
      grid-template-columns: 1fr 2fr;
      }
    
      .close-info-container {
        text-align: right;
      }
    
      .close-info {
        cursor: pointer;
      }
    
      .more-info-container {
        cursor: pointer;
      }

      .parameter-details-container {
        text-align: left;
      }

      .cat-details {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        margin-left: 8px;
      }

      .cat-details > p,
      .cat-details > div > p {
        margin-top: 5px;
        margin-bottom: 5px;
      }

      #uwu-global-container > div.cat-info > div > div > div.cat-details > div {
        margin-top: 8px;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
      }
    `;

    document.head.appendChild(css_catDefects);

    return { catInfoElement, contentContainer };
  }
  // ====================================================================================================================
  //  . . . БОЛЬШЕ ИНФОРМАЦИИ В "О КОТЕ" . . .
  // ====================================================================================================================
  const defectsInfo = {
    wound: {
      name: "Раны",
      states: {
        1: "царапины",
        2: "лёгкие раны",
        3: "глубокие раны",
        4: "смертельные раны",
      },
    },
    poisoning: {
      name: "Отравление",
      states: {
        1: "недомогание",
        2: "лёгкое отравление",
        3: "сильное отравление",
        4: "смертельное отравление",
      },
    },
    drown: {
      name: "Травмы от утопления",
      states: {
        1: "ссадины",
        2: "небольшие кровоподтёки",
        3: "сильные травмы",
        4: "смертельные травмы",
      },
    },
    disease: {
      name: "Болезнь",
      states: {
        1: "кашель",
        2: "кашель",
        3: "кашель",
        4: "кашель",
      },
    },
    trauma: {
      name: "Переломы",
      states: {
        1: "синяки",
        2: "лёгкие ушибы",
        3: "сильные ушибы",
        4: "смертельные ушибы",
      },
    },
    dirt: {
      name: "Грязь",
      states: {
        1: "грязные лапы",
        2: "грязевые пятна",
        3: "клещи",
        4: "блохи",
      },
    },
  };

  function showCatInfo(cat) {
    const catName = cat.querySelector(".cat_tooltip a").textContent;
    const catSize = cat.querySelector(".d .first").style.backgroundSize;
    const catImage = cat
      .querySelector(".d .first")
      .style.backgroundImage.slice(5, -2);

    const defectElements = Array.from(
      cat.querySelectorAll(".d > div:not(.first)")
    );

    const uniqueDefects = new Set();

    const catDefects = defectElements
      .map((element) => {
        const defectUrl = element.style.backgroundImage;

        if (defectUrl.includes("/defects/")) {
          const defectParts = defectUrl.split("/");
          const lastPart = defectParts.pop();
          const defectLevel = parseInt(lastPart.split("/")[0]);
          const defectType = defectParts[5];
          const defectKey = `${defectType}-${defectLevel}`;

          if (!uniqueDefects.has(defectKey)) {
            uniqueDefects.add(defectKey);
            return { type: defectType, level: defectLevel };
          }
        }
        return null;
      })
      .filter(Boolean);

    const catId = cat
      .querySelector(".cat_tooltip a")
      .getAttribute("href")
      .slice(4);

    let { catInfoElement, contentContainer } = createCatInfoContainer();

    contentContainer.innerHTML = // html
    `
      <h2>${catName}</h2>
      <div class="other-cat-info-container">
        <div>
          <img src="${catImage}" class="cat-image">
        </div>
        <div class="cat-details">
          <p><strong>ID</strong>: ${catId}</p>
          <p><strong>Размер</strong>: ${catSize}</p>
        </div>
      </div>
    `;

    const defectsContainer = document.createElement("div");
    if (catDefects.length > 0) {
      defectsContainer.innerHTML = "<p>Дефекты:</p>";
      catDefects.forEach((defect) => {
        const defectData = defectsInfo[defect.type];
        if (defectData) {
          const defectState = defectData.states[defect.level] || "";
          const defectLine = document.createElement("p");
          const defectNameSpan = document.createElement("strong");
          defectNameSpan.textContent = defectData.name;
          defectLine.appendChild(defectNameSpan);
          defectLine.insertAdjacentHTML(
            "beforeend",
            ` (${defect.level} стадия, ${defectState})`
          );

          defectsContainer.appendChild(defectLine);
        }
      });
      contentContainer
        .querySelector(".cat-details")
        .appendChild(defectsContainer);
    } else {
      contentContainer.querySelector(".cat-details").innerHTML +=
        "<p><strong>Здоровый</strong></p>";
    }

    globalContainer.appendChild(catInfoElement);
  }
  // ====================================================================================================================
  //  . . . СОБСТВЕННЫЙ ФОН ЛОКАЦИИ ИГРОВОЙ . . .
  // ====================================================================================================================
  if (settings.gameFieldBackgroundUser) {
    const css_gameField = document.createElement("style");
    css_gameField.textContent = `
      #cages_div {
          background-image: url(${settings.gameFieldBackgroundUserImageURL}) !important;
      }
  `;
    document.head.appendChild(css_gameField);
  }
  // ====================================================================================================================
  //  . . . ГРАНИЦЫ ЯЧЕЕК . . . cellsNumbers
  // ====================================================================================================================
  function updateCellsBordersStyle(checked) {
    let styleElement = document.getElementById("cellsBordersStyle");
    const cellsBordersStyle = `
      .cage {
        box-shadow: inset 0 0 0 0.${settingsMap.uwu_settings.cellsBordersThickness}px ${settings.cellsBordersColor};
      }
    `;

    if (checked) {
      if (!styleElement) {
        styleElement = document.createElement("style");
        styleElement.id = "cellsBordersStyle";
        styleElement.innerHTML = cellsBordersStyle;
        document.head.appendChild(styleElement);
      }
    } else {
      if (styleElement) {
        document.head.removeChild(styleElement);
      }
    }
  }
  // ====================================================================================================================
  //  . . . НУМЕРАЦИЯ ЯЧЕЕК . . .
  // ====================================================================================================================
  if (settings.cellsNumbers) {
    function createCellNumbers(style) {
      let css = // css
      `
        #cages_div { position: relative; }
        #cages > tbody > tr > td { position: relative; }
        #cages > tbody > tr > td::before { 
          content: attr(data-cell-num);
          position: absolute; 
          z-index: 0; 
          top: 5px; 
          right: 5px;
          color: ${style.color || "#000"}; 
          opacity: ${style.opacity || 0.4}; 
          font-size: 16px; 
          font-weight: bold;
        }
      `;
  
      let cagesNums = document.createElement("style");
      cagesNums.id = "cages_nums";
      cagesNums.innerHTML = css;
      document.head.appendChild(cagesNums);
  
      let table = document.getElementById("cages");
      if (!table) return;
      let rows = table.querySelectorAll("tbody > tr");
      for (let i = 0; i < rows.length; i++) {
        let cells = rows[i].querySelectorAll("td");
        for (let j = 0; j < cells.length; j++) {
          cells[j].setAttribute("data-cell-num", (j + 1).toString());
        }
      }
    }
  
    createCellNumbers({
      color: "white",
      opacity: 0.8,
    });
  }
  // ====================================================================================================================
  //   . . . ПРОЦЕНТЫ ПАРАМЕТРОВ . . .
  // ====================================================================================================================
  if (settings.displayParametersPercentages) {
    const parameterTableIds = [
      "dream_table",
      "hunger_table",
      "thirst_table",
      "need_table",
      "health_table",
      "clean_table",
    ];

    function updateParameterPercentages(tableId) {
      const table = document.getElementById(tableId);
      if (table) {
        const row = table.querySelector("tbody tr");
        if (!row) {
          console.warn(`Строка не найдена в таблице с ID "${tableId}".`);
          return;
        }
        const greenBar = row.querySelector(
          "td[style*='background-color: green;']"
        );
        const redBar = row.querySelector("td[style*='background-color: red;']");
        if (!greenBar || !redBar) {
          console.warn(`Бары не найдены в строке таблицы с ID "${tableId}".`);
          return;
        }
        const greenBarWidth = parseInt(greenBar.style.width, 10);
        const redBarWidth = parseInt(redBar.style.width, 10);
        const totalWidth = greenBarWidth + redBarWidth;
        let percentage = (greenBarWidth / totalWidth) * 100;
        percentage =
          percentage % 1 !== 0 ? percentage.toFixed(2) : Math.round(percentage);

        let percentageCell = row.querySelector(".percentage-cell");
        if (!percentageCell) {
          percentageCell = document.createElement("td");
          percentageCell.classList.add("percentage-cell");
          row.appendChild(percentageCell);
        }
        percentageCell.textContent = `${percentage}%`;
      } else {
        console.warn(`Таблица с ID "${tableId}" не найдена.`);
      }
    }

    async function setupTableObservers() {
      for (const tableId of parameterTableIds) {
        const tableSelector = `#${tableId}`;
        const rowSelector = `${tableSelector} tbody tr`;
        const greenBarSelector = `${rowSelector} td[style*='background-color: green;']`;
        const redBarSelector = `${rowSelector} td[style*='background-color: red;']`;

        await setupMutationObserver(tableSelector, () =>
          updateParameterPercentages(tableId)
        );
        await setupMutationObserver(greenBarSelector, () =>
          updateParameterPercentages(tableId)
        );
        await setupMutationObserver(redBarSelector, () =>
          updateParameterPercentages(tableId)
        );
      }
    }

    window.addEventListener("load", setupTableObservers);
  }
  // ====================================================================================================================
  //   . . . ПОДРОБНЕЕ О ПАРАМЕТРАХ (И НАВЫКОВ?) . . .
  // ====================================================================================================================
  function createMoreInfoButton() {
    const parametersBlock = document.getElementById("parameters_block");

    const buttonContainer = document.createElement("div");
    buttonContainer.classList.add("button-container");
    buttonContainer.style.paddingBottom = "5px";

    const moreInfoLink = document.createElement("a");
    moreInfoLink.href = "#";
    moreInfoLink.textContent = "Подробнее";
    moreInfoLink.classList.add("more-info-link");
    moreInfoLink.addEventListener("click", (event) => {
        event.preventDefault();
        showParameterDetails();
    });

    buttonContainer.appendChild(moreInfoLink);

    parametersBlock.insertBefore(buttonContainer, parametersBlock.firstChild);
  }

  function showParameterDetails() {
    const parameters = [
      {
        id: "dream_table",
        name: "Сонливость",
        timePerPixel: 20,
        formula: null,
      },
      {
        id: "hunger_table",
        name: "Голод",
        timePerPixel: null,
        formula: (red) => Math.ceil((red / 150) * 9) * 15,
      },
      { id: "thirst_table", name: "Жажда", timePerPixel: 60, formula: null },
      { id: "need_table", name: "Нужда", timePerPixel: 30, formula: null },
      {
        id: "health_table",
        name: "Здоровье",
        timePerPixel: null,
        formula: null,
      },
      {
        id: "clean_table",
        name: "Чистота",
        timePerPixel: null,
        formula: (red) => {
          red = red % 3 ? red : red - 0.5;
          return ((red - 1) / 1.5) * 100 + 100;
        },
      },
    ];

    let { catInfoElement, contentContainer } = createCatInfoContainer();
    contentContainer.classList.add("parameter-details-container");

    parameters.forEach(({ id, name, timePerPixel, formula }) => {
      const table = document.getElementById(id);
      if (table) {
        const row = table.querySelector("tbody tr");
        if (!row) {
          console.warn(`Строка не найдена в таблице с ID "${id}".`);
          return;
        }
        const greenBar = row.querySelector(
          "td[style*='background-color: green;']"
        );
        const redBar = row.querySelector("td[style*='background-color: red;']");
        if (!greenBar || !redBar) {
          console.warn(`Бары не найдены в строке таблицы с ID "${id}".`);
          return;
        }
        const greenBarWidth = parseInt(greenBar.style.width, 10);
        const redBarWidth = parseInt(redBar.style.width, 10);
        const totalWidth = greenBarWidth + redBarWidth;
        let percentage = (greenBarWidth / totalWidth) * 100;
        percentage =
          percentage % 1 !== 0 ? percentage.toFixed(2) : Math.round(percentage);

        let timeInfo = "";
        let totalTimeSeconds;
        if (formula) {
          totalTimeSeconds = formula(redBarWidth);
        } else if (timePerPixel !== null) {
          totalTimeSeconds = redBarWidth * timePerPixel;
        }

        if (totalTimeSeconds !== undefined) {
          const hours = Math.floor(totalTimeSeconds / 3600);
          const minutes = Math.floor((totalTimeSeconds % 3600) / 60);
          const seconds = totalTimeSeconds % 60;
          if (hours > 0) {
            timeInfo = ` (> ${hours} ч ${minutes} мин)`;
          } else if (minutes > 0) {
            timeInfo = ` (${minutes} мин ${seconds} сек)`;
          } else {
            timeInfo = ` (${seconds} сек)`;
          }
        }

        const detailLine = document.createElement("p");
        detailLine.innerHTML = `<strong>${name}:</strong> <span style="color: #00cc00;">${greenBarWidth}px</span> / <span style="color: red;">${redBarWidth}px</span> - ${percentage}%`;
        detailLine.style.marginBottom = "0";
        contentContainer.appendChild(detailLine);

        if (timeInfo) {
          const detailLineTime = document.createElement("p");
          detailLineTime.innerHTML = `≈${timeInfo}`;
          detailLineTime.style.marginTop = "0";
          contentContainer.appendChild(detailLineTime);
        }
      } else {
        console.warn(`Таблица с ID "${id}" не найдена.`);
      }
    });

    globalContainer.appendChild(catInfoElement);
  }

  if (settings.showParametersDetails) {
    setupSingleCallback("#dream_table", createMoreInfoButton);
  }
  // ====================================================================================================================
  //   . . . ЧИСЛОВАЯ ГРОМКОСТЬ УВЕДОМЛЕНИЙ . . .
  // ====================================================================================================================
  if (settings.climbingNotificationsNumbers) {
    function addClimbingNotificationsStyles() {
      const styles = Array.from(
        { length: 11 },
        (_, i) => `
          .vlm${i} > .nick[style*="italic"]:after {
            content: " [${i}]";
          }
        `
      ).join("");

      const styleElement = document.createElement("style");
      styleElement.textContent = styles;
      document.head.appendChild(styleElement);
    }

    addClimbingNotificationsStyles();
  }
  // ====================================================================================================================
  //   . . . ЗВУКОВОЕ УВЕДОМЛЕНИЕ ПРИ ОБНОВЛЕНИИ КЛЕТОК . . .
  // ====================================================================================================================
  // TODO - debounceTimer, если не сработает решение со сравнением историй. P.S. Вроде работает.
  if (settings.climbingRefreshNotification) {
    function handleClimbingRefresh() {
      const refreshRegex = /Услышала? оглушительн/;
      let previousHistory = "";

      const updateHistory = () => {
        const istElement = document.getElementById("ist");
        const currentHistory = istElement.innerHTML;

        if (currentHistory !== previousHistory) {
          previousHistory = currentHistory;

          const entries = currentHistory.split(".");
          const lastEntry = entries[entries.length - 2];

          if (lastEntry !== undefined && refreshRegex.test(lastEntry)) {
            const lastPlayedEntry = entries[entries.length - 3];

            if (!lastPlayedEntry || !refreshRegex.test(lastPlayedEntry)) {
              soundManager.playSound(
                settings.climbingRefreshNotificationSound,
                settings.climbingRefreshNotificationVolume
              );
            }
          }
        }
      };

      const historyBlock = document.getElementById("history_block");
      const observer = new MutationObserver(() => {
        updateHistory();
      });

      const config = {
        childList: true,
        subtree: true,
        characterData: true,
      };
      observer.observe(historyBlock, config);
    }

    handleClimbingRefresh();
  }
  // ====================================================================================================================
  //   . . . МИННОЕ ПОЛЕ . . .
  // ====================================================================================================================
  // Вторая по ненависти работа с кодами. Но уже к самому себе а не к сайту.........
  // чат уже ничего не перебьёт....... наверно????????????
  // TODO - Переписать всё это мессиво к чертям, это кошмар какой-то. Как оно вообще ещё работает?????? Что я употреблял?????????????????????
  if (settings.climbingPanel) {
    let isDragging = false;
    let initialX;
    let initialY;
    let currentX;
    let currentY;
    let wasDragging = false;

    function saveClimbingPanelStatus() {
      const status = {
        x: currentX,
        y: currentY,
        isOpen: climbingPanelContainer.classList.contains("open"),
        isChecked: transferCheckbox.checked,
        currentTabIndex: tabManager.currentTabIndex,
        currentTableId: tabManager.currentTableId,
      };
      localStorage.setItem("uwu_climbingPanelStatus", JSON.stringify(status));
    }

    function loadClimbingPanelStatus() {
      const savedStatus = localStorage.getItem("uwu_climbingPanelStatus");

      if (savedStatus) {
        const status = JSON.parse(savedStatus);

        currentX = status.x;
        currentY = status.y;

        climbingPanelContainer.classList.toggle("open", status.isOpen);
        transferCheckbox.checked = status.isChecked;

        tabManager.currentTabIndex = status.currentTabIndex;
        if (
          status.currentTableId !== null &&
          tabManager.tabs[status.currentTabIndex].tables[status.currentTableId]
        ) {
          tabManager.currentTableId = status.currentTableId;
        }

        tabManager.render();

        if (status.isChecked) {
          transferColors();
        }
      } else {
        tabManager.render();
      }

      checkAndResetPanelPosition();
    }

    function updateCell(cell, value) {
      cell.dataset.value = value || "";
      cell.textContent = value === "mine" || value === "transit" ? "" : value;
      switch (value) {
        case "mine":
          cell.style.backgroundColor = "#5b000073";
          break;
        case "transit":
          cell.style.backgroundColor = "#ffffff87";
          break;
        default:
          cell.style.backgroundColor = "";
      }
    }

    function transferColors() {
      const transferCheckbox = document.getElementById("uwu-transferCheckbox");
      if (!transferCheckbox.checked) return;

      const climbingPanelCells = Array.from(
        document.querySelectorAll("#uwu-climbingPanel td")
      );
      const cagesCells = Array.from(
        document.querySelectorAll("#cages tbody td.cage")
      );

      climbingPanelCells.forEach((cell, i) => {
        if (cagesCells[i]) {
          cagesCells[i].style.backgroundColor =
            getComputedStyle(cell).backgroundColor;
        }
      });
    }

    function clearColors() {
      const cagesCells = document.querySelectorAll("#cages tbody td.cage");
      cagesCells.forEach((cell) => {
        cell.style.backgroundColor = "";
      });
    }

    let lastClickedCell = null;

    function handleCellClick(event) {
      const cell = event.target.closest("td");
      if (!cell || !cell.closest("#uwu-climbingPanel")) return;

      if (lastClickedCell === cell) {
        updateCell(cell, "");
        saveTableData(tabManager.currentTableId);
        transferColors();
        lastClickedCell = null;
      } else {
        lastClickedCell = cell;
      }
    }

    function handleKeyDown(event) {
      const keyPressed = event.key;
      const activeElement = document.activeElement;

      if (
        activeElement &&
        activeElement.tagName === "TD" &&
        activeElement.closest("#uwu-climbingPanel")
      ) {
        switch (keyPressed) {
          case "0":
          case "1":
          case "2":
          case "3":
          case "4":
          case "5":
          case "6":
          case "7":
            updateCell(activeElement, keyPressed);
            break;
          case "-":
            updateCell(activeElement, "mine");
            break;
          case "=":
            updateCell(activeElement, "transit");
            break;
          default:
            return;
        }

        saveTableData(tabManager.currentTableId);
        transferColors();
      }
    }

    function handleTransferCheckboxChange(event) {
      event.target.checked ? transferColors() : clearColors();
      saveClimbingPanelStatus();
    }

    const uwuClimbingPanelContainer = // html
    `
      <div id="uwu-climbingMainPanel">
        <div id="uwu-climbingPanelButton">
            <div class="left-content">
                <h2>Минное поле</h2>
            </div>
            <div class="right-content">
                <span id="uwu-arrow">▼</span>
            </div>
        </div>
      <div id="uwu-climbingPanelContainer">
          <div id="uwu-climbingPanelContent">
              <div id="uwu-buttonContainer">
                  <h3>Вкладка</h3>
                  <div id="uwu-buttonRow1"></div>
                  <hr id="uwu-hr">
                  <h3>Локация</h3>
                  <div id="uwu-buttonRow2"></div>
              </div>
              <div id="uwu-functionButtonsContainer">
                  <input type="checkbox" id="uwu-transferCheckbox">
                  <label for="uwu-transferCheckbox">Перенос на Игровое поле</label>
              </div>
              <div id="uwu-tableContainer"></div>
          </div>
      </div>
      </div>
    `;

    function createClimbingPanel() {
      const globalContainer = document.getElementById("uwu-global-container");
      globalContainer.insertAdjacentHTML(
        "beforeend",
        uwuClimbingPanelContainer
      );

      const transferCheckbox = document.getElementById("uwu-transferCheckbox");

      document.addEventListener("keydown", handleKeyDown);
      transferCheckbox.addEventListener("change", handleTransferCheckboxChange);
    }

    function saveTableData(tableIndex) {
      const climbingPanel = document.getElementById("uwu-climbingPanel");
      if (!climbingPanel) return;

      const tableData = getTableData(climbingPanel.id);
      const currentTab = tabManager.tabs[tabManager.currentTabIndex];
      currentTab.tables[tableIndex] = {
        name: currentTab.tables[tableIndex].name,
        data: tableData,
      };
      tabManager.saveState();
    }

    function clearTable() {
      const climbingPanel = document.getElementById("uwu-climbingPanel");
      if (!climbingPanel) return;

      const cells = Array.from(climbingPanel.querySelectorAll("td"));
      cells.forEach((cell) => {
        if (cell.dataset.value !== "transit") {
          updateCell(cell, "");
        }
      });

      const currentTab = tabManager.tabs[tabManager.currentTabIndex];
      currentTab.tables[tabManager.currentTableId] = {
        name: currentTab.tables[tabManager.currentTableId].name,
        data: getTableData(climbingPanel.id),
      };
      tabManager.saveState();
      transferColors();
    }

    const tabManager = {
      tabs: [],
      currentTabIndex: 0,
      currentTableId: 0,

      createTab(name) {
        const newTab = {
          name: name,
          tables: [],
        };

        this.tabs.push(newTab);
        this.render();
        this.switchTab(this.tabs.length - 1);
      },

      switchTab(index) {
        this.currentTabIndex = index;
        const currentTab = this.tabs[this.currentTabIndex];
        this.currentTableId =
          currentTab && currentTab.tables.length > 0 ? 0 : null;

        if (currentTab && currentTab.tables.length === 0) {
          this.renderNoTableMessage();
        } else {
          this.render();
        }

        transferColors();
        saveClimbingPanelStatus();
      },

      switchTable(tableIndex) {
        this.currentTableId = tableIndex;
        this.render();
        transferColors();
        saveClimbingPanelStatus();
      },

      saveState() {
        localStorage.setItem("uwu_climbingPanelState", JSON.stringify(this));
      },

      render() {
        this.renderTabs();
        this.renderTables();
        if (this.currentTableId !== null) {
          this.renderTable(this.currentTableId);
        }
      },

      renderTabs() {
        const tabRow = document.getElementById("uwu-buttonRow1");
        tabRow.innerHTML = "";

        this.tabs.forEach((tab, index) => {
          const tabButton = document.createElement("button");
          tabButton.textContent = tab.name;
          tabButton.classList.add("tab-button");

          if (index === this.currentTabIndex) {
            tabButton.classList.add("active");
          }

          tabButton.addEventListener("click", () => this.switchTab(index));

          const tabContainer = document.createElement("div");
          tabContainer.classList.add("tab-container");
          tabContainer.appendChild(tabButton);

          tabRow.appendChild(tabContainer);
        });
      },

      renderTables() {
        const tableRow = document.getElementById("uwu-buttonRow2");
        tableRow.innerHTML = "";

        const currentTab = this.tabs[this.currentTabIndex];
        if (currentTab) {
          currentTab.tables.forEach((table, index) => {
            const tableButton = document.createElement("button");
            tableButton.textContent = table.name || `Локация ${index + 1}`;
            tableButton.classList.add("table-button");

            if (index === this.currentTableId) {
              tableButton.classList.add("active");
            }

            tableButton.addEventListener("click", () =>
              this.switchTable(index)
            );

            const tableContainer = document.createElement("div");
            tableContainer.classList.add("table-container");
            tableContainer.appendChild(tableButton);

            tableRow.appendChild(tableContainer);
          });
        }
      },

      renderTable(tableIndex) {
        const tableContainer = document.getElementById("uwu-tableContainer");
        tableContainer.innerHTML = "";

        const currentTab = this.tabs[this.currentTabIndex];
        const climbingPanel = document.createElement("table");
        climbingPanel.id = "uwu-climbingPanel";

        for (let i = 0; i < 6; i++) {
          const row = document.createElement("tr");
          for (let j = 0; j < 10; j++) {
            const cell = document.createElement("td");
            cell.setAttribute("tabindex", "0");
            cell.addEventListener("click", handleCellClick);
            row.appendChild(cell);
          }
          climbingPanel.appendChild(row);
        }

        const tableData = currentTab.tables[tableIndex]?.data;

        if (tableData) {
          tableData.forEach((rowData, i) => {
            rowData.forEach((cellData, j) => {
              updateCell(climbingPanel.rows[i].cells[j], cellData.value);
            });
          });
        }

        tableContainer.appendChild(climbingPanel);

        const clearButton = document.createElement("button");
        clearButton.textContent = "Очистить всё поле/таблицу";
        clearButton.id = "button-clear-table";
        clearButton.addEventListener("click", clearTable);
        tableContainer.appendChild(clearButton);
      },

      renderNoTableMessage() {
        const tableContainer = document.getElementById("uwu-tableContainer");
        tableContainer.innerHTML = "";

        const message = document.createElement("div");
        message.textContent = "Добавьте поле/таблицу в настройках";
        message.style.textAlign = "center";
        message.style.marginTop = "20px";
        tableContainer.appendChild(message);

        this.renderTabs();
        this.renderTables();
      },
    };

    function loadSavedState() {
      const savedState = localStorage.getItem("uwu_climbingPanelState");
      if (savedState) {
        const state = JSON.parse(savedState);
        Object.assign(tabManager, state);
        tabManager.currentTabIndex = 0;

        const currentTab = tabManager.tabs[tabManager.currentTabIndex];
        if (currentTab && currentTab.tables.length > 0) {
          if (tabManager.currentTableId >= currentTab.tables.length) {
            tabManager.currentTableId = 0;
          }
        } else {
          tabManager.currentTableId = null;
        }
      }
    }

    loadSavedState();
    createClimbingPanel();
    tabManager.render();

    function getTableData(tableId) {
      const table = document.getElementById(tableId);
      if (!table) {
        console.error(`Таблица с id ${tableId} не найдена`);
        return [];
      }

      const tableData = [];

      for (let i = 0; i < table.rows.length; i++) {
        const rowData = [];
        for (let j = 0; j < table.rows[i].cells.length; j++) {
          const cell = table.rows[i].cells[j];
          rowData.push({
            value: cell.dataset.value || "",
          });
        }
        tableData.push(rowData);
      }

      return tableData;
    }

    // ===================== ПЕРЕТАСКИВАНИЕ =====================

    const climbingMainPanel = document.getElementById("uwu-climbingMainPanel");
    const climbingPanelButton = document.getElementById(
      "uwu-climbingPanelButton"
    );
    const climbingPanelContainer = document.getElementById(
      "uwu-climbingPanelContainer"
    );
    const transferCheckbox = document.getElementById("uwu-transferCheckbox");

    function dragStart(e) {
      e.preventDefault();
      const savedStatus = JSON.parse(
        localStorage.getItem("uwu_climbingPanelStatus")
      );
      initialX =
        e.clientX -
        (savedStatus ? savedStatus.x : climbingMainPanel.offsetLeft);
      initialY =
        e.clientY - (savedStatus ? savedStatus.y : climbingMainPanel.offsetTop);

      if (e.target === climbingPanelButton) {
        isDragging = true;
        wasDragging = false;
      }
    }

    function drag(e) {
      if (isDragging) {
        e.preventDefault();

        currentX = e.clientX - initialX;
        currentY = e.clientY - initialY;

        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        const panelWidth = climbingMainPanel.offsetWidth;
        const panelHeight = climbingMainPanel.offsetHeight;

        const maxX = windowWidth - panelWidth;
        currentX = Math.max(0, Math.min(currentX, maxX));

        const maxY = windowHeight - panelHeight;
        currentY = Math.max(0, Math.min(currentY, maxY));

        setPosition(currentX, currentY, climbingMainPanel);

        wasDragging = true;
      }
    }

    function dragEnd(e) {
      if (isDragging) {
        saveClimbingPanelStatus();
      }
      isDragging = false;
    }

    function setPosition(x, y, el) {
      el.style.left = `${x}px`;
      el.style.top = `${y}px`;
    }

    function togglePanelContainer(e) {
      if (!wasDragging) {
        const arrow = document.getElementById("uwu-arrow");
        climbingPanelContainer.classList.toggle("open");
        saveClimbingPanelStatus();
  
        if (climbingPanelContainer.classList.contains("open")) {
          arrow.textContent = "▲";
        } else {
          arrow.textContent = "▼";
        }
      }
      wasDragging = false;
    }

    function checkAndResetPanelPosition() {
      const windowWidth = window.innerWidth;
      const windowHeight = window.innerHeight;
      const panelWidth = climbingMainPanel.offsetWidth;
      const panelHeight = climbingMainPanel.offsetHeight;

      const savedStatus = JSON.parse(
        localStorage.getItem("uwu_climbingPanelStatus")
      );

      if (savedStatus) {
        currentX = savedStatus.x;
        currentY = savedStatus.y;
      } else {
        currentX = 0;
        currentY = 0;
      }

      if (
        currentX + panelWidth > windowWidth ||
        currentY + panelHeight > windowHeight
      ) {
        currentX = 0;
        currentY = 0;
        saveClimbingPanelStatus();
      }

      setPosition(currentX, currentY, climbingMainPanel);
    }

    climbingPanelButton.addEventListener("mousedown", dragStart);
    document.addEventListener("mouseup", dragEnd);
    document.addEventListener("mousemove", drag);
    climbingPanelButton.addEventListener("click", togglePanelContainer);

    setTimeout(loadClimbingPanelStatus, 10);

    const uwuClimbingPanel = document.createElement("style");
    uwuClimbingPanel.innerHTML = // css
    `
    #uwu-climbingPanelContainer {
      background-color: "";
      display: none;
      padding: 5px;
    }
    
    #uwu-climbingPanelContainer.open {
      display: block;
    }

    #uwu-climbingMainPanel {
      z-index: 2;
      pointer-events: auto;
      width: 260px;
      position: absolute;
      background-color: #ffffff08;
      border: 1px solid #ffffff1a;
      backdrop-filter: blur(20px);
      border-radius: 10px;
    }

    #uwu-climbingPanelButton .left-content {
      pointer-events: none;
      width: 90%;
    }

    #uwu-climbingPanelButton .right-content {
      pointer-events: none;
      width: 10%;
      text-align: right;
    }

    #uwu-arrow {
      font-size: 18px;
      margin-right: 8px;
    }

    #uwu-climbingPanelButton {
      cursor: grab;
      background-color: #00000026;
      border-radius: 10px;
      border: 1px solid #ffffff1a;
      display: flex;
      align-items: center;
      justify-content: space-around;
    }

    #uwu-climbingPanelButton h2 {
      display: flex;
      margin-top: 2px;
      margin-bottom: 2px;
      justify-content: center;
      pointer-events: none;
    }

    #uwu-climbingPanel {
      font-size: 26px;
      border-collapse: collapse;
      width: fit-content;
      background-color: #ffffff1a;
      border: 2px solid black;
    }
  
    #uwu-climbingPanel > tr> td {
      width: 23px;
      height: 32px;
      border: 1px solid black;
      text-align: center;
      cursor: pointer;
      pointer-events: auto;
      position: relative;
    }

    #uwu-climbingPanelContainer h3 {
      margin-top: 5px;
      margin-bottom: 5px;
    }

    #uwu-functionButtonsContainer {
      height: 25px;
    }

    #uwu-climbingPanel > tr > td:focus {
      outline: 2px solid white;
    }

    #uwu-climbingPanel > tr > td:not(:empty) {
      background-color: #cccccc4d;
    }

    #uwu-transferCheckbox, #uwu-transferValuesCheckbox {
    pointer-events: auto;
    cursor: pointer;
    }

    #uwu-buttonRow1,
    #uwu-buttonRow2 {
      display: flex;
      flex-wrap: wrap;
    }

    #uwu-climbingPanel > tab-container, #uwu-climbingPanel > table-container {
      display: inline-block;
      margin-right: 10px;
    }
  
    #uwu-climbingPanelContainer button {
      background-color: #ffffff4d;
      border: 1px solid rgba(255, 255, 255, 0.1);
      padding: 2px 10px;
      border-radius: 10px;
      cursor: pointer;
      transition: background-color 0.3s ease;
      margin: 3px;
      margin-left: 0px;
    }

    #uwu-buttonRow1 > div > button.tab-button.active,
    #uwu-buttonRow2 > div > button.table-button.active {
      background-color: #abf6ffb0;
    }

    #button-clear-table {
      margin-top: 5px !important;
      width: 100%;
      border-radius: 5px !important;
    }
  `;
    document.head.appendChild(uwuClimbingPanel);

    const uwuClimbingPanelHorizontal = document.createElement("style");
    uwuClimbingPanelHorizontal.innerHTML = // css
    `
    #uwu-climbingMainPanel {
      width: 390px !important;
    }

    #uwu-climbingPanelContent {
      display: grid !important;
      grid-template-columns: 1fr 2fr;
      grid-template-rows: auto auto;
    }
    
    #uwu-buttonContainer {
      overflow-y: auto;
      grid-column: 1 / 2;
      grid-row: 1 / 3;
    }
    
    #uwu-functionButtonsContainer {
      grid-column: 2 / 3;
      grid-row: 1 / 2;
    }
    
    #uwu-tableContainer {
      grid-column: 2 / 3;
      grid-row: 2 / 3;
    }
    `;

    if (settings.climbingPanelOrientation === "horizontal") {
      document.head.appendChild(uwuClimbingPanelHorizontal);
    }
  }
  // ====================================================================================================================
  //   . . . БЫСТРЫЕ СТИЛИ . . .
  // ====================================================================================================================
  const settingsContainer = document.getElementById(
    "extended-settings-container"
  );
  if (!settingsContainer) {
    console.error("Контейнер #extended-settings-container не найден");
    return;
  }

  const checkboxes = [
    {
      label: "Не показывать всплывающее окно 'О коте'",
      key: "hideCatTooltip",
      storageKey: "uwu_fastStyles",
      style: ".cat_tooltip { display: none !important; }",
      callback: function (checked) {
        if (checked) {
          const style = document.createElement("style");
          style.innerHTML = this.style;
          document.head.appendChild(style);
        } else {
          const styles = document.head.querySelectorAll("style");
          styles.forEach((style) => {
            if (style.innerHTML === this.style) {
              document.head.removeChild(style);
            }
          });
        }
      },
    },
    {
      label: "Скрыть Игровое поле",
      key: "hideGameField",
      storageKey: "uwu_fastStyles",
      style: "#cages_overflow { visibility: hidden !important; }",
      callback: function (checked) {
        if (checked) {
          const style = document.createElement("style");
          style.innerHTML = this.style;
          document.head.appendChild(style);
        } else {
          const styles = document.head.querySelectorAll("style");
          styles.forEach((style) => {
            if (style.innerHTML === this.style) {
              document.head.removeChild(style);
            }
          });
        }
      },
    },
    {
      label: "Скрыть фон Игрового Поля",
      key: "hideGameFieldBackground",
      storageKey: "uwu_fastStyles",
      style: "#cages_div { background-image: none !important; }",
      callback: function (checked) {
        if (checked) {
          const style = document.createElement("style");
          style.innerHTML = this.style;
          document.head.appendChild(style);
        } else {
          const styles = document.head.querySelectorAll("style");
          styles.forEach((style) => {
            if (style.innerHTML === this.style) {
              document.head.removeChild(style);
            }
          });
        }
      },
    },
    {
      label: "Скрыть Небо",
      key: "hideSky",
      storageKey: "uwu_fastStyles",
      style: "#tr_sky { display: none !important; }",
      callback: function (checked) {
        if (checked) {
          const style = document.createElement("style");
          style.innerHTML = this.style;
          document.head.appendChild(style);
        } else {
          const styles = document.head.querySelectorAll("style");
          styles.forEach((style) => {
            if (style.innerHTML === this.style) {
              document.head.removeChild(style);
            }
          });
        }
      },
    },
    {
      label: "Всегда день/ярко",
      key: "alwaysDay",
      storageKey: "uwu_settings",
      callback: function (checked) {
        updateAlwaysDayStyle(checked);
      },
    },
    {
      label: "Границы клеток",
      key: "cellsBorders",
      storageKey: "uwu_settings",
      callback: function (checked) {
        updateCellsBordersStyle(checked);
      },
    },
  ];

  const loadSettings = (storageKey) => {
    const savedSettings = localStorage.getItem(storageKey);
    return savedSettings ? JSON.parse(savedSettings) : {};
  };

  const saveSettings = (storageKey, settings) => {
    localStorage.setItem(storageKey, JSON.stringify(settings));
  };

  const settingsMap = {
    uwu_fastStyles: loadSettings("uwu_fastStyles"),
    uwu_settings: loadSettings("uwu_settings"),
  };

  const applyStyles = () => {
    checkboxes.forEach((checkbox) => {
      if (settingsMap[checkbox.storageKey][checkbox.key] === true) {
        checkbox.callback.call(checkbox, true);
      }
    });
  };

  if (settings.fastStyles) {
    const settingsDiv = document.createElement("div");
    settingsDiv.id = "fast-Styles-container";
    settingsDiv.classList.add("extended-settings-block");

    checkboxes.forEach((checkbox) => {
      const label = document.createElement("div");
      const input = document.createElement("input");
      input.type = "checkbox";
      input.name = checkbox.key;

      const storedValue = settingsMap[checkbox.storageKey][checkbox.key];
      if (storedValue === true) {
        input.checked = true;
        checkbox.callback.call(checkbox, true);
      }

      input.addEventListener("change", function () {
        settingsMap[checkbox.storageKey][checkbox.key] = this.checked;
        saveSettings(checkbox.storageKey, settingsMap[checkbox.storageKey]);
        checkbox.callback.call(checkbox, this.checked);
      });

      label.appendChild(input);
      label.appendChild(document.createTextNode(checkbox.label));
      settingsDiv.appendChild(label);
    });

    settingsContainer.appendChild(settingsDiv);

    const style = document.createElement("style");
    style.innerHTML = `
      .extended-settings-block {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
      }
      .extended-settings-block div {
        display: flex;
       align-items: center;
      }
    `;
    document.head.appendChild(style);
  } else {
    applyStyles();
  }
  // ====================================================================================================================
  //   . . . БЫСТРЫЕ ССЫЛКИ В ИГРОВОЙ . . .
  // ====================================================================================================================
  const quickLinks = {
    quickLink1: {
      href: "/settings",
      text: "Настройки",
    },
    quickLink2: {
      href: "/ls?id=0",
      text: "Памятка",
    },
    quickLink3: {
      href: "/blogs",
      text: "Блоги",
    },
    quickLink4: {
      href: "/sniff",
      text: "Лента",
    },
  };

  const spanElement = document.querySelector("span.small");

  Object.entries(quickLinks).forEach(([key, link]) => {
    if (settings[key]) {
      const newLink = document.createElement("a");
      newLink.href = link.href;
      newLink.textContent = link.text;

      const pipe = document.createTextNode(" | ");
      spanElement.appendChild(pipe);
      spanElement.appendChild(newLink);
    }
  });

  if (settings.userQuickLinks) {
    const userLinksArray = settings.userQuickLinks.split(", ");

    userLinksArray.forEach((userLink) => {
      const [href, text] = userLink.trim().split(" ");

      const newLink = document.createElement("a");
      newLink.href = href;
      newLink.textContent = text;

      const pipe = document.createTextNode(" | ");
      spanElement.appendChild(pipe);
      spanElement.appendChild(newLink);
    });
  }
  // ====================================================================================================================
  //  . . . ПОДСВЕТКА РЕСУРСОВ . . .
  // ====================================================================================================================
  if (settings.highlightResources) {
    function hexToRGBA(hex, alpha) {
      const r = parseInt(hex.slice(1, 3), 16);
      const g = parseInt(hex.slice(3, 5), 16);
      const b = parseInt(hex.slice(5, 7), 16);
      return `rgba(${r}, ${g}, ${b}, ${alpha})`;
    }
  
    const ITEM_MAP = {
      'Травы': ['13', '15', '17', '19', '21', '23', '25', '26', '106', '108', '109', '110', '111', '112', '115', '116', '119', '655'],
      'Мох': ['75', '78', '95'],
      'Паутина': ['20'],
      'Пыль': ['94', '385', '386', '387', '388', '389', '390', '391', '392'],
      'Ветки, вьюнки, костоправы': ['565', '566', '562', '563', '3993'],
      'Травящие предметы': ['985', '986', '987', '988', '989', '44', '180', '77', '7801', '7802', '7803', '7804', '7805', '7806']
    };
  
    function generateHighlightStyles(cageItem) {
      const savedSettings = localStorage.getItem('uwu_highlightResources');
      if (!savedSettings) return;
    
      const uwu_highlightResources = JSON.parse(savedSettings);
    
      if (settings.highlightResourcesStyle === "background") {
        const styleElement = document.getElementById('resourcesStyle') || document.createElement('style');
        styleElement.id = 'resourcesStyle';
        styleElement.textContent = '';
    
        uwu_highlightResources.forEach(resource => {
          if (resource.highlight) {
            const rgbaColor = hexToRGBA(resource.color, 0.4);
            let cssRules = '';
    
            const items = ITEM_MAP[resource.name];
            if (!items) {
              console.warn("Неизвестный ресурс:", resource.name);
              return;
            }
    
            items.forEach(itemName => {
              cssRules += `
                .cage_items[style*='things/${itemName}.png'] {
                  background-color: ${rgbaColor} !important;
                }`;
            });
    
            if (cssRules) {
              styleElement.textContent += cssRules;
            }
          }
        });
    
        document.head.appendChild(styleElement);
      } else if (settings.highlightResourcesStyle === "glow") {
        const style = cageItem.getAttribute("style");
        if (!style) return;
    
        const oldHighlights = cageItem.querySelectorAll("style.uwu_itemHighlight");
        oldHighlights.forEach(oldHighlight => oldHighlight.remove());
    
        cageItem.style.position = 'relative';
    
        uwu_highlightResources.forEach((resource) => {
          if (resource.highlight) {
            const rgbaColor = hexToRGBA(resource.color, 1);
            let highlightedItems = [];
    
            const items = ITEM_MAP[resource.name];
            if (!items) {
              console.warn("Неизвестный ресурс:", resource.name);
              return;
            }
    
            items.forEach((itemName) => {
              const backgroundImages = style.match(/url\("things\/(.*?)\.png"\) (\d+)% (\d+)% no-repeat/g) || [];
    
              backgroundImages.forEach((backgroundImage) => {
                if (backgroundImage.includes(`things/${itemName}.png`)) {
                  const positionMatch = backgroundImage.match(/(url\("things\/(.*?)\.png"\)) (\d+)% (\d+)% no-repeat/);
                  const imageUrl = positionMatch ? positionMatch[1] : "";
                  const positionX = positionMatch ? positionMatch[3] : "0";
                  const positionY = positionMatch ? positionMatch[4] : "0";
    
                  highlightedItems.push(
                    `${imageUrl} ${positionX}% ${positionY}% no-repeat`
                  );
                }
              });
            });
    
            if (highlightedItems.length > 0) {
              const styleBody = `
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                pointer-events: none;
                background: ${highlightedItems.join(", ")};
                filter: drop-shadow(0 0 8px ${rgbaColor}) drop-shadow(0 0 8px ${rgbaColor});
              `;
    
              const styleElement = document.createElement('style');
              styleElement.classList.add('uwu_itemHighlight');
              styleElement.textContent = `
                .cage_items[style*='${style}']::before {
                  ${styleBody}
                }
              `;
              cageItem.appendChild(styleElement);
            }
          }
        });
      }
    }
  
    function setupMutationObserver(targetNode, callback, config) {
      const observer = new MutationObserver((mutationsList, observer) => {
        for (let mutation of mutationsList) {
          if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
            callback(targetNode);
          }
        }
      });
  
      observer.observe(targetNode, config);
    }
  
    document.querySelectorAll(".cage_items").forEach((cageItem) => {
      generateHighlightStyles(cageItem);
      setupMutationObserver(cageItem, generateHighlightStyles, {
        attributes: true,
        childList: true,
        subtree: true,
      });
    });
  }
  // ====================================================================================================================
  //   . . . ПОЛЬЗОВАТЕЛЬКИЙ ФОН . . .
  // ====================================================================================================================
  const cagesDiv = document.querySelector("#cages_div");

  function createBackgroundDiv() {
    const backgroundDiv = document.createElement("div");
    backgroundDiv.style.position = "fixed";
    backgroundDiv.style.top = "-1%";
    backgroundDiv.style.left = "-1%";
    backgroundDiv.style.width = "102%";
    backgroundDiv.style.height = "102%";
    backgroundDiv.style.zIndex = "-2";
    backgroundDiv.style.overflow = "hidden";
    return backgroundDiv;
  }

  function updateBackgroundImage(backgroundDiv, imageUrl) {
    if (imageUrl) {
      backgroundDiv.style.backgroundImage = `url(${imageUrl})`;
      backgroundDiv.style.backgroundSize = "cover";
      backgroundDiv.style.backgroundPosition = "center";
      backgroundDiv.style.backgroundRepeat = "no-repeat";
    } else {
      backgroundDiv.style.backgroundImage = "none";
    }
  }

  if (settings.backgroundRepeat) {
    const backgroundDiv = createBackgroundDiv();

    backgroundDiv.style.filter = "blur(16px)";
    backgroundDiv.style.backgroundBlendMode = "overlay";
    backgroundDiv.style.backgroundColor = "rgba(0, 0, 0, 0.5)";

    const backgroundImageStyle =
      window.getComputedStyle(cagesDiv).backgroundImage;
    const url = backgroundImageStyle.match(/url\("?(.+?)"?\)/);
    const backgroundImageUrl = url ? url[1] : null;

    updateBackgroundImage(backgroundDiv, backgroundImageUrl);
    globalContainerElement.appendChild(backgroundDiv);

    setupMutationObserver(
      "#cages_div",
      () => {
        const backgroundImageStyle =
          window.getComputedStyle(cagesDiv).backgroundImage;
        const url = backgroundImageStyle.match(/url\("?(.+?)"?\)/);
        const backgroundImageUrl = url ? url[1] : null;
        updateBackgroundImage(backgroundDiv, backgroundImageUrl);
      },
      { attributes: true, attributeFilter: ["style"] },
      8,
      500,
      10
    );
  }

  if (settings.backgroundUser) {
    const backgroundDiv = createBackgroundDiv();
    updateBackgroundImage(backgroundDiv, settings.backgroundUserImageURL);
    globalContainerElement.appendChild(backgroundDiv);
  }
  // ====================================================================================================================
  //   . . . ПОЛЬЗОВАТЕЛЬСКИЕ ЦВЕТА НАВЫКОВ И ПАРАМЕТРОВ . . .
  // ====================================================================================================================
  if (settings.userParametersTheme) {
    const defaultBackgroundImageUrl =
      "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/parametersBackgroundImageURL.png";

    function applyParameterColors() {
      let cssStyles = "";

      const otherColors = settings.parametersColors.other;
      const otherFirstCellBackground = `linear-gradient(to right, ${otherColors[0]}, ${otherColors[1]})`;
      const otherLastCellBackground = `linear-gradient(to right, ${otherColors[2]}, ${otherColors[3]})`;

      cssStyles += `#parameters_block .parameter td:first-child { background: ${otherFirstCellBackground}; }\n`;
      cssStyles += `#parameters_block .parameter td:last-child { background: ${otherLastCellBackground}; }\n`;

      for (const paramId in settings.parametersColors) {
        if (paramId === "other") continue;

        const colors = settings.parametersColors[paramId];
        const backgroundImageURL = settings.parametersUserBackgroundImage
          ? settings.parametersUserBackgroundImageURL
          : defaultBackgroundImageUrl;
        const firstCellBackground =
          settings.parametersBackgroundImage ||
          settings.parametersUserBackgroundImage
            ? `url(${backgroundImageURL}), linear-gradient(to right, ${colors[0]}, ${colors[1]})`
            : `linear-gradient(to right, ${colors[0]}, ${colors[1]})`;
        const lastCellBackground =
          settings.parametersBackgroundImage ||
          settings.parametersUserBackgroundImage
            ? `url(${backgroundImageURL}), linear-gradient(to right, ${colors[2]}, ${colors[3]})`
            : `linear-gradient(to right, ${colors[2]}, ${colors[3]})`;

        cssStyles += `#${paramId}_table .parameter td:first-child { background: ${firstCellBackground}; }\n`;
        cssStyles += `#${paramId}_table .parameter td:last-child { background: ${lastCellBackground}; }\n`;
      }

      const styleTag = document.createElement("style");
      styleTag.id = "custom-parameter-styles";
      styleTag.innerHTML = cssStyles;
      document.head.appendChild(styleTag);
    }

    applyParameterColors();
  }
  // ====================================================================================================================
  //   . . . ПОЛЬЗОВАТЕЛЬСКИЙ ШРИФТ . . .
  // ====================================================================================================================
  let fontSize = JSON.parse(localStorage.getItem('uwu_fontSize'));
  function applyFonts() {
    const newFontStyle = document.createElement("style");
    newFontStyle.innerHTML = // css
      `
      body {
        font-size: ${fontSize?.fontSizeBody}px;
        font-family: ${fontSize?.fontFamilyBody};
      }

      .small {
        font-size: ${fontSize?.fontSizeSmall}px;
      }

      #location {
        font-size: ${fontSize?.fontSizeLocation}px !important;
      }

      .vlm0 {
        font-size: ${fontSize?.vlm0}px; }

      .vlm1 {
        font-size: ${fontSize?.vlm1}px; }

      .vlm2 {
        font-size: ${fontSize?.vlm2}px; }

      .vlm3 {
        font-size: ${fontSize?.vlm3}px; }

      .vlm4 {
        font-size: ${fontSize?.vlm4}px; }

      .vlm5 {
        font-size: ${fontSize?.vlm5}px; }

      .vlm6 {
        font-size: ${fontSize?.vlm6}px; }

      .vlm7 {
        font-size: ${fontSize?.vlm7}px; }

      .vlm8 {
        font-size: ${fontSize?.vlm8}px; }

      .vlm9 {
        font-size: ${fontSize?.vlm9}px; }

      .vlm10 {
        font-size: ${fontSize?.vlm10}px; }
      `;
    document.head.appendChild(newFontStyle);
  }

  if (settings.useUserFonts) {
    applyFonts();
  }

  // ====================================================================================================================
  //   . . . ПОЛЬЗОВАТЕЛЬСКИЕ ТЕМЫ / ЦВЕТА . . .
  // ====================================================================================================================
  function applyTheme() {
    const newStyle = document.createElement("style");
    newStyle.innerHTML = // css
    `
      body {
        background: ${theme?.backgroundColor || ""};
      }

      #cages_overflow {
        background: black;
      } 

      #tr_actions > td, #tr_mouth > td, #location, .small {
        background-color: ${theme?.blocksColor || ""};
      }

      #history_block > div {
        background-color: unset !important;
      }

      #main_table, #tr_mouth, #tr_actions, #info_main {
        background-color: unset;
        background: none;
      }
    
      #tr_chat {
        background-color: ${theme?.chatColor || ""};
      }
    
      body, input, select, .ui-slider-handle {
        color: ${theme?.textColor || ""};
      }
    
      input, select, .ui-slider-horizontal {
        background-color: ${theme?.accentColor1 || ""};
        background: ${theme?.accentColor1 || ""};
        border: solid 1px ${theme?.accentColor2 || ""};
      }

      .ui-widget-content .ui-state-default {
        background: ${theme?.accentColor2 || ""};
        border: solid 1px ${theme?.accentColor2 || ""};
      } 

      hr {
        border: solid 1px ${theme?.accentColor2 || ""};
      }

      .myname {
        color: ${theme?.accentColor1 || ""};
        background: ${theme?.accentColor3 || ""};
      }

      span.cat_tooltip {
        background: ${theme?.catTooltipBackground || ""} !important;
        color: ${theme?.textColor || ""} !important;
        border: 2px solid ${theme?.accentColor2 || ""} !important;
      } 

      span.cat_tooltip > span.online {
        filter: brightness(2) contrast(150%);
      }
      
      .cat:hover .cat_tooltip a, .other_cats_list > a { 
        color: ${theme?.linkColor || ""}; 
      }

      .move_name {
        color: ${theme?.moveNameColor || ""};
        background-color: ${theme?.moveNameBackground || ""} !important;
      }
    
      a, a:hover {
        color: ${theme?.linkColor || ""};
      }

      #fightPanel {
        background-color: ${theme?.fightPanelBackground || ""};
      }

      .hotkey {
        background-color: ${theme?.accentColor1 || ""};
      }

      #newchat, #newls {
        color: ${theme?.accentColor3 || ""};
      }

      .cat-info {
      background-color: ${theme?.catTooltipBackground || ""} !important;
      color: ${theme?.textColor || ""} !important;
      }
      `;
    document.head.appendChild(newStyle);
  }

  if (settings.userTheme) {
    applyTheme();
  }
  // ====================================================================================================================
  //   . . . РЕДИЗАЙН ИГРОВОЙ . . .
  // ====================================================================================================================
  if (settings.customLayout) {
    // ==================================================================
    function prependOtherCatsListContent() {
      const otherCatsList = document.querySelector(".other_cats_list");
      const smallContainer = document.querySelector(".small");

      if (!otherCatsList || !smallContainer) return;

      const catsListContent = otherCatsList.innerHTML;

      switch (settings.showOtherCatsList) {
        case "1":
          break;
        case "2":
          const clickableBlockHTML =
            '<span style="display: inline; cursor: pointer;"><a href="#" style="display: inline; pointer-events: none;">Душевые коты</a></span>';
          smallContainer.insertAdjacentHTML(
            "afterbegin",
            clickableBlockHTML + " || "
          );

          const clickableBlock = smallContainer.firstChild;

          const catsListContainer = document.createElement("span");
          catsListContainer.id = "catsListContainer";
          catsListContainer.innerHTML = ": " + catsListContent;
          catsListContainer.style.display = "none";
          smallContainer.insertBefore(
            catsListContainer,
            smallContainer.firstChild.nextSibling
          );

          clickableBlock.addEventListener("click", (event) => {
            event.preventDefault();
            if (catsListContainer.style.display === "none") {
              catsListContainer.style.display = "inline";
            } else {
              catsListContainer.style.display = "none";
            }
          });
          break;
        case "3":
          smallContainer.insertAdjacentHTML(
            "afterbegin",
            catsListContent + " || "
          );
          break;
        default:
          break;
      }
    }

    setupSingleCallback(".other_cats_list", prependOtherCatsListContent);
    // ==================================================================

    function applyLayoutSettings() {
      const savedSettings = localStorage.getItem("uwu_layoutSettings");
      if (savedSettings) {
        const { leftBlocks, rightBlocks } = JSON.parse(savedSettings);

        const mainTable = document.getElementById("main_table");
        const tbody = mainTable.getElementsByTagName("tbody")[0];
        const blocks = Array.from(tbody.children);

        resetBlockStyles(tbody);

        const gridAreaTemplate = generateGridTemplate(leftBlocks, rightBlocks);

        // console.log(gridAreaTemplate);

        tbody.style.display = "grid";
        tbody.style.gridTemplateAreas = gridAreaTemplate;
        tbody.style.gridTemplateColumns = "1fr auto 1fr";
        tbody.style.gridTemplateRows = generateGridRowStyles(
          leftBlocks,
          rightBlocks
        );

        blocks.forEach((block) => {
          if (block.id) {
            block.style.gridArea = block.id;
          }
        });
      }
    }

    function generateGridRowStyles(leftBlocks, rightBlocks) {
      const numRows = Math.max(leftBlocks.length, rightBlocks.length);
      let rowStyles = [];

      for (let i = 0; i < numRows; i++) {
        let rowHeight = "auto";
        rowStyles.push(rowHeight);
      }

      const rowStylesString = rowStyles.join(" ");
      return rowStylesString;
    }

    function generateGridTemplate(leftBlocks, rightBlocks) {
      const numRows = Math.max(leftBlocks.length, rightBlocks.length);
      let template = "";
      let lastLeftBlockId = "";
      let lastRightBlockId = "";
      let isFirstRow = true;

      for (let i = 0; i < numRows; i++) {
        const leftBlockId = leftBlocks[i] || lastLeftBlockId;
        const rightBlockId = rightBlocks[i] || lastRightBlockId;

        if (isFirstRow) {
          template += `"${leftBlockId} tr_field ${rightBlockId}" `;
          isFirstRow = false;
        } else {
          template += `"${
            leftBlockId === lastLeftBlockId ? "." : leftBlockId
          } . ${rightBlockId === lastRightBlockId ? "." : rightBlockId}" `;
        }

        if (leftBlockId) {
          lastLeftBlockId = leftBlockId;
        }
        if (rightBlockId) {
          lastRightBlockId = rightBlockId;
        }
      }

      return template;
    }

    function resetBlockStyles(parent) {
      const blocks = parent.querySelectorAll("tr > *");
      blocks.forEach((block) => {
        block.style.gridArea = "";
      });
    }

    // Больше фикс стилей.
    const fixStyle = document.createElement("style");
    fixStyle.innerHTML = // css
    `
      #main_table {
        width: 100%;
        max-width: unset;
        height: 100%;

        background: none;
        border-spacing: 0px !important;
      }

      #main_table > tbody {
        margin-top: 10px;
      }

      #app {
        width: 100%;
        height: 100%;
      }
      
      #chat_msg, #cws_chat_msg {
        height: ${settings.chatHeight}px;
        width: auto;
      }

      #history_block > div { 
        visibility: hidden; 
      }

      #history_block {
        display: block;
        height: ${settings.historyHeight}px; 
        overflow-y: auto;
        resize: vertical;
      }

      #family { 
        display: block;
        overflow-y: auto;
        resize: vertical;
      }

      .infos {
        width: auto;
      }

      #cages_overflow {
        background: black;
      }

      .chat_text {
        width: auto !important;
        overflow-wrap: anywhere;
      }

      #chat_form {
        margin: unset;
        margin: 5px;
      }

      #volume {
        margin: 5px;
      }

      #app > p:last-of-type {
        position: fixed;
        bottom: 0px;
        margin: 8px;
      }

      h2 {
        margin-top: 5px;
        margin-bottom: 10px;
      }

      #itemList {
        overflow-y: auto;
        max-height: 180px;
        display: flex;
        flex-wrap: wrap;
      }

      #location {
        visibility: visible;
        position: fixed;
        right: 0px;
        top: 0px;
        font-size: 1.5rem;
        background-color: ${theme?.blocksColor};
        z-index: 1;
      }

      .small {
        position: fixed;
        left: 0px;
        top: 0px;
        font-size: ${fontSize?.fontSizeSmall || 16}px;
        z-index: 1;
      }

      body {
        overflow-y: scroll;
      }

      #tr_chat, #tr_actions > td, #tr_mouth > td, #location, .small, #info_main > tbody > tr > td {
        padding: 5px !important;
      }

      #tr_chat > td {
        display: contents;
      }

      #chat_msg, #cws_chat_msg {
        height: ${theme?.chatHeight}px;
        resize: vertical;
      }

      #tr_field, #tr_info {
        height: 10px;
      }

      #newchat, #newls {
        background-color: transparent;
      }

      .other_cats_list {
        display: none;
      }
    `;
    document.head.appendChild(fixStyle);
    applyLayoutSettings();

    const paragraph = document.querySelector("#app > p > b");
    paragraph.textContent = "ТБ:";

    function applyLayoutSettingsForInfoMain() {
      const infoMainTable = document.getElementById("info_main");
      const tableRow = infoMainTable.querySelector("tr");
      const tds = tableRow.getElementsByTagName("td");

      for (const td of tds) {
        td.style.gridArea = "";
      }

      tableRow.style.display = "grid";
      // хахахах поглядите на смешного строчного
      tableRow.style.gridTemplateAreas = `"parameter"
                                          "history"
                                          "family"`;

      tds[0].style.gridArea = "family";
      tds[1].style.gridArea = "history";
      tds[2].style.gridArea = "parameter";
    }
    applyLayoutSettingsForInfoMain();
  }

  // ====================================================================================================================
  //   . . . ПОДСКАЗЫВАТЬ ОСТАВШЕЕСЯ ВРЕМЯ ДО НЮХА . . .
  // ====================================================================================================================
  if (settings.showHintWhenToSniff) {
    let firstNote = "";
    let timerStartTime = null;
    let initialTimerValue = 0;
    
    const smellTimer = {
      0: 3600,
      1: 3600,
      2: 3600,
      3: 3600,
      4: 1800,
      5: 1200,
      6: 900,
      7: 720,
      8: 600,
      9: 0,
    };
    
    function formatTime(seconds) {
      const hours = Math.floor(seconds / 3600);
      const minutes = Math.floor((seconds % 3600) / 60);
      const remainingSeconds = seconds % 60;
      return `${hours ? `${hours} ч ` : ""}${
        minutes ? `${minutes} мин ` : ""
      }${remainingSeconds} с`;
    }
    
    function updateSmellTimer() {
      const timerElement = document.getElementById("uwu_sniff_timer");
      if (!timerElement) return;
    
      if (timerStartTime !== null) {
        const isActive = document.querySelector('#dein a[data-id="14"]') !== null;
        if (isActive) {
          timerStartTime = null;
          initialTimerValue = 0;
          timerElement.setAttribute("value", 0);
          timerElement.textContent = "";
          soundManager.playSound("notificationSound3", settings.notificationMyNameVolume);
          return;
        }
    
        const currentTime = Date.now();
        const elapsedTime = Math.floor((currentTime - timerStartTime) / 1000);
        let remainingTime = initialTimerValue - elapsedTime;
    
        if (remainingTime <= 0) {
          remainingTime = 0;
          timerStartTime = null;
          initialTimerValue = 0;
          soundManager.playSound("notificationSound3", settings.notificationMyNameVolume);
        }
    
        timerElement.setAttribute("value", remainingTime);
        timerElement.textContent = remainingTime > 0 ? ` | Нюх через: ${formatTime(remainingTime)}` : "";
      }
    }
    
    setInterval(updateSmellTimer, 1000);
    
    function smellIconClick() {
      firstNote = document.getElementById("error").innerHTML;
      document.getElementById("smell_icon").click();
    }
    
    function errorObserver() {
      const errorElement = document.getElementById("error");
      const html = errorElement.innerHTML;
      if (html && html.includes("Следующее обнюхивание")) {
        const text = html.replace(
          "Следующее обнюхивание будет доступно через ",
          ""
        );
        const smellMin =
          (text.match(/(\d+) мин/g) || [])
            .map((num) => parseInt(num.replace(/\D/g, ""), 10))
            .shift() || 0;
        const smellSec = parseInt(
          (text.match(/(\d+) с/g) || [])
            .map((num) => num.replace(/\D/g, ""))
            .shift(),
          10
        );
        const totalSec = smellMin * 60 + smellSec;
        const timerElement = document.getElementById("uwu_sniff_timer");
        timerElement.setAttribute("value", totalSec);
        timerElement.textContent = ` | Нюх через: ${smellMin} мин ${smellSec} с`;
        timerStartTime = Date.now();
        initialTimerValue = totalSec;
        if (firstNote !== "") {
          errorElement.innerHTML = firstNote;
          firstNote = "";
        }
      } else if (html.includes("Час уже прошёл") && firstNote !== "") {
        errorElement.innerHTML = firstNote;
        firstNote = "";
      }
    }
    
    function messObserver() {
      const blockMessElement = document.getElementById("block_mess");
      if (!blockMessElement) return;
    
      const isActive = document.querySelector('#dein a[data-id="14"]') !== null;
      if (!isActive && blockMessElement.children.length === 0 && timerStartTime === null) {
        const smellLevel = document.querySelector("#smell b").textContent;
        const smellTime = smellTimer[smellLevel];
        const timerElement = document.getElementById("uwu_sniff_timer");
        timerElement.setAttribute("value", smellTime);
        timerElement.textContent = ` | Нюх через: ${formatTime(smellTime)}`;
        timerStartTime = Date.now();
        initialTimerValue = smellTime;
      }
    }
    
    function timerElement() {
      const smallElement = document.querySelector(".small");
      if (smallElement) {
        smallElement.insertAdjacentHTML(
          "beforeend",
          '<span id="uwu_sniff_timer" value="0"></span>'
        );
      }
    }
    
    window.addEventListener("load", function () {
      setupSingleCallback(".small", timerElement);
      setupSingleCallback("#smell_icon", smellIconClick);
      setupMutationObserver("#error", errorObserver, {
        childList: true,
        subtree: true,
      });
      setupMutationObserver("#block_mess", messObserver, {
        childList: true,
        subtree: true,
      }, 8, 500, 20);
    });
  }
  // ====================================================================================================================
  //   . . . ДУБЛИРОВАНИЕ ДЕЙСТВИЙ НА ВКЛАДКУ БРАУЗЕРА . . .
  // ====================================================================================================================
  if (settings.duplicateTimeInBrowserTab) {
    const blockMess = document.getElementById("block_mess");
    const titleElement = document.querySelector("title");
    let previousTime = null;
    let previousMessage = null;
  
    function updateTitle() {
      const timeElement = blockMess.querySelector("#sek");
      const messageText = blockMess.textContent.trim();
  
      if (messageText === previousMessage) return;
  
      const catNameMatch = messageText.match(/^(.+?)\s+держит/);
      const catName = catNameMatch ? catNameMatch[1] : "";
  
      if (catName) {
        titleElement.textContent = `Поднят. Во рту | ${catName}`;
      } else if (timeElement) {
        const currentTime = timeElement.textContent.trim();
        if (currentTime !== previousTime) {
          const actionText = messageText
            .replace(currentTime, "")
            .replace(/\s*\.\s*Отменить$/, "")
            .trim();
          titleElement.textContent = `${currentTime} | ${actionText}`;
          previousTime = currentTime;
        }
      } else {
        titleElement.textContent = "Игровая / CatWar";
        previousTime = null;
      }
  
      previousMessage = messageText;
    }
  
    setupMutationObserver("#block_mess", updateTitle, { childList: true, subtree: true });
  }
  // ====================================================================================================================
  //   . . . ЗВУКОВЫЕ УВЕДОМЛЕНИЯ . . .
  // ====================================================================================================================
  // мяу мяу мяу мяу мяу мяу мяу мяу мяу мяу мяу мяу
  // ====================================================================================================================
  //   . . . ЛИЧНЫЕ СООБЩЕНИЯ . . .
  // ====================================================================================================================
  let previousCount = 0;

  if (settings.notificationPM) {
    const newlsElement = document.getElementById("newls");
    if (newlsElement) {
      const observer = new MutationObserver(handleNewlsChange);
      observer.observe(newlsElement, {
        characterData: true,
        subtree: true,
      });
    }

    function handleNewlsChange(mutations) {
      if (mutations.length > 0) {
        const currentText = newlsElement.textContent;
        const currentCount = parseInt(
          currentText.match(/\(\d+\)/)?.[0].slice(1, -1) || 0,
          10
        );

        if (!isNaN(currentCount) && currentCount > previousCount) {
          soundManager.playSound(
            "notificationSound1",
            settings.notificationMyNameVolume
          );
          previousCount = currentCount;
        } else if (!isNaN(currentCount)) {
          previousCount = currentCount;
        }
      }
    }
  }
  // ====================================================================================================================
  //   . . . ОКОНЧАНИЕ ДЕЙСТВИЯ . . .
  // ====================================================================================================================
  if (settings.notificationActionEnd) {
    const blockMess = document.getElementById("block_mess");
    let wasBlockMessEmpty = blockMess.innerHTML.trim() === "";
    let actionStartTime = null;

    const observer = new MutationObserver(() => {
      const isBlockMessEmptyNow = blockMess.innerHTML.trim() === "";

      if (!isBlockMessEmptyNow && !actionStartTime) {
        actionStartTime = Date.now();
      } else if (isBlockMessEmptyNow && actionStartTime) {
        const actionEndTime = Date.now();
        const actionDuration = actionEndTime - actionStartTime;

        if (actionDuration >= 6000) {
          soundManager.playSound(
            "notificationSound3",
            settings.notificationMyNameVolume
          );
        }
        actionStartTime = null;
      }

      wasBlockMessEmpty = isBlockMessEmptyNow;
    });

    observer.observe(blockMess, { childList: true, subtree: true });
  }
  // ====================================================================================================================
  //   . . . ПОДНЯЛИ В РОТ . . .
  // ====================================================================================================================
  if (settings.notificationInMouth) {
    const blockMess = document.getElementById("block_mess");

    const observer = new MutationObserver(() => {
      if (blockMess.innerHTML.includes("во рту. Вы не сможете выбраться")) {
        soundManager.playSound(
          "notificationSound1",
          settings.notificationMyNameVolume
        );
      }
    });

    observer.observe(blockMess, { childList: true, subtree: true });
  }
  // ====================================================================================================================
  //   . . . ВВЕЛИ В БОЕВУЮ СТОЙКУ . . .
  // ====================================================================================================================
  if (settings.notificationInFightMode) {
    const attackRegex = /в боевую стойку, поскольку на меня напал/;
    let previousHistory = "";

    const updateHistory = () => {
      const istElement = document.getElementById("ist");
      const currentHistory = istElement.innerHTML;

      if (currentHistory !== previousHistory) {
        previousHistory = currentHistory;

        const entries = currentHistory.split(".");
        const lastEntry = entries[entries.length - 2];

        if (lastEntry !== undefined && attackRegex.test(lastEntry)) {
          soundManager.playSound(
            "notificationSound1",
            settings.notificationMyNameVolume
          );
        }
      }
    };

    const historyBlock = document.getElementById("history_block");
    const observer = new MutationObserver(() => {
      updateHistory();
    });

    const config = {
      childList: true,
      subtree: true,
      characterData: true,
    };
    observer.observe(historyBlock, config);
  }
  // ====================================================================================================================
  // мяу мяу мяу мяу мяу мяу мяу мяу мяу мяу мяу мяу
  // ====================================================================================================================
  //   . . . СОВРЕМЕННЫЙ (НОВЫЙ) ЧАТ . . .
  // ====================================================================================================================
  // я на этом инвалиде потерял все нервы кетвар желаю тебе счастья удачи и всего хорошего 😌😌😌😌😌😌😌😌😌😌
  // И ДО СИХ ПОР ТЕРЯЮ ААААА
  // TODO - как-то пределать шоле
  if (settings.newChat) {
    const newChatContainer = document.createElement("div");
    newChatContainer.id = "uwu_chat_msg";
    const chatForm = document.getElementById("chat_form");
    chatForm.parentNode.insertBefore(newChatContainer, chatForm.nextSibling);

    newChatContainer.addEventListener("click", function (event) {
      const target = event.target;

      const nickElement = target.closest(".nick");
      if (nickElement) {
        const textArea = document.getElementById("text");
        textArea.value += nickElement.textContent;
        textArea.focus();
        return;
      }

      const reportButton = target.closest(".msg_report");
      if (reportButton) {
        const dataId = reportButton.getAttribute("data-id");
        const originalReportLink = document.querySelector(
          `#chat_msg .msg_report[data-id="${dataId}"]`
        );
        if (originalReportLink) {
          originalReportLink.click();
        }
        return;
      }
    });

    const chatElement = document.getElementById("chat_msg");
    if (chatElement) {
      const observer = new MutationObserver(handleNewChatMessage);
      observer.observe(chatElement, { childList: true, subtree: true });
    }

    let addedSpanCount = 0;

    function handleNewChatMessage(mutations) {
      const addedNodes = Array.from(mutations)
        .flatMap((mutation) => Array.from(mutation.addedNodes))
        .filter(
          (node) =>
            node.nodeName === "SPAN" && node.querySelector("td > .chat_text")
        );

      addedSpanCount += addedNodes.length;
      processChatMessages(addedSpanCount);
      addedSpanCount = 0;
    }

    function processChatMessages(messageCount) {
      const chatMessages = document.querySelectorAll("#chat_msg > span");
      const messagesArray = Array.from(chatMessages);
      const messagesToProcess = messagesArray.slice(0, messageCount);
      messagesToProcess.reverse();

      messagesToProcess.forEach((message) => {
        copyMessageToNewChat(message);
      });
    }

    function copyMessageToNewChat(chatMessage) {
      const chatTextSpan = chatMessage.querySelector("td > .chat_text");
      const messageSpan = chatTextSpan.querySelector("span");
      const messageText = messageSpan ? messageSpan.innerHTML : "";
      const nickElement = chatTextSpan.querySelector(".nick");
      const nickName = nickElement ? nickElement.textContent.trim() : "";
      const chatTextClasses = chatTextSpan.className;
      const nickStyle = nickElement ? nickElement.getAttribute("style") : "";
      let nameFound = false;

      let processedText = messageText;

      if (settings.namesForNotification) {
        const names = settings.namesForNotification
          .trim()
          .split(/\s*,\s*/)
          .filter((name) => name);

        names.forEach((name) => {
          const regex = new RegExp(
            `(^|\\s|[.,!?])(${name})(?=$|\\s|[.,!?])`,
            "gi"
          );
          processedText = processedText.replace(regex, (match, p1, p2) => {
            nameFound = true;
            return `${p1}<span class="myname">${p2}</span>`;
          });
        });
      }

      if (!nameFound && messageSpan && messageSpan.querySelector(".myname")) {
        nameFound = true;
      }

      if (nameFound) {
        soundManager.playSound(
          settings.myNameNotificationSound,
          settings.notificationMyNameVolume
        );
      }

      const profileLink = chatMessage.querySelector('a[href^="/cat"]').href;
      const catIdMatch = profileLink.match(/\/cat(\d+)/);
      const catId = catIdMatch ? catIdMatch[1] : ". . .";

      const reportLink = chatMessage.querySelector(".msg_report");
      const dataId = reportLink ? reportLink.getAttribute("data-id") : "";

      const newChatMessageHTML = // html
      `
        <hr>
        <div id="msg">
          <div class="${chatTextClasses}">${processedText} - <b class="nick" style="${nickStyle}">${nickName}</b> <i>[${catId}]</i></div>
          <div style="display: flex; width: 42px; justify-content: flex-end; margin-right: 2px;">
            <a href="${profileLink}" title="Перейти в профиль" target="_blank" rel="noopener noreferrer">➝</a>&nbsp;|&nbsp;
            <a href="#" title="Пожаловаться на нарушение ОПИ" class="msg_report" data-id="${dataId}">X</a>
          </div>
        </div>
      `;
      newChatContainer.insertAdjacentHTML("afterbegin", newChatMessageHTML);
    }

    const uwuChatMsg = document.createElement("style");
    uwuChatMsg.innerHTML = `
        #uwu_chat_msg {
          height: ${settings.chatHeight}px;
          resize: vertical;
          overflow-y: auto;
          display: flex;
          flex-direction: ${settings.reverseChat ? "column-reverse" : "column"};
        }
  
        #chat_msg {
          display: none;
        }
  
        #msg {
          display: flex;
          justify-content: space-between;
        }

        #uwu_chat_msg > hr {
          width: -webkit-fill-available;
        }
     `;
    document.head.appendChild(uwuChatMsg);
  }
  // ====================================================================================================================
  //   . . . НОВЫЙ ВВОД ЧАТА . . .
  // ====================================================================================================================
  const chatForm = document.getElementById("chat_form");
  const trChatTd = document.querySelector("#tr_chat > td");

  function updateChatFormPosition() {
    if (settings.reverseChat) {
      trChatTd.appendChild(chatForm);
    } else {
      trChatTd.prepend(chatForm);
    }
  }
  updateChatFormPosition();

  if (settings.newChatInput) {
    const txtSpan = document.getElementById("txt");
    const selectField = txtSpan.querySelector("select#text");

    let textarea;

    function initTextarea(id, value) {
      const textarea = document.createElement("textarea");
      textarea.id = id;
      textarea.maxLength = 255;
      textarea.style.height = "auto";
      textarea.style.width = "100%";
      textarea.style.resize = "vertical";
      textarea.value = value || "";
      return textarea;
    }

    if (selectField) {
      textarea =
        document.getElementById("text-hide") || initTextarea("text-hide");
      textarea.style.display = "none";
    } else {
      const inputField = txtSpan.querySelector("input#text");

      textarea = initTextarea("text", inputField ? inputField.value : "");
      txtSpan.insertBefore(textarea, inputField);
    }

    const observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.type === "childList") {
          const selectField = txtSpan.querySelector("select#text");
          if (selectField) {
            textarea.style.display = "none";
            textarea.id = "text-hide";
          } else {
            textarea.style.display = "";
            textarea.id = "text";
          }
        }
      });
    });

    observer.observe(txtSpan, { childList: true });

    // Make Enter great again!
    textarea.addEventListener("keydown", function (event) {
      if (event.key === "Enter") {
        if (event.shiftKey) {
          event.preventDefault();
          textarea.value += "\n";
        } else {
          event.preventDefault();
          const sendButton = document.getElementById("msg_send");
          sendButton.click();
        }
      }
    });

    const NewChatDesign = document.createElement("style");
    NewChatDesign.innerHTML = `
  input#text {
    display: none;
  }

  #text, #text-hide {
    color: ${theme?.textColor};
    background: ${theme?.accentColor1};
    border: solid 1px ${theme?.accentColor2};
    font-family: Verdana;
  }
`;
    document.head.appendChild(NewChatDesign);
  }
  // ====================================================================================================================
  //   . . . РЕДИЗАЙНЫ + + ЗАКРУГЛЕНИЕ БЛОКОВ . . .
  // ====================================================================================================================
  const sliceInfoStyle = document.createElement("style");

  if (settings.sliceInfoBlock) {
    sliceInfoStyle.innerHTML = `
      #info_main > tbody > tr > td {
        background-color: ${theme?.blocksColor || ""};
        margin-bottom: 5px;
      }
    `;
    document.head.appendChild(sliceInfoStyle);
  } else {
    sliceInfoStyle.innerHTML = `
      #tr_info > td {
        background-color: ${theme?.blocksColor || ""};
      }
    `;
    document.head.appendChild(sliceInfoStyle);
  }

  const edgeTrimBlocksStyle = document.createElement("style");
  if (settings.edgeTrimBlocks) {
    edgeTrimBlocksStyle.innerHTML = // css
    `
    #info_main > tbody > tr > td {
      width: fit-content;
      border-radius: 10px;
      margin-bottom: 10px;
    }
    
    #info_main,
    #tos,
    #cages_overflow,
    #cages_div {
      border-radius: 10px;
    }
    
    #main_table > tbody > #tr_actions,
    #main_table > tbody > #tr_mouth,
    #main_table > tbody > #tr_chat,
    #main_table > tbody > #tr_tos,
    #main_table > tbody > #tr_info {
      margin: 0px 10px 10px 10px;
    }
    
    #tr_chat,
    #tr_actions > td,
    #tr_mouth > td,
    #location,
    .small,
    #tr_info > td {
      border-radius: 10px;
    }
    `;
    document.head.appendChild(edgeTrimBlocksStyle);
  }
  // ====================================================================================================================
  //  . . . КОМАНДЫ В БОЕВОМ РЕЖИМЕ . . .
  // ====================================================================================================================
  if (settings.fightTeams) {
    const colors = settings.fightTeamsColors;
  
    const fightPanel = document.getElementById("fightPanel");
    const buttonHTML =
      '<button id="updateTableButton" style="width: 100%;">Обновить команды</button>';
    fightPanel.insertAdjacentHTML("beforeend", buttonHTML);
  
    document.getElementById("updateTableButton").onclick = () => {
      if (!document.getElementById("uwu-team-settings")) {
        createTeamTable();
      }
      updateTeamTable();
    };
  
    function createTeamTable() {
      const tableHTML = // html
      `
        <div id="uwu-team-settings" style="height: ${
          settings.fightTeamsPanelHight || "auto"
        }px; overflow-y: scroll; resize: vertical;">
          <table id="uwu-team-settings-table" style="width: 100%; border-collapse: collapse;">
            <thead>
              <tr>
                <th style="border: 1px solid #000; padding: 5px;">Имя</th>
                <th style="border: 1px solid #000; padding: 5px;">Команда</th>
              </tr>
            </thead>
            <tbody id="teamTableBody"></tbody>
          </table>
        </div>
      `;
      const updateButton = document.getElementById("updateTableButton");
      updateButton.insertAdjacentHTML("beforebegin", tableHTML);
    }
  
    function updateTeamTable() {
      const tbody = document.getElementById("teamTableBody");
      tbody.innerHTML = "";
      const cages = document.querySelectorAll("#cages .cage");
  
      cages.forEach((cage) => {
        const catName = cage.querySelector(".cat_tooltip a")?.textContent;
        const arrow = cage.querySelector(".arrow.arrow-paws");
  
        if (catName && arrow) {
          const arrowId = arrow.id;
          const buttonsHTML = Object.keys(colors)
            .map((team) => {
              return `
                <button 
                  class="team-color-button"
                  data-arrow-id="${arrowId}"
                  data-team="${team}"
                  style="background-color: ${colors[team][0]}; width: 21%; height: 16px;"
                ></button>
              `;
            })
            .join("");
  
          const rowHTML = `
            <tr>
              <td style="border: 1px solid #000; padding: 5px;">${catName}</td>
              <td style="border: 1px solid #000; padding: 5px;">${buttonsHTML}</td>
            </tr>
          `;
          tbody.insertAdjacentHTML("beforeend", rowHTML);
        }
      });
  
      const teamColorButtons = document.querySelectorAll('.team-color-button');
      teamColorButtons.forEach(button => {
        button.addEventListener('click', () => {
          const arrowId = button.getAttribute('data-arrow-id');
          const team = button.getAttribute('data-team');
          applyTeamColors(arrowId, team);
        });
      });
    }
  
    function applyTeamColors(arrowId, team) {
      const styleElement = document.createElement('style');
      styleElement.type = 'text/css';
      const cssRule = `
        #${arrowId} .arrow_green { background-color: ${colors[team][0]} !important; }
        #${arrowId} .arrow_red { background-color: ${colors[team][1]} !important; }
      `;
      styleElement.appendChild(document.createTextNode(cssRule));
      document.head.appendChild(styleElement);
    }
  }
  // ====================================================================================================================
  //   . . . ПЕРЕТАСКИВАНИЕ ПАНЕЛИ БОЕВОГО РЕЖИМА . . .
  // ====================================================================================================================
  if (settings.draggingFightPanel) {
    const dragDiv = document.createElement("div");
    dragDiv.style.cursor = "move";
    dragDiv.style.display = "inline-block";

    const dragImage = document.createElement("img");
    dragImage.src =
      "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/drag-move.png";
    dragImage.style.width = "24px";
    dragImage.style.height = "24px";
    dragImage.style.pointerEvents = "none";
    dragDiv.appendChild(dragImage);

    const fightPanel = document.getElementById("fightPanel");
    const firstImage = fightPanel.querySelector("img");
    fightPanel.insertBefore(dragDiv, firstImage);

    let mouseX = 0;
    let mouseY = 0;
    let panelX = 0;
    let panelY = 0;
    let isDragging = false;

    function saveFightPanelPosition(x, y) {
      localStorage.setItem("uwu_fightPanelPosition", JSON.stringify({ x, y }));
    }

    function loadFightPanelPosition() {
      const savedPosition = localStorage.getItem("uwu_fightPanelPosition");
      if (savedPosition) {
        const position = JSON.parse(savedPosition);
        panelX = position.x;
        panelY = position.y;
      }
    }

    function setFightPanelPosition(x, y) {
      const windowWidth = window.innerWidth;
      const windowHeight = window.innerHeight;
      const panelWidth = fightPanel.offsetWidth;
      const panelHeight = fightPanel.offsetHeight;

      const maxX = windowWidth - panelWidth;
      x = Math.max(0, Math.min(x, maxX));

      const maxY = windowHeight - panelHeight;
      y = Math.max(0, Math.min(y, maxY));

      fightPanel.style.left = `${x}px`;
      fightPanel.style.top = `${y}px`;

      saveFightPanelPosition(x, y);
    }

    dragDiv.addEventListener("mousedown", (e) => {
      e.preventDefault();
      isDragging = true;
      mouseX = e.clientX;
      mouseY = e.clientY;

      loadFightPanelPosition();

      document.body.style.userSelect = "none";
    });

    document.addEventListener("mousemove", (e) => {
      if (isDragging) {
        e.preventDefault();

        const dx = e.clientX - mouseX;
        const dy = e.clientY - mouseY;

        setFightPanelPosition(panelX + dx, panelY + dy);
      }
    });

    document.addEventListener("mouseup", () => {
      isDragging = false;

      document.body.style.userSelect = "auto";
    });

    loadFightPanelPosition();
    setFightPanelPosition(panelX, panelY);
  }
  // ====================================================================================================================
  //   . . . СОКРАЩЕНИЕ ЛОГА БОЕВОГО РЕЖИМА . . .
  // ====================================================================================================================
  // емааааа ужасное решение
  // TODO - исправить переделать уничтожить пересобрать заамогусить чё за фигню я сделал
  if (settings.compactFightLog) {
    function compactFightLog() {
      const fightLog = document.getElementById("fightLog");
      fightLog.style.display = "none";

      let compactedFightLog = document.getElementById(
        "uwu-Compacted-Fight-Log"
      );
      if (!compactedFightLog) {
        compactedFightLog = document.createElement("div");
        compactedFightLog.id = "uwu-Compacted-Fight-Log";
        compactedFightLog.style.height = settings.fightPanelHeight + "px";
        fightLog.parentNode.insertBefore(compactedFightLog, fightLog);
      }

      const logEntries = Array.from(fightLog.childNodes).filter(
        (entry) => entry.tagName === "SPAN"
      );

      if (logEntries.length > 0) {
        const firstEntry = logEntries[0];
        const text = firstEntry.textContent.trim();
        const match = text.match(/^(.*) x(\d+)$/);
        const originalText = match ? match[1] : text;
        const count = match ? parseInt(match[2], 10) : 1;

        const latestEntry = compactedFightLog.firstElementChild;

        if (latestEntry) {
          const latestTextSpan = latestEntry.querySelector(".text");

          if (
            latestTextSpan &&
            latestTextSpan.textContent.trim() === originalText
          ) {
            const countLabel = latestEntry.querySelector(".count");
            const existingCount = parseInt(
              countLabel.textContent.match(/x(\d+)$/)[1],
              10
            );
            countLabel.textContent = ` x${existingCount + count}`;
          } else {
            const newEntryHTML = createEntryHTML(
              firstEntry.className,
              originalText,
              count
            );
            compactedFightLog.insertAdjacentHTML("afterbegin", newEntryHTML);
          }
        } else {
          const newEntryHTML = createEntryHTML(
            firstEntry.className,
            originalText,
            count
          );
          compactedFightLog.insertAdjacentHTML("afterbegin", newEntryHTML);
        }

        fightLog.removeChild(firstEntry);
      }
    }

    function createEntryHTML(className, originalText, count) {
      return `
        <div class="${className}">
          <span class="text">${originalText}</span>
          <label class="count"> x${count}</label>
        </div>
      `;
    }

    setupMutationObserver(
      "#fightLog",
      compactFightLog,
      {
        attributes: true,
        childList: true,
      },
      8,
      500,
      10
    );
  }
  // ====================================================================================================================
  //   . . . ИЗМЕНЯЕМАЯ ВЫСОТА ПАНЕЛИ БОЕВОГО РЕЖИМА . . .
  // ====================================================================================================================
  if (settings.FightPanelAdjustableHeight) {
    const uwuFightLog = document.createElement("style");
    uwuFightLog.innerHTML = `
      #fightPanel {
        height: auto;
      }

      #fightLog {
        resize: vertical;
        overflow-y: scroll;
      }
      
      #uwu-Compacted-Fight-Log {
        resize: vertical;
        overflow-y: scroll;
      } 
      `;
    document.head.appendChild(uwuFightLog);

    const fightLogElement = document.getElementById("fightLog");
    if (fightLogElement) {
        fightLogElement.style.height = `${settings.fightPanelHeight || 70}px`;
    }
}
  // ====================================================================================================================
  //   . . . ВСЕГДА ДЕНЬ В ИГРОВОЙ . . .
  // ====================================================================================================================
  // Вот бы всё писалось так кратко и легко...........
  function updateAlwaysDayStyle(checked) {
    const alwaysDayStyle = `
      #cages_div {
        opacity: 1 !important;
      }   
    `;

    const styles = document.head.querySelectorAll("style");
    let styleFound = false;

    styles.forEach((style) => {
      if (style.innerHTML === alwaysDayStyle) {
        if (!checked) {
          document.head.removeChild(style);
        }
        styleFound = true;
      }
    });

    if (checked && !styleFound) {
      const alwaysDay = document.createElement("style");
      alwaysDay.innerHTML = alwaysDayStyle;
      document.head.appendChild(alwaysDay);
    }
  }
  // ====================================================================================================================
  //   . . . НЕБО - ШАПКА . . .
  // ====================================================================================================================
  if (settings.skyInHeader) {
    function getSkyUrl() {
      const skyElement = document.querySelector("#sky");
      if (skyElement) {
        const skyStyle = skyElement.getAttribute("style");
        const match = skyStyle.match(/url\((.*?)\)/);
        if (match) {
          return match[1].trim();
        } else {
          console.log("Не удалось найти URL изображения неба");
        }
      }
      return "";
    }

    const skyDiv = document.createElement("div");
    skyDiv.id = "skyDuplicate";

    const globalContainerElement = document.getElementById(
      "uwu-global-container"
    );
    globalContainerElement.appendChild(skyDiv);

    const skyStyle = document.createElement("style");
    skyStyle.innerHTML = `
      #skyDuplicate {
        height: 15%;
        width: 100%;
        mask-image: linear-gradient(to bottom, 
          rgba(0, 0, 0, 1), 
          rgba(0, 0, 0, 0.40) 50%,
          rgba(0, 0, 0, 0)
        );
        top: 0;
        left: 0;
        z-index: -1;
        position: absolute;
        background-size: cover;
      }
    `;
    document.head.appendChild(skyStyle);

    const originalSkyStyle = document.createElement("style");
    originalSkyStyle.innerHTML = `
      #tr_sky {
        display: none;
      }
    `;
    document.head.appendChild(originalSkyStyle);

    function updateSkyImage() {
      const skyUrl = getSkyUrl();
      if (skyUrl) {
        skyDiv.style.backgroundImage = `url(${skyUrl})`;
      }
    }

    updateSkyImage();

    setupMutationObserver(
      "#sky",
      updateSkyImage,
      { attributes: true, attributeFilter: ["style"] },
      8,
      500,
      10
    );
  }
  // ====================================================================================================================
  //   . . . ОПРЕДЕЛЕНИЕ ПОГОДЫ В ИГРОВОЙ . . . 🛠️
  // ====================================================================================================================
  let currentWeather = "null";
  let currentHour = "null";
  let currentSeason = "null";
  let currentTemperature = "null";
  let temperatureDescription = "null";
  // ахахаха глянье на этих незнающих
  let weatherModifier = 1;

  if (settings.manualWeatherPanel) {
    const manualWeatherSlider = document.getElementById("manualWeather");

    manualWeatherSlider.addEventListener("change", () => {
      const selectedWeather = manualWeatherSlider.value;

      if (selectedWeather === "1") {
        currentWeather = "clear";
      } else if (selectedWeather === "2") {
        if (settings.minecraftStyle) {
          currentWeather = "pixelRain";
        } else {
          currentWeather = "rain";
        }
      } else if (selectedWeather === "3") {
        if (settings.minecraftStyle) {
          currentWeather = "pixelSnow";
        } else {
          currentWeather = "snow";
        }
      }
    });
  }

  function getSkyType() {
    const skyElement = document.querySelector("#sky");
    const skyStyle = skyElement.getAttribute("style");

    if (settings.weatherEnabled) {
      const match = skyStyle.match(/\/(\d+)\.png/);
      if (match) {
        const skyNumber = parseInt(match[1]);

        switch (skyNumber) {
          case 2:
          case 4:
            if (settings.minecraftStyle) {
              currentWeather = "pixelRain";
            } else {
              currentWeather = "rain";
            }
            break;
          case 7:
          case 8:
            if (settings.minecraftStyle) {
              currentWeather = "pixelSnow";
            } else {
              currentWeather = "snow";
            }
            break;
          case 22:
            currentWeather = "northernLights";
            break;
          default:
            currentWeather = "clear";
        }
      } else {
        console.log("Потерял небо, небо найдись пж...");
        currentWeather = "unknown";
      }
    }
  }

  function getTime() {
    const timeElement = document.querySelector("#hour");
    const hourTime = timeElement.querySelector("img").getAttribute("src");

    if (settings.weatherEnabled) {
      const hourNumber = parseInt(hourTime.match(/(\d+)\.png$/)[1]);

      if (hourNumber >= 6 && hourNumber <= 12) {
        currentHour = "morning";
      } else if (hourNumber >= 13 && hourNumber <= 18) {
        currentHour = "day";
      } else if (hourNumber >= 19 && hourNumber <= 21) {
        currentHour = "evening";
      } else {
        currentHour = "night";
      }
      // console.log("Текущий час:", hourNumber);
    }
  }

  function getSeason() {
    const seasonElement = document.querySelector("img[src*='symbole/season']");
    const seasonSrc = seasonElement.getAttribute("src");
    const match = seasonSrc.match(/season(\d+)\.png/);

    if (match) {
      const seasonNumber = parseInt(match[1]);
      switch (seasonNumber) {
        case 0:
          currentSeason = "winter";
          break;
        case 1:
          currentSeason = "spring";
          break;
        case 2:
          currentSeason = "summer";
          break;
        case 3:
          currentSeason = "autumn";
          break;
      }
      // console.log("Текущий сезон:", currentSeason);
    }
  }

  function getTemperature() {
    const temperatureElement = document.querySelector("#tos");
    const temperatureElementHTML = temperatureElement.outerHTML;
    const backgroundValue = /background:\s*([a-zA-Z0-9#()]+);/.exec(
      temperatureElementHTML
    );

    if (backgroundValue && backgroundValue.length > 1) {
      const foundBackground = backgroundValue[1];

      const temperatureRanges = [
        {
          description: "Очень холодно",
          temperature: -3,
          colors: [
            "#94BDD2",
            "#9DC5D8",
            "#B2D8E5",
            "#C3E8EF",
            "#AED4E2",
            "#AAD1E0",
            "#A5CDDD",
          ],
        },
        {
          description: "Холодно",
          temperature: -2,
          colors: [
            "#7FAAC5",
            "#76A2C0",
            "#6A96B8",
            "#6593B6",
            "#618FB3",
            "#7BA6C3",
          ],
        },
        {
          description: "Прохладно",
          temperature: -1,
          colors: [
            "#3B6C9B",
            "#4C7BA6",
            "#5887AE",
            "#5D8BB0",
            "#4777A3",
            "#366899",
            "#3F709E",
            "#4374A1",
            "#5483AB",
          ],
        },
        {
          description: "Тепло",
          temperature: 1,
          colors: ["#FCBD8E", "#F8A37A", "#F79E77", "#FDC291", "#FCB88A"],
        },
        {
          description: "Жарковато",
          temperature: 2,
          colors: [
            "#F79973",
            "#F6946F",
            "#F58F6B",
            "#F28060",
            "#F38563",
            "#F17A5C",
            "#EF6B50",
            "#F07054",
          ],
        },
        {
          description: "Жарко",
          temperature: 3,
          colors: [
            "#EE664D",
            "#ED6149",
            "#EB5741",
            "#EB523D",
            "#E73D2E",
            "#E6382A",
          ],
        },
        {
          description: "Засуха",
          temperature: 4,
          colors: ["#DF0A08", "#E3241B", "#E4291F", "#E52E22", "#E63326"],
        },
      ];

      let foundTemperature = null;

      for (const range of temperatureRanges) {
        if (range.colors.includes(foundBackground)) {
          foundTemperature = range;
          break;
        }
      }

      if (foundTemperature) {
        currentTemperature = foundTemperature.temperature;
        temperatureDescription = foundTemperature.description;
      } else {
        currentTemperature = 1;
        temperatureDescription =
          "Неизвестная температура. Разработчик скорее всего уже в курсе и в скором времени выпустит правку.";
        console.warn("Неизвестная температура:", foundBackground);
      }

      switch (currentTemperature) {
        case 1:
        case -1:
          weatherModifier = 2;
          break;
        case 2:
        case -2:
          weatherModifier = 1.5;
          break;
        case 3:
        case -3:
          weatherModifier = 1;
          break;
        default:
          weatherModifier = 1;
      }

      // console.log("Температура:", currentTemperature);

      const temperatureDisplayElement = document.getElementById("temperature");
      if (temperatureDisplayElement) {
        temperatureDisplayElement.innerHTML = `[?] Текущий модификатор: ${weatherModifier} (${temperatureDescription})`;
      }
    } else {
      console.log("...я временно потерял бекграунд температуры🌡️...");
    }
  }
  // ====================================================================================================================
  if (!settings.manualWeatherPanel) {
    setupMutationObserver("#sky", getSkyType);

    setupMutationObserver("#hour", getTime, {
      attributes: true,
      attributeFilter: ["src"],
      subtree: true,
    });

    setupMutationObserver("img[src*='symbole/season']", getSeason, {
      attributes: true,
      attributeFilter: ["src"],
    });
  }

  setupMutationObserver("#tos", getTemperature, {
    attributes: true,
    subtree: true,
  });
  // ====================================================================================================================
  //   . . . ПОДГОТОВКА КОНТЕЙНЕРОВ / ИЗОБРАЖЕНИЙ . . . 🖼️
  // ====================================================================================================================
  const weatherContainer = document.getElementById("uwu-main-container");
  const weatherCanvas = document.createElement("canvas");
  weatherCanvas.classList.add("weatherCanvas");
  weatherContainer.appendChild(weatherCanvas);
  const weatherCtx = weatherCanvas.getContext("2d");

  function resizeCanvasElement() {
    weatherCanvas.width = weatherCanvas.parentNode.offsetWidth;
    weatherCanvas.height = weatherCanvas.parentNode.offsetHeight;
  }

  window.addEventListener("resize", resizeCanvasElement);
  resizeCanvasElement();

  const images = {
    pixelSnow: [
      {
        url: "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/snowflake1.png",
      },
      {
        url: "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/snowflake2.png",
      },
    ],
    pixelRain: [
      {
        url: "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/rain1.png",
      },
      {
        url: "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/rain2.png",
      },
    ],
    pixelSplash: [
      {
        url: "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/splash_0.png",
      },
      {
        url: "https://raw.githubusercontent.com/Ibirtem/CatWar/main/images/splash_1.png",
      },
    ],
    sus: [
      {
        url: "https://firebasestorage.googleapis.com/v0/b/xwx-823ac.appspot.com/o/images%2Ftiny-red-among-us.png?alt=media&token=354b34c6-6297-4a4d-8a73-f36a903170c0",
      },
    ],
  };

  async function loadImages(type) {
    const imagesForType = images[type];
    if (!imagesForType) {
      console.error(`Чё ета...?: ${type}`);
      return;
    }

    const promises = [];

    for (const image of imagesForType) {
      promises.push(
        new Promise((resolve, reject) => {
          const img = new Image();
          img.src = image.url;
          img.onload = function () {
            image.image = this;
            resolve();
          };
          img.onerror = function () {
            console.error(`Чёта не скачалось: ${image.url}`);
            reject();
          };
        })
      );
    }

    await Promise.all(promises);
  }
  loadImages("pixelSnow");
  loadImages("pixelRain");
  loadImages("pixelSplash");
  loadImages("sus");

  const { raindrops } = generateRain();
  const { snowflakes } = generateSnowflakes();
  const { pixelRaindrops } = generatePixelRain();
  const { pixelSnowflakes } = generatePixelSnow();

  // ====================================================================================================================
  //   . . . РЕЖИМ НИЗКОЙ ПРОИЗВОДИТЕЛЬНОСТИ . . .
  // ====================================================================================================================
  // Может быть уже даже готовка к динамичному количеству частиц.
  var rainNumParticles = 10;
  var snowTimerValue = 120;
  var desiredNumberOfFireflies = 10;

  function setWeatherPerformanceMode() {
    rainNumParticles = settings.lowPerformanceMode ? 4 : 10;
    snowTimerValue = settings.lowPerformanceMode ? 240 : 120;
    desiredNumberOfFireflies = settings.lowPerformanceMode ? 6 : 10;

    return { rainNumParticles, snowTimerValue, desiredNumberOfFireflies };
  }

  setWeatherPerformanceMode();
  // ====================================================================================================================
  //   . . . ДОЖДЬ . . . 🌧️
  // ====================================================================================================================
  function generateRain() {
    const raindrops = [];

    setInterval(() => {
      if (currentWeather === "rain") {
        for (let i = 0; i < rainNumParticles; i++) {
          const raindrop = generateRaindrop();
          if (raindrop) {
            raindrops.push(raindrop);
          }
        }
      }
    }, 80);

    function generateRaindrop() {
      if (document.hidden) {
        return;
      }
      const x = Math.random() * weatherCanvas.width;
      const y = Math.random() * -100;
      const length = (Math.random() * 20 + 40) / weatherModifier;
      const width = (Math.random() * 1 + 1) / weatherModifier;
      const ySpeed = length * 0.2 * weatherModifier;
      const xSpeed = Math.random() * 1;

      return { x, y, length, width, ySpeed, xSpeed };
    }

    return { raindrops };
  }

  function drawRaindrop(raindrop) {
    weatherCtx.beginPath();
    weatherCtx.ellipse(
      raindrop.x,
      raindrop.y,
      raindrop.width,
      raindrop.length,
      0,
      Math.PI,
      2 * Math.PI
    );
    weatherCtx.fillStyle = "rgba(150, 150, 150, 0.4)";
    weatherCtx.fill();
  }
  // ====================================================================================================================
  //   . . . СНЕГ . . . 🌨️
  // ====================================================================================================================
  function generateSnowflakes() {
    const snowflakes = [];
    const snowTimerValue = setWeatherPerformanceMode().snowTimerValue;

    setInterval(() => {
      if (currentWeather === "snow") {
        for (let i = 0; i < 1; i++) {
          const snowflake = generateSnowflake();
          if (snowflake) {
            snowflakes.push(snowflake);
          }
        }
      }
    }, snowTimerValue);

    function generateSnowflake() {
      if (document.hidden) {
        return;
      }
      const y = Math.random() * -100;
      const x = Math.random() * weatherCanvas.width;
      const size = (Math.random() * 5 + 2) / weatherModifier;
      const ySpeed = size * 0.1 * weatherModifier;
      const xSpeed = (Math.random() - Math.random()) * 0.2;
      const opacity = 1;

      return { x, y, size, ySpeed, xSpeed, opacity };
    }

    return { snowflakes };
  }

  function drawSnowflake(x, y, size) {
    weatherCtx.beginPath();
    weatherCtx.ellipse(x, y, size, size, 0, 0, 2 * Math.PI);
    weatherCtx.fillStyle = "white";
    weatherCtx.fill();
  }
  // ====================================================================================================================
  //   . . . ПИКСЕЛЬНЫЙ ДОЖДЬ . . . 🌧️
  // ====================================================================================================================
  function generatePixelRain() {
    const pixelRaindrops = [];

    setInterval(() => {
      if (currentWeather === "pixelRain") {
        for (let i = 0; i < rainNumParticles; i++) {
          const pixelRaindrop = generatePixelRaindrop();
          if (pixelRaindrop) {
            pixelRaindrops.push(pixelRaindrop);
          }
        }
      }
    }, 80);

    function generatePixelRaindrop() {
      if (document.hidden) {
        return;
      }
      const x = Math.random() * weatherCanvas.width;
      const y = Math.random() * -100;
      const size = (Math.random() * 26 + 26) / Math.pow(weatherModifier, 0.5);
      const ySpeed = size * 0.2 * Math.pow(weatherModifier, 0.5);
      const xSpeed = Math.random() * 0.2 - 0.1;
      const imageData =
        images.pixelRain[Math.floor(Math.random() * images.pixelRain.length)];
      const image = imageData.image;

      return { x, y, size, ySpeed, xSpeed, image };
    }

    return { pixelRaindrops };
  }

  function drawPixelRaindrop(pixelRaindrop) {
    const imageWidth = pixelRaindrop.image.width;
    const imageHeight = pixelRaindrop.image.height;
    const scaleFactor = pixelRaindrop.size / Math.max(imageWidth, imageHeight);

    weatherCtx.drawImage(
      pixelRaindrop.image,
      pixelRaindrop.x,
      pixelRaindrop.y,
      imageWidth * scaleFactor,
      imageHeight * scaleFactor
    );
  }
  // ====================================================================================================================
  //   . . . ПИКСЕЛЬНЫЙ СНЕГ . . . 🌨️
  // ====================================================================================================================
  function generatePixelSnow() {
    const pixelSnowflakes = [];
    const snowTimerValue = setWeatherPerformanceMode().snowTimerValue;

    setInterval(() => {
      if (currentWeather === "pixelSnow") {
        for (let i = 0; i < 1; i++) {
          const pixelSnowflake = generatePixelSnowflake();
          if (pixelSnowflake) {
            pixelSnowflakes.push(pixelSnowflake);
          }
        }
      }
    }, snowTimerValue);

    function generatePixelSnowflake() {
      if (document.hidden) {
        return;
      }
      const y = Math.random() * -100;
      const x = Math.random() * weatherCanvas.width;
      const size = (Math.random() * 8 + 8) / Math.pow(weatherModifier, 0.8); // TODO - Протестить, сильно ли влияет Math.pow на производительность или нет
      const ySpeed = size * 0.1 * Math.pow(weatherModifier, 0.8) - 0.6;
      const xSpeed = (Math.random() - Math.random()) * 0.2;
      const imageData =
        images.pixelSnow[Math.floor(Math.random() * images.pixelSnow.length)];
      const image = imageData.image;
      const opacity = 1;

      return { x, y, size, ySpeed, xSpeed, image, opacity };
    }

    return { pixelSnowflakes };
  }

  function drawPixelSnowflake(x, y, size, image) {
    weatherCtx.drawImage(image, x - size / 2, y - size / 2, size, size);
  }
  // ====================================================================================================================
  //   . . . АНИМАЦИЯ ПОГОДЫ / ЧАСТИЦ . . .
  // ====================================================================================================================
  function animateWeather() {
    weatherCtx.clearRect(0, 0, weatherCanvas.width, weatherCanvas.height);

    if (raindrops.length > 0) {
      for (const raindrop of raindrops) {
        raindrop.y += raindrop.ySpeed;
        raindrop.x += raindrop.xSpeed;
        drawRaindrop(raindrop);
      }
    }

    if (snowflakes.length > 0) {
      for (const snowflake of snowflakes) {
        snowflake.y += snowflake.ySpeed;
        snowflake.x += snowflake.xSpeed;
        drawSnowflake(snowflake.x, snowflake.y, snowflake.size);
      }
    }

    if (pixelSnowflakes.length > 0) {
      for (const pixelSnowflake of pixelSnowflakes) {
        pixelSnowflake.y += pixelSnowflake.ySpeed;
        pixelSnowflake.x += pixelSnowflake.xSpeed;
        drawPixelSnowflake(
          pixelSnowflake.x,
          pixelSnowflake.y,
          pixelSnowflake.size,
          pixelSnowflake.image
        );
      }
    }

    if (pixelRaindrops.length > 0) {
      for (const pixelRaindrop of pixelRaindrops) {
        pixelRaindrop.y += pixelRaindrop.ySpeed;
        pixelRaindrop.x += pixelRaindrop.xSpeed;
        drawPixelRaindrop(pixelRaindrop);
      }
    }

    requestAnimationFrame(animateWeather);
  }
  if (settings.weatherEnabled || settings.manualWeatherPanel) {
    animateWeather();
  }
  // ====================================================================================================================
  //   . . . СЕВЕРНОЕ СИЯНИЕ . . . 🌟
  // ====================================================================================================================
  const auroraColors = {
    green: {
      1: "#aaff9d",
      2: "#00faa0",
      3: "#00ff62",
    },
    blue: {
      1: "#9DF5ED",
      2: "#82BBF5",
      3: "#725DFA",
    },
  };
  const auroras = [];

  function removeAurora(auroraElement) {
    auroraElement.style.animation = "auroraFadeOut 6s ease-in-out";

    setTimeout(() => {
      weatherContainer.removeChild(auroraElement);
      const index = auroras.indexOf(auroraElement);
      if (index > -1) {
        auroras.splice(index, 1);
      }
    }, 6000);
  }

  function createAurora(color) {
    for (const auroraElement of auroras) {
      removeAurora(auroraElement);
    }

    const newAurora = document.createElement("div");

    newAurora.style.cssText = `
    transform: translate(0, 60%);
    z-index: -1;
    position: fixed;
    left: 0;
    width: 100%;
    height: 30%;
    filter: blur(4rem);
    animation: aurora-spin 15s linear infinite, auroraFadeIn 6s ease-in-out;
    background: conic-gradient(from var(--gradient-angle),
    ${auroraColors[color][1]},
    ${auroraColors[color][2]},
    ${auroraColors[color][3]},
    ${auroraColors[color][2]},
    ${auroraColors[color][1]});
    `;

    if (settings.auroraPos === "1") {
      newAurora.style.top = "-30%";
    } else if (settings.auroraPos === "2") {
      newAurora.style.bottom = "0";
    }

    weatherContainer.appendChild(newAurora);
    auroras.push(newAurora);
  }

  function toggleAurora() {
      if (settings.manualWeatherPanel) return;

      const isAuroraConditionMet = 
          currentWeather === "northernLights" || 
          (currentWeather === "clear" && 
          currentHour === "night" && 
          (currentSeason === "autumn" || currentSeason === "winter"));

      if (isAuroraConditionMet) {
          if (auroras.length === 0) {
              const auroraColor = Math.random() > 0.5 ? "green" : "blue";
              createAurora(auroraColor);
          }
      } else {
          auroras.forEach(removeAurora);
      }
  }

  setInterval(() => {
    toggleAurora();
    if (!settings.manualWeatherPanel) {
      generateFirefliesNaturally();
    }
  }, 2000);
  // ====================================================================================================================
  //   . . . СВЕТЛЯЧКИ . . . 🪲
  // ====================================================================================================================
  const fireflies = [];
  const glowSizeMultiplier = 12;

  function generateFirefly() {
    const x = Math.random() * weatherCanvas.width;
    const y = Math.random() * weatherCanvas.height;
    const size = Math.random() * 5 + 10;
    const xSpeed = (Math.random() - 0.5) * 0.5;
    const ySpeed = (Math.random() - 0.5) * 0.5;

    const firefly = document.createElement("div");
    firefly.className = "firefly";
    firefly.style.left = x + "px";
    firefly.style.top = y + "px";
    firefly.style.width = size + "px";
    firefly.style.height = size + "px";

    const glow = document.createElement("div");
    glow.className = "firefly-glow";
    glow.style.left = x + "px";
    glow.style.top = y + "px";
    glow.style.width = size * glowSizeMultiplier + "px";
    glow.style.height = size * glowSizeMultiplier + "px";

    return { element: firefly, glowElement: glow, x, y, size, xSpeed, ySpeed };
  }

  function createNewFirefliesIfNeeded() {
    const missingFireflies = desiredNumberOfFireflies - fireflies.length;

    for (let i = 0; i < missingFireflies; i++) {
      const newFirefly = generateFirefly();
      fireflies.push(newFirefly);
      weatherContainer.appendChild(newFirefly.element);
      weatherContainer.appendChild(newFirefly.glowElement);
    }
  }

  function removeFireflies() {
    for (const firefly of fireflies) {
      weatherContainer.removeChild(firefly.element);
      weatherContainer.removeChild(firefly.glowElement);
    }
    fireflies.length = 0;
  }

  function toggleFireflies() {
    if (settings.manualWeatherPanel) {
      if (fireflies.length === 0) {
        for (let i = 0; i < desiredNumberOfFireflies; i++) {
          fireflies.push(generateFirefly());
          weatherContainer.appendChild(fireflies[i].element);
          weatherContainer.appendChild(fireflies[i].glowElement);
        }
      } else {
        for (const firefly of fireflies) {
          firefly.element.classList.add("firefly-disappearing");
          firefly.glowElement.classList.add("firefly-disappearing");
        }
        setTimeout(() => {
          removeFireflies();
        }, 6000);
      }
    }
  }

  function generateFirefliesNaturally() {
    if (
      currentWeather === "clear" &&
      currentHour === "night" &&
      currentSeason === "summer"
    ) {
      if (fireflies.length === 0) {
        for (let i = 0; i < desiredNumberOfFireflies; i++) {
          fireflies.push(generateFirefly());
          weatherContainer.appendChild(fireflies[i].element);
          weatherContainer.appendChild(fireflies[i].glowElement);
        }
      }
    } else {
      for (const firefly of fireflies) {
        firefly.element.classList.add("firefly-disappearing");
        firefly.glowElement.classList.add("firefly-disappearing");
      }
      setTimeout(() => {
        removeFireflies();
      }, 6000);
    }
  }

  function animateFireflies() {
    for (let i = fireflies.length - 1; i >= 0; i--) {
      const firefly = fireflies[i];
      firefly.x += firefly.xSpeed;
      firefly.y += firefly.ySpeed;

      if (firefly.x < 0 || firefly.x + firefly.size > weatherCanvas.width) {
        firefly.xSpeed *= -1;
      }
      if (firefly.y < 0 || firefly.y + firefly.size > weatherCanvas.height) {
        firefly.ySpeed *= -1;
      }

      firefly.element.style.left = firefly.x + "px";
      firefly.element.style.top = firefly.y + "px";

      firefly.glowElement.style.left =
        firefly.x - (firefly.size * glowSizeMultiplier) / 2 + "px";
      firefly.glowElement.style.top =
        firefly.y - (firefly.size * glowSizeMultiplier) / 2 + "px";

      createNewFirefliesIfNeeded();
    }

    requestAnimationFrame(animateFireflies);
  }

  if (settings.weatherEnabled || settings.manualWeatherPanel) {
    animateFireflies();
  }
  // ====================================================================================================================
  //   . . . ПРИЗЕМЛЕНИЕ ЧАСТИЦ . . . ☔
  // ====================================================================================================================
  const landedSnowflakes = [];
  const landedPixelSnowflakes = [];
  const splashes = [];
  const pixelSplashes = [];

  switch (true) {
    case settings.manualWeatherPanel && !settings.weatherDrops:
    case settings.weatherEnabled && !settings.weatherDrops:
      setInterval(() => {
        checkElements(raindrops, weatherContainer);
        checkElements(snowflakes, weatherContainer);
        checkElements(pixelSnowflakes, weatherContainer);
        checkElements(pixelRaindrops, weatherContainer);
      }, 120);
      break;

    case settings.manualWeatherPanel && settings.weatherDrops:
    case settings.weatherEnabled && settings.weatherDrops:
      animateLanding();
      break;

    default:
      break;
  }

  function checkElements(elements, container) {
    for (let i = elements.length - 1; i >= 0; i--) {
      const element = elements[i];

      if (
        element &&
        (element.y >= container.offsetHeight ||
          element.x >= container.offsetWidth ||
          element.x <= 0)
      ) {
        elements.splice(i, 1);
      }
    }
    // console.log(`Количество элементов: ${elements.length}`)
  }

  function animateLanding() {
    for (let i = snowflakes.length - 1; i >= 0; i--) {
      const snowflake = snowflakes[i];
      if (snowflake.y >= weatherCanvas.height - snowflake.size) {
        snowflakes.splice(i, 1);
        landedSnowflakes.push(snowflake);
      }
    }
    for (let i = pixelSnowflakes.length - 1; i >= 0; i--) {
      const pixelSnowflake = pixelSnowflakes[i];
      if (pixelSnowflake.y >= weatherCanvas.height - pixelSnowflake.size) {
        pixelSnowflakes.splice(i, 1);
        landedPixelSnowflakes.push(pixelSnowflake);
      }
    }
    for (let i = landedSnowflakes.length - 1; i >= 0; i--) {
      const snowflake = landedSnowflakes[i];
      snowflake.opacity -= 0.001;
      if (snowflake.opacity <= 0) {
        landedSnowflakes.splice(i, 1);
      }
    }
    for (const snowflake of landedSnowflakes) {
      weatherCtx.globalAlpha = snowflake.opacity;
      drawSnowflake(snowflake.x, snowflake.y, snowflake.size);
    }

    for (let i = landedPixelSnowflakes.length - 1; i >= 0; i--) {
      const pixelSnowflake = landedPixelSnowflakes[i];
      pixelSnowflake.opacity -= 0.001;

      if (pixelSnowflake.opacity <= 0) {
        landedPixelSnowflakes.splice(i, 1);
      }
    }
    for (const pixelSnowflake of landedPixelSnowflakes) {
      weatherCtx.globalAlpha = pixelSnowflake.opacity;
      drawPixelSnowflake(
        pixelSnowflake.x,
        pixelSnowflake.y,
        pixelSnowflake.size,
        pixelSnowflake.image
      );
    }

    for (let i = raindrops.length - 1; i >= 0; i--) {
      const raindrop = raindrops[i];
      if (raindrop.y >= weatherCanvas.height - raindrop.length) {
        raindrops.splice(i, 1);
        splashes.push(generateSplash(raindrop.x, weatherCanvas.height));
      }
    }

    for (let i = pixelRaindrops.length - 1; i >= 0; i--) {
      const pixelRaindrop = pixelRaindrops[i];
      if (pixelRaindrop.y >= weatherCanvas.height - pixelRaindrop.size) {
        pixelRaindrops.splice(i, 1);
        pixelSplashes.push(
          generateSplash(pixelRaindrop.x, weatherCanvas.height - 24)
        );
      }
    }

    for (const splash of splashes) {
      splash.x += splash.xSpeed;
      splash.y += splash.ySpeed;
      splash.ySpeed += 0.1;

      weatherCtx.beginPath();
      weatherCtx.arc(
        splash.x,
        splash.y,
        splash.size / 1.2 / weatherModifier,
        0,
        Math.PI * 2
      );
      weatherCtx.fillStyle = "rgba(150, 150, 150, 0.4)";
      weatherCtx.fill();
    }

    for (const pixelSplash of pixelSplashes) {
      pixelSplash.x += pixelSplash.xSpeed;
      pixelSplash.y += pixelSplash.ySpeed;
      pixelSplash.ySpeed += 0.1;
      weatherCtx.drawImage(
        pixelSplash.image,
        pixelSplash.x,
        pixelSplash.y,
        pixelSplash.size * weatherModifier * 2,
        pixelSplash.size * weatherModifier * 2
      );
    }

    checkSplashes();
    checkPixelSplashes();
    weatherCtx.globalAlpha = 1;
    requestAnimationFrame(animateLanding);
  }

  function generateSplash(x, y) {
    const size = Math.random() * 5 + 2;
    const xSpeed = (Math.random() - 0.5) * 2;
    const ySpeed = -Math.random() * 2 - 1;
    const imageData =
      images.pixelSplash[Math.floor(Math.random() * images.pixelSplash.length)];
    const image = imageData.image;

    return { x, y, size, xSpeed, ySpeed, image };
  }

  function checkSplashes() {
    for (let i = splashes.length - 1; i >= 0; i--) {
      const splash = splashes[i];
      if (
        splash.y >= weatherCanvas.height ||
        splash.x >= weatherCanvas.width ||
        splash.x <= 0
      ) {
        splashes.splice(i, 1);
      }
    }
    // console.log(`Количество сплешев: ${splashes.length}`)
  }
  function checkPixelSplashes() {
    for (let i = pixelSplashes.length - 1; i >= 0; i--) {
      const pixelSplash = pixelSplashes[i];
      if (
        pixelSplash.y >= weatherCanvas.height ||
        pixelSplash.x >= weatherCanvas.width ||
        pixelSplash.x <= 0
      ) {
        pixelSplashes.splice(i, 1);
      }
    }
  }
// ====================================================================================================================
} // Конец грандиозного, но и начало чево то нового... Зогдачно......
// ====================================================================================================================
// 🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨🦐✨
// ====================================================================================================================
//   . . . ТАРГЕТИНГ ОКНА ОХОТЫ И ПОДГОТОВКА КОНТЕЙНЕРОВ . . .
// ====================================================================================================================
if (window.location.href === targetCW3Hunt) {
  amogusSus();
  const containerElement = document.querySelector("body");
  const globalContainerElement = document.createElement("div");
  globalContainerElement.id = "uwu-main-container";
  containerElement.appendChild(globalContainerElement);
  // ====================================================================================================================
  //   . . . ПОДПИСЫВАТЬ ЗАПАХ . . .
  // ====================================================================================================================
  if (settings.describeHuntingSmell) {
    const smellElement = document.getElementById("smell");
    let smellText = null;
    let smellTimer = null;
    let previousRed = null;
    let seconds = 0;

    function updateHintText(currentRed) {
      if (currentRed === 0) {
        smellText.textContent = "Потерян";
      } else if (previousRed !== null) {
        if (currentRed > previousRed) {
          smellText.textContent = "Ближе";
        } else if (currentRed < previousRed) {
          smellText.textContent = "Дальше";
        }
      } else {
        smellText.textContent = " ";
      }
      previousRed = currentRed;
    }

    function updateTimer() {
      const minutes = Math.floor(seconds / 60);
      const remainingSeconds = seconds % 60;
      smellTimer.textContent = `${String(minutes).padStart(2, "0")}:${String(
        remainingSeconds
      ).padStart(2, "0")}`;
      seconds++;
    }

    function handleSmellChange() {
      const style = window.getComputedStyle(smellElement);
      const currentColor = style.backgroundColor;

      if (
        currentColor !== "rgba(0, 0, 0, 0)" &&
        currentColor !== "transparent"
      ) {
        if (!smellText) {
          smellText = document.createElement("div");
          smellText.id = "smellText";
          smellTimer = document.createElement("div");
          smellTimer.id = "smellTimer";
          document.body.appendChild(smellText);
          document.body.appendChild(smellTimer);

          intervalId = setInterval(updateTimer, 1000);
        }

        const currentRed = parseInt(
          currentColor.slice(
            currentColor.indexOf("(") + 1,
            currentColor.indexOf(",")
          )
        );
        updateHintText(currentRed);
      }
    }

    new MutationObserver(handleSmellChange).observe(smellElement, {
      attributes: true,
      attributeFilter: ["style"],
    });

    const describeHuntingSmell = document.createElement("style");
    describeHuntingSmell.innerHTML = `
  #smellText {
    font-size: 20px;
    background: white;
    color: black;
    text-align: center;
    width: 100px;
    position: absolute;
    z-index: 3;
    bottom: 60px;
  }
  
  #smellTimer {
    font-size: 18px;
    background: white;
    color: black;
    text-align: center;
    width: 100px;
    position: absolute;
    z-index: 3;
    bottom: 40px; 
  }
  `;
    document.head.appendChild(describeHuntingSmell);
  }
  // ====================================================================================================================
  //   . . . ВИРТУАЛЬНЫЙ ДЖОЙСТИК . . .
  // ====================================================================================================================
  // Работаем с сайтовым обработчиком нажатий: "//e.catwar.net/js/key.js?268881668"
  if (settings.huntingVirtualJoystick) {
    function createJoystick() {
      const joystickHTML = `
        <div id="joystick-container">
          <div id="joystick-base">
            <div id="joystick-head"></div>
          </div>
        </div>
      `;

      const uwuContainer = document.getElementById("uwu-main-container");
      uwuContainer.insertAdjacentHTML("beforeend", joystickHTML);

      const css = // css
      `
        #nav_buttons_wrapper {
          display: none;
        }
  
        #joystick-container {
          pointer-events: auto;
          position: fixed;
          bottom: 20px;
          right: 20px;
          width: ${settings.sizeHuntingVirtualJoystick}px; 
          height: ${settings.sizeHuntingVirtualJoystick}px;
          z-index: 10; 
        }
  
        #joystick-base {
          width: 100%;
          height: 100%;
          border-radius: 50%;
          background-color: rgba(128, 128, 128, 0.5);
          position: relative;
        }
  
        #joystick-head {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          width: ${settings.sizeHuntingVirtualJoystick / 2}px;
          height: ${settings.sizeHuntingVirtualJoystick / 2}px;
          border-radius: 50%;
          background-color: #808080;
          touch-action: none; 
        }
      `;
      const style = document.createElement("style");
      style.innerHTML = css;
      document.head.appendChild(style);

      const joystickContainer = document.getElementById("joystick-container");
      const joystickHead = document.getElementById("joystick-head");
      const baseRadius = joystickContainer.offsetWidth / 2;
      let activeTouchId = null;
      let keys = {};

      function handleTouchStart(event) {
        if (activeTouchId === null) {
          const touch = event.touches[0];
          activeTouchId = touch.identifier;
          updateJoystickPosition(touch.clientX, touch.clientY);
        }
      }

      function handleTouchMove(event) {
        event.preventDefault();
        for (let i = 0; i < event.touches.length; i++) {
          const touch = event.touches[i];
          if (touch.identifier === activeTouchId) {
            updateJoystickPosition(touch.clientX, touch.clientY);
            break;
          }
        }
      }

      function handleTouchEnd(event) {
        activeTouchId = null;
        resetJoystick();
        releaseAllKeys();
      }

      function updateJoystickPosition(x, y) {
        const containerRect = joystickContainer.getBoundingClientRect();
        const deltaX = x - (containerRect.left + baseRadius);
        const deltaY = y - (containerRect.top + baseRadius);
        const angle = Math.atan2(deltaY, deltaX);
        const distance = Math.min(Math.hypot(deltaX, deltaY), baseRadius * 0.8);

        joystickHead.style.left = `${
          baseRadius + distance * Math.cos(angle)
        }px`;
        joystickHead.style.top = `${baseRadius + distance * Math.sin(angle)}px`;

        const threshold = 0.3;
        const newDirections = {
          w: false,
          a: false,
          s: false,
          d: false,
          q: false,
          e: false,
          z: false,
          x: false,
        };

        simulateKeyRelease("w");
        simulateKeyRelease("a");
        simulateKeyRelease("s");
        simulateKeyRelease("d");
        simulateKeyRelease("q");
        simulateKeyRelease("e");
        simulateKeyRelease("z");
        simulateKeyRelease("x");

        if (distance > baseRadius * threshold) {
          if (angle >= -Math.PI * 0.125 && angle < Math.PI * 0.125) {
            newDirections.d = true;
          } else if (angle >= Math.PI * 0.125 && angle < Math.PI * 0.375) {
            newDirections.x = true;
          } else if (angle >= Math.PI * 0.375 && angle < Math.PI * 0.625) {
            newDirections.s = true;
          } else if (angle >= Math.PI * 0.625 && angle < Math.PI * 0.875) {
            newDirections.z = true;
          } else if (angle >= Math.PI * 0.875 || angle < -Math.PI * 0.875) {
            newDirections.a = true;
          } else if (angle >= -Math.PI * 0.875 && angle < -Math.PI * 0.625) {
            newDirections.q = true;
          } else if (angle >= -Math.PI * 0.625 && angle < -Math.PI * 0.375) {
            newDirections.w = true;
          } else if (angle >= -Math.PI * 0.375 && angle < -Math.PI * 0.125) {
            newDirections.e = true;
          }
        }

        for (const key in newDirections) {
          if (newDirections[key] !== keys[key]) {
            if (newDirections[key]) {
              simulateKeyPress(key);
            } else {
              simulateKeyRelease(key);
            }
            keys[key] = newDirections[key];
          }
        }
      }

      function resetJoystick() {
        joystickHead.style.left = "50%";
        joystickHead.style.top = "50%";
      }

      function releaseAllKeys() {
        for (const key in keys) {
          if (keys[key]) {
            simulateKeyRelease(key);
            keys[key] = false;
          }
        }
      }

      function simulateKeyPress(key) {
        const keyCode = Key.dict[key];
        if (keyCode && !Key.keys.includes(keyCode)) {
          Key.push(keyCode);
          const mockEvent = createMockEvent(keyCode);
          Key.keydown(mockEvent);
        }
      }

      function simulateKeyRelease(key) {
        const keyCode = Key.dict[key];
        if (keyCode) {
          const mockEvent = createMockEvent(keyCode);
          Key.keyup(mockEvent);
          const index = Key.keys.indexOf(keyCode);
          if (index > -1) {
            Key.keys.splice(index, 1);
          }
        }
      }

      function createMockEvent(keyCode) {
        return {
          keyCode: keyCode,
          ctrlKey: false,
          shiftKey: false,
          altKey: false,
          preventDefault: () => {},
          repeat: false,
        };
      }

      joystickContainer.addEventListener("touchstart", handleTouchStart);
      joystickContainer.addEventListener("touchmove", handleTouchMove);
      joystickContainer.addEventListener("touchend", handleTouchEnd);
      joystickContainer.addEventListener("touchcancel", handleTouchEnd);

      window.addEventListener("blur", function () {
        releaseAllKeys();
        resetJoystick();
      });
    }

    createJoystick();
  }
  // ====================================================================================================================
}
// ====================================================================================================================
function amogusSus() {
  console.log("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣤⣤⣤⣤⣤⣤⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠛⠉⠙⠛⠛⠛⠛⠻⢿⣿⣷⣤⡀⠀⠀⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⠋⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠈⢻⣿⣿⡄⠀⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⣸⣿⡏⠀⠀⠀⣠⣶⣾⣿⣿⣿⠿⠿⠿⢿⣿⣿⣿⣄⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⣿⣿⠁⠀⠀⢰⣿⣿⣯⠁⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣷⡄⠀ ");
  console.log("⠀⠀⣀⣤⣴⣶⣶⣿⡟⠀⠀⢸⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣷⠀ ");
  console.log("⠀⢰⣿⡟⠋⠉⣹⣿⡇⠀⠀⠘⣿⣿⣿⣿⣷⣦⣤⣤⣤⣶⣶⣶⣶⣿⣿⣿⠀ ");
  console.log("⠀⢸⣿⡇⠀⠀⣿⣿⡇⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀ ");
  console.log("⠀⣸⣿⡇⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠉⠻⠿⣿⣿⣿⣿⡿⠿⠿⠛⢻⣿⡇⠀⠀ ");
  console.log("⠀⣿⣿⠁⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣧⠀⠀ ");
  console.log("⠀⣿⣿⠀⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⠀⠀ ");
  console.log("⠀⣿⣿⠀⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⠀⠀ ");
  console.log("⠀⢿⣿⡆⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡇⠀⠀ ");
  console.log("⠀⠸⣿⣧⡀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀ ");
  console.log("⠀⠀⠛⢿⣿⣿⣿⣿⣇⠀⠀⠀⠀⣰⣿⣿⣷⣶⣶⣶⣶⠶⠀⠀⢠⣿⣿⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⣿⣿⡇⠀⣽⣿⡏⠁⠀⠀⠀⢸⣿⡇⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⣿⣿⡇⠀⢹⣿⡆⠀⠀⠀⠀⣸⣿⠇⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⢿⣿⣦⣄⣀⣠⣴⣿⣿⠁⠀⠈⠻⣿⣿⣿⣿⡿⠏⠀⠀⠀⠀ ");
  console.log("⠀⠀⠀⠀⠀⠀⠀⠈⠛⠻⠿⠿⠿⠿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀");
}
// ====================================================================================================================
//   . . . ТАРГЕТИНГ БЛОГОВОЙ СТРАНИЦЫ . . .
// ====================================================================================================================
if (targetBlogsCreation.test(window.location.href)) {
  // ====================================================================================================================
  //   . . . ВОССТАНОВЛЕНИЕ БЛОГОВОГО ТЕКСТА . . .
  // ====================================================================================================================
  if (settings.restoreBlogCreation) {
    const textarea = document.getElementById("creation-text");

    function saveTextToStorage(text) {
      localStorage.setItem("uwu_blogCreation", text);
    }

    function restoreTextFromStorage() {
      const savedText = localStorage.getItem("uwu_blogCreation");
      if (savedText && !textarea.value) {
        textarea.value = savedText;
      }
    }

    textarea.addEventListener("input", () => {
      saveTextToStorage(textarea.value);
    });

    window.addEventListener("beforeunload", () => {
      saveTextToStorage(textarea.value);
    });

    restoreTextFromStorage();
  }
}

// ====================================================================================================================
//   . . . КНОПКИ BB-КОДОВ . . .
// ====================================================================================================================
if (settings.moreBBCodes) {
  function addBBCodeButtons() {
    const bbCodeContainers = document.querySelectorAll(".bbcode");

    const commonButtonsHTML = // html
    `
      <button class="bbcode" title="Абзац" data-code="p">p</button>
      <button class="bbcode" title="Перенос" data-code="br" data-parameter="0">br</button>
      <button class="bbcode" title="Таблица" data-code="table">table</button>
      <button class="bbcode" title="Строка таблицы" data-code="tr">tr</button>
      <button class="bbcode" title="Ячейка таблицы" data-code="td">td</button>
      <button class="bbcode" title="Нумерованный список" data-code="ol">ol</button>
      <button class="bbcode" title="Маркированный список" data-code="ul">ul</button>
      <button class="bbcode" title="Строка списка" data-code="li">li</button>
    `;

    const overblockButtonHTML = `
      <button class="bbcode" title="Раскрывающийся блок" data-code="overblock" data-parameter="1" data-text="Введите название раскрывающегося блока (то же, что и у заголовка, который раскрывает этот блок):">overblock</button>
    `;

    bbCodeContainers.forEach((bbCode) => {
      const container = bbCode.parentElement;
      if (!container) return;

      if (!container.querySelector('.bbcode[data-code="p"]')) {
        container.insertAdjacentHTML("beforeend", commonButtonsHTML);
      }

      const blockElement = container.querySelector('[data-code="block"]');
      if (
        blockElement &&
        !container.querySelector('.bbcode[data-code="overblock"]')
      ) {
        blockElement.insertAdjacentHTML("afterend", overblockButtonHTML);
      }
    });
  }

  setupSingleCallback(".bbcode", addBBCodeButtons);
}
// ====================================================================================================================
//   . . . ПРОФИЛЬ ИГРОКА . . .
// ====================================================================================================================
if (targetMainProfile.test(window.location.href)) {

  if (settings.calculators) {
    setupSingleCallback("#info", setupActivityCalc);
    setupSingleCallback("#info", moonCalculator);
  }

}
// ====================================================================================================================
//   . . . ПРОФИЛЯ ДРУГИХ ПОЛЬЗОВАТЕЛЕЙ . . .
// ====================================================================================================================
if (targetProfile.test(window.location.href)) {

  // ====================================================================================================================
  //   . . . БУ И ПРОЧЕЕ . . .
  // ====================================================================================================================
  if (settings.moreProfileInfo) {
    setupSingleCallback("tr:has(img[src='img/icon_kraft.png'])", addKraftLevel);
    
    function addKraftLevel() {
      const kraftLevels = {
        "блоха": 0,
        "котёночек": 1,
        "задира": 2,
        "гроза детской": 3,
        "страх барсуков": 4,
        "победитель псов": 5,
        "защитник племени": 6,
        "великий воин": 7,
        "достоин Львиного племени": 8,
        "идеальная": 9
      };
    
        const kraftRow = document.querySelector('tr:has(img[src="img/icon_kraft.png"])');
        const kraftTextElement = kraftRow.querySelector('b');
        const kraftText = kraftTextElement.textContent.trim();
        const kraftLevel = kraftLevels[kraftText];
        if (kraftLevel !== undefined) {
            kraftTextElement.textContent = `${kraftText} (${kraftLevel})`;
        }
    }
  }
  
  if (settings.calculators) {
    setupSingleCallback("#info", moonCalculator);
  }
}

// ===================================================================================================================
// Калькуляторы возраста/лун и активности частично под авторством "CatWar Mod (Варомод) от Хвойницы"
// ====================================================================================================================
//   . . . КАЛЬКУЛЯТОР ВОЗРАСТА / ЛУН . . .
// ====================================================================================================================
function moonCalculator() {
  const months = [
    "января", "февраля", "марта", "апреля", "мая", "июня",
    "июля", "августа", "сентября", "октября", "ноября", "декабря"
  ];

  const catTimeStart = 1200000000000;

  const infoElement = document.getElementById("info");
  if (!infoElement) return;

  const style = document.createElement("style");
  style.textContent = `
    .calculator-error { color: darkred; }
    .hidden { display: none; }
    .calculator-style { max-width: 400px; margin: 5px; padding: 5px; border-radius: 10px; background: #ffffff08; }
  `;
  document.head.appendChild(style);

  let calculatorAgeElement = document.getElementById("calculator-age");
  if (!calculatorAgeElement) {
    infoElement.insertAdjacentHTML('afterend', `<div id="calculator-age" class="calculator-style hidden"></div>`);
    calculatorAgeElement = document.getElementById("calculator-age");
  }

  const infoObserver = new MutationObserver((mutations) => {
    mutations.forEach(() => {
      if (!infoElement.textContent.match("Дата")) {
        calculatorAgeElement.classList.add("hidden");
        return;
      }

      calculatorAgeElement.classList.remove("hidden");

      const birthDateString = infoElement.textContent.match(/\d{4}-\d\d-\d\d \d\d:\d\d/)[0].replace(" ", "T");
      const nowDateString = formatDate(new Date());

      const ageMoons = getMoonsFromElement("age_icon");
      const age2Moons = getMoonsFromElement("age2_icon");

      const sex = document.querySelector('[src^="//e.catwar.net/avatar"]').style.borderColor;
      const isRegistrationDate = /регистрац/.test(infoElement.textContent);
      const moonsNow = age2Moons ? (isRegistrationDate ? ageMoons : age2Moons) : ageMoons;

      const bornWord = getBornWord(sex, isRegistrationDate);
      const catTimeString = formatCatTime(Date.parse(birthDateString), moonsNow);

      calculatorAgeElement.innerHTML = `
        <p><b>Калькулятор возраста</b></p>
        <label>Дата и время: <input type="datetime-local" id="calculator-date" min="${birthDateString}" value="${nowDateString}" max="9999-12-31T23:59"></label> <span id="calculator-error-date" class="calculator-error"></span>
        <br><label>Возраст: <input type="number" id="calculator-moons" min="0" step="0.1" value="${moonsNow}" style="width: 60px"></label> <span id="moon-word"></span> <span id="calculator-error-moons" class="calculator-error"></span>
        <br>${bornWord} ${catTimeString} по кошачьему времени.
        <br><br>
      `;

      updateMoonWord(moonsNow);

      const calculatorDateElement = document.getElementById("calculator-date");
      const calculatorMoonsElement = document.getElementById("calculator-moons");

      calculatorDateElement.addEventListener("input", function () {
        handleDateInput.call(this, birthDateString);
      });

      calculatorMoonsElement.addEventListener("input", function () {
        handleMoonsInput.call(this, birthDateString);
      });
    });
  });

  infoObserver.observe(infoElement, { childList: true });

  function getMoonsFromElement(iconId) {
    const iconElement = document.querySelector(`img[id="${iconId}"]`);
    if (!iconElement) return 0;
    const ageElement = iconElement.closest("tr").querySelector("td:nth-child(2) b");
    return parseFloat(ageElement.textContent);
  }

  function getBornWord(sex, isRegistrationDate) {
    const sexWords = {
      pink: ["Зарегистрировалась", "Родилась"],
      blue: ["Зарегистрировался", "Родился"],
      default: ["Зарегистрировалось", "Родилось"],
    };
    return isRegistrationDate ? (sexWords[sex] ? sexWords[sex][0] : sexWords.default[0]) : (sexWords[sex] ? sexWords[sex][1] : sexWords.default[1]);
  }

  function formatDate(date) {
    const pad = (num) => String(num).padStart(2, "0");
    return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
  }

  function formatCatTime(birthTimestamp, moons) {
    const daysToAdd = moons * 4;
    const targetDate = new Date(birthTimestamp + daysToAdd * 24 * 60 * 60 * 1000);
    const ms = birthTimestamp - catTimeStart;
    let time = Math.round(ms / 1000 * 7);
    const secInYear = 12 * 28 * 24 * 60 * 60;
    const secInMonth = 28 * 24 * 60 * 60;
    const year = Math.floor(time / secInYear);
    time -= year * secInYear;
    const month = Math.floor(time / secInMonth);
    time -= month * secInMonth;
    const day = Math.floor(time / (24 * 60 * 60)) + 1;
    time -= (day - 1) * 24 * 60 * 60;
    const hour = Math.floor(time / (60 * 60));
    time -= hour * 60 * 60;
    const minute = Math.floor(time / 60);
    const pad = (num) => String(num).padStart(2, "0");
    return `${day} ${months[month]} ${year} года в ${pad(hour)}:${pad(minute)}`;
  }

  function handleDateInput(birthDateString) {
    const dateString = this.value;
    const date = Date.parse(dateString);
    const errorDateElement = document.getElementById("calculator-error-date");
    errorDateElement.textContent = "";

    if (isNaN(date) || date < Date.parse(birthDateString)) {
      errorDateElement.textContent = "Ошибка!";
      return;
    }

    const moons = getMoonsFromDate(birthDateString, dateString);
    const calcMoonsElement = document.getElementById("calculator-moons");
    if (calcMoonsElement) {
      calcMoonsElement.value = moons;
      updateMoonWord(moons);
      const catTimeString = formatCatTime(Date.parse(birthDateString), moons);
      document.querySelector("br").nextSibling.textContent = `${catTimeString} по кошачьему времени.`;
    }
    updateMoonWord(moons);
  }

  function handleMoonsInput(birthDateString) {
    const moons = Number(this.value);
    const errorMoonsElement = document.getElementById("calculator-error-moons");
    errorMoonsElement.textContent = "";

    if (moons < 0 || isNaN(moons)) {
      errorMoonsElement.textContent = "Ошибка!";
      return;
    }

    const calcDateElement = document.getElementById("calculator-date");
    if (calcDateElement) {
      calcDateElement.value = getDateStringFromMoons(birthDateString, moons);
      updateMoonWord(moons);
      const catTimeString = formatCatTime(Date.parse(birthDateString), moons);
      document.querySelector("br").nextSibling.textContent = `${catTimeString} по кошачьему времени.`;
    }
    updateMoonWord(moons);
  }

  function getMoonsFromDate(birthDateString, dateString) {
    const birthday = Date.parse(birthDateString);
    const date = Date.parse(dateString);
    const moons = Math.floor((date - birthday) / (1000 * 60 * 60 * 24 * 4) * 10) / 10;
    return moons;
  }

  function getDateStringFromMoons(birthDateString, moons) {
    const birthday = Date.parse(birthDateString);
    const age = Math.round(moons * 4 * 24 * 60 * 60 * 1000);
    return formatDate(new Date(birthday + age));
  }

  function updateMoonWord(moons) {
    const integerMoons = Math.floor(moons);
    document.getElementById("moon-word").textContent = declOfNum(integerMoons, ['луна', 'луны', 'лун']);
  }

  function declOfNum(number, titles) {
    const cases = [2, 0, 1, 1, 1, 2];
    return titles[(number % 100 > 4 && number % 100 < 20) ? 2 : cases[(number % 10 < 5) ? number % 10 : 5]];
  }
}
// ====================================================================================================================
//   . . . КАЛЬКУЛЯТОР АКТИВНОСТИ . . .
// ====================================================================================================================
// TODO - Переписать, сделать рефакторинг и как-то объединить и упростить код с калькулятором выше.
function setupActivityCalc() {
  const catId = document.getElementById("id_val").textContent;

  const activityStages = [
    { name: "пустое место", fromZero: -5000 },
    { name: "подлежащий удалению", fromZero: -5000 },
    { name: "покинувший игру", fromZero: -2000 },
    { name: "забывший про игру", fromZero: -1000 },
    { name: "забытый кот", fromZero: -750 },
    { name: "ужаснейшая", fromZero: -500 },
    { name: "ужасная", fromZero: -300 },
    { name: "ухудшающаяся", fromZero: -150 },
    { name: "отрицательная", fromZero: -50 },
    { name: "переходная", fromZero: -5 },
    { name: "положительная", fromZero: 5 },
    { name: "улучшающаяся", fromZero: 50 },
    { name: "замечательная", fromZero: 150 },
    { name: "переход 2 мин 15 с", fromZero: 225 },
    { name: "замечательнейшая", fromZero: 300 },
    { name: "переход 2 мин", fromZero: 450 },
    { name: "любимый кот", fromZero: 500 },
    { name: "переход 1 мин 45 с", fromZero: 675 },
    { name: "легенда сайта", fromZero: 750 },
    { name: "переход 1 мин 30 с", fromZero: 900 },
    { name: "ходячий миф", fromZero: 1000 },
    { name: "переход 1 мин 15 с", fromZero: 1125 },
    { name: "переход 1 мин", fromZero: 1350 },
    { name: "переход 45 c", fromZero: 1575 },
    { name: "император Игровой", fromZero: 2000 },
    { name: "частичка Игровой", fromZero: 5000 },
    { name: "хранитель Игровой", fromZero: 20000 },
    { name: "идеальная", fromZero: 75000 },
    { name: "сверхидеальная", fromZero: 150000 },
  ];

  const months = [
    "января", "февраля", "марта", "апреля", "мая", "июня",
    "июля", "августа", "сентября", "октября", "ноября", "декабря"
  ];

  const activitySettings = JSON.parse(
    window.localStorage.getItem("uwu_activity") || "{}"
  );

  if (!activitySettings[catId]) {
    activitySettings[catId] = { hours: 24, opened: false };
  }

  if (activitySettings[catId].actgoal) {
    activityStages.forEach(function (stage, index) {
      if (index && Number(activitySettings[catId].actgoal) === stage.fromZero) {
        activitySettings[catId].goal = index;
        delete activitySettings[catId].actgoal;
      }
    });
  }

  function calculateActivityLength(days) {
    const minus = activitySettings[catId].minus || 0;
    if (days <= 14) return 150 - minus;
    else if (days >= 1575) return 45 - minus;
    else return Math.ceil(150 - days / 15) - minus;
  }

  function calculateRemainingTime(currentActivity, goal, hoursPerDay) {
    const secondsPerDay = convertTime("h s", hoursPerDay);
    if (calculateActivityLength(currentActivity) * 4 + 1 > secondsPerDay) {
      return { actions: "∞", time: "∞", date: "никогда" };
    }

    const actionsWithoutDecrease = goal - currentActivity;
    let days = 0;
    let secondsToday;

    while (currentActivity < goal) {
      secondsToday = 0;
      while (secondsToday < secondsPerDay) {
        currentActivity++;
        secondsToday += calculateActivityLength(currentActivity);
        if (currentActivity >= goal) break;
      }
      if (currentActivity >= goal) break;
      days++;
      currentActivity -= 4.8;
    }

    const actionsDecrease = Math.floor(
      days * 4.8 + convertTime("s h", secondsToday) / 5
    );
    const totalTime = secondsPerDay * days + secondsToday;

    const now = new Date();
    const tomorrow = new Date(
      now.getFullYear(),
      now.getMonth(),
      now.getDate() + 1
    );
    const secondsToTomorrow = convertTime("ms s", tomorrow - now);
    if (days === 0 && secondsToday > secondsToTomorrow) days++;

    const targetDate = new Date(Date.now() + convertTime("d ms", days));

    return {
      actions: actionsWithoutDecrease + actionsDecrease,
      time: secondsToTime(totalTime),
      date:
        targetDate.getDate() +
        " " +
        months[targetDate.getMonth()] +
        " " +
        targetDate.getFullYear(),
    };
  }

  function updateGoalProgress() {
    if (progress.stage === activityStages.length - 1) {
      document.getElementById("goal-progress").style.display = "none";
      return;
    }
    const goalIndex = Number(document.getElementById("activity-list").value);
    const result = calculateRemainingTime(
      progress.doneFromZero,
      activityStages[goalIndex].fromZero,
      activitySettings[catId].hours
    );
    document.querySelector("#goal-progress > ul").innerHTML = `
      <li>${result.actions} ${declensionOfNumber(result.actions, [
      "переход",
      "перехода",
      "переходов",
    ])} (${result.time})</li>
      <li>будет достигнута ${result.date}</li>
    `;
  }

  const activity = document
    .querySelector("#act_name b")
    .textContent.split(" (");
  const progress = {};

  const currentStage = activityStages.find(stage => stage.name === activity[0]);

  if (currentStage) {
    progress.doneFromZero = currentStage.fromZero + Number(activity[1].split("/")[0]);
    progress.stage = activityStages.indexOf(currentStage); 
  }

  const activityInfoHTML = // html
    `
      <details id="calculator-activity" class="calculator-style">
        <summary id="open-calculator"><b>Калькулятор активности</b></summary>
        <div id="calculator-content" style="margin-top: 10px;">
          <p id="congratulations" style="display:none"></p>
          <div id="activity-length"><b>Переход</b>: ${secondsToTime(calculateActivityLength(progress.doneFromZero))}</div>
          <div>Мой переход изменён на <input id="minus" type="number" value="${activitySettings[catId].minus || 0}" min="-60" max="10" step="1" style="width: 50px;"> <span id="minus-word"></span></nobr></div>
          <div>Я качаю активность <input id="hours-per-day" type="number" step="0.25" min="0" max="24" value="${activitySettings[catId].hours}" style="width: 60px"> <span id="hour-word"></span> в сутки</div>
          <div id="goal-progress">
            <b>Цель: <select style="display: inline" id="activity-list"></select></b>:
            <ul style="margin: 0.5em"></ul>
          </div>
          <div id="to-fall-container" style="display: none;">Переход начнёт падать <span id="to-fall"></span></div>
        </div>
      </details>
    `;

  document
    .getElementById("info")
    .insertAdjacentHTML("afterend", activityInfoHTML);

  if (activitySettings[catId].opened) {
    document.getElementById("calculator-activity").open = true;
  }

  for (let i = progress.stage + 1; i < activityStages.length; i++) {
    const option = document.createElement("option");
    option.value = i;
    option.textContent = activityStages[i].name;
    document.getElementById("activity-list").appendChild(option);
  }

  function showCongratulations() {

    document.getElementById("congratulations").innerHTML = // html
    `
      Цель <b>«${activityStages[activitySettings[catId].goal].name}»</b> достигнута!
      <center><img src="/img/stickers/systempaw3/6.png"></center>
      <input id="congratulations-button" type="button" value="Скрыть">
      <br><input id="never-show-congratulations" type="checkbox"> Больше не поздравлять на этом персонаже
    `;

    document.getElementById("congratulations").style.display = "block";
    document
      .getElementById("congratulations-button")
      .addEventListener("click", function () {
        document.getElementById("congratulations").style.display = "none";
        activitySettings[catId].goal = Number(
          document.getElementById("activity-list").value
        );
        activitySettings[catId].noGrats = document.getElementById(
          "never-show-congratulations"
        ).checked;
        saveData(activitySettings);
      });
  }

  if (activitySettings[catId].goal > progress.stage || activitySettings[catId].noGrats) {
    document.querySelector(
      `#activity-list > [value="${activitySettings[catId].goal}"]`
    ).selected = true;
  } else if (activitySettings[catId].goal) {
    showCongratulations();
  }

  if (activitySettings[catId].minus) {
    document.getElementById("minus").value = activitySettings[catId].minus;
  }

  const hours = activitySettings[catId].hours;
  const minusValue = activitySettings[catId].minus || 0;

  updateHourWord(hours);
  updateGoalProgress();
  updateMinusWord(minusValue);

  if (calculateActivityLength(progress.doneFromZero) !== 45) {
    document.getElementById("to-fall-container").style.display = "none";
  } else {
    const timeFall = new Date(
      Date.now() + (progress.doneFromZero - 1575) * 5 * 3600000
    );
    document.getElementById("to-fall").innerHTML =
      timeFall.getDate() +
      " " +
      months[timeFall.getMonth()] +
      " " +
      timeFall.getFullYear();
    document.getElementById("to-fall-container").style.display = "block";
  }

  document.getElementById("minus").addEventListener("change", function () {
    activitySettings[catId].minus = this.value;
    saveData(activitySettings);
    updateGoalProgress();
    document.getElementById(
      "activity-length"
    ).innerHTML = `<b>Переход</b>: ${secondsToTime(
      calculateActivityLength(progress.doneFromZero)
    )}`;
    updateMinusWord(this.value);
  });

  document.getElementById("activity-list").addEventListener("change", function () {
    activitySettings[catId].goal = Number(this.value);
    saveData(activitySettings);
    updateGoalProgress();
  });

  document
    .getElementById("hours-per-day")
    .addEventListener("input", function () {
      const hours = Number(this.value);
      if (hours < 0 || hours > 24 || !Number.isInteger(hours * 1000)) {
        this.value = activitySettings[catId].hours;
        return;
      }
      activitySettings[catId].hours = hours;
      saveData(activitySettings);
      updateHourWord(hours);
      updateGoalProgress();
    });

  document.getElementById("open-calculator").addEventListener("click", function () {
    activitySettings[catId].opened = !document.getElementById("calculator-activity").open;
    saveData(activitySettings);
  });

  function saveData(data) {
    window.localStorage.setItem("uwu_activity", JSON.stringify(data));
  }

  function declensionOfNumber(number, titles) {
    const cases = [2, 0, 1, 1, 1, 2];
    const absNumber = Math.abs(number);
    return titles[
      absNumber % 100 > 4 && absNumber % 100 < 20
        ? 2
        : cases[absNumber % 10 < 5 ? absNumber % 10 : 5]
    ];
  }

  function convertTime(from, value) {
    const factors = {
      ms: 1,
      s: 1000,
      m: 60000,
      h: 3600000,
      d: 86400000,
    };
    const [fromUnit, toUnit] = from.split(" ");
    return (value * factors[fromUnit]) / factors[toUnit];
  }

  function secondsToTime(seconds) {
    const days = Math.floor(seconds / 86400);
    const hours = Math.floor((seconds % 86400) / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = seconds % 60;
    let result = "";
    if (days > 0) result += `${days} д `;
    if (hours > 0) result += `${hours} ч `;
    if (minutes > 0) result += `${minutes} мин `;
    if (secs > 0 || result === "") result += `${secs} с`;
    return result.trim();
  }

  function updateHourWord(hours) {
    document.getElementById("hour-word").textContent = declensionOfNumber(hours, ["час", "часа", "часов"]);
  }
  
  function updateMinusWord(minusValue) {
    document.getElementById("minus-word").textContent = declensionOfNumber(minusValue, ["секунду", "секунды", "секунд"]);
  }
}
// ====================================================================================================================
//   . . . ПИСЬМА . . .
// ====================================================================================================================
if (targetLs.test(window.location.href)) {

  if (settings.lsWrapPreview) {
    setupMutationObserver("#main", setupPreviewButton, {
      childList: true,
      subtree: true,
    }); 
  }

}
// ====================================================================================================================
//   . . . БЛОГИ . . .
// ====================================================================================================================
if (targetBlog.test(window.location.href)) {

  if (settings.commentPreview) {
    setupMutationObserver("#site_table", addCommentPreview); 
  }

  if (settings.moreCommentButtons) {
    setupMutationObserver("#view_comments", addCommentButtons, {
      childList: true,
      subtree: true,
    });
    setupSingleCallback("#view_comments", handleCommentActions);
  }

}

// ====================================================================================================================
//   . . . ЛЕНТА . . .
// ====================================================================================================================
if (targetSniff.test(window.location.href)) {
  
  if (settings.commentPreview) {
    setupMutationObserver("#site_table", addCommentPreview); 
  }

  if (settings.moreCommentButtons) {
    setupMutationObserver("#view_comments", addCommentButtons, {
      childList: true,
      subtree: true,
    });
    setupSingleCallback("#view_comments", handleCommentActions);
  }

}

// ====================================================================================================================
//   . . . ПРЕДПРОСМОТР КОММЕНТАРИЯ . . .
// ====================================================================================================================
function addCommentPreview() {
  const form = document.querySelector("#send_comment_form");
  if (!form || document.getElementById("comment-preview")) return;

  const lastParagraph = form.querySelector("p:last-child");
  lastParagraph.insertAdjacentHTML( "afterbegin",
    `
    <input type="button" id="comment-preview" value="Предпросмотр"> 
    `
  );

  form.insertAdjacentHTML( "afterend",
    `
    <p id="comment-preview-hide" style="display: none; margin: 0.5em 0;"><a href="#">Скрыть предпросмотр</a></p>
    <div id="comment-preview-div" style="display: none;"></div>
    `
  );

  const previewButton = document.getElementById("comment-preview");
  const hideParagraph = document.getElementById("comment-preview-hide");
  const previewDiv = document.getElementById("comment-preview-div");

  const ws = io(window.location.origin, {
    path: "/ws/blogs/socket.io",
    reconnectionDelay: 10000,
    reconnectionDelayMax: 20000,
  });

  ws.on('creation preview', (data) => {
    previewDiv.innerHTML = data;
    previewDiv.style.display = 'block';
    hideParagraph.style.display = 'block';
  });

  previewButton.addEventListener('click', function() {
    const commentText = document.getElementById('comment').value;
    ws.emit('creation preview', commentText);
  });

  form
    .querySelector('[type="submit"]')
    .addEventListener("click", hideCommentPreview);
  hideParagraph.addEventListener("click", function (e) {
    e.preventDefault();
    hideCommentPreview();
  });

  function hideCommentPreview() {
    hideParagraph.style.display = "none";
    previewDiv.innerHTML = "";
    previewDiv.style.display = "none";
  }
};
// ====================================================================================================================
//   . . . КНОПКИ ОТВЕТИТЬ И ЦИТИРОВАТЬ . . .
// ====================================================================================================================
function addCommentButtons() {
  const comments = document.querySelectorAll('#view_comments .view-comment');
  comments.forEach(comment => {
      if (!comment.querySelector('.comment-answer-buttons')) {
          comment.insertAdjacentHTML('beforeend', // html
            `
              <p class="comment-answer-buttons">
                  <a class="comment-answer" href="#">Ответить</a>
                  <span class="comment-cite-wrap"> | <a class="comment-cite" href="#">Цитировать</a></span>
              </p>
          `);
      }
  });
}

function getCommentInfo(comment) {
  const commentId = comment.getAttribute('data-id');
  const commentNum = comment.querySelector('.num').textContent;
  const authorLink = comment.querySelector('.comment-info a.author');
  const authorSpan = comment.querySelector('.comment-info span[data-id]');
  const authorName = authorLink ? authorLink.textContent : (authorSpan ? authorSpan.textContent : '...');
  const authorProfile = authorLink ? authorLink.getAttribute('href').replace('/cat', '') : null;
  const commentText = comment.querySelector('.comment-text .parsed').innerText;
  const commentInfo = comment.querySelector('.comment-info');
  const commentTime = commentInfo.innerHTML.split('</b>')[1].split(' @')[0].trim();

  return {
    commentId,
    commentNum,
    authorName,
    authorProfile,
    commentText,
    commentTime
  };
}

function handleAnswerAction(commentInfo) {
  const textarea = document.getElementById('comment');
  if (commentInfo.authorProfile) {
      textarea.value = `[link${commentInfo.authorProfile}] (#${commentInfo.commentNum}), `;
  } else {
      textarea.value = `[b][code]${commentInfo.authorName}[/code][/b] (#${commentInfo.commentNum}), `;
  }
}

function handleCiteAction(commentInfo) {
  const selectedText = window.getSelection().toString().trim();
  const quoteText = selectedText ? selectedText : commentInfo.commentText;
  const profileLink = commentInfo.authorProfile ? `[link${commentInfo.authorProfile}]` : commentInfo.authorName;

  const quote = `[table][tr][td][size=10][i]Цитата:[/i] [b]#${commentInfo.commentNum}[/b] ${commentInfo.commentTime} @ ${profileLink}[/size][/td][/tr][tr][td][table=0][tr][td]  [/td][td]${quoteText}[/td][/tr][/table][/td][/tr][/table]`;

  const textarea = document.getElementById('comment');
  textarea.value = quote;
}

function handleCommentActions() {
    const viewComments = document.getElementById('view_comments');

    viewComments.addEventListener('click', function(event) {
        const target = event.target;
        const actionMap = {
            'comment-answer': handleAnswerAction,
            'comment-cite': handleCiteAction
        };

        for (const className in actionMap) {
            if (target.classList.contains(className)) {
                event.preventDefault();
                const comment = target.closest('.view-comment');
                const commentInfo = getCommentInfo(comment);
                actionMap[className](commentInfo);
                break;
            }
        }
    });
}

// ====================================================================================================================
//   . . . КРАСИВЫЙ ПРЕДПРОСМОТР ПИСЬМА . . .
// ====================================================================================================================
function setupPreviewButton() {
  const previewButton = document.getElementById('preview');
  if (previewButton) {
      previewButton.addEventListener('click', wrapPreviewInTable);
  }
}

function wrapPreviewInTable() {
  const previewDiv = document.getElementById('preview_div');
  if (!previewDiv) return;

  const mainElement = document.getElementById('main');
  const senderId = mainElement.getAttribute('data-id');
  const senderLogin = mainElement.getAttribute('data-login');
  const subject = document.getElementById('subject').value;
  const currentDate = new Date().toLocaleString('ru-RU', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
  });

  const newTable = document.createElement('table');
  newTable.border = "1";
  newTable.style.width = "90%";
  newTable.style.maxWidth = "500px";

  newTable.innerHTML = // html
  `
      <tbody>
          <tr><td id="preview-subject" colspan="2">${subject}</td></tr>
          <tr>
              <td valign="top" id="msg_info">
                  Отправитель: <span id="preview-sender"><a href="cat${senderId}">${senderLogin}</a></span>
                  <br>${currentDate}
                  <br>Переписка: <u><big><b>+</b></big></u> …
              </td>
              <td id="preview-text">${previewDiv.outerHTML}</td>
          </tr>
      </tbody>
  `;

  const existingTable = document.querySelector('table');
  if (existingTable) {
      existingTable.parentNode.replaceChild(newTable, existingTable);
  } else {
      previewDiv.parentNode.insertBefore(newTable, previewDiv);
      previewDiv.style.display = 'none';
  }
}

// ====================================================================================================================
//   . . . ШАБЛОНЫ . . .
// ====================================================================================================================
function initializeTemplates() {
  if (!settings.showTemplates) return;

  const templateContainer = // html
  `
      <div id="uwu-templates">
          <h2>ШАБЛОНЫ</h2>
          <div id="uwu-templates-list"></div>
          <div class="button-container">
              <button id="create-template-button" class="uwu-button install-button">Создать шаблон ✎</button>
          </div>
      </div>
  `;

  const templateItem = // html
  `
      <div class="uwu-template-item">
          <div class="template-name-container">
              <span class="template-name"></span>
              <button class="rename-button uwu-button install-button" title="Переименовать шаблон">✎</button>
          </div>
          <div class="template-actions-container">
              <button class="update-button uwu-button install-button" title="Обновить шаблон">↻</button>
              <button class="remove-button uwu-button install-button" title="Удалить шаблон">X</button>
          </div>
      </div>
  `;

  const cssStyles = // css
  `
      #uwu-templates {
        font-family: Montserrat;
        border: 1px solid rgba(255, 255, 255, 0.1);
        border-radius: 20px;
        background-color: #242424;
        margin-bottom: 5px;
        margin-top: 5px;
        color: #d5d5d5;
      }
      
      #uwu-templates > h2 {
        font-size: 2em;
        text-align: center;
        margin-top: 10px;
        margin-bottom: 10px;
        letter-spacing: 20px;
      }

      #uwu-templates-list {
        max-height: 220px;
        overflow-x: auto;
        border-radius: 20px;
        background-color: #2e2e2e;
      }

      .uwu-template-item {
        padding-left: 10px;
        padding-right: 10px;
        padding-top: 5px;
        padding-bottom: 5px;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }

      #uwu-templates > div.button-container {
        display: flex;
        justify-content: flex-end;
        padding-left: 10px;
        padding-right: 4px;
        padding-top: 5px;
        padding-bottom: 5px;
      }

      .template-name {
        cursor: pointer;
        text-decoration: underline;
      }

      .uwu-button {
        background-color: rgba(255, 255, 255, 0.03);
        border: 1px solid rgba(255, 255, 255, 0.1);
        padding: 5px 10px;
        border-radius: 20px;
        cursor: pointer;
        transition: background-color 0.3s ease;
      }
      
      .uwu-button:hover {
        background-color: rgba(255, 255, 255, 0.2);
      }
  `;

  document.head.insertAdjacentHTML('beforeend', `<style>${cssStyles}</style>`);

  function setupTemplates(targetElementId, contentElementId, subjectElementId = null, pageType) {
    const targetElement = document.getElementById(targetElementId);

    if (!document.getElementById('uwu-templates')) {
        if (targetElementId === 'mess_form') {
            targetElement.insertAdjacentHTML('beforeend', templateContainer);
        } else {
            targetElement.insertAdjacentHTML('afterbegin', templateContainer);
        }
    }

      const templatesList = document.getElementById('uwu-templates-list');
      const createButton = document.getElementById('create-template-button');

      createButton.addEventListener('click', (event) => {
          event.preventDefault();
          createTemplate(contentElementId, subjectElementId, pageType);
      });

      function createTemplate(contentElementId, subjectElementId, pageType) {
          const templateName = prompt('Введите название шаблона:');
          if (templateName) {
              const template = {
                  name: templateName,
                  content: document.getElementById(contentElementId).innerText || document.getElementById(contentElementId).value,
                  subject: subjectElementId ? document.getElementById(subjectElementId).value || "" : "",
                  pageType: pageType
              };
              saveTemplate(template);
              renderTemplates(pageType);
          }
      }

      function saveTemplate(template) {
          if (!localStorage.getItem('uwu_templates')) {
              localStorage.setItem('uwu_templates', JSON.stringify([]));
          }
          const templates = JSON.parse(localStorage.getItem('uwu_templates'));
          templates.push(template);
          localStorage.setItem('uwu_templates', JSON.stringify(templates));
      }

      function renderTemplates(pageType) {
          const templates = JSON.parse(localStorage.getItem('uwu_templates')) || [];
          templatesList.innerHTML = '';

          templates.forEach((template, index) => {
              if (template.pageType === pageType) {
                  const templateItemHTML = document.createElement('div');
                  templateItemHTML.innerHTML = templateItem;
                  const templateItemElement = templateItemHTML.children[0];

                  const templateName = templateItemElement.querySelector('.template-name');
                  templateName.textContent = template.name;
                  templateName.addEventListener('click', () => {
                      if (document.getElementById(contentElementId).tagName === 'DIV') {
                          document.getElementById(contentElementId).innerText = template.content;
                      } else {
                          document.getElementById(contentElementId).value = template.content;
                      }
                      if (subjectElementId) {
                          document.getElementById(subjectElementId).value = template.subject || "";
                      }
                  });

                  const renameButton = templateItemElement.querySelector('.rename-button');
                  renameButton.addEventListener('click', () => renameTemplate(index));

                  const updateButton = templateItemElement.querySelector('.update-button');
                  updateButton.addEventListener('click', () => updateTemplate(index, contentElementId, subjectElementId));

                  const removeButton = templateItemElement.querySelector('.remove-button');
                  removeButton.addEventListener('click', () => removeTemplate(index));

                  templatesList.appendChild(templateItemElement);
              }
          });
      }

      function renameTemplate(index) {
          const newName = prompt('Введите новое название шаблона:');
          if (newName) {
              const templates = JSON.parse(localStorage.getItem('uwu_templates'));
              templates[index].name = newName;
              localStorage.setItem('uwu_templates', JSON.stringify(templates));
              renderTemplates(pageType);
          }
      }

      function updateTemplate(index, contentElementId, subjectElementId) {
          const templates = JSON.parse(localStorage.getItem('uwu_templates'));
          if (document.getElementById(contentElementId).tagName === 'DIV') {
              templates[index].content = document.getElementById(contentElementId).innerText;
          } else {
              templates[index].content = document.getElementById(contentElementId).value;
          }
          if (subjectElementId) {
              templates[index].subject = document.getElementById(subjectElementId).value || "";
          }
          localStorage.setItem('uwu_templates', JSON.stringify(templates));
          renderTemplates(pageType);
      }

      function removeTemplate(index) {
        const confirmation = confirm('Вы уверены, что хотите удалить этот шаблон?');
        if (confirmation) {
            const templates = JSON.parse(localStorage.getItem('uwu_templates'));
            templates.splice(index, 1);
            localStorage.setItem('uwu_templates', JSON.stringify(templates));
            renderTemplates(pageType);
        }
    }

      renderTemplates(pageType);
  }

  function checkUrlAndSetup() {
    if (targetLsNew.test(window.location.href) && settings.templatesInLs) {
        setupSingleCallback("#write_form", () => setupTemplates("write_div", "text", "subject", "ls"));
    } else if ((targetBlogsCreation.test(window.location.href) || targetSniffCreation.test(window.location.href)) && settings.templatesInBlogsAndSniffs) {
        setupSingleCallback(".creation_form", () => setupTemplates("creation_form", "creation-text", "creation-title", "blogsAndSniffs"));
    } else if (targetChats.test(window.location.href) && settings.templatesInChats) {
        setupSingleCallback("#mess_form", () => setupTemplates("mess_form", "mess", null, "chat"));
    }
}

setupMutationObserver("#main", checkUrlAndSetup, {
  childList: true,
  attributes: true,
});

setupMutationObserver("#branch", checkUrlAndSetup, {
  childList: true,
});
}

initializeTemplates();