Ultimate Steam Enhancer

Добавляет множество функций для улучшения взаимодействия с магазином и сообществом (Полный список на странице скрипта)

Install this script?
Author's suggested script

You may also like SteamDB - Sales; Ultimate Enhancer.

Install this script
// ==UserScript==
// @name         Ultimate Steam Enhancer
// @namespace    https://store.steampowered.com/
// @version      2.1.0
// @description  Добавляет множество функций для улучшения взаимодействия с магазином и сообществом (Полный список на странице скрипта)
// @author       0wn3df1x
// @license      MIT
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/15.7.1/nouislider.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-datalabels.min.js
// @match        https://store.steampowered.com/*
// @match        *://*steamcommunity.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceText
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_deleteValue
// @grant        unsafeWindow
// @connect      zoneofgames.ru
// @connect      raw.githubusercontent.com
// @connect      gist.githubusercontent.com
// @connect      store.steampowered.com
// @connect      api.steampowered.com
// @connect      steamcommunity.com
// @connect      shared.cloudflare.steamstatic.com
// @connect      umadb.ro
// @connect      api.github.com
// @connect      howlongtobeat.com
// @connect      vgtimes.ru
// @connect      api.digiseller.com
// @connect      plati.market
// @connect      digiseller.mycdn.ink
// @connect      steambuy.com
// @connect      steammachine.ru
// @connect      playo.ru
// @connect      steampay.com
// @connect      gabestore.ru
// @connect      static.gabestore.ru
// @connect      gamersbase.store
// @connect      coreplatform.blob.core.windows.net
// @connect      cdn-contentprod.azureedge.net
// @connect      cdn-resize.enaza.games
// @connect      cdn-static.enaza.games
// @connect      www.igromagaz.ru
// @connect      gamesforfarm.com
// @connect      shared.fastly.steamstatic.com
// @connect      i.imgur.com
// @connect      zaka-zaka.com
// @connect      images.zaka-zaka.com
// @connect      gamazavr.ru
// @connect      gameray.ru
// @connect      shop.buka.ru
// @connect      upload.wikimedia.org
// @connect      keysforgamers.com
// @connect      api4.ggsel.com
// @connect      ggsel.net
// @connect      cdn.ggsel.com
// @connect      explorer.kupikod.com
// @connect      cdn.jsdelivr.net
// ==/UserScript==


(function() {
    'use strict';

    function makeGMRequest(options) {
        return new Promise((resolve, reject) => {
            options.onload = (response) => {
                if (response.status >= 200 && response.status < 400) {
                    resolve(response);
                } else {
                    reject(new Error(`Запрос не удался, статус ${response.status}: ${options.method} ${options.url}`));
                }
            };
            options.onerror = (err) => reject(new Error(`Сетевая ошибка: ${options.method} ${options.url}. Details: ${JSON.stringify(err)}`));
            options.ontimeout = () => reject(new Error(`Таймаут: ${options.method} ${options.url}`));
            GM_xmlhttpRequest(options);
        });
    }

    function injectPageAndRunModules(responseText) {
        for (let i = 1; i < 99999; i++) {
            window.clearInterval(i);
            window.clearTimeout(i);
        }

        const injectionScript = `
            <script type="text/javascript">
                window.addEventListener('DOMContentLoaded', () => {
                    // Устанавливаем флаг в глобальном объекте window новой страницы
                    window.USE_unlocked_page_ready = true;
                    console.log('[U.S.E. Injected Script] DOMContentLoaded сработал, страница готова.');
                });
            </script>
        `;

        const modifiedResponseText = responseText.replace('</head>', `${injectionScript}</head>`);

        document.open();
        document.write(modifiedResponseText);
        document.close();

        const maxRetries = 40;
        let retries = 0;
        const readyCheckInterval = setInterval(() => {
            if (unsafeWindow.USE_unlocked_page_ready) {
                clearInterval(readyCheckInterval);
                console.log('[U.S.E. Userscript] Обнаружен сигнал готовности от новой страницы. Запускаем модули USE.');
                setTimeout(runUSEModules, 250);
            } else {
                retries++;
                if (retries > maxRetries) {
                    clearInterval(readyCheckInterval);
                    console.error('[U.S.E.] Время ожидания готовности страницы истекло. Пытаюсь запустить модули вслепую...');
                    setTimeout(runUSEModules, 250);
                }
            }
        }, 250);
    }

    async function handleComplexBypass() {
        const appId = window.location.pathname.match(/\/app\/(\d+)/)?.[1];
        if (!appId) {
            console.error('[U.S.E.] Не удалось определить AppID на странице.');
            return;
        }

        document.body.innerHTML = `
            <div style="font-family: 'Motiva Sans', sans-serif; color: #c7d5e0; background-color: #1b2838; text-align: center; padding: 100px 20px; height: 100vh; font-size: 1.8em; line-height: 1.5;">
                <p>Обнаружена региональная блокировка.</p>
                <p>Запускаю многоступенчатый обход...</p>
                <p id="use-unblock-status" style="font-size: 0.8em; color: #8f98a0; margin-top: 20px;"></p>
                <p style="font-size: 0.7em; color: #8f98a0;">(Ultimate Steam Enhancer)</p>
            </div>`;
        const statusElement = document.getElementById('use-unblock-status');

        try {
            statusElement.textContent = 'Шаг 1/3: Получение анонимной сессии...';
            const { sessionid, browserid } = await getAnonymousSession();
            const baseCookies = `sessionid=${sessionid}; browserid=${browserid};`;
            const countryCookie = `steamCountry=US;`;

            statusElement.textContent = 'Шаг 2/3: Проверка страницы...';
            const gamePageUrl = `https://store.steampowered.com/app/${appId}/?cc=us&l=russian`;
            const initialPageResponse = await makeGMRequest({
                method: "GET",
                url: gamePageUrl,
                headers: {
                    'Cookie': `${baseCookies} ${countryCookie}`,
                    'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7'
                 },
                anonymous: true
            });

            const responseText = initialPageResponse.responseText;

            if (responseText.includes('agegate_birthday_selector')) {
                statusElement.textContent = 'Шаг 3/3: Обход возрастного ограничения и загрузка...';

                const ageBypassCookies = `birthtime=631152001; wants_mature_content=1;`;

                const finalPageResponse = await makeGMRequest({
                    method: "GET",
                    url: gamePageUrl,
                    headers: {
                        'Cookie': `${baseCookies} ${countryCookie} ${ageBypassCookies}`,
                        'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7'
                    },
                    anonymous: true
                });

                if (finalPageResponse.responseText.includes('agegate_birthday_selector')) {
                     throw new Error('Не удалось обойти возрастное ограничение с помощью cookie. Возможно, Steam изменил логику.');
                }

                injectPageAndRunModules(finalPageResponse.responseText);
            } else {
                statusElement.textContent = 'Возрастное ограничение не найдено. Загрузка страницы...';
                injectPageAndRunModules(responseText);
            }

        } catch (error) {
            console.error('[U.S.E.] Ошибка в процессе обхода:', error);
            if (statusElement) {
                statusElement.textContent = `Ошибка: ${error.message}`;
                statusElement.style.color = '#ff6961';
            }
        }
    }

    async function getAnonymousSession(retryCount = 0) {
        const MAX_RETRIES = 2;
        console.log(`[U.S.E. Unblocker] Попытка #${retryCount + 1} получения анонимной сессии...`);

        const sessionUrl = 'https://store.steampowered.com/join/?l=russian';

        try {
            const response = await makeGMRequest({
                method: "GET",
                url: sessionUrl,
                headers: {
                    'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7'
                },
                anonymous: true
            });

            const headers = response.responseHeaders;
            const cookies = headers.trim().split(/[\r\n]+/)
                .filter(h => h.toLowerCase().startsWith('set-cookie:'))
                .map(h => h.substring(h.indexOf(':') + 1).trim());

            const sessionid = cookies.find(c => c.startsWith('sessionid='))?.split(';')[0].split('=')[1] || null;
            const browserid = cookies.find(c => c.startsWith('browserid='))?.split(';')[0].split('=')[1] || null;

            if (sessionid && browserid) {
                console.log(`[U.S.E. Unblocker] Успешно получены sessionid=${sessionid}, browserid=${browserid}`);
                return { sessionid, browserid };
            }

            console.warn('[U.S.E. Unblocker] Не удалось получить cookies с текущей попытки. Заголовки ответа:', { headers });

            if (retryCount < MAX_RETRIES) {
                await new Promise(resolve => setTimeout(resolve, 500));
                return getAnonymousSession(retryCount + 1);
            } else {
                throw new Error('Не удалось получить анонимный sessionid/browserid после нескольких попыток.');
            }

        } catch (error) {
            console.error(`[U.S.E. Unblocker] Ошибка при запросе сессии (попытка ${retryCount + 1}):`, error);
            if (retryCount < MAX_RETRIES) {
                await new Promise(resolve => setTimeout(resolve, 500));
                return getAnonymousSession(retryCount + 1);
            }
            throw error instanceof Error ? error : new Error('Не удалось выполнить запрос для получения анонимной сессии.');
        }
    }


    (function unblockerDispatcher() {
        const storedSettings = GM_getValue('useSettings', {});
        const isUnblockerEnabled = storedSettings.regionUnblocker !== false;

        if (isUnblockerEnabled && window.location.pathname.includes('/app/')) {
            const regionLockMessage = 'Данный товар недоступен в вашем регионе';
            const errorBox = document.getElementById('error_box');

            if (errorBox && errorBox.innerText.includes(regionLockMessage)) {
                handleComplexBypass();
                return;
            }
        }

        runUSEModules();
    })();


    function runUSEModules() {
    const scriptsConfig = {
        // Основные скрипты
        regionUnblocker: true,
        gamePage: true, // Скрипт для страницы игры (индикаторы о наличии русского перевода; получение дополнительных обзоров) | https://store.steampowered.com/app/*
        hltbData: true, // Скрипт для страницы игры (HLTB; получение сведений о времени прохождения) | https://store.steampowered.com/app/*
        friendsPlaytime: true, // Скрипт для страницы игры (Время друзей & Достижения) | https://store.steampowered.com/app/*
        earlyaccdata: true, // Скрипт для страницы игры (Ранний доступ) | https://store.steampowered.com/app/*
        zogInfo: true, // Скрипт для страницы игры (ZOG; получение сведение о наличии русификаторов) | https://store.steampowered.com/app/*
        platiSales: true, // Скрипт для страницы игры (Plati; отображение цен с Plati.Market) | https://store.steampowered.com/app/*
        salesMaster: true, // Скрипт для страницы игры (%; агрегатор цен из разных магазинов) | https://store.steampowered.com/app/*
        pageGiftHelper: true, // Скрипт для страницы игры, для проверки возможности отправки подарка друзьям в других странах | https://store.steampowered.com/app/*
        catalogInfo: true, // Скрипт для получения дополнительной информации об игре при наведении на неё на странице поиска по каталогу | https://store.steampowered.com/search/
        catalogHider: false, // Скрипт скрытия игр на странице поиска по каталогу | https://store.steampowered.com/search/
        newsFilter: true, // Скрипт для скрытия новостей в новостном центре: | https://store.steampowered.com/news/
        Kaznachei: true, // Скрипт для показа годовых и исторических продаж предмета на торговой площадке Steam | https://steamcommunity.com/market/listings/*
        homeInfo: true, // Скрипт для получения дополнительной информации об игре при наведении на неё на странице вашей активности Steam | https://steamcommunity.com/my/
        stelicasRoulette: true, //Скрипт для выбора случайной игры из ваших коллекций с помощью Stelicas и рулетки на странице вашей активности Steam | https://steamcommunity.com/my/
        Sledilka: true, // Скрипт для получения уведомлений об изменении дат/статуса игр (вишлист/библиотека) и показа календаря релизов | Глобально
        wishlistGiftHelper: true, // Скрипт для проверки возможности отправки подарка из списка желаемого друзьям в других странах | https://steamcommunity.com/my/wishlist/
        RuRegionalPriceAnalyzer: true, // Скрипт для страницы игры (Анализатор цен; цена РФ vs рекомендованная; рейтинг цен) | https://store.steampowered.com/app/*
        // Дополнительные настройки
        autoExpandHltb: false, // Автоматически раскрывать спойлер HLTB
        autoLoadReviews: false, // Автоматически загружать дополнительные обзоры
        toggleEnglishLangInfo: false // Отображает данные об английском языке в дополнительной информации при поиске по каталогу и в активности (функция для переводчиков)
    };


    /* --- Код для настроек U.S.E. --- */
    const useDefaultSettings = {
        regionUnblocker: true, gamePage: true, hltbData: true, friendsPlaytime: true, earlyaccdata: true, zogInfo: true, pageGiftHelper: true,
        platiSales: true, salesMaster: true, catalogInfo: true, catalogHider: false, newsFilter: true,
        Kaznachei: true, homeInfo: true, Sledilka: true, wishlistGiftHelper: true, stelicasRoulette: true, RuRegionalPriceAnalyzer: true,
        autoExpandHltb: false, autoLoadReviews: false, toggleEnglishLangInfo: false
    };

    const dependentModules = {
        gamePage: ['hltbData', 'zogInfo', 'friendsPlaytime']
    };

    let useCurrentSettings = { ...useDefaultSettings, ...GM_getValue('useSettings', {}) };

    Object.assign(scriptsConfig, useCurrentSettings);

    // --- Данные для настроек: метки, заголовки, описания и категории ---
    const settingInfo = {
        // --- Страница игры ---
        gamePage: {
            category: 'gamePage',
            label: "Индикаторы / Доп. обзоры / Монитор обзоров",
            title: "Индикаторы перевода, доп. обзоры и глобальный монитор обзоров",
            details: `
                <p><strong>Что делает:</strong></p>
                <ol style="margin-left: 20px; padding-left: 5px; list-style-type: decimal;">
                    <li style="margin-bottom: 0.7em;">Отображает значки-индикаторы наличия русского языка (интерфейс, озвучка, субтитры) прямо на странице игры.</li>
                    <li style="margin-bottom: 0.7em;">Добавляет под стандартными обзорами блок с расширенной статистикой (загружается по щелчку или автоматически, если включена опция):
                        <ul>
                            <li><strong>Тотальные:</strong> Все обзоры Steam (включая активации ключами).</li>
                            <li><strong>Безкитайские:</strong> Обзоры за исключением написанных на китайском языке.</li>
                            <li><strong>Русские:</strong> Только обзоры на русском языке.</li>
                        </ul>
                    </li>
                    <img src="https://i.imgur.com/fcdZh8b.png" alt="Пример индикаторов и обзоров 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                    <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                    <li style="margin-bottom: 0.7em;">Модальные окна:
                        <ul>
                             <li>При щелчке по строке "Русские" открывается окно с актуальными <strong>русскоязычными обзорами</strong> для этой игры.</li>
                             <img src="https://i.imgur.com/MOEyAlM.png" alt="Пример индикаторов и обзоров 2" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                             <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                             <li>При щелчке по строке "Тотальные" открывается окно <strong>"Глобальный монитор обзоров"</strong>. Этот инструмент позволяет собрать (по кнопке "Собрать") и визуализировать статистику обзоров по <strong>27 языкам</strong> Steam. Он показывает таблицу с рейтингом языков по количеству обзоров и доле в общей массе, а также интерактивную круговую диаграмму для наглядного представления.</li>
                             <img src="https://i.imgur.com/2azVyAW.png" alt="Пример индикаторов и обзоров 3" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                        </ul>
                    </li>
                </ol>
                <div style="margin-top: 15px; margin-bottom: 10px; padding: 10px; background-color: rgba(255, 179, 0, 0.1); border: 1px solid rgba(255, 179, 0, 0.4); border-radius: 4px; font-size: 0.95em; line-height: 1.4;">
                    <p style="margin: 0 0 5px 0; font-weight: bold; color: #FFB300;">⚠️ Важное замечание о зависимостях:</p>
                    <p style="margin: 0; color: #c6d4df;">Отключение этого модуля приведет к автоматическому отключению или нарушению корректной работы модулей «Время прохождения (HLTB)», «Русификаторы (ZOG)» и «Время друзей / Глобальные достижения», так как они критически зависят от его функционала по отображению элементов на странице игры.</p>
                </div>
            `
        },
        RuRegionalPriceAnalyzer: {
            category: 'gamePage',
            label: "Анализатор цен",
            title: "Анализатор цен",
            details: `
                <p><strong>Что делает:</strong> Добавляет кнопку "Анализатор цен" на страницу игры. Этот инструмент позволяет анализировать региональные цены двумя способами: в рублях (по умолчанию) и в долларах США.</p>

                <p>После нажатия кнопки "Сбор данных" в специальном окне, модуль выполняет следующее в зависимости от выбранного режима:</p>

                <div style="display: flex; gap: 20px; margin-top:10px; margin-bottom:10px;">
                    <div style="flex: 1; padding:10px; background-color: rgba(0,0,0,0.1); border-radius:4px;">
                        <h4 style="margin-top:0; color: #67c1f5;">Режим Рублей (по умолчанию):</h4>
                        <ul>
                            <li>Определяет AppID текущей игры и запрашивает цены через официальное API Steam (<code>IStoreBrowseService/GetItems</code>) для множества регионов.</li>
                            <li>В качестве базы для расчета <strong>рекомендованной рублевой цены</strong> используется цена в США (USD).</li>
                            <li>Цены из всех регионов, включая Россию, <strong>конвертируются в рубли</strong> по актуальным обменным курсам для прямого сопоставления.</li>
                            <li>Производится ключевое сравнение: фактическая цена в российском Steam сопоставляется с <strong>официально рекомендованной Valve ценой для России</strong>. Отклонения подсвечиваются.</li>
                            <li>Отображается <strong>рейтинг российской цены</strong> среди всех проанализированных стран, позволяя увидеть её место от самой дешёвой к самой дорогой в рублевом эквиваленте.</li>
                        </ul>
                    </div>
                    <div style="flex: 1; padding:10px; background-color: rgba(0,0,0,0.1); border-radius:4px;">
                        <h4 style="margin-top:0; color: #67c1f5;">Режим Долларов США (переключаемый):</h4>
                        <ul>
                            <li>Активируется кнопкой "USD" в окне анализатора. Интерфейс и названия валют <strong>переключаются на английский язык</strong>.</li>
                            <li>Цены всех регионов также запрашиваются через API Steam и <strong>конвертируются в доллары США</strong>.</li>
                            <li>Цена в США используется как <strong>базовый ориентир (100%)</strong> для сравнения.</li>
                            <li>Отображается <strong>процентное отклонение</strong> цен других регионов от цены в США.</li>
                            <li>Представляется общий рейтинг всех региональных цен в долларовом эквиваленте.</li>
                            <li>Этот режим полезен для оценки ценовой политики при общении с разработчиками/издателями.</li>
                        </ul>
                    </div>
                </div>

                <p>В обоих режимах, если игра в США бесплатна или цена не найдена, возможности анализа могут быть ограничены. Вся собранная информация представляется в модальном окне.</p>

                <div style="margin-top: 15px; padding: 10px; background-color: rgba(103, 193, 245, 0.1); border: 1px solid rgba(103, 193, 245, 0.35); border-radius: 4px; font-size: 0.95em; line-height: 1.4;">
                    <p style="margin: 0 0 5px 0; font-weight: bold; color: #67c1f5;">⚠️ Важная информация:</p>
                    <p style="margin: 0; color: #c6d4df;">Каждый полный сбор данных подразумевает отправку <strong>~41 запроса</strong> к серверам Steam (количество зависит от числа доступных регионов). Пожалуйста, используйте эту функцию обдуманно. Частое нажатие кнопки на разных играх в течение короткого периода времени может привести к временному ограничению доступа к API Steam (обычно на 5-15 минут).</p>
                </div>
                <img src="https://i.imgur.com/OzebvaA.png" alt="Пример интерфейса анализатора цен" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
        hltbData: {
            category: 'gamePage',
            label: "Время прохождения (HLTB)",
            title: "Время прохождения HLTB",
            details: `
                <p><strong>Что делает:</strong> Добавляет компактный блок с информацией о времени прохождения игры, полученной с популярного сайта HowLongToBeat.com.</p>
                <p>Показывает среднее время для разных стилей:</p>
                <ul>
                    <li>Только основной сюжет.</li>
                    <li>Сюжет + дополнительные задания.</li>
                    <li>Полное прохождение (100%).</li>
                    <li>Усредненное время для всех стилей.</li>
                </ul>
                <p>Рядом со временем указывается количество игроков, на чьих данных основана статистика. Поиск игры в базе HLTB идет по названию, при неоднозначности предлагается выбор из похожих вариантов.</p>
                <img src="https://i.imgur.com/6tgxA2s.png" alt="Пример HLTB 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
        platiSales: {
            category: 'gamePage',
            label: "Поиск цен Plati.Market",
            title: "Поиск цен на Plati.Market",
            details: `
                <p><strong>Что делает:</strong> Добавляет кнопку "Plati" рядом с кнопкой "В желаемое" на странице игры. Нажатие открывает полноэкранное окно для поиска предложений по этой игре на торговой площадке Plati.Market.</p>
                <p><strong>Возможности окна поиска:</strong></p>
                <ul>
                    <li>Автозаполнение поиска названием текущей игры.</li>
                    <li>Ручной ввод и поиск.</li>
                    <li>Подсказки при вводе (API Plati).</li>
                    <li>Сортировка по цене, продажам, релевантности, названию, дате, рейтингу продавца и др.</li>
                    <li>Фильтрация по цене (RUR, USD, EUR, UAH), продажам, рейтингу, наличию плохих отзывов/возвратов, участию в скидках, дате добавления.</li>
                    <li>Исключение товаров по ключевым словам (панель справа).</li>
                    <li>Сохранение фильтров, сортировки, валюты и исключений.</li>
                </ul>
                 <p>Используются официальные API Plati.Market.</p>
               <img src="https://i.imgur.com/lyL8i5g.png" alt="Кнопка Plati" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                <img src="https://i.imgur.com/j1TGmY8.png" alt="Окно Plati" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
        zogInfo: {
            category: 'gamePage',
            label: "Русификаторы (ZOG)",
            title: "Информация о наличии переводов с ZOG (ZoneOfGames)",
            details: `
                <p><strong>Что делает:</strong> Добавляет блок с информацией о наличии русификаторов для игры на сайте ZoneOfGames.ru.</p>
                <p>В блоке отображается:</p>
                <ul>
                    <li>Название игры (ведет на страницу игры в базе ZOG).</li>
                    <li>Список доступных русификаторов. Каждая запись является ссылкой на соответствующий файл/страницу на ZOG.</li>
                    <li>Если переводы не найдены, выводится соответствующее сообщение.</li>
                </ul>
                <p>Поиск происходит в <strong>реальном времени</strong>. Скрипт автоматически определяет название игры, выполняет поиск по алфавитному указателю на ZoneOfGames.ru и предлагает вам выбрать наиболее точное совпадение.</p>
                <img src="https://i.imgur.com/XgAVWAp.png" alt="Пример ZOG 21" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
        salesMaster: {
            category: 'gamePage',
            label: "Агрегатор цен (%)",
            title: "Агрегатор цен (%)",
            details: `
                <p><strong>Что делает:</strong> Добавляет кнопку "%" рядом с кнопкой "В желаемое" на странице игры. Нажатие открывает модальное окно с ценами на эту игру из различных цифровых магазинов.</p>
                <p><strong>Возможности окна агрегатора:</strong></p>
                <ul>
                    <li>Отображение предложений из магазинов: SteamBuy, Playo, SteamPay, Gabestore, GamersBase, Igromagaz, GamesForFarm, Gamazavr, GameRay, KupiKod, KeysForGamers, Zaka-zaka, Buka, GGSEL, Plati.Market и текущей страницы Steam.</li>
                    <li>Переключение валют: Возможность просмотра всех цен в рублях (RUB, по умолчанию) или в долларах США (USD), с автоматической конвертацией по актуальному курсу. Выбор валюты сохраняется.</li>
                    <li>Сортировка по цене, проценту скидки, сумме скидки, названию.</li>
                    <li>Фильтрация по диапазону цен, проценту и сумме скидки, наличию скидки, названию (слова через ";"), магазинам.</li>
                    <li>Исключение товаров по ключевым словам.</li>
                    <li>Сохранение состояния фильтров, сортировки и исключений.</li>
                </ul>
                 <p>Использует различные методы для получения цен (API, парсинг HTML).</p>
                <img src="https://i.imgur.com/PsrocCt.png" alt="Пример Агрегатора 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                <img src="https://i.imgur.com/DcidcTe.png" alt="Пример Агрегатора 2" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
        friendsPlaytime: {
            category: 'gamePage',
            label: "Время друзей / Глобальные достижения",
            title: "Информация о времени друзей и статистике достижений",
            details: `
                <p><strong>Что делает:</strong> Добавляет на страницу игры два независимых блока, расширяющих информацию о действиях ваших друзей и глобальной статистике достижений.</p>

                <h4 style="color: #67c1f5; border-bottom: 1px solid #444a52; padding-bottom: 5px; margin-top: 20px;">1. Плавающий блок статистики (у шапки игры)</h4>
                <p>Справа от изображения игры появляется компактный значок, при нажатии на который загружается и отображается сводная статистика:</p>
                <div style="display: flex; gap: 20px; margin-top:10px; margin-bottom:10px;">
                    <div style="flex: 1;">
                        <p><strong>Время друзей:</strong></p>
                        <ul>
                            <li>Максимальное время в игре (и ник друга со ссылкой).</li>
                            <li>Среднее время (с указанием кол-ва друзей).</li>
                            <li>Минимальное время в игре.</li>
                        </ul>
                    </div>
                    <div style="flex: 1;">
                        <p><strong>Глобальные достижения:</strong></p>
                        <ul>
                            <li>Процент "платины" (самое редкое достижение).</li>
                            <li>Средний прогресс выполнения всех достижений.</li>
                        </ul>
                    </div>
                </div>
                <img src="https://i.imgur.com/9TaMCbZ.png" alt="Пример Время друзей / Ачивки" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">

                <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">

                <h4 style="color: #67c1f5; border-bottom: 1px solid #444a52; padding-bottom: 5px; margin-top: 20px;">2. Информационный блок друзей (в правой колонке)</h4>
                <div style="margin-top: 10px; margin-bottom: 15px; padding: 10px; background-color: rgba(255, 179, 0, 0.1); border: 1px solid rgba(255, 179, 0, 0.4); border-radius: 4px; font-size: 0.95em; line-height: 1.4;">
                    <p style="margin: 0 0 5px 0; font-weight: bold; color: #FFB300;">⚠️ Важное примечание:</p>
                    <p style="margin: 0; color: #c6d4df;">Этот блок появляется только в том случае, если Steam не отображает на странице стандартный блок с рекомендациями друзей (например, на страницах, открытых с помощью виртуального режима инкогнито).</p>
                </div>
                <p>Скрипт добавляет в правую колонку подробный список друзей, взаимодействовавших с игрой, сгруппированный по категориям:</p>
                <ul>
                    <li>Друзья, игравшие недавно (за последние 2 недели).</li>
                    <li>Все друзья, когда-либо игравшие в игру (объединяет недавних и игравших ранее).</li>
                    <li>Все друзья, имеющие игру в библиотеке.</li>
                    <li>Друзья, которые добавили игру в свой список желаемого.</li>
                </ul>
                <p>Каждая категория сопровождается сеткой из шести аватаров друзей со ссылками на их профили.</p>
                <img src="https://i.imgur.com/6jbZ03L.png" alt="Пример" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
        pageGiftHelper: {
            category: 'gamePage',
            label: "Доступность подарков (страница игры)",
            title: "Доступность подарков (страница игры)",
            details: `
                <p><strong>Что делает:</strong> Добавляет кнопку "GIFT" в блок с кнопкой "В желаемое" на странице игры.</p>
                <p>Нажатие открывает окно, где можно:</p>
                <ul>
                    <li>Выбрать регион друга из списка.</li>
                    <li>Нажать "Узнать", чтобы запросить цену игры в этом регионе.</li>
                    <li>Увидеть цену друга (сконвертированную в вашу валюту), процент разницы и вердикт (<span style="color:#77dd77; font-weight:bold;">Можно подарить</span> / <span style="color:#ff6961; font-weight:bold;">Нельзя подарить</span>), основанный на правилах Steam о разнице цен (±10%).</li>
                </ul>
                <p>Использует те же механизмы получения цен и курсов валют, что и помощник для списка желаемого.</p>
                 <img src="https://i.imgur.com/jDdf4pR.png" alt="Пример PageGiftHelper 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                `
        },
        earlyaccdata: {
            category: 'gamePage',
            label: "Индикатор раннего доступа",
            title: "Индикатор раннего доступа",
            details: `
                <p><strong>Что делает:</strong> Показывает небольшую плашку над изображением игры с информацией о статусе раннего доступа (Early Access).</p>
                <ul>
                    <li><strong>Если игра еще в раннем доступе:</strong> Отображается, сколько времени игра уже находится в нем (например, "В раннем доступе уже 1 год и 3 месяца").</li>
                    <img src="https://i.imgur.com/6iGlcTf.png" alt="Пример Раннего Доступа 2" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                    <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                    <li><strong>Если игра вышла из раннего доступа:</strong> Отображается, сколько времени игра провела в нем до релиза (например, "Вышла спустя 2 года раннего доступа").</li>
                    <img src="https://i.imgur.com/SPzJrpi.png" alt="Пример Раннего Доступа 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                </ul>
                <p>Расчет времени динамический. Использует даты со страницы Steam, а также может подтягивать дату старта раннего доступа из собственной базы для вышедших игр, если Steam ее не показывает.</p>
            `
        },

        // --- Каталог ---
        catalogInfo: {
            category: 'catalog',
            label: "Доп. инфо / Фильтры",
            title: "Дополнительная информация и фильтрация в каталоге поиска",
            details: `
                <p><strong>Что делает:</strong> Расширяет функционал страницы поиска по каталогу Steam (<a href="https://store.steampowered.com/search/" target="_blank" style="color:#67c1f5;">store.steampowered.com/search/</a>).</p>
                <p><strong>При наведении:</strong></p>
                <ul>
                    <li>Появляется всплывающая подсказка слева от строки игры с подробной информацией: издатели, разработчики, серия, отзывы (% и кол-во), статус раннего доступа, поддержка русского/английского языков, первые 5 меток, краткое описание.</li>
                    <img src="https://i.imgur.com/U7DYIvJ.png" alt="Пример Доп. Инфо" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                </ul>
                <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                <p><strong>Фильтры (панель справа):</strong></p>
                <ul>
                    <li><strong>Русский перевод:</strong>
                        <ul>
                            <li><em>Только текст:</em> Игры с рус. интерфейсом/субтитрами (без озвучки).</li>
                            <li><em>Озвучка:</em> Игры с русской озвучкой.</li>
                            <li><em>Без перевода:</em> Игры без русского языка.</li>
                        </ul>
                    <img src="https://i.imgur.com/nLfsBzR.png" alt="Пример Фильтра Языка" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                    </li>
                    <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                     <li><strong>DLC:</strong>
                        <ul>
                            <li><em>Только ваши DLC:</em> Показывает только DLC для игр, которые есть в вашей библиотеке (сами DLC подсвечиваются фиолетовым фоном).</li>
                        </ul>
                    </li>
                    <img src="https://i.imgur.com/MqjuXoD.png" alt="Пример Фильтра DLC" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                </ul>
                 <p>Фильтры применяются динамически по мере получения данных от API.</p>
            `
        },
        catalogHider: {
            category: 'catalog',
            label: "Скрытие игр",
            title: "Система скрытия игр в каталоге поиска",
            details: `
                <p><strong>Что делает:</strong> Добавляет инструменты для массового скрытия неинтересующих игр прямо со страницы поиска по каталогу.</p>
                <p><strong>Элементы интерфейса:</strong></p>
                <ul>
                    <li>Счетчик отображаемых игр (слева вверху).</li>
                    <li>Чекбокс слева от каждой игры (кроме уже купленных/скрытых/в желаемом) для отметки на скрытие.</li>
                    <li>Кнопка "Скрыть выбранное" (слева вверху).</li>
                </ul>
                <p><strong>Принцип работы:</strong></p>
                <ol>
                    <li>Отмечаете чекбоксами игры, которые хотите скрыть.</li>
                    <li>Нажимаете "Скрыть выбранное".</li>
                    <li>Скрипт добавляет эти игры в ваш официальный список игнорируемых в Steam и удаляет их элементы со страницы.</li>
                </ol>
                <p>В отличие от стандартного механизма Steam, элементы полностью удаляются из DOM, что улучшает производительность при работе с большим количеством результатов.</p>
                <p><strong>Внимание:</strong> Рекомендуется использовать только при необходимости массового скрытия. Для обычного просмотра каталога лучше отключать эту опцию.</p>
                <img src="https://i.imgur.com/uCA8x2P.png" alt="Пример Скрытия Игр" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
         // --- Сообщество / Активность ---
        homeInfo: {
            category: 'community',
            label: "Доп. инфо в ленте активности",
            title: "Дополнительная информация в ленте активности Steam",
            details: `
                <p><strong>Что делает:</strong> Добавляет всплывающую подсказку при наведении на название игры в вашей ленте активности Steam (<a href="https://steamcommunity.com/my/home" target="_blank" style="color:#67c1f5;">steamcommunity.com/my/home</a>).</p>
                <p>Подсказка содержит подробную информацию об игре, аналогичную той, что показывается в каталоге поиска:</p>
                <ul>
                    <li>Название и изображение-шапка.</li>
                    <li>Дата выхода.</li>
                    <li>Издатели, разработчики, серия игр.</li>
                    <li>Отзывы (% и кол-во).</li>
                    <li>Статус раннего доступа.</li>
                    <li>Поддержка русского и английского языков.</li>
                    <li>Первые 5 меток.</li>
                    <li>Краткое описание.</li>
                </ul>
                 <p>Данные загружаются через API Steam.</p>
                 <img src="https://i.imgur.com/xE75iU8.png" alt="Пример Инфо в Ленте" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
           `
        },
        stelicasRoulette: {
            category: 'community',
            label: "Рулетка Stelicas",
            title: "Рулетка Stelicas - Случайный выбор игры из ваших коллекций",
            details: `
                <p><strong>Что делает:</strong> Добавляет блок "Рулетка Stelicas" на страницу вашей активности Steam (<a href="https://steamcommunity.com/my/home" target="_blank" style="color:#67c1f5;">steamcommunity.com/my/home</a>). Позволяет загрузить CSV-файл, сгенерированный приложением <a href="https://github.com/0wn3dg0d/Stelicas" target="_blank" style="color:#67c1f5;">Stelicas</a>, применить к нему разнообразные фильтры и случайным образом выбрать игру из вашей коллекции.</p>
                <p><strong>Возможности:</strong></p>
                <ul style="margin-left: 20px; padding-left: 5px; list-style-type: disc;">
                    <li style="margin-bottom: 0.5em;">Загрузка CSV-данных из Stelicas (содержащих информацию о ваших играх и коллекциях).</li>
                    <li style="margin-bottom: 0.5em;"><strong>Система фильтрации:</strong> по категориям коллекций Stelicas, дате выхода, пользовательским тегам, поддержке русского языка (интерфейс, субтитры, озвучка), а также по диапазонам количества отзывов и общего рейтинга игры.</li>
                    <li style="margin-bottom: 0.5em;">Анимированная рулетка для выбора случайной игры из отфильтрованного списка.</li>
                    <li style="margin-bottom: 0.5em;">Возможность включить приоритет по отзывам и рейтингу, чтобы игры с лучшими показателями имели больше шансов на выпадение.</li>
                    <li style="margin-bottom: 0.5em;">Переключение в режим <strong>просмотра всей отфильтрованной подборки</strong> игр в виде удобных карточек (изображение и название).</li>
                    <li style="margin-bottom: 0.5em;">Отображение подробной информации о выбранной (или просматриваемой в подборке) игре: постер, название, рейтинг и количество отзывов, краткое описание, основные теги, точная дата выхода, разработчики/издатели, информация о поддержке русского языка.</li>
                    <li style="margin-bottom: 0.5em;">Прямые ссылки на страницу игры в сообществе Steam и для её запуска через протокол <code>steam://run/&lt;AppID&gt;</code>.</li>
                </ul>
                <p><strong>Как пользоваться:</strong></p>
                <ul style="margin-left: 20px; padding-left: 5px; list-style-type: disc;">
                    <li style="margin-bottom: 0.5em;">Подробная инструкция по подготовке CSV-файла и использованию всех функций рулетки доступна по нажатию на значок вопроса <strong>?</strong> в правом верхнем углу окна самой рулетки.</li>
                </ul>
                <p><em>Примечание: Качество работы и полнота информации в рулетке напрямую зависят от корректности и актуальности данных в предоставленном CSV-файле из Stelicas.</em></p>
                <img src="https://i.imgur.com/KDfW10m.png" alt="Пример модального окна Рулетки Stelicas с фильтрами" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333; border-radius: 4px;">
            `
        },
        // --- Торговая площадка ---
        Kaznachei: {
            category: 'market',
            label: "Продажи предмета",
            title: "Информация об исторических продажах на торговой площадке Steam",
            details: `
                <p><strong>Что делает:</strong> Добавляет информационный блок на страницу предмета на торговой площадке Steam (<a href="https://steamcommunity.com/market/" target="_blank" style="color:#67c1f5;">steamcommunity.com/market/</a>).</p>
                <p>Блок содержит:</p>
                <ul>
                    <li>Таблицу с историей продаж по годам:
                        <ul>
                            <li>Общая сумма продаж за год (в рублях).</li>
                            <li>Примерная сумма, полученная разработчиком игры.</li>
                            <li>Примерная сумма, полученная Valve.</li>
                        </ul>
                    </li>
                    <li>Итоговую сумму продаж за все время.</li>
                    <li>Итоговые суммы, полученные разработчиком и Valve.</li>
                </ul>
                 <p>Данные загружаются через API истории цен Steam.</p>
                <img src="https://i.imgur.com/ZPnzyNH.png" alt="Пример Продаж 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
            `
        },
         // --- Новости / Список желаемого ---
        Sledilka: {
            category: 'news_wishlist',
            label: "Наблюдатель (Желаемое/Библиотека)",
            title: "Наблюдатель: Отслеживание изменений в списке желаемого и библиотеке",
            details: `
                <p><strong>Что делает:</strong> Отслеживает изменения в вашем списке желаемого Steam и в вашей библиотеке игр, отображает календарь релизов.</p>
                <p><strong>Основные функции:</strong></p>
                <ol style="margin-left: 20px; padding-left: 5px; list-style-type: decimal;">
                    <li style="margin-bottom: 0.7em;">В правом верхнем углу страниц Steam появляется кнопка "Наблюдатель".</li>
                    <li style="margin-bottom: 0.7em;"><strong>Индикаторы статуса (Ж/Б):</strong> Показывают, как давно обновлялись данные для <strong>Ж</strong>елаемого и <strong>Б</strong>иблиотеки.</li>
                    <li style="margin-bottom: 0.7em;"><strong>Счетчик уведомлений:</strong> Показывает количество новых (непрочитанных) изменений.</li>
                    <li style="margin-bottom: 0.7em;"><strong>Панель уведомлений (по щелчку на кнопку):</strong>
                        <ul style="margin-top: 0.8em; margin-left: 15px; list-style-type: disc;">
                            <li style="margin-bottom: 0.5em;">Кнопка "Обновить" для ручного запуска проверки (использует Steam API).</li>
                            <li style="margin-bottom: 0.5em;"><strong>Настройки (значок ⚙️):</strong> Открывает выпадающее меню с опциями:
                                <ul style="margin-top: 0.5em; margin-left: 15px; list-style-type: square;">
                                    <li style="margin-bottom: 0.3em;"><strong>Список желаемого / Библиотека:</strong> Позволяют включать/отключать проверку для каждой из секций.</li>
                                    <li style="margin-bottom: 0.3em;"><strong>Перепроверять игры с русским:</strong> <em>(Опция для Библиотеки)</em>. По умолчанию включена. Если её <strong>отключить</strong>, скрипт пропустит проверку игр, для которых уже известно о наличии <strong>любой</strong> русской локализации. Это значительно ускоряет повторные обновления.</li>
                                    <li style="margin-bottom: 0.3em;"><strong>...только без полной локализации:</strong> <em>(Доступна, если предыдущая опция отключена)</em>. Если включить, то из повторной проверки будут исключаться только игры с <strong>полной</strong> локализацией (интерфейс+озвучка+субтитры). Игры с частичным переводом продолжат проверяться.</li>
                                </ul>
                            </li>
                            <li style="margin-bottom: 0.5em;">Список изменений:
                                <ul style="margin-top: 0.5em; margin-left: 15px; list-style-type: square;">
                                    <li style="margin-bottom: 0.3em;"><strong>Список желаемого:</strong> Изменение даты выхода, статуса раннего доступа или русского языка.</li>
                                    <li style="margin-bottom: 0.3em;"><strong>Библиотека:</strong> Выход игры из раннего доступа, появление/изменение русского языка (и тип локализации).</li>
                                </ul>
                            </li>
                            <li style="margin-bottom: 0.5em;">Кнопки для отметки уведомления как прочитанного (конверт) или удаления (крестик).</li>
                            <li style="margin-bottom: 0.5em;">Кнопка "Очистить" для удаления всех уведомлений.</li>
                            <li style="margin-bottom: 0.5em;">Кнопка "Календарь".</li>
                            <li style="margin-bottom: 0.5em;">Кнопка "Хранилище" для очистки сохраненных данных.</li>
                        </ul>
                     </li>
                     <img src="https://i.imgur.com/BpuDq6U.png" alt="Пример Трекера 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                     <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                     <li style="margin-bottom: 0.7em;"><strong>Календарь релизов (по щелчку на кнопку "Календарь"):</strong>
                        <ul style="margin-top: 0.8em; margin-left: 15px; list-style-type: disc;">
                            <li style="margin-bottom: 0.5em;">Отображает игры из вашего списка желаемого в виде календаря по месяцам.</li>
                            <li style="margin-bottom: 0.5em;">Показывает игры с точными датами выхода в будущем.</li>
                            <li style="margin-bottom: 0.5em;">Для игр с примерной датой (месяц, квартал, год) отображается подсказка при наведении.</li>
                            <li style="margin-bottom: 0.5em;">Позволяет подгружать следующие месяцы.</li>
                        </ul>
                     </li>
                     <img src="https://i.imgur.com/b5PDYG3.png" alt="Пример Календаря" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                     <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                      <li style="margin-bottom: 0.7em;"><strong>Хранилище (по щелчку на кнопку "Хранилище"):</strong>
                        <ul style="margin-top: 0.8em; margin-left: 15px; list-style-type: disc;">
                            <li style="margin-bottom: 0.5em;">Позволяет очистить кэш дат/статусов для списка желаемого или для игр библиотеки.</li>
                        </ul>
                     </li>
                     <img src="https://i.imgur.com/nI6Uoo0.png" alt="Пример Хранилища" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                </ol>
                <p>Требует авторизации. Обработка больших списков/библиотек может занять время. Используйте новые опции в настройках для ускорения сканирования библиотеки.</p>
            `
        },
        newsFilter: {
            category: 'news_wishlist',
            label: "Фильтр новостей",
            title: "Система скрытия новостей в новостном центре",
            details: `
                <p><strong>Что делает:</strong> Позволяет гибко управлять отображением новостей в новостном центре Steam (<a href="https://store.steampowered.com/news/" target="_blank" style="color:#67c1f5;">store.steampowered.com/news/</a>), скрывая неинтересные материалы.</p>
                <p><strong>Основные возможности и использование:</strong></p>
                <ol style="margin-left: 20px; padding-left: 5px; list-style-type: decimal;">
                    <li style="margin-bottom: 0.7em;">
                        <strong>Выбор новостей для скрытия:</strong>
                        <ul>
                            <li>На каждой новости в правой части изображения появляется крупный квадратный чекбокс.</li>
                            <li>При установке галочки новость становится полупрозрачной (<em>"мягкое" скрытие</em>) и отмечается для последующего подтверждения скрытия. Повторный щелчок снимает отметку.</li>
                        </ul>
                    </li>
                    <li style="margin-bottom: 0.7em;">
                        <strong>Панель управления (справа вверху):</strong>
                        <ul>
                            <li><strong>"Скрыть выбранные (X)":</strong> Нажатие этой кнопки перемещает все отмеченные (полупрозрачные) новости в постоянное хранилище. Новость исчезает с экрана (или становится затемненной, если включен режим "Показать скрытое"). Счетчик в скобках показывает, сколько новостей сейчас выбрано.</li>
                            <li><strong>"В хранилище: X":</strong> Эта надпись показывает общее количество новостей, находящихся в вашем постоянном хранилище скрытых новостей.</li>
                            <li><strong>"Отменить":</strong> Появляется после подтверждения скрытия и активна 6 секунд. Позволяет отменить последнее действие по добавлению новостей в хранилище.</li>
                            <li><strong>"Показать скрытое" / "Спрятать скрытое":</strong> Переключатель. Если выбрано "Показать скрытое", новости из вашего хранилища будут отображаться в ленте, но в затемненном виде. В режиме "Спрятать скрытое" они полностью исчезают.</li>
                            <li><strong>"Хранилище":</strong> Открывает модальное окно для управления списком постоянно скрытых новостей.</li>
                        </ul>
                    </li>
                <img src="https://i.imgur.com/iYTtyWk.png" alt="Пример интерфейса фильтра новостей" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                     <hr style="border: none; border-top: 1px solid #444a52; margin: 1.5em 0;">
                    <li style="margin-bottom: 0.7em;">
                        <strong>Панель "Хранилище скрытых новостей":</strong>
                        <ul>
                            <li>Отображает список всех новостей, добавленных в постоянное хранилище. Для каждой записи указывается название игры, заголовок новости и ее AppID.</li>
                            <li><strong>"Вернуть":</strong> Кнопка напротив каждой записи позволяет удалить новость из хранилища и немедленно отобразить ее в ленте (если она еще присутствует в DOM). Чекбокс на этой новости также снова станет активным.</li>
                            <li><strong>"Очистить хранилище":</strong> Удаляет все новости из вашего списка постоянно скрытых. Требует подтверждения.</li>
                            <li><strong>"Закрыть":</strong> Закрывает панель хранилища.</li>
                            <img src="https://i.imgur.com/T5pUb9a.png" alt="Пример интерфейса хранилища" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">
                        </ul>
                    </li>
                </ol>
            `
        },
        wishlistGiftHelper: {
            category: 'news_wishlist',
            label: "Доступность подарков (список желаемого)",
            title: "Доступность подарков (список желаемого)",
            details: `
                <p><strong>Что делает:</strong> Добавляет кнопку со значком лупы <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14" fill="currentColor" style="vertical-align: middle;"><path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></svg> на страницу списка желаемого, позволяющую определить, какие игры можно подарить друзьям в других регионах.</p>
                <p><strong>Основные функции:</strong></p>
                <ul>
                    <li>Загружает игры из отображаемого списка желаемого и выводит их в виде информативных карточек с возможностью сортировки.</li>
                    <li>Активирует режим <strong>помощника подарков</strong>:
                        <ul>
                            <li>Вы выбираете регион вашего друга.</li>
                            <li>Скрипт запрашивает цены на игры из списка желаемого для выбранного региона.</li>
                            <li>Цены друга конвертируются в вашу валюту (используется API курсов валют).</li>
                            <li>Отображается <strong>разница в цене</strong> между вашим регионом и регионом друга (с цветовой индикацией: <span style="color:#77dd77; font-weight:bold;">зелёный</span> - можно дарить (разница до ±10%), <span style="color:#ff6961; font-weight:bold;">красный</span> - нельзя).</li>
                            <li>Доступен фильтр <strong>"Можно подарить"</strong>, который показывает только те игры, у которых разница в цене до ±10% и которые Steam разрешает покупать в подарок.</li>
                        </ul>
                    </li>
                </ul>
                 <p>Это помогает легко найти подходящие и экономически целесообразные подарки для друзей за границей.</p>
                 <p><i><small>*Примечание: Скорость загрузки данных зависит от размера списка желаемого.</small></i></p>
                 <img src="https://i.imgur.com/WPbhyPI.png" alt="Пример WishlistGiftHelper 1" style="max-width: 90%; height: auto; margin-top: 10px; display: block; margin-left: auto; margin-right: auto; border: 1px solid #333;">`
        },
        // --- Дополнительные ---
        autoExpandHltb: {
            category: 'additional',
            label: "Авто-раскрытие HLTB",
            title: "Автоматически раскрывать спойлер HLTB",
            details: "<p>Если включено, блок с информацией о времени прохождения (HLTB) на странице игры будет автоматически раскрываться при загрузке страницы (если основной модуль HLTB включен).</p><p>Удобно, если вы всегда хотите видеть эту информацию без лишнего щелчка.</p>"
        },
        autoLoadReviews: {
            category: 'additional',
            label: "Авто-загрузка доп. обзоров",
            title: "Автоматически загружать дополнительные обзоры",
            details: "<p>Если включено, блок с дополнительными обзорами (Тотальные, Безкитайские, Русские) на странице игры будет загружаться автоматически при загрузке страницы (если основной модуль 'Индикаторы/Обзоры' включен).</p><p>Экономит щелчок, если вам всегда нужна эта статистика.</p>"
        },
        toggleEnglishLangInfo: {
            category: 'additional',
            label: "Показ инфо об англ. языке",
            title: "Отображать данные об английском языке",
            details: "<p><strong>Функция для переводчиков и интересующихся.</strong> Если включено, в блоках дополнительной информации (в каталоге при наведении и в ленте активности при наведении) будет также отображаться информация о поддержке английского языка (интерфейс, озвучка, субтитры), аналогично русскому.</p><p>По умолчанию эта информация скрыта для экономии места.</p>"
        }
    };

    function showInfoModal(settingKey) {
        const existingInfoModal = document.getElementById('useSettingInfoModal');
        if (existingInfoModal) existingInfoModal.remove();

        const infoData = settingInfo[settingKey];
        if (!infoData) return;

        const infoModal = document.createElement('div');
        infoModal.id = 'useSettingInfoModal';
        infoModal.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: #1f2c3a;
            color: #c6d4df;
            padding: 25px;
            border-radius: 5px;
            border: 1px solid #8f98a0;
            box-shadow: 0 5px 25px rgba(0, 0, 0, 0.7);
            z-index: 10002;
            display: block;
            width: 800px;
            max-width: 90vw;
            max-height: 90vh;
            overflow-y: auto;
            font-family: "Motiva Sans",
            Sans-serif,
            Arial;
            font-size: 14px;
            scrollbar-color: #4b6f9c #1b2838;
            scrollbar-width: thin;
        `;
        infoModal.style.setProperty('--scrollbar-track-color-info', '#1b2838');
        infoModal.style.setProperty('--scrollbar-thumb-color-info', '#4b6f9c');
         GM_addStyle(`
            #useSettingInfoModal::-webkit-scrollbar {
            	width: 8px;
            }

            #useSettingInfoModal::-webkit-scrollbar-track {
            	background: var(--scrollbar-track-color-info);
            	border-radius: 4px;
            }

            #useSettingInfoModal::-webkit-scrollbar-thumb {
            	background-color: var(--scrollbar-thumb-color-info);
            	border-radius: 4px;
            	border: 2px solid var(--scrollbar-track-color-info);
            }

            #useSettingInfoModal::-webkit-scrollbar-thumb:hover {
            	background-color: #67c1f5;
            }

            #useSettingInfoModal p {
            	margin-bottom: 1em;
            	line-height: 1.6;
            }

            #useSettingInfoModal ul {
            	margin-left: 20px;
            	margin-bottom: 5px;
            	list-style-position: outside;
            }

            #useSettingInfoModal li {
            	margin-bottom: 0.5em;
            }

            #useSettingInfoModal strong {
            	color: #67c1f5;
            }

            #useSettingInfoModal img {
            	border-radius: 3px;
            }

            #useSettingInfoModal a {
            	color: #67c1f5;
            	text-decoration: none;
            }

            #useSettingInfoModal a:hover {
            	text-decoration: underline;
            }
        `);

        const title = document.createElement('h3');
        title.textContent = infoData.title || "Информация";
        title.style.cssText = 'margin-top: 0; margin-bottom: 20px; color: #67c1f5; text-align: center; font-weight: 500; font-size: 17px;';
        infoModal.appendChild(title);

        const detailsDiv = document.createElement('div');
        detailsDiv.innerHTML = infoData.details || "Описание отсутствует.";
        infoModal.appendChild(detailsDiv);

        const closeButton = document.createElement('button');
        closeButton.textContent = 'Закрыть';
        closeButton.style.cssText = `
            display: block; margin: 25px auto 0; padding: 10px 25px;
            background-color: #8f98a0; color: #1b2838; border: none;
            border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: bold;
            transition: background-color 0.2s;
        `;
        closeButton.onmouseover = () => closeButton.style.backgroundColor = '#aab5c1';
        closeButton.onmouseout = () => closeButton.style.backgroundColor = '#8f98a0';
        closeButton.addEventListener('click', function() {
            infoModal.remove();
        });
        infoModal.appendChild(closeButton);

        document.body.appendChild(infoModal);
    }

    function createSettingRow(key) {
        const settingData = settingInfo[key];
        if (!settingData) return null;

        const row = document.createElement('div');
        row.style.cssText = 'display: flex; align-items: center; justify-content: space-between; min-height: 24px;';

        const labelContainer = document.createElement('label');
        labelContainer.style.cssText = 'display: flex; align-items: center; cursor: pointer; flex-grow: 1; margin-right: 10px;';

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = useCurrentSettings[key];
        checkbox.dataset.settingKey = key;
        checkbox.style.cssText = 'margin-right: 10px; accent-color: #67c1f5; cursor: pointer; width: 16px; height: 16px; flex-shrink: 0;';

        const labelText = document.createElement('span');
        labelText.textContent = settingData.label || key;
        labelText.style.lineHeight = '1.3';

        if (key === 'gamePage') {
            labelText.style.color = '#9E9E9E';
            checkbox.style.accentColor = '#FFB300';

            const dependentLabelsTooltip = dependentModules.gamePage
                .map(depKey => `'${settingInfo[depKey]?.label || depKey}'`)
                .join(', ');
            labelContainer.title = `Отключение этого модуля приведет к нарушению работы или полному отключению модулей: ${dependentLabelsTooltip}. Эти модули критически зависят от данного модуля.`;
        }

        checkbox.addEventListener('change', function() {
            const currentSettingKey = this.dataset.settingKey;
            const isChecked = this.checked;

            if (currentSettingKey === 'gamePage' && !isChecked) {
                const dependentFullNames = dependentModules.gamePage
                    .map(depKey => `'${settingInfo[depKey]?.label || depKey}'`)
                    .join(', ');
                showConfirmationModal(
                    'Подтверждение отключения',
                    `Отключение этого модуля приведёт к отключению модулей: ${dependentFullNames}. Вы уверены?`,
                    () => {
                        useCurrentSettings[currentSettingKey] = false;
                        scriptsConfig[currentSettingKey] = false;

                        dependentModules.gamePage.forEach(depKey => {
                            useCurrentSettings[depKey] = false;
                            scriptsConfig[depKey] = false;
                            const depCheckbox = document.querySelector(`input[data-setting-key="${depKey}"]`);
                            if (depCheckbox) {
                                depCheckbox.checked = false;
                            }
                        });
                        GM_setValue('useSettings', useCurrentSettings);
                    },
                    () => {
                        this.checked = true;
                    }
                );
            } else {
                useCurrentSettings[currentSettingKey] = isChecked;
                scriptsConfig[currentSettingKey] = isChecked;
                GM_setValue('useSettings', useCurrentSettings);
            }
        });

        labelContainer.appendChild(checkbox);
        labelContainer.appendChild(labelText);
        row.appendChild(labelContainer);

        const infoButton = document.createElement('span');
        infoButton.textContent = 'ⓘ';
        infoButton.style.cssText = `
            cursor: pointer; color: #67c1f5; font-size: 18px;
            line-height: 1; font-weight: bold;
            margin-left: 5px; padding: 0 4px; border-radius: 3px; user-select: none;
            transition: color 0.2s, background-color 0.2s;
            flex-shrink: 0; vertical-align: middle;
        `;
        infoButton.title = 'Подробнее...';
        infoButton.onmouseover = () => { infoButton.style.backgroundColor = 'rgba(103, 193, 245, 0.2)'; };
        infoButton.onmouseout = () => { infoButton.style.backgroundColor = 'transparent'; };
        infoButton.addEventListener('click', (e) => {
            e.stopPropagation();
            showInfoModal(key);
        });

        row.appendChild(infoButton);
        return row;
    }

    function createSettingsModal() {
        const existingModal = document.getElementById('useSettingsModal');
        if (existingModal) existingModal.remove();

        const modal = document.createElement('div');
        modal.id = 'useSettingsModal';
        modal.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: #171a21;
            color: #c6d4df;
            padding: 30px;
            border-radius: 5px;
            border: 1px solid #67c1f5;
            box-shadow: 0 5px 30px rgba(0, 0, 0, 0.8);
            z-index: 10001;
            display: block;
            width: 800px;
            max-height: 90vh;
            overflow-y: auto;
            font-family: "Motiva Sans",
            Sans-serif,
            Arial;
            font-size: 14px;
            scrollbar-color: #4b6f9c #1b2838;
            scrollbar-width: thin;
        `;
        modal.style.setProperty('--scrollbar-track-color', '#1b2838');
        modal.style.setProperty('--scrollbar-thumb-color', '#4b6f9c');

        GM_addStyle(`
            #useSettingsModal::-webkit-scrollbar {
            	width: 8px;
            }

            #useSettingsModal::-webkit-scrollbar-track {
            	background: var(--scrollbar-track-color);
            	border-radius: 4px;
            }

            #useSettingsModal::-webkit-scrollbar-thumb {
            	background-color: var(--scrollbar-thumb-color);
            	border-radius: 4px;
            	border: 2px solid var(--scrollbar-track-color);
            }

            #useSettingsModal::-webkit-scrollbar-thumb:hover {
            	background-color: #67c1f5;
            }

            #useCreditsFooter {
            	position: absolute;
            	bottom: 20px;
            	right: 25px;
            	font-size: 12px;
            	color: #8091a2;
            	text-align: right;
            	line-height: 1.4;
            	z-index: 1;
            }

            #useCreditsFooter a {
            	color: #8f98a0;
            	text-decoration: none;
            }

            #useCreditsFooter a:hover {
            	color: #67c1f5;
            	text-decoration: underline;
            }

            #useCreditsFooter .author-line {
            	margin-bottom: 3px;
            }
        `);

        const mainTitleHeader = document.createElement('h2');
        mainTitleHeader.textContent = 'Настройки Ultimate Steam Enhancer';
        mainTitleHeader.style.cssText = 'margin-top: 0; margin-bottom: 25px; color: #67c1f5; text-align: center; font-weight: 500; font-size: 18px;';
        modal.appendChild(mainTitleHeader);

        const categories = {
            gamePage: { title: 'Для страницы игры', container: document.createElement('div') },
            catalog: { title: 'Для каталога', container: document.createElement('div') },
            community: { title: 'Для ленты активности', container: document.createElement('div') },
            market: { title: 'Для торговой площадки', container: document.createElement('div') },
            news_wishlist: { title: 'Для списка желаемого / Новостей', container: document.createElement('div') },
            additional: { title: 'Дополнительные настройки', container: document.createElement('div') }
        };

        for (const catKey in categories) {
            const category = categories[catKey];
            category.container.style.marginBottom = '25px';
            const categoryTitle = document.createElement('h4');
            categoryTitle.textContent = category.title;
            categoryTitle.style.cssText = 'color: #c6d4df; border-bottom: 1px solid #4b6f9c; padding-bottom: 6px; margin-bottom: 12px; font-size: 15px; font-weight: normal;';
            category.container.appendChild(categoryTitle);
            const checkboxesGrid = document.createElement('div');
            checkboxesGrid.style.cssText = 'display: grid; grid-template-columns: 1fr 1fr; gap: 10px 25px;';
            category.container.appendChild(checkboxesGrid);
            modal.appendChild(category.container);
        }

        for (const key of Object.keys(settingInfo)) {
            const settingData = settingInfo[key];
            if (settingData && settingData.category && categories[settingData.category]) {
                 if (useCurrentSettings.hasOwnProperty(key)) {
                     const settingRow = createSettingRow(key);
                     if (settingRow) {
                        const gridContainer = categories[settingData.category].container.querySelector('div[style*="grid-template-columns"]');
                        if (gridContainer) {
                            gridContainer.appendChild(settingRow);
                        }
                     }
                 }
            }
        }

        const creditsFooter = document.createElement('div');
        creditsFooter.id = 'useCreditsFooter';

        const authorLine = document.createElement('div');
        authorLine.className = 'author-line';
        authorLine.textContent = 'by 0wn3df1x';
        creditsFooter.appendChild(authorLine);

        const zogLine = document.createElement('div');
        zogLine.appendChild(document.createTextNode('и '));

        const zogLink = document.createElement('a');
        zogLink.href = 'https://www.zoneofgames.ru';
        zogLink.target = '_blank';
        zogLink.title = 'Перейти на ZoneOfGames.ru';
        zogLink.textContent = 'команда ZoneOfGames.ru';
        zogLine.appendChild(zogLink);
        creditsFooter.appendChild(zogLine);

        modal.appendChild(creditsFooter);

        const closeButton = document.createElement('button');
        closeButton.textContent = 'Закрыть';
        closeButton.style.cssText = `
            display: block; margin: 30px auto 0; padding: 10px 30px;
            background-color: #67c1f5; color: #1b2838; border: none;
            border-radius: 3px; cursor: pointer; font-size: 15px; font-weight: bold;
            transition: background-color 0.2s;
        `;
        closeButton.onmouseover = () => closeButton.style.backgroundColor = '#8ad3f7';
        closeButton.onmouseout = () => closeButton.style.backgroundColor = '#67c1f5';
        closeButton.addEventListener('click', function() {
            modal.remove();
        });
        modal.appendChild(closeButton);

        document.body.appendChild(modal);
    }

    function addLoggedInSettingsMenuItem(accountDropdown) {
        const logoutLink = accountDropdown.querySelector('a[href="javascript:Logout();"]');
        if (!logoutLink || document.getElementById('use_settings_menu_item')) {
            return;
        }

        const settingsMenuItem = document.createElement('a');
        settingsMenuItem.className = 'popup_menu_item';
        settingsMenuItem.id = 'use_settings_menu_item';
        settingsMenuItem.href = '#';
        settingsMenuItem.textContent = 'Настройки U.S.E.';
        settingsMenuItem.style.color = '#67c1f5';
        settingsMenuItem.style.fontWeight = 'bold';


        settingsMenuItem.addEventListener('click', function(event) {
            event.preventDefault();
            event.stopPropagation();
            createSettingsModal();
        });

        const popupBody = accountDropdown.querySelector('.popup_body.popup_menu');
        if (popupBody) {
            popupBody.insertBefore(settingsMenuItem, logoutLink);
        }
    }

    function addLoggedOutSettingsMenuItem(globalActionMenu) {
        const languagePulldown = document.getElementById('language_pulldown');
        const loginLink = globalActionMenu.querySelector('a[href*="/login"]');

        if (!languagePulldown || !loginLink || document.getElementById('use_settings_logged_out_link')) {
            return;
        }

        const separator = document.createTextNode('\u00A0|\u00A0');

        const settingsLinkElement = document.createElement('a');
        settingsLinkElement.href = '#';
        settingsLinkElement.id = 'use_settings_logged_out_link';
        settingsLinkElement.className = 'global_action_link';
        settingsLinkElement.textContent = 'Настройки U.S.E.';
        settingsLinkElement.style.color = '#67c1f5';
        settingsLinkElement.style.fontWeight = 'bold';

        settingsLinkElement.addEventListener('click', (e) => {
            e.preventDefault();
            createSettingsModal();
        });

        globalActionMenu.appendChild(separator);
        globalActionMenu.appendChild(settingsLinkElement);
    }

    function addSettingsButtonGlobal() {
        const globalActionMenu = document.getElementById('global_action_menu');
        if (!globalActionMenu) {
            return;
        }

        const existingLoggedInButton = document.getElementById('use_settings_menu_item');
        if (existingLoggedInButton) {
            existingLoggedInButton.remove();
        }

        const existingLoggedOutLink = document.getElementById('use_settings_logged_out_link');
        if (existingLoggedOutLink) {
            const prevNode = existingLoggedOutLink.previousSibling;
            if (prevNode && prevNode.nodeType === Node.TEXT_NODE && prevNode.textContent === '\u00A0|\u00A0') {
                prevNode.remove();
            }
            existingLoggedOutLink.remove();
        }

        const accountDropdown = document.getElementById('account_dropdown');
        if (accountDropdown) {
            addLoggedInSettingsMenuItem(accountDropdown);
        } else {
            addLoggedOutSettingsMenuItem(globalActionMenu);
        }
    }

    let globalUiAttempts = 0;
    const globalUiMaxAttempts = 20;
    const globalUiInterval = setInterval(() => {
        const globalHeader = document.getElementById('global_header');

        if (globalHeader || globalUiAttempts >= globalUiMaxAttempts) {
            clearInterval(globalUiInterval);
            if (globalHeader) {
                addSettingsButtonGlobal();

                const observer = new MutationObserver((mutationsList, obs) => {
                    const isNowLoggedIn = !!document.getElementById('account_dropdown');

                    const loggedInButtonPresent = !!document.getElementById('use_settings_menu_item');
                    const loggedOutLinkPresent = !!document.getElementById('use_settings_logged_out_link');

                    let needsRebuild = false;

                    if (isNowLoggedIn) {
                        if (!loggedInButtonPresent || loggedOutLinkPresent) {
                            needsRebuild = true;
                        }
                    } else {
                        const loginPageMarker = !!document.querySelector('#global_action_menu a[href*="/login"]');

                        if (loginPageMarker) {
                            if (!loggedOutLinkPresent || loggedInButtonPresent) {
                                needsRebuild = true;
                            }
                        } else if (loggedInButtonPresent || loggedOutLinkPresent) {
                            needsRebuild = true;
                        }
                    }

                    if (needsRebuild) {
                        addSettingsButtonGlobal();
                    }
                });

                observer.observe(globalHeader, {
                    childList: true,
                    subtree: true
                });
            }
        }
        globalUiAttempts++;
    }, 500);

    function showConfirmationModal(titleText, messageText, onConfirm, onCancel) {
        const existingConfirmModal = document.getElementById('useConfirmationModal');
        if (existingConfirmModal) existingConfirmModal.remove();

        const confirmModal = document.createElement('div');
        confirmModal.id = 'useConfirmationModal';
        confirmModal.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: #1f2c3a;
            color: #c6d4df;
            padding: 25px;
            border-radius: 5px;
            border: 1px solid #FFB300;
            box-shadow: 0 5px 25px rgba(0, 0, 0, 0.7);
            z-index: 10003;
            display: block;
            width: 500px;
            max-width: 90vw;
            font-family: "Motiva Sans", Sans-serif, Arial;
            font-size: 14px;
        `;

        const title = document.createElement('h3');
        title.textContent = titleText;
        title.style.cssText = 'margin-top: 0; margin-bottom: 15px; color: #FFB300; text-align: center; font-weight: 500; font-size: 17px;';
        confirmModal.appendChild(title);

        const message = document.createElement('p');
        message.textContent = messageText;
        message.style.cssText = 'margin-bottom: 25px; line-height: 1.6; text-align: center;';
        confirmModal.appendChild(message);

        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = 'display: flex; justify-content: space-around;';

        const confirmButton = document.createElement('button');
        confirmButton.textContent = 'Да';
        confirmButton.style.cssText = `
            padding: 10px 25px; background-color: #FFB300; color: #1b2838; border: none;
            border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: bold;
            transition: background-color 0.2s;
        `;
        confirmButton.onmouseover = () => confirmButton.style.backgroundColor = '#FFC107';
        confirmButton.onmouseout = () => confirmButton.style.backgroundColor = '#FFB300';
        confirmButton.addEventListener('click', function() {
            onConfirm();
            confirmModal.remove();
        });

        const cancelButton = document.createElement('button');
        cancelButton.textContent = 'Нет';
        cancelButton.style.cssText = `
            padding: 10px 25px; background-color: #8f98a0; color: #1b2838; border: none;
            border-radius: 3px; cursor: pointer; font-size: 14px; font-weight: bold;
            transition: background-color 0.2s;
        `;
        cancelButton.onmouseover = () => cancelButton.style.backgroundColor = '#aab5c1';
        cancelButton.onmouseout = () => cancelButton.style.backgroundColor = '#8f98a0';
        cancelButton.addEventListener('click', function() {
            onCancel();
            confirmModal.remove();
        });

        buttonContainer.appendChild(confirmButton);
        buttonContainer.appendChild(cancelButton);
        confirmModal.appendChild(buttonContainer);

        document.body.appendChild(confirmModal);
    }

    // Скрипт для страницы игры (индикаторы о наличии русского перевода; получение дополнительных обзоров) | https://store.steampowered.com/app/*
    if (scriptsConfig.gamePage && unsafeWindow.location.pathname.includes('/app/')) {
        (function() {
            'use strict';

            if (typeof ChartDataLabels !== 'undefined') {
                Chart.register(ChartDataLabels);
            } else {
                console.error("ChartDataLabels plugin is not loaded. Make sure the @require line is correct.");
            }

            function createFruitIndicator(apple, hasSupport, orange) {
                const banana = document.createElement('div');
                banana.style.position = 'relative';
                banana.style.cursor = 'pointer';

                const grape = document.createElement('div');
                grape.style.width = '60px';
                grape.style.height = '60px';
                grape.style.borderRadius = '4px';
                grape.style.display = 'flex';
                grape.style.alignItems = 'center';
                grape.style.justifyContent = 'center';
                grape.style.background = hasSupport ? 'rgba(66, 135, 245, 0.2)' : 'rgba(0, 0, 0, 0.1)';
                grape.style.border = `1px solid ${hasSupport ? '#2A5891' : '#3c3c3c'}`;
                grape.style.opacity = '0.95';
                grape.style.transition = 'transform 0.3s ease, box-shadow 0.3s ease';
                grape.style.overflow = 'hidden';
                grape.style.position = 'relative';
                grape.style.transform = 'translateZ(0)';

                const kiwi = document.createElement('div');
                kiwi.innerHTML = apple;
                kiwi.style.width = '30px';
                kiwi.style.height = '30px';
                kiwi.style.display = 'block';
                kiwi.style.margin = '0 auto';
                kiwi.style.transition = 'fill 0.3s ease';

                grape.appendChild(kiwi);

                const svgElement = kiwi.querySelector('svg');

                function setColor(hasSupport) {
                    const borderColor = hasSupport ? '#2A5891' : '#3c3c3c';
                    const svgFill = hasSupport ? '#FFFFFF' : '#0E1C25';

                    grape.style.border = `1px solid ${borderColor}`;
                    if (svgElement) {
                        svgElement.style.fill = svgFill;
                    }
                }

                setColor(hasSupport);

                const pineapple = document.createElement('div');
                const hasLabel = hasSupport ? orange : getGenitiveCase(orange);
                pineapple.textContent = hasSupport ? `Есть ${orange}` : `Нет ${hasLabel}`;
                pineapple.style.position = 'absolute';
                pineapple.style.top = '50%';
                pineapple.style.left = '100%';
                pineapple.style.transform = 'translateY(-50%) translateX(10px)';
                pineapple.style.background = 'rgba(0, 0, 0, 0.8)';
                pineapple.style.color = '#fff';
                pineapple.style.padding = '8px 12px';
                pineapple.style.borderRadius = '8px';
                pineapple.style.fontSize = '14px';
                pineapple.style.whiteSpace = 'nowrap';
                pineapple.style.opacity = '0';
                pineapple.style.transition = 'opacity 0.3s ease';
                pineapple.style.zIndex = '10000';
                pineapple.style.pointerEvents = 'none';
                banana.appendChild(pineapple);

                banana.addEventListener('mouseenter', () => {
                    grape.style.transform = 'scale(1.1) translateZ(0)';
                    pineapple.style.opacity = '1';
                });

                banana.addEventListener('mouseleave', () => {
                    grape.style.transform = 'scale(1) translateZ(0)';
                    pineapple.style.opacity = '0';
                });

                banana.appendChild(grape);
                return banana;
            }

            function getGenitiveCase(orange) {
                switch (orange) {
                    case 'интерфейс':
                        return 'интерфейса';
                    case 'озвучка':
                        return 'озвучки';
                    case 'субтитры':
                        return 'субтитров';
                    default:
                        return orange;
                }
            }

            function checkRussianSupport() {
                const mango = document.querySelector('#languageTable table.game_language_options');
                if (!mango) return { interface: false, voice: false, subtitles: false };

                const strawberry = mango.querySelectorAll('tr');
                for (let blueberry of strawberry) {
                    const watermelon = blueberry.querySelector('td.ellipsis');
                    if (watermelon && /русский|Russian/i.test(watermelon.textContent.trim())) {
                        const cherry = blueberry.querySelector('td.checkcol:nth-child(2) span');
                        const raspberry = blueberry.querySelector('td.checkcol:nth-child(3) span');
                        const blackberry = blueberry.querySelector('td.checkcol:nth-child(4) span');
                        return {
                            interface: cherry !== null,
                            voice: raspberry !== null,
                            subtitles: blackberry !== null
                        };
                    }
                }
                return { interface: false, voice: false, subtitles: false };
            }

            function addRussianIndicators() {
                const russianSupport = checkRussianSupport();
                if (!russianSupport) return;

                let lemon = document.querySelector('#gameHeaderImageCtn');
                if (!lemon) return;

                const existingIndicatorContainer = lemon.querySelector('.use-rus-indicator-container');
                if (existingIndicatorContainer) {
                    existingIndicatorContainer.remove();
                }

                const lime = document.createElement('div');
                lime.className = 'use-rus-indicator-container';
                lime.style.position = 'absolute';
                lime.style.top = '-10px';
                lime.style.left = 'calc(100% + 10px)';
                lime.style.display = 'flex';
                lime.style.flexDirection = 'column';
                lime.style.gap = '15px';
                lime.style.alignItems = 'flex-start';
                lime.style.zIndex = '2';
                lime.style.marginTop = '10px';

                const peach = createFruitIndicator(`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12,0C5.38,0,0,5.38,0,12s5.38,12,12,12s12-5.38,12-12S18.62,0,12,0z M12,22C6.49,22,2,17.51,2,12S6.49,2,12,2	s10,4.49,10,10S17.51,22,12,22z M10.5,10h3v8h-3V10z M10.5,5h3v3h-3V5z" /></svg>`, russianSupport.interface, 'интерфейс');
                const plum = createFruitIndicator(`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M15,21v-2c3.86,0,7-3.14,7-7s-3.14-7-7-7V3c4.96,0,9,4.04,9,9S19.96,21,15,21z M15,17v-2c1.65,0,3-1.35,3-3s-1.35-3-3-3V7 c2.76,0,5,2.24,5,5S17.76,17,15,17z M1,12v4h5l6,5V3L6,8H1V12" /></svg>`, russianSupport.voice, 'озвучка');
                const apricot = createFruitIndicator(`<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g><path d="M11,24l-4.4-5H0V0h23v19h-7.6L11,24z M2,17h5.4l3.6,4l3.6-4H21V2H2V17z" /></g><g><rect x="5" y="8" width="3" height="3" /></g><g><rect x="10" y="8" width="3" height="3" /></g><g><rect x="15" y="8" width="3" height="3" /></g></svg>`, russianSupport.subtitles, 'субтитры');

                lime.appendChild(peach);
                lime.appendChild(plum);
                lime.appendChild(apricot);

                lemon.style.position = 'relative';
                lemon.appendChild(lime);

                const appName = document.querySelector('#appHubAppName.apphub_AppName');
                if (appName) {
                    appName.style.maxWidth = '530px';
                    appName.style.overflow = 'hidden';
                    appName.style.textOverflow = 'ellipsis';
                    appName.style.whiteSpace = 'nowrap';
                    appName.title = appName.textContent;
                }
            }

            const additionalReviewsSettings = {
                showTotalReviews: true,
                showNonChineseReviews: true,
                showRussianReviews: true
            };

            let allReviewsDataGlobal = null;
            let schineseDataGlobal = null;
            let russianDataGlobal = null;
            let appidGlobal = null;

            function fetchReviews(appid, language, callback) {
                let url = `https://store.steampowered.com/appreviews/${appid}?json=1&language=${language}&purchase_type=all`;
                GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    timeout: 15000,
                    onload: function(response) {
                        if (response.status >= 200 && response.status < 400) {
                            try {
                                let data = JSON.parse(response.responseText);
                                if (data.success === 1) {
                                    callback(data.query_summary);
                                } else {
                                    console.error(`Steam API error for ${language}:`, data);
                                    callback(null);
                                }
                            } catch (e) {
                                console.error(`Error parsing Steam API response for ${language}:`, e);
                                callback(null);
                            }
                        } else {
                            console.error(`Steam API request failed for ${language}. Status: ${response.status}`);
                            callback(null);
                        }
                    },
                    onerror: function(error) {
                        console.error(`Network error fetching reviews for ${language}:`, error);
                        callback(null);
                    },
                    ontimeout: function() {
                        console.error(`Timeout fetching reviews for ${language}`);
                        callback(null);
                    }
                });
            }

            function fetchRussianReviewsHTML(appid, filter, callback) {
                let url = `https://store.steampowered.com/appreviews/${appid}?language=russian&purchase_type=all&filter=${filter}&day_range=365`;
                GM_xmlhttpRequest({
                    method: "GET",
                    url: url,
                    timeout: 15000,
                    onload: function(response) {
                        if (response.status >= 200 && response.status < 400) {
                            try {
                                let data = JSON.parse(response.responseText);
                                if (data.success === 1) {
                                    callback(data.html);
                                } else {
                                    console.error('Error fetching Russian reviews HTML (success != 1):', data);
                                    callback('<p style="color: #ff6961;">Ошибка загрузки обзоров.</p>');
                                }
                            } catch (e) {
                                console.error('Error parsing Russian reviews HTML:', e);
                                callback('<p style="color: #ff6961;">Ошибка обработки ответа.</p>');
                            }
                        } else {
                            console.error(`Failed to fetch Russian reviews HTML. Status: ${response.status}`);
                            callback('<p style="color: #ff6961;">Ошибка сети при загрузке обзоров.</p>');
                        }
                    },
                    onerror: function(error) {
                        console.error('Network error fetching Russian reviews HTML:', error);
                        callback('<p style="color: #ff6961;">Ошибка сети.</p>');
                    },
                    ontimeout: function() {
                        console.error('Timeout fetching Russian reviews HTML');
                        callback('<p style="color: #ff6961;">Таймаут загрузки обзоров.</p>');
                    }
                });
            }

            function addStyles() {
                GM_addStyle(`
                        .additional-reviews {
                        	margin-top: 10px;
                        	padding-top: 10px;
                        	border-top: 1px solid #3e4c583d;
                        }

                        .additional-reviews .user_reviews_summary_row {
                        	display: flex;
                        	line-height: 16px;
                        	margin-bottom: 5px;
                        }

                        .additional-reviews .user_reviews_summary_row.clickable {
                        	cursor: pointer;
                        	transition: background-color 0.2s;
                        	border-radius: 2px;
                        	padding: 2px 4px;
                        	margin: 0 5px 5px -4px;
                        }

                        .additional-reviews .user_reviews_summary_row.clickable:hover {
                        	background-color: rgba(103, 193, 245, 0.1);
                        }

                        .additional-reviews .subtitle {
                        	flex: 1;
                        	color: #556772;
                        	font-size: 12px;
                        	user-select: none;
                        }

                        .additional-reviews .summary {
                        	flex: 3;
                        	color: #c6d4df;
                        	font-size: 12px;
                        	overflow: hidden;
                        	white-space: nowrap;
                        	text-overflow: ellipsis;
                        }

                        .additional-reviews .game_review_summary {
                        	font-weight: normal;
                        }

                        .additional-reviews .positive {
                        	color: #66c0f4;
                        }

                        .additional-reviews .mixed {
                        	color: #B9A074;
                        }

                        .additional-reviews .negative {
                        	color: #a34c25;
                        }

                        .additional-reviews .no_reviews {
                        	color: #929396;
                        }

                        .additional-reviews .responsive_hidden {
                        	color: #556772;
                        	margin-left: 5px;
                        }

                        .additional-reviews .summary-error {
                        	color: #ff6961;
                        	font-style: italic;
                        }

                        .ofxmodal {
                        	display: none;
                        	position: fixed;
                        	z-index: 1000;
                        	left: 0;
                        	top: 0;
                        	width: 100%;
                        	height: 100%;
                        	overflow: auto;
                        	background-color: rgba(0, 0, 0, 0.85);
                        	backdrop-filter: blur(3px);
                        }

                        .ofxmodal-content {
                        	background-color: #1b2838;
                        	margin: 8% auto;
                        	padding: 25px;
                        	border: 1px solid #567d9c;
                        	width: 80%;
                        	max-width: 900px;
                        	color: #c6d4df;
                        	position: relative;
                        	max-height: 80vh;
                        	overflow-y: auto;
                        	border-radius: 4px;
                        	font-family: "Motiva Sans", Arial, sans-serif;
                        	scrollbar-color: #4b6f9c #1b2838;
                        	scrollbar-width: thin;
                        }

                        .ofxmodal-content::-webkit-scrollbar {
                        	width: 8px;
                        }

                        .ofxmodal-content::-webkit-scrollbar-track {
                        	background: #1b2838;
                        	border-radius: 4px;
                        }

                        .ofxmodal-content::-webkit-scrollbar-thumb {
                        	background-color: #4b6f9c;
                        	border-radius: 4px;
                        	border: 2px solid #1b2838;
                        }

                        .ofxclose {
                            background: none;
                            border: none;
                            color: #aaa;
                            font-size: 30px;
                            font-weight: normal;
                            padding: 0 5px;
                            line-height: 1;
                            cursor: pointer;
                            transition: color 0.2s ease;
                            position: absolute;
                            top: 15px;
                            right: 15px;
                            z-index: 1001;
                        }

                        .ofxclose:hover {
                            color: #fff;
                            background: none;
                            transform: none;
                        }

                        .ofxclose:active {
                            color: #fff;
                            background: none;
                            transform: none;
                        }

                        .refresh-button {
                        	position: absolute;
                        	top: 20px;
                        	left: 25px;
                        	background: #66c0f4;
                        	color: #1b2838;
                        	padding: 10px 20px;
                        	border: none;
                        	cursor: pointer;
                        	z-index: 1001;
                        	border-radius: 2px;
                        	transition: background 0.2s ease, color 0.2s ease;
                        	font-weight: 500;
                        }

                        .refresh-button:hover {
                        	background: #45b0e6;
                        	color: #fff;
                        }

                        .refresh-button:active {
                        	background: #329cd4;
                        	transform: translateY(1px);
                        }

                        #reviews-container .review_box {
                        	background-color: #16202d;
                        	border: 1px solid #2a3f5a;
                        	margin-bottom: 15px;
                        	border-radius: 3px;
                        }

                        #reviews-container .title {
                        	color: #67c1f5;
                        }

                        #reviews-container .hours {
                        	color: #8f98a0;
                        }

                        #reviews-container .content {
                        	color: #acb2b8;
                        }

                        #reviews-container .posted,
                        #reviews-container .found_helpful {
                        	color: #556772;
                        	font-size: 11px;
                        }

                        #globalReviewsModal {
                        	display: none;
                        	position: fixed;
                        	z-index: 10000;
                        	left: 0;
                        	top: 0;
                        	width: 100%;
                        	height: 100%;
                        	overflow: hidden;
                        	background-color: rgba(0, 0, 0, 0.9);
                        	backdrop-filter: blur(5px);
                        	color: #c6d4df;
                        	font-family: "Motiva Sans", Arial, sans-serif;
                        }

                        #globalReviewsModal .modal-content-inner {
                        	background-color: #101822;
                        	margin: 3vh auto;
                        	padding: 0;
                        	border: 1px solid #67c1f5;
                        	width: 94%;
                        	max-width: 1400px;
                        	height: 94vh;
                        	display: flex;
                        	flex-direction: column;
                        	border-radius: 5px;
                        	box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
                        }

                        #globalReviewsModal .modal-header {
                        	padding: 15px 25px;
                        	background-color: #16202d;
                        	border-bottom: 1px solid #2a3f5a;
                        	display: flex;
                        	justify-content: space-between;
                        	align-items: center;
                        	flex-shrink: 0;
                        }

                        #globalReviewsModal .modal-title {
                        	font-size: 20px;
                        	color: #67c1f5;
                        	font-weight: 500;
                        	margin: 0;
                        }

                        #globalReviewsModal .modal-close-btn {
                        	font-size: 30px;
                        	color: #aaa;
                        	background: none;
                        	border: none;
                        	cursor: pointer;
                        	line-height: 1;
                        	padding: 0 5px;
                        	transition: color 0.2s;
                        }

                        #globalReviewsModal .modal-close-btn:hover {
                        	color: #fff;
                        }

                        #globalReviewsModal .modal-body {
                        	display: flex;
                        	flex-grow: 1;
                        	overflow: hidden;
                        	padding: 20px 25px;
                        	gap: 25px;
                        }

                        #globalReviewsModal .modal-left-panel {
                        	width: 55%;
                        	display: flex;
                        	flex-direction: column;
                        	overflow: hidden;
                        }

                        #globalReviewsModal .modal-right-panel {
                        	width: 45%;
                        	display: flex;
                        	justify-content: center;
                        	align-items: center;
                        	position: relative;
                        	background-color: #16202d;
                        	border-radius: 4px;
                        	border: 1px solid #2a3f5a;
                        	padding: 15px;
                        }

                        #globalReviewsModal .controls-area {
                        	margin-bottom: 15px;
                        	display: flex;
                        	gap: 15px;
                        	align-items: center;
                        	flex-shrink: 0;
                        }

                        #globalReviewsModal .collect-btn {
                        	background: #66c0f4;
                        	color: #1b2838;
                        	padding: 10px 22px;
                        	border: none;
                        	cursor: pointer;
                        	border-radius: 3px;
                        	font-size: 14px;
                        	font-weight: bold;
                        	transition: background 0.2s, transform 0.1s;
                        }

                        #globalReviewsModal .collect-btn:hover:not(:disabled) {
                        	background: #8ad3f7;
                        }

                        #globalReviewsModal .collect-btn:active:not(:disabled) {
                        	transform: scale(0.98);
                        }

                        #globalReviewsModal .collect-btn:disabled {
                        	background: #556772;
                        	color: #8f98a0;
                        	cursor: not-allowed;
                        	opacity: 0.7;
                        }

                        #globalReviewsModal .progress-area {
                        	flex-grow: 1;
                        	display: flex;
                        	flex-direction: column;
                        	justify-content: center;
                        }

                        #globalReviewsModal .progress-bar-container {
                        	width: 100%;
                        	background-color: #0a1016;
                        	border-radius: 5px;
                        	height: 20px;
                        	overflow: hidden;
                        	border: 1px solid #2a3f5a;
                        	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.4);
                        }

                        #globalReviewsModal .progress-bar-inner {
                        	width: 0%;
                        	height: 100%;
                        	background-color: #4b6f9c;
                        	background-image: linear-gradient(-45deg, rgba(255, 255, 255, .1) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, .1) 75%, transparent 75%, transparent);
                        	background-size: 30px 30px;
                        	transition: width 0.4s ease;
                        	text-align: right;
                        	color: #fff;
                        	font-weight: bold;
                        	line-height: 20px;
                        	font-size: 11px;
                        	padding-right: 8px;
                        	text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
                        }

                        #globalReviewsModal .progress-text {
                        	font-size: 11px;
                        	color: #8f98a0;
                        	margin-top: 3px;
                        	text-align: left;
                        	height: 1.2em;
                        }

                        #globalReviewsModal .table-container {
                        	flex-grow: 1;
                        	overflow: auto;
                        	border: 1px solid #2a3f5a;
                        	border-radius: 3px;
                        	background: #16202d;
                        	scrollbar-color: #4b6f9c #16202d;
                        	scrollbar-width: thin;
                        }

                        #globalReviewsModal .table-container::-webkit-scrollbar {
                        	width: 8px;
                        }

                        #globalReviewsModal .table-container::-webkit-scrollbar-track {
                        	background: #16202d;
                        	border-radius: 0 3px 3px 0;
                        }

                        #globalReviewsModal .table-container::-webkit-scrollbar-thumb {
                        	background-color: #4b6f9c;
                        	border-radius: 4px;
                        	border: 2px solid #16202d;
                        }

                        #globalReviewsModal .reviews-table {
                        	width: 100%;
                        	border-collapse: collapse;
                        	font-size: 13px;
                        }

                        #globalReviewsModal .reviews-table th,
                        #globalReviewsModal .reviews-table td {
                        	padding: 9px 12px;
                        	text-align: left;
                        	border-bottom: 1px solid #2a3f5a;
                        	white-space: nowrap;
                        }

                        #globalReviewsModal .reviews-table th {
                        	background-color: #1f2c3a;
                        	color: #8f98a0;
                        	font-weight: normal;
                        	position: sticky;
                        	top: 0;
                        	z-index: 1;
                        }

                        #globalReviewsModal .reviews-table td {
                        	color: #acb2b8;
                        	vertical-align: middle;
                        }

                        #globalReviewsModal .reviews-table tr:last-child td {
                        	border-bottom: none;
                        }

                        #globalReviewsModal .reviews-table tr:hover td {
                        	background-color: rgba(103, 193, 245, 0.05);
                        }

                        #globalReviewsModal .reviews-table .col-rank {
                        	width: 40px;
                        	text-align: center;
                        	color: #8f98a0;
                        }

                        #globalReviewsModal .reviews-table .col-check {
                        	width: 40px;
                        	text-align: center;
                        }

                        #globalReviewsModal .reviews-table .col-lang {
                        	width: auto;
                        }

                        #globalReviewsModal .reviews-table .col-count {
                        	width: 90px;
                        	text-align: right;
                        }

                        #globalReviewsModal .reviews-table .col-percent-total {
                        	width: 80px;
                        	text-align: right;
                        	color: #8f98a0;
                        }

                        #globalReviewsModal .reviews-table .col-percent-pos {
                        	width: 70px;
                        	text-align: right;
                        }

                        #globalReviewsModal .reviews-table input[type=checkbox] {
                        	accent-color: #67c1f5;
                        	width: 16px;
                        	height: 16px;
                        	cursor: pointer;
                        	vertical-align: middle;
                        }

                        #globalReviewsModal .no-reviews-info {
                        	margin-top: 15px;
                        	font-size: 13px;
                        	color: #8f98a0;
                        	padding: 0 5px;
                        }

                        #globalReviewsModal .chart-container {
                        	width: 100%;
                        	height: 100%;
                        	position: relative;
                        }

                        #globalReviewsModal #reviewsPieChart {
                        	max-width: 100%;
                        	max-height: 100%;
                        }

                        #globalReviewsModal .modal-footer {
                        	padding: 15px 25px;
                        	border-top: 1px solid #2a3f5a;
                        	background-color: #16202d;
                        	text-align: center;
                        	font-size: 12px;
                        	color: #8f98a0;
                        	line-height: 1.4;
                        	flex-shrink: 0;
                        }
                    `);
            }

            function formatNumber(number) {
                return number.toLocaleString('ru-RU');
            }

            function getReviewClass(percent, totalReviews) {
                if (totalReviews === 0) return 'no_reviews';
                if (percent === null || typeof percent === 'undefined') return 'no_reviews';
                if (percent >= 70) return 'positive';
                if (percent >= 40) return 'mixed';
                return 'negative';
            }

            function addLoadButton() {
                let reviewsContainer = document.querySelector('.user_reviews');
                if (reviewsContainer) {
                    const existingButton = document.getElementById('load-reviews-button');
                    if (existingButton) existingButton.remove();
                    const existingReviews = document.querySelector('.additional-reviews');
                    if (existingReviews) existingReviews.remove();

                    let additionalReviewsContainer = document.createElement('div');
                    additionalReviewsContainer.className = 'additional-reviews';

                    let loadButton = document.createElement('div');
                    loadButton.className = 'user_reviews_summary_row clickable';
                    loadButton.id = 'load-reviews-button';
                    loadButton.innerHTML = `
                            <div class="subtitle column all">Доп. обзоры:</div>
                            <div class="summary column">
                                <span class="game_review_summary no_reviews">Загрузить статистику</span>
                            </div>
                        `;

                    additionalReviewsContainer.appendChild(loadButton);
                    reviewsContainer.appendChild(additionalReviewsContainer);

                    loadButton.addEventListener('click', loadAdditionalReviews);

                    if (scriptsConfig.autoLoadReviews) {
                        loadAdditionalReviews();
                    }
                }
            }

            function loadAdditionalReviews() {
                appidGlobal = unsafeWindow.location.pathname.match(/\/app\/(\d+)/)[1];
                if (!appidGlobal) return;

                let loadButton = document.getElementById('load-reviews-button');
                if (loadButton) {
                    loadButton.querySelector('.game_review_summary').textContent = 'Загрузка...';
                    loadButton.style.pointerEvents = 'none';
                    loadButton.style.opacity = '0.6';
                }

                const languagesToFetch = ['all', 'schinese', 'russian'];
                let fetchedData = {};
                let completedRequests = 0;

                languagesToFetch.forEach(language => {
                    fetchReviews(appidGlobal, language, (summaryData) => {
                        fetchedData[language] = summaryData;
                        completedRequests++;

                        if (completedRequests === languagesToFetch.length) {
                            allReviewsDataGlobal = fetchedData['all'];
                            schineseDataGlobal = fetchedData['schinese'];
                            russianDataGlobal = fetchedData['russian'];
                            displayAdditionalReviews(allReviewsDataGlobal, schineseDataGlobal, russianDataGlobal);

                            if (loadButton) {
                                loadButton.remove();
                            }
                        }
                    });
                });
            }

            function displayAdditionalReviews(allReviews, schineseReviews, russianReviews) {
                let additionalReviewsContainer = document.querySelector('.additional-reviews');
                if (!additionalReviewsContainer) return;

                additionalReviewsContainer.innerHTML = '';

                const addReviewRow = (id, title, reviewsData, isClickable = false, onClick = null) => {
                    const row = document.createElement('div');
                    row.className = 'user_reviews_summary_row';
                    if (isClickable) {
                        row.classList.add('clickable');
                        row.addEventListener('click', onClick);
                    }
                    row.id = id;

                    let percent = 0;
                    let total = 0;
                    let statusClass = 'no_reviews';
                    let summaryText = 'Нет данных';
                    let errorText = null;

                    if (reviewsData === null) {
                        errorText = 'Ошибка загрузки';
                        statusClass = 'summary-error';
                    } else if (reviewsData) {
                        total = reviewsData.total_reviews;
                        if (total > 0) {
                            percent = total > 0 ? Math.round((reviewsData.total_positive / total) * 100) : 0;
                            statusClass = getReviewClass(percent, total);
                            summaryText = `${percent}% из ${formatNumber(total)} положительные`;
                        } else {
                            summaryText = 'Нет обзоров';
                            statusClass = 'no_reviews';
                        }
                    } else {
                        summaryText = 'Нет данных';
                        statusClass = 'no_reviews';
                    }

                    row.innerHTML = `
                            <div class="subtitle column all">${title}:</div>
                            <div class="summary column">
                                <span class="game_review_summary ${statusClass}">${errorText || summaryText}</span>
                            </div>
                        `;
                    additionalReviewsContainer.appendChild(row);
                };

                if (additionalReviewsSettings.showTotalReviews) {
                    addReviewRow('total-reviews-row', 'Тотальные', allReviews, true, openGlobalReviewsModal);
                }

                if (additionalReviewsSettings.showNonChineseReviews) {
                    let nonChineseSummary = null;
                    let nonChineseError = null;
                    if (allReviews === null || schineseReviews === null) {
                        nonChineseError = 'Ошибка загрузки';
                    } else if (allReviews && schineseReviews) {
                        nonChineseSummary = { total_reviews: 0, total_positive: 0, review_score: 0 };
                        nonChineseSummary.total_reviews = Math.max(0, allReviews.total_reviews - schineseReviews.total_reviews);
                        nonChineseSummary.total_positive = Math.max(0, allReviews.total_positive - schineseReviews.total_positive);
                        if (nonChineseSummary.total_reviews > 0) {
                            const percent = Math.round((nonChineseSummary.total_positive / nonChineseSummary.total_reviews) * 100);
                            if (percent >= 70) nonChineseSummary.review_score = 8;
                            else if (percent >= 40) nonChineseSummary.review_score = 5;
                            else nonChineseSummary.review_score = 2;
                        } else {
                            nonChineseSummary.review_score = 0;
                        }
                    }
                    const row = document.createElement('div');
                    row.className = 'user_reviews_summary_row';
                    row.id = 'non-chinese-reviews-row';
                    let percent = 0;
                    let total = 0;
                    let statusClass = 'no_reviews';
                    let summaryText = 'Нет данных';

                    if (nonChineseError) {
                        summaryText = nonChineseError;
                        statusClass = 'summary-error';
                    } else if (nonChineseSummary) {
                        total = nonChineseSummary.total_reviews;
                        if (total > 0) {
                            percent = Math.round((nonChineseSummary.total_positive / total) * 100);
                            statusClass = getReviewClass(percent, total);
                            summaryText = `${percent}% из ${formatNumber(total)} положительные`;
                        } else {
                            summaryText = 'Нет обзоров';
                            statusClass = 'no_reviews';
                        }
                    }

                    row.innerHTML = `
                            <div class="subtitle column all">Безкитайские:</div>
                            <div class="summary column">
                                <span class="game_review_summary ${statusClass}">${summaryText}</span>
                            </div>
                        `;
                    additionalReviewsContainer.appendChild(row);
                }

                if (additionalReviewsSettings.showRussianReviews) {
                    addReviewRow('russian-reviews-row', 'Русские', russianReviews, true, openRussianReviewsModal);
                }
            }

            function openRussianReviewsModal() {
                let modal = document.getElementById('russianReviewsModal');
                if (!modal) {
                    modal = document.createElement('div');
                    modal.id = 'russianReviewsModal';
                    modal.className = 'ofxmodal';
                    modal.innerHTML = `
                            <div class="ofxmodal-content">
                                <span class="ofxclose" title="Закрыть">&times;</span>
                                <button class="refresh-button" id="refresh-reviews">Загрузить актуальные</button>
                                <h3 style="text-align: center; color: #67c1f5; margin-top: 5px; margin-bottom: 25px;">Русскоязычные обзоры</h3>
                                <div id="reviews-container" style="padding-top: 10px;">Загрузка...</div>
                            </div>
                        `;
                    document.body.appendChild(modal);

                    modal.querySelector('.ofxclose').addEventListener('click', () => modal.style.display = 'none');
                    modal.querySelector('#refresh-reviews').addEventListener('click', () => refreshRussianReviews(modal));
                    modal.addEventListener('click', (event) => {
                        if (event.target === modal) {
                            modal.style.display = 'none';
                        }
                    });
                }

                modal.style.display = 'block';
                loadRussianReviews(modal, 'all');
            }

            function refreshRussianReviews(modal) {
                modal.querySelector('#reviews-container').innerHTML = 'Загрузка актуальных...';
                loadRussianReviews(modal, 'recent');
            }

            function loadRussianReviews(modal, filter) {
                if (!appidGlobal) return;
                fetchRussianReviewsHTML(appidGlobal, filter, function(html) {
                    const container = modal.querySelector('#reviews-container');
                    container.innerHTML = html;
                    container.querySelector('#LoadMoreReviewsall')?.remove();
                    container.querySelector('#LoadMoreReviewsrecent')?.remove();
                    container.querySelectorAll('a').forEach(a => a.target = '_blank');
                });
            }

            let globalReviewsChart = null;
            let allLanguageData = [];

            const steamLanguages = {
                'english': 'Английский', 'german': 'Немецкий', 'french': 'Французский', 'italian': 'Итальянский',
                'koreana': 'Корейский', 'spanish': 'Испанский', 'schinese': 'Упр. китайский',
                'tchinese': 'Трад. китайский',
                'russian': 'Русский', 'thai': 'Тайский', 'japanese': 'Японский',
                'portuguese': 'Португальский', 'polish': 'Польский', 'danish': 'Датский', 'dutch': 'Нидерландский',
                'finnish': 'Финский', 'norwegian': 'Норвежский', 'swedish': 'Шведский', 'hungarian': 'Венгерский',
                'czech': 'Чешский', 'romanian': 'Румынский', 'turkish': 'Турецкий', 'bulgarian': 'Болгарский',
                'greek': 'Греческий', 'ukrainian': 'Украинский', 'latam': 'Испанский Лат. Ам.',
                'vietnamese': 'Вьетнамский', 'indonesian': 'Индонезийский', 'brazilian': 'Португ. (Браз.)'
            };

            function openGlobalReviewsModal() {
                let modal = document.getElementById('globalReviewsModal');
                if (!modal) {
                    modal = createGlobalReviewsModalStructure();
                    document.body.appendChild(modal);
                }
                const tableBody = document.getElementById('global-reviews-table-body');
                const noReviewsInfo = document.getElementById('global-reviews-no-reviews-info');
                const collectBtn = document.getElementById('global-reviews-collect-btn');
                const progressBar = document.getElementById('global-reviews-progress-bar');
                const progressText = document.getElementById('global-reviews-progress-text');

                if (tableBody) {
                    tableBody.innerHTML = '<tr><td colspan="6" style="text-align:center; padding: 20px; color: #8f98a0;">Нажмите "Собрать", чтобы загрузить данные.</td></tr>';
                }
                if (noReviewsInfo) {
                    noReviewsInfo.textContent = '';
                } else {
                    console.error("Element with ID 'global-reviews-no-reviews-info' not found during reset!");
                }
                if (collectBtn) {
                    collectBtn.disabled = false;
                }
                if (progressBar) {
                    progressBar.style.width = '0%';
                    progressBar.textContent = '';
                }
                if (progressText) {
                    progressText.textContent = '';
                }

                if (globalReviewsChart) {
                    globalReviewsChart.destroy();
                    globalReviewsChart = null;
                }

                const modalElement = document.getElementById('globalReviewsModal');
                if (modalElement) {
                    modalElement.style.display = 'block';
                } else {
                    console.error("Modal element #globalReviewsModal not found when trying to display!");
                }
                document.body.style.overflow = 'hidden';
            }

            function closeGlobalReviewsModal() {
                const modal = document.getElementById('globalReviewsModal');
                if (modal) {
                    modal.style.display = 'none';
                    if (modal._escHandler) {
                        document.removeEventListener('keydown', modal._escHandler);
                        delete modal._escHandler;
                    }
                }
                document.body.style.overflow = '';
            }

            function createGlobalReviewsModalStructure() {
                const modal = document.createElement('div');
                modal.id = 'globalReviewsModal';
                modal.innerHTML = `
                        <div class="modal-content-inner">
                            <div class="modal-header">
                                <h3 class="modal-title">Глобальный монитор обзоров</h3>
                                <button class="modal-close-btn" title="Закрыть">&times;</button>
                            </div>
                            <div class="modal-body">
                                <div class="modal-left-panel">
                                    <div class="controls-area">
                                        <button id="global-reviews-collect-btn" class="collect-btn">Собрать</button>
                                        <div class="progress-area">
                                            <div class="progress-bar-container">
                                                <div id="global-reviews-progress-bar" class="progress-bar-inner"></div>
                                            </div>
                                            <div id="global-reviews-progress-text" class="progress-text"></div>
                                        </div>
                                    </div>
                                    <div class="table-container">
                                        <table class="reviews-table">
                                            <thead>
                                                <tr>
                                                    <th class="col-rank">#</th>
                                                    <th class="col-check" title="Показать на диаграмме">📊</th>
                                                    <th class="col-lang">Язык</th>
                                                    <th class="col-count">Обзоры</th>
                                                    <th class="col-percent-total">% Общ</th>
                                                    <th class="col-percent-pos">% 👍</th>
                                                </tr>
                                            </thead>
                                            <tbody id="global-reviews-table-body">
                                               <tr><td colspan="6" style="text-align:center; padding: 20px; color: #8f98a0;">Нажмите "Собрать", чтобы загрузить данные.</td></tr>
                                            </tbody>
                                        </table>
                                    </div>
                                    <div id="global-reviews-no-reviews-info" class="no-reviews-info"></div>
                                </div>
                                <div class="modal-right-panel">
                                    <div class="chart-container">
                                        <canvas id="reviewsPieChart"></canvas>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <strong>Внимание:</strong> Загрузка данных для каждого языка отправляет отдельный запрос к Steam.<br>Частое использование на множестве игр может привести к временным ограничениям со стороны Steam.
                            </div>
                        </div>
                    `;

                modal.querySelector('.modal-close-btn').addEventListener('click', closeGlobalReviewsModal);
                modal.querySelector('#global-reviews-collect-btn').addEventListener('click', () => {
                    startGlobalReviewCollection(appidGlobal, russianDataGlobal, schineseDataGlobal);
                });
                modal.addEventListener('click', (event) => {
                    if (event.target === modal) {
                        closeGlobalReviewsModal();
                    }
                });
                modal._escHandler = (event) => {
                    if (event.key === "Escape") {
                        closeGlobalReviewsModal();
                    }
                };
                document.addEventListener('keydown', modal._escHandler);

                return modal;
            }

            async function startGlobalReviewCollection(appid, existingRussianData, existingSchineseData) {
                const collectBtn = document.getElementById('global-reviews-collect-btn');
                const progressBar = document.getElementById('global-reviews-progress-bar');
                const progressText = document.getElementById('global-reviews-progress-text');
                const tableBody = document.getElementById('global-reviews-table-body');
                const noReviewsInfo = document.getElementById('global-reviews-no-reviews-info');

                if (!collectBtn || !progressBar || !progressText || !tableBody || !noReviewsInfo) {
                    console.error("[Global Reviews Monitor] Could not find all necessary modal elements. Aborting collection.");
                    if (tableBody) tableBody.innerHTML = '<tr><td colspan="6" style="text-align:center; padding: 20px; color: #ff6961;">Ошибка: Не найдены элементы интерфейса. Попробуйте закрыть и снова открыть окно.</td></tr>';
                    return;
                }

                collectBtn.disabled = true;
                tableBody.innerHTML = '<tr><td colspan="6" style="text-align:center; padding: 20px; color: #8f98a0;">Загрузка данных... <span class="spinner"></span></td></tr>';
                noReviewsInfo.textContent = '';
                if (globalReviewsChart) {
                    globalReviewsChart.destroy();
                    globalReviewsChart = null;
                }
                const canvas = document.getElementById('reviewsPieChart');
                if (canvas) {
                    const ctx = canvas.getContext('2d');
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                }

                allLanguageData = [];

                if (existingRussianData && typeof existingRussianData === 'object') {
                    allLanguageData.push({ langCode: 'russian', langName: steamLanguages['russian'], summary: existingRussianData, visible: true, fetched: true });
                } else {
                    allLanguageData.push({ langCode: 'russian', langName: steamLanguages['russian'], summary: null, visible: true, fetched: false });
                }
                if (existingSchineseData && typeof existingSchineseData === 'object') {
                    allLanguageData.push({ langCode: 'schinese', langName: steamLanguages['schinese'], summary: existingSchineseData, visible: true, fetched: true });
                } else {
                    allLanguageData.push({ langCode: 'schinese', langName: steamLanguages['schinese'], summary: null, visible: true, fetched: false });
                }

                const languagesToFetch = Object.keys(steamLanguages).filter(lang => lang !== 'russian' && lang !== 'schinese');
                const totalLanguagesToFetch = languagesToFetch.length;
                let completedFetches = 0;
                let errors = 0;

                const updateProgress = () => {
                    const totalCompleted = completedFetches + errors;
                    const percentage = totalLanguagesToFetch > 0 ? Math.round((totalCompleted / totalLanguagesToFetch) * 100) : 100;
                    if (progressBar) {
                        progressBar.style.width = `${percentage}%`;
                        progressBar.textContent = `${percentage}%`;
                    }
                    if (progressText) {
                        progressText.textContent = `Обработано: ${totalCompleted} из ${totalLanguagesToFetch} языков (Успешно: ${completedFetches}, Ошибок: ${errors})`;
                    }
                };

                progressBar.textContent = '';
                updateProgress();

                for (const langCode of languagesToFetch) {
                    if (!appid) {
                        console.error("[Global Reviews Monitor] AppID is missing, stopping fetch loop.");
                        if (progressText) progressText.textContent = 'Ошибка: AppID не найден.';
                        if (collectBtn) collectBtn.disabled = false;
                        return;
                    }

                    const langName = steamLanguages[langCode];
                    try {
                        const summaryData = await new Promise((resolve) => {
                            fetchReviews(appid, langCode, resolve);
                        });

                        const existingIndex = allLanguageData.findIndex(d => d.langCode === langCode);
                        if (existingIndex > -1) {
                            allLanguageData[existingIndex].summary = summaryData;
                            allLanguageData[existingIndex].fetched = (summaryData !== null);
                        } else {
                            allLanguageData.push({ langCode, langName, summary: summaryData, visible: true, fetched: (summaryData !== null) });
                        }

                        if (summaryData !== null) {
                            completedFetches++;
                        } else {
                            errors++;
                        }
                    } catch (error) {
                        console.error(`Error processing fetch for ${langName}:`, error);
                        const existingIndex = allLanguageData.findIndex(d => d.langCode === langCode);
                        if (existingIndex === -1) {
                            allLanguageData.push({ langCode, langName, summary: null, visible: true, fetched: false });
                        }
                        errors++;
                    }
                    updateProgress();
                    await new Promise(resolve => setTimeout(resolve, 200));
                }

                renderGlobalReviewResults();
                if (collectBtn) collectBtn.disabled = false;
                if (progressText) progressText.textContent += ' - Готово!';
            }

            function renderGlobalReviewResults() {
                const tableBody = document.getElementById('global-reviews-table-body');
                const noReviewsInfo = document.getElementById('global-reviews-no-reviews-info');
                if (!tableBody || !noReviewsInfo) return;

                tableBody.innerHTML = '';
                noReviewsInfo.textContent = '';

                const languagesWithErrors = allLanguageData.filter(data => !data.fetched && data.summary === null);
                const validLanguageData = allLanguageData.filter(data => data.fetched && data.summary !== null);
                const languagesWithZeroReviews = [];

                const totalReviews = validLanguageData.reduce((sum, data) => sum + (data.summary?.total_reviews || 0), 0);

                validLanguageData.sort((a, b) => (b.summary?.total_reviews || 0) - (a.summary?.total_reviews || 0));

                if (validLanguageData.length === 0 && languagesWithErrors.length === 0) {
                    tableBody.innerHTML = '<tr><td colspan="6" style="text-align:center; padding: 20px; color: #8f98a0;">Нет обзоров ни на одном языке или не удалось загрузить данные.</td></tr>';
                    return;
                } else if (validLanguageData.length === 0 && languagesWithErrors.length > 0) {
                    tableBody.innerHTML = '<tr><td colspan="6" style="text-align:center; padding: 20px; color: #ff6961;">Не удалось загрузить данные об обзорах.</td></tr>';
                }

                validLanguageData.forEach((data, index) => {
                    const summary = data.summary;
                    const reviewCount = summary?.total_reviews || 0;
                    const positiveCount = summary?.total_positive || 0;
                    const percentTotal = totalReviews > 0 ? ((reviewCount / totalReviews) * 100).toFixed(1) : '0.0';
                    const percentPositive = reviewCount > 0 ? Math.round((positiveCount / reviewCount) * 100) : 0;
                    const reviewClass = getReviewClass(percentPositive, reviewCount);

                    if (reviewCount === 0) {
                        languagesWithZeroReviews.push(data.langName);
                        return;
                    }

                    const row = document.createElement('tr');
                    row.dataset.langCode = data.langCode;
                    row.innerHTML = `
                            <td class="col-rank">${index + 1}</td>
                            <td class="col-check"><input type="checkbox" class="chart-toggle-checkbox" data-lang-code="${data.langCode}" ${data.visible ? 'checked' : ''}></td>
                            <td class="col-lang">${data.langName}</td>
                            <td class="col-count">${formatNumber(reviewCount)}</td>
                            <td class="col-percent-total">${percentTotal}%</td>
                            <td class="col-percent-pos"><span class="game_review_summary ${reviewClass}">${reviewCount > 0 ? percentPositive + '%' : '-'}</span></td>
                        `;
                    tableBody.appendChild(row);
                });

                tableBody.querySelectorAll('.chart-toggle-checkbox').forEach(checkbox => {
                    checkbox.addEventListener('change', handleChartToggle);
                });

                let infoTextParts = [];
                if (languagesWithZeroReviews.length > 0) {
                    infoTextParts.push(`На этих языках нет обзоров: ${languagesWithZeroReviews.join(', ')}`);
                }
                if (languagesWithErrors.length > 0) {
                    infoTextParts.push(`Ошибки загрузки для: ${languagesWithErrors.map(l => l.langName).join(', ')}`);
                }
                noReviewsInfo.textContent = infoTextParts.join('. ');

                updateGlobalReviewsChart();
            }

            function handleChartToggle(event) {
                const langCode = event.target.dataset.langCode;
                const isVisible = event.target.checked;

                const langData = allLanguageData.find(d => d.langCode === langCode);
                if (langData) {
                    langData.visible = isVisible;
                }
                updateGlobalReviewsChart();
            }

            function updateGlobalReviewsChart() {
                const ctx = document.getElementById('reviewsPieChart')?.getContext('2d');
                if (!ctx) return;

                const visibleData = allLanguageData
                    .filter(data => data.visible && data.summary && data.summary.total_reviews > 0)
                    .sort((a, b) => (b.summary?.total_reviews || 0) - (a.summary?.total_reviews || 0));

                const chartLabels = [];
                const chartDataPoints = [];
                const chartColors = [];
                let otherCount = 0;
                const otherLanguagesTooltipDetails = [];

                const topN = 6;

                const totalVisibleReviews = visibleData.reduce((sum, data) => sum + data.summary.total_reviews, 0);

                const colorPalette = [
                    '#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b',
                    '#e377c2', '#7f7f7f', '#bcbd22', '#17becf', '#aec7e8', '#ffbb78',
                    '#98df8a', '#ff9896', '#c5b0d5', '#c49c94', '#f7b6d2', '#c7c7c7',
                    '#dbdb8d', '#9edae5'
                ];

                visibleData.forEach((data, index) => {
                    const count = data.summary.total_reviews;
                    if (index < topN) {
                        chartLabels.push(data.langName);
                        chartDataPoints.push(count);
                        chartColors.push(colorPalette[index % colorPalette.length]);
                    } else {
                        otherCount += count;
                        otherLanguagesTooltipDetails.push(`${data.langName}: ${formatNumber(count)}`);
                    }
                });

                if (otherCount > 0) {
                    chartLabels.push('Другие');
                    chartDataPoints.push(otherCount);
                    chartColors.push('#808080');
                }

                if (globalReviewsChart) {
                    globalReviewsChart.destroy();
                    globalReviewsChart = null;
                }

                if (chartDataPoints.length > 0) {
                    globalReviewsChart = new Chart(ctx, {
                        type: 'pie',
                        data: {
                            labels: chartLabels,
                            datasets: [{
                                data: chartDataPoints,
                                backgroundColor: chartColors,
                                borderColor: '#101822',
                                borderWidth: 2,
                                hoverOffset: 8,
                                hoverBorderColor: '#FFF'
                            }]
                        },
                        options: {
                            responsive: true,
                            maintainAspectRatio: false,
                            animation: {
                                animateScale: true,
                                animateRotate: true
                            },
                            plugins: {
                                legend: {
                                    position: 'right',
                                    align: 'center',
                                    labels: {
                                        color: '#c6d4df',
                                        padding: 12,
                                        font: { size: 12 },
                                        boxWidth: 12,
                                        usePointStyle: true,
                                    }
                                },
                                tooltip: {
                                    callbacks: {
                                        label: function(context) {
                                            let label = context.label || '';
                                            const value = context.parsed || 0;
                                            const percentage = totalVisibleReviews > 0 ? ((value / totalVisibleReviews) * 100).toFixed(1) : 0;
                                            let tooltipText = [];

                                            if (label) {
                                                tooltipText.push(`${label}: ${formatNumber(value)} (${percentage}%)`);
                                            }

                                            if (context.label === 'Другие' && otherLanguagesTooltipDetails.length > 0) {
                                                tooltipText.push('');
                                                tooltipText.push('Включает:');
                                                const maxTooltipItems = 10;
                                                const displayedItems = otherLanguagesTooltipDetails.slice(0, maxTooltipItems);
                                                const remainingItems = otherLanguagesTooltipDetails.length - maxTooltipItems;
                                                tooltipText.push(...displayedItems);
                                                if (remainingItems > 0) {
                                                    tooltipText.push(`...и еще ${remainingItems}`);
                                                }
                                            }
                                            return tooltipText;
                                        }
                                    },
                                    backgroundColor: 'rgba(16, 24, 34, 0.9)',
                                    titleFont: { size: 13, weight: 'bold' },
                                    bodyFont: { size: 12 },
                                    padding: 10,
                                    cornerRadius: 4,
                                    bodySpacing: 4,
                                    multiKeyBackground: 'transparent'
                                },
                                datalabels: {
                                    formatter: (value, ctx) => {
                                        const percentage = totalVisibleReviews > 0 ? ((value / totalVisibleReviews) * 100) : 0;
                                        if (percentage < 3) {
                                            return null;
                                        }
                                        let label = ctx.chart.data.labels[ctx.dataIndex] || '';
                                        if (label.length > 15 && label !== 'Другие') {
                                            const parts = label.split(' ');
                                            label = parts.length > 1 ? parts[0] : label.substring(0, 12) + '...';
                                        }
                                        return `${label}\n${percentage.toFixed(0)}%`;
                                    },
                                    color: '#FFFFFF',
                                    font: {
                                        weight: 'bold',
                                        size: 12,
                                        family: '"Motiva Sans", Arial, sans-serif'
                                    },
                                    backgroundColor: 'rgba(16, 24, 34, 0.75)',
                                    borderRadius: 3,
                                    padding: {
                                        top: 3,
                                        bottom: 3,
                                        left: 6,
                                        right: 6
                                    },
                                    anchor: 'end',
                                    align: 'start',
                                    offset: 15,
                                    display: function(context) {
                                        const percentage = totalVisibleReviews > 0 ? ((context.dataset.data[context.dataIndex] / totalVisibleReviews) * 100) : 0;
                                        return percentage >= 3;
                                    },
                                }
                            },
                            layout: {
                                padding: {
                                    top: 25,
                                    bottom: 25,
                                    left: 25,
                                    right: 25
                                }
                            }
                        }
                    });
                } else {
                    const canvas = document.getElementById('reviewsPieChart');
                    if (canvas) {
                        const ctx = canvas.getContext('2d');
                        ctx.clearRect(0, 0, canvas.width, canvas.height);
                        ctx.fillStyle = '#8f98a0';
                        ctx.textAlign = 'center';
                        ctx.font = '14px "Motiva Sans", Arial, sans-serif';
                        ctx.fillText('Нет данных для отображения диаграммы', canvas.width / 2, canvas.height / 2);
                    }
                }
            }

            function getLanguageColor(index) {
                const colors = [
                    '#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b',
                    '#e377c2', '#7f7f7f', '#bcbd22', '#17becf', '#aec7e8', '#ffbb78',
                    '#98df8a', '#ff9896', '#c5b0d5', '#c49c94', '#f7b6d2', '#c7c7c7',
                    '#dbdb8d', '#9edae5'
                ];
                return colors[index % colors.length];
            }

            function main() {
                addStyles();
                addRussianIndicators();
                addLoadButton();
            }

            const observer = new MutationObserver((mutations, obs) => {
                const reviewsContainer = document.querySelector('.user_reviews');
                const headerImage = document.querySelector('#gameHeaderImageCtn');
                const langTable = document.querySelector('#languageTable');

                if (headerImage) {
                    main();
                    obs.disconnect();
                }
            });

            observer.observe(document.body, {
                childList: true,
                subtree: true
            });

        })();
    }

    // Скрипт для страницы игры (HLTB; получение сведений о времени прохождения) | https://store.steampowered.com/app/*
    if (window.location.pathname.includes('/app/') && scriptsConfig.hltbData) {
        (async function() {
            let hltbBlock = document.createElement('div');
            Object.assign(hltbBlock.style, {
                position: 'absolute',
                top: '0',
                left: '334px',
                width: '30px',
                height: '30px',
                background: 'rgba(27, 40, 56, 0.95)',
                padding: '15px',
                borderRadius: '4px',
                border: '1px solid #3c3c3c',
                boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)',
                zIndex: '2',
                fontFamily: 'Arial, sans-serif',
                overflow: 'hidden',
                opacity: '0',
                transition: 'opacity 0.3s ease, width 0.3s ease, height 0.3s ease'
            });

            let triangle = document.createElement('div');
            triangle.className = 'triangle-down';
            Object.assign(triangle.style, {
                position: 'absolute',
                bottom: '5px',
                left: '50%',
                transform: 'translateX(-50%)',
                width: '0',
                height: '0',
                borderLeft: '5px solid transparent',
                borderRight: '5px solid transparent',
                borderTop: '5px solid #67c1f5',
                cursor: 'pointer'
            });

            let title = document.createElement('div');
            Object.assign(title.style, {
                fontSize: '12px',
                fontWeight: 'bold',
                color: '#67c1f5',
                marginBottom: '10px',
                cursor: 'pointer'
            });
            title.textContent = 'HLTB';

            let content = document.createElement('div');
            Object.assign(content.style, {
                fontSize: '14px',
                color: '#c6d4df',
                display: 'none',
                whiteSpace: 'auto',
                padding: '0 0'
            });

            hltbBlock.append(triangle, title, content);
            document.querySelector('#gameHeaderImageCtn').appendChild(hltbBlock);

            let hltb_gameHeaderImageCtnNode = null;
            let hltb_gameHeaderImageCtnObserverInstance = null;
            let hltb_russianIndicatorsNode = null;
            let hltb_russianIndicatorsObserverInstance = null;


            const fadeInElement = (element) => {
                element.style.opacity = '0';
                requestAnimationFrame(() => {
                    element.style.opacity = '1';
                });
            };

            const updateHltbPosition = () => {
                let topPosition = '0px';
                if (scriptsConfig.gamePage) {
                    const russianIndicators = document.querySelector('#gameHeaderImageCtn > div[style*="position: absolute; top: -10px; left: calc(100% + 10px);"]');
                    if (russianIndicators) {
                        topPosition = `${russianIndicators.offsetTop + russianIndicators.offsetHeight + 16}px`;
                    }
                }
                hltbBlock.style.top = topPosition;
                hltbBlock.style.left = '334px';
                if (hltbBlock.style.opacity === '0') {
                    fadeInElement(hltbBlock);
                }
            };

            const hltb_manageRussianIndicatorsObserver = () => {
                const currentRussianIndicators = document.querySelector('#gameHeaderImageCtn > div[style*="position: absolute; top: -10px; left: calc(100% + 10px);"]');

                if (currentRussianIndicators) {
                    if (currentRussianIndicators !== hltb_russianIndicatorsNode || !hltb_russianIndicatorsObserverInstance) {
                        if (hltb_russianIndicatorsObserverInstance) {
                            hltb_russianIndicatorsObserverInstance.disconnect();
                        }
                        hltb_russianIndicatorsNode = currentRussianIndicators;
                        if (scriptsConfig.gamePage) {
                            hltb_russianIndicatorsObserverInstance = new MutationObserver(() => {
                                updateHltbPosition();
                            });
                            hltb_russianIndicatorsObserverInstance.observe(hltb_russianIndicatorsNode, {
                                attributes: true,
                                childList: true,
                                subtree: true
                            });
                        }
                    }
                } else {
                    if (hltb_russianIndicatorsObserverInstance) {
                        hltb_russianIndicatorsObserverInstance.disconnect();
                        hltb_russianIndicatorsObserverInstance = null;
                    }
                    hltb_russianIndicatorsNode = null;
                }
            };

            const hltb_setupPageChangeObservers = () => {
                hltb_gameHeaderImageCtnNode = document.querySelector('#gameHeaderImageCtn');
                if (!hltb_gameHeaderImageCtnNode) {
                    console.warn("HLTB: #gameHeaderImageCtn not found for main observer.");
                    return;
                }

                if (hltb_gameHeaderImageCtnObserverInstance) {
                    hltb_gameHeaderImageCtnObserverInstance.disconnect();
                }

                hltb_gameHeaderImageCtnObserverInstance = new MutationObserver((mutations) => {
                    let needsPosUpdateDueToContainerChange = false;
                    let russianIndicatorsPotentiallyChanged = false;

                    for (const mutation of mutations) {
                        if (mutation.type === 'childList') {
                            russianIndicatorsPotentiallyChanged = true;
                            needsPosUpdateDueToContainerChange = true;
                            break;
                        }
                    }

                    if (russianIndicatorsPotentiallyChanged) {
                        hltb_manageRussianIndicatorsObserver();
                    }
                    if (needsPosUpdateDueToContainerChange) {
                        updateHltbPosition();
                    }
                });

                hltb_gameHeaderImageCtnObserverInstance.observe(hltb_gameHeaderImageCtnNode, {
                    childList: true,
                    subtree: true
                });
                hltb_manageRussianIndicatorsObserver();
            };

            updateHltbPosition();
            hltb_setupPageChangeObservers();


            const handleClick = async function() {
                if (content.style.display === 'none') {
                    hltbBlock.style.transition = 'width 0.3s ease, height 0.3s ease';
                    updateHltbPosition();
                    await new Promise(resolve => setTimeout(resolve, 50));

                    hltbBlock.style.width = '200px';
                    hltbBlock.style.height = '40px';
                    await new Promise(resolve => setTimeout(resolve, 300));

                    content.textContent = 'Ищем в базе...';
                    content.style.display = 'block';
                    triangle.classList.remove('triangle-down');
                    triangle.classList.add('triangle-up');
                    triangle.style.borderTop = 'none';
                    triangle.style.borderBottom = '5px solid #67c1f5';

                    let gameName = getGameName();
                    let gameNameNormalized = normalizeGameName(gameName);
                    let orangutanFetchUrl = 'https://umadb.ro/hltb/fetch.php';
                    let orangutanHltbUrl = "https://howlongtobeat.com";

                    try {
                        const response = await new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: orangutanFetchUrl,
                                onload: resolve,
                                onerror: reject,
                                ontimeout: reject,
                                timeout: 7000
                            });
                        });
                        if (response.status === 200) {
                            const key = response.responseText.trim();
                            orangutanHltbUrl = "https://howlongtobeat.com" + key;
                        } else {
                            throw new Error('Failed to fetch key. Status: ' + response.status);
                        }
                    } catch (error) {
                        content.textContent = 'Ошибка при получении ключа.';
                        return;
                    }

                    let chimpQuery = '{"searchType":"games","searchTerms":[' + gameNameNormalized + '],"searchPage":1,"size":20,"searchOptions":{"games":{"userId":0,"platform":"","sortCategory":"popular","rangeCategory":"main","rangeTime":{"min":null,"max":null},"gameplay":{"perspective":"","flow":"","genre":"","difficulty":""},"rangeYear":{"min":"","max":""},"modifier":""},"users":{"sortCategory":"postcount"},"lists":{"sortCategory":"follows"},"filter":"","sort":0,"randomizer":0},"useCache":true}';
                    GM_xmlhttpRequest({
                        method: "POST",
                        url: orangutanHltbUrl,
                        data: chimpQuery,
                        headers: {
                            "Content-Type": "application/json",
                            "origin": "https://howlongtobeat.com",
                            "referer": "https://howlongtobeat.com/"
                        },
                        onload: async function(response) {
                            let baboonData = { count: 0, data: [] };
                            if (!response.responseText.includes("<title>HowLongToBeat - 404</title>")) {
                                try {
                                    baboonData = JSON.parse(response.responseText);
                                } catch (e) {
                                    content.textContent = 'Ошибка при обработке данных.';
                                    return;
                                }
                            }

                            if (baboonData.count === 0 && /[а-яё]/i.test(gameName)) {
                                const appId = unsafeWindow.location.pathname.split('/')[2];
                                const steamApiUrl = `https://api.steampowered.com/IStoreBrowseService/GetItems/v1?input_json={"ids": [{"appid": ${appId}}], "context": {"language": "english", "country_code": "US", "steam_realm": 1}, "data_request": {"include_assets": true}}`;
                                try {
                                    const steamResponse = await new Promise((resolve, reject) => {
                                        GM_xmlhttpRequest({
                                            method: "GET",
                                            url: steamApiUrl,
                                            onload: resolve,
                                            onerror: reject
                                        });
                                    });
                                    if (steamResponse.status === 200) {
                                        const steamData = JSON.parse(steamResponse.responseText);
                                        const englishName = steamData.response.store_items[0]?.name;
                                        if (englishName) {
                                            gameName = englishName;
                                            gameNameNormalized = normalizeGameName(gameName);
                                            chimpQuery = '{"searchType":"games","searchTerms":[' + gameNameNormalized + '],"searchPage":1,"size":20,"searchOptions":{"games":{"userId":0,"platform":"","sortCategory":"popular","rangeCategory":"main","rangeTime":{"min":null,"max":null},"gameplay":{"perspective":"","flow":"","genre":"","difficulty":""},"rangeYear":{"min":"","max":""},"modifier":""},"users":{"sortCategory":"postcount"},"lists":{"sortCategory":"follows"},"filter":"","sort":0,"randomizer":0},"useCache":true}';
                                            const secondResponse = await new Promise((resolve, reject) => {
                                                GM_xmlhttpRequest({
                                                    method: "POST",
                                                    url: orangutanHltbUrl,
                                                    data: chimpQuery,
                                                    headers: {
                                                        "Content-Type": "application/json",
                                                        "origin": "https://howlongtobeat.com",
                                                        "referer": "https://howlongtobeat.com/"
                                                    },
                                                    onload: resolve,
                                                    onerror: reject
                                                });
                                            });
                                            if (secondResponse.status === 200) {
                                                baboonData = JSON.parse(secondResponse.responseText);
                                            }
                                        }
                                    }
                                } catch (error) {
                                    console.error('Ошибка при запросе к Steam API:', error);
                                }
                            }

                            if (baboonData.count > 0) {
                                const matches = findPossibleMatches(gameName, baboonData.data);
                                if (matches.length > 0) {
                                    renderPossibleMatches(matches);
                                    hltbBlock.style.height = `${content.scrollHeight + 30}px`;
                                    return;
                                }
                            }
                            renderContent(baboonData.data[0]);
                            hltbBlock.style.height = `${content.scrollHeight + 30}px`;
                        },
                        onerror: function(error) { content.textContent = 'Ошибка при запросе к HLTB.'; },
                        ontimeout: function() { content.textContent = 'Тайм-аут при запросе к HLTB.'; },
                        timeout: 10000
                    });
                } else {
                    content.style.display = 'none';
                    hltbBlock.style.height = '30px';
                    hltbBlock.style.width = '30px';
                    triangle.classList.remove('triangle-up');
                    triangle.classList.add('triangle-down');
                    triangle.style.borderBottom = 'none';
                    triangle.style.borderTop = '5px solid #67c1f5';
                }
            };

            title.onclick = handleClick;
            triangle.onclick = handleClick;
            window.addEventListener('resize', updateHltbPosition);

            function normalizeGameName(name) {
                return name.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zа-яё0-9 _'\-!]/gi, '').toLowerCase().split(/\s+/).map(word => `"${word}"`).join(",");
            }

            function findPossibleMatches(gameName, data) {
                const cleanGameName = gameName.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zа-яё0-9 _'\-!]/gi, '').toLowerCase();
                return data.map(item => {
                    const cleanItemName = item.game_name.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zа-яё0-9 _'\-!]/gi, '').toLowerCase();
                    const similarity = calculateSimilarity(cleanGameName, cleanItemName);
                    const startsWith = cleanItemName.startsWith(cleanGameName);
                    return { ...item, percentage: similarity, startsWith: startsWith };
                }).filter(item => item.percentage > 50 || item.startsWith)
                .sort((a, b) => {
                    if (a.startsWith && !b.startsWith) return -1;
                    if (!a.startsWith && b.startsWith) return 1;
                    return b.percentage - a.percentage;
                }).slice(0, 5);
            }

            function calculateSimilarity(str1, str2) {
                const len = Math.max(str1.length, str2.length);
                if (len === 0) return 100;
                const distance = levenshteinDistance(str1, str2);
                return Math.round(((len - distance) / len) * 100);
            }

            function levenshteinDistance(str1, str2) {
                const m = str1.length; const n = str2.length;
                const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
                for (let i = 0; i <= m; i++) {
                    for (let j = 0; j <= n; j++) {
                        if (i === 0) dp[i][j] = j;
                        else if (j === 0) dp[i][j] = i;
                        else dp[i][j] = Math.min(dp[i - 1][j - 1] + (str1[i - 1] === str2[j - 1] ? 0 : 1), dp[i - 1][j] + 1, dp[i][j - 1] + 1);
                    }
                }
                return dp[m][n];
            }

            function getTextWidth(text, font) {
                const canvas = document.createElement('canvas'); const context = canvas.getContext('2d');
                context.font = font; const metrics = context.measureText(text); return metrics.width;
            }

            function renderPossibleMatches(matches) {
                content.innerHTML = '';
                const title = document.createElement('div');
                title.textContent = 'Возможные совпадения:';
                title.style.color = '#67c1f5'; title.style.marginBottom = '10px'; content.appendChild(title);
                const list = document.createElement('ul');
                list.style.paddingLeft = '15px'; list.style.marginTop = '5px'; list.style.marginBottom = '0';
                matches.forEach(match => {
                    const li = document.createElement('li'); li.style.marginBottom = '8px';
                    const link = document.createElement('a'); link.href = '#';
                    link.textContent = `${match.game_name} (${match.percentage}%)`;
                    link.style.color = '#c6d4df'; link.style.wordBreak = 'break-word'; link.style.textDecoration = 'none';
                    link.onclick = () => { renderContent(match); hltbBlock.style.height = `${content.scrollHeight + 30}px`; return false; };
                    li.appendChild(link); list.appendChild(li);
                });
                const noMatch = document.createElement('li'); noMatch.style.marginBottom = '8px';
                const noMatchLink = document.createElement('a'); noMatchLink.href = '#';
                noMatchLink.textContent = 'Ничего не подходит';
                noMatchLink.style.color = '#c6d4df'; noMatchLink.style.wordBreak = 'break-word'; noMatchLink.style.textDecoration = 'none';
                noMatchLink.onclick = () => { renderContent(null); hltbBlock.style.height = `${content.scrollHeight + 30}px`; return false; };
                noMatch.appendChild(noMatchLink); list.appendChild(noMatch); content.appendChild(list);
                let maxWidth = 0;
                content.querySelectorAll('a').forEach(link => {
                    const text = link.textContent; const font = window.getComputedStyle(link).font;
                    const width = getTextWidth(text, font); if (width > maxWidth) maxWidth = width;
                });
                hltbBlock.style.width = `${Math.max(maxWidth + 40, 250)}px`;
            }

            function renderContent(entry) {
                content.innerHTML = '';
                if (!entry) { content.textContent = 'Игра не найдена в базе HLTB'; return; }
                const titleLink = document.createElement('a');
                titleLink.href = `https://howlongtobeat.com/game/${entry.game_id}`; titleLink.target = '_blank';
                titleLink.textContent = entry.game_name || 'Без названия';
                titleLink.style.color = '#67c1f5'; titleLink.style.wordBreak = 'break-word'; content.appendChild(titleLink);
                const list = document.createElement('ul');
                list.style.paddingLeft = '15px'; list.style.marginTop = '5px'; list.style.marginBottom = '0';
                const times = [
                    { label: 'Только сюжет', time: entry.comp_main, count: entry.comp_main_count },
                    { label: 'Сюжет + доп.', time: entry.comp_plus, count: entry.comp_plus_count },
                    { label: 'Комплеционист', time: entry.comp_100, count: entry.comp_100_count },
                    { label: 'Все стили', time: entry.comp_all, count: entry.comp_all_count }
                ];
                times.forEach(time => {
                    const li = document.createElement('li'); li.style.marginBottom = '8px';
                    const timeText = time.time ? formatTime(time.time) : "X";
                    li.innerHTML = `${time.label}: <span style="color: #fff;">${timeText}</span> (${time.count} чел.)`;
                    list.appendChild(li);
                });
                content.appendChild(list);
                let maxWidth = 0;
                content.querySelectorAll('li').forEach(child => {
                    const text = child.textContent; const font = window.getComputedStyle(child).font;
                    const width = getTextWidth(text, font); if (width > maxWidth) maxWidth = width;
                });
                hltbBlock.style.width = `${Math.max(maxWidth + 30, 200)}px`;
                hltbBlock.style.whiteSpace = 'nowrap';
            }

            function formatTime(seconds) {
                const hours = Math.floor(seconds / 3600); const minutes = Math.round((seconds % 3600) / 60);
                if (hours === 0) return `${minutes} м.`;
                else if (hours + (minutes / 60) >= hours + 0.5) return `${hours + 1} ч.`;
                else return `${hours} ч.`;
            }

            function getGameName() {
                return document.querySelector('.apphub_AppName').textContent.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[’]/g, "'").replace(/[^a-zA-Zа-яёА-ЯЁ0-9 _'\-!]/g, '').trim().toLowerCase();
            }

            if (scriptsConfig.autoExpandHltb) {
                handleClick();
            }
        })();
    }

    // Скрипт для страницы игры (ZOG; получение сведений о наличии русификаторов) | https://store.steampowered.com/app/*
    if (window.location.pathname.includes('/app/') && scriptsConfig.zogInfo) {
        (async function() {
            const zogBlock = document.createElement('div');
            Object.assign(zogBlock.style, {
                position: 'absolute', left: '334px', width: '30px', height: '30px',
                background: 'rgba(27, 40, 56, 0.95)', padding: '15px', borderRadius: '4px',
                border: '1px solid #3c3c3c', boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)',
                zIndex: '2', fontFamily: 'Arial, sans-serif', overflow: 'hidden',
                transition: 'all 0.3s ease', visibility: 'hidden', opacity: '0'
            });

            let hltbBlockElement, hltbObserverInstance, hltbTransitionHandlerFunc,
                russianIndicatorsNode, russianIndicatorsObserverInstance,
                gameHeaderImageCtnNode, gameHeaderImageCtnObserverInstance;
            let isFirstUpdate = true;

            const alphabetMap = {
                'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10,
                'k': 11, 'l': 12, 'm': 13, 'n': 14, 'o': 15, 'p': 16, 'q': 17, 'r': 18, 's': 19,
                't': 20, 'u': 21, 'v': 22, 'w': 23, 'x': 24, 'y': 25, 'z': 26, '#': 0
            };
            const russianAlphabetMap = {
                'а': 1, 'б': 2, 'в': 3, 'г': 4, 'д': 5, 'е': 6, 'ё': 6, 'ж': 7, 'з': 8, 'и': 9,
                'й': 9, 'к': 10, 'л': 11, 'м': 12, 'н': 13, 'о': 14, 'п': 15, 'р': 16, 'с': 17,
                'т': 18, 'у': 19, 'ф': 20, 'х': 21, 'ц': 22, 'ч': 23, 'ш': 24, 'щ': 25, 'э': 26,
                'ю': 27, 'я': 28
            };

            const updatePosition = () => {
                const localHltbBlock = document.querySelector('#gameHeaderImageCtn > div[style*="background: rgba(27, 40, 56, 0.95)"]');
                const localRussianIndicators = document.querySelector('#gameHeaderImageCtn > div[style*="position: absolute; top: -10px; left: calc(100% + 10px);"]');
                if (localHltbBlock && scriptsConfig.hltbData) {
                    zogBlock.style.top = `${localHltbBlock.offsetTop + localHltbBlock.offsetHeight + 16}px`;
                } else if (localRussianIndicators && scriptsConfig.gamePage) {
                    zogBlock.style.top = `${localRussianIndicators.offsetTop + localRussianIndicators.offsetHeight + 16}px`;
                } else {
                    if (document.querySelector('#gameHeaderImageCtn')) zogBlock.style.top = '0px';
                }
                zogBlock.style.left = '334px';
                zogBlock.style.zIndex = '2';
                if (isFirstUpdate) {
                    requestAnimationFrame(() => {
                        zogBlock.style.visibility = 'visible';
                        zogBlock.style.opacity = '1';
                    });
                    isFirstUpdate = false;
                }
            };

            const manageHltbObserver = () => {
                const currentHltbBlock = document.querySelector('#gameHeaderImageCtn > div[style*="background: rgba(27, 40, 56, 0.95)"]');
                if (currentHltbBlock) {
                    if (currentHltbBlock !== hltbBlockElement) {
                        if (hltbObserverInstance) hltbObserverInstance.disconnect();
                        if (hltbBlockElement && hltbTransitionHandlerFunc) hltbBlockElement.removeEventListener('transitionend', hltbTransitionHandlerFunc);
                        hltbBlockElement = currentHltbBlock;
                        if (scriptsConfig.hltbData) {
                            hltbObserverInstance = new ResizeObserver(updatePosition);
                            hltbObserverInstance.observe(hltbBlockElement);
                            hltbTransitionHandlerFunc = updatePosition;
                            hltbBlockElement.addEventListener('transitionend', hltbTransitionHandlerFunc);
                        }
                    }
                } else {
                    if (hltbObserverInstance) hltbObserverInstance.disconnect();
                    if (hltbBlockElement && hltbTransitionHandlerFunc) hltbBlockElement.removeEventListener('transitionend', hltbTransitionHandlerFunc);
                    hltbBlockElement = hltbObserverInstance = hltbTransitionHandlerFunc = null;
                }
            };

            const manageRussianIndicatorsObserver = () => {
                const currentIndicators = document.querySelector('#gameHeaderImageCtn > div[style*="position: absolute; top: -10px; left: calc(100% + 10px);"]');
                if (currentIndicators) {
                    if (currentIndicators !== russianIndicatorsNode) {
                        if (russianIndicatorsObserverInstance) russianIndicatorsObserverInstance.disconnect();
                        russianIndicatorsNode = currentIndicators;
                        if (scriptsConfig.gamePage) {
                            russianIndicatorsObserverInstance = new MutationObserver(mutations => mutations.forEach(m => { if (m.type === 'attributes' && m.attributeName === 'style') updatePosition(); }));
                            russianIndicatorsObserverInstance.observe(russianIndicatorsNode, { attributes: true, attributeFilter: ['style'] });
                        }
                    }
                } else {
                    if (russianIndicatorsObserverInstance) russianIndicatorsObserverInstance.disconnect();
                    russianIndicatorsNode = russianIndicatorsObserverInstance = null;
                }
            };

            const initDynamicElementObservers = () => {
                manageHltbObserver();
                manageRussianIndicatorsObserver();
            };

            const setupPageChangeObservers = () => {
                gameHeaderImageCtnNode = document.querySelector('#gameHeaderImageCtn');
                if (!gameHeaderImageCtnNode) return;
                if (gameHeaderImageCtnObserverInstance) gameHeaderImageCtnObserverInstance.disconnect();
                gameHeaderImageCtnObserverInstance = new MutationObserver(mutations => {
                    if (mutations.some(m => m.type === 'childList')) {
                        initDynamicElementObservers();
                        updatePosition();
                    }
                });
                gameHeaderImageCtnObserverInstance.observe(gameHeaderImageCtnNode, { childList: true, subtree: true });
                initDynamicElementObservers();
            };

            const title = document.createElement('div');
            Object.assign(title.style, { fontSize: '12px', fontWeight: 'bold', color: '#67c1f5', marginBottom: '10px', cursor: 'pointer' });
            title.textContent = 'ZOG';

            const content = document.createElement('div');
            Object.assign(content.style, { display: 'none', color: '#c6d4df', fontSize: '14px', maxWidth: '300px', overflowY: 'auto', whiteSpace: 'normal', lineHeight: '1.4', padding: '0 5px' });

            const arrow = document.createElement('div');
            Object.assign(arrow.style, { position: 'absolute', bottom: '5px', left: '50%', width: '0', height: '0', borderLeft: '5px solid transparent', borderRight: '5px solid transparent', borderTop: '5px solid #67c1f5', cursor: 'pointer', transition: 'transform 0.3s ease', transform: 'translateX(-50%)' });

            zogBlock.append(arrow, title, content);
            document.querySelector('#gameHeaderImageCtn').appendChild(zogBlock);

            await new Promise(resolve => setTimeout(resolve, 10));
            setupPageChangeObservers();
            updatePosition();

            const toggleBlock = async (el) => content.style.display === 'none' ? await expandBlock(el) : collapseBlock(el);
            title.onclick = () => toggleBlock(arrow);
            arrow.onclick = () => toggleBlock(arrow);

            async function expandBlock(arrowElement) {
                Object.assign(zogBlock.style, { transition: 'width 0.3s ease, height 0.3s ease', width: '300px', height: '40px' });
                arrowElement.style.transform = 'translateX(-50%) rotate(180deg)';
                await new Promise(resolve => setTimeout(resolve, 300));
                content.style.display = 'block';
                content.textContent = 'Запрос названия игры...';
                await new Promise(r => requestAnimationFrame(r));
                const englishName = await getEnglishGameName(getAppId()) || getGameName();
                content.textContent = 'Поиск на Zone of Games...';
                await new Promise(r => requestAnimationFrame(r));
                try {
                    const possibleMatches = await findGamesOnZog(englishName);
                    renderPossibleMatches(possibleMatches, englishName);
                    zogBlock.style.height = `${content.scrollHeight + 40}px`;
                    updatePosition();
                } catch (error) {
                    console.error("ZOG Search Error:", error);
                    content.textContent = 'Ошибка поиска на ZOG.';
                }
            }

            function collapseBlock(arrowElement) {
                Object.assign(zogBlock.style, { transition: 'width 0.3s ease, height 0.3s ease', width: '30px', height: '30px' });
                arrowElement.style.transform = 'translateX(-50%) rotate(0deg)';
                content.style.display = 'none';
                content.innerHTML = '';
                updatePosition();
            }

            async function getEnglishGameName(appId) {
                const url = `https://api.steampowered.com/IStoreBrowseService/GetItems/v1?input_json=${JSON.stringify({ ids: [{ appid: parseInt(appId) }], context: { language: "english", country_code: "US" }, data_request: { include_basic_info: true } })}`;
                try {
                    const response = await new Promise((resolve, reject) => GM_xmlhttpRequest({ method: "GET", url, onload: resolve, onerror: reject, ontimeout: reject }));
                    if (response.status === 200) return JSON.parse(response.responseText).response?.store_items?.[0]?.name;
                } catch (e) { console.error('Ошибка при запросе к Steam API:', e); }
                return null;
            }

            async function findGamesOnZog(gameName) {
                const isRussian = /[а-яё]/i.test(gameName);
                const activeMap = isRussian ? russianAlphabetMap : alphabetMap;
                const articles = ['the', 'a', 'an'];
                const words = gameName.toLowerCase().split(' ');
                const searchLetters = new Set();

                if (!isRussian && articles.includes(words[0]) && words.length > 1) {
                    searchLetters.add(words[0][0]);
                    if (activeMap[words[1][0]]) searchLetters.add(words[1][0]);
                } else {
                    let firstChar = gameName.toLowerCase().charAt(0);
                    searchLetters.add(activeMap.hasOwnProperty(firstChar) ? firstChar : '#');
                }

                const allGamesFound = [];
                const uniquePaths = new Set();
                for (const letter of searchLetters) {
                    const isNonAlpha = letter === '#';
                    const pageNum = activeMap[letter];
                    if (pageNum === undefined) continue;
                    const baseUrl = isNonAlpha ? 'https://www.zoneofgames.ru/games/eng/' : (isRussian ? 'https://www.zoneofgames.ru/games/rus/' : 'https://www.zoneofgames.ru/games/eng/');
                    const url = `${baseUrl}${pageNum}/`;
                    try {
                        const response = await new Promise((resolve, reject) => GM_xmlhttpRequest({ method: 'GET', url, onload: resolve, onerror: reject }));
                        const doc = new DOMParser().parseFromString(response.responseText, 'text/html');
                        doc.querySelectorAll('td.gameinfoblock a').forEach(link => {
                            const path = link.getAttribute('href');
                            if (path && !uniquePaths.has(path)) {
                                const rawTitle = link.textContent.trim();
                                const articleMatch = rawTitle.match(/,\s+(The|An|A)$/i);
                                let title = articleMatch ? `${articleMatch[1]} ${rawTitle.replace(articleMatch[0], '').trim()}` : rawTitle;
                                allGamesFound.push({ title, path });
                                uniquePaths.add(path);
                            }
                        });
                    } catch (e) { console.error(`Ошибка при загрузке страницы '${url}':`, e); }
                }
                return allGamesFound;
            }

            async function fetchAndRenderLocalizations(gamePath) {
                const fullUrl = `https://www.zoneofgames.ru${gamePath}`;
                content.innerHTML = 'Загрузка русификаторов...';
                try {
                    const response = await new Promise((resolve, reject) => GM_xmlhttpRequest({ method: 'GET', url: fullUrl, onload: resolve, onerror: reject }));
                    const doc = new DOMParser().parseFromString(response.responseText, 'text/html');
                    const localizations = [];
                    const translationLabel = Array.from(doc.querySelectorAll('b')).find(b => b.textContent.trim() === 'Переводы:');
                    if (translationLabel) {
                        const table = translationLabel.closest('table');
                        if (table) {
                            table.querySelectorAll('tr').forEach(row => {
                                const linkEl = row.querySelector('a');
                                if (linkEl?.getAttribute('href')) {
                                    localizations.push({
                                        name: linkEl.textContent.trim(),
                                        size: row.querySelector('td:last-child')?.textContent.trim() || '',
                                        link: `https://www.zoneofgames.ru${linkEl.getAttribute('href')}`
                                    });
                                }
                            });
                        }
                    }
                    const gameTitle = doc.querySelector('td.blockstyle > b > font')?.textContent.trim() || 'Выбранная игра';
                    renderContent({ title: gameTitle, url: fullUrl, localizations });
                    zogBlock.style.height = `${content.scrollHeight + 40}px`;
                    updatePosition();
                } catch (e) {
                    content.textContent = 'Ошибка загрузки локализаций.';
                    console.error("Ошибка получения страницы игры:", e);
                }
            }

            function renderContent(entry) {
                content.innerHTML = '';
                if (!entry) {
                    content.textContent = 'Игра не найдена в базе ZOG';
                    return;
                }
                const titleLink = Object.assign(document.createElement('a'), { href: entry.url, target: '_blank', textContent: entry.title || 'Без названия' });
                Object.assign(titleLink.style, { color: '#67c1f5', wordBreak: 'break-word', textDecoration: 'none' });
                content.appendChild(titleLink);
                const list = document.createElement('ul');
                Object.assign(list.style, { paddingLeft: '15px', marginTop: '5px', marginBottom: '0' });
                if (entry.localizations?.length > 0) {
                    entry.localizations.forEach(loc => {
                        const li = document.createElement('li');
                        li.style.marginBottom = '8px';
                        const link = Object.assign(document.createElement('a'), { href: loc.link, target: '_blank', textContent: `${loc.name} ${loc.size}` });
                        Object.assign(link.style, { color: '#c6d4df', wordBreak: 'break-word', textDecoration: 'none' });
                        li.appendChild(link);
                        list.appendChild(li);
                    });
                } else {
                    const li = Object.assign(document.createElement('li'), { textContent: 'Русификаторы отсутствуют' });
                    li.style.color = '#999';
                    list.appendChild(li);
                }
                content.appendChild(list);
            }

            function renderPossibleMatches(matches, originalGameName) {
                content.innerHTML = '';
                const title = Object.assign(document.createElement('div'), { textContent: 'Возможные совпадения:' });
                Object.assign(title.style, { color: '#67c1f5', marginBottom: '10px' });
                content.appendChild(title);
                const list = document.createElement('ul');
                Object.assign(list.style, { paddingLeft: '15px', marginTop: '5px', marginBottom: '0' });
                const processedMatches = findPossibleMatches(originalGameName, matches);
                if (processedMatches.length === 0) {
                    renderContent(null);
                    return;
                }
                processedMatches.forEach(match => {
                    const li = document.createElement('li');
                    li.style.marginBottom = '8px';
                    const link = Object.assign(document.createElement('a'), { href: `https://www.zoneofgames.ru${match.item.path}`, target: '_blank', textContent: `${match.item.title} (${match.percentage}%)` });
                    Object.assign(link.style, { color: '#c6d4df', wordBreak: 'break-word', textDecoration: 'none', cursor: 'pointer' });
                    link.onclick = (e) => {
                        e.preventDefault();
                        fetchAndRenderLocalizations(match.item.path);
                    };
                    li.appendChild(link);
                    list.appendChild(li);
                });
                content.appendChild(list);
            }

            function findPossibleMatches(gameName, data) {
                const cleanGameName = gameName.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zа-яё0-9 _'\-!]/gi, '').toLowerCase();
                return data.map(item => {
                        const cleanItemName = item.title.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zа-яё0-9 _'\-!]/gi, '').toLowerCase();
                        return { item, percentage: calculateSimilarity(cleanGameName, cleanItemName), startsWith: cleanItemName.startsWith(cleanGameName) };
                    })
                    .filter(item => item.percentage > 45 || item.startsWith)
                    .sort((a, b) => {
                        if (a.startsWith && !b.startsWith) return -1;
                        if (!a.startsWith && b.startsWith) return 1;
                        return b.percentage - a.percentage;
                    })
                    .slice(0, 5);
            }

            function calculateSimilarity(str1, str2) {
                let longer = str1, shorter = str2;
                if (str1.length < str2.length) { longer = str2; shorter = str1; }
                if (longer.length === 0) return 100.0;
                return Math.round(((longer.length - levenshteinDistance(longer, shorter)) / longer.length) * 100);
            }

            function levenshteinDistance(s1, s2) {
                const costs = [];
                for (let i = 0; i <= s1.length; i++) {
                    let lastValue = i;
                    for (let j = 0; j <= s2.length; j++) {
                        if (i === 0) costs[j] = j;
                        else if (j > 0) {
                            let newValue = costs[j - 1];
                            if (s1.charAt(i - 1) !== s2.charAt(j - 1)) newValue = Math.min(newValue, lastValue, costs[j]) + 1;
                            costs[j - 1] = lastValue;
                            lastValue = newValue;
                        }
                    }
                    if (i > 0) costs[s2.length] = lastValue;
                }
                return costs[s2.length];
            }

            function getAppId() { return unsafeWindow.location.pathname.split('/')[2]; }
            function getGameName() { return document.querySelector('.apphub_AppName')?.textContent.trim() || ''; }
        })();
    }

    // Скрипт для страницы игры (Время друзей & Достижения) | https://store.steampowered.com/app/*
    if (window.location.pathname.includes('/app/') && scriptsConfig.friendsPlaytime) {
        (async function() {
            const appIdMatch = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
            if (!appIdMatch) return;
            const appId = appIdMatch[1];
            const gameName = document.querySelector('#appHubAppName')?.textContent.trim() || 'этой игры';

            async function fetchAndParseAllFriendsData(appId) {
                const url = `https://steamcommunity.com/my/friendsthatplay/${appId}`;
                const results = {
                    recent: {
                        count: 0,
                        blocks: []
                    },
                    ever: {
                        count: 0,
                        blocks: []
                    },
                    own: {
                        count: 0,
                        blocks: []
                    },
                    wishlist: {
                        count: 0,
                        blocks: []
                    }
                };

                try {
                    const response = await new Promise((resolve, reject) => {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: url,
                            timeout: 15000,
                            onload: resolve,
                            onerror: reject,
                            ontimeout: () => reject(new Error('Timeout'))
                        });
                    });

                    if (response.status !== 200) throw new Error(`HTTP Status ${response.status}`);

                    const parser = new DOMParser();
                    const doc = parser.parseFromString(response.responseText, 'text/html');
                    const allHeaders = doc.querySelectorAll('.mainSectionHeader.friendListSectionHeader');

                    const keywords = {
                        recent: ['последние 2 недели', 'последних 2 недель', 'in the last 2 weeks'],
                        ever: ['когда-либо игравшие', 'когда-либо игравшие в', 'previously'],
                        own: ['имеющие', 'имеющие в', 'in their library'],
                        wishlist: ['которые хотят', 'who want']
                    };

                    allHeaders.forEach(header => {
                        const text = header.textContent.trim().toLowerCase();
                        const container = header.nextElementSibling;

                        if (!container || !container.matches('.profile_friends')) return;

                        const blocks = Array.from(container.querySelectorAll('.friendBlock'));
                        const count = blocks.length;

                        for (const key in keywords) {
                            if (keywords[key].some(k => text.includes(k.toLowerCase()))) {
                                results[key] = { count, blocks };
                                break;
                            }
                        }
                    });
                    return results;
                } catch (error) {
                    return results;
                }
            }

            function buildAvatarGrid(blocks) {
                const grid = document.createElement('div');
                grid.className = 'friend_blocks_grid';
                blocks.slice(0, 6).forEach(block => {
                    const profileLink = block.querySelector('a.friendBlockLinkOverlay')?.href;
                    const miniprofile = block.dataset.miniprofile;
                    const avatarImgSrc = block.querySelector('.playerAvatar img')?.src;
                    const statusClass = block.classList.contains('in-game') ? 'friend_status_in-game' : (block.classList.contains('online') ? 'friend_status_online' : 'friend_status_offline');
                    if (!profileLink || !miniprofile || !avatarImgSrc) return;

                    const link = document.createElement('a');
                    link.style.display = 'inline-block';
                    link.href = profileLink;
                    link.className = `friend_block_holder ${statusClass}`;
                    link.dataset.miniprofile = miniprofile;

                    const avatarDiv = document.createElement('div');
                    avatarDiv.className = 'friend_block_avatar';
                    avatarDiv.style.display = 'inline-block';

                    const img = document.createElement('img');
                    img.src = avatarImgSrc;

                    avatarDiv.appendChild(img);
                    link.appendChild(avatarDiv);
                    grid.appendChild(link);
                });
                return grid;
            }

            async function createFriendsInfoBlock() {
                const targetContainer = document.querySelector('.rightcol.game_meta_data');
                if (!targetContainer) return;

                const friendsBlock = document.createElement('div');
                friendsBlock.className = 'block responsive_apppage_details_right recommendation_reasons';
                friendsBlock.innerHTML = `<p class="reason info" style="text-align:center;">Загрузка данных о друзьях (U.S.E.)...</p>`;
                targetContainer.prepend(friendsBlock);

                const data = await fetchAndParseAllFriendsData(appId);

                const getUniqueBlocks = (blocksArrays) => {
                    const unique = new Map();
                    blocksArrays.flat().forEach(block => {
                        const id = block.dataset.miniprofile;
                        if (id && !unique.has(id)) {
                            unique.set(id, block);
                        }
                    });
                    return Array.from(unique.values());
                };

                const allEverPlayedBlocks = getUniqueBlocks([data.recent.blocks, data.ever.blocks]);
                const allOwnedBlocks = getUniqueBlocks([data.recent.blocks, data.ever.blocks, data.own.blocks]);

                let finalHTML = '';

                if (data.recent.count > 0) {
                    finalHTML += `<p class="reason for">Друзей, игравших недавно: ${data.recent.count}</p>`;
                    finalHTML += buildAvatarGrid(data.recent.blocks).outerHTML + '<hr>';
                }

                if (allEverPlayedBlocks.length > 0) {
                    finalHTML += `<p class="reason for"><a href="https://steamcommunity.com/my/friendsthatplay/${appId}" target="_blank">Друзей, когда-либо игравших в игру: ${allEverPlayedBlocks.length}</a></p>`;
                    finalHTML += buildAvatarGrid(allEverPlayedBlocks).outerHTML + '<hr>';
                }

                if (allOwnedBlocks.length > 0) {
                    finalHTML += `<p class="reason for"><a href="https://steamcommunity.com/my/friendsthatplay/${appId}" target="_blank">Друзей, имеющих игру в библиотеке: ${allOwnedBlocks.length}</a></p>`;
                    finalHTML += buildAvatarGrid(allOwnedBlocks).outerHTML + '<hr>';
                }

                if (data.wishlist.count > 0) {
                    finalHTML += `<p class="reason for"><a href="https://steamcommunity.com/my/friendsthatplay/${appId}" target="_blank">Друзей, которые хотят эту игру: ${data.wishlist.count}</a></p>`;
                    finalHTML += buildAvatarGrid(data.wishlist.blocks).outerHTML + '<hr>';
                }

                friendsBlock.innerHTML = finalHTML.length > 0 ? finalHTML.replace(/<hr>$/, '') : `<p class="reason info">Нет данных о действиях друзей с этой игрой.</p>`;
            }

            const recommendationBlock = document.querySelector('.recommendation_reasons');
            if (!recommendationBlock) {
                await createFriendsInfoBlock();
            }

            const headerCtn = document.querySelector('#gameHeaderImageCtn');
            if (headerCtn) {
                const statsBlock = document.createElement('div');
                statsBlock.style.position = 'absolute';
                statsBlock.style.top = '0px';
                statsBlock.style.left = '406px';
                statsBlock.style.width = '30px';
                statsBlock.style.height = '30px';
                statsBlock.style.background = 'rgba(27, 40, 56, 0.95)';
                statsBlock.style.padding = '15px';
                statsBlock.style.borderRadius = '4px';
                statsBlock.style.border = '1px solid #3c3c3c';
                statsBlock.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
                statsBlock.style.zIndex = '1';
                statsBlock.style.fontFamily = 'Arial, sans-serif';
                statsBlock.style.overflow = 'hidden';
                statsBlock.style.transition = 'all 0.3s ease';

                const triangle = document.createElement('div');
                triangle.style.position = 'absolute';
                triangle.style.bottom = '5px';
                triangle.style.left = '50%';
                triangle.style.transform = 'translateX(-50%)';
                triangle.style.width = '0';
                triangle.style.height = '0';
                triangle.style.borderLeft = '5px solid transparent';
                triangle.style.borderRight = '5px solid transparent';
                triangle.style.borderTop = '5px solid #67c1f5';
                triangle.style.cursor = 'pointer';
                statsBlock.appendChild(triangle);

                const title = document.createElement('div');
                title.style.display = 'flex';
                title.style.alignItems = 'center';
                title.style.marginBottom = '7px';
                title.style.cursor = 'pointer';

                const combinedImg = document.createElement('div');
                combinedImg.style.width = '29px';
                combinedImg.style.height = '29px';
                combinedImg.style.backgroundImage = 'url(https://gist.githubusercontent.com/0wn3dg0d/9c259eebc40a1e97397ccf3da7ee7bd6/raw/SUEftach.png)';
                combinedImg.style.backgroundSize = 'contain';
                combinedImg.style.backgroundPosition = 'center';

                title.appendChild(combinedImg);
                statsBlock.appendChild(title);

                const content = document.createElement('div');
                content.style.fontSize = '14px';
                content.style.color = '#c6d4df';
                content.style.display = 'none';
                content.style.padding = '0';
                statsBlock.appendChild(content);

                const toggleBlock = async () => {
                    if (content.style.display === 'none') {
                        statsBlock.style.width = '250px';
                        statsBlock.style.height = '60px';
                        content.style.display = 'block';
                        content.textContent = 'Загрузка...';
                        triangle.style.borderTop = 'none';
                        triangle.style.borderBottom = '5px solid #67c1f5';
                        try {
                            const friendsData = await loadFriendsDataForStats();
                            const achievementsData = await loadAchievementsDataForStats();
                            content.innerHTML = '';
                            const friendsTitle = document.createElement('div');
                            friendsTitle.style.fontSize = '12px';
                            friendsTitle.style.fontWeight = 'bold';
                            friendsTitle.style.color = '#67c1f5';
                            friendsTitle.style.marginBottom = '5px';
                            friendsTitle.textContent = 'ВРЕМЯ ДРУЗЕЙ';
                            content.appendChild(friendsTitle);
                            if (friendsData.length > 0) {
                                const maxHours = Math.max(...friendsData.map(f => f.hours));
                                const minHours = Math.min(...friendsData.map(f => f.hours));
                                const avgHours = friendsData.reduce((sum, f) => sum + f.hours, 0) / friendsData.length;
                                const maxPlayers = friendsData.filter(f => f.hours === maxHours);
                                const maxEl = document.createElement('div');
                                maxEl.style.marginBottom = '4px';
                                maxEl.innerHTML = `<span style="color: #67c1f5;">Макс:</span> ${maxHours.toFixed(1)} ч.`;
                                if (maxPlayers.length > 0) {
                                    maxEl.innerHTML += ` (${maxPlayers.map(p => `<a href="${p.profile}" target="_blank" style="color: #c6d4df; text-decoration: none;">${p.name}</a>`).join(', ')})`;
                                }
                                const avgEl = document.createElement('div');
                                avgEl.style.marginBottom = '4px';
                                avgEl.innerHTML = `<span style="color: #67c1f5;">Среднее:</span> ${avgHours.toFixed(1)} ч. (${friendsData.length} чел.)`;
                                const minEl = document.createElement('div');
                                minEl.innerHTML = `<span style="color: #67c1f5;">Минимальное:</span> ${minHours.toFixed(1)} ч.`;
                                content.append(maxEl, avgEl, minEl);
                            } else {
                                const noData = document.createElement('div');
                                noData.textContent = 'Друзья не играли';
                                noData.style.marginBottom = '12px';
                                content.appendChild(noData);
                            }
                            const achTitle = document.createElement('div');
                            achTitle.style.fontSize = '12px';
                            achTitle.style.fontWeight = 'bold';
                            achTitle.style.color = '#67c1f5';
                            achTitle.style.margin = '16px 0 5px 0';
                            achTitle.textContent = 'ГЛОБАЛЬНЫЕ ДОСТИЖЕНИЯ';
                            content.appendChild(achTitle);
                            if (achievementsData.hasAchievements) {
                                const platinumEl = document.createElement('div');
                                platinumEl.style.marginBottom = '4px';
                                platinumEl.innerHTML = `<span style="color: #67c1f5;">Платина:</span> ${achievementsData.platinumPercent}%`;
                                const averageEl = document.createElement('div');
                                averageEl.innerHTML = `<span style="color: #67c1f5;">Средний прогресс:</span> ${achievementsData.averageAdjustedPercent}%`;
                                content.append(platinumEl, averageEl);
                            } else {
                                const noAch = document.createElement('div');
                                noAch.textContent = achievementsData.error === 'Достижения отсутствуют' ? 'Достижений нет' : achievementsData.error;
                                noAch.style.marginBottom = '12px';
                                content.appendChild(noAch);
                            }
                            statsBlock.style.height = `${content.scrollHeight + 38}px`;
                        } catch (error) {
                            content.textContent = 'Ошибка загрузки';
                            statsBlock.style.height = '60px';
                        }
                    } else {
                        content.style.display = 'none';
                        statsBlock.style.height = '30px';
                        statsBlock.style.width = '30px';
                        triangle.style.borderBottom = 'none';
                        triangle.style.borderTop = '5px solid #67c1f5';
                    }
                };

                async function loadFriendsDataForStats() {
                    const friendsUrl = `https://steamcommunity.com/my/friendsthatplay/${appId}`;
                    try {
                        const response = await new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: friendsUrl,
                                onload: resolve,
                                onerror: reject,
                                timeout: 5000
                            });
                        });
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(response.responseText, 'text/html');
                        const playedBlocks = [];
                        const headers = doc.querySelectorAll('.mainSectionHeader.friendListSectionHeader');
                        const playedKeywords = ['последние 2 недели', 'in the last 2 weeks', 'когда-либо игравшие', 'previously'];
                        headers.forEach(header => {
                            const headerText = header.textContent;
                            if (playedKeywords.some(keyword => headerText.includes(keyword))) {
                                const container = header.nextElementSibling;
                                if (container && container.matches('.profile_friends')) {
                                    const blocks = container.querySelectorAll('.friendBlock');
                                    playedBlocks.push(...blocks);
                                }
                            }
                        });
                        return playedBlocks.map(block => {
                            const contentBlock = block.querySelector('.friendBlockContent');
                            if (!contentBlock) return null;
                            const timeText = contentBlock.querySelector('.friendSmallText')?.textContent.trim();
                            let hours = 0;
                            if (timeText) {
                                const timeParts = timeText.split('/');
                                const relevantTimePart = timeParts.length > 1 ? timeParts[1] : timeParts[0];
                                const hoursMatch = relevantTimePart.match(/(\d+[,.]?\d*)\s*(?:ч|hrs)\.?/);
                                if (hoursMatch && hoursMatch[1]) {
                                    hours = parseFloat(hoursMatch[1].replace(',', '.')) || 0;
                                }
                            }
                            return {
                                name: contentBlock.firstChild.textContent.trim(),
                                hours: hours,
                                profile: block.querySelector('a.friendBlockLinkOverlay')?.href
                            };
                        }).filter(f => f && f.hours > 0);
                    } catch (error) {
                        return [];
                    }
                }

                async function loadAchievementsDataForStats() {
                    const achievementsUrl = `https://steamcommunity.com/stats/${appId}/achievements/`;
                    try {
                        const response = await new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: achievementsUrl,
                                onload: resolve,
                                onerror: reject,
                                timeout: 8000
                            });
                        });
                        if (response.status !== 200) return {
                            hasAchievements: false,
                            error: 'Ошибка загрузки страницы'
                        };
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(response.responseText, 'text/html');
                        if (doc.querySelector('.no_achievements_message')) return {
                            hasAchievements: false,
                            error: 'Достижения отсутствуют'
                        };
                        const percentElements = doc.querySelectorAll('.achievePercent');
                        if (percentElements.length === 0) return {
                            hasAchievements: false,
                            error: 'Достижения отсутствуют'
                        };
                        const percents = Array.from(percentElements).map(el => parseFloat(el.textContent.trim().replace('%', '')) || 0).filter(p => p > 0);
                        if (percents.length === 0) return {
                            hasAchievements: false,
                            error: 'Нет данных'
                        };
                        const maxPercent = Math.max(...percents);
                        const minPercent = Math.min(...percents);
                        const adjustment = 100 - maxPercent;
                        const adjustedPercents = percents.map(p => p + adjustment);
                        const averageAdjusted = adjustedPercents.reduce((sum, p) => sum + p, 0) / adjustedPercents.length;
                        return {
                            hasAchievements: true,
                            platinumPercent: (minPercent + adjustment).toFixed(1),
                            averageAdjustedPercent: averageAdjusted.toFixed(1)
                        };
                    } catch (error) {
                        return {
                            hasAchievements: false,
                            error: 'Ошибка соединения'
                        };
                    }
                }
                title.addEventListener('click', toggleBlock);
                triangle.addEventListener('click', toggleBlock);
                headerCtn.appendChild(statsBlock);
            }
        })();
    }

    // Скрипт для страницы игры (Ранний доступ) | https://store.steampowered.com/app/*
    if (window.location.pathname.includes('/app/') && scriptsConfig.earlyaccdata) {
        (function() {
            'use strict';

            const EAORDATE_STORAGE_KEY = 'USE_EarlyAccess_ordateData';
            const EAORDATE_URL = 'https://gist.githubusercontent.com/0wn3dg0d/58a8e35f3d34014ea749a22d02f7e203/raw/eaordate.json';
            const CACHE_DURATION = 180 * 24 * 60 * 60 * 1000; // 6 месяцев

            const getYearForm = (n) => {
                n = Math.abs(n) % 100;
                const n1 = n % 10;
                if (n > 10 && n < 20) return 'лет';
                if (n1 === 1) return 'год';
                if (n1 >= 2 && n1 <= 4) return 'года';
                return 'лет';
            };

            const getMonthForm = (n) => {
                n = Math.abs(n) % 100;
                const n1 = n % 10;
                if (n > 10 && n < 20) return 'месяцев';
                if (n1 === 1) return 'месяц';
                if (n1 >= 2 && n1 <= 4) return 'месяца';
                return 'месяцев';
            };

            const parseSteamDate = (dateStr) => {
                const numericParts = dateStr.split('.');
                if (numericParts.length === 3) {
                    const day = parseInt(numericParts[0], 10);
                    const month = parseInt(numericParts[1], 10) - 1;
                    const year = parseInt(numericParts[2], 10);
                    return new Date(year, month, day);
                }

                const monthsMap = {
                    'янв': 0,
                    'фев': 1,
                    'мар': 2,
                    'апр': 3,
                    'мая': 4,
                    'июн': 5,
                    'июл': 6,
                    'авг': 7,
                    'сен': 8,
                    'окт': 9,
                    'ноя': 10,
                    'дек': 11
                };

                const cleanedStr = dateStr.replace(/\./g, '');
                const [day, monthNameRaw, year] = cleanedStr.split(' ');
                const monthName = monthNameRaw.substring(0, 3);
                return new Date(parseInt(year), monthsMap[monthName], parseInt(day));
            };

            const fetchOrdateData = async () => {
                const cachedData = GM_getValue(EAORDATE_STORAGE_KEY, null);
                if (cachedData && Date.now() - cachedData.timestamp < CACHE_DURATION) {
                    return cachedData.data;
                }

                return new Promise(resolve => {
                    GM_xmlhttpRequest({
                        method: 'GET',
                        url: EAORDATE_URL,
                        onload: function(response) {
                            try {
                                const data = JSON.parse(response.responseText);
                                GM_setValue(EAORDATE_STORAGE_KEY, {
                                    timestamp: Date.now(),
                                    data: data
                                });
                                resolve(data);
                            } catch (e) {
                                console.error('Error parsing EAOrdate data:', e);
                                resolve(cachedData?.data || []);
                            }
                        },
                        onerror: () => resolve(cachedData?.data || [])
                    });
                });
            };

            const getAppId = () => {
                const match = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
                return match ? parseInt(match[1]) : null;
            };

            const createInfoBox = (duration, isReleased) => {
                const infoBox = document.createElement('div');
                Object.assign(infoBox.style, {
                    position: 'absolute',
                    top: '-46px',
                    left: '334px',
                    background: isReleased ? 'rgba(103, 193, 245, 0.15)' : 'rgba(245, 166, 35, 0.15)',
                    padding: '6.5px',
                    borderRadius: '3px',
                    border: `1px solid ${isReleased ? '#2A568E' : '#f5a623'}`,
                    fontSize: '12px',
                    color: '#c6d4df',
                    boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)',
                    fontFamily: '"Motiva Sans", Arial, sans-serif',
                    zIndex: 3,
                    display: 'inline-block',
                    whiteSpace: 'nowrap'
                });

                let message;
                if (isReleased) {
                    message = duration ?
                        `Вышла спустя ${duration} раннего доступа` :
                        'Игра вышла из раннего доступа (срок неизвестен)';
                } else {
                    message = `В раннем доступе уже ${duration}`;
                }

                infoBox.innerHTML = `
                <div style="display: flex; align-items: center; gap: 8px;">
                    <span style="color: ${isReleased ? '#67c1f5' : '#f5a623'}; font-weight: bold;">
                        ${isReleased ? '➡️' : '⏳'}
                    </span>
                    <span>${message}</span>
                </div>
            `;
                return infoBox;
            };

            const calculateDuration = (startDate, endDate) => {
                let diffMonths = (endDate.getFullYear() - startDate.getFullYear()) * 12 +
                    (endDate.getMonth() - startDate.getMonth());

                if (endDate.getDate() < startDate.getDate()) diffMonths--;

                const years = Math.floor(diffMonths / 12);
                const months = diffMonths % 12;

                const parts = [];
                if (years > 0) parts.push(`${years} ${getYearForm(years)}`);
                if (months > 0) parts.push(`${months} ${getMonthForm(months)}`);

                return parts.length > 0 ? parts.join(' и ') : 'менее месяца';
            };

            const main = async () => {
                const detailsBlock = document.querySelector('#genresAndManufacturer');
                const isStillEarlyAccess = !!document.querySelector('#earlyAccessHeader');
                if (!detailsBlock) return;

                const parseDates = () => {
                    const fullText = detailsBlock.textContent;
                    const dates = {
                        earlyDate: null,
                        releaseDate: null
                    };

                    const earlyMatch = fullText.match(/Дата выпуска в раннем доступе:\s*(\d+\s\S+\s\d{4})/);
                    const releaseMatch = fullText.match(/Дата выхода:\s*(\d+\s\S+\s\d{4})/);

                    if (isStillEarlyAccess && !earlyMatch && releaseMatch) {
                        dates.earlyDate = releaseMatch[1];
                    } else {
                        if (earlyMatch) dates.earlyDate = earlyMatch[1];
                        if (releaseMatch) dates.releaseDate = releaseMatch[1];
                    }
                    return dates;
                };

                const {
                    earlyDate: earlyDateStr,
                    releaseDate: releaseDateStr
                } = parseDates();
                const appid = getAppId();

                if (!earlyDateStr && appid) {
                    const ordateData = await fetchOrdateData();
                    const gameData = ordateData.find(item => item.appid === appid);

                    if (gameData) {
                        try {
                            const ordate = parseSteamDate(gameData.ordate);
                            const releaseDate = releaseDateStr ? parseSteamDate(releaseDateStr) : new Date();

                            if (ordate >= releaseDate) throw new Error('Invalid date order');

                            const duration = calculateDuration(ordate, releaseDate);
                            const infoBox = createInfoBox(duration, true);
                            document.querySelector('.game_header_image_ctn')?.appendChild(infoBox);
                        } catch (e) {
                            const infoBox = createInfoBox(null, true);
                            document.querySelector('.game_header_image_ctn')?.appendChild(infoBox);
                        }
                    }
                    return;
                }

                const earlyDate = earlyDateStr ? parseSteamDate(earlyDateStr) :
                    isStillEarlyAccess ? parseSteamDate(releaseDateStr) : null;
                const releaseDate = releaseDateStr ? parseSteamDate(releaseDateStr) : null;

                if (!earlyDate) return;

                const endDate = isStillEarlyAccess ? new Date() : releaseDate;
                if (!endDate) return;

                try {
                    const duration = calculateDuration(earlyDate, endDate);
                    const infoBox = createInfoBox(duration, !isStillEarlyAccess);
                    document.querySelector('.game_header_image_ctn')?.appendChild(infoBox);
                } catch (e) {
                    console.error('Early access date calculation error:', e);
                }
            };

            main();
        })();
    }

    // Скрипт для страницы игры (Анализатор цен; цена РФ vs рекомендованная; рейтинг цен) | https://store.steampowered.com/app/*
    if (scriptsConfig.RuRegionalPriceAnalyzer && unsafeWindow.location.pathname.includes('/app/')) {
        (function regionalPriceAnalyzer() {
            'use strict';

            let rpa_currentDisplayMode = 'RUB';
            let rpa_hideUsdSwitchWarning = localStorage.getItem('rpa_hide_usd_switch_warning') === 'true';

            const userProvidedRegionsRU = {
                'US': {
                    name: 'Доллар США',
                    code: 1,
                    iso: 'usd'
                },
                'EU': {
                    name: 'Евро',
                    code: 3,
                    iso: 'eur'
                },
                'AR': {
                    name: 'Лат. Ам. - Доллар США',
                    code: 1,
                    iso: 'usd'
                },
                'AU': {
                    name: 'Австралийский доллар',
                    code: 21,
                    iso: 'aud'
                },
                'BR': {
                    name: 'Бразильский реал',
                    code: 7,
                    iso: 'brl'
                },
                'GB': {
                    name: 'Британский фунт',
                    code: 2,
                    iso: 'gbp'
                },
                'CA': {
                    name: 'Канадский доллар',
                    code: 20,
                    iso: 'cad'
                },
                'CL': {
                    name: 'Чилийское песо',
                    code: 25,
                    iso: 'clp'
                },
                'CN': {
                    name: 'Китайский юань',
                    code: 23,
                    iso: 'cny'
                },
                'AZ': {
                    name: 'СНГ - Доллар США',
                    code: 1,
                    iso: 'usd'
                },
                'CO': {
                    name: 'Колумбийское песо',
                    code: 27,
                    iso: 'cop'
                },
                'CR': {
                    name: 'Коста-риканский колон',
                    code: 40,
                    iso: 'crc'
                },
                'HK': {
                    name: 'Гонконгский доллар',
                    code: 29,
                    iso: 'hkd'
                },
                'IN': {
                    name: 'Индийская рупия',
                    code: 24,
                    iso: 'inr'
                },
                'ID': {
                    name: 'Индонезийская рупия',
                    code: 10,
                    iso: 'idr'
                },
                'IL': {
                    name: 'Израильский новый шекель',
                    code: 35,
                    iso: 'ils'
                },
                'JP': {
                    name: 'Японская иена',
                    code: 8,
                    iso: 'jpy'
                },
                'KZ': {
                    name: 'Казахстанский тенге',
                    code: 37,
                    iso: 'kzt'
                },
                'KW': {
                    name: 'Кувейтский динар',
                    code: 38,
                    iso: 'kwd'
                },
                'MY': {
                    name: 'Малазийский ринггит',
                    code: 11,
                    iso: 'myr'
                },
                'MX': {
                    name: 'Мексиканское песо',
                    code: 19,
                    iso: 'mxn'
                },
                'NZ': {
                    name: 'Новозеландский доллар',
                    code: 22,
                    iso: 'nzd'
                },
                'NO': {
                    name: 'Норвежская крона',
                    code: 9,
                    iso: 'nok'
                },
                'PE': {
                    name: 'Перуанский соль',
                    code: 26,
                    iso: 'pen'
                },
                'PH': {
                    name: 'Филиппинское песо',
                    code: 12,
                    iso: 'php'
                },
                'PL': {
                    name: 'Польский злотый',
                    code: 6,
                    iso: 'pln'
                },
                'QA': {
                    name: 'Катарский риал',
                    code: 39,
                    iso: 'qar'
                },
                'RU': {
                    name: 'Российский рубль',
                    code: 5,
                    iso: 'rub'
                },
                'SA': {
                    name: 'Саудовский риал',
                    code: 31,
                    iso: 'sar'
                },
                'SG': {
                    name: 'Сингапурский доллар',
                    code: 13,
                    iso: 'sgd'
                },
                'ZA': {
                    name: 'Южноафриканский рэнд',
                    code: 28,
                    iso: 'zar'
                },
                'PK': {
                    name: 'Юж. Азия - Доллар США',
                    code: 1,
                    iso: 'usd'
                },
                'KR': {
                    name: 'Южнокорейская вона',
                    code: 16,
                    iso: 'krw'
                },
                'CH': {
                    name: 'Швейцарский франк',
                    code: 4,
                    iso: 'chf'
                },
                'TW': {
                    name: 'Тайваньский доллар',
                    code: 30,
                    iso: 'twd'
                },
                'TH': {
                    name: 'Тайский бат',
                    code: 14,
                    iso: 'thb'
                },
                'TR': {
                    name: 'MENA - Доллар США',
                    code: 1,
                    iso: 'usd'
                },
                'AE': {
                    name: 'Дирхам ОАЭ',
                    code: 32,
                    iso: 'aed'
                },
                'UA': {
                    name: 'Украинская гривна',
                    code: 18,
                    iso: 'uah'
                },
                'UY': {
                    name: 'Уругвайское песо',
                    code: 41,
                    iso: 'uyu'
                },
                'VN': {
                    name: 'Вьетнамский донг',
                    code: 15,
                    iso: 'vnd'
                }
            };
            const userProvidedRegionsEN = {
                'US': {
                    name: 'United States Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'EU': {
                    name: 'Euro',
                    code: 3,
                    iso: 'eur'
                },
                'AR': {
                    name: 'Latin America - USD',
                    code: 1,
                    iso: 'usd'
                },
                'AU': {
                    name: 'Australian Dollar',
                    code: 21,
                    iso: 'aud'
                },
                'BR': {
                    name: 'Brazilian Real',
                    code: 7,
                    iso: 'brl'
                },
                'GB': {
                    name: 'British Pound',
                    code: 2,
                    iso: 'gbp'
                },
                'CA': {
                    name: 'Canadian Dollar',
                    code: 20,
                    iso: 'cad'
                },
                'CL': {
                    name: 'Chilean Peso',
                    code: 25,
                    iso: 'clp'
                },
                'CN': {
                    name: 'Chinese Yuan Renminbi',
                    code: 23,
                    iso: 'cny'
                },
                'AZ': {
                    name: 'CIS - USD',
                    code: 1,
                    iso: 'usd'
                },
                'CO': {
                    name: 'Colombian Peso',
                    code: 27,
                    iso: 'cop'
                },
                'CR': {
                    name: 'Costa Rican Colon',
                    code: 40,
                    iso: 'crc'
                },
                'HK': {
                    name: 'Hong Kong Dollar',
                    code: 29,
                    iso: 'hkd'
                },
                'IN': {
                    name: 'Indian Rupee',
                    code: 24,
                    iso: 'inr'
                },
                'ID': {
                    name: 'Indonesian Rupiah',
                    code: 10,
                    iso: 'idr'
                },
                'IL': {
                    name: 'Israeli New Shekel',
                    code: 35,
                    iso: 'ils'
                },
                'JP': {
                    name: 'Japanese Yen',
                    code: 8,
                    iso: 'jpy'
                },
                'KZ': {
                    name: 'Kazakhstani Tenge',
                    code: 37,
                    iso: 'kzt'
                },
                'KW': {
                    name: 'Kuwaiti Dinar',
                    code: 38,
                    iso: 'kwd'
                },
                'MY': {
                    name: 'Malaysian Ringgit',
                    code: 11,
                    iso: 'myr'
                },
                'MX': {
                    name: 'Mexican Peso',
                    code: 19,
                    iso: 'mxn'
                },
                'NZ': {
                    name: 'New Zealand Dollar',
                    code: 22,
                    iso: 'nzd'
                },
                'NO': {
                    name: 'Norwegian Krone',
                    code: 9,
                    iso: 'nok'
                },
                'PE': {
                    name: 'Peruvian Sol',
                    code: 26,
                    iso: 'pen'
                },
                'PH': {
                    name: 'Philippine Peso',
                    code: 12,
                    iso: 'php'
                },
                'PL': {
                    name: 'Polish Zloty',
                    code: 6,
                    iso: 'pln'
                },
                'QA': {
                    name: 'Qatari Riyal',
                    code: 39,
                    iso: 'qar'
                },
                'RU': {
                    name: 'Russian Ruble',
                    code: 5,
                    iso: 'rub'
                },
                'SA': {
                    name: 'Saudi Riyal',
                    code: 31,
                    iso: 'sar'
                },
                'SG': {
                    name: 'Singapore Dollar',
                    code: 13,
                    iso: 'sgd'
                },
                'ZA': {
                    name: 'South African Rand',
                    code: 28,
                    iso: 'zar'
                },
                'PK': {
                    name: 'South Asia - USD',
                    code: 1,
                    iso: 'usd'
                },
                'KR': {
                    name: 'South Korean Won',
                    code: 16,
                    iso: 'krw'
                },
                'CH': {
                    name: 'Swiss Franc',
                    code: 4,
                    iso: 'chf'
                },
                'TW': {
                    name: 'New Taiwan Dollar',
                    code: 30,
                    iso: 'twd'
                },
                'TH': {
                    name: 'Thai Baht',
                    code: 14,
                    iso: 'thb'
                },
                'TR': {
                    name: 'MENA - USD',
                    code: 1,
                    iso: 'usd'
                },
                'AE': {
                    name: 'UAE Dirham',
                    code: 32,
                    iso: 'aed'
                },
                'UA': {
                    name: 'Ukrainian Hryvnia',
                    code: 18,
                    iso: 'uah'
                },
                'UY': {
                    name: 'Uruguayan Peso',
                    code: 41,
                    iso: 'uyu'
                },
                'VN': {
                    name: 'Vietnamese Dong',
                    code: 15,
                    iso: 'vnd'
                }
            };

            const RPA_CONFIG = {
                regions: [],
                currencyApiUrl: 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/',
                steamApiUrl: 'https://api.steampowered.com/IStoreBrowseService/GetItems/v1/',
                priorButtonText: '',
                modalTitle: '',
                fetchButtonText: '',
                delayBetweenBatches: 300,
                batchSize: 10,
            };

            function rpa_updateTextsAndRegionNames() {
                const isUSDMode = rpa_currentDisplayMode === 'USD';
                RPA_CONFIG.priorButtonText = isUSDMode ? 'Price Analyzer' : 'Анализатор цен';
                RPA_CONFIG.modalTitle = isUSDMode ? 'Regional Price Analyzer' : 'Анализатор цен';
                RPA_CONFIG.fetchButtonText = isUSDMode ? 'Fetch Data' : 'Сбор данных';

                const sourceRegions = isUSDMode ? userProvidedRegionsEN : userProvidedRegionsRU;
                RPA_CONFIG.regions = Object.entries(sourceRegions).map(([key, value]) => ({
                    cc: key === 'EU' ? 'DE' : key,
                    name: value.name,
                    currencyApiCode: value.iso.toLowerCase(),
                    steamCurrencyId: value.code
                }));

                if (rpa_priorButton) rpa_priorButton.textContent = RPA_CONFIG.priorButtonText;
                const modalTitleEl = rpa_modal ? rpa_modal.querySelector('#rpaHeaderBar h3') : null;
                if (modalTitleEl) modalTitleEl.textContent = RPA_CONFIG.modalTitle;
                const fetchBtnEl = rpa_modal ? rpa_modal.querySelector('#rpaFetchDataButton') : null;
                if (fetchBtnEl) fetchBtnEl.textContent = RPA_CONFIG.fetchButtonText;
                rpa_updateModeToggleButtonText();
            }

            let rpa_exchangeRates = {};
            let rpa_modal = null;
            let rpa_priorButton = null;
            let rpa_currentAppId = null;
            let rpa_currentGameName = '';
            let rpa_progressBarFill = null;
            let rpa_fetchController = null;
            let rpa_modeToggleButton = null;

            function calculateRecommendedRubPrice(pUSD) {
                if (typeof pUSD !== 'number' || isNaN(pUSD)) return null;
                if (pUSD < 0.99) return 42;
                if (pUSD >= 0.99 && pUSD < 1.99) return 42;
                if (pUSD >= 1.99 && pUSD < 2.99) return 82;
                if (pUSD >= 2.99 && pUSD < 3.99) return 125;
                if (pUSD >= 3.99 && pUSD < 4.99) return 165;
                if (pUSD >= 4.99 && pUSD < 5.99) return 200;
                if (pUSD >= 5.99 && pUSD < 6.99) return 240;
                if (pUSD >= 6.99 && pUSD < 7.99) return 280;
                if (pUSD >= 7.99 && pUSD < 8.99) return 320;
                if (pUSD >= 8.99 && pUSD < 9.99) return 350;
                if (pUSD >= 9.99 && pUSD < 10.99) return 385;
                if (pUSD >= 10.99 && pUSD < 11.99) return 420;
                if (pUSD >= 11.99 && pUSD < 12.99) return 460;
                if (pUSD >= 12.99 && pUSD < 13.99) return 490;
                if (pUSD >= 13.99 && pUSD < 14.99) return 520;
                if (pUSD >= 14.99 && pUSD < 15.99) return 550;
                if (pUSD >= 15.99 && pUSD < 16.99) return 590;
                if (pUSD >= 16.99 && pUSD < 17.99) return 620;
                if (pUSD >= 17.99 && pUSD < 18.99) return 650;
                if (pUSD >= 18.99 && pUSD < 19.99) return 680;
                if (pUSD >= 19.99 && pUSD < 22.99) return 710;
                if (pUSD >= 22.99 && pUSD < 27.99) return 880;
                if (pUSD >= 27.99 && pUSD < 32.99) return 1100;
                if (pUSD >= 32.99 && pUSD < 37.99) return 1200;
                if (pUSD >= 37.99 && pUSD < 43.99) return 1300;
                if (pUSD >= 43.99 && pUSD < 47.99) return 1500;
                if (pUSD >= 47.99 && pUSD < 52.99) return 1600;
                if (pUSD >= 52.99 && pUSD < 57.99) return 1750;
                if (pUSD >= 57.99 && pUSD < 63.99) return 1900;
                if (pUSD >= 63.99 && pUSD < 67.99) return 2100;
                if (pUSD >= 67.99 && pUSD < 74.99) return 2250;
                if (pUSD >= 74.99 && pUSD < 79.99) return 2400;
                if (pUSD >= 79.99 && pUSD < 84.99) return 2600;
                if (pUSD >= 84.99 && pUSD < 89.99) return 2700;
                if (pUSD >= 89.99 && pUSD < 99.99) return 2900;
                if (pUSD >= 99.99 && pUSD < 109.99) return 3200;
                if (pUSD >= 109.99 && pUSD < 119.99) return 3550;
                if (pUSD >= 119.99 && pUSD < 129.99) return 3900;
                if (pUSD >= 129.99 && pUSD < 139.99) return 4200;
                if (pUSD >= 139.99 && pUSD < 149.99) return 4500;
                if (pUSD >= 149.99 && pUSD < 199.99) return 4800;
                if (pUSD >= 199.99) return 6500;
                return null;
            }

            function rpa_getAppIdFromUrl() {
                const match = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
                return match ? match[1] : null;
            }

            async function rpa_fetchExchangeRates(baseCurrency = 'usd', signal) {
                baseCurrency = baseCurrency.toLowerCase();
                if (rpa_exchangeRates[baseCurrency] && Object.keys(rpa_exchangeRates[baseCurrency]).length > 0) {
                    return rpa_exchangeRates[baseCurrency];
                }
                if (baseCurrency === 'rub' && !rpa_exchangeRates['rub']) rpa_exchangeRates['rub'] = {};
                if (baseCurrency === 'rub' && rpa_exchangeRates['rub']['rub'] === 1) return rpa_exchangeRates['rub'];
                if (baseCurrency === 'usd' && !rpa_exchangeRates['usd']) rpa_exchangeRates['usd'] = {};
                if (baseCurrency === 'usd' && rpa_exchangeRates['usd']['usd'] === 1 && Object.keys(rpa_exchangeRates['usd']).length > 1) return rpa_exchangeRates['usd'];

                try {
                    const response = await new Promise((resolve, reject) => {
                        const xhr = GM_xmlhttpRequest({
                            method: "GET",
                            url: `${RPA_CONFIG.currencyApiUrl}${baseCurrency}.json`,
                            timeout: 8000,
                            onload: function(resp) {
                                if (resp.status >= 200 && resp.status < 400) {
                                    try {
                                        resolve(JSON.parse(resp.responseText));
                                    } catch (e) {
                                        reject(new Error(`JSON Parse error for ${baseCurrency}: ${e.message}`));
                                    }
                                } else {
                                    reject(new Error(`Currency API error: ${resp.status} for ${baseCurrency}`));
                                }
                            },
                            onerror: (err) => reject(new Error(`Network error for ${baseCurrency}: ${err}`)),
                            ontimeout: () => reject(new Error(`Currency API timeout for ${baseCurrency}`))
                        });
                        if (signal) {
                            signal.addEventListener('abort', () => {
                                xhr.abort();
                                reject(new DOMException('Request aborted', 'AbortError'));
                            });
                        }
                    });
                    rpa_exchangeRates[baseCurrency] = response[baseCurrency] || {};
                    rpa_exchangeRates[baseCurrency][baseCurrency] = 1;
                    return rpa_exchangeRates[baseCurrency];
                } catch (error) {
                    if (error.name === 'AbortError') {
                        console.log(`[RPA] Exchange rate request for ${baseCurrency} aborted.`);
                    } else {
                        console.error(`[RPA] Error fetching exchange rates for ${baseCurrency}:`, error);
                    }
                    throw error;
                }
            }

            function rpa_getPriceInCents(purchaseOption) {
                if (purchaseOption && purchaseOption.discount_pct > 0 && purchaseOption.original_price_in_cents) {
                    return parseInt(purchaseOption.original_price_in_cents, 10);
                }
                if (purchaseOption && purchaseOption.final_price_in_cents) {
                    return parseInt(purchaseOption.final_price_in_cents, 10);
                }
                return null;
            }

            function rpa_getDisplayFormattedPrice(purchaseOption) {
                if (purchaseOption) {
                    if (purchaseOption.discount_pct > 0 && purchaseOption.formatted_original_price) {
                        return purchaseOption.formatted_original_price;
                    }
                    if (purchaseOption.formatted_final_price) {
                        return purchaseOption.formatted_final_price;
                    }
                }
                return 'N/A';
            }

            async function rpa_fetchItemData(appid, countryCode, signal) {
                const lang = rpa_currentDisplayMode === 'USD' ? 'english' : 'russian';
                const url = `${RPA_CONFIG.steamApiUrl}?input_json=${encodeURIComponent(JSON.stringify({
                    "ids": [{ "appid": parseInt(appid) }],
                    "context": { "country_code": countryCode, "steam_realm": 1, "language": lang },
                    "data_request": { "include_all_purchase_options": true, "include_basic_info": true }
                }))}`;
                return new Promise((resolve, reject) => {
                    const xhr = GM_xmlhttpRequest({
                        method: "GET",
                        url: url,
                        timeout: 15000,
                        onload: function(response) {
                            try {
                                if (response.status >= 200 && response.status < 400) {
                                    const data = JSON.parse(response.responseText);
                                    if (data.response && data.response.store_items && data.response.store_items.length > 0) {
                                        resolve(data.response.store_items[0]);
                                    } else {
                                        resolve(null);
                                    }
                                } else {
                                    reject(new Error(`Steam API error: ${response.status} for ${countryCode}`));
                                }
                            } catch (e) {
                                reject(new Error(`Error parsing Steam API response for ${countryCode}: ${e.message}`));
                            }
                        },
                        onerror: (err) => reject(new Error(`Network error for ${countryCode}: ${err.toString()}`)),
                        ontimeout: () => reject(new Error(`Timeout for ${countryCode}`))
                    });
                    if (signal) {
                        signal.addEventListener('abort', () => {
                            xhr.abort();
                            reject(new DOMException('Request aborted', 'AbortError'));
                        });
                    }
                });
            }

            function rpa_addPriorButton() {
                if (document.getElementById('rpaPriorButton')) return;
                let targetWrapper = document.querySelector('.game_area_purchase_game_wrapper');
                if (!targetWrapper) {
                    return;
                }
                const allPurchaseWrappers = document.querySelectorAll('.game_area_purchase_game_wrapper');
                for (let wrapper of allPurchaseWrappers) {
                    if (wrapper.querySelector('.game_purchase_action .price, .game_purchase_action .discount_block')) {
                        targetWrapper = wrapper;
                        break;
                    }
                }
                rpa_priorButton = document.createElement('button');
                rpa_priorButton.id = 'rpaPriorButton';
                rpa_priorButton.textContent = RPA_CONFIG.priorButtonText;
                rpa_priorButton.className = 'btnv6_blue_hoverfade btn_medium';
                Object.assign(rpa_priorButton.style, {
                    marginRight: '10px',
                    marginBottom: '10px',
                    height: '32px',
                    padding: '0 15px',
                    lineHeight: '32px'
                });
                rpa_priorButton.addEventListener('click', rpa_openModal);
                const buttonContainer = document.createElement('div');
                buttonContainer.appendChild(rpa_priorButton);
                if (targetWrapper.parentNode) {
                    targetWrapper.parentNode.insertBefore(buttonContainer, targetWrapper);
                }
            }

            function rpa_updateModeToggleButtonText() {
                if (!rpa_modeToggleButton) return;
                if (rpa_currentDisplayMode === 'USD') {
                    rpa_modeToggleButton.textContent = 'RUB';
                    rpa_modeToggleButton.title = 'Вернуться в режим рублей?';
                } else {
                    rpa_modeToggleButton.textContent = 'USD';
                    rpa_modeToggleButton.title = 'Переключиться на режим долларов?';
                }
            }

            function rpa_handleModeToggle() {
                if (rpa_currentDisplayMode === 'RUB') {
                    if (rpa_hideUsdSwitchWarning) {
                        rpa_switchToUsdMode();
                    } else {
                        rpa_showUsdSwitchConfirmation();
                    }
                } else {
                    rpa_switchToRubMode();
                }
            }

            function rpa_switchToUsdMode() {
                rpa_currentDisplayMode = 'USD';
                rpa_updateTextsAndRegionNames();
                if (rpa_modal && rpa_modal.style.display === 'flex') {
                    document.getElementById('rpaSummaryDiv').innerHTML = `<p>Click "Fetch Data" to begin.</p>`;
                    document.getElementById('rpaResultsDiv').innerHTML = '';
                    rpa_updateModalStatus('Click "Fetch Data" to start analysis.');
                }
                rpa_updateModeToggleButtonText();
            }

            function rpa_switchToRubMode() {
                rpa_currentDisplayMode = 'RUB';
                rpa_updateTextsAndRegionNames();
                if (rpa_modal && rpa_modal.style.display === 'flex') {
                    document.getElementById('rpaSummaryDiv').innerHTML = '<p>Нажмите "Сбор данных" для начала.</p>';
                    document.getElementById('rpaResultsDiv').innerHTML = '';
                    rpa_updateModalStatus('Нажмите "Сбор данных" для начала анализа.');
                }
                rpa_updateModeToggleButtonText();
            }

            function rpa_showUsdSwitchConfirmation() {
                let existingDialog = document.getElementById('rpaUsdConfirmDialog');
                if (existingDialog) existingDialog.remove();

                const dialog = document.createElement('div');
                dialog.id = 'rpaUsdConfirmDialog';
                Object.assign(dialog.style, {
                    position: 'fixed',
                    top: '50%',
                    left: '50%',
                    transform: 'translate(-50%, -50%)',
                    backgroundColor: '#1b2838',
                    color: '#c6d4df',
                    padding: '25px',
                    borderRadius: '5px',
                    boxShadow: '0 0 20px rgba(0,0,0,0.7)',
                    zIndex: '100005',
                    textAlign: 'left',
                    border: '1px solid #000',
                    maxWidth: '450px'
                });

                const message = document.createElement('p');
                message.innerHTML = 'Вы переходите в режим долларов. Данный режим предназначен для получения цен в долларах США и может быть полезен для оценки ценовой политики при общении с разработчиками/издателями.<br><br>Продолжить?';
                message.style.marginBottom = '20px';
                message.style.lineHeight = '1.6';

                const checkboxContainer = document.createElement('div');
                checkboxContainer.style.marginBottom = '20px';
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.id = 'rpaDontShowAgainUsd';
                checkbox.style.marginRight = '8px';
                const label = document.createElement('label');
                label.htmlFor = 'rpaDontShowAgainUsd';
                label.textContent = 'Больше не показывать это сообщение';
                checkboxContainer.appendChild(checkbox);
                checkboxContainer.appendChild(label);

                const buttonsContainer = document.createElement('div');
                buttonsContainer.style.textAlign = 'right';

                const yesButton = document.createElement('button');
                yesButton.textContent = 'Да';
                Object.assign(yesButton.style, {
                    padding: '8px 15px',
                    marginRight: '10px',
                    backgroundColor: '#76b72a',
                    color: 'white',
                    border: 'none',
                    borderRadius: '3px',
                    cursor: 'pointer'
                });
                yesButton.onclick = () => {
                    if (checkbox.checked) {
                        rpa_hideUsdSwitchWarning = true;
                        localStorage.setItem('rpa_hide_usd_switch_warning', 'true');
                    }
                    rpa_switchToUsdMode();
                    dialog.remove();
                };

                const cancelButton = document.createElement('button');
                cancelButton.textContent = 'Отмена';
                Object.assign(cancelButton.style, {
                    padding: '8px 15px',
                    backgroundColor: '#55606e',
                    color: 'white',
                    border: 'none',
                    borderRadius: '3px',
                    cursor: 'pointer'
                });
                cancelButton.onclick = () => {
                    dialog.remove();
                };

                buttonsContainer.appendChild(yesButton);
                buttonsContainer.appendChild(cancelButton);
                dialog.appendChild(message);
                dialog.appendChild(checkboxContainer);
                dialog.appendChild(buttonsContainer);
                document.body.appendChild(dialog);
            }

            function rpa_createModal() {
                if (document.getElementById('rpaRegionalPriceModal')) return;
                rpa_modal = document.createElement('div');
                rpa_modal.id = 'rpaRegionalPriceModal';
                Object.assign(rpa_modal.style, {
                    position: 'fixed',
                    top: '0',
                    left: '0',
                    width: '100vw',
                    height: '100vh',
                    backgroundColor: 'rgba(21, 33, 45, 0.985)',
                    color: '#c6d4df',
                    zIndex: '100001',
                    display: 'flex',
                    flexDirection: 'column',
                    fontFamily: '"Motiva Sans", Sans-serif, Arial',
                    padding: '0'
                });

                const headerBar = document.createElement('div');
                headerBar.id = 'rpaHeaderBar';
                Object.assign(headerBar.style, {
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    padding: '10px 20px',
                    backgroundColor: '#17202d',
                    borderBottom: '1px solid #2a3f5a',
                    flexShrink: '0'
                });

                const title = document.createElement('h3');
                title.textContent = RPA_CONFIG.modalTitle;
                Object.assign(title.style, {
                    margin: '0',
                    color: '#67c1f5',
                    fontSize: '18px',
                    fontWeight: '500'
                });

                const gameNameDisplay = document.createElement('p');
                gameNameDisplay.id = 'rpaGameNameDisplay';
                Object.assign(gameNameDisplay.style, {
                    margin: '0 0 0 20px',
                    fontSize: '16px',
                    color: '#e5e5e5',
                    fontWeight: 'bold',
                    flexGrow: '1',
                    textAlign: 'center'
                });

                rpa_modeToggleButton = document.createElement('button');
                Object.assign(rpa_modeToggleButton.style, {
                    background: '#4b6f9c',
                    color: 'white',
                    border: '1px solid #2a3f5a',
                    borderRadius: '3px',
                    padding: '5px 10px',
                    cursor: 'pointer',
                    fontSize: '13px',
                    marginRight: '15px'
                });
                rpa_modeToggleButton.onmouseover = () => rpa_modeToggleButton.style.backgroundColor = '#67c1f5';
                rpa_modeToggleButton.onmouseout = () => rpa_modeToggleButton.style.backgroundColor = '#4b6f9c';
                rpa_modeToggleButton.addEventListener('click', rpa_handleModeToggle);
                rpa_updateModeToggleButtonText();

                const closeButton = document.createElement('button');
                closeButton.innerHTML = '&times;';
                Object.assign(closeButton.style, {
                    background: 'none',
                    border: 'none',
                    color: '#8f98a0',
                    fontSize: '30px',
                    cursor: 'pointer',
                    lineHeight: '1',
                    padding: '0 8px'
                });
                closeButton.onmouseover = () => closeButton.style.color = '#fff';
                closeButton.onmouseout = () => closeButton.style.color = '#8f98a0';
                closeButton.addEventListener('click', rpa_closeModal);

                const rightControls = document.createElement('div');
                rightControls.style.display = 'flex';
                rightControls.style.alignItems = 'center';
                rightControls.appendChild(rpa_modeToggleButton);
                rightControls.appendChild(closeButton);

                headerBar.appendChild(title);
                headerBar.appendChild(gameNameDisplay);
                headerBar.appendChild(rightControls);
                rpa_modal.appendChild(headerBar);

                const controlsBar = document.createElement('div');
                controlsBar.id = 'rpaControlsBar';
                Object.assign(controlsBar.style, {
                    display: 'flex',
                    alignItems: 'center',
                    gap: '15px',
                    padding: '10px 20px',
                    backgroundColor: '#1a2430',
                    borderBottom: '1px solid #23313f',
                    flexShrink: '0'
                });

                const fetchButton = document.createElement('button');
                fetchButton.textContent = RPA_CONFIG.fetchButtonText;
                fetchButton.id = 'rpaFetchDataButton';
                Object.assign(fetchButton.style, {
                    padding: '8px 20px',
                    backgroundColor: '#76b72a',
                    color: 'white',
                    border: '1px solid #5c9e1f',
                    borderRadius: '3px',
                    boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
                    textShadow: '1px 1px 0px rgba(0,0,0,0.3)',
                    fontWeight: '500',
                    cursor: 'pointer',
                    fontSize: '14px',
                    lineHeight: '1.5'
                });
                fetchButton.onmouseover = () => {
                    fetchButton.style.backgroundColor = '#85c83a';
                };
                fetchButton.onmouseout = () => {
                    fetchButton.style.backgroundColor = '#76b72a';
                };
                fetchButton.onmousedown = () => {
                    fetchButton.style.backgroundColor = '#6aa424';
                };
                fetchButton.onmouseup = () => {
                    fetchButton.style.backgroundColor = '#85c83a';
                };
                fetchButton.addEventListener('click', rpa_handleFetchData);
                controlsBar.appendChild(fetchButton);

                const progressBarContainer = document.createElement('div');
                progressBarContainer.id = 'rpaProgressBarContainer';
                Object.assign(progressBarContainer.style, {
                    flexGrow: '1',
                    height: '10px',
                    backgroundColor: '#2a3f5a',
                    borderRadius: '5px',
                    overflow: 'hidden',
                    display: 'none'
                });
                rpa_progressBarFill = document.createElement('div');
                rpa_progressBarFill.id = 'rpaProgressBarFill';
                Object.assign(rpa_progressBarFill.style, {
                    width: '0%',
                    height: '100%',
                    backgroundColor: '#67c1f5',
                    borderRadius: '5px',
                    transition: 'width 0.2s ease-out'
                });
                progressBarContainer.appendChild(rpa_progressBarFill);
                controlsBar.appendChild(progressBarContainer);

                const statusDiv = document.createElement('div');
                statusDiv.id = 'rpaStatusDiv';
                Object.assign(statusDiv.style, {
                    minWidth: '250px',
                    textAlign: 'right',
                    fontSize: '13px',
                    color: '#8f98a0'
                });
                controlsBar.appendChild(statusDiv);
                rpa_modal.appendChild(controlsBar);

                const mainContentWrapper = document.createElement('div');
                mainContentWrapper.id = 'rpaMainContentWrapper';
                Object.assign(mainContentWrapper.style, {
                    display: 'flex',
                    flexGrow: '1',
                    overflow: 'hidden',
                    padding: '15px 20px'
                });

                const leftSidebar = document.createElement('div');
                leftSidebar.id = 'rpaLeftSidebar';
                Object.assign(leftSidebar.style, {
                    width: '280px',
                    flexShrink: '0',
                    paddingRight: '15px',
                    borderRight: '1px solid #23313f',
                    overflowY: 'auto',
                    scrollbarWidth: 'thin',
                    scrollbarColor: '#4b6f9c #1e2c3a'
                });
                leftSidebar.innerHTML = `<style>
                    #rpaLeftSidebar::-webkit-scrollbar { width: 6px; }
                    #rpaLeftSidebar::-webkit-scrollbar-track { background: #1e2c3a; border-radius: 3px; }
                    #rpaLeftSidebar::-webkit-scrollbar-thumb { background-color: #4b6f9c; border-radius: 3px; }
                    #rpaLeftSidebar h4 { color: #67c1f5; font-size: 15px; margin-top: 0; margin-bottom: 8px; border-bottom: 1px solid #2a3f5a; padding-bottom: 5px; }
                    #rpaLeftSidebar .summary-item { margin-bottom: 12px; }
                    #rpaLeftSidebar .summary-label { display: block; font-weight: bold; color: #67c1f5; margin-bottom: 3px; font-size: 13px; }
                    #rpaLeftSidebar .summary-value { display: block; color: #e5e5e5; font-size: 14px; }
                    #rpaLeftSidebar .summary-sub-value { display: block; font-size: 11px; margin-top: 2px; opacity: 0.85; }
                </style>`;
                const summaryDiv = document.createElement('div');
                summaryDiv.id = 'rpaSummaryDiv';
                leftSidebar.appendChild(summaryDiv);
                mainContentWrapper.appendChild(leftSidebar);

                const resultsArea = document.createElement('div');
                resultsArea.id = 'rpaResultsArea';
                Object.assign(resultsArea.style, {
                    flexGrow: '1',
                    overflow: 'auto',
                    paddingLeft: '15px',
                    scrollbarWidth: 'thin',
                    scrollbarColor: '#4b6f9c #1e2c3a'
                });
                resultsArea.innerHTML = `<style>
                    #rpaResultsArea::-webkit-scrollbar { width: 8px; height: 8px; }
                    #rpaResultsArea::-webkit-scrollbar-track { background: #1e2c3a; border-radius: 4px; }
                    #rpaResultsArea::-webkit-scrollbar-thumb { background-color: #4b6f9c; border-radius: 4px; border: 2px solid #1e2c3a; }
                    #rpaResultsArea::-webkit-scrollbar-thumb:hover { background-color: #67c1f5; }
                </style>`;
                const resultsDiv = document.createElement('div');
                resultsDiv.id = 'rpaResultsDiv';
                resultsArea.appendChild(resultsDiv);
                mainContentWrapper.appendChild(resultsArea);

                rpa_modal.appendChild(mainContentWrapper);
                document.body.appendChild(rpa_modal);
                rpa_modal.style.display = 'none';

                const style = document.createElement('style');
                style.textContent = `
                    @keyframes rpa_spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
                    .rpa_spinner { border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 50%; border-top-color: #fff; width: 0.9em; height: 0.9em; animation: rpa_spin 1s linear infinite; display: inline-block; vertical-align: middle; margin-left: 8px; }
                    .rpaSinglePriceTable { width: auto; min-width: 680px; border-collapse: collapse; font-size: 12px; table-layout: fixed; background-color: #1e2c3a; border-radius: 3px; margin-left: 0; }
                    .rpaSinglePriceTable th, .rpaSinglePriceTable td { border: 1px solid #2a3f5a; padding: 6px 8px; text-align: left; }
                    .rpaSinglePriceTable th { background-color: #23313f; color: #a0b1c3; font-weight: 500; position: sticky; top: 0; z-index: 1; }
                    .rpaSinglePriceTable th.col-rank-header { width: 45px; }
                    .rpaSinglePriceTable th.col-region-header { width: 230px; }
                    .rpaSinglePriceTable th.col-local-price-header { width: 110px; }
                    .rpaSinglePriceTable th.col-rub-price-header, .rpaSinglePriceTable th.col-usd-price-header { width: 110px; }
                    .rpaSinglePriceTable th.col-diff-ru-header, .rpaSinglePriceTable th.col-diff-us-header { width: 120px; }
                    .rpaSinglePriceTable td.col-rank { text-align: center; }
                    .rpaSinglePriceTable td.col-region { word-break: break-word; white-space: normal; }
                    .rpaSinglePriceTable td.col-local-price, .rpaSinglePriceTable td.col-rub-price, .rpaSinglePriceTable td.col-usd-price, .rpaSinglePriceTable td.col-diff-ru, .rpaSinglePriceTable td.col-diff-us { text-align: right; white-space: nowrap; }
                    .rpaSinglePriceTable td.col-diff-ru.positive, .rpaSinglePriceTable td.col-diff-us.positive { color: lightgreen; }
                    .rpaSinglePriceTable td.col-diff-ru.negative, .rpaSinglePriceTable td.col-diff-us.negative { color: salmon; }
                    .rpaSinglePriceTable td.col-diff-ru.neutral, .rpaSinglePriceTable td.col-diff-us.neutral { color: #c6d4df; }
                    .rpaSinglePriceTable tr.highlight-ru td, .rpaSinglePriceTable tr.highlight-us td { background-color: rgba(103, 193, 245, 0.15) !important; font-weight: bold; }
                `;
                document.head.appendChild(style);
            }

            function rpa_updateProgressBar(percentage) {
                if (rpa_progressBarFill) {
                    rpa_progressBarFill.style.width = `${Math.min(100, Math.max(0, percentage))}%`;
                }
                const progressBarContainer = document.getElementById('rpaProgressBarContainer');
                if (progressBarContainer) {
                    progressBarContainer.style.display = (percentage > 0 && percentage < 100) ? 'flex' : 'none';
                }
            }

            function rpa_openModal() {
                if (!rpa_modal) rpa_createModal();
                rpa_updateTextsAndRegionNames();
                rpa_currentAppId = rpa_getAppIdFromUrl();
                const initialMsg = rpa_currentDisplayMode === 'USD' ? 'Click "Fetch Data" to begin.' : 'Нажмите "Сбор данных" для начала.';
                const statusMsg = rpa_currentDisplayMode === 'USD' ? 'Click "Fetch Data" to start analysis.' : 'Нажмите "Сбор данных" для начала анализа.';

                if (!rpa_currentAppId) {
                    alert(rpa_currentDisplayMode === 'USD' ? '[RPA] Could not determine AppID of the game.' : '[RPA] Не удалось определить AppID игры.');
                    return;
                }

                const gameTitleElement = document.querySelector('#appHubAppName');
                rpa_currentGameName = gameTitleElement ? gameTitleElement.textContent.trim() : (rpa_currentDisplayMode === 'USD' ? `Game #${rpa_currentAppId}` : `Игра #${rpa_currentAppId}`);
                const gameNameDisplay = document.getElementById('rpaGameNameDisplay');
                if (gameNameDisplay) gameNameDisplay.textContent = rpa_currentGameName;

                rpa_modal.style.display = 'flex';
                document.getElementById('rpaSummaryDiv').innerHTML = `<p>${initialMsg}</p>`;
                document.getElementById('rpaResultsDiv').innerHTML = '';
                rpa_updateModalStatus(statusMsg);
                document.getElementById('rpaFetchDataButton').disabled = false;
                rpa_updateProgressBar(0);
            }

            function rpa_closeModal() {
                if (rpa_fetchController) {
                    rpa_fetchController.abort();
                    rpa_fetchController = null;
                }
                if (rpa_modal) rpa_modal.style.display = 'none';
                const statusMsg = rpa_currentDisplayMode === 'USD' ? 'Ready for new analysis.' : 'Готово к новому анализу.';
                rpa_updateModalStatus(statusMsg);
                rpa_updateProgressBar(0);
            }

            function rpa_updateModalStatus(message, isLoading = false) {
                const statusDiv = document.getElementById('rpaStatusDiv');
                const fetchBtn = document.getElementById('rpaFetchDataButton');
                if (statusDiv) {
                    statusDiv.innerHTML = isLoading ? `${message} <span class="rpa_spinner"></span>` : message;
                }
                if (fetchBtn) {
                    fetchBtn.disabled = isLoading;
                }
            }

            async function rpa_handleFetchData() {
                if (rpa_fetchController) {
                    rpa_fetchController.abort();
                    console.log("[RPA] Previous data fetch aborted.");
                }
                rpa_fetchController = new AbortController();
                const signal = rpa_fetchController.signal;

                rpa_updateProgressBar(0);
                rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Initializing...' : 'Инициализация...', true);
                const summaryDiv = document.getElementById('rpaSummaryDiv');
                const resultsDiv = document.getElementById('rpaResultsDiv');
                summaryDiv.innerHTML = `<h4>${rpa_currentDisplayMode === 'USD' ? 'Summary:' : 'Сводная информация:'}</h4>`;
                resultsDiv.innerHTML = '';

                if (!rpa_currentAppId) {
                    rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Error: AppID not defined.' : 'Ошибка: AppID не определен.', false);
                    rpa_updateProgressBar(0);
                    return;
                }

                const gameTitleElement = document.querySelector('#appHubAppName');
                rpa_currentGameName = gameTitleElement ? gameTitleElement.textContent.trim() : (rpa_currentDisplayMode === 'USD' ? `Game #${rpa_currentAppId}` : `Игра #${rpa_currentAppId}`);
                const gameNameDisplay = document.getElementById('rpaGameNameDisplay');
                if (gameNameDisplay) gameNameDisplay.textContent = rpa_currentGameName;

                rpa_updateProgressBar(2);

                let usData;
                const usRegionConfig = RPA_CONFIG.regions.find(r => r.cc === 'US');
                if (!usRegionConfig) {
                    rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Error: Configuration for US region not found.' : 'Ошибка: Конфигурация для региона США не найдена.', false);
                    rpa_updateProgressBar(0);
                    return;
                }

                try {
                    rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Fetching US price...' : 'Запрос цены для США...', true);
                    usData = await rpa_fetchItemData(rpa_currentAppId, usRegionConfig.cc, signal);
                    if (signal.aborted) throw new DOMException('Request aborted', 'AbortError');
                    if (usData && usData.basic_info && usData.basic_info.name) {
                        rpa_currentGameName = usData.basic_info.name;
                        if (gameNameDisplay) gameNameDisplay.textContent = rpa_currentGameName;
                    }
                } catch (error) {
                    if (error.name === 'AbortError') {
                        rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Data fetch aborted.' : 'Сбор данных отменен.', false);
                    } else {
                        rpa_updateModalStatus((rpa_currentDisplayMode === 'USD' ? `Error fetching US price: ` : `Ошибка при запросе цены для США: `) + error.message, false);
                    }
                    rpa_updateProgressBar(0);
                    return;
                }

                if (!usData || !usData.best_purchase_option || !usData.best_purchase_option.final_price_in_cents) {
                    let msg = (rpa_currentDisplayMode === 'USD' ? `Game "${rpa_currentGameName}" ` : `Игра "${rpa_currentGameName}" `);
                    const isFreeOrUnavailableUS = (usData && usData.success === 1 && (!usData.best_purchase_option || usData.best_purchase_option.final_price_in_cents === "0" || !usData.best_purchase_option.final_price_in_cents));
                    msg += isFreeOrUnavailableUS ? (rpa_currentDisplayMode === 'USD' ? "is free or not available in the US." : "бесплатна или недоступна в США.") :
                        (rpa_currentDisplayMode === 'USD' ? "is unavailable in the US or has no price." : "недоступна в США или не имеет цены.");
                    msg += (rpa_currentDisplayMode === 'USD' ? " Analysis cannot proceed." : " Анализ невозможен.");
                    rpa_updateModalStatus(msg, false);
                    rpa_updateProgressBar(0);
                    return;
                }

                const basePriceCents = rpa_getPriceInCents(usData.best_purchase_option);
                if (!basePriceCents) {
                    rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Could not determine base US price for calculation.' : 'Не удалось определить базовую цену в США для расчета.', false);
                    rpa_updateProgressBar(0);
                    return;
                }
                const baseUsdPrice = parseFloat(basePriceCents) / 100;
                const baseUsdFormattedPrice = rpa_getDisplayFormattedPrice(usData.best_purchase_option);

                rpa_updateProgressBar(5);

                if (rpa_currentDisplayMode === 'USD') {
                    summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Base US Price:</span><span class="summary-value">${baseUsdPrice.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}</span></div>`;
                    try {
                        await rpa_fetchExchangeRates('usd', signal);
                        if (signal.aborted) throw new DOMException('Request aborted', 'AbortError');
                    } catch (e) {
                        if (e.name === 'AbortError') {
                            rpa_updateModalStatus('Data fetch aborted.', false);
                        } else {
                            rpa_updateModalStatus('Error fetching base USD exchange rates.', false);
                        }
                        rpa_updateProgressBar(0);
                        return;
                    }
                } else {
                    summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Базовая цена в США (для расчета):</span><span class="summary-value">$${baseUsdPrice.toFixed(2)}</span></div>`;
                    const recommendedRubPriceVal = calculateRecommendedRubPrice(baseUsdPrice);
                    if (recommendedRubPriceVal === null || typeof recommendedRubPriceVal === 'string') {
                        summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Рекомендуемая цена Steam в РФ:</span><span class="summary-value">${recommendedRubPriceVal || 'Не удалось рассчитать'}</span></div>`;
                    } else {
                        summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Рекомендуемая цена Steam в РФ:</span><span class="summary-value">${recommendedRubPriceVal.toLocaleString('ru-RU')} руб.</span></div>`;
                    }
                    try {
                        await rpa_fetchExchangeRates('rub', signal);
                        if (signal.aborted) throw new DOMException('Request aborted', 'AbortError');
                    } catch (e) {
                        if (e.name === 'AbortError') {
                            rpa_updateModalStatus('Сбор данных отменен.', false);
                        } else {
                            rpa_updateModalStatus('Ошибка загрузки базовых курсов валют.', false);
                        }
                        rpa_updateProgressBar(0);
                        return;
                    }
                }

                const regionalPrices = [];
                let ruActualPriceData = null;
                let ruActualPriceInRub = null;

                if (rpa_currentDisplayMode === 'USD') {
                    regionalPrices.push({
                        regionName: usRegionConfig.name,
                        localPriceFormatted: baseUsdFormattedPrice,
                        priceInUsd: baseUsdPrice,
                        cc: usRegionConfig.cc
                    });
                }

                const otherRegions = RPA_CONFIG.regions.filter(r => rpa_currentDisplayMode === 'USD' ? r.cc !== usRegionConfig.cc : true);
                const totalRegionsToProcess = otherRegions.length;
                let regionsProcessedCount = 0;

                for (let i = 0; i < totalRegionsToProcess; i += RPA_CONFIG.batchSize) {
                    if (signal.aborted) break;
                    const batch = otherRegions.slice(i, i + RPA_CONFIG.batchSize);
                    const batchProgressText = rpa_currentDisplayMode === 'USD' ?
                        `Workspaceing prices: batch ${Math.floor(i/RPA_CONFIG.batchSize)+1}/${Math.ceil(totalRegionsToProcess/RPA_CONFIG.batchSize)}` :
                        `Сбор цен: группа ${Math.floor(i/RPA_CONFIG.batchSize)+1}/${Math.ceil(totalRegionsToProcess/RPA_CONFIG.batchSize)}`;
                    rpa_updateModalStatus(`${batchProgressText} (${batch.map(r=>r.cc).join(', ')})...`, true);

                    const batchPromises = batch.map(region =>
                        rpa_fetchItemData(rpa_currentAppId, region.cc, signal)
                        .then(data => ({
                            region,
                            data
                        }))
                        .catch(error => {
                            if (error.name === 'AbortError') throw error;
                            console.warn(`[RPA] Error for region ${region.name} (${region.cc}): ${error.message}`);
                            return {
                                region,
                                error,
                                data: null
                            };
                        })
                    );

                    try {
                        const batchResults = await Promise.allSettled(batchPromises);
                        if (signal.aborted) throw new DOMException('Request aborted', 'AbortError');

                        for (const result of batchResults) {
                            regionsProcessedCount++;
                            let currentProgress = 5 + Math.round(((regionsProcessedCount + 1) / (totalRegionsToProcess + 1)) * 85);
                            rpa_updateProgressBar(currentProgress);

                            if (result.status === 'fulfilled' && result.value.data) {
                                const {
                                    region,
                                    data: regionData
                                } = result.value;
                                if (regionData && regionData.basic_info && regionData.best_purchase_option) {
                                    const purchaseOption = regionData.best_purchase_option;
                                    let priceInCents = rpa_getPriceInCents(purchaseOption);
                                    let displayFormattedPrice = rpa_getDisplayFormattedPrice(purchaseOption);

                                    if (priceInCents !== null && priceInCents >= 0) {
                                        const localPrice = parseFloat(priceInCents) / 100;

                                        if (rpa_currentDisplayMode === 'USD') {
                                            let priceInUsd = null;
                                            if (region.currencyApiCode.toLowerCase() === 'usd') {
                                                priceInUsd = localPrice;
                                            } else {
                                                try {
                                                    const rates = await rpa_fetchExchangeRates(region.currencyApiCode.toLowerCase(), signal);
                                                    if (signal.aborted) throw new DOMException('Request aborted', 'AbortError');
                                                    if (rates && typeof rates.usd === 'number') {
                                                        priceInUsd = localPrice * rates.usd;
                                                    } else {
                                                        const usdBasedRates = await rpa_fetchExchangeRates('usd', signal);
                                                        if (usdBasedRates && typeof usdBasedRates[region.currencyApiCode.toLowerCase()] === 'number' && usdBasedRates[region.currencyApiCode.toLowerCase()] !== 0) {
                                                            priceInUsd = localPrice / usdBasedRates[region.currencyApiCode.toLowerCase()];
                                                        } else {
                                                            console.warn(`[RPA] USD rate not found for ${region.currencyApiCode}`);
                                                        }
                                                    }
                                                } catch (rateError) {
                                                    if (rateError.name === 'AbortError') throw rateError;
                                                    console.warn(`[RPA] Rate error (USD) for ${region.currencyApiCode}: ${rateError.message}`);
                                                }
                                            }
                                            if (priceInUsd !== null && region.cc !== 'US') {
                                                regionalPrices.push({
                                                    regionName: region.name,
                                                    localPriceFormatted: displayFormattedPrice,
                                                    priceInUsd: priceInUsd,
                                                    cc: region.cc
                                                });
                                            }
                                        } else {
                                            let priceInRub = null;
                                            if (region.currencyApiCode.toLowerCase() === 'rub') {
                                                priceInRub = localPrice;
                                            } else {
                                                try {
                                                    const rates = await rpa_fetchExchangeRates(region.currencyApiCode.toLowerCase(), signal);
                                                    if (signal.aborted) throw new DOMException('Request aborted', 'AbortError');
                                                    if (rates && typeof rates.rub === 'number') {
                                                        priceInRub = localPrice * rates.rub;
                                                    } else {
                                                        console.warn(`[RPA] RUB rate not found for ${region.currencyApiCode}`);
                                                    }
                                                } catch (rateError) {
                                                    if (rateError.name === 'AbortError') throw rateError;
                                                    console.warn(`[RPA] Rate error (RUB) for ${region.currencyApiCode}: ${rateError.message}`);
                                                }
                                            }
                                            if (priceInRub !== null) {
                                                regionalPrices.push({
                                                    regionName: region.name,
                                                    localPriceFormatted: displayFormattedPrice,
                                                    priceInRub: priceInRub,
                                                    cc: region.cc
                                                });
                                            }
                                            if (region.cc === 'RU') {
                                                ruActualPriceData = {
                                                    formatted: displayFormattedPrice,
                                                    rub: priceInRub
                                                };
                                                ruActualPriceInRub = priceInRub;
                                            }
                                            if (region.cc === 'US' && rpa_currentDisplayMode === 'RUB' && !regionalPrices.find(p => p.cc === 'US')) {
                                                regionalPrices.push({
                                                    regionName: region.name,
                                                    localPriceFormatted: displayFormattedPrice,
                                                    priceInRub: priceInRub,
                                                    cc: region.cc
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } catch (batchError) {
                        if (batchError.name === 'AbortError') {
                            rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Data fetch aborted.' : 'Сбор данных отменен.', false);
                            rpa_updateProgressBar(0);
                            rpa_fetchController = null;
                            return;
                        }
                        console.error("[RPA] Error processing batch:", batchError);
                    }
                    if (i + RPA_CONFIG.batchSize < totalRegionsToProcess && !signal.aborted) {
                        await new Promise(resolve => setTimeout(resolve, RPA_CONFIG.delayBetweenBatches));
                    }
                    if (signal.aborted) break;
                }
                if (signal.aborted) {
                    rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Data fetch aborted.' : 'Сбор данных отменен.', false);
                    rpa_updateProgressBar(0);
                    rpa_fetchController = null;
                    return;
                }

                rpa_updateProgressBar(98);

                if (rpa_currentDisplayMode === 'USD') {
                    if (regionalPrices.length > 0) {
                        regionalPrices.sort((a, b) => a.priceInUsd - b.priceInUsd);
                        const cheapestRegion = regionalPrices[0];
                        const mostExpensiveRegion = regionalPrices[regionalPrices.length - 1];
                        summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Cheapest (USD):</span><span class="summary-value">${cheapestRegion.priceInUsd.toLocaleString('en-US', { style: 'currency', currency: 'USD' })} (${cheapestRegion.regionName})</span></div>`;
                        summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Most Expensive (USD):</span><span class="summary-value">${mostExpensiveRegion.priceInUsd.toLocaleString('en-US', { style: 'currency', currency: 'USD' })} (${mostExpensiveRegion.regionName})</span></div>`;
                        const usEntryIndex = regionalPrices.findIndex(r => r.cc === 'US');
                        if (usEntryIndex !== -1) {
                            summaryDiv.innerHTML += `<div class="summary-item"><span class="summary-label">US Price Rank:</span><span class="summary-value">${usEntryIndex + 1} of ${regionalPrices.length}</span></div>`;
                        }
                        generatePriceTable(regionalPrices, baseUsdPrice, resultsDiv);
                    } else {
                        resultsDiv.innerHTML = `<p style="text-align:center; margin-top:20px; color: #8f98a0;">Could not retrieve regional prices for comparison.</p>`;
                    }
                } else {
                    const ruComparisonDiv = document.createElement('div');
                    ruComparisonDiv.id = 'rpaRuComparison';
                    ruComparisonDiv.style.cssText = "margin-top:10px; padding-top:10px; border-top: 1px solid #2a3f5a;";
                    summaryDiv.appendChild(ruComparisonDiv);
                    const recommendedRubPriceVal = calculateRecommendedRubPrice(baseUsdPrice);

                    if (ruActualPriceData && typeof recommendedRubPriceVal === 'number') {
                        const actualRu = ruActualPriceData.rub;
                        let factPriceValue = "N/A",
                            factPriceSubValue = "",
                            subValueColor = "#c6d4df";
                        if (actualRu !== null) {
                            factPriceValue = `${actualRu.toLocaleString('ru-RU', {minimumFractionDigits: 2, maximumFractionDigits: 2})} руб.`;
                            const diff = actualRu - recommendedRubPriceVal;
                            const diffPercent = recommendedRubPriceVal !== 0 ? (diff / recommendedRubPriceVal) * 100 : (diff > 0 ? Infinity : (actualRu === 0 ? 0 : -Infinity));
                            if (diff < -0.01) {
                                subValueColor = 'lightgreen';
                                factPriceSubValue = `(на ${Math.abs(diff).toLocaleString('ru-RU', {maximumFractionDigits: 2})} руб. / ${Math.abs(diffPercent).toFixed(1)}% ДЕШЕВЛЕ рекомендуемой)`;
                            } else if (diff > 0.01) {
                                subValueColor = 'salmon';
                                factPriceSubValue = `(на ${diff.toLocaleString('ru-RU', {maximumFractionDigits: 2})} руб. / ${diffPercent.toFixed(1)}% ДОРОЖЕ рекомендуемой)`;
                            } else {
                                factPriceSubValue = `(соответствует рекомендуемой)`;
                            }
                        } else {
                            factPriceValue = `<span style="color: orange;">Цена в РФ не найдена/неконвертируема.</span>`;
                        }
                        ruComparisonDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Фактическая цена в РФ:</span><span class="summary-value">${factPriceValue}${factPriceSubValue ? `<span class="summary-sub-value" style="color:${subValueColor};">${factPriceSubValue}</span>` : ''}</span></div>`;
                    } else if (typeof recommendedRubPriceVal === 'number') {
                        ruComparisonDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Фактическая цена в РФ:</span><span class="summary-value" style="color:orange;">Не найдена.</span></div>`;
                    }

                    if (regionalPrices.length > 0) {
                        regionalPrices.sort((a, b) => a.priceInRub - b.priceInRub);
                        let ruRank = -1;
                        if (ruActualPriceInRub !== null) {
                            ruRank = regionalPrices.findIndex(rp => rp.cc === 'RU' && Math.abs(rp.priceInRub - ruActualPriceInRub) < 0.01) + 1;
                            if (ruRank === 0) {
                                const ruEntry = regionalPrices.find(rp => rp.cc === 'RU');
                                if (ruEntry) ruRank = regionalPrices.findIndex(rp => rp.priceInRub >= ruEntry.priceInRub) + 1;
                                if (ruRank === 0 && regionalPrices.length > 0) ruRank = 1;
                            }
                        }
                        let rankText = "Цена РФ отсутствует, мировой ранг не определен.";
                        if (ruRank > 0) {
                            rankText = `${ruRank} из ${regionalPrices.length}`;
                        } else if (ruActualPriceInRub !== null) {
                            rankText = `Не удалось точно определить ранг РФ.`;
                        }
                        ruComparisonDiv.innerHTML += `<div class="summary-item"><span class="summary-label">Место РФ в мировом рейтинге цен:</span><span class="summary-value">${rankText}</span></div>`;
                        generatePriceTable(regionalPrices, ruActualPriceInRub, resultsDiv);
                    } else {
                        resultsDiv.innerHTML = `<p style="text-align:center; margin-top:20px; color: #8f98a0;">Не удалось получить региональные цены для сравнения.</p>`;
                    }
                }

                rpa_updateModalStatus(rpa_currentDisplayMode === 'USD' ? 'Analysis complete.' : 'Анализ завершен.', false);
                rpa_updateProgressBar(100);
                setTimeout(() => rpa_updateProgressBar(0), 2000);
                rpa_fetchController = null;
            }

            function generatePriceTable(prices, comparisonPriceBase, container) {
                container.innerHTML = '';
                const table = document.createElement('table');
                table.className = 'rpaSinglePriceTable';
                const thead = table.createTHead();
                const headerRow = thead.insertRow();

                const isUSDMode = rpa_currentDisplayMode === 'USD';
                const headers = isUSDMode ? [{
                        text: '#',
                        class: 'col-rank-header'
                    }, {
                        text: 'Region (CC)',
                        class: 'col-region-header'
                    },
                    {
                        text: 'Local Price',
                        class: 'col-local-price-header'
                    }, {
                        text: 'Price (USD)',
                        class: 'col-usd-price-header'
                    },
                    {
                        text: 'Diff. vs US (%)',
                        class: 'col-diff-us-header'
                    }
                ] : [{
                        text: '№',
                        class: 'col-rank-header'
                    }, {
                        text: 'Регион (Код страны)',
                        class: 'col-region-header'
                    },
                    {
                        text: 'Цена (лок. вал.)',
                        class: 'col-local-price-header'
                    }, {
                        text: 'Цена (RUB)',
                        class: 'col-rub-price-header'
                    },
                    {
                        text: 'Разница с РФ (%)',
                        class: 'col-diff-ru-header'
                    }
                ];

                headers.forEach(headerInfo => {
                    const th = document.createElement('th');
                    th.textContent = headerInfo.text;
                    th.className = headerInfo.class;
                    headerRow.appendChild(th);
                });

                const tbody = table.createTBody();
                prices.forEach((rp, index) => {
                    const row = tbody.insertRow();
                    const highlightCC = isUSDMode ? 'US' : 'RU';
                    const highlightClass = isUSDMode ? 'highlight-us' : 'highlight-ru';
                    if (rp.cc === highlightCC) {
                        row.classList.add(highlightClass);
                    }

                    row.insertCell().textContent = index + 1;
                    row.cells[0].className = 'col-rank';
                    row.insertCell().textContent = `${rp.regionName} (${rp.cc})`;
                    row.cells[1].className = 'col-region';

                    const priceToDisplay = isUSDMode ? rp.priceInUsd : rp.priceInRub;
                    row.insertCell().textContent = rp.localPriceFormatted || (priceToDisplay === 0 ? (isUSDMode ? 'Free' : 'Бесплатно') : 'N/A');
                    row.cells[2].className = 'col-local-price';

                    const convertedPriceCell = row.insertCell();
                    convertedPriceCell.className = isUSDMode ? 'col-usd-price' : 'col-rub-price';
                    if (priceToDisplay !== null) {
                        convertedPriceCell.textContent = isUSDMode ?
                            priceToDisplay.toLocaleString('en-US', {
                                style: 'currency',
                                currency: 'USD'
                            }) :
                            priceToDisplay.toLocaleString('ru-RU', {
                                maximumFractionDigits: 0
                            }) + ' ₽';
                    } else {
                        convertedPriceCell.textContent = 'N/A';
                    }

                    const diffCell = row.insertCell();
                    diffCell.className = isUSDMode ? 'col-diff-us' : 'col-diff-ru';
                    if (rp.cc === highlightCC) {
                        diffCell.textContent = isUSDMode ? 'Base' : '-';
                        diffCell.classList.add('neutral');
                    } else if (comparisonPriceBase !== null && comparisonPriceBase > 0 && priceToDisplay !== null) {
                        const diffPercent = ((priceToDisplay - comparisonPriceBase) / comparisonPriceBase) * 100;
                        diffCell.textContent = (diffPercent >= 0 ? '+' : '') + diffPercent.toFixed(1) + '%';
                        if (diffPercent < -0.1) diffCell.classList.add('positive');
                        else if (diffPercent > 0.1) diffCell.classList.add('negative');
                        else diffCell.classList.add('neutral');
                    } else if (priceToDisplay === 0 && comparisonPriceBase === 0) {
                        diffCell.textContent = '0%';
                        diffCell.classList.add('neutral');
                    } else {
                        diffCell.textContent = 'N/A';
                        diffCell.classList.add('neutral');
                    }
                });
                container.appendChild(table);
            }

            function rpa_init() {
                rpa_updateTextsAndRegionNames();
                const initLoad = () => {
                    if (document.querySelector('.game_area_purchase_game_wrapper')) {
                        rpa_addPriorButton();
                        rpa_createModal();
                    } else {
                        setTimeout(initLoad, 500);
                    }
                };
                if (document.readyState === 'complete' || document.readyState === 'interactive') {
                    initLoad();
                } else {
                    window.addEventListener('DOMContentLoaded', initLoad);
                }
            }
            rpa_init();
        })();
    }

    // Скрипт для получения дополнительной информации об игре при наведении на неё на странице поиска по каталогу | https://store.steampowered.com/search/
    if (scriptsConfig.catalogInfo && unsafeWindow.location.pathname.includes('/search')) {
        (function() {
            'use strict';

            const ALEXANDER_API_URL = "https://api.steampowered.com/IStoreBrowseService/GetItems/v1";
            const HANNIBAL_WAIT_TIME = 2000;
            const CAESAR_VISIBLE_ELEMENTS_SELECTOR = "a.search_result_row[data-ds-appid]";
            const NAPOLEON_HOVER_ELEMENT_SELECTOR = "a.search_result_row";

            let GENghis_collectedAppIds = new Set();
            let ATTILA_tooltip = null;
            let SALADIN_hoverTimer = null;
            let TAMERLAN_hideTimer = null;

            let RUSSIAN_TRANSLATION_CHECKBOX = null;
            let RUSSIAN_VOICE_CHECKBOX = null;
            let NO_RUSSIAN_CHECKBOX = null;
            const STEAM_TAGS_CACHE_KEY = 'SteamEnhancer_TagsCache_v2';
            const STEAM_TAGS_URL = "https://gist.githubusercontent.com/0wn3dg0d/22a351ff4c65e50a9a8af6da360defad/raw/steamrutagsownd.json";
            const OWNED_APPS_CACHE_KEY = 'SteamEnhancer_OwnedApps';
            const USERDATA_URL = 'https://store.steampowered.com/dynamicstore/userdata/';
            const CACHE_DURATION = 24 * 60 * 60 * 1000;

            async function loadSteamTags() {
                const cached = GM_getValue(STEAM_TAGS_CACHE_KEY, {
                    data: null,
                    timestamp: 0
                });
                const now = Date.now();
                const CACHE_DURATION = 744 * 60 * 60 * 1000;

                if (cached.data && (now - cached.timestamp) < CACHE_DURATION) {
                    return cached.data;
                }

                try {
                    const response = await new Promise((resolve, reject) => {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: STEAM_TAGS_URL,
                            onload: resolve,
                            onerror: reject
                        });
                    });

                    if (response.status === 200) {
                        const data = JSON.parse(response.responseText);
                        GM_setValue(STEAM_TAGS_CACHE_KEY, {
                            data: data,
                            timestamp: now
                        });
                        return data;
                    }
                } catch (e) {
                    console.error('Ошибка загрузки тегов:', e);
                    return cached.data || {};
                }

                return {};
            }

            async function fetchOwnedApps() {
                const cached = GM_getValue(OWNED_APPS_CACHE_KEY, {
                    data: null,
                    timestamp: 0
                });
                const now = Date.now();

                if (cached.data && (now - cached.timestamp) < CACHE_DURATION) {
                    return cached.data;
                }

                try {
                    const response = await new Promise((resolve, reject) => {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: USERDATA_URL,
                            onload: resolve,
                            onerror: reject
                        });
                    });

                    if (response.status === 200) {
                        const data = JSON.parse(response.responseText);
                        const ownedApps = data.rgOwnedApps || [];
                        GM_setValue(OWNED_APPS_CACHE_KEY, {
                            data: ownedApps,
                            timestamp: now
                        });
                        return ownedApps;
                    }
                } catch (e) {
                    console.error('Ошибка загрузки списка игр:', e);
                    return cached.data || [];
                }

                return [];
            }

            function fetchGameData(appIds) {
                const inputJson = {
                    ids: Array.from(appIds).map(appid => ({
                        appid
                    })),
                    context: {
                        language: "russian",
                        country_code: "US",
                        steam_realm: 1
                    },
                    data_request: {
                        include_assets: true,
                        include_release: true,
                        include_platforms: true,
                        include_all_purchase_options: true,
                        include_screenshots: true,
                        include_trailers: true,
                        include_ratings: true,
                        include_tag_count: true,
                        include_reviews: true,
                        include_basic_info: true,
                        include_supported_languages: true,
                        include_full_description: true,
                        include_included_items: true,
                        included_item_data_request: {
                            include_assets: true,
                            include_release: true,
                            include_platforms: true,
                            include_all_purchase_options: true,
                            include_screenshots: true,
                            include_trailers: true,
                            include_ratings: true,
                            include_tag_count: true,
                            include_reviews: true,
                            include_basic_info: true,
                            include_supported_languages: true,
                            include_full_description: true,
                            include_included_items: true,
                            include_assets_without_overrides: true,
                            apply_user_filters: false,
                            include_links: true
                        },
                        include_assets_without_overrides: true,
                        apply_user_filters: false,
                        include_links: true
                    }
                };

                GM_xmlhttpRequest({
                    method: "GET",
                    url: `${ALEXANDER_API_URL}?input_json=${encodeURIComponent(JSON.stringify(inputJson))}`,
                    onload: function(response) {
                        const data = JSON.parse(response.responseText);
                        processGameData(data);
                    }
                });
            }

            async function processGameData(data) {
                const ownedApps = await fetchOwnedApps();
                const items = data.response.store_items;
                const dlcFilterActive = document.querySelector('[data-param="your_dlc"] .tab_filter_control')?.classList.contains('checked');

                items.forEach(item => {
                    const appId = item.id;
                    const gameElement = document.querySelector(`a.search_result_row[data-ds-appid="${appId}"]`);
                    if (gameElement) {
                        const gameData = {
                            is_early_access: item.is_early_access,
                            review_count: item.reviews?.summary_filtered?.review_count,
                            percent_positive: item.reviews?.summary_filtered?.percent_positive,
                            short_description: item.basic_info?.short_description,
                            publishers: item.basic_info?.publishers?.map(p => p.name).join(", "),
                            developers: item.basic_info?.developers?.map(d => d.name).join(", "),
                            franchises: item.basic_info?.franchises?.map(f => f.name).join(", "),
                            tagids: item.tagids || [],
                            language_support_russian: item.supported_languages?.find(lang => lang.elanguage === 8),
                            language_support_english: item.supported_languages?.find(lang => lang.elanguage === 0),
                            type: item.type,
                            parent_appid: item.related_items?.parent_appid
                        };

                        gameElement.dataset.gameInfo = JSON.stringify(gameData);
                        applyRussianLanguageFilter(gameElement);

                        if (item.type === 4 && item.related_items?.parent_appid && ownedApps.includes(item.related_items.parent_appid)) {
                            gameElement.classList.add('es_highlighted_dlcforya');
                        }

                        if (dlcFilterActive) {
                            applyDlcFilter(gameElement, true);
                        }
                    }
                });
            }

            function collectAndFetchAppIds() {
                const visibleElements = document.querySelectorAll(CAESAR_VISIBLE_ELEMENTS_SELECTOR);
                const newAppIds = new Set();

                visibleElements.forEach(element => {
                    const appId = element.dataset.dsAppid;
                    if (!GENghis_collectedAppIds.has(appId)) {
                        newAppIds.add(parseInt(appId, 10));
                        GENghis_collectedAppIds.add(appId);
                    }
                });

                if (newAppIds.size > 0) {
                    fetchGameData(newAppIds);
                }
            }

            function handleHover(event) {
                const gameElement = event.target.closest(NAPOLEON_HOVER_ELEMENT_SELECTOR);

                if (gameElement && gameElement.dataset.gameInfo) {
                    clearTimeout(SALADIN_hoverTimer);
                    clearTimeout(TAMERLAN_hideTimer);

                    SALADIN_hoverTimer = setTimeout(() => {
                        const gameData = JSON.parse(gameElement.dataset.gameInfo);
                        displayGameInfo(gameElement, gameData);
                    }, 300);
                } else {
                    clearTimeout(SALADIN_hoverTimer);
                    clearTimeout(TAMERLAN_hideTimer);
                    if (ATTILA_tooltip) {
                        ATTILA_tooltip.style.opacity = 0;
                        setTimeout(() => {
                            ATTILA_tooltip.style.display = 'none';
                        }, 300);
                    }
                }
            }

            function getReviewClassCatalog(percent, totalReviews) {
                if (totalReviews === 0) return 'catalog-no-reviews';
                if (percent >= 70) return 'catalog-positive';
                if (percent >= 40) return 'catalog-mixed';
                if (percent >= 1) return 'catalog-negative';
                return 'catalog-negative';
            }

            async function getTagNames(tagIds) {
                const tagsData = await loadSteamTags();
                return tagIds.slice(0, 5).map(tagId =>
                    tagsData[tagId] || `Тег #${tagId}`
                );
            }

            async function displayGameInfo(element, data) {
                if (!ATTILA_tooltip) {
                    ATTILA_tooltip = document.createElement('div');
                    ATTILA_tooltip.className = 'custom-tooltip';
                    ATTILA_tooltip.innerHTML = '<div class="tooltip-arrow"></div><div class="tooltip-content"></div>';
                    document.body.appendChild(ATTILA_tooltip);
                }

                const tooltipContent = ATTILA_tooltip.querySelector('.tooltip-content');

                let languageSupportRussianText = "Отсутствует";
                let languageSupportRussianClass = 'catalog-language-no';
                if (data.language_support_russian) {
                    languageSupportRussianText = "";
                    if (data.language_support_russian.supported) languageSupportRussianText += "<br>Интерфейс: ✔ ";
                    if (data.language_support_russian.full_audio) languageSupportRussianText += "<br>Озвучка: ✔ ";
                    if (data.language_support_russian.subtitles) languageSupportRussianText += "<br>Субтитры: ✔";
                    if (languageSupportRussianText === "") languageSupportRussianText = "Отсутствует";
                    else languageSupportRussianClass = 'catalog-language-yes';
                }

                let languageSupportEnglishText = "Отсутствует";
                let languageSupportEnglishClass = 'catalog-language-no';
                if (scriptsConfig.toggleEnglishLangInfo && data.language_support_english) {
                    languageSupportEnglishText = "";
                    if (data.language_support_english.supported) languageSupportEnglishText += "<br>Интерфейс: ✔ ";
                    if (data.language_support_english.full_audio) languageSupportEnglishText += "<br>Озвучка: ✔ ";
                    if (data.language_support_english.subtitles) languageSupportEnglishText += "<br>Субтитры: ✔";
                    if (languageSupportEnglishText === "") languageSupportEnglishText = "Отсутствует";
                    else languageSupportEnglishClass = 'catalog-language-yes';
                }

                const reviewClass = getReviewClassCatalog(data.percent_positive, data.review_count);
                const earlyAccessClass = data.is_early_access ? 'catalog-early-access-yes' : 'catalog-early-access-no';
                const tags = await getTagNames(data.tagids || []);
                const tagsHtml = tags.map(tag =>
                    `<div class="custom-tag">${tag}</div>`
                ).join('');

                tooltipContent.innerHTML = `
                    <div style="margin-bottom: 0px;"><strong>Издатели:</strong> <span class="${!data.publishers ? 'catalog-no-reviews' : ''}">${data.publishers || "Нет данных"}</span></div>
                    <div style="margin-bottom: 0px;"><strong>Разработчики:</strong> <span class="${!data.developers ? 'catalog-no-reviews' : ''}">${data.developers || "Нет данных"}</span></div>
                    <div style="margin-bottom: 10px;"><strong>Серия игр:</strong> <span class="${!data.franchises ? 'catalog-no-reviews' : ''}">${data.franchises || "Нет данных"}</span></div>
                    <div style="margin-bottom: 10px;"><strong>Отзывы: </strong><span id="reviewCount">${data.review_count || "0"} </span><span class="${reviewClass}">(${data.percent_positive || "0"}% положительных)</span></div>
                    <div style="margin-bottom: 10px;"><strong>Ранний доступ:</strong> <span class="${earlyAccessClass}">${data.is_early_access ? "Да" : "Нет"}</span></div>
                    <div style="margin-bottom: 10px;"><strong>Русский язык:</strong> <span class="${languageSupportRussianClass}">${languageSupportRussianText}</span></div>
                    ${scriptsConfig.toggleEnglishLangInfo ? `<div style="margin-bottom: 10px;"><strong>Английский язык:</strong> <span class="${languageSupportEnglishClass}">${languageSupportEnglishText}</span></div>` : ''}
                    <div style="margin-bottom: 10px;"><strong>Метки:</strong><br>
                    <div class="custom-tags-container">${tagsHtml}</div></div>
                    <div style="margin-bottom: 10px;"><strong>Описание:</strong> <span class="${!data.short_description ? 'catalog-no-reviews' : ''}">${data.short_description || "Нет данных"}</span></div>
                `;

                ATTILA_tooltip.style.display = 'block';

                const rect = element.getBoundingClientRect();
                const tooltipRect = ATTILA_tooltip.getBoundingClientRect();
                ATTILA_tooltip.style.left = `${rect.left + window.scrollX - tooltipRect.width - 4}px`;
                ATTILA_tooltip.style.top = `${rect.top + window.scrollY - 20}px`;

                ATTILA_tooltip.style.opacity = 0;
                ATTILA_tooltip.style.display = 'block';
                setTimeout(() => {
                    ATTILA_tooltip.style.opacity = 1;
                }, 10);

                element.addEventListener('mouseleave', () => {
                    clearTimeout(TAMERLAN_hideTimer);
                    TAMERLAN_hideTimer = setTimeout(() => {
                        ATTILA_tooltip.style.opacity = 0;
                        setTimeout(() => {
                            ATTILA_tooltip.style.display = 'none';
                        }, 300);
                    }, 200);
                }, {
                    once: true
                });

                element.addEventListener('mouseover', () => {
                    clearTimeout(TAMERLAN_hideTimer);
                });
            }

            function createRussianLanguageFilterBlock() {
                const filterBlock = document.createElement('div');
                filterBlock.className = 'block search_collapse_block';
                filterBlock.innerHTML = `
                    <div data-panel="{&quot;focusable&quot;:true,&quot;clickOnActivate&quot;:true}" class="block_header labs_block_header">
                        <div>Русский перевод</div>
                    </div>
                    <div class="block_content block_content_inner">
                        <div class="tab_filter_control_row" data-param="russian_translation" data-value="__toggle" data-loc="Только текст" data-clientside="0">
                            <span data-panel="{&quot;focusable&quot;:true,&quot;clickOnActivate&quot;:true}" class="tab_filter_control tab_filter_control_include" data-param="russian_translation" data-value="__toggle" data-loc="Только текст" data-clientside="0" data-gpfocus="item">
                                <span>
                                    <span class="tab_filter_control_checkbox"></span>
                                    <span class="tab_filter_control_label">Только текст</span>
                                    <span class="tab_filter_control_count" style="display: none;"></span>
                                </span>
                            </span>
                        </div>
                        <div class="tab_filter_control_row" data-param="russian_voice" data-value="__toggle" data-loc="Озвучка" data-clientside="0">
                            <span data-panel="{&quot;focusable&quot;:true,&quot;clickOnActivate&quot;:true}" class="tab_filter_control tab_filter_control_include" data-param="russian_voice" data-value="__toggle" data-loc="Озвучка" data-clientside="0" data-gpfocus="item">
                                <span>
                                    <span class="tab_filter_control_checkbox"></span>
                                    <span class="tab_filter_control_label">Озвучка</span>
                                    <span class="tab_filter_control_count" style="display: none;"></span>
                                </span>
                            </span>
                        </div>
                        <div class="tab_filter_control_row" data-param="no_russian" data-value="__toggle" data-loc="Без перевода" data-clientside="0">
                            <span data-panel="{&quot;focusable&quot;:true,&quot;clickOnActivate&quot;:true}" class="tab_filter_control tab_filter_control_include" data-param="no_russian" data-value="__toggle" data-loc="Без перевода" data-clientside="0" data-gpfocus="item">
                                <span>
                                    <span class="tab_filter_control_checkbox"></span>
                                    <span class="tab_filter_control_label">Без перевода</span>
                                    <span class="tab_filter_control_count" style="display: none;"></span>
                                </span>
                            </span>
                        </div>
                    </div>
                `;

                const dlcFilterBlock = document.createElement('div');
                dlcFilterBlock.className = 'block search_collapse_block';
                dlcFilterBlock.innerHTML = `
                    <div data-panel="{&quot;focusable&quot;:true,&quot;clickOnActivate&quot;:true}" class="block_header labs_block_header">
                        <div>DLC</div>
                    </div>
                    <div class="block_content block_content_inner">
                        <div class="tab_filter_control_row" data-param="your_dlc" data-value="__toggle" data-loc="Только ваши DLC" data-clientside="0">
                            <span data-panel="{&quot;focusable&quot;:true,&quot;clickOnActivate&quot;:true}" class="tab_filter_control tab_filter_control_include" data-param="your_dlc" data-value="__toggle" data-loc="Только ваши DLC" data-clientside="0" data-gpfocus="item">
                                <span>
                                    <span class="tab_filter_control_checkbox"></span>
                                    <span class="tab_filter_control_label">Только ваши DLC</span>
                                    <span class="tab_filter_control_count" style="display: none;"></span>
                                </span>
                            </span>
                        </div>
                    </div>
                `;

                const priceBlock = document.querySelector('.block.search_collapse_block[data-collapse-name="price"]');
                priceBlock.parentNode.insertBefore(filterBlock, priceBlock.nextSibling);
                priceBlock.parentNode.insertBefore(dlcFilterBlock, filterBlock.nextSibling);

                const translationRow = filterBlock.querySelector('[data-param="russian_translation"]');
                const voiceRow = filterBlock.querySelector('[data-param="russian_voice"]');
                const noRussianRow = filterBlock.querySelector('[data-param="no_russian"]');
                const dlcRow = dlcFilterBlock.querySelector('[data-param="your_dlc"]');

                [translationRow, voiceRow, noRussianRow].forEach(row => {
                    row.addEventListener('click', () => {
                        const control = row.querySelector('.tab_filter_control');
                        const wasChecked = control.classList.contains('checked');

                        [translationRow, voiceRow, noRussianRow].forEach(r => {
                            r.querySelector('.tab_filter_control').classList.remove('checked');
                            r.classList.remove('checked');
                        });

                        if (!wasChecked) {
                            control.classList.add('checked');
                            row.classList.add('checked');
                        }

                        document.querySelectorAll(CAESAR_VISIBLE_ELEMENTS_SELECTOR).forEach(gameElement => {
                            applyRussianLanguageFilter(gameElement);
                        });
                    });
                });

                dlcRow.addEventListener('click', () => {
                    const control = dlcRow.querySelector('.tab_filter_control');
                    const isChecked = !control.classList.contains('checked');

                    control.classList.toggle('checked');
                    dlcRow.classList.toggle('checked');

                    document.querySelectorAll(CAESAR_VISIBLE_ELEMENTS_SELECTOR).forEach(gameElement => {
                        applyDlcFilter(gameElement, isChecked);
                    });
                });
            }

            function applyDlcFilter(gameElement, showOnlyDlc) {
                if (!gameElement.dataset.gameInfo) return;

                const gameData = JSON.parse(gameElement.dataset.gameInfo);
                const isDlcForOwnedGame = gameElement.classList.contains('es_highlighted_dlcforya');

                if (showOnlyDlc) {
                    if (!isDlcForOwnedGame) {
                        animateDisappearance(gameElement);
                    } else {
                        animateAppearance(gameElement);
                    }
                } else {
                    animateAppearance(gameElement);
                }
            }

            function applyRussianLanguageFilter(gameElement) {
                if (!gameElement.dataset.gameInfo) return;

                const gameData = JSON.parse(gameElement.dataset.gameInfo);
                const hasRussianText = gameData.language_support_russian?.supported || gameData.language_support_russian?.subtitles;
                const hasRussianVoice = gameData.language_support_russian?.full_audio;
                const hasAnyRussian = hasRussianText || hasRussianVoice;

                const translationChecked = document.querySelector('[data-param="russian_translation"] .tab_filter_control').classList.contains('checked');
                const voiceChecked = document.querySelector('[data-param="russian_voice"] .tab_filter_control').classList.contains('checked');
                const noRussianChecked = document.querySelector('[data-param="no_russian"] .tab_filter_control').classList.contains('checked');
                const dlcFilterActive = document.querySelector('[data-param="your_dlc"] .tab_filter_control')?.classList.contains('checked');

                if (dlcFilterActive && !gameElement.classList.contains('es_highlighted_dlcforya')) {
                    animateDisappearance(gameElement);
                    return;
                }

                if (translationChecked) {
                    if (!hasRussianText || hasRussianVoice) animateDisappearance(gameElement);
                    else animateAppearance(gameElement);
                } else if (voiceChecked) {
                    if (!hasRussianVoice) animateDisappearance(gameElement);
                    else animateAppearance(gameElement);
                } else if (noRussianChecked) {
                    if (hasAnyRussian) animateDisappearance(gameElement);
                    else animateAppearance(gameElement);
                } else {
                    animateAppearance(gameElement);
                }
            }

            function animateDisappearance(element) {
                element.style.transition = 'opacity 0.5s ease-out, transform 0.5s ease-out';
                element.style.opacity = '0';
                element.style.transform = 'translateX(-100%)';

                setTimeout(() => {
                    element.style.display = 'none';
                }, 500);
            }

            function animateAppearance(element) {
                element.style.display = 'block';
                element.style.opacity = '0';
                element.style.transform = 'translateX(-100%)';
                element.style.transition = 'opacity 0.5s ease-in-out, transform 0.5s ease-in-out';

                setTimeout(() => {
                    element.style.opacity = '1';
                    element.style.transform = 'translateX(0)';
                }, 0);

                setTimeout(() => {
                    element.style.transition = '';
                }, 500);
            }

            function observeNewElements() {
                const observer = new MutationObserver((mutations) => {
                    mutations.forEach(mutation => {
                        if (mutation.type === 'childList') {
                            collectAndFetchAppIds();
                        }
                    });
                });

                observer.observe(document.body, {
                    childList: true,
                    subtree: true
                });
            }

            function initialize() {
                setTimeout(() => {
                    collectAndFetchAppIds();
                    observeNewElements();
                    document.addEventListener('mouseover', handleHover);
                    createRussianLanguageFilterBlock();
                }, HANNIBAL_WAIT_TIME);
            }

            initialize();

            const style = document.createElement('style');
            style.innerHTML = `
                .custom-tooltip {
                    position: absolute;
                    background: linear-gradient(to bottom, #e3eaef, #c7d5e0);
                    color: #30455a;
                    padding: 12px;
                    border-radius: 0px;
                    box-shadow: 0 0 12px #000;
                    font-size: 12px;
                    max-width: 300px;
                    display: none;
                    z-index: 1000;
                    opacity: 0;
                    transition: opacity 0.4s ease-in-out;
                }
                .tooltip-arrow {
                    position: absolute;
                    right: -9px;
                    top: 32px;
                    width: 0;
                    height: 0;
                    border-top: 10px solid transparent;
                    border-bottom: 10px solid transparent;
                    border-left: 10px solid #E1E8ED;
                }
                .catalog-positive {
                    color: #2B80E9;
                }
                .catalog-mixed {
                    color: #997a00;
                }
                .catalog-negative {
                    color: #E53E3E;
                }
                .catalog-no-reviews {
                    color: #929396;
                }
                .catalog-language-yes {
                    color: #2B80E9;
                }
                .catalog-language-no {
                    color: #E53E3E;
                }
                .catalog-early-access-yes {
                    color: #2B80E9;
                }
                .catalog-early-access-no {
                    color: #929396;
                }
                .search_result_row {
                    transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
                }
                .custom-tags-container {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 3px;
                    margin-top: 6px;
                }
                .custom-tag {
                    background-color: #96a3ae;
                    color: #e3eaef;
                    padding: 0 4px;
                    border-radius: 2px;
                    font-size: 11px;
                    line-height: 19px;
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    max-width: 200px;
                    box-shadow: none;
                    margin-bottom: 3px;
                }
                .es_highlighted_dlcforya {
                    background: #822dbf linear-gradient(135deg, rgba(0, 0, 0, 0.70) 10%, rgba(0, 0, 0, 0) 100%) !important;
                }
            `;
            document.head.appendChild(style);
        })();
    }

    // Скрипт скрытия игр на странице поиска по каталогу | https://store.steampowered.com/search/
    if (scriptsConfig.catalogHider && unsafeWindow.location.pathname.includes('/search')) {
        (function() {
            "use strict";

            function addBeetles() {
                const scarabLinks = document.querySelectorAll("a.search_result_row:not(.ds_ignored):not(.ds_excluded_by_preferences):not(.ds_wishlist):not(.ds_owned)");
                scarabLinks.forEach(link => {
                    if (link.querySelector(".my-checkbox")) return;
                    const ladybug = document.createElement("input");
                    ladybug.type = "checkbox";
                    ladybug.className = "my-checkbox";
                    ladybug.dataset.aphid = link.dataset.dsAppid;
                    link.insertBefore(ladybug, link.firstChild);

                    ladybug.addEventListener("change", function() {
                        link.style.background = this.checked ? "linear-gradient(to bottom, #381616, #5d1414)" : "";
                    });
                });
            }

            function hideSelectedCrickets() {
                const checkedLadybugs = document.querySelectorAll(".my-checkbox:checked");
                const sessionID = typeof unsafeWindow !== 'undefined' ? unsafeWindow.g_sessionID : window.g_sessionID;

                if (!sessionID) {
                    console.error('[CatalogHider] Не удалось получить g_sessionID!');
                    alert('Не удалось получить ID сессии для скрытия игр. Пожалуйста, убедитесь, что вы авторизованы.');
                    return;
                }

                checkedLadybugs.forEach(ladybug => {
                    const aphid = ladybug.dataset.aphid;
                    const link = document.querySelector(`a[data-ds-appid="${aphid}"]`);
                    if (link) {
                        link.classList.add("ds_ignored", "ds_flagged");
                        ladybug.remove();

                        GM_xmlhttpRequest({
                            method: "POST",
                            url: "https://store.steampowered.com/recommended/ignorerecommendation/",
                            data: `sessionid=${sessionID}&appid=${aphid}&remove=0&snr=1_account_notinterested_`,
                            headers: { "Content-Type": "application/x-www-form-urlencoded" },
                            onload: function(response) {
                                console.log(`[CatalogHider] Игра с appid ${aphid} добавлена в список игнорируемого.`);
                                if (typeof unsafeWindow !== 'undefined' && unsafeWindow.GDynamicStore) {
                                    unsafeWindow.GDynamicStore.InvalidateCache();
                                }
                            },
                            onerror: function(error) {
                                console.error(`[CatalogHider] Ошибка при скрытии игры ${aphid}:`, error);
                            }
                        });
                    }
                });
                setTimeout(updateAntCounter, 500);
            }

            function removeIgnoredDragonflies() {
                const ignoredGames = document.querySelectorAll("a.search_result_row.ds_ignored, a.search_result_row.ds_excluded_by_preferences,a.search_result_row.ds_wishlist");
                ignoredGames.forEach(game => game.remove());
                updateAntCounter();
            }

            function updateAntCounter() {
                const scarabLinks = document.querySelectorAll("a.search_result_row:not(.ds_ignored):not(.ds_excluded_by_preferences):not(.ds_wishlist):not(.ds_owned)");
                const termiteElement = document.querySelector(".game-counter");
                if (termiteElement) {
                    termiteElement.textContent = `Игр осталось: ${scarabLinks.length}`;
                }
            }

            const grasshopperButton = document.createElement("button");
            grasshopperButton.textContent = "Скрыть выбранное";
            grasshopperButton.addEventListener("click", hideSelectedCrickets);
            grasshopperButton.classList.add("my-button", "floating-button");
            document.body.appendChild(grasshopperButton);

            const cockroach = document.createElement("div");
            cockroach.textContent = "Игр осталось: 0";
            cockroach.classList.add("game-counter", "floating-button");
            document.body.appendChild(cockroach);



            GM_addStyle(`
            input[type=checkbox].my-checkbox {
            	-webkit-appearance: none;
            	-moz-appearance: none;
            	appearance: none;
            	border: 6px inset rgba(255, 0, 0, 0.8);
            	border-radius: 50%;
            	width: 42px;
            	height: 42px;
            	outline: none;
            	transition: .15s ease-in-out;
            	vertical-align: middle;
            	position: absolute;
            	left: 0px;
            	top: 50%;
            	transform: translateY(-50%);
            	background-color: rgba(0, 0, 0, 0.0);
            	box-shadow: inset 0 0 0 0 rgba(255, 255, 255, 0.5);
            	cursor: pointer;
            	z-index: 9999;
            }

            input[type=checkbox].my-checkbox:checked {
            	background-color: rgba(0, 0, 0, 0.5);
            	border-color: #b71c1c;
            	box-shadow: inset 0 0 0 12px rgba(255, 0, 0, 0.5);
            }

            input[type=checkbox].my-checkbox:after {
            	content: "";
            	display: block;
            	position: absolute;
            	left: 50%;
            	top: 50%;
            	transform: translate(-50%, -50%) scale(0);
            	width: 25px;
            	height: 25px;
            	border-radius: 50%;
            	background-color: rgba(0, 0, 0, 0.9);
            	opacity: 0.9;
            	box-shadow: 0 0 0 0 #b71c1c;
            	transition: transform .15s ease-in-out, box-shadow .15s ease-in-out;
            }

            input[type=checkbox].my-checkbox:checked:after {
            	transform: translate(-50%, -50%) scale(1);
            	box-shadow: 0 0 0 4px #b71c1c;
            }

            .my-button {
            	margin-right: 10px;
            	padding: 10px 20px;
            	border: none;
            	border-radius: 50px;
            	font-size: 16px;
            	font-weight: 700;
            	color: #fff;
            	background: linear-gradient(to right, #16202D, #1B2838);
            	box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
            	cursor: pointer;
            	font-family: "Roboto", sans-serif;
            	margin-top: 245px;
            }

            .my-button:hover {
            	background: linear-gradient(to right, #0072ff, #00c6ff);
            	box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.3);
            }

            .floating-button {
            	position: fixed;
            	top: -189px;
            	left: 240px;
            	z-index: 1000;
            }

            .game-counter {
            	margin-right: 10px;
            	padding: 10px 20px;
            	border: none;
            	border-radius: 50px;
            	font-size: 16px;
            	font-weight: 700;
            	color: #fff;
            	background: linear-gradient(to right, #16202D, #1B2838);
            	box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.2);
            	font-family: "Roboto", sans-serif;
            	margin-top: 195px;
            }
    `);

            const butterflyObserver = new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    if (mutation.type === "childList" && mutation.addedNodes.length) {
                        addBeetles();
                        removeIgnoredDragonflies();
                        updateAntCounter();
                    }
                });
            });

            butterflyObserver.observe(document.body, {
                childList: true,
                subtree: true
            });

            addBeetles();
            removeIgnoredDragonflies();
            updateAntCounter();
        })();
    }

    // Скрипт для скрытия новостей в новостном центре: | https://store.steampowered.com/news/
    if (scriptsConfig.newsFilter && unsafeWindow.location.pathname.includes('/news')) {
        (function() {
            'use strict';

            function runNewsMigration() {
                const OLD_STORAGE_KEY = 'hiddenNews';
                const NEW_STORAGE_KEY = 'use_hiddenNewsData_v4';

                const oldDataRaw = localStorage.getItem(OLD_STORAGE_KEY);

                if (!oldDataRaw) {
                    return;
                }

                try {
                    const oldData = JSON.parse(oldDataRaw);
                    if (!Array.isArray(oldData) || oldData.length === 0) {
                        localStorage.removeItem(OLD_STORAGE_KEY);
                        return;
                    }

                    const newData = GM_getValue(NEW_STORAGE_KEY, []);
                    const existingNewIds = new Set(newData.map(item => item.id));
                    const itemsToMigrate = [];

                    for (const oldItem of oldData) {
                        if (!oldItem.link || !oldItem.title) continue;

                        const match = oldItem.link.match(/\/app\/(\d+)\/view\/(\d+)/);
                        if (match && match[1] && match[2]) {
                            const appID = match[1];
                            const newsID = match[2];

                            if (!existingNewIds.has(newsID)) {
                                const newItem = {
                                    id: newsID,
                                    appID: appID,
                                    gameName: "[N/A; 1.9.5]",
                                    newsTitle: oldItem.title,
                                    dateHidden: new Date(oldItem.date).getTime() || Date.now()
                                };
                                itemsToMigrate.push(newItem);
                                existingNewIds.add(newsID);
                            }
                        }
                    }

                    if (itemsToMigrate.length > 0) {
                        const finalData = [...newData, ...itemsToMigrate];
                        GM_setValue(NEW_STORAGE_KEY, finalData);
                    }

                    localStorage.removeItem(OLD_STORAGE_KEY);

                } catch (e) {
                    localStorage.removeItem(OLD_STORAGE_KEY);
                }
            }
            runNewsMigration();

            const HIDDEN_NEWS_GM_KEY = 'use_hiddenNewsData_v4';
            const NEWS_ITEM_SELECTOR = '._398u23KF15gxmeH741ZSyL';
            const NEWS_APP_AREA_SELECTOR = '._3-0KOhYVQX2zIP3z-jCAdu';
            const NEWS_APP_NAME_SELECTOR = '._71phFKOzg8aQlBU1rCA2T';
            const NEWS_LINK_SELECTOR = 'a.Focusable[href^="/news/app/"]';
            const NEWS_TITLE_SELECTOR = '._1M8-Pa3b3WboayCgd5VBJT';
            const NEWS_IMAGE_CONTAINER_SELECTOR = '._3HF9tOy_soo1B_odf1XArk';
            const NEWS_IMAGE_CONTAINER_FALLBACK_SELECTOR = '._2A8sQ35o5MKE0P2B9C0bAn';
            let lastHiddenItems = [];

            GM_addStyle(`
                .use-newsfilter-checkbox-area {
                	position: absolute;
                	top: 0;
                	right: 0;
                	width: 90px;
                	height: 100%;
                	display: flex;
                	align-items: center;
                	justify-content: center;
                	cursor: pointer;
                	z-index: 10;
                	-webkit-tap-highlight-color: transparent;
                }

                .use-newsfilter-checkbox {
                	appearance: none;
                	-webkit-appearance: none;
                	width: 46px;
                	height: 46px;
                	border: 3px solid rgba(102, 192, 244, 0.6);
                	border-radius: 5px;
                	background-color: rgba(27, 40, 56, 0.5);
                	cursor: pointer;
                	transition: all 0.2s ease-in-out;
                	opacity: 0.5;
                	pointer-events: none;
                	display: flex;
                	align-items: center;
                	justify-content: center;
                }

                .use-newsfilter-checkbox-area:hover .use-newsfilter-checkbox {
                	opacity: 1;
                	border-color: #ade0ff;
                	background-color: rgba(27, 40, 56, 0.75);
                }

                .use-newsfilter-checkbox:checked {
                	background-color: rgba(102, 192, 244, 1);
                	border-color: #e1e8ed;
                	opacity: 1;
                }

                .use-newsfilter-checkbox:checked::before {
                	content: '✔';
                	color: #0a121c;
                	font-size: 30px;
                	font-weight: bold;
                }

                .use-newsfilter-newsitem-selected {
                	opacity: 0.45;
                	transition: opacity 0.25s ease-in-out;
                }

                .use-newsfilter-newsitem-selected:hover {
                	opacity: 0.75;
                }

                .use-newsfilter-newsitem-persistently-hidden {
                	opacity: 0.25 !important;
                	border: 1px dashed #4a5562;
                	transition: opacity 0.3s, border 0.3s;
                }

                .use-newsfilter-controls-container {
                	position: fixed;
                	top: 20px;
                	right: 15px;
                	background: rgba(20, 23, 28, 0.92);
                	backdrop-filter: blur(4px);
                	-webkit-backdrop-filter: blur(4px);
                	padding: 8px;
                	border-radius: 4px;
                	z-index: 10001;
                	display: flex;
                	flex-direction: column;
                	gap: 6px;
                	width: 200px;
                }

                .use-newsfilter-button {
                	padding: 7px 12px;
                	background-color: #58a6ff;
                	color: #0d1117;
                	border: none;
                	border-radius: 3px;
                	cursor: pointer;
                	font-size: 13px;
                	font-weight: 500;
                	transition: background-color 0.2s, transform 0.1s;
                	width: 100%;
                	text-align: center;
                	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
                }

                .use-newsfilter-button:hover:not(:disabled) {
                	background-color: #79bbff;
                	transform: translateY(-1px);
                }

                .use-newsfilter-button:active:not(:disabled) {
                	transform: translateY(0px);
                	background-color: #4a90e2;
                }

                .use-newsfilter-button:disabled {
                	background-color: #30363d;
                	color: #6a737d;
                	cursor: not-allowed;
                	box-shadow: none;
                }

                .use-newsfilter-storage-count {
                	color: #99a1a8;
                	font-size: 11px;
                	margin-top: 2px;
                	text-align: center;
                }

                #use-newsfilter-confirm-hide-button:not(:disabled) {
                	background-color: #d9534f;
                	color: white;
                }

                #use-newsfilter-confirm-hide-button:not(:disabled):hover {
                	background-color: #c9302c;
                }

                #use-newsfilter-confirm-hide-button:not(:disabled):active {
                	background-color: #ac2925;
                }

                #use-newsfilter-undo-button {
                	background-color: #f0ad4e;
                	color: #0d1117;
                }

                #use-newsfilter-undo-button:hover:not(:disabled) {
                	background-color: #ec971f;
                }

                #use-newsfilter-manage-panel {
                	position: fixed;
                	top: 50%;
                	left: 50%;
                	transform: translate(-50%, -50%);
                	width: 90%;
                	max-width: 650px;
                	max-height: 75vh;
                	background-color: #171a21;
                	border: 1px solid #4a5562;
                	border-radius: 4px;
                	box-shadow: 0 4px 20px rgba(0, 0, 0, 0.6);
                	z-index: 10002;
                	padding: 15px;
                	display: none;
                	flex-direction: column;
                	color: #c6d4df;
                }

                #use-newsfilter-manage-panel h3 {
                	margin-top: 0;
                	margin-bottom: 10px;
                	color: #67c1f5;
                	text-align: center;
                	font-size: 16px;
                }

                #use-newsfilter-hidden-list {
                	list-style: none;
                	padding: 0;
                	margin: 10px 0;
                	overflow-y: auto;
                	flex-grow: 1;
                	background: rgba(0, 0, 0, 0.15);
                	border-radius: 3px;
                }

                #use-newsfilter-hidden-list li {
                	padding: 7px 10px;
                	border-bottom: 1px solid #232830;
                	display: flex;
                	justify-content: space-between;
                	align-items: center;
                	font-size: 12px;
                }

                #use-newsfilter-hidden-list li:last-child {
                	border-bottom: none;
                }

                #use-newsfilter-hidden-list li .hidden-item-text {
                	flex-grow: 1;
                	margin-right: 10px;
                	overflow: hidden;
                	text-overflow: ellipsis;
                	white-space: nowrap;
                }

                #use-newsfilter-hidden-list li .hidden-item-text .game-name {
                	color: #67c1f5;
                	font-weight: bold;
                }

                #use-newsfilter-hidden-list li .hidden-item-text .news-title {
                	color: #b0b8c0;
                	display: block;
                	font-size: 0.9em;
                	overflow: hidden;
                	text-overflow: ellipsis;
                	white-space: nowrap;
                }

                #use-newsfilter-hidden-list li .hidden-item-text .app-id {
                	color: #76808c;
                	font-size: 0.85em;
                	display: block;
                }

                .use-newsfilter-restore-btn {
                	background-color: #55c655;
                	color: #0d1117;
                	border: none;
                	padding: 3px 7px;
                	font-size: 10px;
                	border-radius: 3px;
                	cursor: pointer;
                	font-weight: 500;
                	flex-shrink: 0;
                }

                .use-newsfilter-restore-btn:hover {
                	background-color: #4CAF50;
                }

                .use-newsfilter-manage-buttons {
                	display: flex;
                	justify-content: space-between;
                	margin-top: 10px;
                	gap: 10px;
                }

                .use-newsfilter-manage-buttons .use-newsfilter-button {
                	font-size: 13px;
                	padding: 7px 12px;
                }

                @keyframes use-newsfilter-fadeout {
                	from {
                		opacity: 1;
                		transform: translateY(0);
                	}

                	to {
                		opacity: 0;
                		transform: translateY(-20px);
                	}
                }

                .use-newsfilter-fading-out {
                	animation: use-newsfilter-fadeout 0.35s forwards ease-out;
                	overflow: hidden;
                }
            `);

            let persistentlyHiddenItems = GM_getValue(HIDDEN_NEWS_GM_KEY, []);
            let showPersistentlyHidden = false;

            function getNewsIdsFromLink(newsItem) {
                const linkElement = newsItem.querySelector(NEWS_LINK_SELECTOR);
                if (linkElement) {
                    const href = linkElement.getAttribute('href');
                    const match = href.match(/\/news\/app\/(\d+)\/view\/(\d+)/);
                    if (match && match[1] && match[2]) {
                        return {
                            appID: match[1],
                            newsID: match[2]
                        };
                    }
                }
                return {
                    appID: null,
                    newsID: null
                };
            }

            function getNewsItemDetails(newsItem) {
                const {
                    appID,
                    newsID
                } = getNewsIdsFromLink(newsItem);
                let gameName = null;
                let newsTitle = newsItem.querySelector(NEWS_TITLE_SELECTOR) ?.textContent.trim() || 'Без заголовка';
                const appArea = newsItem.querySelector(NEWS_APP_AREA_SELECTOR);
                if (appArea) {
                    gameName = appArea.querySelector(NEWS_APP_NAME_SELECTOR) ?.textContent.trim() || null;
                }
                return {
                    appID,
                    newsID,
                    gameName,
                    newsTitle
                };
            }

            function addNewsCheckboxes(newsItems) {
                newsItems.forEach(item => {
                    const {
                        newsID
                    } = getNewsItemDetails(item);
                    const hasExistingCheckboxArea = item.querySelector('.use-newsfilter-checkbox-area');
                    if (newsID && !hasExistingCheckboxArea) {
                        const checkboxArea = document.createElement('div');
                        checkboxArea.className = 'use-newsfilter-checkbox-area';
                        checkboxArea.title = 'Отметить для скрытия';
                        const checkbox = document.createElement('input');
                        checkbox.type = 'checkbox';
                        checkbox.className = 'use-newsfilter-checkbox';
                        checkbox.dataset.newsId = newsID;
                        checkboxArea.appendChild(checkbox);
                        checkboxArea.addEventListener('click', (event) => {
                            event.preventDefault();
                            event.stopPropagation();
                            checkbox.checked = !checkbox.checked;
                            toggleTemporaryHide(item, checkbox.checked);
                        });
                        const imageContainer = item.querySelector(NEWS_IMAGE_CONTAINER_SELECTOR) || item.querySelector(NEWS_IMAGE_CONTAINER_FALLBACK_SELECTOR) || item;
                        if (imageContainer) {
                            if (getComputedStyle(imageContainer).position === 'static') {
                                imageContainer.style.position = 'relative';
                            }
                            imageContainer.appendChild(checkboxArea);
                        }
                        if (persistentlyHiddenItems.some(hidden => hidden.id === newsID)) {
                            applyPersistentHideStyle(item, newsID);
                            checkboxArea.style.display = 'none';
                        }
                    } else if (newsID && hasExistingCheckboxArea) {
                        if (persistentlyHiddenItems.some(hidden => hidden.id === newsID)) {
                            applyPersistentHideStyle(item, newsID);
                            hasExistingCheckboxArea.style.display = 'none';
                        } else {
                            hasExistingCheckboxArea.style.display = 'flex';
                            applyPersistentHideStyle(item, newsID);
                        }
                    }
                });
            }

            function toggleTemporaryHide(newsItem, shouldHide) {
                if (shouldHide) {
                    newsItem.classList.add('use-newsfilter-newsitem-selected');
                } else {
                    newsItem.classList.remove('use-newsfilter-newsitem-selected');
                }
                updateSelectedCount();
            }

            function updateSelectedCount() {
                const selectedItems = document.querySelectorAll(`${NEWS_ITEM_SELECTOR}.use-newsfilter-newsitem-selected`);
                const confirmButton = document.getElementById('use-newsfilter-confirm-hide-button');
                if (confirmButton) {
                    confirmButton.disabled = selectedItems.length === 0;
                    confirmButton.textContent = `Скрыть выбранные (${selectedItems.length})`;
                }
            }

            function updatePersistentHiddenCountDisplay() {
                const countElement = document.getElementById('use-newsfilter-storage-count-span');
                if (countElement) {
                    countElement.textContent = persistentlyHiddenItems.length;
                }
            }

            function createControls() {
                if (document.getElementById('use-newsfilter-controls-container')) return;
                const controlsContainer = document.createElement('div');
                controlsContainer.id = 'use-newsfilter-controls-container';
                controlsContainer.className = 'use-newsfilter-controls-container';
                const confirmHideButton = document.createElement('button');
                confirmHideButton.id = 'use-newsfilter-confirm-hide-button';
                confirmHideButton.className = 'use-newsfilter-button';
                confirmHideButton.textContent = 'Скрыть выбранные (0)';
                confirmHideButton.disabled = true;
                confirmHideButton.title = 'Переместить выбранные новости в список постоянно скрытых';
                confirmHideButton.onclick = confirmAndHideSelectedNews;
                const storageCountDisplay = document.createElement('div');
                storageCountDisplay.className = 'use-newsfilter-storage-count';
                storageCountDisplay.innerHTML = `В хранилище: <span id="use-newsfilter-storage-count-span">${persistentlyHiddenItems.length}</span>`;
                controlsContainer.appendChild(storageCountDisplay);
                const undoButton = document.createElement('button');
                undoButton.id = 'use-newsfilter-undo-button';
                undoButton.className = 'use-newsfilter-button';
                undoButton.textContent = 'Отменить';
                undoButton.style.display = 'none';
                undoButton.title = 'Отменить последнее подтвержденное скрытие';
                undoButton.onclick = undoLastPersistentHide;
                controlsContainer.appendChild(undoButton);
                const togglePersistentlyHiddenButton = document.createElement('button');
                togglePersistentlyHiddenButton.id = 'use-newsfilter-toggle-persistent-button';
                togglePersistentlyHiddenButton.className = 'use-newsfilter-button';
                togglePersistentlyHiddenButton.textContent = showPersistentlyHidden ? 'Спрятать скрытое' : 'Показать скрытое';
                togglePersistentlyHiddenButton.title = 'Показать/скрыть новости из списка постоянно скрытых';
                togglePersistentlyHiddenButton.onclick = toggleShowPersistentlyHidden;
                controlsContainer.appendChild(togglePersistentlyHiddenButton);
                const manageHiddenButton = document.createElement('button');
                manageHiddenButton.id = 'use-newsfilter-manage-button';
                manageHiddenButton.className = 'use-newsfilter-button';
                manageHiddenButton.textContent = 'Хранилище';
                manageHiddenButton.title = 'Просмотреть и восстановить скрытые новости';
                manageHiddenButton.onclick = showManageHiddenPanel;
                controlsContainer.appendChild(manageHiddenButton);
                controlsContainer.appendChild(confirmHideButton);
                document.body.appendChild(controlsContainer);
                createManageHiddenPanel();
            }

            function confirmAndHideSelectedNews() {
                const selectedItems = document.querySelectorAll(`${NEWS_ITEM_SELECTOR}.use-newsfilter-newsitem-selected`);
                if (selectedItems.length === 0) return;
                lastHiddenItems = [];
                const itemsToHideDetails = [];
                selectedItems.forEach(item => {
                    const {
                        appID,
                        newsID,
                        gameName,
                        newsTitle
                    } = getNewsItemDetails(item);
                    if (newsID && !persistentlyHiddenItems.some(h => h.id === newsID)) {
                        const newItemData = {
                            id: newsID,
                            appID: appID,
                            gameName: gameName || "Неизвестная игра",
                            newsTitle: newsTitle,
                            dateHidden: Date.now()
                        };
                        itemsToHideDetails.push(newItemData);
                    }
                    item.classList.add('use-newsfilter-fading-out');
                    item.classList.remove('use-newsfilter-newsitem-selected');
                    const checkboxArea = item.querySelector('.use-newsfilter-checkbox-area');
                    if (checkboxArea) checkboxArea.style.display = 'none';
                    setTimeout(() => {
                        applyPersistentHideStyle(item, newsID);
                        item.classList.remove('use-newsfilter-fading-out');
                    }, 350);
                });
                if (itemsToHideDetails.length > 0) {
                    const newPersistentItems = itemsToHideDetails.filter(newItem =>
                        !persistentlyHiddenItems.some(existingItem => existingItem.id === newItem.id)
                    );
                    persistentlyHiddenItems.push(...newPersistentItems);
                    lastHiddenItems = newPersistentItems;
                    GM_setValue(HIDDEN_NEWS_GM_KEY, persistentlyHiddenItems);
                    updatePersistentHiddenCountDisplay();
                }
                updateSelectedCount();
                const undoButton = document.getElementById('use-newsfilter-undo-button');
                if (undoButton && lastHiddenItems.length > 0) {
                    undoButton.style.display = 'block';
                    setTimeout(() => {
                        undoButton.style.display = 'none';
                    }, 6000);
                }
            }

            function undoLastPersistentHide() {
                if (lastHiddenItems.length === 0) return;
                const idsToRestore = lastHiddenItems.map(item => item.id);
                persistentlyHiddenItems = persistentlyHiddenItems.filter(item => !idsToRestore.includes(item.id));
                GM_setValue(HIDDEN_NEWS_GM_KEY, persistentlyHiddenItems);
                updatePersistentHiddenCountDisplay();
                document.querySelectorAll(NEWS_ITEM_SELECTOR).forEach(itemOnPage => {
                    const {
                        newsID
                    } = getNewsIdsFromLink(itemOnPage);
                    if (newsID && idsToRestore.includes(newsID)) {
                        itemOnPage.style.display = '';
                        itemOnPage.classList.remove('use-newsfilter-newsitem-persistently-hidden', 'use-newsfilter-fading-out');
                        const checkboxArea = itemOnPage.querySelector('.use-newsfilter-checkbox-area');
                        if (checkboxArea) checkboxArea.style.display = 'flex';
                        const checkbox = itemOnPage.querySelector('.use-newsfilter-checkbox');
                        if (checkbox) checkbox.checked = false;
                        toggleTemporaryHide(itemOnPage, false);
                    }
                });
                lastHiddenItems = [];
                document.getElementById('use-newsfilter-undo-button').style.display = 'none';
                if (isManagePanelOpen()) populateHiddenList();
                updateSelectedCount();
            }

            function applyPersistentHideStyle(newsItem, newsID) {
                const isHidden = persistentlyHiddenItems.some(h => h.id === newsID);
                if (isHidden) {
                    newsItem.classList.add('use-newsfilter-newsitem-persistently-hidden');
                    if (!showPersistentlyHidden) {
                        newsItem.style.display = 'none';
                    } else {
                        newsItem.style.display = '';
                    }
                } else {
                    newsItem.classList.remove('use-newsfilter-newsitem-persistently-hidden');
                    newsItem.style.display = '';
                }
            }

            function toggleShowPersistentlyHidden() {
                showPersistentlyHidden = !showPersistentlyHidden;
                const button = document.getElementById('use-newsfilter-toggle-persistent-button');
                if (button) {
                    button.textContent = showPersistentlyHidden ? 'Спрятать скрытое' : 'Показать скрытое';
                }
                document.querySelectorAll(NEWS_ITEM_SELECTOR).forEach(item => {
                    const {
                        newsID
                    } = getNewsIdsFromLink(item);
                    if (newsID) {
                        applyPersistentHideStyle(item, newsID);
                        const checkboxArea = item.querySelector('.use-newsfilter-checkbox-area');
                        if (checkboxArea) {
                            if (persistentlyHiddenItems.some(h => h.id === newsID)) {
                                checkboxArea.style.display = 'none';
                            } else {
                                checkboxArea.style.display = 'flex';
                            }
                        }
                    }
                });
            }

            function applyInitialHide() {
                persistentlyHiddenItems = GM_getValue(HIDDEN_NEWS_GM_KEY, []);
                updatePersistentHiddenCountDisplay();
                const newsItems = document.querySelectorAll(NEWS_ITEM_SELECTOR);
                newsItems.forEach(item => {
                    const {
                        newsID
                    } = getNewsIdsFromLink(item);
                    if (newsID) {
                        applyPersistentHideStyle(item, newsID);
                        const checkboxArea = item.querySelector('.use-newsfilter-checkbox-area');
                        if (checkboxArea) {
                            if (persistentlyHiddenItems.some(h => h.id === newsID)) {
                                checkboxArea.style.display = 'none';
                            } else {
                                checkboxArea.style.display = 'flex';
                            }
                        }
                    }
                });
            }

            function createManageHiddenPanel() {
                if (document.getElementById('use-newsfilter-manage-panel')) return;
                const panel = document.createElement('div');
                panel.id = 'use-newsfilter-manage-panel';
                panel.innerHTML = `
                    <h3>Хранилище скрытых новостей</h3>
                    <p style="font-size:11px; color: #808b96; text-align:center; margin-bottom: 10px;">Новости, ID которых есть в этом списке, не будут отображаться (если не включен режим "Показать скрытое").</p>
                    <ul id="use-newsfilter-hidden-list"></ul>
                    <div class="use-newsfilter-manage-buttons">
                        <button id="use-newsfilter-clear-all-hidden-btn" class="use-newsfilter-button" style="background-color: #c9302c; color: #DCEBF7;">Очистить хранилище</button>
                        <button id="use-newsfilter-close-manage-panel-btn" class="use-newsfilter-button" style="background-color: #4a5562;">Закрыть</button>
                    </div>
                `;
                document.body.appendChild(panel);
                document.getElementById('use-newsfilter-clear-all-hidden-btn').onclick = () => {
                    if (confirm('Вы уверены, что хотите очистить хранилище скрытых новостей? Это действие нельзя будет отменить.')) {
                        clearAllPersistentHiddenNews();
                    }
                };
                document.getElementById('use-newsfilter-close-manage-panel-btn').onclick = hideManageHiddenPanel;
            }

            function showManageHiddenPanel() {
                const panel = document.getElementById('use-newsfilter-manage-panel');
                if (panel) {
                    populateHiddenList();
                    panel.style.display = 'flex';
                }
            }

            function hideManageHiddenPanel() {
                const panel = document.getElementById('use-newsfilter-manage-panel');
                if (panel) {
                    panel.style.display = 'none';
                }
            }

            function isManagePanelOpen() {
                const panel = document.getElementById('use-newsfilter-manage-panel');
                return panel && panel.style.display === 'flex';
            }

            function populateHiddenList() {
                const listElement = document.getElementById('use-newsfilter-hidden-list');
                if (!listElement) return;
                listElement.innerHTML = '';
                if (persistentlyHiddenItems.length === 0) {
                    listElement.innerHTML = '<li style="text-align:center; color:#808b96; padding: 10px;">Хранилище пусто.</li>';
                    return;
                }
                const sortedItems = [...persistentlyHiddenItems].sort((a, b) =>(b.dateHidden || 0) - (a.dateHidden || 0));
                sortedItems.forEach(itemData => {
                    const listItem = document.createElement('li');
                    const textContainer = document.createElement('div');
                    textContainer.className = 'hidden-item-text';
                    const gameNameSpan = document.createElement('span');
                    gameNameSpan.className = 'game-name';
                    gameNameSpan.textContent = itemData.gameName ? `${itemData.gameName}` : 'Игра не указана';
                    const newsTitleSpan = document.createElement('span');
                    newsTitleSpan.className = 'news-title';
                    newsTitleSpan.textContent = itemData.newsTitle || `(Новость без заголовка)`;
                    newsTitleSpan.title = itemData.newsTitle || `Новость для AppID: ${itemData.appID}`;
                    const appIdSpan = document.createElement('span');
                    appIdSpan.className = 'app-id';
                    appIdSpan.textContent = `NewsID: ${itemData.id} (AppID: ${itemData.appID})`;
                    textContainer.appendChild(gameNameSpan);
                    textContainer.appendChild(newsTitleSpan);
                    textContainer.appendChild(appIdSpan);
                    listItem.appendChild(textContainer);
                    const restoreButton = document.createElement('button');
                    restoreButton.className = 'use-newsfilter-restore-btn';
                    restoreButton.textContent = 'Вернуть';
                    restoreButton.title = `Восстановить "${itemData.newsTitle || itemData.id}"`;
                    restoreButton.onclick = () => restoreNewsItem(itemData.id);
                    listItem.appendChild(restoreButton);
                    listElement.appendChild(listItem);
                });
            }

            function restoreNewsItem(newsIDToRestore) {
                persistentlyHiddenItems = persistentlyHiddenItems.filter(item => item.id !== newsIDToRestore);
                GM_setValue(HIDDEN_NEWS_GM_KEY, persistentlyHiddenItems);
                updatePersistentHiddenCountDisplay();
                document.querySelectorAll(NEWS_ITEM_SELECTOR).forEach(itemOnPage => {
                    const {
                        newsID
                    } = getNewsIdsFromLink(itemOnPage);
                    if (newsID === newsIDToRestore) {
                        itemOnPage.style.display = '';
                        itemOnPage.classList.remove('use-newsfilter-newsitem-persistently-hidden');
                        const checkboxArea = itemOnPage.querySelector('.use-newsfilter-checkbox-area');
                        if (checkboxArea) checkboxArea.style.display = 'flex';
                        const checkbox = itemOnPage.querySelector('.use-newsfilter-checkbox');
                        if (checkbox) checkbox.checked = false;
                        toggleTemporaryHide(itemOnPage, false);
                    }
                });
                populateHiddenList();
                updateSelectedCount();
            }

            function clearAllPersistentHiddenNews() {
                persistentlyHiddenItems = [];
                GM_setValue(HIDDEN_NEWS_GM_KEY, []);
                updatePersistentHiddenCountDisplay();
                document.querySelectorAll(NEWS_ITEM_SELECTOR).forEach(item => {
                    item.style.display = '';
                    item.classList.remove('use-newsfilter-newsitem-persistently-hidden', 'use-newsfilter-fading-out');
                    const checkboxArea = item.querySelector('.use-newsfilter-checkbox-area');
                    if (checkboxArea) checkboxArea.style.display = 'flex';
                    const checkbox = item.querySelector('.use-newsfilter-checkbox');
                    if (checkbox) checkbox.checked = false;
                    toggleTemporaryHide(item, false);
                });
                populateHiddenList();
                updateSelectedCount();
            }

            function initNewsFilterEnhanced() {
                applyInitialHide();
                addNewsCheckboxes(document.querySelectorAll(NEWS_ITEM_SELECTOR));
                createControls();
                updateSelectedCount();
            }

            setTimeout(initNewsFilterEnhanced, 1500);

            const newsObserver = new MutationObserver((mutations) => {
                let processNewsItems = false;
                for (const mutation of mutations) {
                    if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                        for (const node of mutation.addedNodes) {
                            if (node.nodeType === Node.ELEMENT_NODE) {
                                processNewsItems = true;
                                break;
                            }
                        }
                    }
                    if (processNewsItems) {
                        break;
                    }
                }
                if (processNewsItems) {
                    setTimeout(() => {
                        const allNewsItems = document.querySelectorAll(NEWS_ITEM_SELECTOR);
                        addNewsCheckboxes(allNewsItems);
                        applyInitialHide();
                    }, 100);
                }
            });

            const newsFeedParentContainer = document.querySelector('div[class*="eventcalendar_EventBlockContainer"]');
            if (newsFeedParentContainer) {
                newsObserver.observe(newsFeedParentContainer, {
                    childList: true,
                    subtree: true
                });
            } else {
                const observeBody = () => newsObserver.observe(document.body, {
                    childList: true,
                    subtree: true
                });
                if (document.readyState === "complete" || document.readyState === "interactive") {
                    observeBody();
                } else {
                    window.addEventListener('DOMContentLoaded', observeBody);
                }
            }
        })();
    }

    // Скрипт для показа годовых и исторических продаж предмета на торговой площадке Steam | https://steamcommunity.com/market/listings/*
    if (scriptsConfig.Kaznachei && unsafeWindow.location.pathname.includes('/market/listings/')) {
        async function fetchSalesInfo() {
            const urlParts = unsafeWindow.location.pathname.split('/');
            const appId = urlParts[3];
            const marketHashName = decodeURIComponent(urlParts[4]);
            const apiUrl = `https://steamcommunity.com/market/pricehistory/?appid=${appId}&market_hash_name=${marketHashName}`;

            try {
                const response = await fetch(apiUrl);
                const data = await response.json();

                if (data.success) {
                    const salesData = data.prices;
                    const yearlySales = {};
                    let totalSales = 0;

                    salesData.forEach(sale => {
                        const date = sale[0];
                        const price = parseFloat(sale[1]);
                        const quantity = parseInt(sale[2]);
                        const year = date.split(' ')[2];

                        const totalForDay = price * quantity;

                        if (!yearlySales[year]) {
                            yearlySales[year] = {
                                total: 0,
                                commission: 0,
                                developerShare: 0,
                                valveShare: 0
                            };
                        }

                        yearlySales[year].total += totalForDay;
                        totalSales += totalForDay;
                    });

                    for (const year in yearlySales) {
                        const commission = yearlySales[year].total * 0.13;
                        const developerShare = commission * 0.6667;
                        const valveShare = commission * 0.3333;

                        yearlySales[year].commission = commission;
                        yearlySales[year].developerShare = developerShare;
                        yearlySales[year].valveShare = valveShare;
                    }

                    displaySalesInfo(yearlySales, totalSales);
                } else {
                    console.error('Не удалось получить информацию о продажах.');
                }
            } catch (error) {
                console.error('Ошибка при получении данных:', error);
            }
        }

        function displaySalesInfo(yearlySales, totalSales) {
            const salesInfoContainer = document.createElement('div');
            salesInfoContainer.style.marginTop = '20px';
            salesInfoContainer.style.padding = '10px';
            salesInfoContainer.style.border = '1px solid #4a4a4a';
            salesInfoContainer.style.backgroundColor = '#1b2838';
            salesInfoContainer.style.borderRadius = '4px';
            salesInfoContainer.style.boxShadow = '0 1px 3px rgba(0, 0, 0, 0.5)';
            salesInfoContainer.style.color = '#c7d5e0';

            const spoilerHeader = document.createElement('div');
            spoilerHeader.style.cursor = 'pointer';
            spoilerHeader.style.padding = '10px';
            spoilerHeader.style.backgroundColor = '#171a21';
            spoilerHeader.style.borderRadius = '4px 4px 0 0';
            spoilerHeader.style.color = '#c7d5e0';
            spoilerHeader.style.fontWeight = 'bold';
            spoilerHeader.style.fontFamily = '"Motiva Sans", sans-serif';
            spoilerHeader.style.fontSize = '16px';
            spoilerHeader.style.display = 'flex';
            spoilerHeader.style.alignItems = 'center';
            spoilerHeader.style.justifyContent = 'space-between';
            spoilerHeader.innerHTML = 'Информация о продажах <span style="font-size: 12px; transform: rotate(0deg); transition: transform 0.3s ease;">&#9660;</span>';

            spoilerHeader.addEventListener('click', () => {
                const content = spoilerHeader.nextElementSibling;
                content.style.display = content.style.display === 'none' ? 'block' : 'none';
                const arrow = spoilerHeader.querySelector('span');
                arrow.style.transform = content.style.display === 'none' ? 'rotate(0deg)' : 'rotate(180deg)';
            });

            const spoilerContent = document.createElement('div');
            spoilerContent.style.display = 'none';
            spoilerContent.style.padding = '10px';
            spoilerContent.style.borderTop = '1px solid #4a4a4a';

            const yearlySalesTable = document.createElement('table');
            yearlySalesTable.style.width = '100%';
            yearlySalesTable.style.borderCollapse = 'collapse';
            yearlySalesTable.style.marginBottom = '20px';
            yearlySalesTable.style.fontFamily = '"Motiva Sans", sans-serif';
            yearlySalesTable.style.fontSize = '14px';

            const yearlySalesHeader = document.createElement('tr');
            yearlySalesHeader.innerHTML = '<th style="padding: 8px; text-align: left; border-bottom: 2px solid #4a4a4a; background-color: #171a21; color: #c7d5e0;">Год</th><th style="padding: 8px; text-align: left; border-bottom: 2px solid #4a4a4a; background-color: #171a21; color: #c7d5e0;">Сумма продаж за год</th><th style="padding: 8px; text-align: left; border-bottom: 2px solid #4a4a4a; background-color: #171a21; color: #c7d5e0;">Ушло разработчику</th><th style="padding: 8px; text-align: left; border-bottom: 2px solid #4a4a4a; background-color: #171a21; color: #c7d5e0;">Ушло Valve</th>';
            yearlySalesTable.appendChild(yearlySalesHeader);

            for (const year in yearlySales) {
                const row = document.createElement('tr');
                row.innerHTML = `<td style="padding: 8px; border-bottom: 1px solid #4a4a4a; background-color: #1b2838; color: #c7d5e0;">${year}</td><td style="padding: 8px; border-bottom: 1px solid #4a4a4a; background-color: #1b2838; color: #c7d5e0;">${yearlySales[year].total.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} руб.</td><td style="padding: 8px; border-bottom: 1px solid #4a4a4a; background-color: #1b2838; color: #c7d5e0;">${yearlySales[year].developerShare.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} руб.</td><td style="padding: 8px; border-bottom: 1px solid #4a4a4a; background-color: #1b2838; color: #c7d5e0;">${yearlySales[year].valveShare.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} руб.</td>`;
                yearlySalesTable.appendChild(row);
            }

            const totalSalesParagraph = document.createElement('p');
            totalSalesParagraph.textContent = `Сумма продаж за всё время: ${totalSales.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} руб.`;
            totalSalesParagraph.style.fontWeight = 'bold';
            totalSalesParagraph.style.fontSize = '16px';
            totalSalesParagraph.style.color = '#c7d5e0';
            totalSalesParagraph.style.fontFamily = '"Motiva Sans", sans-serif';

            const commission = totalSales * 0.13;
            const developerShare = commission * 0.6667;
            const valveShare = commission * 0.3333;

            const developerShareParagraph = document.createElement('p');
            developerShareParagraph.textContent = `Ушло разработчику: ${developerShare.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} руб.`;
            developerShareParagraph.style.fontSize = '14px';
            developerShareParagraph.style.color = '#c7d5e0';
            developerShareParagraph.style.fontFamily = '"Motiva Sans", sans-serif';

            const valveShareParagraph = document.createElement('p');
            valveShareParagraph.textContent = `Ушло Valve: ${valveShare.toLocaleString('ru-RU', { minimumFractionDigits: 2, maximumFractionDigits: 2 })} руб.`;
            valveShareParagraph.style.fontSize = '14px';
            valveShareParagraph.style.color = '#c7d5e0';
            valveShareParagraph.style.fontFamily = '"Motiva Sans", sans-serif';

            spoilerContent.appendChild(yearlySalesTable);
            spoilerContent.appendChild(totalSalesParagraph);
            spoilerContent.appendChild(developerShareParagraph);
            spoilerContent.appendChild(valveShareParagraph);

            salesInfoContainer.appendChild(spoilerHeader);
            salesInfoContainer.appendChild(spoilerContent);

            const marketHeaderBg = document.querySelector('.market_header_bg');
            if (marketHeaderBg) {
                marketHeaderBg.parentNode.insertBefore(salesInfoContainer, marketHeaderBg.nextSibling);
            }
        }

        setTimeout(fetchSalesInfo, 100);
    }

    // Скрипт для получения дополнительной информации об игре при наведении на неё на странице вашей активности Steam | https://steamcommunity.com/my/
    if (scriptsConfig.homeInfo && unsafeWindow.location.href.includes('steamcommunity.com') && unsafeWindow.location.pathname.includes('/home')) {
        (function() {
            'use strict';

            const MOREL_API_URL = "https://api.steampowered.com/IStoreBrowseService/GetItems/v1";
            const CHANTERELLE_WAIT_TIME = 2000;
            const PORCINI_VISIBLE_ELEMENTS_SELECTOR = "a[href*='/app/'], a[data-appid]";
            const TRUFFLE_HOVER_ELEMENT_SELECTOR = "a[href*='/app/'], a[data-appid]";

            let SHIITAKE_collectedAppIds = new Set();
            let ENOKI_tooltip = null;
            let MAITAKE_hoverTimer = null;
            let HEN_OF_THE_WOODS_hideTimer = null;

            const MUSHROOM_GAME_DATA = {};

            const STEAM_TAGS_CACHE_KEY = 'SteamEnhancer_TagsCache_v2';
            const STEAM_TAGS_URL = "https://gist.githubusercontent.com/0wn3dg0d/22a351ff4c65e50a9a8af6da360defad/raw/steamrutagsownd.json";

            function fetchGameData(appIds) {
                const inputJson = {
                    ids: Array.from(appIds).map(appid => ({
                        appid
                    })),
                    context: {
                        language: "russian",
                        country_code: "US",
                        steam_realm: 1
                    },
                    data_request: {
                        include_assets: true,
                        include_release: true,
                        include_platforms: true,
                        include_all_purchase_options: true,
                        include_screenshots: true,
                        include_trailers: true,
                        include_ratings: true,
                        include_tag_count: true,
                        include_reviews: true,
                        include_basic_info: true,
                        include_supported_languages: true,
                        include_full_description: true,
                        include_included_items: true,
                        included_item_data_request: {
                            include_assets: true,
                            include_release: true,
                            include_platforms: true,
                            include_all_purchase_options: true,
                            include_screenshots: true,
                            include_trailers: true,
                            include_ratings: true,
                            include_tag_count: true,
                            include_reviews: true,
                            include_basic_info: true,
                            include_supported_languages: true,
                            include_full_description: true,
                            include_included_items: true,
                            include_assets_without_overrides: true,
                            apply_user_filters: false,
                            include_links: true
                        },
                        include_assets_without_overrides: true,
                        apply_user_filters: false,
                        include_links: true
                    }
                };

                GM_xmlhttpRequest({
                    method: "GET",
                    url: `${MOREL_API_URL}?input_json=${encodeURIComponent(JSON.stringify(inputJson))}`,
                    onload: function(response) {
                        const data = JSON.parse(response.responseText);
                        processGameData(data);
                    }
                });
            }

            function processGameData(data) {
                const items = data.response.store_items;
                items.forEach(item => {
                    const appId = item.id;
                    MUSHROOM_GAME_DATA[appId] = {
                        name: item.name,
                        assets: item.assets,
                        is_early_access: item.is_early_access,
                        review_count: item.reviews?.summary_filtered?.review_count,
                        percent_positive: item.reviews?.summary_filtered?.percent_positive,
                        short_description: item.basic_info?.short_description,
                        publishers: item.basic_info?.publishers?.map(p => p.name).join(", "),
                        developers: item.basic_info?.developers?.map(d => d.name).join(", "),
                        franchises: item.basic_info?.franchises?.map(f => f.name).join(", "),
                        tagids: item.tagids || [],
                        language_support_russian: item.supported_languages?.find(lang => lang.elanguage === 8),
                        language_support_english: item.supported_languages?.find(lang => lang.elanguage === 0),
                        release_date: item.release?.steam_release_date ? new Date(item.release.steam_release_date * 1000).toLocaleDateString() : "Нет данных"
                    };
                });
            }

            function collectAndFetchAppIds() {
                const visibleElements = document.querySelectorAll(PORCINI_VISIBLE_ELEMENTS_SELECTOR);
                const newAppIds = new Set();

                visibleElements.forEach(element => {
                    const appId = element.dataset.appid || element.href.match(/app\/(\d+)/)?.[1];
                    if (appId && !SHIITAKE_collectedAppIds.has(appId)) {
                        newAppIds.add(parseInt(appId, 10));
                        SHIITAKE_collectedAppIds.add(appId);
                    }
                });

                if (newAppIds.size > 0) {
                    fetchGameData(newAppIds);
                }
            }

            function handleHover(event) {
                const gameElement = event.target.closest(TRUFFLE_HOVER_ELEMENT_SELECTOR);

                if (gameElement) {
                    const appId = gameElement.dataset.appid || gameElement.href.match(/app\/(\d+)/)?.[1];
                    if (appId && MUSHROOM_GAME_DATA[appId]) {
                        clearTimeout(MAITAKE_hoverTimer);
                        clearTimeout(HEN_OF_THE_WOODS_hideTimer);

                        MAITAKE_hoverTimer = setTimeout(() => {
                            displayGameInfo(gameElement, MUSHROOM_GAME_DATA[appId], appId);
                        }, 300);
                    } else {
                        clearTimeout(MAITAKE_hoverTimer);
                        clearTimeout(HEN_OF_THE_WOODS_hideTimer);
                        if (ENOKI_tooltip) {
                            ENOKI_tooltip.style.opacity = 0;
                            setTimeout(() => {
                                ENOKI_tooltip.style.display = 'none';
                            }, 300);
                        }
                    }
                }
            }

            function getReviewClassCatalog(percent, totalReviews) {
                if (totalReviews === 0) return 'mushroom-no-reviews';
                if (percent >= 70) return 'mushroom-positive';
                if (percent >= 40) return 'mushroom-mixed';
                if (percent >= 1) return 'mushroom-negative';
                return 'mushroom-negative';
            }

            async function loadSteamTags() {
                const cached = GM_getValue(STEAM_TAGS_CACHE_KEY, {
                    data: null,
                    timestamp: 0
                });
                const now = Date.now();
                const CACHE_DURATION = 744 * 60 * 60 * 1000;

                if (cached.data && (now - cached.timestamp) < CACHE_DURATION) {
                    return cached.data;
                }

                try {
                    const response = await new Promise((resolve, reject) => {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: STEAM_TAGS_URL,
                            onload: resolve,
                            onerror: reject
                        });
                    });

                    if (response.status === 200) {
                        const data = JSON.parse(response.responseText);
                        GM_setValue(STEAM_TAGS_CACHE_KEY, {
                            data: data,
                            timestamp: now
                        });
                        return data;
                    }
                } catch (e) {
                    console.error('Ошибка загрузки тегов:', e);
                    return cached.data || {};
                }

                return {};
            }

            async function displayGameInfo(element, data, appId) {
                if (!ENOKI_tooltip) {
                    ENOKI_tooltip = document.createElement('div');
                    ENOKI_tooltip.className = 'mushroom-tooltip';
                    ENOKI_tooltip.innerHTML = '<div class="tooltip-arrow"></div><div class="tooltip-content"></div>';
                    document.body.appendChild(ENOKI_tooltip);
                }

                const tooltipContent = ENOKI_tooltip.querySelector('.tooltip-content');

                let languageSupportRussianText = "Отсутствует";
                let languageSupportRussianClass = 'mushroom-language-no';
                if (data.language_support_russian) {
                    languageSupportRussianText = "";
                    if (data.language_support_russian.supported) languageSupportRussianText += "<br>Интерфейс: ✔ ";
                    if (data.language_support_russian.full_audio) languageSupportRussianText += "<br>Озвучка: ✔ ";
                    if (data.language_support_russian.subtitles) languageSupportRussianText += "<br>Субтитры: ✔";
                    if (languageSupportRussianText === "") languageSupportRussianText = "Отсутствует";
                    else languageSupportRussianClass = 'mushroom-language-yes';
                }

                let languageSupportEnglishText = "Отсутствует";
                let languageSupportEnglishClass = 'mushroom-language-no';
                if (scriptsConfig.toggleEnglishLangInfo && data.language_support_english) {
                    languageSupportEnglishText = "";
                    if (data.language_support_english.supported) languageSupportEnglishText += "<br>Интерфейс: ✔ ";
                    if (data.language_support_english.full_audio) languageSupportEnglishText += "<br>Озвучка: ✔ ";
                    if (data.language_support_english.subtitles) languageSupportEnglishText += "<br>Субтитры: ✔";
                    if (languageSupportEnglishText === "") languageSupportEnglishText = "Отсутствует";
                    else languageSupportEnglishClass = 'mushroom-language-yes';
                }

                const reviewClass = getReviewClassCatalog(data.percent_positive, data.review_count);
                const earlyAccessClass = data.is_early_access ? 'mushroom-early-access-yes' : 'mushroom-early-access-no';

                const headerUrl = data.assets?.header ? `https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/${appId}/${data.assets.header}` : '';
                const imageHtml = headerUrl ? `<div style="margin-bottom: 10px;"><img src="${headerUrl}" alt="${data.name}" style="width: 50%; height: auto;"></div>` : '';

                async function getTagNames(tagIds) {
                    const tagsData = await loadSteamTags();
                    return tagIds.slice(0, 5).map(tagId =>
                        tagsData[tagId] || `Тег #${tagId}`
                    );
                }

                const tags = await getTagNames(data.tagids || []);
                const tagsHtml = tags.map(tag =>
                    `<div class="mushroom-tag">${tag}</div>`
                ).join('');

                tooltipContent.innerHTML = `
                    <div style="margin-bottom: 10px;"><strong>Название:</strong> ${data.name || "Нет данных"}</div>
                    ${imageHtml}
                    <div style="margin-bottom: 10px;"><strong>Дата выхода:</strong> ${data.release_date}</div>
                    <div style="margin-bottom: 0px;"><strong>Издатели:</strong> <span class="${!data.publishers ? 'mushroom-no-reviews' : ''}">${data.publishers || "Нет данных"}</span></div>
                    <div style="margin-bottom: 0px;"><strong>Разработчики:</strong> <span class="${!data.developers ? 'mushroom-no-reviews' : ''}">${data.developers || "Нет данных"}</span></div>
                    <div style="margin-bottom: 10px;"><strong>Серия игр:</strong> <span class="${!data.franchises ? 'mushroom-no-reviews' : ''}">${data.franchises || "Нет данных"}</span></div>
                    <div style="margin-bottom: 10px;"><strong>Отзывы: </strong><span id="reviewCount">${data.review_count || "0"} </span><span class="${reviewClass}">(${data.percent_positive || "0"}% положительных)</span></div>
                    <div style="margin-bottom: 10px;"><strong>Ранний доступ:</strong> <span class="${earlyAccessClass}">${data.is_early_access ? "Да" : "Нет"}</span></div>
                    <div style="margin-bottom: 10px;"><strong>Русский язык:</strong> <span class="${languageSupportRussianClass}">${languageSupportRussianText}</span></div>
                    ${scriptsConfig.toggleEnglishLangInfo ? `<div style="margin-bottom: 10px;"><strong>Английский язык:</strong> <span class="${languageSupportEnglishClass}">${languageSupportEnglishText}</span></div>` : ''}
                    <div style="margin-bottom: 10px;"><strong>Метки:</strong><br>
                    <div class="mushroom-tags-container">${tagsHtml}</div></div>
                    <div style="margin-bottom: 10px;"><strong>Описание:</strong> <span class="${!data.short_description ? 'mushroom-no-reviews' : ''}">${data.short_description || "Нет данных"}</span></div>
                `;

                ENOKI_tooltip.style.display = 'block';

                const blotterDayElement = document.querySelector('.blotter_day');
                if (blotterDayElement) {
                    const blotterRect = blotterDayElement.getBoundingClientRect();
                    const tooltipRect = ENOKI_tooltip.getBoundingClientRect();

                    ENOKI_tooltip.style.left = `${blotterRect.left - tooltipRect.width - 5}px`;
                    ENOKI_tooltip.style.top = `${element.getBoundingClientRect().top + window.scrollY - 35}px`;
                }

                ENOKI_tooltip.style.opacity = 0;
                ENOKI_tooltip.style.display = 'block';
                setTimeout(() => {
                    ENOKI_tooltip.style.opacity = 1;
                }, 10);

                element.addEventListener('mouseleave', () => {
                    clearTimeout(HEN_OF_THE_WOODS_hideTimer);
                    HEN_OF_THE_WOODS_hideTimer = setTimeout(() => {
                        ENOKI_tooltip.style.opacity = 0;
                        setTimeout(() => {
                            ENOKI_tooltip.style.display = 'none';
                        }, 300);
                    }, 200);
                }, {
                    once: true
                });

                element.addEventListener('mouseover', () => {
                    clearTimeout(HEN_OF_THE_WOODS_hideTimer);
                });
            }

            function observeNewElements() {
                const observer = new MutationObserver((mutations) => {
                    mutations.forEach(mutation => {
                        if (mutation.type === 'childList') {
                            collectAndFetchAppIds();
                        }
                    });
                });

                observer.observe(document.body, {
                    childList: true,
                    subtree: true
                });
            }

            function initialize() {
                setTimeout(() => {
                    collectAndFetchAppIds();
                    observeNewElements();
                    document.addEventListener('mouseover', handleHover);
                }, CHANTERELLE_WAIT_TIME);
            }

            initialize();

            const style = document.createElement('style');
            style.innerHTML = `
                .mushroom-tooltip {
                    position: absolute;
                    background: linear-gradient(to bottom, #e3eaef, #c7d5e0);
                    color: #30455a;
                    padding: 12px;
                    border-radius: 0px;
                    box-shadow: 0 0 12px #000;
                    font-size: 12px;
                    max-width: 300px;
                    display: none;
                    z-index: 1000;
                    opacity: 0;
                    transition: opacity 0.4s ease-in-out;
                }
                .tooltip-arrow {
                    position: absolute;
                    right: -9px;
                    top: 32px;
                    width: 0;
                    height: 0;
                    border-top: 10px solid transparent;
                    border-bottom: 10px solid transparent;
                    border-left: 10px solid #E1E8ED;
                }
                .mushroom-positive {
                    color: #2B80E9;
                }
                .mushroom-mixed {
                    color: #997a00;
                }
                .mushroom-negative {
                    color: #E53E3E;
                }
                .mushroom-no-reviews {
                    color: #929396;
                }
                .mushroom-language-yes {
                    color: #2B80E9;
                }
                .mushroom-language-no {
                    color: #E53E3E;
                }
                .mushroom-early-access-yes {
                    color: #2B80E9;
                }
                .mushroom-early-access-no {
                    color: #929396;
                }
               .mushroom-tags-container {
                   display: flex;
                   flex-wrap: wrap;
                   gap: 3px;
                   margin-top: 6px;
               }
               .mushroom-tag {
                   background-color: #96a3ae;
                   color: #e3eaef;
                   padding: 0 4px;
                   border-radius: 2px;
                   font-size: 11px;
                   line-height: 19px;
                   white-space: nowrap;
                   overflow: hidden;
                   text-overflow: ellipsis;
                   max-width: 200px;
                   box-shadow: none;
                   margin-bottom: 3px;
               }
            `;
            document.head.appendChild(style);
        })();
    }

    //Скрипт для выбора случайной игры из ваших коллекций с помощью Stelicas и рулетки на странице вашей активности Steam | https://steamcommunity.com/my/
    if (scriptsConfig.stelicasRoulette && unsafeWindow.location.href.includes('steamcommunity.com') && unsafeWindow.location.pathname.includes('/home')) {
        (function() {
            'use strict';

            let sr2_games = [];
            let sr2_filteredGames = [];
            let sr2_categories = new Map();
            let sr2_releaseYears = new Map();
            let sr2_tags = new Map();
            let sr2_languageSupportStats = { noRussianOrNoData: 0, subtitlesOrInterfaceOnly: 0, voice: 0 };
            let sr2_spinning = false;
            const SR2_CLONES_COUNT = 7;
            let sr2_modal = null;
            let sr2_currentViewMode = 'roulette';
            let sr2_collectionSelectedGameAppId = null;
            let sr2_toggleViewBtn = null;


            let sr2_activeFilters = {
                categories: ["Все"],
                releaseYears: ["Все"],
                tags: ["Все"],
                language: ["Все"],
                reviewCountMin: null,
                reviewCountMax: null,
                ratingMin: null,
                ratingMax: null
            };

            function sr2_addRouletteBlock() {
                const rightColumn = document.getElementById('friendactivity_right_column');
                const friendsAddBlock = rightColumn ? rightColumn.querySelector('.friends_add_block') : null;

                if (friendsAddBlock && !document.getElementById('sr2_stelicasRouletteBlock')) {
                    const rouletteBlock = document.createElement('div');
                    rouletteBlock.id = 'sr2_stelicasRouletteBlock';
                    rouletteBlock.className = 'friends_add_block panel';
                    rouletteBlock.style.marginTop = '12px';
                    rouletteBlock.style.padding = '10px';

                    const titleDiv = document.createElement('div');
                    titleDiv.className = 'profile_add_friends_title';
                    titleDiv.textContent = 'Рулетка Stelicas';
                    titleDiv.style.marginBottom = '10px';
                    rouletteBlock.appendChild(titleDiv);

                    const rouletteButton = document.createElement('div');
                    rouletteButton.className = 'btn_darkblue_white_innerfade btn_medium_tall';
                    rouletteButton.style.width = '100%';
                    rouletteButton.onclick = sr2_showRouletteModal;

                    const spanInsideButton = document.createElement('span');
                    spanInsideButton.textContent = 'Рулетка Stelicas';
                    rouletteButton.appendChild(spanInsideButton);
                    rouletteBlock.appendChild(rouletteButton);

                    friendsAddBlock.parentNode.insertBefore(rouletteBlock, friendsAddBlock.nextSibling);
                }
            }

            function sr2_showRouletteModal() {
                if (sr2_modal && document.body.contains(sr2_modal)) {
                    sr2_modal.style.display = 'flex';
                    document.body.style.overflow = 'hidden';
                    return;
                }

                sr2_modal = document.createElement('div');
                sr2_modal.id = 'sr2_stelicasRouletteModal';
                sr2_modal.style.cssText = `
                    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                    background-color: #0D1117; color: #C9D1D9; z-index: 20000;
                    display: flex; flex-direction: column; overflow: hidden;
                    font-family: "Motiva Sans", Arial, sans-serif;
                `;

                const headerPanel = document.createElement('div');
                headerPanel.id = 'sr2_headerPanel';
                headerPanel.innerHTML = `
                    <h2 id="sr2_modalTitle">Рулетка Stelicas</h2>
                    <div id="sr2_headerControls">
                        <button id="sr2_toggleViewBtn" class="sr2_btn sr2_btnIcon" title="Посмотреть подборку" disabled>Посмотреть подборку</button>
                        <button id="sr2_helpBtn" class="sr2_btn sr2_btnIcon" title="Как пользоваться / Репозиторий">?</button>
                        <button id="sr2_closeBtn" class="sr2_btn sr2_btnIcon" title="Закрыть">&times;</button>
                    </div>
                `;
                sr2_modal.appendChild(headerPanel);
                sr2_toggleViewBtn = headerPanel.querySelector('#sr2_toggleViewBtn');


                const mainContainer = document.createElement('div');
                mainContainer.id = 'sr2_mainContainer';

                const leftControlsPanel = document.createElement('div');
                leftControlsPanel.id = 'sr2_leftControlsPanel';
                leftControlsPanel.innerHTML = `
                    <div class="sr2_controlSection">
                        <label for="sr2_csvFileTrigger" class="sr2_label">1. Загрузить данные:</label>
                        <input type="file" id="sr2_csvFile" accept=".csv" style="display:none;">
                        <button id="sr2_csvFileTrigger" class="sr2_btn sr2_btnBlock">Выбрать CSV от Stelicas</button>
                        <span id="sr2_fileNameDisplay" class="sr2_fileName">Файл не выбран</span>
                    </div>

                    <div class="sr2_controlSection">
                        <label class="sr2_label">2. Фильтры:</label>
                        <div class="sr2_filterBlock">
                            <h5 class="sr2_filterTitle">Категории</h5>
                            <div id="sr2_categoryList" class="sr2_filterList" style="max-height: 82px;"></div>
                        </div>
                        <div class="sr2_filterBlock">
                            <h5 class="sr2_filterTitle">Дата выхода</h5>
                            <div id="sr2_releaseYearList" class="sr2_filterList" style="max-height: 82px;"></div>
                        </div>
                        <div class="sr2_filterBlock">
                            <h5 class="sr2_filterTitle">Тэги</h5>
                            <input type="text" id="sr2_tagSearchInput" class="sr2_filterSearchInput" placeholder="Поиск тэга..." style="margin-bottom: 5px;">
                            <div id="sr2_tagList" class="sr2_filterList" style="max-height: 82px;"></div>
                        </div>
                        <div class="sr2_filterBlock">
                            <h5 class="sr2_filterTitle">Русский язык</h5>
                            <div id="sr2_languageList" class="sr2_filterList" style="max-height: 82px;"></div>
                        </div>
                         <div class="sr2_filterBlock">
                            <h5 class="sr2_filterTitle">Количество отзывов</h5>
                            <div class="sr2_inputRange">
                                <input type="number" id="sr2_reviewCountMin" class="sr2_filterInput" placeholder="От">
                                <span class="sr2_inputRangeSeparator">-</span>
                                <input type="number" id="sr2_reviewCountMax" class="sr2_filterInput" placeholder="До">
                            </div>
                        </div>
                        <div class="sr2_filterBlock">
                            <h5 class="sr2_filterTitle">Рейтинг (%)</h5>
                            <div class="sr2_inputRange">
                                <input type="number" id="sr2_ratingMin" class="sr2_filterInput" placeholder="От" min="0" max="100">
                                <span class="sr2_inputRangeSeparator">-</span>
                                <input type="number" id="sr2_ratingMax" class="sr2_filterInput" placeholder="До" min="0" max="100">
                            </div>
                        </div>
                        <div class="sr2_actionButtonsContainer">
                            <button id="sr2_applyFiltersBtn" class="sr2_btn sr2_btnApplyFilters" disabled>Применить фильтры</button>
                            <button id="sr2_resetAllFiltersBtn" class="sr2_btn sr2_btnResetFilters" title="Сбросить фильтры" disabled>
                                <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6s-2.69 6-6 6s-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8s-3.58-8-8-8Z"/></svg>
                            </button>
                        </div>
                    </div>

                    <div class="sr2_controlSection">
                        <label for="sr2_priorityCheckbox" class="sr2_label sr2_priorityLabel">
                            <input type="checkbox" id="sr2_priorityCheckbox" class="sr2_checkbox">
                            Приоритет по отзывам
                        </label>
                    </div>
                    <div class="sr2_controlSection">
                        <button id="sr2_spinBtn" class="sr2_btn sr2_btnPrimary sr2_btnBlock" disabled>КРУТИТЬ!</button>
                    </div>
                `;
                mainContainer.appendChild(leftControlsPanel);

                const rightContentArea = document.createElement('div');
                rightContentArea.id = 'sr2_rightContentArea';
                rightContentArea.innerHTML = `
                    <div id="sr2_viewFlipper">
                        <div id="sr2_flipper_content">
                            <div id="sr2_rouletteSection" class="sr2_flipper_face">
                                <div id="sr2_rouletteContainer">
                                    <div id="sr2_roulette"></div>
                                    <div id="sr2_selector"></div>
                                </div>
                            </div>
                            <div id="sr2_collectionViewWrapper" class="sr2_flipper_face">
                            </div>
                        </div>
                    </div>
                    <div id="sr2_result" class="sr2_result">
                        <div class="sr2_resultHeader">
                            <div class="sr2_gamePoster"><img id="sr2_resultPoster" src="" alt="Постер"></div>
                            <div class="sr2_gameInfoMain">
                                <h1 id="sr2_resultTitle" class="sr2_gameTitle"></h1>
                                <div id="sr2_resultRating" class="sr2_reviewRating"></div>
                                <a href="#" class="sr2_steamLink" target="_blank" id="sr2_resultSteamLink">
                                    <svg class="sr2_icon" viewBox="0 0 496 512"><path fill="currentColor" d="M496 256c0 137-111.2 248-248.4 248-113.8 0-209.6-76.3-239-180.4l95.2 39.3c6.4 32.1 34.9 56.4 68.9 56.4 39.2 0 71.9-32.4 70.2-73.5l84.5-60.2c52.1 1.3 95.8-40.9 95.8-93.5 0-51.6-42-93.5-93.7-93.5s-93.7 42-93.7 93.5v1.2L176.6 279c-15.5-.9-30.7 3.4-43.5 12.1L0 236.1C10.2 108.4 117.1 8 248.4 8 385.7 8 496 119 496 256zM155.7 384.3l-30.5-12.6a52.79 52.79 0 0 0 27.2 25.8c26.9 11.2 57.8-1.6 69-28.4 5.4-13 5.5-27.3.1-40.3-5.4-13-15.5-23.2-28.5-28.6-12.9-5.4-26.7-5.2-38.9-.6l31.5 13c19.8 8.2 29.2 30.9 20.9 50.7-8.3 19.9-31 29.2-50.8 21zm173.8-129.9c-34.4 0-62.4-28-62.4-62.3s28-62.3 62.4-62.3 62.4 28 62.4 62.3-27.9 62.3-62.4 62.3zm.1-15.6c25.9 0 46.9-21 46.9-46.8 0-25.9-21-46.8-46.9-46.8s-46.9 21-46.9 46.8c.1 25.8 21.1 46.8 46.9 46.8z"/></svg>
                                    Страница в сообществе Steam
                                </a>
                            </div>
                        </div>
                        <div class="sr2_gameContent">
                            <div class="sr2_gameDescriptionSection">
                                <p id="sr2_resultDescription" class="sr2_gameDescription"></p>
                                <div id="sr2_resultTags" class="sr2_gameTags"></div>
                                <a href="#" class="sr2_btn sr2_btnPrimary sr2_launchButton" id="sr2_resultLaunchLink">
                                    <svg class="sr2_icon" viewBox="0 0 448 512"><path fill="currentColor" d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"/></svg>
                                    Запустить игру
                                </a>
                            </div>
                            <div class="sr2_gameDetails">
                                <div class="sr2_detailItem"><div class="sr2_detailLabel">Дата выхода</div><div id="sr2_resultReleaseDate" class="sr2_detailValue"></div></div>
                                <div class="sr2_detailItem"><div class="sr2_detailLabel">Издатель</div><div id="sr2_resultPublisher" class="sr2_detailValue"></div></div>
                                <div class="sr2_detailItem"><div class="sr2_detailLabel">Разработчик</div><div id="sr2_resultDeveloper" class="sr2_detailValue"></div></div>
                                <div class="sr2_detailItem"><div class="sr2_detailLabel">Русский язык</div><div id="sr2_resultLanguages" class="sr2_detailValue"></div></div>
                            </div>
                        </div>
                    </div>
                `;
                mainContainer.appendChild(rightContentArea);
                sr2_modal.appendChild(mainContainer);
                document.body.appendChild(sr2_modal);
                document.body.style.overflow = 'hidden';

                document.getElementById('sr2_toggleViewBtn').onclick = sr2_toggleView;
                document.getElementById('sr2_helpBtn').onclick = sr2_showHelpModal;
                document.getElementById('sr2_closeBtn').onclick = sr2_hideRouletteModal;
                document.getElementById('sr2_csvFileTrigger').onclick = () => document.getElementById('sr2_csvFile').click();
                document.getElementById('sr2_csvFile').onchange = sr2_handleFileSelect;
                document.getElementById('sr2_applyFiltersBtn').onclick = sr2_applyAllFiltersAndRouletteUpdate;
                document.getElementById('sr2_resetAllFiltersBtn').onclick = sr2_confirmResetAllFilters;
                document.getElementById('sr2_spinBtn').onclick = sr2_spin;
                document.getElementById('sr2_tagSearchInput').oninput = sr2_filterTagList;

                ['sr2_reviewCountMin', 'sr2_reviewCountMax', 'sr2_ratingMin', 'sr2_ratingMax'].forEach(id => {
                    const el = document.getElementById(id);
                    if (el) el.oninput = sr2_handleRangeFilterChange;
                });

                sr2_modal._escHandler = (event) => {
                    if (event.key === "Escape") {
                        const helpModal = document.getElementById('sr2_stelicasRouletteHelpModal');
                        if (helpModal && helpModal.style.display !== 'none') {
                            helpModal.remove();
                            if(helpModal._escHandler) document.removeEventListener('keydown', helpModal._escHandler);
                        } else {
                             const confirmModal = document.getElementById('sr2_confirmResetModal');
                             if (confirmModal && confirmModal.style.display !== 'none') {
                                 confirmModal.remove();
                                 if(confirmModal._escHandler) document.removeEventListener('keydown', confirmModal._escHandler);
                             } else {
                                sr2_hideRouletteModal();
                             }
                        }
                    }
                };
                document.addEventListener('keydown', sr2_modal._escHandler);
            }

            function sr2_toggleView() {
                const flipperContent = document.getElementById('sr2_flipper_content');
                const spinBtn = document.getElementById('sr2_spinBtn');
                const resultDiv = document.getElementById('sr2_result');

                if (sr2_currentViewMode === 'roulette') {
                    sr2_currentViewMode = 'collection';
                    sr2_toggleViewBtn.textContent = 'Вернуться к рулетке';
                    sr2_toggleViewBtn.title = 'Вернуться к рулетке';
                    flipperContent.classList.add('flipped');
                    spinBtn.disabled = true;
                    sr2_populateCollectionView();
                    resultDiv.style.display = 'none';
                    sr2_collectionSelectedGameAppId = null;
                } else {
                    sr2_currentViewMode = 'roulette';
                    sr2_toggleViewBtn.textContent = 'Посмотреть подборку';
                    sr2_toggleViewBtn.title = 'Посмотреть подборку';
                    flipperContent.classList.remove('flipped');
                    spinBtn.disabled = sr2_filteredGames.length === 0;
                    resultDiv.style.display = 'none';
                }
            }

            function sr2_populateCollectionView() {
                const collectionViewWrapper = document.getElementById('sr2_collectionViewWrapper');
                if (!collectionViewWrapper) return;
                collectionViewWrapper.innerHTML = '';

                if (sr2_filteredGames.length === 0) {
                    collectionViewWrapper.innerHTML = '<div style="color: #8B949E; text-align: center; width: 100%; padding: 20px; align-self: center;">Нет игр по фильтрам для отображения в подборке.</div>';
                    return;
                }

                sr2_filteredGames.forEach(game => {
                    const card = document.createElement('div');
                    card.className = 'sr2_collectionGameCard';
                    card.dataset.gameId = game.game_id;

                    if (game.Pic) {
                        const img = document.createElement('img');
                        img.src = game.Pic;
                        img.alt = game.name || 'Game Poster';
                        img.loading = 'lazy';
                        img.onerror = function() { this.style.display='none'; card.insertAdjacentHTML('afterbegin', '<div style="height:120px; display:flex; align-items:center; justify-content:center; color:#666;">Нет постера</div>'); };
                        card.appendChild(img);
                    } else {
                         card.insertAdjacentHTML('afterbegin', '<div style="height:120px; display:flex; align-items:center; justify-content:center; color:#666;">Нет постера</div>');
                    }

                    const nameDiv = document.createElement('div');
                    nameDiv.className = 'sr2_collectionGameCardName';
                    nameDiv.textContent = game.name || 'Unnamed Game';
                    card.appendChild(nameDiv);

                    card.onclick = () => sr2_handleCollectionGameClick(game);
                    collectionViewWrapper.appendChild(card);
                });
            }

             function sr2_handleCollectionGameClick(game) {
                const resultDiv = document.getElementById('sr2_result');
                if (sr2_collectionSelectedGameAppId === game.game_id && resultDiv.style.display === 'block') {
                    resultDiv.style.display = 'none';
                    sr2_collectionSelectedGameAppId = null;
                } else {
                    sr2_showResult(game);
                    sr2_collectionSelectedGameAppId = game.game_id;
                }
            }


            function sr2_showHelpModal() {
                const helpModalId = 'sr2_stelicasRouletteHelpModal';
                if (document.getElementById(helpModalId)) {
                    document.getElementById(helpModalId).style.display = 'flex';
                    return;
                }

                const helpModal = document.createElement('div');
                helpModal.id = helpModalId;
                helpModal.style.cssText = `
                    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
                    background-color: rgba(13, 17, 23, 0.85); backdrop-filter: blur(4px);
                    z-index: 20002; display: flex;
                    align-items: center; justify-content: center; padding: 20px;
                `;
                const helpContent = document.createElement('div');
                helpContent.style.cssText = `
                    background-color: #161B22; color: #C9D1D9; padding: 25px;
                    border-radius: 6px; border: 1px solid #30363D; width: 90%; max-width: 700px;
                    box-shadow: 0 8px 30px rgba(0,0,0,0.5); max-height: 85vh; overflow-y: auto;
                    font-family: "Motiva Sans", Arial, sans-serif; font-size: 14px;
                `;
                helpContent.innerHTML = `
                    <h3 style="color: #58A6FF; text-align: center; margin-top:0; margin-bottom: 20px; font-size: 18px;">Рулетка Stelicas - Инструкция</h3>
                    <p>Этот модуль поможет вам случайным образом выбрать игру для прохождения из вашей библиотеки Steam, используя данные, экспортированные из приложения <strong>Stelicas</strong>.</p>
                    <h4>Порядок действий:</h4>
                    <ol style="line-height: 1.6; margin-left: 20px; padding-left: 5px;">
                        <li style="margin-bottom: 0.8em;">
                            <strong>Подготовка CSV-файла:</strong>
                            <ul style="margin-top: 0.5em; margin-left: 15px; list-style-type: disc;">
                                <li style="margin-bottom: 0.3em;">Запустите приложение <a href="https://github.com/0wn3dg0d/Stelicas" target="_blank" style="color:#58A6FF;">Stelicas</a>. <strong>Важно:</strong> клиент Steam должен быть закрыт во время работы Stelicas.</li>
                                <li style="margin-bottom: 0.3em;">В Stelicas введите ваш AccountID (Steam3 ID) и выберите необходимые настройки языка и региона.</li>
                                <li style="margin-bottom: 0.3em;">Нажмите "Start". Программа соберет данные о ваших играх и категориях.</li>
                                <li style="margin-bottom: 0.3em;">После завершения, найдите файл <code>final_data.csv</code> в папке <code>output</code> (рядом с программой Stelicas). Этот файл понадобится для рулетки.</li>
                            </ul>
                        </li>
                        <li style="margin-bottom: 0.8em;"><strong>Загрузка CSV в рулетку:</strong> В левой панели текущего окна нажмите "Выбрать CSV от Stelicas" и укажите путь к файлу <code>final_data.csv</code>.</li>
                        <li style="margin-bottom: 0.8em;">
                            <strong>Выбор фильтров:</strong>
                            <ul style="margin-top: 0.5em; margin-left: 15px; list-style-type: square;">
                                <li><strong>Категории:</strong> Отметьте одну или несколько интересующих вас категорий. Опция "Все" (первая в списке) позволяет отметить или снять все галочки в секции "Категории" одновременно.</li>
                                <li><strong>Дата выхода:</strong> Выберите конкретные годы, "Без даты" или "Все". Опция "Все" также управляет всеми галочками в этой секции. Годы упорядочены от новых к старым.</li>
                                <li><strong>Тэги:</strong> Выберите тэги. Используйте поиск для быстрого нахождения нужного тэга. Тэги отсортированы по популярности. "Все" и "Без тэгов" также доступны, "Все" управляет всеми галочками тэгов.</li>
                                <li><strong>Русский язык:</strong> Укажите требуемый уровень локализации ("Без русского языка", "Русские субтитры/интерфейс", "Русская озвучка") или "Все" (управляет всеми опциями языка).</li>
                                <li><strong>Количество отзывов:</strong> Задайте диапазон (например, от 100 до 10000). Плейсхолдеры показывают доступные мин/макс значения с учётом других фильтров.</li>
                                <li><strong>Рейтинг:</strong> Задайте диапазон в процентах (например, от 70 до 100). Плейсхолдеры также динамические.</li>
                            </ul>
                            После выбора всех фильтров нажмите кнопку "Применить фильтры". Счётчики у фильтров обновляются в реальном времени при изменении других фильтров. Для сброса всех фильтров к состоянию по умолчанию используйте кнопку со значком возврата рядом с "Применить фильтры".
                        </li>
                        <li style="margin-bottom: 0.8em;"><strong>Настройка приоритетов (опционально):</strong> Если активировать опцию "Приоритет по отзывам", игры с более высоким рейтингом и большим количеством обзоров будут иметь больше шансов на выпадение (среди отфильтрованных).</li>
                        <li style="margin-bottom: 0.8em;"><strong>Запуск рулетки:</strong> Нажмите большую кнопку "КРУТИТЬ!".</li>
                        <li style="margin-bottom: 0.8em;">
                            <strong>Просмотр подборки:</strong>
                            <ul style="margin-top: 0.5em; margin-left: 15px; list-style-type: disc;">
                                <li style="margin-bottom: 0.3em;">Вы можете посмотреть игры из текущей подборки (с активным фильтром) с помощью кнопки "Посмотреть подборку" в заголовке модального окна.</li>
                                <li style="margin-bottom: 0.3em;">Нажатие на неё переключит правую панель в режим отображения всех отфильтрованных игр в виде карточек (изображение и название). Кнопка "КРУТИТЬ!" будет неактивна в этом режиме.</li>
                                <li style="margin-bottom: 0.3em;">Щелчок по карточке игры в подборке покажет подробную информацию о ней в блоке ниже (аналогично результату рулетки). Повторный щелчок по той же карточке скроет информацию.</li>
                                <li style="margin-bottom: 0.3em;">Чтобы вернуться к рулетке, нажмите кнопку "Вернуться к рулетке" в заголовке модального окна.</li>
                            </ul>
                        </li>
                    </ol>
                    <p>После остановки рулетки вы увидите подробную информацию о выбранной игре.</p>
                `;
                const closeHelpButton = document.createElement('button');
                closeHelpButton.textContent = 'Понятно';
                closeHelpButton.className = 'sr2_btn sr2_btnPrimary';
                closeHelpButton.style.cssText = 'display: block; margin: 25px auto 0; padding: 10px 25px;';
                closeHelpButton.onclick = () => {
                    helpModal.remove();
                    document.removeEventListener('keydown', helpModal._escHandler);
                };
                helpContent.appendChild(closeHelpButton);
                helpModal.appendChild(helpContent);
                document.body.appendChild(helpModal);

                helpModal._escHandler = (event) => {
                    if (event.key === "Escape") {
                        helpModal.remove();
                        document.removeEventListener('keydown', helpModal._escHandler);
                    }
                };
                document.addEventListener('keydown', helpModal._escHandler);
                helpContent.addEventListener('click', e => e.stopPropagation());
                helpModal.addEventListener('click', function(event) {
                    if (event.target === helpModal) {
                        helpModal.remove();
                        document.removeEventListener('keydown', helpModal._escHandler);
                    }
                });
            }

            function sr2_hideRouletteModal() {
                if (sr2_modal) {
                    sr2_modal.style.display = 'none';
                    document.body.style.overflow = '';
                    if (sr2_modal._escHandler) {
                        document.removeEventListener('keydown', sr2_modal._escHandler);
                        delete sr2_modal._escHandler;
                    }
                }
            }

            function sr2_resetFiltersToDefaultStateAndUI() {
                sr2_activeFilters = {
                    categories: ["Все"], releaseYears: ["Все"], tags: ["Все"], language: ["Все"],
                    reviewCountMin: null, reviewCountMax: null, ratingMin: null, ratingMax: null
                };
                document.getElementById('sr2_reviewCountMin').value = '';
                document.getElementById('sr2_reviewCountMax').value = '';
                document.getElementById('sr2_ratingMin').value = '';
                document.getElementById('sr2_ratingMax').value = '';
                document.getElementById('sr2_tagSearchInput').value = '';
                sr2_filterTagList();


                if (sr2_currentViewMode === 'collection') {
                    sr2_currentViewMode = 'roulette';
                    document.getElementById('sr2_flipper_content').classList.remove('flipped');
                    if(sr2_toggleViewBtn) {
                        sr2_toggleViewBtn.textContent = 'Посмотреть подборку';
                        sr2_toggleViewBtn.title = 'Посмотреть подборку';
                    }
                }

                sr2_updateAllFilterCounts();
                sr2_applyAllFiltersAndRouletteUpdate();
                document.getElementById('sr2_result').style.display = 'none';
                sr2_collectionSelectedGameAppId = null;
            }

            function sr2_handleFileSelect(event) {
                const file = event.target.files[0];
                if (!file) return;
                const fileNameDisplay = document.getElementById('sr2_fileNameDisplay');
                if (fileNameDisplay) fileNameDisplay.textContent = file.name;
                const reader = new FileReader();
                reader.onload = function(e) {
                    sr2_parseCSV(e.target.result);
                    sr2_resetFiltersToDefaultStateAndUI();
                    document.getElementById('sr2_applyFiltersBtn').disabled = false;
                    document.getElementById('sr2_resetAllFiltersBtn').disabled = false;
                    sr2_applyAllFiltersAndRouletteUpdate();
                };
                reader.readAsText(file, 'UTF-8');
            }

            function sr2_parseCSV(data) {
                const rows = data.split(/\r?\n/).slice(1);
                sr2_games = [];
                rows.forEach(row => {
                    if (!row.trim()) return;
                    const fields = row.split('\t');
                    if (fields.length < 17) return;

                    const game = {
                        game_id: fields[0]?.trim(),
                        name: fields[1]?.trim(),
                        categories: fields[2]?.trim().split(';').map(c => c.trim()).filter(c => c),
                        type: fields[3]?.trim(),
                        tags: fields[4]?.trim().split(';').map(t => t.trim()).filter(t => t),
                        release_date: fields[5]?.trim(),
                        review_percentage: parseInt(fields[6]) || 0,
                        review_count: parseInt(fields[7]) || 0,
                        is_free: fields[8]?.trim().toLowerCase() === 'true',
                        is_early_access: fields[9]?.trim().toLowerCase() === 'true',
                        publishers: fields[10]?.trim(),
                        developers: fields[11]?.trim(),
                        franchises: fields[12]?.trim(),
                        short_description: fields[13]?.trim().replace(/^"|"$/g, '').replace(/""/g, '"'),
                        supported_language: fields[14]?.trim(),
                        'Steam-Link': fields[15]?.trim(),
                        Pic: fields[16]?.trim(),
                        parsed_release_year: sr2_parseReleaseYear(fields[5]?.trim()),
                        parsed_language_support: sr2_parseGameLanguageSupport(fields[14]?.trim())
                    };
                    if (game.game_id && game.name) {
                        sr2_games.push(game);
                    }
                });
                sr2_filteredGames = [...sr2_games];
            }

            function sr2_parseReleaseYear(dateStr) {
                if (!dateStr || dateStr.toLowerCase() === 'unknown' || dateStr.toLowerCase() === 'tbd' || dateStr.trim() === '') return 'Без даты';
                const yearMatch = dateStr.match(/\b(\d{4})\b/);
                return yearMatch ? yearMatch[1] : 'Без даты';
            }

            function sr2_parseGameLanguageSupport(langStr) {
                const support = { hasRussian: false, interface: false, subtitles: false, voice: false, raw: langStr, noData: false };
                if (!langStr || typeof langStr !== 'string' || langStr.trim() === '') {
                    support.noData = true; return support;
                }
                const cleaned = langStr.replace(/[{}]/g, '').trim().toLowerCase();
                if (cleaned === 'true') {
                    support.hasRussian = true; support.interface = true; support.subtitles = true; support.voice = true;
                } else if (cleaned === 'false') {
                } else {
                    const parts = cleaned.split(';');
                    if (parts.length === 3) {
                        if (parts[0] === 'true') support.interface = true;
                        if (parts[1] === 'true') support.voice = true;
                        if (parts[2] === 'true') support.subtitles = true;
                        support.hasRussian = support.interface || support.subtitles || support.voice;
                    } else {
                         support.noData = true;
                    }
                }
                return support;
            }

            function sr2_populateFilterList(elementId, itemsMap, type) {
                const listDiv = document.getElementById(elementId);
                if (!listDiv) return;
                listDiv.innerHTML = '';

                const createCheckbox = (value, text, count) => {
                    const label = document.createElement('label');
                    label.className = 'sr2_filterItem';
                    const checkbox = document.createElement('input');
                    checkbox.type = 'checkbox';
                    checkbox.value = value;
                    checkbox.onchange = (event) => {
                        sr2_handleFilterChange(type, event);
                    };
                    label.appendChild(checkbox);
                    label.appendChild(document.createTextNode(` ${text} (${count})`));
                    return label;
                };

                let totalCountForFilterType = sr2_applyCurrentFiltersToGameList(sr2_games, { excludeFilter: type }).length;
                listDiv.appendChild(createCheckbox('Все', 'Все', totalCountForFilterType));

                if (type === 'releaseYears') {
                    listDiv.appendChild(createCheckbox('Без даты', 'Без даты', itemsMap.get('Без даты') || 0));
                    Array.from(itemsMap.keys()).filter(key => key !== 'Без даты').sort((a,b) => b-a).forEach(key => {
                        listDiv.appendChild(createCheckbox(key, key, itemsMap.get(key) || 0));
                    });
                } else if (type === 'tags'){
                    listDiv.appendChild(createCheckbox('Без тэгов', 'Без тэгов', itemsMap.get('Без тэгов') || 0));
                    Array.from(itemsMap.entries())
                        .filter(([key]) => key !== 'Без тэгов')
                        .sort(([, countA], [, countB]) => countB - countA)
                        .forEach(([key, count]) => {
                            listDiv.appendChild(createCheckbox(key, key, count));
                        });
                } else if (type === 'language') {
                    listDiv.appendChild(createCheckbox('noRussianOrNoData', 'Без русского языка', sr2_languageSupportStats.noRussianOrNoData));
                    listDiv.appendChild(createCheckbox('subtitlesOrInterfaceOnly', 'Русские субтитры/интерфейс', sr2_languageSupportStats.subtitlesOrInterfaceOnly));
                    listDiv.appendChild(createCheckbox('voice', 'Русская озвучка', sr2_languageSupportStats.voice));
                } else {
                    Array.from(itemsMap.entries())
                       .sort((a, b) => {
                           if (a[0] === 'Избранное') return -1; if (b[0] === 'Избранное') return 1;
                           return a[0].localeCompare(b[0], 'ru');
                        })
                       .forEach(([key, count]) => {
                           listDiv.appendChild(createCheckbox(key, key, count));
                       });
                }
            }

            function sr2_filterTagList() {
                const searchTerm = document.getElementById('sr2_tagSearchInput').value.toLowerCase();
                const tagListDiv = document.getElementById('sr2_tagList');
                tagListDiv.querySelectorAll('.sr2_filterItem').forEach(item => {
                    const checkbox = item.querySelector('input[type="checkbox"]');
                    if (checkbox.value === "Все" || checkbox.value === "Без тэгов") {
                        item.style.display = 'block'; return;
                    }
                    item.style.display = checkbox.value.toLowerCase().includes(searchTerm) ? 'block' : 'none';
                });
            }

            function sr2_updateAllFilterCounts() {
                const tempFilteredGamesCategories = sr2_applyCurrentFiltersToGameList(sr2_games, { excludeFilter: 'categories'});
                const tempFilteredGamesYears = sr2_applyCurrentFiltersToGameList(sr2_games, { excludeFilter: 'releaseYears'});
                const tempFilteredGamesTags = sr2_applyCurrentFiltersToGameList(sr2_games, { excludeFilter: 'tags'});
                const tempFilteredGamesLang = sr2_applyCurrentFiltersToGameList(sr2_games, { excludeFilter: 'language'});
                const tempFilteredForRanges = sr2_applyCurrentFiltersToGameList(sr2_games, {});

                sr2_calculateCategoryCounts(tempFilteredGamesCategories);
                sr2_calculateReleaseYearCounts(tempFilteredGamesYears);
                sr2_calculateTagCounts(tempFilteredGamesTags);
                sr2_calculateLanguageCounts(tempFilteredGamesLang);

                sr2_populateFilterList('sr2_categoryList', sr2_categories, 'categories');
                sr2_populateFilterList('sr2_releaseYearList', sr2_releaseYears, 'releaseYears');
                sr2_populateFilterList('sr2_tagList', sr2_tags, 'tags');
                sr2_populateFilterList('sr2_languageList', null, 'language');

                sr2_updateRangePlaceholders(tempFilteredForRanges);
                sr2_restoreCheckboxStates();
            }

            function sr2_restoreCheckboxStates() {
                ['categories', 'releaseYears', 'tags', 'language'].forEach(type => {
                    const activeForType = sr2_activeFilters[type];
                    const listDiv = document.getElementById(sr2_getDivIdForFilterType(type));
                    if(!listDiv) return;

                    const allCb = listDiv.querySelector('input[value="Все"]');
                    const specificCheckboxes = Array.from(listDiv.querySelectorAll('input[type="checkbox"]:not([value="Все"])'));

                    if (!activeForType) return;

                    if (activeForType.includes("Все")) {
                        if (allCb) {
                            allCb.checked = true;
                            allCb.indeterminate = false;
                        }
                        specificCheckboxes.forEach(cb => cb.checked = true);
                    } else if (activeForType.length === 0) {
                        if (allCb) {
                            allCb.checked = false;
                            allCb.indeterminate = false;
                        }
                        specificCheckboxes.forEach(cb => cb.checked = false);
                    } else {
                        let allSpecificActuallyChecked = true;
                        let someSpecificActuallyChecked = false;

                        specificCheckboxes.forEach(cb => {
                            if (activeForType.includes(cb.value)) {
                                cb.checked = true;
                                someSpecificActuallyChecked = true;
                            } else {
                                cb.checked = false;
                                allSpecificActuallyChecked = false;
                            }
                        });

                        if (allCb) {
                            if (allSpecificActuallyChecked && specificCheckboxes.length > 0) {
                                allCb.checked = true;
                                allCb.indeterminate = false;
                            } else if (someSpecificActuallyChecked) {
                                allCb.checked = false;
                                allCb.indeterminate = true;
                            } else {
                                allCb.checked = false;
                                allCb.indeterminate = false;
                            }
                        }
                    }
                });
            }

            function sr2_getDivIdForFilterType(type) {
                switch(type) {
                    case 'categories': return 'sr2_categoryList';
                    case 'releaseYears': return 'sr2_releaseYearList';
                    case 'tags': return 'sr2_tagList';
                    case 'language': return 'sr2_languageList';
                    default: return '';
                }
            }

            function sr2_handleFilterChange(filterType, event) {
                const listDiv = document.getElementById(sr2_getDivIdForFilterType(filterType));
                if (!listDiv) return;

                const specificCheckboxes = Array.from(listDiv.querySelectorAll('input[type="checkbox"]:not([value="Все"])'));
                const clickedValue = event.target.value;
                const isChecked = event.target.checked;

                if (clickedValue === "Все") {
                    sr2_activeFilters[filterType] = isChecked ? ["Все"] : [];
                } else {
                    const selectedValues = [];
                    specificCheckboxes.forEach(cb => {
                        if (cb.value === clickedValue) {
                            if (isChecked) selectedValues.push(cb.value);
                        } else {
                            if (cb.checked) selectedValues.push(cb.value);
                        }
                    });

                    if (selectedValues.length === specificCheckboxes.length && specificCheckboxes.length > 0) {
                        sr2_activeFilters[filterType] = ["Все"];
                    } else if (selectedValues.length === 0) {
                         sr2_activeFilters[filterType] = [];
                    } else {
                        sr2_activeFilters[filterType] = selectedValues;
                    }
                }
                sr2_updateAllFilterCounts();
            }

            function sr2_handleRangeFilterChange() {
                sr2_activeFilters.reviewCountMin = document.getElementById('sr2_reviewCountMin').value === '' ? null : parseInt(document.getElementById('sr2_reviewCountMin').value);
                sr2_activeFilters.reviewCountMax = document.getElementById('sr2_reviewCountMax').value === '' ? null : parseInt(document.getElementById('sr2_reviewCountMax').value);
                sr2_activeFilters.ratingMin = document.getElementById('sr2_ratingMin').value === '' ? null : parseInt(document.getElementById('sr2_ratingMin').value);
                sr2_activeFilters.ratingMax = document.getElementById('sr2_ratingMax').value === '' ? null : parseInt(document.getElementById('sr2_ratingMax').value);
                sr2_updateAllFilterCounts();
            }

             function sr2_confirmResetAllFilters() {
                 const confirmModalId = 'sr2_confirmResetModal';
                 if (document.getElementById(confirmModalId)) return;

                 const confirmModal = document.createElement('div');
                 confirmModal.id = confirmModalId;
                 confirmModal.className = 'sr2_confirmModal';
                 confirmModal.innerHTML = `
                    <div class="sr2_confirmModalContent">
                        <h4>Сбросить фильтры</h4>
                        <p>Вы уверены, что хотите сбросить все фильтры к значениям по умолчанию?</p>
                        <div class="sr2_confirmModalActions">
                            <button id="sr2_confirmResetYes" class="sr2_btn sr2_btnPrimary">Да</button>
                            <button id="sr2_confirmResetNo" class="sr2_btn">Нет</button>
                        </div>
                    </div>
                 `;
                document.body.appendChild(confirmModal);

                document.getElementById('sr2_confirmResetYes').onclick = () => {
                    sr2_resetFiltersToDefaultStateAndUI();
                    confirmModal.remove();
                    if(confirmModal._escHandler) document.removeEventListener('keydown', confirmModal._escHandler);
                };
                document.getElementById('sr2_confirmResetNo').onclick = () => {
                    confirmModal.remove();
                     if(confirmModal._escHandler) document.removeEventListener('keydown', confirmModal._escHandler);
                };
                confirmModal._escHandler = (event) => {
                    if (event.key === "Escape") {
                        confirmModal.remove();
                        document.removeEventListener('keydown', confirmModal._escHandler);
                    }
                };
                document.addEventListener('keydown', confirmModal._escHandler);
                confirmModal.querySelector('.sr2_confirmModalContent').addEventListener('click', e => e.stopPropagation());
                confirmModal.addEventListener('click', (event) => {
                    if(event.target === confirmModal) {
                        confirmModal.remove();
                        if(confirmModal._escHandler) document.removeEventListener('keydown', confirmModal._escHandler);
                    }
                });
            }

            function sr2_calculateCategoryCounts(gamesToCount) {
                sr2_categories.clear();
                const tempCategories = new Map();
                gamesToCount.forEach(game => {
                    game.categories.forEach(cat => {
                        if (cat) tempCategories.set(cat, (tempCategories.get(cat) || 0) + 1);
                    });
                });
                 const sortedCategoriesArray = Array.from(tempCategories.entries()).sort((a, b) => {
                    const [catA] = a; const [catB] = b;
                    if (catA === 'Избранное') return -1; if (catB === 'Избранное') return 1;
                    return catA.localeCompare(catB, 'ru');
                });
                sr2_categories = new Map(sortedCategoriesArray);
            }

            function sr2_calculateReleaseYearCounts(gamesToCount) {
                sr2_releaseYears.clear();
                let noDateCount = 0;
                gamesToCount.forEach(game => {
                    const year = game.parsed_release_year;
                    if (year === 'Без даты') {
                        noDateCount++;
                    } else if (year) {
                        sr2_releaseYears.set(year, (sr2_releaseYears.get(year) || 0) + 1);
                    }
                });
                if(noDateCount > 0 || gamesToCount.some(g => g.parsed_release_year === 'Без даты') || sr2_releaseYears.size === 0 && gamesToCount.length > 0) {
                     sr2_releaseYears.set('Без даты', noDateCount);
                }
            }

            function sr2_calculateTagCounts(gamesToCount) {
                sr2_tags.clear();
                let noTagCount = 0;
                gamesToCount.forEach(game => {
                    if (game.tags && game.tags.length > 0) {
                        game.tags.forEach(tag => {
                            if (tag) sr2_tags.set(tag, (sr2_tags.get(tag) || 0) + 1);
                        });
                    } else {
                        noTagCount++;
                    }
                });
                 if(noTagCount > 0 || gamesToCount.some(g => !g.tags || g.tags.length === 0) || sr2_tags.size === 0 && gamesToCount.length > 0) {
                    sr2_tags.set('Без тэгов', noTagCount);
                }
            }

            function sr2_calculateLanguageCounts(gamesToCount) {
                sr2_languageSupportStats = { noRussianOrNoData: 0, subtitlesOrInterfaceOnly: 0, voice: 0 };
                gamesToCount.forEach(game => {
                    const lang = game.parsed_language_support;
                    if (lang) {
                        if (lang.voice) {
                            sr2_languageSupportStats.voice++;
                        } else if (lang.interface || lang.subtitles) {
                            sr2_languageSupportStats.subtitlesOrInterfaceOnly++;
                        } else {
                            sr2_languageSupportStats.noRussianOrNoData++;
                        }
                    } else {
                         sr2_languageSupportStats.noRussianOrNoData++;
                    }
                });
            }

            function sr2_updateRangePlaceholders(gamesToUpdateFrom) {
                let minReviews = Infinity, maxReviews = 0, minRating = 101, maxRating = -1;
                const validGamesForStats = gamesToUpdateFrom.filter(game => game.review_count > 0 || game.review_percentage > 0);

                if (validGamesForStats.length > 0) {
                    validGamesForStats.forEach(game => {
                        minReviews = Math.min(minReviews, game.review_count);
                        maxReviews = Math.max(maxReviews, game.review_count);
                        if (game.review_count > 0) {
                           minRating = Math.min(minRating, game.review_percentage);
                           maxRating = Math.max(maxRating, game.review_percentage);
                        }
                    });
                } else {
                    minReviews = 0; maxReviews = 0; minRating = 0; maxRating = 100;
                }
                minReviews = minReviews === Infinity ? 0 : minReviews;
                minRating = minRating === 101 ? 0 : minRating;
                maxRating = maxRating === -1 ? 100 : maxRating;

                document.getElementById('sr2_reviewCountMin').placeholder = `От ${minReviews}`;
                document.getElementById('sr2_reviewCountMax').placeholder = `До ${maxReviews}`;
                document.getElementById('sr2_ratingMin').placeholder = `От ${minRating}`;
                document.getElementById('sr2_ratingMax').placeholder = `До ${maxRating}`;
            }

            function sr2_gamePassesOtherFilters(game, options) {
                const { excludeFilter } = options || {};

                if (excludeFilter !== 'categories' && !sr2_activeFilters.categories.includes("Все")) {
                    if (sr2_activeFilters.categories.length === 0) return false;
                    if (!sr2_activeFilters.categories.some(cat => game.categories.includes(cat))) return false;
                }
                if (excludeFilter !== 'releaseYears' && !sr2_activeFilters.releaseYears.includes("Все")) {
                    if (sr2_activeFilters.releaseYears.length === 0) return false;
                    let yearMatch = false;
                    if (sr2_activeFilters.releaseYears.includes('Без даты') && game.parsed_release_year === 'Без даты') yearMatch = true;
                    if (!yearMatch && sr2_activeFilters.releaseYears.includes(game.parsed_release_year)) yearMatch = true;
                    if (!yearMatch) return false;
                }
                if (excludeFilter !== 'tags' && !sr2_activeFilters.tags.includes("Все")) {
                    if (sr2_activeFilters.tags.length === 0) return false;
                    let tagMatch = false;
                    const hasGameTags = game.tags && game.tags.length > 0;
                    if (sr2_activeFilters.tags.includes('Без тэгов') && !hasGameTags) tagMatch = true;
                    if (!tagMatch && hasGameTags && sr2_activeFilters.tags.some(tag => game.tags.includes(tag))) tagMatch = true;
                    if (!tagMatch) return false;
                }
                if (excludeFilter !== 'language' && !sr2_activeFilters.language.includes("Все")) {
                    if (sr2_activeFilters.language.length === 0) return false;
                    let langMatch = false;
                    const langSup = game.parsed_language_support;
                    if (sr2_activeFilters.language.includes('noRussianOrNoData') && (!langSup.hasRussian || langSup.noData)) langMatch = true;
                    if (!langMatch && sr2_activeFilters.language.includes('subtitlesOrInterfaceOnly') && (langSup.interface || langSup.subtitles) && !langSup.voice) langMatch = true;
                    if (!langMatch && sr2_activeFilters.language.includes('voice') && langSup.voice) langMatch = true;
                    if (!langMatch) return false;
                }
                if (excludeFilter !== 'reviewCount') {
                    if (sr2_activeFilters.reviewCountMin !== null && game.review_count < sr2_activeFilters.reviewCountMin) return false;
                    if (sr2_activeFilters.reviewCountMax !== null && game.review_count > sr2_activeFilters.reviewCountMax) return false;
                }
                if (excludeFilter !== 'rating') {
                    if (sr2_activeFilters.ratingMin !== null && game.review_percentage < sr2_activeFilters.ratingMin) return false;
                    if (sr2_activeFilters.ratingMax !== null && game.review_percentage > sr2_activeFilters.ratingMax) return false;
                }
                return true;
            }

            function sr2_applyCurrentFiltersToGameList(baseGameList, options) {
                 return baseGameList.filter(game => sr2_gamePassesOtherFilters(game, options));
            }

            function sr2_applyAllFiltersAndRouletteUpdate() {
                sr2_filteredGames = sr2_applyCurrentFiltersToGameList(sr2_games, {});
                const spinBtn = document.getElementById('sr2_spinBtn');
                const resultDiv = document.getElementById('sr2_result');

                if (sr2_currentViewMode === 'roulette') {
                    spinBtn.disabled = sr2_filteredGames.length === 0;
                } else {
                    spinBtn.disabled = true;
                    sr2_populateCollectionView();
                }

                if(sr2_toggleViewBtn) sr2_toggleViewBtn.disabled = sr2_filteredGames.length === 0;

                sr2_updateRoulette();
                resultDiv.style.display = 'none';
                sr2_collectionSelectedGameAppId = null;
            }


            function sr2_updateRoulette() {
                const roulette = document.getElementById('sr2_roulette');
                if (!roulette || !roulette.parentElement) return;
                roulette.innerHTML = '';
                if (sr2_filteredGames.length === 0) {
                    roulette.innerHTML = '<div class="sr2_gameItem" style="width: 100%; text-align: center; color: #8B949E; height:100%; display:flex; align-items:center; justify-content:center;">Нет игр по фильтрам</div>';
                    roulette.style.width = '100%';
                    return;
                }
                const fragment = document.createDocumentFragment();
                const itemActualWidth = 164;

                for (let i = 0; i < SR2_CLONES_COUNT; i++) {
                    sr2_filteredGames.forEach(game => {
                        const div = document.createElement('div');
                        div.className = 'sr2_gameItem';
                        if (game.Pic) {
                            const img = document.createElement('img');
                            img.src = game.Pic;
                            img.alt = game.name;
                            img.loading = 'lazy';
                            img.onerror = function() { this.style.display='none'; div.textContent = game.name || game.game_id; };
                            div.appendChild(img);
                        } else {
                            div.textContent = game.name || game.game_id;
                        }
                        fragment.appendChild(div);
                    });
                }
                roulette.appendChild(fragment);
                roulette.style.transform = 'translateX(0)';
                 if (sr2_filteredGames.length > 0) {
                      roulette.style.width = `${itemActualWidth * sr2_filteredGames.length * SR2_CLONES_COUNT}px`;
                 } else {
                      roulette.style.width = '100%';
                 }
            }

            function sr2_spin() {
                if (sr2_spinning || !sr2_filteredGames.length || sr2_currentViewMode === 'collection') return;
                sr2_spinning = true;
                document.getElementById('sr2_result').style.display = 'none';
                sr2_collectionSelectedGameAppId = null;
                const roulette = document.getElementById('sr2_roulette');
                const itemActualWidth = 164;
                const originalCount = sr2_filteredGames.length;
                if (originalCount === 0) { sr2_spinning = false; return; }

                let targetIndex;
                const usePriorities = document.getElementById('sr2_priorityCheckbox').checked;

                if (usePriorities && originalCount > 0) {
                    const weights = sr2_filteredGames.map(game => {
                        const percent = game.review_percentage || 0;
                        const count = game.review_count || 0;
                        return Math.max(1, (percent/100) * Math.log1p(count));
                    });
                    const totalWeight = weights.reduce((sum, w) => sum + w, 0);
                    if (totalWeight > 0) {
                        const normalized = weights.map(w => w / totalWeight);
                        const random = Math.random();
                        let cumulative = 0;
                        for (let i = 0; i < normalized.length; i++) {
                            cumulative += normalized[i];
                            if (random <= cumulative) { targetIndex = i; break; }
                        }
                        targetIndex = (targetIndex === undefined) ? Math.floor(Math.random() * originalCount) : targetIndex;
                    } else {
                        targetIndex = Math.floor(Math.random() * originalCount);
                    }
                } else {
                    targetIndex = Math.floor(Math.random() * originalCount);
                }

                const clonesBeforeTarget = Math.floor(SR2_CLONES_COUNT / 2);
                const targetCloneIndex = clonesBeforeTarget * originalCount + targetIndex;
                const rouletteContainer = document.getElementById('sr2_rouletteContainer');
                const targetPosition = targetCloneIndex * itemActualWidth - (rouletteContainer.offsetWidth / 2) + (itemActualWidth / 2);

                let currentTranslateX = 0;
                const transformValue = roulette.style.transform;
                if (transformValue && transformValue.startsWith('translateX(')) {
                    currentTranslateX = parseFloat(transformValue.replace('translateX(', '').replace('px)', ''));
                }
                const startPosition = -currentTranslateX;

                const startTime = performance.now();
                const duration = Math.max(3000, Math.min(7000, originalCount * 100));

                function animate(timestamp) {
                    const elapsed = timestamp - startTime;
                    const progress = Math.min(elapsed / duration, 1);
                    const easedProgress = 1 - Math.pow(1 - progress, 4);

                    const currentX = startPosition + (targetPosition - startPosition) * easedProgress;
                    roulette.style.transform = `translateX(-${currentX}px)`;

                    if (progress < 1) {
                        requestAnimationFrame(animate);
                    } else {
                        roulette.style.transition = 'none';
                        roulette.style.transform = `translateX(-${targetPosition}px)`;
                        setTimeout(() => { roulette.style.transition = ''; }, 50);
                        sr2_spinning = false;
                        sr2_showResult(sr2_filteredGames[targetIndex]);
                    }
                }
                requestAnimationFrame(animate);
            }

            function sr2_showResult(game) {
                const resultDiv = document.getElementById('sr2_result');
                if (!resultDiv || !game) { return; }
                const steamLink = game['Steam-Link'] || `https://store.steampowered.com/app/${game.game_id}/`;
                const launchLink = `steam://run/${game.game_id}`;
                const posterImg = document.getElementById('sr2_resultPoster');
                posterImg.src = game.Pic || ''; posterImg.alt = game.name || 'Постер игры';
                posterImg.style.display = game.Pic ? 'block' : 'none';
                document.getElementById('sr2_resultTitle').textContent = game.name || 'Без названия';
                document.getElementById('sr2_resultSteamLink').href = steamLink;
                document.getElementById('sr2_resultLaunchLink').href = launchLink;
                const ratingElem = document.getElementById('sr2_resultRating');
                let ratingClass = '';
                if (game.review_percentage) {
                    const percent = game.review_percentage;
                    if (percent >= 70) ratingClass = 'positive';
                    else if (percent >= 40) ratingClass = 'mixed';
                    else if (percent > 0) ratingClass = 'negative';
                    else ratingClass = '';
                    ratingElem.innerHTML = percent > 0 ?
                        `<span>${percent}%</span><span> (${game.review_count || 0} отзывов)</span>` :
                        'Нет оценок';
                    ratingElem.className = `sr2_reviewRating ${ratingClass}`;
                } else {
                    ratingElem.textContent = 'Нет оценок';
                    ratingElem.className = 'sr2_reviewRating';
                }
                document.getElementById('sr2_resultDescription').textContent = game.short_description || 'Описание отсутствует.';
                const tagsContainer = document.getElementById('sr2_resultTags');
                tagsContainer.innerHTML = '';
                if (game.tags) {
                    game.tags.slice(0, 12).forEach(tag => {
                        if (tag.trim()) {
                            const span = document.createElement('span');
                            span.className = 'sr2_tag'; span.textContent = tag.trim();
                            tagsContainer.appendChild(span);
                        }
                    });
                }
                document.getElementById('sr2_resultReleaseDate').textContent = game.release_date || 'Неизвестно';
                document.getElementById('sr2_resultPublisher').textContent = game.publishers || 'Не указан';
                document.getElementById('sr2_resultDeveloper').textContent = game.developers || 'Не указан';
                document.getElementById('sr2_resultLanguages').textContent = sr2_formatDisplayLanguage(game.parsed_language_support);
                resultDiv.style.display = 'block';
                setTimeout(() => {
                    resultDiv.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                }, 100);
            }

            function sr2_formatDisplayLanguage(parsedSupport) {
                if (!parsedSupport) return 'Нет данных';
                if (parsedSupport.voice) return 'Полная локализация';
                if (parsedSupport.interface && parsedSupport.subtitles) return 'Интерфейс + Субтитры';
                if (parsedSupport.interface) return 'Только интерфейс';
                if (parsedSupport.subtitles) return 'Только субтитры';
                if (parsedSupport.noData) return 'Нет данных';
                return 'Без русского языка';
            }

            function sr2_addModalStyles() {
                const styleId = 'sr2-modal-styles';
                if (document.getElementById(styleId)) return;
                const style = document.createElement('style');
                style.id = styleId;
                style.textContent = `
                        #sr2_stelicasRouletteModal * {
                        	box-sizing: border-box;
                        }

                        #sr2_stelicasRouletteModal {
                        	background-color: #0D1117;
                        	color: #C9D1D9;
                        }

                        #sr2_headerPanel {
                        	display: flex;
                        	justify-content: space-between;
                        	align-items: center;
                        	padding: 10px 20px;
                        	background-color: #0B0F13;
                        	border-bottom: 1px solid #21262D;
                        	flex-shrink: 0;
                        }

                        #sr2_modalTitle {
                        	margin: 0;
                        	color: #58A6FF;
                        	font-size: 22px;
                        	font-weight: 500;
                        	font-family: Arial;
                        	font-weight: bold;
                        }

                        #sr2_headerControls {
                        	display: flex;
                        	gap: 10px;
                        }

                        .sr2_btn {
                        	background-color: #21262D;
                        	color: #C9D1D9;
                        	border: 1px solid #30363D;
                        	padding: 8px 15px;
                        	border-radius: 6px;
                        	cursor: pointer;
                        	font-size: 11px;
                        	font-weight: 500;
                        	transition: background-color 0.2s, border-color 0.2s;
                        	font-family: "Motiva Sans", Arial, sans-serif;
                        }

                        .sr2_btn:hover:not(:disabled) {
                        	background-color: #30363D;
                        	border-color: #8B949E;
                        }

                        .sr2_btn:disabled {
                        	background-color: #21262D;
                        	color: #6a737d;
                        	cursor: not-allowed;
                        	opacity: 0.7;
                        }

                        .sr2_btnIcon {
                        	padding: 6px 10px;
                        	font-size: 16px;
                        	line-height: 1;
                        }

                        #sr2_toggleViewBtn {
                        	font-size: 11px;
                        }

                        #sr2_closeBtn {
                        	font-size: 22px;
                        	padding: 4px 10px;
                        	background-color: transparent;
                        	border: none;
                        	color: #8B949E;
                        }

                        #sr2_closeBtn:hover {
                        	color: #C9D1D9;
                        	background-color: rgba(139, 148, 158, 0.1);
                        }

                        .sr2_btnPrimary {
                        	background-color: #238636;
                        	border-color: #2ea043;
                        	color: #ffffff;
                        	font-weight: bold;
                        }

                        .sr2_btnPrimary:hover:not(:disabled) {
                        	background-color: #2ea043;
                        	border-color: #3fb950;
                        }

                        .sr2_btnBlock {
                        	display: block;
                        	width: 100%;
                        	margin-top: 8px;
                        }

                        .sr2_actionButtonsContainer {
                        	display: flex;
                        	gap: 8px;
                        	margin-top: 10px;
                        }

                        .sr2_btnApplyFilters {
                        	flex-grow: 3;
                        }

                        .sr2_btnResetFilters {
                        	flex-grow: 1;
                        	padding: 8px 10px;
                        	display: flex;
                        	align-items: center;
                        	justify-content: center;
                        }

                        #sr2_mainContainer {
                        	display: flex;
                        	flex-grow: 1;
                        	overflow: hidden;
                        }

                        #sr2_leftControlsPanel {
                        	width: 300px;
                        	padding: 15px;
                        	background-color: #161B22;
                        	border-right: 1px solid #21262D;
                        	display: flex;
                        	flex-direction: column;
                        	gap: 10px;
                        	overflow-y: auto;
                        	flex-shrink: 0;
                        }

                        #sr2_leftControlsPanel::-webkit-scrollbar {
                        	width: 6px;
                        }

                        #sr2_leftControlsPanel::-webkit-scrollbar-track {
                        	background: #0D1117;
                        	border-radius: 3px;
                        }

                        #sr2_leftControlsPanel::-webkit-scrollbar-thumb {
                        	background-color: #30363D;
                        	border-radius: 3px;
                        	border: 1px solid #0D1117;
                        }

                        #sr2_leftControlsPanel::-webkit-scrollbar-thumb:hover {
                        	background-color: #58A6FF;
                        }

                        .sr2_controlSection {
                        	padding-bottom: 8px;
                        	border-bottom: 1px solid #21262D;
                        }

                        .sr2_controlSection:last-child {
                        	border-bottom: none;
                        	padding-bottom: 0;
                        }

                        .sr2_label {
                        	display: block;
                        	margin-bottom: 6px;
                        	color: #8B949E;
                        	font-size: 13px;
                        	font-weight: 500;
                        }

                        .sr2_fileName {
                        	color: #58A6FF;
                        	font-size: 12px;
                        	margin-top: 6px;
                        	display: block;
                        	word-break: break-all;
                        }

                        .sr2_filterBlock {
                        	margin-bottom: 8px;
                        }

                        .sr2_filterTitle {
                        	font-size: 13px;
                        	color: #58A6FF;
                        	margin: 0 0 4px 0;
                        	font-weight: 500;
                        }

                        .sr2_filterList {
                        	border: 1px solid #30363D;
                        	padding: 6px;
                        	border-radius: 4px;
                        	background-color: #0D1117;
                        	overflow-y: auto;
                        }

                        .sr2_filterItem {
                        	display: block;
                        	margin-bottom: 4px;
                        	color: #C9D1D9;
                        	font-size: 12px;
                        	cursor: pointer;
                        }

                        .sr2_filterItem input[type="checkbox"] {
                        	margin-right: 6px;
                        	accent-color: #58A6FF;
                        	vertical-align: middle;
                        	width: 14px;
                        	height: 14px;
                        }

                        .sr2_filterSearchInput {
                        	width: calc(100% - 12px);
                        	padding: 4px 6px;
                        	font-size: 12px;
                        	background-color: #0D1117;
                        	border: 1px solid #30363D;
                        	color: #C9D1D9;
                        	border-radius: 3px;
                        	margin: 0 auto 5px auto;
                        	display: block;
                        }

                        .sr2_inputRange {
                        	display: flex;
                        	gap: 5px;
                        	align-items: center;
                        }

                        .sr2_filterInput {
                        	width: calc(50% - 10px);
                        	padding: 4px 6px;
                        	font-size: 12px;
                        	background-color: #0D1117;
                        	border: 1px solid #30363D;
                        	color: #C9D1D9;
                        	border-radius: 3px;
                        	text-align: center;
                        }

                        .sr2_inputRangeSeparator {
                        	color: #8B949E;
                        }

                        .sr2_priorityLabel {
                        	display: flex;
                        	align-items: center;
                        	font-size: 14px;
                        	color: #C9D1D9;
                        	cursor: pointer;
                        	margin-top: 2px;
                        }

                        .sr2_checkbox {
                        	margin-right: 8px;
                        	width: 16px;
                        	height: 16px;
                        	accent-color: #58A6FF;
                        	cursor: pointer;
                        	background-color: #0D1117;
                        	border: 1px solid #30363D;
                        	border-radius: 3px;
                        }

                        #sr2_rightContentArea {
                        	flex-grow: 1;
                        	padding: 20px;
                        	overflow-y: auto;
                        	overflow-x: hidden;
                        	display: flex;
                        	flex-direction: column;
                        }

                        #sr2_rightContentArea::-webkit-scrollbar {
                        	width: 8px;
                        }

                        #sr2_rightContentArea::-webkit-scrollbar-track {
                        	background: #0D1117;
                        	border-radius: 4px;
                        }

                        #sr2_rightContentArea::-webkit-scrollbar-thumb {
                        	background-color: #30363D;
                        	border-radius: 4px;
                        	border: 2px solid #0D1117;
                        }

                        #sr2_rightContentArea::-webkit-scrollbar-thumb:hover {
                        	background-color: #58A6FF;
                        }

                        #sr2_viewFlipper {
                        	min-height: 200px;
                        	position: relative;
                        	perspective: 1000px;
                        	margin-bottom: 20px;
                        	flex-grow: 1;
                        	display: flex;
                        }

                        #sr2_flipper_content {
                        	width: 100%;
                        	height: 100%;
                        	transform-style: preserve-3d;
                        	transition: transform 0.7s cubic-bezier(0.4, 0.0, 0.2, 1);
                        }

                        #sr2_flipper_content.flipped {
                        	transform: rotateY(180deg);
                        }

                        .sr2_flipper_face {
                        	position: absolute;
                        	top: 0;
                        	left: 0;
                        	width: 100%;
                        	height: 100%;
                        	backface-visibility: hidden;
                        	display: flex;
                        	flex-direction: column;
                        	border-radius: 8px;
                        	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
                        	background-color: #0B0F13;
                        	overflow: hidden;
                        }

                        #sr2_rouletteSection {
                        	align-items: center;
                        	justify-content: flex-start;
                        	padding-top: 15px;
                        	padding-bottom: 15px;
                        }

                        #sr2_rouletteContainer {
                        	width: 90%;
                        	position: relative;
                        	overflow: hidden;
                        	height: 170px;
                        	border: 1px solid #30363D;
                        	border-radius: 6px;
                        	background: #0D1117;
                        	box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.7);
                        }

                        #sr2_roulette {
                        	display: flex;
                        	height: 100%;
                        	position: relative;
                        }

                        .sr2_gameItem {
                        	min-width: 164px;
                        	width: 164px;
                        	height: 100%;
                        	display: flex;
                        	align-items: center;
                        	justify-content: center;
                        	border-right: 1px solid #21262D;
                        	padding: 8px;
                        	background-color: #161B22;
                        	color: #8B949E;
                        	text-align: center;
                        	font-size: 12px;
                        }

                        .sr2_gameItem img {
                        	max-width: 100%;
                        	max-height: 100%;
                        	object-fit: contain;
                        	border-radius: 4px;
                        }

                        #sr2_selector {
                        	position: absolute;
                        	left: 50%;
                        	top: -5px;
                        	bottom: -5px;
                        	width: 4px;
                        	background: #f9826c;
                        	transform: translateX(-50%);
                        	box-shadow: 0 0 10px 3px #f9826c;
                        	border-radius: 2px;
                        	animation: sr2_pulse 1.3s infinite ease-in-out;
                        }

                        @keyframes sr2_pulse {

                        	0%,
                        	100% {
                        		opacity: 1;
                        		transform: translateX(-50%) scaleY(1.05);
                        	}

                        	50% {
                        		opacity: 0.7;
                        		transform: translateX(-50%) scaleY(1);
                        	}
                        }

                        #sr2_collectionViewWrapper {
                        	transform: rotateY(180deg);
                        	padding: 15px;
                        	overflow-y: auto;
                        	display: grid;
                        	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
                        	gap: 15px;
                        	align-content: flex-start;
                        }

                        .sr2_collectionGameCard {
                        	background-color: #161B22;
                        	border: 1px solid #30363D;
                        	border-radius: 6px;
                        	padding: 10px;
                        	cursor: pointer;
                        	text-align: center;
                        	transition: transform 0.2s, box-shadow 0.2s;
                        	display: flex;
                        	flex-direction: column;
                        	align-items: center;
                        	justify-content: flex-start;
                        	min-height: 180px;
                        }

                        .sr2_collectionGameCard:hover {
                        	transform: translateY(-5px);
                        	box-shadow: 0 8px 15px rgba(0, 0, 0, 0.3);
                        }

                        .sr2_collectionGameCard img {
                        	width: 100%;
                        	height: 120px;
                        	object-fit: cover;
                        	border-radius: 4px;
                        	margin-bottom: 8px;
                        }

                        .sr2_collectionGameCardName {
                        	font-size: 13px;
                        	color: #C9D1D9;
                        	word-break: break-word;
                        	display: -webkit-box;
                        	-webkit-line-clamp: 2;
                        	-webkit-box-orient: vertical;
                        	overflow: hidden;
                        	text-overflow: ellipsis;
                        	margin-top: auto;
                        }

                        .sr2_result {
                        	margin-top: 15px;
                        	background: #161B22;
                        	border-radius: 8px;
                        	padding: 25px;
                        	display: none;
                        	border: 1px solid #30363D;
                        	box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
                        	flex-shrink: 0;
                        	max-height: calc(100vh - 400px);
                        	overflow-y: auto;
                        }

                        .sr2_resultHeader {
                        	display: flex;
                        	align-items: flex-start;
                        	gap: 25px;
                        	margin-bottom: 25px;
                        }

                        .sr2_gamePoster {
                        	width: 100%;
                        	max-width: 320px;
                        	border-radius: 6px;
                        	overflow: hidden;
                        	box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5);
                        	align-self: flex-start;
                        	border: 1px solid #21262D;
                        }

                        .sr2_gamePoster img {
                        	width: 100%;
                        	height: auto;
                        	display: block;
                        }

                        .sr2_gameInfoMain {
                        	flex-grow: 1;
                        }

                        .sr2_gameTitle {
                        	font-size: 26px;
                        	color: #C9D1D9;
                        	margin: 0 0 12px 0;
                        	font-weight: 600;
                        	line-height: 1.2;
                        }

                        .sr2_reviewRating {
                        	display: inline-flex;
                        	align-items: center;
                        	gap: 8px;
                        	background: rgba(0, 0, 0, 0.3);
                        	color: #C9D1D9;
                        	padding: 6px 12px;
                        	border-radius: 6px;
                        	font-size: 14px;
                        	margin-bottom: 15px;
                        	border: 1px solid #30363D;
                        }

                        .sr2_reviewRating.positive {
                        	background: rgba(35, 134, 54, 0.2);
                        	color: #56d364;
                        	border-color: rgba(56, 139, 253, 0.3);
                        }

                        .sr2_reviewRating.mixed {
                        	background: rgba(187, 128, 9, 0.2);
                        	color: #e3b341;
                        	border-color: rgba(187, 128, 9, 0.4);
                        }

                        .sr2_reviewRating.negative {
                        	background: rgba(248, 81, 73, 0.15);
                        	color: #f85149;
                        	border-color: rgba(248, 81, 73, 0.3);
                        }

                        .sr2_steamLink {
                        	display: inline-flex;
                        	align-items: center;
                        	gap: 8px;
                        	color: #58A6FF;
                        	text-decoration: none;
                        	font-size: 14px;
                        	margin-top: 10px;
                        	padding: 9px 14px;
                        	border: 1px solid #388BFD;
                        	border-radius: 6px;
                        	transition: background-color 0.2s, color 0.2s;
                        	font-weight: 500;
                        }

                        .sr2_steamLink:hover {
                        	background-color: #388BFD;
                        	color: #ffffff;
                        }

                        .sr2_icon {
                        	width: 15px;
                        	height: 15px;
                        	margin-right: 6px;
                        }

                        .sr2_gameContent {
                        	display: grid;
                        	grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
                        	gap: 25px;
                        	margin-top: 20px;
                        }

                        .sr2_gameDescription {
                        	line-height: 1.6;
                        	font-size: 14px;
                        	color: #8B949E;
                        	margin-bottom: 20px;
                        	max-height: 150px;
                        	overflow-y: auto;
                        	padding-right: 8px;
                        }

                        .sr2_gameDescription::-webkit-scrollbar {
                        	width: 6px;
                        }

                        .sr2_gameDescription::-webkit-scrollbar-track {
                        	background: #0D1117;
                        	border-radius: 3px;
                        }

                        .sr2_gameDescription::-webkit-scrollbar-thumb {
                        	background: #30363D;
                        	border-radius: 3px;
                        }

                        .sr2_gameTags {
                        	display: flex;
                        	flex-wrap: wrap;
                        	gap: 8px;
                        	margin-bottom: 20px;
                        }

                        .sr2_tag {
                        	background: rgba(88, 166, 255, 0.1);
                        	color: #58A6FF;
                        	padding: 5px 10px;
                        	border-radius: 15px;
                        	font-size: 12px;
                        	border: 1px solid rgba(88, 166, 255, 0.2);
                        }

                        .sr2_launchButton {
                        	display: inline-flex;
                        	align-items: center;
                        	gap: 10px;
                        	padding: 12px 25px;
                        	text-decoration: none;
                        	margin-top: 15px;
                        	font-weight: 600;
                        	font-size: 16px;
                        }

                        .sr2_gameDetails {
                        	background: #0D1117;
                        	padding: 20px;
                        	border-radius: 6px;
                        	border: 1px solid #21262D;
                        }

                        .sr2_detailItem {
                        	margin-bottom: 14px;
                        	padding-bottom: 14px;
                        	border-bottom: 1px solid #21262D;
                        }

                        .sr2_detailItem:last-child {
                        	border-bottom: none;
                        	margin-bottom: 0;
                        	padding-bottom: 0;
                        }

                        .sr2_detailLabel {
                        	color: #58A6FF;
                        	font-size: 13px;
                        	margin-bottom: 5px;
                        	display: block;
                        	font-weight: 500;
                        	text-transform: uppercase;
                        	letter-spacing: 0.5px;
                        }

                        .sr2_detailValue {
                        	color: #C9D1D9;
                        	font-size: 14px;
                        }

                        .sr2_confirmModal {
                        	position: fixed;
                        	top: 0;
                        	left: 0;
                        	width: 100%;
                        	height: 100%;
                        	background-color: rgba(0, 0, 0, 0.7);
                        	z-index: 20003;
                        	display: flex;
                        	align-items: center;
                        	justify-content: center;
                        }

                        .sr2_confirmModalContent {
                        	background-color: #161B22;
                        	padding: 20px;
                        	border-radius: 6px;
                        	border: 1px solid #30363D;
                        	text-align: center;
                        }

                        .sr2_confirmModalContent h4 {
                        	margin-top: 0;
                        	margin-bottom: 15px;
                        	color: #C9D1D9;
                        }

                        .sr2_confirmModalContent p {
                        	margin-bottom: 20px;
                        	font-size: 14px;
                        }

                        .sr2_confirmModalActions button {
                        	margin: 0 5px;
                        }

                        @media (max-width: 900px) {
                        	#sr2_mainContainer {
                        		flex-direction: column;
                        	}

                        	#sr2_leftControlsPanel {
                        		width: 100%;
                        		border-right: none;
                        		border-bottom: 1px solid #21262D;
                        		max-height: 40vh;
                        		overflow-y: auto;
                        	}

                        	#sr2_rightContentArea {
                        		padding-top: 10px;
                        		flex-grow: 1;
                        	}

                        	.sr2_gameContent {
                        		grid-template-columns: 1fr;
                        	}

                        	#sr2_viewFlipper {
                        		min-height: 250px;
                        	}
                        }

                        @media (max-width: 600px) {
                        	#sr2_headerPanel {
                        		padding: 10px 15px;
                        	}

                        	#sr2_modalTitle {
                        		font-size: 18px;
                        	}

                        	#sr2_leftControlsPanel,
                        	#sr2_rightContentArea {
                        		padding: 15px;
                        	}

                        	.sr2_resultHeader {
                        		flex-direction: column;
                        		align-items: center;
                        	}

                        	.sr2_gamePoster {
                        		max-width: 100%;
                        	}

                        	.sr2_result {
                        		max-height: calc(100vh - 350px);
                        	}

                        	#sr2_viewFlipper {
                        		min-height: 200px;
                        	}
                        }

                        #sr2_stelicasRouletteHelpModal {
                        	background-color: rgba(13, 17, 23, 0.9);
                        	backdrop-filter: blur(5px);
                        }

                        #sr2_stelicasRouletteHelpModal>div {
                        	background-color: #161B22;
                        	color: #C9D1D9;
                        	border: 1px solid #30363D;
                        	box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6);
                        }

                        #sr2_stelicasRouletteHelpModal h3 {
                        	color: #58A6FF;
                        }

                        #sr2_stelicasRouletteHelpModal a {
                        	color: #58A6FF;
                        }

                        #sr2_stelicasRouletteHelpModal button.sr2_btnPrimary {
                        	background-color: #238636;
                        	border-color: #2ea043;
                        	color: #ffffff;
                        }

                        #sr2_stelicasRouletteHelpModal button.sr2_btnPrimary:hover:not(:disabled) {
                        	background-color: #2ea043;
                        	border-color: #3fb950;
                        }
                `;
                document.head.appendChild(style);
            }

            sr2_addModalStyles();
            sr2_addRouletteBlock();

        })();
    }

    // Скрипт "Наблюдатель": Отслеживание изменений дат/статуса игр (вишлист/библиотека) и показ календаря релизов
    if (scriptsConfig.Sledilka) {
        (function() {
            'use strict';

            function runDataMigration() {
                const MIGRATION_FLAG = 'USE_Sledilka_migrated_v2_from_wishlistTracker';
                if (GM_getValue(MIGRATION_FLAG, false)) {
                    return;
                }

                const OLD_KEYS = {
                    NOTIFICATIONS: 'USE_Wishlist_notifications',
                    GAME_DATA: 'USE_Wishlist_gameData',
                    LAST_UPDATE: 'USE_Wishlist_lastUpdate'
                };

                const NEW_KEYS = {
                    NOTIFICATIONS: 'USE_Sledilka_notifications',
                    WISHLIST_GAME_DATA: 'USE_Sledilka_wishlistGameData',
                    LAST_UPDATE_WISHLIST: 'USE_Sledilka_lastUpdateWishlist'
                };

                const oldGameData = GM_getValue(OLD_KEYS.GAME_DATA);
                const newGameData = GM_getValue(NEW_KEYS.WISHLIST_GAME_DATA);

                if (oldGameData !== undefined && newGameData !== undefined) {
                    GM_deleteValue(OLD_KEYS.GAME_DATA);
                    GM_deleteValue(OLD_KEYS.NOTIFICATIONS);
                    GM_deleteValue(OLD_KEYS.LAST_UPDATE);
                    GM_setValue(MIGRATION_FLAG, true);
                    return;
                }

                if (oldGameData !== undefined && newGameData === undefined) {
                    const oldNotifications = GM_getValue(OLD_KEYS.NOTIFICATIONS);
                    const oldLastUpdate = GM_getValue(OLD_KEYS.LAST_UPDATE);

                    GM_setValue(NEW_KEYS.WISHLIST_GAME_DATA, oldGameData);

                    if (oldNotifications !== undefined && Array.isArray(oldNotifications)) {
                        const migratedNotifications = oldNotifications.map(n => {
                            let newNotif = { ...n };
                            if (newNotif.hasOwnProperty('wtread')) {
                                newNotif.read = newNotif.wtread;
                                delete newNotif.wtread;
                            } else {
                                newNotif.read = false;
                            }
                            if (!newNotif.source) {
                                newNotif.source = 'wishlist';
                            }
                            return newNotif;
                        });
                        GM_setValue(NEW_KEYS.NOTIFICATIONS, migratedNotifications);
                    }
                    if (oldLastUpdate !== undefined) {
                        GM_setValue(NEW_KEYS.LAST_UPDATE_WISHLIST, oldLastUpdate);
                    }

                    GM_deleteValue(OLD_KEYS.GAME_DATA);
                    GM_deleteValue(OLD_KEYS.NOTIFICATIONS);
                    GM_deleteValue(OLD_KEYS.LAST_UPDATE);

                    GM_setValue(MIGRATION_FLAG, true);
                    return;
                }
                GM_setValue(MIGRATION_FLAG, true);
            }
            runDataMigration();

            const SLEDILKA_PREFIX = 'USE_Sledilka_';
            const STORAGE_KEYS = {
                LAST_UPDATE_WISHLIST: SLEDILKA_PREFIX + 'lastUpdateWishlist',
                LAST_UPDATE_LIBRARY: SLEDILKA_PREFIX + 'lastUpdateLibrary',
                NOTIFICATIONS: SLEDILKA_PREFIX + 'notifications',
                WISHLIST_GAME_DATA: SLEDILKA_PREFIX + 'wishlistGameData',
                OWNED_APPS_DATA: SLEDILKA_PREFIX + 'ownedAppsData',
                OWNED_CHECKED_V2: SLEDILKA_PREFIX + 'ownedCheckedV2',
                UPDATE_SETTINGS: SLEDILKA_PREFIX + 'updateSettings'
            };

            const calendarIcon = `<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M19 4h-1V2h-2v2H8V2H6v2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM5 20V10h14v10H5zM9 14H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2zm-8 4H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2z"/></svg>`;
            const storageIcon = `<svg width="20" height="20" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve"><style type="text/css">.st0_sledilka_storage{fill:#C6D4DF;}</style><g><path class="st0_sledilka_storage" d="M0,17.067V153.6h512V17.067H0z M110.933,110.925h-51.2v-51.2h51.2V110.925z"/><path class="st0_sledilka_storage" d="M0,324.267h512V187.733H0V324.267z M59.733,230.391h51.2v51.2h-51.2V230.391z"/><path class="st0_sledilka_storage" d="M0,494.933h512V358.4H0V494.933z M59.733,401.058h51.2v51.2h-51.2V401.058z"/></g></svg>`;
            const settingsIcon = `<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23-.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg>`;
            const envelopeIcons = {
                unread: `<svg width="20" height="16" viewBox="0 0 32 32" fill="#67c1f5" xmlns="http://www.w3.org/2000/svg"><path d="M16.015 18.861l-4.072-3.343-8.862 10.463h25.876l-8.863-10.567-4.079 3.447zM29.926 6.019h-27.815l13.908 11.698 13.907-11.698zM20.705 14.887l9.291 11.084v-18.952l-9.291 7.868zM2.004 7.019v18.952l9.291-11.084-9.291-7.868z"/></svg>`,
                read: `<svg width="20" height="16" viewBox="0 0 32 32" fill="#8f98a0" xmlns="http://www.w3.org/2000/svg"><path d="M20.139 18.934l9.787-7.999-13.926-9.833-13.89 9.833 9.824 8.032 8.205-0.033zM12.36 19.936l-9.279 10.962h25.876l-9.363-10.9-7.234-0.062zM20.705 19.803l9.291 11.084v-18.952l-9.291 7.868zM2.004 11.935v18.952l9.291-11.084-9.291-7.868z"/></svg>`
            };

            const BATCH_SIZE = 200;
            const MILLISECONDS_IN_HOUR = 60 * 60 * 1000;
            const API_RETRY_DELAY = 3000;
            const MAX_API_RETRIES = 2;

            let notifications = GM_getValue(STORAGE_KEYS.NOTIFICATIONS, []);
            let isPanelOpen = false;
            let updateInProgress = false;
            let positionCheckInterval;
            let mutationObserver;

            function runOneTimeMigration() {
                if (GM_getValue('USE_Sledilka_ownedChecked') !== undefined) {
                    GM_deleteValue('USE_Sledilka_ownedChecked');
                }
                if (GM_getValue('USE_Sledilka_lastUpdate') !== undefined) {
                    GM_deleteValue('USE_Sledilka_lastUpdate');
                }
            }
            runOneTimeMigration();

            GM_addStyle(`
                .sledilka-container {
                    position: absolute;
                    visibility: hidden;
                    z-index: 999;
                    background-color: rgba(23, 26, 33, 0.9);
                    border-radius: 3px;
                    color: #c7d5e0;
                    font-family: "Motiva Sans", Sans-serif;
                    font-size: 13px;
                    line-height: 1.2;
                }

                .sledilka-button {
                    color: #c6d4df;
                    background: rgba(103, 193, 245, 0.1);
                    padding: 7px 12px;
                    border-radius: 2px;
                    cursor: pointer;
                    font-size: 13px;
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    transition: all 0.2s ease;
                    user-select: none;
                    -webkit-user-select: none;
                    -moz-user-select: none;
                    -ms-user-select: none;
                }

                .sledilka-button:hover {
                    background: rgba(103, 193, 245, 0.2);
                }

                .sledilka-notification-badge {
                    background: #67c1f5;
                    color: #1b2838;
                    border-radius: 3px;
                    padding: 3px 6px;
                    font-size: 14px;
                    font-weight: bold;
                    min-width: 20px;
                    text-align: center;
                    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
                }

                .sledilka-status-indicator-group {
                    display: flex;
                    gap: 4px;
                }

                .sledilka-status-indicator {
                    background: #4a5562;
                    color: #c6d4df;
                    border-radius: 3px;
                    padding: 3px 6px;
                    font-size: 12px;
                    font-weight: bold;
                    min-width: 40px;
                    text-align: center;
                    transition: all 0.3s ease;
                    cursor: help;
                }

                .status-ok {
                    background: #4a5562;
                }

                .status-warning {
                    background: #4a5562;
                }

                .status-alert1 {
                    background: #665c3a;
                    color: #ffd700;
                }

                .status-alert2 {
                    background: #804d4d;
                    color: #ffb3b3;
                }

                .status-critical {
                    background: #e60000;
                    color: #fff;
                }

                .status-unknown {
                    background: #1b2838;
                    color: #8f98a0;
                }

                .sledilka-panel {
                    position: fixed;
                    right: 132px;
                    top: 50px;
                    background: #1b2838;
                    border: 1px solid #67c1f5;
                    width: 550px;
                    max-height: 70vh;
                    overflow-y: auto;
                    z-index: 9999;
                    box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
                    display: none;
                    flex-direction: column;
                }

                .sledilka-panel-header {
                    padding: 12px 15px;
                    background: #171a21;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    flex-shrink: 0;
                    border-bottom: 1px solid #2a475e;
                }

                .sledilka-panel-title {
                    font-size: 16px;
                    font-weight: 500;
                    color: #67c1f5;
                }

                .sledilka-panel-controls {
                    display: flex;
                    gap: 5px;
                    align-items: center;
                }

                .sledilka-panel-controls button {
                    background: rgba(30, 45, 60, 0.7);
                    border: none;
                    color: #c6d4df;
                    padding: 6px 10px;
                    cursor: pointer;
                    border-radius: 2px;
                    font-size: 12px;
                    font-weight: 400;
                    text-transform: uppercase;
                    letter-spacing: 0.5px;
                    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
                    transition: background 0.2s ease, box-shadow 0.2s ease;
                    display: inline-flex;
                    align-items: center;
                    gap: 4px;
                }

                .sledilka-panel-controls button:hover:not(:disabled) {
                    background: rgba(40, 60, 80, 0.9);
                    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
                }

                .sledilka-panel-controls button:active:not(:disabled) {
                    background: rgba(30, 45, 60, 0.6);
                    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
                    transform: translateY(1px);
                }

                .sledilka-panel-controls button:disabled {
                    opacity: 0.5;
                    cursor: not-allowed;
                }

                .sledilka-panel-controls button svg {
                    width: 16px;
                    height: 16px;
                }

                .sledilka-settings-container {
                    position: relative;
                }

                .sledilka-settings-btn {
                    padding: 6px;
                }

                .sledilka-settings-dropdown {
                    display: none;
                    position: fixed;
                    background-color: #171a21;
                    border: 1px solid #2a475e;
                    border-radius: 3px;
                    padding: 10px;
                    z-index: 10000;
                    width: 250px;
                    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
                }

                .sledilka-settings-dropdown label {
                    display: block;
                    margin-bottom: 5px;
                    color: #c6d4df;
                    font-size: 13px;
                    cursor: pointer;
                }

                .sledilka-settings-dropdown label.disabled {
                    color: #5c626a;
                    cursor: default;
                }

                .sledilka-settings-dropdown input {
                    margin-right: 5px;
                    vertical-align: middle;
                    accent-color: #67c1f5;
                }

                #sledilkaLibrarySubSettings {
                    padding-left: 20px;
                    margin-top: 5px;
                    border-top: 1px solid #2a475e;
                    padding-top: 5px;
                }

                .sledilka-panel-content {
                    flex-grow: 1;
                    overflow-y: auto;
                    scrollbar-width: thin;
                    scrollbar-color: #4b6f9c #1b2838;
                }

                .sledilka-panel-content::-webkit-scrollbar {
                    width: 6px;
                }

                .sledilka-panel-content::-webkit-scrollbar-track {
                    background: #1b2838;
                }

                .sledilka-panel-content::-webkit-scrollbar-thumb {
                    background-color: #4b6f9c;
                    border-radius: 3px;
                }

                .sledilka-notification-item {
                    padding: 12px 15px;
                    border-bottom: 1px solid #2a475e;
                    position: relative;
                    transition: opacity 0.3s;
                }

                .sledilka-notification-content {
                    display: flex;
                    gap: 12px;
                }

                .sledilka-notification-image {
                    width: 80px;
                    height: 45px;
                    object-fit: cover;
                    flex-shrink: 0;
                    border-radius: 2px;
                }

                .sledilka-notification-text {
                    flex-grow: 1;
                    padding-right: 30px;
                    font-size: 13px;
                }

                .sledilka-notification-game-title {
                    color: #66c0f4;
                    font-weight: bold;
                    text-decoration: none;
                    display: block;
                    margin-bottom: 4px;
                    font-size: 14px;
                }

                .sledilka-notification-type {
                    font-size: 11px;
                    color: #8f98a0;
                    margin-bottom: 4px;
                    text-transform: uppercase;
                }

                .sledilka-notification-details {
                    color: #c6d4df;
                    margin-bottom: 4px;
                    line-height: 1.4;
                }

                .sledilka-notification-timestamp {
                    font-size: 11px;
                    color: #556772;
                }

                .sledilka-notification-unread {
                    background: rgba(102, 192, 244, 0.1);
                }

                .sledilka-notification-controls {
                    position: absolute;
                    right: 10px;
                    top: 10px;
                    display: flex;
                    gap: 8px;
                }

                .sledilka-notification-control {
                    cursor: pointer;
                    width: 18px;
                    height: 18px;
                    opacity: 0.7;
                    transition: opacity 0.2s;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }

                .sledilka-notification-control:hover {
                    opacity: 1;
                }

                .sledilka-delete-btn {
                    color: #6C7781;
                    font-size: 16px;
                    font-weight: bold;
                    line-height: 1;
                    transition: color 0.2s ease, transform 0.1s ease;
                }

                .sledilka-delete-btn:hover {
                    color: #8F98A0;
                }

                .sledilka-delete-btn:active {
                    color: #800000;
                    transform: scale(0.9);
                }

                .sledilka-loading-indicator,
                .sledilka-error-indicator {
                    color: #67c1f5;
                    text-align: center;
                    padding: 10px;
                    font-size: 13px;
                }

                .sledilka-error-indicator {
                    color: #ff4747;
                }

                .sledilka-progress-bar {
                    height: 4px;
                    background-color: #2a475e;
                    width: 100%;
                    margin-top: -1px;
                }

                .sledilka-progress-bar-inner {
                    height: 100%;
                    width: 0%;
                    background-color: #67c1f5;
                    transition: width 0.3s ease;
                }

                .calendar-wtmodal.active {
                    display: flex;
                    flex-direction: column;
                }

                .calendar-wtmodal {
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    width: 80%;
                    height: 80vh;
                    background: #1b2838;
                    border: 1px solid #67c1f5;
                    box-shadow: 0 0 30px rgba(0, 0, 0, 0.7);
                    z-index: 100000;
                    display: none;
                    padding: 20px;
                    overflow: hidden;
                }

                .calendar-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding-bottom: 15px;
                    border-bottom: 1px solid #2a475e;
                    margin-bottom: 15px;
                }

                .calendar-title {
                    color: #67c1f5;
                    font-size: 25px;
                }

                .calendar-close {
                    cursor: pointer;
                    color: #8f98a0;
                    font-size: 54px;
                    padding: 5px;
                }

                .calendar-close:hover {
                    color: #67c1f5;
                }

                .calendar-content {
                    flex-grow: 1;
                    overflow-y: auto;
                    padding-right: 10px;
                    scrollbar-width: thin;
                    scrollbar-color: #4b6f9c #1b2838;
                }

                .calendar-content::-webkit-scrollbar {
                    width: 6px;
                }

                .calendar-content::-webkit-scrollbar-track {
                    background: #1b2838;
                }

                .calendar-content::-webkit-scrollbar-thumb {
                    background-color: #4b6f9c;
                    border-radius: 3px;
                }

                .calendar-month {
                    margin-bottom: 30px;
                }

                .month-header {
                    color: #67c1f5;
                    font-size: 24px;
                    margin-bottom: 15px;
                }

                .calendar-grid {
                    display: grid;
                    grid-template-columns: repeat(7, 1fr);
                    gap: 2px;
                    font-size: 14px;
                    font-weight: 500;
                }

                .calendar-grid>div:not(.calendar-day) {
                    padding: 10px 0;
                    background: #1b2838;
                    color: #67c1f5;
                    border-bottom: 2px solid #67c1f5;
                    text-transform: uppercase;
                    text-align: center;
                }

                .calendar-day {
                    background: #2a475e;
                    min-height: 69px;
                    padding: 20px 5px 5px 5px;
                    position: relative;
                    display: flex;
                    flex-direction: column;
                    gap: 3px;
                }

                .day-number {
                    position: absolute;
                    top: 3px;
                    right: 5px;
                    color: #8f98a0;
                    font-size: 14px;
                    z-index: 100003
                }

                .calendar-game {
                    display: flex;
                    position: relative;
                    padding-bottom: 8px;
                    align-items: center;
                    margin: 5px 0;
                    padding: 5px;
                    background: rgba(42, 71, 94, 0.5);
                    border-radius: 3px;
                    transition: background 0.2s;
                    text-decoration: none !important;
                    color: inherit;
                }

                .calendar-game:not(:last-child)::after {
                    content: "";
                    position: absolute;
                    bottom: -7px;
                    left: 0;
                    right: 0;
                    height: 1px;
                    background: linear-gradient(90deg, transparent 0%, rgba(103, 193, 245, 0.3) 20%, rgba(103, 193, 245, 0.4) 50%, rgba(103, 193, 245, 0.3) 80%, transparent 100%);
                    margin-top: 8px;
                }

                .calendar-game-approximate .calendar-game-title {
                    color: #FFD580 !important;
                    opacity: 0.9;
                }

                .calendar-game:hover {
                    background: rgba(67, 103, 133, 0.5);
                }

                .calendar-game-image {
                    width: 100px;
                    height: 45px;
                    object-fit: cover;
                    margin-right: 10px;
                    flex-shrink: 0;
                    border-radius: 2px;
                }

                .calendar-game-title {
                    color: #c6d4df;
                    font-size: 13px;
                    line-height: 1.2;
                }

                .load-more-months {
                    text-align: center;
                    padding: 15px;
                }

                .load-more-btn {
                    background: rgba(103, 193, 245, 0.1);
                    color: #67c1f5;
                    border: none;
                    padding: 10px 20px;
                    cursor: pointer;
                    border-radius: 3px;
                }

                .load-more-btn:hover {
                    background: rgba(103, 193, 245, 0.2);
                }

                .wt-tooltip {
                    display: flex !important;
                    position: relative;
                }

                .wt-tooltip .wt-tooltiptext {
                    visibility: hidden;
                    width: 220px;
                    background-color: #171a21;
                    color: #c6d4df;
                    text-align: center;
                    border-radius: 3px;
                    padding: 12px;
                    position: absolute;
                    z-index: 1;
                    left: 100%;
                    margin-left: 2px;
                    opacity: 0;
                    transition: opacity 0.3s;
                    border: 1px solid #67c1f5;
                }

                .wt-tooltip:hover .wt-tooltiptext {
                    visibility: visible;
                    opacity: 1;
                }

                .sledilka-storage-modal {
                    display: none;
                    position: fixed;
                    z-index: 100001;
                    left: 0;
                    top: 0;
                    width: 100%;
                    height: 100%;
                    overflow: auto;
                    background-color: rgba(0, 0, 0, 0.7);
                    backdrop-filter: blur(3px);
                }

                .sledilka-storage-modal-content {
                    background-color: #1f2c3a;
                    margin: 15% auto;
                    padding: 25px;
                    border: 1px solid #67c1f5;
                    width: 80%;
                    max-width: 500px;
                    border-radius: 5px;
                    text-align: center;
                    position: relative;
                }

                .sledilka-storage-modal-close {
                    color: #aaa;
                    position: absolute;
                    top: 10px;
                    right: 15px;
                    font-size: 28px;
                    font-weight: bold;
                    cursor: pointer;
                }

                .sledilka-storage-modal-close:hover {
                    color: #fff;
                }

                .sledilka-storage-modal h3 {
                    margin-top: 0;
                    color: #67c1f5;
                    font-size: 18px;
                    margin-bottom: 20px;
                }

                .sledilka-storage-modal button {
                    background-color: #4a5562;
                    color: #c6d4df;
                    border: 1px solid #67c1f5;
                    padding: 12px 20px;
                    margin: 10px;
                    cursor: pointer;
                    border-radius: 3px;
                    font-size: 14px;
                    transition: background-color 0.2s;
                    min-width: 200px;
                }

                .sledilka-storage-modal button:hover {
                    background-color: #5a6978;
                }
                `);

                function retryPositionCheck() {
                    if (positionCheckInterval) clearInterval(positionCheckInterval);
                    positionCheckInterval = setInterval(createSledilkaUI.positionButtonSafely, 300);
                    setTimeout(() => {
                        if (positionCheckInterval) clearInterval(positionCheckInterval);
                    }, 10000);
                }

                function stopPositionTracking() {
                    if (positionCheckInterval) {
                        clearInterval(positionCheckInterval);
                        positionCheckInterval = null;
                    }
                }

                function setupMutationObserver(target) {
                    if (mutationObserver) mutationObserver.disconnect();
                    mutationObserver = new MutationObserver((mutations) => {
                        let needsUpdate = mutations.some(mutation => {
                            return mutation.type === 'attributes' ||
                                mutation.addedNodes.length > 0 ||
                                mutation.removedNodes.length > 0;
                        });
                        if (needsUpdate) {
                            if (typeof createSledilkaUI.positionButtonSafely === 'function') {
                                createSledilkaUI.positionButtonSafely();
                            }
                        }
                    });
                    if (target) {
                        mutationObserver.observe(target, {
                            childList: true,
                            subtree: true,
                            attributes: true,
                            attributeFilter: ['style', 'class']
                        });
                    }
                }

                function createSledilkaUI() {
                    const initialGlobalActionsContainer = document.getElementById('global_actions');
                    if (!initialGlobalActionsContainer) { return; }
                    const initialAvatarLink = initialGlobalActionsContainer.querySelector('a.user_avatar');
                    if (!initialAvatarLink) { return; }
                    if (document.querySelector('.sledilka-container')) { return; }

                    const updateSettings = GM_getValue(STORAGE_KEYS.UPDATE_SETTINGS, {
                        wishlist: true,
                        library: true,
                        recheckRussian: true,
                        recheckPartial: false
                    });

                    const container = $(`
                        <div class="sledilka-container">
                            <div class="sledilka-button">
                                <span>Наблюдатель</span>
                                <div class="sledilka-status-indicator-group">
                                     <div class="sledilka-status-indicator sledilka-status-wishlist status-unknown" title="Время обновления списка желаемого">Ж:??</div>
                                     <div class="sledilka-status-indicator sledilka-status-library status-unknown" title="Время обновления библиотеки">Б:??</div>
                                </div>
                                <div class="sledilka-notification-badge">${getUnreadCount()}</div>
                            </div>
                            <div class="sledilka-panel">
                                 <div class="sledilka-panel-header">
                                    <div class="sledilka-panel-title">Уведомления</div>
                                    <div class="sledilka-panel-controls">
                                        <div class="sledilka-settings-container">
                                            <button class="sledilka-settings-btn" title="Настройки обновления">${settingsIcon}</button>
                                            <div class="sledilka-settings-dropdown">
                                                <label><input type="checkbox" id="sledilkaUpdateWishlist" ${updateSettings.wishlist ? 'checked' : ''}> Список желаемого</label>
                                                <label><input type="checkbox" id="sledilkaUpdateLibrary" ${updateSettings.library ? 'checked' : ''}> Библиотека</label>
                                                <div id="sledilkaLibrarySubSettings">
                                                    <label><input type="checkbox" id="sledilkaRecheckRussian" ${updateSettings.recheckRussian ? 'checked' : ''}> Перепроверять игры с русским</label>
                                                    <label id="sledilkaRecheckPartialLabel"><input type="checkbox" id="sledilkaRecheckPartial" ${updateSettings.recheckPartial ? 'checked' : ''}> ...только без полной локализации</label>
                                                </div>
                                            </div>
                                        </div>
                                        <button class="sledilka-refresh-btn">⟳ Обновить</button>
                                        <button class="sledilka-clear-btn">× Очистить</button>
                                        <button class="sledilka-calendar-btn">${calendarIcon}</button>
                                        <button class="sledilka-storage-btn">${storageIcon}</button>
                                    </div>
                                </div>
                                 <div class="sledilka-progress-bar"><div class="sledilka-progress-bar-inner"></div></div>
                                 <div class="sledilka-panel-content"></div>
                            </div>
                        </div>`);
                    initialGlobalActionsContainer.appendChild(container[0]);

                    function positionButtonSafely() {
                        const currentGlobalActionsContainer = document.getElementById('global_actions');
                        if (!currentGlobalActionsContainer || !container[0] || !container[0].isConnected) { stopPositionTracking(); return; }
                        const currentAvatarLink = currentGlobalActionsContainer.querySelector('a.user_avatar');
                        if (!currentAvatarLink) { retryPositionCheck(); return; }
                        const isVisible = (element) => {
                            if (!element) return false;
                            const rect = element.getBoundingClientRect();
                            return !(rect.width === 0 && rect.height === 0 && element.offsetWidth === 0 && element.offsetHeight === 0);
                        };
                        if (!isVisible(currentAvatarLink)) { retryPositionCheck(); return; }
                        const avatarRect = currentAvatarLink.getBoundingClientRect();
                        const globalActionsRect = currentGlobalActionsContainer.getBoundingClientRect();
                        const sledilkaViewportTop = avatarRect.top;
                        const sledilkaViewportLeft = avatarRect.right + 45;
                        const sledilkaContainerTop = sledilkaViewportTop - globalActionsRect.top;
                        const sledilkaContainerLeft = sledilkaViewportLeft - globalActionsRect.left;
                        container.css({ top: sledilkaContainerTop + 'px', left: sledilkaContainerLeft + 'px', visibility: 'visible' });
                        setTimeout(() => {
                            if (container[0] && container[0].isConnected && currentAvatarLink && currentAvatarLink.isConnected) {
                                const postRect = container[0].getBoundingClientRect();
                                const liveAvatarRect = currentAvatarLink.getBoundingClientRect();
                                if (postRect.left < liveAvatarRect.right) {
                                    container.css('left', (sledilkaContainerLeft + 50) + 'px');
                                }
                            }
                        }, 100);
                        stopPositionTracking();
                        setupMutationObserver(currentGlobalActionsContainer);
                    }
                    createSledilkaUI.positionButtonSafely = positionButtonSafely;
                    setTimeout(positionButtonSafely, 700);

                    const panel = container.find('.sledilka-panel');
                    container.find('.sledilka-button').on('click', function(e) { e.stopPropagation(); togglePanel(); });
                    container.find('.sledilka-refresh-btn').on('click', (e) => { e.stopPropagation(); if (!updateInProgress) updateData(); });
                    container.find('.sledilka-clear-btn').on('click', (e) => {
                        e.stopPropagation();
                        if (confirm("Вы уверены, что хотите очистить ВСЕ уведомления?")) {
                            notifications = [];
                            GM_setValue(STORAGE_KEYS.NOTIFICATIONS, notifications);
                            updateNotificationPanel();
                            updateBadge();
                            showInfoIndicator("Все уведомления очищены.");
                        }
                    });
                    container.find('.sledilka-calendar-btn').on('click', (e) => { e.stopPropagation(); showCalendarModal(); });
                    container.find('.sledilka-storage-btn').on('click', (e) => { e.stopPropagation(); showStorageModal(); });

                    const settingsBtn = container.find('.sledilka-settings-btn');
                    const settingsDropdown = container.find('.sledilka-settings-dropdown');
                    const libCheck = $('#sledilkaUpdateLibrary');
                    const recheckRuCheck = $('#sledilkaRecheckRussian');
                    const recheckPartialCheck = $('#sledilkaRecheckPartial');
                    const recheckPartialLabel = $('#sledilkaRecheckPartialLabel');
                    const libSubSettings = $('#sledilkaLibrarySubSettings');

                    function toggleSubSettings() {
                        const libIsChecked = libCheck.is(':checked');
                        libSubSettings.toggle(libIsChecked);
                        if (!libIsChecked) {
                            recheckRuCheck.prop('disabled', true);
                            recheckPartialCheck.prop('disabled', true);
                            recheckPartialLabel.addClass('disabled');
                        } else {
                            recheckRuCheck.prop('disabled', false);
                            togglePartialRecheckOption();
                        }
                    }

                    function togglePartialRecheckOption() {
                        const recheckRuIsChecked = recheckRuCheck.is(':checked');
                        if (recheckRuIsChecked || !libCheck.is(':checked')) {
                            recheckPartialCheck.prop('disabled', true);
                            recheckPartialCheck.prop('checked', false);
                            recheckPartialLabel.addClass('disabled');
                        } else {
                            recheckPartialCheck.prop('disabled', false);
                            recheckPartialLabel.removeClass('disabled');
                        }
                    }

                    settingsBtn.on('click', function(e) {
                        e.stopPropagation();
                        if (settingsDropdown.is(':visible')) {
                            settingsDropdown.hide();
                        } else {
                            const btnRect = this.getBoundingClientRect();
                            const dropdownWidth = settingsDropdown.outerWidth();
                            settingsDropdown.css({
                                top: (btnRect.bottom + 5) + 'px',
                                left: (btnRect.right - dropdownWidth) + 'px'
                            }).show();
                        }
                    });

                    settingsDropdown.on('click', function(e) {
                        e.stopPropagation();
                    });

                    $('#sledilkaUpdateWishlist, #sledilkaUpdateLibrary, #sledilkaRecheckRussian, #sledilkaRecheckPartial').on('change', function() {
                        toggleSubSettings();
                        const newSettings = {
                            wishlist: $('#sledilkaUpdateWishlist').is(':checked'),
                            library: $('#sledilkaUpdateLibrary').is(':checked'),
                            recheckRussian: $('#sledilkaRecheckRussian').is(':checked'),
                            recheckPartial: $('#sledilkaRecheckPartial').is(':checked')
                        };
                        GM_setValue(STORAGE_KEYS.UPDATE_SETTINGS, newSettings);
                    });

                    toggleSubSettings();

                    updateNotificationPanel();
                    $(document).on('click', (e) => {
                         const $target = $(e.target);
                         if (isPanelOpen && panel.is(":visible")) {
                             if (!$target.closest('.sledilka-container').length) {
                                 togglePanel(false);
                             }
                         }
                         if(settingsDropdown.is(':visible')) {
                             if (!$target.closest('.sledilka-settings-container').length) {
                                 settingsDropdown.hide();
                             }
                         }
                    });
                }

                function togglePanel() {
                    updateStatusIndicator();
                    const panel = $('.sledilka-panel');
                    panel.toggle();
                    isPanelOpen = !isPanelOpen;
                    if (isPanelOpen) {
                        panel.css('display', 'flex');
                        updateBadge();
                        updateNotificationPanel();
                    }
                }

                function showLoadingIndicator(message = "Обновление данных...") {
                    const panelContent = $('.sledilka-panel-content');
                    panelContent.find('.sledilka-loading-indicator, .sledilka-error-indicator').remove();
                    panelContent.prepend($(`<div class="sledilka-loading-indicator">${message} <span class="spinner"></span></div>`));
                }

                function removeLoadingIndicator() {
                    $('.sledilka-panel-content .sledilka-loading-indicator').remove();
                }

                function showErrorIndicator(message) {
                    const panelContent = $('.sledilka-panel-content');
                    panelContent.find('.sledilka-loading-indicator, .sledilka-error-indicator').remove();
                    const error = $(`<div class="sledilka-error-indicator">${message}</div>`);
                    panelContent.prepend(error);
                    setTimeout(() => error.remove(), 8000);
                }

                function showInfoIndicator(message) {
                    const panelContent = $('.sledilka-panel-content');
                    panelContent.find('.sledilka-loading-indicator, .sledilka-error-indicator').remove();
                    const info = $(`<div class="sledilka-loading-indicator" style="color: #67c1f5;">${message}</div>`);
                    panelContent.prepend(info);
                    setTimeout(() => info.remove(), 4000);
                }

                function updateProgressBar(percentage) {
                    const progressBar = $('.sledilka-progress-bar');
                    const progressBarInner = progressBar.find('.sledilka-progress-bar-inner');
                    if (percentage > 0 && percentage <= 100) {
                        progressBar.show();
                        progressBarInner.css('width', `${percentage}%`);
                    } else {
                        progressBar.hide();
                        progressBarInner.css('width', '0%');
                    }
                }

                function getNotificationType(notification) {
                    if (notification.source === 'wishlist') {
                         if ('oldDate' in notification) return 'wishlist_date';
                         if (notification.changeType === 'ea_status') return 'wishlist_ea';
                         if (notification.changeType === 'ru_lang') return 'wishlist_ru';
                    }
                    if (notification.source === 'library') {
                         if (notification.changeType === 'ea_status') return 'owned_ea';
                         if (notification.changeType === 'ru_lang') return 'owned_ru';
                    }
                    if ('oldDate' in notification) return 'wishlist_date';
                    if (notification.changeType === 'ea_status') return 'owned_ea';
                    if (notification.changeType === 'ru_lang') return 'owned_ru';
                    return 'unknown';
                }

                function getNotificationTitle(type) {
                     switch (type) {
                        case 'wishlist_date': return 'Желаемое (Дата выхода)';
                        case 'wishlist_ea': return 'Желаемое (Ранний доступ)';
                        case 'wishlist_ru': return 'Желаемое (Русский язык)';
                        case 'owned_ea': return 'Библиотека (Ранний доступ)';
                        case 'owned_ru': return 'Библиотека (Русский язык)';
                        default: return 'Уведомление';
                    }
                }

                function getNotificationDetailsHTML(notification, type) {
                    if (type.endsWith('_ru')) {
                        const changeDetails = notification.ruChangeDetails;
                        if (!changeDetails) return 'Изменение в локализации.';

                        const added = [], removed = [];
                        const langMap = { supported: 'Интерфейс', full_audio: 'Озвучка', subtitles: 'Субтитры' };

                        for (const key in changeDetails.added) { if (changeDetails.added[key]) added.push(langMap[key]); }
                        for (const key in changeDetails.removed) { if (changeDetails.removed[key]) removed.push(langMap[key]); }

                        const oldHasAny = Object.values(changeDetails.oldState).some(v => v);
                        const newHasAny = Object.values(changeDetails.newState).some(v => v);

                        let parts = [];
                        if (added.length > 0 && removed.length > 0) {
                            parts.push(`Изменения в локализации:<br><b>Добавлено:</b> ${added.join(', ')}<br><b>Убрано:</b> ${removed.join(', ')}`);
                        } else if (added.length > 0) {
                            if (oldHasAny) {
                                 parts.push(`К русскому языку добавлено:<br><b>${added.join(' + ')}</b>`);
                            } else {
                                 parts.push(`Появился русский язык:<br><b>${added.join(' + ')}</b>`);
                            }
                        } else if (removed.length > 0) {
                            if (newHasAny) {
                                 parts.push(`Локализация урезана:<br><b>Убрано: ${removed.join(', ')}</b>`);
                            } else {
                                 parts.push(`<b>Русский язык удален из игры.</b>`);
                            }
                        }
                        return parts.join('<br>');

                    } else {
                         switch (type) {
                            case 'wishlist_date':
                                return `Дата выхода изменилась:<br>
                                             <span class="old-date">${formatDate(notification.oldDate)}</span> →
                                             <span class="new-date">${formatDate(notification.newDate)}</span>`;
                            case 'wishlist_ea':
                            case 'owned_ea':
                                return `Игра вышла из раннего доступа!`;
                            default:
                                return 'Детали неизвестны';
                        }
                    }
                }

                function updateNotificationPanel() {
                    const panelContent = $('.sledilka-panel-content');
                    if (!panelContent.length) return;
                    panelContent.find('.sledilka-notification-item, .sledilka-loading-indicator, .sledilka-error-indicator').remove();
                    $('.sledilka-panel-title').text(`Уведомления (${notifications.length})`);
                    notifications.sort((a, b) => {
                        if (a.read === b.read) {
                            return b.timestamp - a.timestamp;
                        }
                        return a.read ? 1 : -1;
                    });
                    if (notifications.length === 0) {
                        panelContent.append('<div class="sledilka-loading-indicator" style="color: #8f98a0;">Нет новых уведомлений</div>');
                        return;
                    }
                    notifications.slice(0, 5000).forEach((notification, index) => {
                        const notificationType = getNotificationType(notification);
                        const imageUrl = notification.header ?
                            `https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/${notification.appid}/${notification.header}` :
                            `https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/${notification.appid}/header.jpg`;
                        const item = $(`
                            <div class="sledilka-notification-item ${notification.read ? '' : 'sledilka-notification-unread'}" data-index="${index}">
                                <div class="sledilka-notification-controls">
                                    <div class="sledilka-toggle-read-btn sledilka-notification-control" title="${notification.read ? 'Пометить как непрочитанное' : 'Пометить как прочитанное'}">
                                        ${notification.read ? envelopeIcons.read : envelopeIcons.unread}
                                    </div>
                                    <div class="sledilka-delete-btn sledilka-notification-control" title="Удалить уведомление">X</div>
                                </div>
                                <div class="sledilka-notification-content">
                                    <a href="https://store.steampowered.com/app/${notification.appid}" target="_blank">
                                        <img src="${imageUrl}"
                                             class="sledilka-notification-image" loading="lazy"
                                             onerror="this.onerror=null; this.src='https://via.placeholder.com/80x45?text=No+Img'; this.style.objectFit='contain';">
                                    </a>
                                    <div class="sledilka-notification-text">
                                        <div class="sledilka-notification-type">${getNotificationTitle(notificationType)}</div>
                                        <a href="https://store.steampowered.com/app/${notification.appid}"
                                           class="sledilka-notification-game-title" target="_blank">
                                            ${notification.name || `Игра #${notification.appid}`}
                                        </a>
                                        <div class="sledilka-notification-details">
                                            ${getNotificationDetailsHTML(notification, notificationType)}
                                        </div>
                                        <div class="sledilka-notification-timestamp">
                                            Обнаружено: ${new Date(notification.timestamp).toLocaleString()}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        `);
                        item.find('.sledilka-delete-btn').on('click', (e) => {
                            e.stopPropagation();
                            const itemIndex = parseInt($(e.target).closest('.sledilka-notification-item').data('index'));
                            if (!isNaN(itemIndex) && itemIndex >= 0 && itemIndex < notifications.length) {
                                notifications.splice(itemIndex, 1);
                                GM_setValue(STORAGE_KEYS.NOTIFICATIONS, notifications);
                                item.fadeOut(300, () => {
                                    updateNotificationPanel();
                                    updateBadge();
                                });
                            } else {
                                console.error("Ошибка удаления: неверный индекс", itemIndex);
                            }
                        });
                        item.find('.sledilka-toggle-read-btn').on('click', (e) => {
                            e.stopPropagation();
                            const itemIndex = parseInt($(e.target).closest('.sledilka-notification-item').data('index'));
                            if (!isNaN(itemIndex) && itemIndex >= 0 && itemIndex < notifications.length) {
                                notifications[itemIndex].read = !notifications[itemIndex].read;
                                GM_setValue(STORAGE_KEYS.NOTIFICATIONS, notifications);
                                item.toggleClass('sledilka-notification-unread', !notifications[itemIndex].read);
                                $(e.currentTarget).html(notifications[itemIndex].read ? envelopeIcons.read : envelopeIcons.unread);
                                $(e.currentTarget).attr('title', notifications[itemIndex].read ? 'Пометить как непрочитанное' : 'Пометить как прочитанное');
                                updateBadge();
                            } else {
                                console.error("Ошибка чтения/нечтения: неверный индекс", itemIndex);
                            }
                        });
                        panelContent.append(item);
                    });
                }

                function formatDate(dateInfo) {
                    if (!dateInfo || dateInfo.value === 'Не указана') return 'Не указано';
                    const value = dateInfo.value;
                    const displayType = dateInfo.displayType;
                    if (typeof value === 'string' && isNaN(value)) {
                        return value;
                    }
                    const ts = formatTimestamp(value);
                    if (typeof ts === 'string') return ts;
                    const date = new Date(ts * 1000);
                    const monthNames = ["январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"];
                    const quarter = Math.floor(date.getMonth() / 3) + 1;
                    if (displayType) {
                        switch (displayType) {
                            case 'date_month':
                                return `${monthNames[date.getMonth()]} ${date.getFullYear()}`;
                            case 'date_quarter':
                                return `Q${quarter} ${date.getFullYear()}`;
                            case 'date_year':
                                return `${date.getFullYear()}`;
                            case 'date_full':
                            default:
                                return date.toLocaleDateString('ru-RU', {
                                    day: 'numeric',
                                    month: 'long',
                                    year: 'numeric'
                                });
                        }
                    }
                    return date.toLocaleDateString('ru-RU', {
                        day: 'numeric',
                        month: 'long',
                        year: 'numeric'
                    });
                }

                function formatTimestamp(ts) {
                    if (!ts) return ts;
                    if (typeof ts === 'string') {
                        if (/^\d{4}-\d{2}-\d{2}$/.test(ts)) {
                            return Math.floor(new Date(ts).getTime() / 1000);
                        }
                        return ts;
                    }
                    return typeof ts === 'number' ? ts : parseInt(ts, 10);
                }

                function updateStatusIndicator() {
                     const updateTime = (key, selector, prefix) => {
                        const lastUpdate = GM_getValue(key, 0);
                        const indicator = $(selector);
                        indicator.removeClass('status-ok status-warning status-alert1 status-alert2 status-critical status-unknown');
                        if (!lastUpdate) {
                            indicator.text(`${prefix}:??`).addClass('status-unknown').attr('title', 'Данные ни разу не обновлялись');
                            return;
                        }
                        const hoursPassed = (Date.now() - lastUpdate) / MILLISECONDS_IN_HOUR;
                        const days = Math.floor(hoursPassed / 24);
                        const hours = Math.floor(hoursPassed % 24);
                        indicator.attr('title', `Данные не обновлялись: ${days} д. и ${hours} ч.`);

                        if (hoursPassed < 12) indicator.text(`${prefix}:OK`).addClass('status-ok');
                        else if (hoursPassed < 24) indicator.text(`${prefix}:OK?`).addClass('status-warning');
                        else if (hoursPassed < 48) indicator.text(`${prefix}:!`).addClass('status-alert1');
                        else if (hoursPassed < 72) indicator.text(`${prefix}:!!`).addClass('status-alert2');
                        else indicator.text(`${prefix}:!!!`).addClass('status-critical');
                    };

                    updateTime(STORAGE_KEYS.LAST_UPDATE_WISHLIST, '.sledilka-status-wishlist', 'Ж');
                    updateTime(STORAGE_KEYS.LAST_UPDATE_LIBRARY, '.sledilka-status-library', 'Б');
                }

                function updateBadge() {
                    $('.sledilka-notification-badge').text(getUnreadCount());
                }

                function getUnreadCount() {
                    return notifications.filter(n => !n.read).length;
                }

                async function getUserData() {
                    return new Promise(resolve => {
                        GM_xmlhttpRequest({
                            method: 'GET',
                            url: 'https://store.steampowered.com/dynamicstore/userdata/?_t=' + Date.now(),
                            onload: function(response) {
                                try {
                                    const data = JSON.parse(response.responseText);
                                    resolve({
                                        wishlist: data.rgWishlist || [],
                                        owned: data.rgOwnedApps || []
                                    });
                                } catch (e) {
                                    console.error("Ошибка парсинга UserData:", e);
                                    resolve({
                                        wishlist: [],
                                        owned: []
                                    });
                                }
                            },
                            onerror: function(error) {
                                console.error("Ошибка запроса UserData:", error);
                                resolve({
                                    wishlist: [],
                                    owned: []
                                });
                            }
                        });
                    });
                }

                async function fetchGameDetails(appIds, includeLanguages = false) {
                    if (!appIds || appIds.length === 0) return [];
                    const batches = [];
                    for (let i = 0; i < appIds.length; i += BATCH_SIZE) {
                        batches.push(appIds.slice(i, i + BATCH_SIZE));
                    }
                    const allDetails = [];
                    for (const batch of batches) {
                        const details = await fetchBatchDetails(batch, includeLanguages);
                        allDetails.push(...details);
                        await new Promise(resolve => setTimeout(resolve, 500));
                    }
                    return allDetails;
                }

                async function fetchBatchDetails(appIds, includeLanguages = false, retries = MAX_API_RETRIES) {
                    const requestData = {
                        ids: appIds.map(appid => ({
                            appid
                        })),
                        context: {
                            language: 'russian',
                            country_code: 'RU',
                            steam_realm: 1
                        },
                        data_request: {
                            include_assets: true,
                            include_release: true,
                            include_basic_info: true
                        }
                    };
                    if (includeLanguages) {
                        requestData.data_request.include_supported_languages = true;
                    }
                    try {
                        return await new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: 'GET',
                                url: `https://api.steampowered.com/IStoreBrowseService/GetItems/v1?input_json=${encodeURIComponent(JSON.stringify(requestData))}`,
                                timeout: 15000,
                                onload: function(response) {
                                    try {
                                        if (response.status >= 200 && response.status < 400) {
                                            const data = JSON.parse(response.responseText);
                                            resolve(data.response?.store_items || []);
                                        } else {
                                            console.warn(`API Request Failed (Status: ${response.status}) for batch:`, appIds);
                                            reject(new Error(`API Status ${response.status}`));
                                        }
                                    } catch (e) {
                                        console.error('Error parsing response:', e, response.responseText);
                                        reject(new Error('Parse Error'));
                                    }
                                },
                                onerror: (error) => {
                                    console.error('API Request Network Error:', error);
                                    reject(new Error('Network Error'));
                                },
                                ontimeout: () => {
                                    console.warn('API Request Timeout for batch:', appIds);
                                    reject(new Error('Timeout'));
                                }
                            });
                        });
                    } catch (error) {
                        if (retries > 0) {
                            console.log(`Retrying API request for batch (Retries left: ${retries})...`);
                            await new Promise(resolve => setTimeout(resolve, API_RETRY_DELAY));
                            return fetchBatchDetails(appIds, includeLanguages, retries - 1);
                        } else {
                            console.error(`API request failed after multiple retries for batch:`, appIds, error);
                            showErrorIndicator(`Ошибка API Steam после ${MAX_API_RETRIES+1} попыток.`);
                            return [];
                        }
                    }
                }

                function getWishlistReleaseInfo(releaseData) {
                    if (!releaseData) return {
                        date: 'Не указана',
                        type: 'unknown',
                        displayType: null
                    };
                    const displayType = releaseData.coming_soon_display || null;
                    if (releaseData.steam_release_date) return {
                        date: releaseData.steam_release_date,
                        type: 'date',
                        displayType: displayType
                    };
                    if (releaseData.custom_release_date_message) return {
                        date: releaseData.custom_release_date_message,
                        type: 'custom',
                        displayType: null
                    };
                    return {
                        date: 'Не указана',
                        type: 'unknown',
                        displayType: null
                    };
                }

                function getOwnedGameInfo(gameDetails) {
                    if (!gameDetails) return {
                        is_early_access: false,
                        ru_support: {
                            supported: false,
                            full_audio: false,
                            subtitles: false
                        }
                    };
                    const is_early_access = gameDetails.release?.is_early_access ?? false;
                    let ru_support = {
                        supported: false,
                        full_audio: false,
                        subtitles: false
                    };
                    const russianLangData = gameDetails.supported_languages?.find(lang => lang.elanguage === 8);
                    if (russianLangData) {
                        ru_support = {
                            supported: russianLangData.supported || false,
                            full_audio: russianLangData.full_audio || false,
                            subtitles: russianLangData.subtitles || false
                        };
                    }
                    return {
                        is_early_access,
                        ru_support
                    };
                }

                function compareOwnedGameInfo(oldInfo, newInfo) {
                    const changes = [];
                    if (oldInfo.is_early_access && !newInfo.is_early_access) {
                        changes.push({ type: 'ea_status', old: oldInfo.is_early_access, new: newInfo.is_early_access });
                    }

                    const oldSupport = oldInfo.ru_support || { supported: false, full_audio: false, subtitles: false };
                    const newSupport = newInfo.ru_support;

                    const added = {
                        supported: !oldSupport.supported && newSupport.supported,
                        full_audio: !oldSupport.full_audio && newSupport.full_audio,
                        subtitles: !oldSupport.subtitles && newSupport.subtitles
                    };
                    const removed = {
                        supported: oldSupport.supported && !newSupport.supported,
                        full_audio: oldSupport.full_audio && !newSupport.full_audio,
                        subtitles: oldSupport.subtitles && !newSupport.subtitles
                    };

                    const hasAdded = Object.values(added).some(v => v);
                    const hasRemoved = Object.values(removed).some(v => v);

                    if (hasAdded || hasRemoved) {
                        changes.push({
                            type: 'ru_lang',
                            details: {
                                oldState: oldSupport,
                                newState: newSupport,
                                added,
                                removed
                            }
                        });
                    }

                    return changes;
                }

                async function updateData() {
                    if (updateInProgress) {
                        showInfoIndicator("Обновление уже выполняется...");
                        return;
                    }
                    updateInProgress = true;
                    $('.sledilka-refresh-btn').prop('disabled', true);
                    const refreshBtnText = $('.sledilka-refresh-btn').contents().filter(function() { return this.nodeType === 3; });
                    if (refreshBtnText.length) refreshBtnText[0].nodeValue = ' Обновить...';

                    const updateSettings = GM_getValue(STORAGE_KEYS.UPDATE_SETTINGS, {
                        wishlist: true,
                        library: true,
                        recheckRussian: true,
                        recheckPartial: false
                    });
                    if (!updateSettings.wishlist && !updateSettings.library) {
                        showInfoIndicator("Не выбрано, что обновлять. Проверьте настройки (⚙️).");
                        updateInProgress = false;
                        $('.sledilka-refresh-btn').prop('disabled', false);
                        if(refreshBtnText.length) refreshBtnText[0].nodeValue = ' Обновить';
                        return;
                    }

                    showLoadingIndicator("Получение списков игр...");
                    updateProgressBar(1);
                    try {
                        const {
                            wishlist: currentWishlistAppIds,
                            owned: currentOwnedAppIds
                        } = await getUserData();
                        let allNewNotifications = [];

                        if(updateSettings.wishlist) {
                            const wishlistPreviousData = GM_getValue(STORAGE_KEYS.WISHLIST_GAME_DATA, {});
                            const currentWishlistDataToSave = { ...wishlistPreviousData };
                            const currentWishlistAppIdSet = new Set(currentWishlistAppIds);

                            const previouslyTrackedAppIds = Object.keys(wishlistPreviousData).map(id => parseInt(id, 10));
                            const removedAppIds = previouslyTrackedAppIds.filter(appid => !currentWishlistAppIdSet.has(appid));
                            removedAppIds.forEach(appid => {
                                delete currentWishlistDataToSave[String(appid)];
                            });

                            showLoadingIndicator(`Загрузка данных для ${currentWishlistAppIds.length} игр из желаемого...`);
                            updateProgressBar(5);

                            if (currentWishlistAppIds.length > 0) {
                                const wishlistDetails = await fetchGameDetails(currentWishlistAppIds, true);
                                updateProgressBar(25);

                                wishlistDetails.forEach(game => {
                                    if (!game || !game.appid) return;
                                    const appid = game.appid;
                                    const prevGame = wishlistPreviousData[appid];
                                    const currentRelease = getWishlistReleaseInfo(game.release);
                                    const currentGameInfo = getOwnedGameInfo(game);

                                    currentWishlistDataToSave[appid] = {
                                        name: game.name,
                                        rawRelease: game.release,
                                        releaseInfo: currentRelease,
                                        header: game.assets?.header || null,
                                        is_early_access: currentGameInfo.is_early_access,
                                        ru_support: currentGameInfo.ru_support
                                    };

                                    if (prevGame) {
                                        if (currentRelease.date !== prevGame.releaseInfo?.date || currentRelease.type !== prevGame.releaseInfo?.type || currentRelease.displayType !== prevGame.releaseInfo?.displayType) {
                                            allNewNotifications.push({ source: 'wishlist', appid: appid, name: game.name, header: game.assets?.header, oldDate: prevGame.releaseInfo ? { value: prevGame.releaseInfo.date, displayType: prevGame.releaseInfo.displayType } : { value: 'Не указана', displayType: null }, newDate: { value: currentRelease.date, displayType: currentRelease.displayType }, timestamp: Date.now(), read: false });
                                        }

                                        const hadOldStatusData = prevGame.hasOwnProperty('is_early_access') && prevGame.hasOwnProperty('ru_support');
                                        if (hadOldStatusData) {
                                            const oldGameInfo = { is_early_access: prevGame.is_early_access, ru_support: prevGame.ru_support };
                                            const statusChanges = compareOwnedGameInfo(oldGameInfo, currentGameInfo);
                                            statusChanges.forEach(change => {
                                                allNewNotifications.push({ source: 'wishlist', changeType: change.type, appid: appid, name: game.name, header: game.assets?.header, ruChangeDetails: change.type === 'ru_lang' ? change.details : undefined, timestamp: Date.now(), read: false });
                                            });
                                        }
                                    }
                                });
                            }
                            GM_setValue(STORAGE_KEYS.WISHLIST_GAME_DATA, currentWishlistDataToSave);
                            GM_setValue(STORAGE_KEYS.LAST_UPDATE_WISHLIST, Date.now());
                        }

                        if(updateSettings.library) {
                            const ownedPreviousData = GM_getValue(STORAGE_KEYS.OWNED_APPS_DATA, {});
                            const ownedCheckedSet = new Set(GM_getValue(STORAGE_KEYS.OWNED_CHECKED_V2, []));
                            const currentOwnedDataToSave = { ...ownedPreviousData };

                            let appsToCheckInLibrary = currentOwnedAppIds.filter(appid => !ownedCheckedSet.has(appid));

                            if (!updateSettings.recheckRussian) {
                                appsToCheckInLibrary = appsToCheckInLibrary.filter(appid => {
                                    const prevData = ownedPreviousData[appid];
                                    if (!prevData || !prevData.ru_support) {
                                        return true;
                                    }

                                    const hasFullSupport = prevData.ru_support.supported && prevData.ru_support.full_audio && prevData.ru_support.subtitles;
                                    const hasAnySupport = prevData.ru_support.supported || prevData.ru_support.full_audio || prevData.ru_support.subtitles;

                                    if (updateSettings.recheckPartial) {
                                        return !hasFullSupport;
                                    } else {
                                        return !hasAnySupport;
                                    }
                                });
                            }

                            const totalOwnedToCheck = appsToCheckInLibrary.length;
                            showLoadingIndicator(`Проверка ${totalOwnedToCheck} игр из библиотеки...`);

                            if (totalOwnedToCheck > 0) {
                                for (let i = 0; i < totalOwnedToCheck; i += BATCH_SIZE) {
                                    const batch = appsToCheckInLibrary.slice(i, i + BATCH_SIZE);
                                    const progress = 50 + Math.round(((i) / (totalOwnedToCheck || 1)) * 50);
                                    updateProgressBar(progress);
                                    showLoadingIndicator(`Проверка библиотеки... (${i}/${totalOwnedToCheck})`);
                                    const details = await fetchGameDetails(batch, true);
                                    details.forEach(game => {
                                        if (!game || !game.appid) return;
                                        const appid = game.appid;
                                        if (game.type !== 0 || game.visible === false) { ownedCheckedSet.add(appid); delete currentOwnedDataToSave[appid]; return; }
                                        const name = game.name || ownedPreviousData[appid]?.name || `Игра #${appid}`;
                                        if (!name || name.trim() === '' || name === `Игра #${appid}`) { ownedCheckedSet.add(appid); delete currentOwnedDataToSave[appid]; return; }

                                        const prevGameData = ownedPreviousData[appid];
                                        const currentGameInfo = getOwnedGameInfo(game);
                                        currentOwnedDataToSave[appid] = { name: name, ...currentGameInfo };

                                        if (prevGameData) {
                                            const hadOldStatusData = prevGameData.hasOwnProperty('is_early_access') && prevGameData.hasOwnProperty('ru_support');
                                            if(hadOldStatusData) {
                                                const detectedChanges = compareOwnedGameInfo(prevGameData, currentGameInfo);
                                                detectedChanges.forEach(change => allNewNotifications.push({ source: 'library', changeType: change.type, appid: appid, name: name, header: game.assets?.header, ruChangeDetails: change.type === 'ru_lang' ? change.details : undefined, timestamp: Date.now(), read: false }));
                                            }
                                        }
                                    });
                                }
                            }
                            const currentOwnedAppIdSet = new Set(currentOwnedAppIds);
                            const previouslyTrackedAppIds = Object.keys(ownedPreviousData).map(id => parseInt(id, 10));
                            const removedAppIds = previouslyTrackedAppIds.filter(appid => !currentOwnedAppIdSet.has(appid));
                            removedAppIds.forEach(appid => { delete currentOwnedDataToSave[appid]; ownedCheckedSet.delete(appid); });

                            GM_setValue(STORAGE_KEYS.OWNED_APPS_DATA, currentOwnedDataToSave);
                            GM_setValue(STORAGE_KEYS.OWNED_CHECKED_V2, Array.from(ownedCheckedSet));
                            GM_setValue(STORAGE_KEYS.LAST_UPDATE_LIBRARY, Date.now());
                        }

                        if (allNewNotifications.length > 0) {
                            notifications = [...allNewNotifications, ...notifications];
                            notifications.sort((a, b) => b.timestamp - a.timestamp);
                            notifications = notifications.slice(0, 500);
                            GM_setValue(STORAGE_KEYS.NOTIFICATIONS, notifications);
                        }

                        removeLoadingIndicator();
                        updateNotificationPanel();
                        updateBadge();
                        updateStatusIndicator();
                        updateProgressBar(100);
                        showInfoIndicator(`Обновление завершено. Новых уведомлений: ${allNewNotifications.length}.`);
                    } catch (e) {
                        console.error('Ошибка при обновлении данных:', e);
                        showErrorIndicator(`Ошибка обновления: ${e.message || 'Неизвестная ошибка'}`);
                        updateStatusIndicator();
                    } finally {
                        updateInProgress = false;
                         $('.sledilka-refresh-btn').prop('disabled', false);
                        if(refreshBtnText.length) refreshBtnText[0].nodeValue = ' Обновить';
                        setTimeout(() => updateProgressBar(0), 500);
                    }
                }

                function showCalendarModal() {
                    const gameData = GM_getValue(STORAGE_KEYS.WISHLIST_GAME_DATA, {});
                    const monthsData = getGamesByMonths(gameData);
                    const wtmodal = $(`
                         <div class="calendar-wtmodal">
                             <div class="calendar-header"> <div class="calendar-title">Календарь релизов (${Object.keys(gameData).length} игр в списке)</div> <div class="calendar-close">×</div> </div>
                             <div class="calendar-content"></div>
                         </div>`);
                    const clickHandler = (e) => {
                        if (!$(e.target).closest('.calendar-wtmodal').length) {
                            wtmodal.remove();
                            $(document).off('click', clickHandler);
                        }
                    };
                    wtmodal.find('.calendar-close').click((e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        wtmodal.remove();
                        $(document).off('click', clickHandler);
                    });
                    wtmodal.click(e => e.stopPropagation());
                    $(document).on('click', clickHandler);
                    $('body').append(wtmodal);
                    wtmodal.addClass('active');
                    let visibleMonths = 3;
                    const renderCalendar = () => {
                        const visibleData = monthsData.slice(0, visibleMonths);
                        const content = wtmodal.find('.calendar-content').empty();
                        if (monthsData.length === 0) {
                            content.append('<div style="text-align:center; padding: 30px; color: #8f98a0;">Нет игр с датой выхода в будущем в вашем списке желаемого.</div>');
                            return;
                        }
                        visibleData.forEach(({
                            month,
                            year,
                            games
                        }) => {
                            const monthDate = new Date(year, month);
                            const monthName = monthDate.toLocaleString('ru-RU', {
                                month: 'long'
                            });
                            const daysInMonth = new Date(year, month + 1, 0).getDate();
                            const firstDay = new Date(year, month, 1).getDay();
                            const adjustedFirstDay = firstDay === 0 ? 6 : firstDay - 1;
                            const monthBlock = $(`<div class="calendar-month"> <div class="month-header">${monthName} ${year}</div> <div class="calendar-grid"></div> </div>`);
                            const grid = monthBlock.find('.calendar-grid');
                            grid.append('<div>Пн</div><div>Вт</div><div>Ср</div><div>Чт</div><div>Пт</div><div>Сб</div><div>Вс</div>');
                            for (let i = 0; i < adjustedFirstDay; i++) {
                                grid.append('<div class="calendar-day"></div>');
                            }
                            for (let day = 1; day <= daysInMonth; day++) {
                                const dayGames = games.filter(g => {
                                    const releaseDate = new Date(g.releaseInfo.date * 1000);
                                    return releaseDate.getDate() === day && releaseDate.getMonth() === month && releaseDate.getFullYear() === year;
                                });
                                const dayElement = $(`<div class="calendar-day"> <div class="day-number">${day}</div> </div>`);
                                dayGames.sort((a, b) => a.name.localeCompare(b.name)).forEach(game => {
                                    const isApproximate = ['date_month', 'date_quarter', 'date_year'].includes(game.releaseInfo.displayType);
                                    const imageUrl = game.header ? `https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/${game.appid}/${game.header}` : `https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/${game.appid}/header.jpg`;
                                    const gameElement = $(`<a href="https://store.steampowered.com/app/${game.appid}" target="_blank" class="calendar-game ${isApproximate ? 'calendar-game-approximate wt-tooltip' : ''}"> <img src="${imageUrl}" class="calendar-game-image" loading="lazy" onerror="this.onerror=null; this.src='https://via.placeholder.com/100x45?text=No+Img'; this.style.objectFit='contain';"> <div class="calendar-game-title">${game.name}</div> ${isApproximate ? `<div class="wt-tooltiptext">Приблизительная дата: ${getApproximateDateText(game.releaseInfo)}</div>` : ''} </a>`);
                                    dayElement.append(gameElement);
                                });
                                grid.append(dayElement);
                            }
                            content.append(monthBlock);
                        });
                        if (visibleMonths < monthsData.length) {
                            content.append(`<div class="load-more-months"> <button class="load-more-btn">Показать ещё 3 месяца</button> </div>`);
                            content.find('.load-more-btn').click(() => {
                                visibleMonths += 3;
                                renderCalendar();
                            });
                        }
                    };
                    renderCalendar();
                }

                function getGamesByMonths(gameData) {
                    const now = new Date();
                    const currentYear = now.getFullYear();
                    const currentMonth = now.getMonth();
                    const games = Object.entries(gameData).map(([appid, game]) => ({
                            appid: parseInt(appid),
                            ...game,
                            releaseDate: game.releaseInfo?.date && typeof game.releaseInfo.date === 'number' ? new Date(game.releaseInfo.date * 1000) : null
                        }))
                        .filter(g => g.releaseDate).filter(g => {
                            const releaseYear = g.releaseDate.getFullYear();
                            const releaseMonth = g.releaseDate.getMonth();
                            return (releaseYear > currentYear) || (releaseYear === currentYear && releaseMonth >= currentMonth);
                        });
                    const monthMap = games.reduce((acc, game) => {
                        const year = game.releaseDate.getFullYear();
                        const month = game.releaseDate.getMonth();
                        const key = `${year}-${month}`;
                        if (!acc[key]) {
                            acc[key] = {
                                year,
                                month,
                                games: []
                            };
                        }
                        acc[key].games.push(game);
                        return acc;
                    }, {});
                    return Object.values(monthMap).sort((a, b) => a.year === b.year ? a.month - b.month : a.year - b.year);
                }

                function getApproximateDateText(releaseInfo) {
                    const date = new Date(releaseInfo.date * 1000);
                    const quarter = Math.floor(date.getMonth() / 3) + 1;
                    switch (releaseInfo.displayType) {
                        case 'date_month':
                            return date.toLocaleString('ru-RU', {
                                month: 'long',
                                year: 'numeric'
                            });
                        case 'date_quarter':
                            return `Q${quarter} ${date.getFullYear()}`;
                        case 'date_year':
                            return date.getFullYear().toString();
                        default:
                            return date.toLocaleDateString('ru-RU');
                    }
                }

                function showStorageModal() {
                    const modalHtml = `
                                  <div id="sledilkaStorageModal" class="sledilka-storage-modal">
                                      <div class="sledilka-storage-modal-content">
                                          <span id="sledilkaStorageCloseBtn" class="sledilka-storage-modal-close" title="Закрыть">&times;</span>
                                          <h3>Управление хранилищем</h3>
                                          <button id="clearWishlistDataBtn">Очистить данные из списка желаемого</button>
                                          <br>
                                          <button id="clearOwnedDataBtn">Очистить данные из библиотеки</button>
                                      </div>
                                  </div>`;
                    if ($('#sledilkaStorageModal').length === 0) {
                        $('body').append(modalHtml);
                    }
                    const modal = $('#sledilkaStorageModal');
                    modal.show();
                    $('#sledilkaStorageCloseBtn').off('click').on('click', () => modal.hide());
                    modal.off('click').on('click', (event) => {
                        if ($(event.target).is(modal)) {
                            modal.hide();
                        }
                    });
                    $('#clearWishlistDataBtn').off('click').on('click', () => {
                        if (confirm("Вы уверены, что хотите удалить сохраненные данные для Списка желаемого?\nЭто приведет к повторному сканированию при следующем обновлении.")) {
                            GM_deleteValue(STORAGE_KEYS.WISHLIST_GAME_DATA);
                            notifications = notifications.filter(n => !n.source || n.source !== 'wishlist');
                            GM_setValue(STORAGE_KEYS.NOTIFICATIONS, notifications);
                            alert("Данные списка желаемого очищены.");
                            modal.hide();
                            updateNotificationPanel();
                            updateBadge();
                        }
                    });
                    $('#clearOwnedDataBtn').off('click').on('click', () => {
                        if (confirm("Вы уверены, что хотите удалить сохраненные данные для Библиотеки?\nЭто приведет к ПОЛНОМУ ПОВТОРНОМУ сканированию вашей библиотеки при следующем обновлении, что может занять время.")) {
                            GM_deleteValue(STORAGE_KEYS.OWNED_APPS_DATA);
                            GM_deleteValue(STORAGE_KEYS.OWNED_CHECKED_V2);
                            alert("Данные Библиотеки очищены. Потребуется повторное сканирование.");
                            modal.hide();
                        }
                    });
                }

                function initialize() {
                    createSledilkaUI();
                    updateStatusIndicator();
                    setupMutationObserver(document.getElementById('global_actions'));
                }
                if (typeof $ !== 'undefined') {
                    $(document).ready(initialize);
                } else {
                    const checkJQuery = setInterval(() => {
                        if (typeof $ !== 'undefined') {
                            clearInterval(checkJQuery);
                            $(document).ready(initialize);
                        }
                    }, 100);
                }
            })();
        }

    // Скрипт для проверки возможности отправки подарка из списка желаемого друзьям в других странах | https://steamcommunity.com/my/wishlist/*
    if (scriptsConfig.wishlistGiftHelper && unsafeWindow.location.pathname.includes('/wishlist/')) {
        (function() {
            'use strict';

            const WGH_API_URL = "https://api.steampowered.com/IStoreBrowseService/GetItems/v1";
            const WGH_CURRENCY_API_URL = 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/';
            const WGH_BATCH_SIZE = 200;
            const WGH_INITIAL_DELAY_MS = 500;
            const WGH_REQUEST_TIMEOUT_MS = 20000;
            const WGH_GIFT_PRICE_DIFF_THRESHOLD = 0.10;
            const WGH_IMAGE_BASE_URL = 'https://shared.fastly.steamstatic.com/store_item_assets/steam/apps/';
            const WGH_COUNTRY_CURRENCY_MAP = {
                'US': {
                    name: 'U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'EU': {
                    name: 'Euro',
                    code: 3,
                    iso: 'eur'
                },
                'AR': {
                    name: 'LATAM - U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'AU': {
                    name: 'Australian Dollar',
                    code: 21,
                    iso: 'aud'
                },
                'BR': {
                    name: 'Brazilian Real',
                    code: 7,
                    iso: 'brl'
                },
                'GB': {
                    name: 'British Pound',
                    code: 2,
                    iso: 'gbp'
                },
                'CA': {
                    name: 'Canadian Dollar',
                    code: 20,
                    iso: 'cad'
                },
                'CL': {
                    name: 'Chilean Peso',
                    code: 25,
                    iso: 'clp'
                },
                'CN': {
                    name: 'Chinese Yuan',
                    code: 23,
                    iso: 'cny'
                },
                'AZ': {
                    name: 'CIS - U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'CO': {
                    name: 'Colombian Peso',
                    code: 27,
                    iso: 'cop'
                },
                'CR': {
                    name: 'Costa Rican Colon',
                    code: 40,
                    iso: 'crc'
                },
                'HK': {
                    name: 'Hong Kong Dollar',
                    code: 29,
                    iso: 'hkd'
                },
                'IN': {
                    name: 'Indian Rupee',
                    code: 24,
                    iso: 'inr'
                },
                'ID': {
                    name: 'Indonesian Rupiah',
                    code: 10,
                    iso: 'idr'
                },
                'IL': {
                    name: 'Israeli New Shekel',
                    code: 35,
                    iso: 'ils'
                },
                'JP': {
                    name: 'Japanese Yen',
                    code: 8,
                    iso: 'jpy'
                },
                'KZ': {
                    name: 'Kazakhstani Tenge',
                    code: 37,
                    iso: 'kzt'
                },
                'KW': {
                    name: 'Kuwaiti Dinar',
                    code: 38,
                    iso: 'kwd'
                },
                'MY': {
                    name: 'Malaysian Ringgit',
                    code: 11,
                    iso: 'myr'
                },
                'MX': {
                    name: 'Mexican Peso',
                    code: 19,
                    iso: 'mxn'
                },
                'NZ': {
                    name: 'New Zealand Dollar',
                    code: 22,
                    iso: 'nzd'
                },
                'NO': {
                    name: 'Norwegian Krone',
                    code: 9,
                    iso: 'nok'
                },
                'PE': {
                    name: 'Peruvian Sol',
                    code: 26,
                    iso: 'pen'
                },
                'PH': {
                    name: 'Philippine Peso',
                    code: 12,
                    iso: 'php'
                },
                'PL': {
                    name: 'Polish Zloty',
                    code: 6,
                    iso: 'pln'
                },
                'QA': {
                    name: 'Qatari Riyal',
                    code: 39,
                    iso: 'qar'
                },
                'RU': {
                    name: 'Russian Ruble',
                    code: 5,
                    iso: 'rub'
                },
                'SA': {
                    name: 'Saudi Riyal',
                    code: 31,
                    iso: 'sar'
                },
                'SG': {
                    name: 'Singapore Dollar',
                    code: 13,
                    iso: 'sgd'
                },
                'ZA': {
                    name: 'South African Rand',
                    code: 28,
                    iso: 'zar'
                },
                'PK': {
                    name: 'South Asia - USD',
                    code: 1,
                    iso: 'usd'
                },
                'KR': {
                    name: 'South Korean Won',
                    code: 16,
                    iso: 'krw'
                },
                'CH': {
                    name: 'Swiss Franc',
                    code: 4,
                    iso: 'chf'
                },
                'TW': {
                    name: 'Taiwan Dollar',
                    code: 30,
                    iso: 'twd'
                },
                'TH': {
                    name: 'Thai Baht',
                    code: 14,
                    iso: 'thb'
                },
                'TR': {
                    name: 'MENA - U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'AE': {
                    name: 'U.A.E. Dirham',
                    code: 32,
                    iso: 'aed'
                },
                'UA': {
                    name: 'Ukrainian Hryvnia',
                    code: 18,
                    iso: 'uah'
                },
                'UY': {
                    name: 'Uruguayan Peso',
                    code: 41,
                    iso: 'uyu'
                },
                'VN': {
                    name: 'Vietnamese Dong',
                    code: 15,
                    iso: 'vnd'
                }
            };
            const WGH_CURRENCY_CODE_TO_COUNTRY = Object.fromEntries(Object.entries(WGH_COUNTRY_CURRENCY_MAP).map(([country, data]) => [data.code, country]));
            const WGH_CURRENCY_CODE_TO_ISO = Object.fromEntries(Object.entries(WGH_COUNTRY_CURRENCY_MAP).map(([_, data]) => [data.code, data.iso]));
            const WGH_CURRENCY_ISO_TO_CODE = Object.fromEntries(Object.entries(WGH_COUNTRY_CURRENCY_MAP).map(([_, data]) => [data.iso, data.code]));
            const WGH_DEFAULT_SORT = {
                field: 'price',
                direction: 'asc'
            };

            let wgh_allAppIds = [];
            let wgh_gameDataStore = {};
            let wgh_wishlistOwnerSteamID = null;
            let wgh_currentUserCountryCode = 'RU';
            let wgh_currentUserCurrencyCode = 5;
            let wgh_currentUserISOCurrencyCode = 'RUB';
            let wgh_currentSort = {
                ...WGH_DEFAULT_SORT
            };
            let wgh_currentFriendCountryCode = null;
            let wgh_exchangeRates = null;
            let wgh_giftModeActive = false;
            let wgh_showGiftableOnly = false;
            let wgh_modal, wgh_closeBtn, wgh_analyzeBtn;
            let wgh_resultsContainer, wgh_resultsDiv, wgh_statusDiv, wgh_progressBar;
            let wgh_sortButtonsContainer;
            let wgh_giftModeContainer, wgh_giftIconBtn, wgh_giftAccordion, wgh_friendRegionSelect, wgh_fetchFriendPricesBtn, wgh_giftProgressBar, wgh_giftableFilterCheckbox;
            let wgh_myRegionDisplay;

            function wgh_addAnalyzeButton() {
                const titleBlock = document.querySelector('div.jfAmlCmNzHQ-');
                const existingButton = document.getElementById('wghAnalyzeButton');
                if (!titleBlock || existingButton) return;
                wgh_analyzeBtn = document.createElement('button');
                wgh_analyzeBtn.id = 'wghAnalyzeButton';
                wgh_analyzeBtn.title = 'Помощник подарков';
                wgh_analyzeBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="currentColor"><path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>`;
                Object.assign(wgh_analyzeBtn.style, {
                    marginLeft: '15px',
                    background: 'rgba(103, 193, 245, 0.1)',
                    border: '1px solid rgba(103, 193, 245, 0.3)',
                    color: '#67c1f5',
                    borderRadius: '3px',
                    cursor: 'pointer',
                    padding: '5px 8px',
                    display: 'inline-flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    verticalAlign: 'middle'
                });
                wgh_analyzeBtn.onmouseover = () => {
                    wgh_analyzeBtn.style.background = 'rgba(103, 193, 245, 0.2)';
                };
                wgh_analyzeBtn.onmouseout = () => {
                    wgh_analyzeBtn.style.background = 'rgba(103, 193, 245, 0.1)';
                };
                wgh_analyzeBtn.onclick = wgh_showModal;
                const h2Title = titleBlock.querySelector('h2');
                if (h2Title) {
                    h2Title.style.display = 'inline-block';
                    h2Title.after(wgh_analyzeBtn);
                } else {
                    titleBlock.appendChild(wgh_analyzeBtn);
                }
            }

            function wgh_createModal() {
                if (document.getElementById('wghModal')) return;
                wgh_modal = document.createElement('div');
                wgh_modal.id = 'wghModal';
                wgh_modal.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(20, 20, 25, 0.95); backdrop-filter: blur(3px); z-index: 9999; display: none; color: #c6d4df; font-family: "Motiva Sans", Sans-serif, Arial; overflow: hidden; `;
                const container = document.createElement('div');
                container.id = 'wghContainer';
                container.style.cssText = `height: 100%; display: flex; flex-direction: column; padding: 15px;`;
                const header = document.createElement('div');
                header.id = 'wghHeader';
                header.style.cssText = `display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding-bottom: 10px; border-bottom: 1px solid #3a4f6a; margin-bottom: 10px; flex-shrink: 0; padding-right: 45px;`;
                const collectBtn = document.createElement('button');
                collectBtn.textContent = 'Собрать данные';
                collectBtn.id = 'wghCollectBtn';
                collectBtn.className = 'wghBtn wghPrimaryBtn';
                collectBtn.onclick = wgh_collectData;
                header.appendChild(collectBtn);
                wgh_statusDiv = document.createElement('div');
                wgh_statusDiv.id = 'wghStatus';
                wgh_statusDiv.style.cssText = `flex-grow: 1; text-align: center; font-size: 14px; color: #aaa; min-height: 36px; display: flex; align-items: center; justify-content: center;`;
                header.appendChild(wgh_statusDiv);
                wgh_sortButtonsContainer = document.createElement('div');
                wgh_sortButtonsContainer.id = 'wghSortButtons';
                wgh_sortButtonsContainer.style.cssText = `display: flex; gap: 5px; align-items: center; margin-left: auto;`;
                header.appendChild(wgh_sortButtonsContainer);
                wgh_giftIconBtn = document.createElement('button');
                wgh_giftIconBtn.id = 'wghGiftModeBtn';
                wgh_giftIconBtn.className = 'wghBtn';
                wgh_giftIconBtn.title = 'Режим помощника подарков';
                wgh_giftIconBtn.innerHTML = '🎁';
                wgh_giftIconBtn.onclick = wgh_toggleGiftMode;
                header.appendChild(wgh_giftIconBtn);
                container.appendChild(header);
                wgh_giftModeContainer = document.createElement('div');
                wgh_giftModeContainer.id = 'wghGiftAccordionContainer';
                wgh_giftModeContainer.style.cssText = `display: none; padding: 10px 0; border-bottom: 1px solid #3a4f6a; margin-bottom: 10px; flex-shrink: 0;`;
                container.appendChild(wgh_giftModeContainer);
                wgh_resultsContainer = document.createElement('div');
                wgh_resultsContainer.id = 'wghResultsContainer';
                wgh_resultsContainer.style.cssText = ` flex-grow: 1; overflow-y: auto; overflow-x: hidden; scrollbar-color: #4b6f9c #17202d; scrollbar-width: thin; padding-right: 5px; `;
                wgh_resultsContainer.innerHTML = `<style> #wghResultsContainer::-webkit-scrollbar { width: 8px; } #wghResultsContainer::-webkit-scrollbar-track { background: #17202d; border-radius: 4px; } #wghResultsContainer::-webkit-scrollbar-thumb { background-color: #4b6f9c; border-radius: 4px; border: 2px solid #17202d; } #wghResultsContainer::-webkit-scrollbar-thumb:hover { background-color: #67c1f5; } </style>`;
                wgh_resultsDiv = document.createElement('div');
                wgh_resultsDiv.id = 'wghResults';
                wgh_resultsDiv.style.cssText = ` display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 15px; padding-top: 5px; `;
                wgh_resultsContainer.appendChild(wgh_resultsDiv);
                container.appendChild(wgh_resultsContainer);
                wgh_progressBar = wgh_createProgressBar('wghMainProgress');
                container.appendChild(wgh_progressBar);
                wgh_giftProgressBar = wgh_createProgressBar('wghGiftProgress');
                container.appendChild(wgh_giftProgressBar);
                wgh_closeBtn = document.createElement('button');
                wgh_closeBtn.id = 'wghCloseBtn';
                wgh_closeBtn.innerHTML = '&times;';
                wgh_closeBtn.onclick = wgh_hideModal;
                wgh_closeBtn.style.cssText = ` position: absolute; top: 10px; right: 15px; font-size: 30px; color: #aaa; background: none; border: none; cursor: pointer; line-height: 1; z-index: 10002; padding: 5px; transition: color 0.2s, transform 0.2s; `;
                wgh_closeBtn.onmouseover = () => {
                    wgh_closeBtn.style.color = '#fff';
                    wgh_closeBtn.style.transform = 'scale(1.1)';
                };
                wgh_closeBtn.onmouseout = () => {
                    wgh_closeBtn.style.color = '#aaa';
                    wgh_closeBtn.style.transform = 'scale(1)';
                };
                wgh_modal.appendChild(wgh_closeBtn);
                wgh_modal.appendChild(container);
                document.body.appendChild(wgh_modal);
                wgh_createSortButtons();
                wgh_createGiftAccordion();
                wgh_updateSortButtonsState();

                function handleEsc(event) {
                    if (event.key === 'Escape') wgh_hideModal();
                }
                document.addEventListener('keydown', handleEsc);
                wgh_modal._escHandler = handleEsc;
            }

            function wgh_showModal() {
                if (!wgh_modal) wgh_createModal();
                wgh_updateStatus('Нажмите "Собрать данные" для анализа списка желаемого.');
                wgh_resultsDiv.innerHTML = '';
                wgh_gameDataStore = {};
                wgh_hideGiftMode(true);
                wgh_hideProgressBar(wgh_progressBar);
                wgh_hideProgressBar(wgh_giftProgressBar);
                document.body.style.overflow = 'hidden';
                wgh_modal.style.display = 'block';
            }

            function wgh_hideModal() {
                if (wgh_modal) {
                    wgh_modal.style.display = 'none';
                    if (wgh_modal._escHandler) {
                        document.removeEventListener('keydown', wgh_modal._escHandler);
                        delete wgh_modal._escHandler;
                    }
                }
                document.body.style.overflow = '';
            }

            function wgh_updateStatus(message, isLoading = false) {
                if (wgh_statusDiv) {
                    wgh_statusDiv.innerHTML = message + (isLoading ? ' <span class="wghSpinner"></span>' : '');
                }
                const collectBtn = document.getElementById('wghCollectBtn');
                if (collectBtn) collectBtn.disabled = isLoading;
                if (wgh_fetchFriendPricesBtn) wgh_fetchFriendPricesBtn.disabled = isLoading;
            }

            async function wgh_collectData() {
                wgh_updateStatus('Извлечение AppID...', true);
                wgh_resultsDiv.innerHTML = '';
                wgh_gameDataStore = {};
                wgh_hideGiftMode(true);
                wgh_showProgressBar(wgh_progressBar, 0);
                try {
                    wgh_allAppIds = await wgh_extractAppIdsFromPage();
                    if (!wgh_allAppIds || wgh_allAppIds.length === 0) {
                        wgh_updateStatus('Не удалось найти игры в списке желаемого.');
                        wgh_hideProgressBar(wgh_progressBar);
                        return;
                    }
                    wgh_updateStatus(`Найдено ${wgh_allAppIds.length} игр. Запрос данных... (0/${Math.ceil(wgh_allAppIds.length / WGH_BATCH_SIZE)})`, true);
                    const totalBatches = Math.ceil(wgh_allAppIds.length / WGH_BATCH_SIZE);
                    let processedBatches = 0;
                    for (let i = 0; i < wgh_allAppIds.length; i += WGH_BATCH_SIZE) {
                        const batch = wgh_allAppIds.slice(i, i + WGH_BATCH_SIZE);
                        const batchData = await wgh_fetchBatchGameData(batch, wgh_currentUserCountryCode);
                        wgh_processBatchData(batchData, 'myData');
                        processedBatches++;
                        const progress = (processedBatches / totalBatches) * 100;
                        wgh_updateProgressBar(wgh_progressBar, progress);
                        wgh_updateStatus(`Запрос данных... (${processedBatches}/${totalBatches})`, true);
                        await new Promise(res => setTimeout(res, 200));
                    }
                    wgh_updateStatus(`Данные для ${Object.keys(wgh_gameDataStore).length} игр получены.`);
                    wgh_applySort(wgh_currentSort.field, wgh_currentSort.direction);
                    wgh_renderResults();
                    wgh_hideProgressBar(wgh_progressBar);
                } catch (error) {
                    wgh_updateStatus(`Ошибка при сборе данных: ${error.message}`);
                    console.error('[WGH] Ошибка сбора данных:', error);
                    wgh_hideProgressBar(wgh_progressBar);
                }
            }

            async function wgh_extractAppIdsFromPage() {
                let appIds = [];

                if (typeof unsafeWindow !== 'undefined' && unsafeWindow.SSR && unsafeWindow.SSR.renderContext && typeof unsafeWindow.SSR.renderContext.queryData === 'string') {
                    try {
                        const queryData = JSON.parse(unsafeWindow.SSR.renderContext.queryData);

                        if (queryData && Array.isArray(queryData.queries)) {
                            const wishlistQuery = queryData.queries.find(q =>
                                q && Array.isArray(q.queryKey) && q.queryKey[0] === 'WishlistSortedFiltered'
                            );

                            if (wishlistQuery && wishlistQuery.state && wishlistQuery.state.data && Array.isArray(wishlistQuery.state.data.items)) {
                                appIds = wishlistQuery.state.data.items.map(item => item.appid);
                            }
                        }
                    } catch (e) {
                        console.error("[WGH] Ошибка при разборе данных SSR:", e);
                    }
                }

                if (appIds.length === 0 && typeof unsafeWindow.g_rgWishlistData !== 'undefined' && Array.isArray(unsafeWindow.g_rgWishlistData)) {
                    console.warn("[WGH] Используется резервный метод g_rgWishlistData.");
                    appIds = unsafeWindow.g_rgWishlistData.map(item => item.appid).filter(id => id);
                }

                if (appIds.length === 0) {
                    throw new Error("Не удалось извлечь AppID. Возможно, структура страницы изменилась или список желаемого пуст.");
                }

                return [...new Set(appIds)];
            }

            function wgh_detectUserRegion() {
                let found = false;

                if (typeof unsafeWindow?.SSR?.renderContext?.queryData === 'string') {
                    try {
                        const queryData = JSON.parse(unsafeWindow.SSR.renderContext.queryData);
                        const walletInfoQuery = queryData?.queries?.find(q => q?.queryKey?.[0] === 'CurrentUserWalletDetails');
                        const walletInfoInSSR = walletInfoQuery?.state?.data;

                        if (walletInfoInSSR?.has_wallet && walletInfoInSSR?.currency_code && walletInfoInSSR?.wallet_country_code) {
                             wgh_currentUserCurrencyCode = walletInfoInSSR.currency_code;
                             wgh_currentUserCountryCode = walletInfoInSSR.wallet_country_code;
                             wgh_currentUserISOCurrencyCode = WGH_CURRENCY_CODE_TO_ISO[wgh_currentUserCurrencyCode] || null;
                             if (wgh_currentUserCountryCode && wgh_currentUserISOCurrencyCode) {
                                found = true;
                                console.log(`[WGH] Регион успешно определен через SSR/Wallet: ${wgh_currentUserCountryCode}`);
                             }
                        }
                    } catch(e) {
                        console.error('[WGH] Ошибка при разборе SSR для определения региона:', e);
                    }
                }

                if (!found && typeof unsafeWindow?.Config?.COUNTRY === 'string') {
                    const countryCode = unsafeWindow.Config.COUNTRY;
                    const currencyInfo = Object.entries(WGH_COUNTRY_CURRENCY_MAP).find(([key, data]) => key === countryCode);

                    if (currencyInfo) {
                        wgh_currentUserCountryCode = currencyInfo[0];
                        wgh_currentUserCurrencyCode = currencyInfo[1].code;
                        wgh_currentUserISOCurrencyCode = currencyInfo[1].iso;
                        found = true;
                        console.log(`[WGH] Регион определен через резервный метод window.Config: ${wgh_currentUserCountryCode}`);
                    }
                }

                if (!found && typeof unsafeWindow.g_rgWalletInfo !== 'undefined' && unsafeWindow.g_rgWalletInfo.wallet_currency) {
                    console.warn("[WGH] Используется самый старый резервный метод g_rgWalletInfo.");
                    wgh_currentUserCurrencyCode = unsafeWindow.g_rgWalletInfo.wallet_currency;
                    wgh_currentUserCountryCode = WGH_CURRENCY_CODE_TO_COUNTRY[wgh_currentUserCurrencyCode] || null;
                    wgh_currentUserISOCurrencyCode = WGH_CURRENCY_CODE_TO_ISO[wgh_currentUserCurrencyCode] || null;
                    if (wgh_currentUserCountryCode && wgh_currentUserISOCurrencyCode) {
                        found = true;
                    }
                }

                if (!found) {
                    console.warn('[WGH] Не удалось определить регион пользователя, используется значение по умолчанию: RU/RUB.');
                    wgh_currentUserCountryCode = 'RU';
                    wgh_currentUserCurrencyCode = 5;
                    wgh_currentUserISOCurrencyCode = 'RUB';
                }

                if (wgh_myRegionDisplay) {
                    wgh_myRegionDisplay.textContent = `${wgh_currentUserCountryCode || '??'} (${wgh_currentUserISOCurrencyCode || '???'})`;
                }
            }




            async function wgh_fetchBatchGameData(appIdsBatch, countryCode) {
                const inputJson = {
                    ids: appIdsBatch.map(appid => ({
                        appid
                    })),
                    context: {
                        language: "russian",
                        country_code: countryCode || 'RU',
                        steam_realm: 1
                    },
                    data_request: {
                        include_basic_info: true,
                        include_assets: true,
                        include_release: true,
                        include_reviews: true,
                        include_platforms: true,
                        include_all_purchase_options: true,
                        include_supported_languages: true
                    }
                };
                return new Promise((resolve, reject) => {
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: `${WGH_API_URL}?input_json=${encodeURIComponent(JSON.stringify(inputJson))}`,
                        timeout: WGH_REQUEST_TIMEOUT_MS,
                        onload: function(response) {
                            try {
                                if (response.status >= 200 && response.status < 400) {
                                    const data = JSON.parse(response.responseText);
                                    if (data?.response?.store_items) {
                                        resolve(data.response.store_items);
                                    } else {
                                        console.warn(`[WGH] API вернул успех, но нет store_items для batch: ${appIdsBatch.join(',')}`, data);
                                        resolve([]);
                                    }
                                } else {
                                    reject(new Error(`HTTP статус ${response.status} для батча`));
                                }
                            } catch (e) {
                                reject(new Error(`Ошибка парсинга JSON: ${e.message}`));
                            }
                        },
                        onerror: (error) => reject(new Error(`Сетевая ошибка: ${error?.finalUrl || WGH_API_URL}`)),
                        ontimeout: () => reject(new Error('Таймаут запроса к Steam API'))
                    });
                });
            }

            function wgh_processBatchData(batchData, dataType = 'myData') {
                if (!Array.isArray(batchData)) return;
                batchData.forEach(item => {
                    if (!item || !item.id || item.success !== 1) return;
                    const appid = item.id;
                    if (!wgh_gameDataStore[appid]) {
                        wgh_gameDataStore[appid] = {
                            myData: null,
                            friendData: null
                        };
                    }

                    const headerFileName = item.assets?.header;
                    const imageUrl = headerFileName ? `${WGH_IMAGE_BASE_URL}${item.id}/${headerFileName}` : `${WGH_IMAGE_BASE_URL}${item.appid}/header_292x136.jpg`;

                    const extractedData = {
                        appid: item.appid,
                        name: item.name,
                        type: item.type,
                        imageUrl: imageUrl,
                        releaseDateTimestamp: item.release?.steam_release_date || null,
                        reviewScore: item.reviews?.summary_filtered?.review_score || 0,
                        reviewPercent: item.reviews?.summary_filtered?.percent_positive || 0,
                        reviewCount: item.reviews?.summary_filtered?.review_count || 0,
                        reviewDesc: item.reviews?.summary_filtered?.review_score_label || 'Нет отзывов',
                        platforms: {
                            windows: item.platforms?.windows || false,
                            mac: item.platforms?.mac || false,
                            linux: item.platforms?.steamos_linux || false,
                        },
                        canGift: item.best_purchase_option?.user_can_purchase_as_gift || false,
                        priceData: null
                    };
                    const purchaseOption = item.best_purchase_option;
                    if (purchaseOption) {
                        extractedData.priceData = {
                            formattedFinal: purchaseOption.formatted_final_price || 'N/A',
                            finalCents: purchaseOption.final_price_in_cents ? parseInt(purchaseOption.final_price_in_cents, 10) : null,
                            formattedOriginal: purchaseOption.formatted_original_price || null,
                            originalCents: purchaseOption.original_price_in_cents ? parseInt(purchaseOption.original_price_in_cents, 10) : null,
                            discountPercent: purchaseOption.discount_pct || 0
                        };
                    }
                    wgh_gameDataStore[appid][dataType] = extractedData;
                });
            }

            function wgh_renderResults() {
                if (!wgh_resultsDiv) return;
                wgh_resultsDiv.innerHTML = '';
                const fragment = document.createDocumentFragment();
                const sortedAppIds = Object.keys(wgh_gameDataStore);
                sortedAppIds.sort((idA, idB) => {
                    const a = wgh_gameDataStore[idA]?.myData;
                    const b = wgh_gameDataStore[idB]?.myData;
                    return wgh_compareItems(a, b, wgh_currentSort.field, wgh_currentSort.direction);
                });
                sortedAppIds.forEach(appid => {
                    const game = wgh_gameDataStore[appid];
                    if (game && game.myData) {
                        fragment.appendChild(wgh_createGameCard(appid, game));
                    }
                });
                wgh_resultsDiv.appendChild(fragment);
                wgh_applyGiftFilter();
            }

            function wgh_createGameCard(appid, game) {
                const myData = game.myData;
                const friendData = game.friendData;
                const card = document.createElement('div');
                card.className = 'wghGameCard';
                card.dataset.appid = appid;
                const reviewClass = wgh_getReviewClass(myData.reviewPercent, myData.reviewCount);
                const releaseDateStr = myData.releaseDateTimestamp ? new Date(myData.releaseDateTimestamp * 1000).toLocaleDateString('ru-RU') : 'Неизвестно';
                let friendPriceStr = '';
                let priceDiffStr = '';
                let priceDiffClass = '';
                card.dataset.giftablePrice = 'unknown';
                card.dataset.canGiftApi = myData.canGift ? 'true' : 'false';

                if (wgh_giftModeActive && friendData?.priceData && myData?.priceData && wgh_exchangeRates) {
                    const friendCents = friendData.priceData.finalCents;
                    const myCents = myData.priceData.finalCents;
                    if (friendCents !== null && myCents !== null) {
                        const friendPriceInMyCurrency = wgh_convertCurrency(friendCents / 100, wgh_currentFriendCountryCode, wgh_currentUserCountryCode);
                        if (friendPriceInMyCurrency !== null) {
                            const myPrice = myCents / 100;
                            const diff = friendPriceInMyCurrency - myPrice;
                            const diffPercent = myPrice > 0 ? diff / myPrice : (diff > 0 ? Infinity : -Infinity);
                            friendPriceStr = `Цена друга: ${friendPriceInMyCurrency.toLocaleString('ru-RU', { style: 'currency', currency: wgh_currentUserISOCurrencyCode, minimumFractionDigits: 0, maximumFractionDigits: 2 })}`;
                            if (Math.abs(diffPercent) <= WGH_GIFT_PRICE_DIFF_THRESHOLD) {
                                priceDiffClass = 'wghPriceDiffGood';
                                card.dataset.giftablePrice = 'true';
                            } else {
                                priceDiffClass = 'wghPriceDiffBad';
                                card.dataset.giftablePrice = 'false';
                            }
                            priceDiffStr = `Разница: ${diff > 0 ? '+' : ''}${diff.toLocaleString('ru-RU', { style: 'currency', currency: wgh_currentUserISOCurrencyCode, minimumFractionDigits: 0, maximumFractionDigits: 2 })} (${diffPercent === Infinity || diffPercent === -Infinity ? '∞' : (diffPercent * 100).toFixed(0)}%)`;
                        } else {
                            friendPriceStr = 'Цена друга: Ошибка конв.';
                            card.dataset.giftablePrice = 'false';
                        }
                    } else {
                        friendPriceStr = 'Цена друга: N/A';
                        card.dataset.giftablePrice = 'false';
                    }
                } else if (wgh_giftModeActive) {
                    friendPriceStr = 'Цена друга: ...';
                    card.dataset.giftablePrice = 'false';
                }

                card.innerHTML = ` <a href="https://store.steampowered.com/app/${appid}" target="_blank" class="wghCardLink"> <div class="wghCardImageWrapper"> <img src="${myData.imageUrl}" alt="${myData.name}" loading="lazy" onerror="this.onerror=null;this.src='https://via.placeholder.com/292x136?text=No+Image';"> ${myData.priceData?.discountPercent > 0 ? `<div class="wghCardDiscountBadge">-${myData.priceData.discountPercent}%</div>` : ''} </div> <div class="wghCardContent"> <div class="wghCardTitle" title="${myData.name}">${myData.name}</div> <div class="wghCardPrice"> ${myData.priceData?.formattedOriginal ? `<span class="wghOriginalPrice">${myData.priceData.formattedOriginal}</span>` : ''} <span class="wghCurrentPrice">${myData.priceData?.formattedFinal || 'N/A'}</span> </div> <div class="wghCardReviews ${reviewClass}" title="${myData.reviewCount} отзывов"> ${myData.reviewDesc} (${myData.reviewPercent}%) </div> <div class="wghCardReleaseDate">Дата выхода: ${releaseDateStr}</div> ${myData.canGift ? '' : '<div class="wghCannotGift">Нельзя подарить</div>'} ${friendPriceStr ? `<div class="wghFriendPrice">${friendPriceStr}</div>` : ''} ${priceDiffStr ? `<div class="wghPriceDiff ${priceDiffClass}">${priceDiffStr}</div>` : ''} </div> </a> `;
                return card;
            }

            function wgh_getReviewClass(percent, count) {
                if (count === 0) return 'wghReviewNone';
                if (percent >= 70) return 'wghReviewPositive';
                if (percent >= 40) return 'wghReviewMixed';
                return 'wghReviewNegative';
            }

            function wgh_createSortButtons() {
                if (!wgh_sortButtonsContainer) return;
                wgh_sortButtonsContainer.innerHTML = '';
                const createBtn = (field, text) => {
                    const btn = document.createElement('button');
                    btn.className = 'wghBtn sortBtn';
                    btn.dataset.sort = field;
                    btn.textContent = text;
                    btn.onclick = () => wgh_handleSort(field);
                    wgh_sortButtonsContainer.appendChild(btn);
                    return btn;
                };
                createBtn('price', 'Цена');
                createBtn('discountPercent', '% Скидки');
                createBtn('name', 'Название');
                createBtn('releaseDateTimestamp', 'Дата выхода');
                createBtn('reviewPercent', '% Отзывов');
            }

            function wgh_handleSort(field) {
                const defaultDirections = {
                    price: 'asc',
                    discountPercent: 'desc',
                    name: 'asc',
                    releaseDateTimestamp: 'desc',
                    reviewPercent: 'desc'
                };
                let newDirection;
                if (wgh_currentSort.field === field) {
                    newDirection = wgh_currentSort.direction === 'asc' ? 'desc' : 'asc';
                } else {
                    newDirection = defaultDirections[field] || 'asc';
                }
                wgh_currentSort.field = field;
                wgh_currentSort.direction = newDirection;
                wgh_applySort(field, newDirection);
                wgh_renderResults();
                wgh_updateSortButtonsState();
            }

            function wgh_applySort(field, direction) {
                wgh_currentSort = {
                    field,
                    direction
                };
            }

            function wgh_compareItems(a, b, field, direction) {
                if (!a && !b) return 0;
                if (!a) return direction === 'asc' ? 1 : -1;
                if (!b) return direction === 'asc' ? -1 : 1;
                const dirMultiplier = direction === 'asc' ? 1 : -1;
                let valA, valB;
                switch (field) {
                    case 'price':
                        valA = a.priceData?.finalCents ?? (direction === 'asc' ? Infinity : -Infinity);
                        valB = b.priceData?.finalCents ?? (direction === 'asc' ? Infinity : -Infinity);
                        break;
                    case 'discountPercent':
                        valA = a.priceData?.discountPercent ?? -1;
                        valB = b.priceData?.discountPercent ?? -1;
                        break;
                    case 'name':
                        valA = a.name?.toLowerCase() || '';
                        valB = b.name?.toLowerCase() || '';
                        return valA.localeCompare(valB) * dirMultiplier;
                    case 'releaseDateTimestamp':
                        valA = a.releaseDateTimestamp ?? (direction === 'asc' ? Infinity : 0);
                        valB = b.releaseDateTimestamp ?? (direction === 'asc' ? Infinity : 0);
                        break;
                    case 'reviewPercent':
                        valA = a.reviewPercent ?? -1;
                        valB = b.reviewPercent ?? -1;
                        break;
                    default:
                        return 0;
                }
                let comparisonResult = 0;
                const fallbackAsc = Infinity;
                const fallbackDesc = -Infinity;
                if (valA === null || valA === undefined || isNaN(valA) || valA === Infinity || valA === -Infinity) valA = direction === 'asc' ? fallbackAsc : fallbackDesc;
                if (valB === null || valB === undefined || isNaN(valB) || valB === Infinity || valB === -Infinity) valB = direction === 'asc' ? fallbackAsc : fallbackDesc;
                if (valA < valB) comparisonResult = -1;
                else if (valA > valB) comparisonResult = 1;
                else comparisonResult = 0;
                comparisonResult *= dirMultiplier;
                if (comparisonResult === 0 && field !== 'price') {
                    const priceA = a.priceData?.finalCents ?? Infinity;
                    const priceB = b.priceData?.finalCents ?? Infinity;
                    if (priceA < priceB) return -1;
                    if (priceA > priceB) return 1;
                }
                if (comparisonResult === 0 && field !== 'name') {
                    return (a.name?.toLowerCase() || '').localeCompare(b.name?.toLowerCase() || '');
                }
                return comparisonResult;
            }

            function wgh_updateSortButtonsState() {
                if (!wgh_sortButtonsContainer) return;
                const buttons = wgh_sortButtonsContainer.querySelectorAll('.sortBtn');
                buttons.forEach(btn => {
                    const btnField = btn.dataset.sort;
                    const baseText = btn.textContent.replace(/ [▲▼]$/, '');
                    if (btnField === wgh_currentSort.field) {
                        const arrow = wgh_currentSort.direction === 'asc' ? ' ▲' : ' ▼';
                        btn.classList.add('active');
                        btn.textContent = baseText + arrow;
                    } else {
                        btn.classList.remove('active');
                        btn.textContent = baseText;
                    }
                });
            }

            function wgh_createGiftAccordion() {
                if (!wgh_giftModeContainer) return;
                wgh_giftModeContainer.innerHTML = '';
                const accordionContent = document.createElement('div');
                accordionContent.id = 'wghGiftAccordionContent';
                accordionContent.style.cssText = ` display: flex; flex-wrap: wrap; gap: 10px; align-items: center; padding: 10px; border: 1px solid #3a4f6a; border-radius: 4px; background-color: rgba(42, 71, 94, 0.2); `;
                const myRegionDiv = document.createElement('div');
                myRegionDiv.innerHTML = `Ваш регион: <strong id="wghMyRegionDisplay">${wgh_currentUserCountryCode || '??'} (${wgh_currentUserISOCurrencyCode || '???'})</strong>`;
                myRegionDiv.style.marginRight = '15px';
                accordionContent.appendChild(myRegionDiv);
                wgh_myRegionDisplay = myRegionDiv.querySelector('strong');
                const friendRegionLabel = document.createElement('label');
                friendRegionLabel.textContent = 'Регион друга: ';
                friendRegionLabel.style.marginRight = '5px';
                accordionContent.appendChild(friendRegionLabel);
                wgh_friendRegionSelect = document.createElement('select');
                wgh_friendRegionSelect.id = 'wghFriendRegionSelect';
                wgh_friendRegionSelect.className = 'wghSelect';
                wgh_friendRegionSelect.innerHTML = '<option value="">-- Выберите --</option>';
                Object.entries(WGH_COUNTRY_CURRENCY_MAP).sort(([, a], [, b]) => a.name.localeCompare(b.name)).forEach(([code, data]) => {
                    if (code !== wgh_currentUserCountryCode) {
                        const option = document.createElement('option');
                        option.value = code;
                        option.textContent = `${data.name} (${code})`;
                        wgh_friendRegionSelect.appendChild(option);
                    }
                });
                accordionContent.appendChild(wgh_friendRegionSelect);
                wgh_fetchFriendPricesBtn = document.createElement('button');
                wgh_fetchFriendPricesBtn.id = 'wghFetchFriendPricesBtn';
                wgh_fetchFriendPricesBtn.className = 'wghBtn wghPrimaryBtn';
                wgh_fetchFriendPricesBtn.textContent = 'Узнать цены';
                wgh_fetchFriendPricesBtn.onclick = wgh_fetchFriendData;
                accordionContent.appendChild(wgh_fetchFriendPricesBtn);
                const giftFilterDiv = document.createElement('div');
                giftFilterDiv.style.marginLeft = 'auto';
                giftFilterDiv.innerHTML = ` <label title="Показать только игры с разницей цен +/- ${WGH_GIFT_PRICE_DIFF_THRESHOLD * 100}% и возможностью покупки в подарок"> <input type="checkbox" id="wghGiftableFilterCheckbox"> Можно подарить </label> `;
                wgh_giftableFilterCheckbox = giftFilterDiv.querySelector('input');
                wgh_giftableFilterCheckbox.onchange = wgh_handleGiftableFilterChange;
                accordionContent.appendChild(giftFilterDiv);
                wgh_giftModeContainer.appendChild(accordionContent);
            }

            function wgh_toggleGiftMode() {
                wgh_giftModeActive = !wgh_giftModeActive;
                wgh_giftModeContainer.style.display = wgh_giftModeActive ? 'block' : 'none';
                if (wgh_giftIconBtn) wgh_giftIconBtn.classList.toggle('active', wgh_giftModeActive);
                if (!wgh_giftModeActive) {
                    wgh_hideGiftMode(true);
                }
                wgh_renderResults();
            }

            function wgh_hideGiftMode(resetSelection = false) {
                wgh_giftModeActive = false;
                wgh_currentFriendCountryCode = null;
                wgh_showGiftableOnly = false;
                if (wgh_giftModeContainer) wgh_giftModeContainer.style.display = 'none';
                if (wgh_giftIconBtn) wgh_giftIconBtn.classList.remove('active');
                if (resetSelection && wgh_friendRegionSelect) wgh_friendRegionSelect.value = '';
                if (wgh_giftableFilterCheckbox) wgh_giftableFilterCheckbox.checked = false;
                wgh_hideProgressBar(wgh_giftProgressBar);
                Object.values(wgh_gameDataStore).forEach(game => game.friendData = null);
                wgh_renderResults();
            }

            async function wgh_fetchFriendData() {
                wgh_currentFriendCountryCode = wgh_friendRegionSelect.value;
                if (!wgh_currentFriendCountryCode) {
                    wgh_updateStatus('Выберите регион друга.');
                    return;
                }
                if (wgh_allAppIds.length === 0) {
                    wgh_updateStatus('Сначала соберите данные для своего списка желаемого.');
                    return;
                }
                wgh_updateStatus(`Запрос цен для региона ${wgh_currentFriendCountryCode}... (0/${Math.ceil(wgh_allAppIds.length / WGH_BATCH_SIZE)})`, true);
                wgh_showProgressBar(wgh_giftProgressBar, 0);
                Object.values(wgh_gameDataStore).forEach(game => game.friendData = null);
                wgh_exchangeRates = null;
                try {
                    const friendCurrencyInfo = WGH_COUNTRY_CURRENCY_MAP[wgh_currentFriendCountryCode];
                    const myCurrencyInfo = WGH_COUNTRY_CURRENCY_MAP[wgh_currentUserCountryCode];
                    if (friendCurrencyInfo && myCurrencyInfo && friendCurrencyInfo.code !== myCurrencyInfo.code) {
                        wgh_updateStatus(`Получение курса валют...`, true);
                        try {
                            wgh_exchangeRates = await wgh_fetchExchangeRates(friendCurrencyInfo.iso);
                        } catch (rateError) {
                            wgh_updateStatus(`Ошибка получения курса валют: ${rateError.message}. Сравнение цен будет неточным.`);
                            console.error("[WGH] Ошибка курса валют:", rateError);
                            await new Promise(res => setTimeout(res, 2000));
                            wgh_exchangeRates = {};
                        }
                    } else {
                        wgh_exchangeRates = {};
                    }
                    const totalBatches = Math.ceil(wgh_allAppIds.length / WGH_BATCH_SIZE);
                    let processedBatches = 0;
                    wgh_updateStatus(`Запрос цен для региона ${wgh_currentFriendCountryCode}... (0/${totalBatches})`, true);
                    for (let i = 0; i < wgh_allAppIds.length; i += WGH_BATCH_SIZE) {
                        const batch = wgh_allAppIds.slice(i, i + WGH_BATCH_SIZE);
                        const batchData = await wgh_fetchBatchGameData(batch, wgh_currentFriendCountryCode);
                        wgh_processBatchData(batchData, 'friendData');
                        processedBatches++;
                        const progress = (processedBatches / totalBatches) * 100;
                        wgh_updateProgressBar(wgh_giftProgressBar, progress);
                        wgh_updateStatus(`Запрос цен для региона ${wgh_currentFriendCountryCode}... (${processedBatches}/${totalBatches})`, true);
                        await new Promise(res => setTimeout(res, 200));
                    }
                    wgh_updateStatus(`Цены для региона ${wgh_currentFriendCountryCode} получены.`);
                    wgh_renderResults();
                    wgh_hideProgressBar(wgh_giftProgressBar);
                } catch (error) {
                    wgh_updateStatus(`Ошибка при получении цен друга: ${error.message}`);
                    console.error('[WGH] Ошибка получения цен друга:', error);
                    wgh_hideProgressBar(wgh_giftProgressBar);
                    wgh_renderResults();
                }
            }

            async function wgh_fetchExchangeRates(baseCurrencyIso) {
                if (!baseCurrencyIso) throw new Error("Base currency ISO code not provided");
                const apiUrl = `${WGH_CURRENCY_API_URL}${baseCurrencyIso.toLowerCase()}.json`;
                return new Promise((resolve, reject) => {
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: apiUrl,
                        responseType: 'json',
                        timeout: WGH_REQUEST_TIMEOUT_MS / 2,
                        onload: (response) => {
                            if (response.status >= 200 && response.status < 400 && response.response) {
                                const rates = response.response[baseCurrencyIso.toLowerCase()];
                                if (rates && typeof rates === 'object') {
                                    resolve(rates);
                                } else {
                                    reject(new Error(`Курсы для ${baseCurrencyIso} не найдены в ответе API`));
                                }
                            } else {
                                reject(new Error(`Ошибка API валют: статус ${response.status}`));
                            }
                        },
                        onerror: (error) => reject(new Error('Сетевая ошибка API валют')),
                        ontimeout: () => reject(new Error('Таймаут запроса API валют'))
                    });
                });
            }

            function wgh_convertCurrency(amount, fromCountryCode, toCountryCode) {
                if (fromCountryCode === toCountryCode) return amount;
                if (!wgh_exchangeRates) {
                    console.warn('[WGH] Exchange rates not loaded for conversion');
                    return null;
                }
                const fromCurrencyInfo = WGH_COUNTRY_CURRENCY_MAP[fromCountryCode];
                const toCurrencyInfo = WGH_COUNTRY_CURRENCY_MAP[toCountryCode];
                if (!fromCurrencyInfo || !toCurrencyInfo) {
                    console.warn('[WGH] Unknown country code for conversion', fromCountryCode, toCountryCode);
                    return null;
                }
                if (fromCurrencyInfo.code === toCurrencyInfo.code) {
                    return amount;
                }
                const toCurrencyKey = toCurrencyInfo.iso?.toLowerCase();
                if (!toCurrencyKey) {
                    console.warn('[WGH] Unknown target ISO currency code for conversion', toCountryCode);
                    return null;
                }
                if (wgh_exchangeRates[toCurrencyKey] === undefined || wgh_exchangeRates[toCurrencyKey] === null) {
                    console.warn(`[WGH] Exchange rate to ${toCurrencyKey} not available`);
                    return null;
                }
                const rate = wgh_exchangeRates[toCurrencyKey];
                return parseFloat((amount * rate).toFixed(2));
            }

            function wgh_handleGiftableFilterChange() {
                wgh_showGiftableOnly = wgh_giftableFilterCheckbox.checked;
                wgh_applyGiftFilter();
            }

            function wgh_applyGiftFilter() {
                if (!wgh_giftModeActive) {
                    document.querySelectorAll('.wghGameCard').forEach(card => {
                        card.style.display = 'flex';
                    });
                    return;
                }
                const cards = document.querySelectorAll('.wghGameCard');
                cards.forEach(card => {
                    const isGiftableByPrice = card.dataset.giftablePrice === 'true';
                    const canGiftByApi = card.dataset.canGiftApi === 'true';
                    if (wgh_showGiftableOnly) {
                        if (isGiftableByPrice && canGiftByApi) {
                            card.style.display = 'flex';
                        } else {
                            card.style.display = 'none';
                            card.classList.add('wgh-filtered-out');
                        }
                    } else {
                        card.style.display = 'flex';
                        card.classList.remove('wgh-filtered-out');
                    }
                });
            }

            function wgh_createProgressBar(id) {
                const barContainer = document.createElement('div');
                barContainer.id = id;
                barContainer.style.cssText = ` width: 80%; max-width: 600px; height: 10px; background-color: #3a4f6a; border-radius: 5px; overflow: hidden; margin: 10px auto; display: none; flex-shrink: 0; `;
                const barFill = document.createElement('div');
                barFill.className = 'wghProgressBarFill';
                barFill.style.cssText = ` width: 0%; height: 100%; background-color: #67c1f5; border-radius: 5px; transition: width 0.3s ease-out; `;
                barContainer.appendChild(barFill);
                return barContainer;
            }

            function wgh_showProgressBar(barElement, initialProgress = 0) {
                if (!barElement) return;
                const fill = barElement.querySelector('.wghProgressBarFill');
                fill.style.width = `${initialProgress}%`;
                barElement.style.display = 'block';
            }

            function wgh_updateProgressBar(barElement, progress) {
                if (!barElement) return;
                const fill = barElement.querySelector('.wghProgressBarFill');
                fill.style.width = `${Math.min(100, Math.max(0, progress))}%`;
            }

            function wgh_hideProgressBar(barElement) {
                if (!barElement) return;
                barElement.style.display = 'none';
            }

            function wgh_addStyles() {
                GM_addStyle(`
                   .wghBtn {
                       padding: 8px 14px;
                       font-size: 14px;
                       color: #c6d4df;
                       border: 1px solid #4b6f9c;
                       border-radius: 3px;
                       cursor: pointer;
                       white-space: nowrap;
                       height: 36px;
                       display: inline-flex;
                       align-items: center;
                       justify-content: center;
                       flex-shrink: 0;
                       background-color: rgba(42, 71, 94, 0.8);
                       transition: background-color 0.2s, border-color 0.2s;
                       text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
                   }

                   .wghBtn:hover:not(:disabled) {
                       background-color: rgba(67, 103, 133, 0.9);
                       border-color: #67c1f5;
                   }

                   .wghBtn:disabled {
                       opacity: 0.6;
                       cursor: default;
                   }

                   .wghPrimaryBtn {
                       background-color: rgba(77, 136, 255, 0.8);
                       border-color: #4D88FF;
                   }

                   .wghPrimaryBtn:hover:not(:disabled) {
                       background-color: rgba(51, 102, 204, 0.9);
                   }

                   .wghBtn.sortBtn.active {
                       background-color: rgba(0, 123, 255, 0.8);
                       border-color: #007bff;
                   }

                   .wghBtn.sortBtn.active:hover {
                       background-color: rgba(0, 86, 179, 0.9);
                   }

                   #wghGiftModeBtn.active {
                       background-color: rgba(0, 123, 255, 0.8);
                       border-color: #007bff;
                   }

                   .wghSelect {
                       margin-left: 5px;
                       background-color: #333;
                       color: #eee;
                       border: 1px solid #555;
                       border-radius: 4px;
                       height: 36px;
                       padding: 0 8px;
                       font-size: 14px;
                       cursor: pointer;
                       flex-shrink: 0;
                       outline: none;
                       max-width: 200px;
                   }

                   .wghSelect:focus {
                       border-color: #67c1f5;
                   }

                   .wghGameCard {
                       background-color: rgba(42, 46, 51, 0.85);
                       border-radius: 6px;
                       padding: 10px;
                       display: flex;
                       flex-direction: column;
                       transition: transform 0.2s ease, box-shadow 0.2s ease;
                       box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
                       color: #c6d4df;
                       font-size: 13px;
                       border: 1px solid #333941;
                       min-height: 360px;
                   }

                   .wghGameCard:hover {
                       transform: translateY(-2px);
                       box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
                       border-color: #4b6f9c;
                   }

                   .wghCardLink {
                       text-decoration: none;
                       color: inherit;
                       display: flex;
                       flex-direction: column;
                       height: 100%;
                   }

                   .wghCardImageWrapper {
                       position: relative;
                       width: 100%;
                       aspect-ratio: 292 / 136;
                       margin-bottom: 8px;
                       background-color: #111;
                       border-radius: 4px;
                       overflow: hidden;
                       display: flex;
                       align-items: center;
                       justify-content: center;
                       border: 1px solid #333941;
                   }

                   .wghCardImageWrapper img {
                       display: block;
                       max-width: 100%;
                       max-height: 100%;
                       width: 100%;
                       height: 100%;
                       object-fit: cover;
                       border-radius: 4px;
                   }

                   .wghCardDiscountBadge {
                       position: absolute;
                       bottom: 5px;
                       right: 5px;
                       background-color: #e2004b;
                       color: white;
                       padding: 2px 6px;
                       font-size: 12px;
                       border-radius: 3px;
                       font-weight: 600;
                       z-index: 1;
                   }

                   .wghCardContent {
                       flex-grow: 1;
                       display: flex;
                       flex-direction: column;
                   }

                   .wghCardTitle {
                       font-size: 14px;
                       font-weight: 500;
                       line-height: 1.3;
                       height: 2.6em;
                       overflow: hidden;
                       text-overflow: ellipsis;
                       margin-bottom: 5px;
                       color: #e5e5e5;
                       display: -webkit-box;
                       -webkit-line-clamp: 2;
                       -webkit-box-orient: vertical;
                   }

                   .wghCardPrice {
                       display: flex;
                       align-items: baseline;
                       gap: 8px;
                       margin-bottom: 6px;
                       min-height: 20px;
                   }

                   .wghCurrentPrice {
                       font-size: 16px;
                       font-weight: 600;
                       color: #a4d007;
                   }

                   .wghOriginalPrice {
                       font-size: 13px;
                       color: #8f98a0;
                       text-decoration: line-through;
                   }

                   .wghCardReviews {
                       font-size: 12px;
                       margin-bottom: 4px;
                   }

                   .wghReviewPositive {
                       color: #66c0f4;
                   }

                   .wghReviewMixed {
                       color: #a38b51;
                   }

                   .wghReviewNegative {
                       color: #c44c2c;
                   }

                   .wghReviewNone {
                       color: #8f98a0;
                   }

                   .wghCardReleaseDate {
                       font-size: 11px;
                       color: #8f98a0;
                       margin-bottom: 8px;
                   }

                   .wghCannotGift {
                       font-size: 11px;
                       color: #ff8080;
                       font-style: italic;
                       margin-bottom: 5px;
                       margin-top: auto;
                       padding-top: 5px;
                   }

                   .wghFriendPrice {
                       font-size: 12px;
                       color: #b0e0e6;
                       margin-top: auto;
                       padding-top: 5px;
                   }

                   .wghPriceDiff {
                       font-size: 12px;
                       font-weight: bold;
                       margin-top: 2px;
                   }

                   .wghPriceDiffGood {
                       color: #77dd77;
                   }

                   .wghPriceDiffBad {
                       color: #ff6961;
                   }

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

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

                   .wghSpinner {
                       border: 2px solid rgba(255, 255, 255, 0.3);
                       border-radius: 50%;
                       border-top-color: #fff;
                       width: 1em;
                       height: 1em;
                       animation: wghSpin 1s linear infinite;
                       display: inline-block;
                       vertical-align: middle;
                       margin-left: 8px;
                   }

                   #wghGiftAccordionContent label {
                       display: flex;
                       align-items: center;
                       font-size: 14px;
                       color: #c6d4df;
                       cursor: pointer;
                   }

                   #wghGiftAccordionContent input[type="checkbox"] {
                       margin-right: 5px;
                       width: 16px;
                       height: 16px;
                       accent-color: #67c1f5;
                       cursor: pointer;
                   }

                   .wghGameCard.wgh-filtered-out {
                       display: none !important;
                   }

                   @media (max-width: 1600px) {
                       #wghResults {
                           grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
                       }
                   }

                   @media (max-width: 1300px) {
                       #wghResults {
                           grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
                       }
                   }

                   @media (max-width: 900px) {
                       #wghResults {
                           grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
                       }
                   }

                   @media (max-width: 700px) {
                       #wghResults {
                           grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
                       }

                       #wghHeader {
                           flex-direction: column;
                           align-items: stretch;
                       }

                       #wghSortButtons {
                           justify-content: space-around;
                           margin-left: 0;
                           margin-top: 5px;
                           width: 100%;
                           order: 3;
                       }

                       #wghGiftModeContainer {
                           margin-top: 5px;
                       }

                       #wghGiftAccordionContent {
                           flex-direction: column;
                           align-items: flex-start;
                       }

                       #wghGiftAccordionContent label {
                           margin-bottom: 5px;
                       }

                       #wghGiftAccordionContent #wghFriendRegionSelect {
                           width: 100%;
                           margin-bottom: 10px;
                       }

                       #wghGiftAccordionContent #wghFetchFriendPricesBtn {
                           width: 100%;
                           margin-bottom: 10px;
                       }

                       #wghGiftAccordionContent div[style*='margin-left: auto'] {
                           width: 100%;
                           margin-left: 0 !important;
                           text-align: center;
                       }

                       #wghHeader>.wghBtn:first-child {
                           order: 1;
                           width: 100%;
                           margin-bottom: 5px;
                       }

                       #wghGiftModeBtn {
                           order: 2;
                           align-self: flex-end;
                           margin-bottom: 5px;
                       }

                       #wghStatus {
                           order: 0;
                           text-align: center;
                           justify-content: center;
                           margin-bottom: 5px;
                       }
                   }
                `);
            }

            function wgh_initialize() {
                wgh_detectUserRegion();
                wgh_addStyles();
                wgh_addAnalyzeButton();
            }

            setTimeout(wgh_initialize, WGH_INITIAL_DELAY_MS);

        })();
    }

    // Скрипт для проверки возможности отправки подарка со страницы игры друзьям в других странах | https://store.steampowered.com/app/*
    if (scriptsConfig.pageGiftHelper && unsafeWindow.location.pathname.includes('/app/')) {
        (function() {
            'use strict';

            const PGH_API_URL = "https://api.steampowered.com/IStoreBrowseService/GetItems/v1";
            const PGH_CURRENCY_API_URL = 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/';
            const PGH_REQUEST_TIMEOUT_MS = 15000;
            const PGH_GIFT_PRICE_DIFF_THRESHOLD = 0.10;
            const PGH_COUNTRY_CURRENCY_MAP = {
                'US': {
                    name: 'U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'EU': {
                    name: 'Euro',
                    code: 3,
                    iso: 'eur'
                },
                'AR': {
                    name: 'LATAM - U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'AU': {
                    name: 'Australian Dollar',
                    code: 21,
                    iso: 'aud'
                },
                'BR': {
                    name: 'Brazilian Real',
                    code: 7,
                    iso: 'brl'
                },
                'GB': {
                    name: 'British Pound',
                    code: 2,
                    iso: 'gbp'
                },
                'CA': {
                    name: 'Canadian Dollar',
                    code: 20,
                    iso: 'cad'
                },
                'CL': {
                    name: 'Chilean Peso',
                    code: 25,
                    iso: 'clp'
                },
                'CN': {
                    name: 'Chinese Yuan',
                    code: 23,
                    iso: 'cny'
                },
                'AZ': {
                    name: 'CIS - U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'CO': {
                    name: 'Colombian Peso',
                    code: 27,
                    iso: 'cop'
                },
                'CR': {
                    name: 'Costa Rican Colon',
                    code: 40,
                    iso: 'crc'
                },
                'HK': {
                    name: 'Hong Kong Dollar',
                    code: 29,
                    iso: 'hkd'
                },
                'IN': {
                    name: 'Indian Rupee',
                    code: 24,
                    iso: 'inr'
                },
                'ID': {
                    name: 'Indonesian Rupiah',
                    code: 10,
                    iso: 'idr'
                },
                'IL': {
                    name: 'Israeli New Shekel',
                    code: 35,
                    iso: 'ils'
                },
                'JP': {
                    name: 'Japanese Yen',
                    code: 8,
                    iso: 'jpy'
                },
                'KZ': {
                    name: 'Kazakhstani Tenge',
                    code: 37,
                    iso: 'kzt'
                },
                'KW': {
                    name: 'Kuwaiti Dinar',
                    code: 38,
                    iso: 'kwd'
                },
                'MY': {
                    name: 'Malaysian Ringgit',
                    code: 11,
                    iso: 'myr'
                },
                'MX': {
                    name: 'Mexican Peso',
                    code: 19,
                    iso: 'mxn'
                },
                'NZ': {
                    name: 'New Zealand Dollar',
                    code: 22,
                    iso: 'nzd'
                },
                'NO': {
                    name: 'Norwegian Krone',
                    code: 9,
                    iso: 'nok'
                },
                'PE': {
                    name: 'Peruvian Sol',
                    code: 26,
                    iso: 'pen'
                },
                'PH': {
                    name: 'Philippine Peso',
                    code: 12,
                    iso: 'php'
                },
                'PL': {
                    name: 'Polish Zloty',
                    code: 6,
                    iso: 'pln'
                },
                'QA': {
                    name: 'Qatari Riyal',
                    code: 39,
                    iso: 'qar'
                },
                'RU': {
                    name: 'Russian Ruble',
                    code: 5,
                    iso: 'rub'
                },
                'SA': {
                    name: 'Saudi Riyal',
                    code: 31,
                    iso: 'sar'
                },
                'SG': {
                    name: 'Singapore Dollar',
                    code: 13,
                    iso: 'sgd'
                },
                'ZA': {
                    name: 'South African Rand',
                    code: 28,
                    iso: 'zar'
                },
                'PK': {
                    name: 'South Asia - USD',
                    code: 1,
                    iso: 'usd'
                },
                'KR': {
                    name: 'South Korean Won',
                    code: 16,
                    iso: 'krw'
                },
                'CH': {
                    name: 'Swiss Franc',
                    code: 4,
                    iso: 'chf'
                },
                'TW': {
                    name: 'Taiwan Dollar',
                    code: 30,
                    iso: 'twd'
                },
                'TH': {
                    name: 'Thai Baht',
                    code: 14,
                    iso: 'thb'
                },
                'TR': {
                    name: 'MENA - U.S. Dollar',
                    code: 1,
                    iso: 'usd'
                },
                'AE': {
                    name: 'U.A.E. Dirham',
                    code: 32,
                    iso: 'aed'
                },
                'UA': {
                    name: 'Ukrainian Hryvnia',
                    code: 18,
                    iso: 'uah'
                },
                'UY': {
                    name: 'Uruguayan Peso',
                    code: 41,
                    iso: 'uyu'
                },
                'VN': {
                    name: 'Vietnamese Dong',
                    code: 15,
                    iso: 'vnd'
                }
            };

            const PGH_ISO_TO_COUNTRY = Object.fromEntries(Object.entries(PGH_COUNTRY_CURRENCY_MAP).map(([country, data]) => [data.iso, country]));
            const PGH_ISO_TO_CODE = Object.fromEntries(Object.entries(PGH_COUNTRY_CURRENCY_MAP).map(([_, data]) => [data.iso, data.code]));

            let pgh_modal = null;
            let pgh_resultDiv = null;
            let pgh_fetchBtn = null;
            let pgh_regionSelect = null;
            let pgh_currentAppId = null;
            let pgh_currentUserPrice = null;
            let pgh_currentUserCurrencyISO = null;
            let pgh_exchangeRates = null;

            function pgh_addStyles() {
                GM_addStyle(`
                    .pgh_button {
                        margin-left: 3px;
                    }
                    #pghModal {
                        position: fixed;
                        top: 50%;
                        left: 50%;
                        transform: translate(-50%, -50%);
                        background-color: #1b2838;
                        color: #c6d4df;
                        padding: 20px;
                        border-radius: 5px;
                        border: 1px solid #67c1f5;
                        box-shadow: 0 5px 25px rgba(0, 0, 0, 0.7);
                        z-index: 10001;
                        display: none;
                        width: 400px;
                        font-family: "Motiva Sans", Sans-serif, Arial;
                    }
                    #pghModal h3 {
                        margin-top: 0;
                        margin-bottom: 15px;
                        color: #67c1f5;
                        text-align: center;
                        font-weight: 500;
                        font-size: 16px;
                    }
                    #pghModal label {
                        display: block;
                        margin-bottom: 5px;
                        font-size: 14px;
                    }
                    #pghRegionSelect {
                        width: 100%;
                        padding: 8px 10px;
                        margin-bottom: 15px;
                        background-color: #2a3f5a;
                        border: 1px solid #567d9c;
                        color: #ebebeb;
                        border-radius: 3px;
                        font-size: 14px;
                        cursor: pointer;
                        outline: none;
                    }
                    #pghRegionSelect:focus {
                        border-color: #67c1f5;
                        background-color: #314b6a;
                    }
                    #pghRegionSelect option {
                       background-color: #1b2838;
                       color: #c6d4df;
                    }
                     #pghFetchBtn {
                        display: block;
                        width: 100%;
                        padding: 10px;
                        background-color: #67c1f5;
                        color: #1b2838;
                        border: none;
                        border-radius: 3px;
                        cursor: pointer;
                        font-size: 15px;
                        font-weight: bold;
                        transition: background-color 0.2s;
                        margin-bottom: 15px;
                     }
                     #pghFetchBtn:hover:not(:disabled) {
                        background-color: #8ad3f7;
                     }
                     #pghFetchBtn:disabled {
                         background-color: #556772;
                         cursor: default;
                     }
                     #pghResult {
                        margin-top: 15px;
                        padding-top: 15px;
                        border-top: 1px solid #3a4f6a;
                        font-size: 13px;
                        line-height: 1.5;
                     }
                     .pgh_status_loading {
                         text-align: center;
                         color: #8f98a0;
                     }
                     .pgh_status_error {
                         color: #ff6961;
                         font-weight: bold;
                     }
                     .pgh_result_block {
                         padding: 10px;
                         border-radius: 3px;
                         margin-top: 10px;
                         text-align: center;
                         font-weight: bold;
                         font-size: 15px;
                     }
                     .pgh_result_giftable {
                         background-color: rgba(119, 221, 119, 0.2);
                         border: 1px solid #77dd77;
                         color: #dff0d8;
                     }
                     .pgh_result_not_giftable {
                         background-color: rgba(255, 105, 97, 0.2);
                         border: 1px solid #ff6961;
                         color: #f2dede;
                     }
                    #pghCloseBtn {
                        position: absolute;
                        top: 8px;
                        right: 10px;
                        font-size: 24px;
                        color: #8f98a0;
                        background: none;
                        border: none;
                        cursor: pointer;
                        line-height: 1;
                         padding: 0 5px;
                    }
                     #pghCloseBtn:hover {
                        color: #ffffff;
                     }
                `);
            }

            function pgh_parsePrice(priceStr) {
                if (typeof priceStr !== 'string' && typeof priceStr !== 'number') return null;
                const cleaned = String(priceStr).replace(/[^0-9.,]/g, '').replace(',', '.');
                const price = parseFloat(cleaned);
                return isNaN(price) ? null : price;
            }

            function pgh_getCurrentGameInfo() {
                const appIdMatch = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
                pgh_currentAppId = appIdMatch ? appIdMatch[1] : null;

                const priceMeta = document.querySelector('meta[itemprop="price"]');
                const currencyMeta = document.querySelector('meta[itemprop="priceCurrency"]');

                pgh_currentUserPrice = priceMeta ? pgh_parsePrice(priceMeta.content) : null;
                pgh_currentUserCurrencyISO = currencyMeta ? currencyMeta.content.toLowerCase() : null;

                if (pgh_currentUserPrice === null || pgh_currentUserPrice === 0) {
                    const purchaseBlock = document.querySelector('.game_purchase_action .price[data-price-final], .discount_block .discount_final_price[data-price-final]');
                    if (purchaseBlock) {
                        pgh_currentUserPrice = pgh_parsePrice(purchaseBlock.dataset.priceFinal) / 100;
                    } else {
                         const simplePrice = document.querySelector('.game_purchase_action .price:not([data-price-final])');
                         if(simplePrice) {
                              pgh_currentUserPrice = pgh_parsePrice(simplePrice.textContent.trim());
                         }
                    }
                }

                 if (!pgh_currentUserCurrencyISO) {
                    console.warn("[PGH] Не удалось определить валюту пользователя со страницы. Используем RUB по умолчанию.");
                    pgh_currentUserCurrencyISO = 'rub';
                 }

                return pgh_currentAppId && pgh_currentUserPrice !== null && pgh_currentUserCurrencyISO;
            }

            function pgh_showModal() {
                if (!pgh_getCurrentGameInfo()) {
                    alert("Не удалось получить информацию об игре и цене на этой странице.");
                    return;
                }

                if (!pgh_modal) {
                    pgh_modal = document.createElement('div');
                    pgh_modal.id = 'pghModal';
                    pgh_modal.innerHTML = `
                        <button id="pghCloseBtn" title="Закрыть">&times;</button>
                        <h3>Проверить возможность подарка</h3>
                        <label for="pghRegionSelect">Регион друга:</label>
                        <select id="pghRegionSelect">
                            <option value="">-- Выберите регион друга --</option>
                            ${Object.entries(PGH_COUNTRY_CURRENCY_MAP)
                                .sort(([, a], [, b]) => a.name.localeCompare(b.name))
                                .map(([code, data]) => `<option value="${code}">${data.name} (${code})</option>`)
                                .join('')}
                        </select>
                        <button id="pghFetchBtn" disabled>Узнать</button>
                        <div id="pghResult"></div>
                    `;
                    document.body.appendChild(pgh_modal);

                    pgh_resultDiv = document.getElementById('pghResult');
                    pgh_fetchBtn = document.getElementById('pghFetchBtn');
                    pgh_regionSelect = document.getElementById('pghRegionSelect');

                    document.getElementById('pghCloseBtn').addEventListener('click', pgh_hideModal);
                    pgh_fetchBtn.addEventListener('click', pgh_fetchAndComparePrices);
                    pgh_regionSelect.addEventListener('change', () => {
                        pgh_fetchBtn.disabled = !pgh_regionSelect.value;
                    });

                     pgh_modal._outsideClickListener = (event) => {
                         if (!pgh_modal.contains(event.target) && pgh_modal.style.display === 'block') {
                             pgh_hideModal();
                         }
                     };
                     document.addEventListener('click', pgh_modal._outsideClickListener, true);

                     pgh_modal._escListener = (event) => {
                         if (event.key === 'Escape' && pgh_modal.style.display === 'block') {
                             pgh_hideModal();
                         }
                     };
                     document.addEventListener('keydown', pgh_modal._escListener);

                }

                pgh_regionSelect.value = "";
                pgh_fetchBtn.disabled = true;
                pgh_resultDiv.innerHTML = "";
                pgh_modal.style.display = 'block';
            }

            function pgh_hideModal() {
                if (pgh_modal) {
                    pgh_modal.style.display = 'none';
                     if (pgh_modal._outsideClickListener) {
                         document.removeEventListener('click', pgh_modal._outsideClickListener, true);
                     }
                      if (pgh_modal._escListener) {
                          document.removeEventListener('keydown', pgh_modal._escListener);
                      }
                }
            }

            async function pgh_fetchFriendPrice(appId, friendCountryCode) {
                const friendCurrencyInfo = PGH_COUNTRY_CURRENCY_MAP[friendCountryCode];
                if (!friendCurrencyInfo) {
                    throw new Error("Неизвестный код страны друга.");
                }

                const inputJson = {
                    ids: [{ appid: parseInt(appId) }],
                    context: {
                        language: "russian",
                        country_code: friendCountryCode,
                        steam_realm: 1
                    },
                    data_request: {
                        include_basic_info: true,
                        include_all_purchase_options: true
                    }
                };

                return new Promise((resolve, reject) => {
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: `${PGH_API_URL}?input_json=${encodeURIComponent(JSON.stringify(inputJson))}`,
                        timeout: PGH_REQUEST_TIMEOUT_MS,
                        responseType: 'json',
                        onload: function(response) {
                            if (response.status >= 200 && response.status < 400 && response.response) {
                                const itemData = response.response.response?.store_items?.[0];
                                if (itemData?.success === 1 && itemData?.best_purchase_option) {
                                    const priceData = itemData.best_purchase_option;
                                    const friendPriceCents = priceData.final_price_in_cents ? parseInt(priceData.final_price_in_cents, 10) : null;
                                    const canGift = priceData.user_can_purchase_as_gift || false;

                                    if (friendPriceCents !== null) {
                                        resolve({
                                            price: friendPriceCents / 100,
                                            currencyISO: friendCurrencyInfo.iso,
                                            formatted: priceData.formatted_final_price || 'N/A',
                                            canGift: canGift
                                        });
                                    } else {
                                        resolve({
                                            price: 0,
                                            currencyISO: friendCurrencyInfo.iso,
                                            formatted: priceData.formatted_final_price || 'Бесплатно',
                                            canGift: canGift
                                         });
                                    }
                                } else if (itemData?.success === 1 && !itemData?.best_purchase_option){
                                    reject(new Error(`Игра недоступна для покупки в регионе ${friendCountryCode}.`));
                                }
                                else {
                                    reject(new Error("Не удалось получить данные о цене в регионе друга. Возможно, игра не найдена или недоступна."));
                                }
                            } else {
                                reject(new Error(`Ошибка API Steam: Статус ${response.status}`));
                            }
                        },
                        onerror: (error) => reject(new Error('Сетевая ошибка при запросе цены друга')),
                        ontimeout: () => reject(new Error('Таймаут при запросе цены друга'))
                    });
                });
            }

            async function pgh_fetchExchangeRates(baseCurrencyIso) {
                if (pgh_exchangeRates && pgh_exchangeRates[baseCurrencyIso]) {
                    return pgh_exchangeRates[baseCurrencyIso];
                }

                const apiUrl = `${PGH_CURRENCY_API_URL}${baseCurrencyIso.toLowerCase()}.json`;
                return new Promise((resolve, reject) => {
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: apiUrl,
                        responseType: 'json',
                        timeout: PGH_REQUEST_TIMEOUT_MS / 2,
                        onload: (response) => {
                            if (response.status >= 200 && response.status < 400 && response.response) {
                                const rates = response.response[baseCurrencyIso.toLowerCase()];
                                if (rates && typeof rates === 'object') {
                                    if (!pgh_exchangeRates) pgh_exchangeRates = {};
                                    pgh_exchangeRates[baseCurrencyIso] = rates;
                                    resolve(rates);
                                } else {
                                    reject(new Error(`Курсы для ${baseCurrencyIso} не найдены в ответе API`));
                                }
                            } else {
                                reject(new Error(`Ошибка API валют: статус ${response.status}`));
                            }
                        },
                        onerror: (error) => reject(new Error('Сетевая ошибка API валют')),
                        ontimeout: () => reject(new Error('Таймаут запроса API валют'))
                    });
                });
            }

            async function pgh_fetchAndComparePrices() {
                const selectedRegion = pgh_regionSelect.value;
                if (!selectedRegion) return;

                pgh_resultDiv.innerHTML = '<div class="pgh_status_loading">Загрузка данных...</div>';
                pgh_fetchBtn.disabled = true;
                pgh_regionSelect.disabled = true;

                try {
                    const friendPriceData = await pgh_fetchFriendPrice(pgh_currentAppId, selectedRegion);
                    const friendPrice = friendPriceData.price;
                    const friendCurrencyISO = friendPriceData.currencyISO;
                    const canFriendReceiveGift = friendPriceData.canGift;

                    let friendPriceInUserCurrency = friendPrice;
                    let exchangeRateUsed = null;

                    if (pgh_currentUserCurrencyISO !== friendCurrencyISO) {
                        try {
                            const rates = await pgh_fetchExchangeRates(friendCurrencyISO);
                            const rate = rates[pgh_currentUserCurrencyISO];
                            if (rate === undefined || rate === null) {
                                throw new Error(`Нет курса для ${pgh_currentUserCurrencyISO.toUpperCase()}`);
                            }
                            friendPriceInUserCurrency = parseFloat((friendPrice * rate).toFixed(2));
                            exchangeRateUsed = rate;
                        } catch (rateError) {
                            console.error("[PGH] Ошибка получения/использования курса:", rateError);
                            pgh_resultDiv.innerHTML = `<div class="pgh_status_error">Ошибка конвертации валют: ${rateError.message}. Сравнение невозможно.</div>`;
                            return;
                        }
                    }

                    const userPrice = pgh_currentUserPrice;
                    const priceDifference = friendPriceInUserCurrency - userPrice;
                    const priceDifferencePercent = userPrice > 0 ? (priceDifference / userPrice) : (priceDifference > 0 ? Infinity : -Infinity);

                    const isWithinThreshold = Math.abs(priceDifferencePercent) <= PGH_GIFT_PRICE_DIFF_THRESHOLD;
                    const canGift = isWithinThreshold && canFriendReceiveGift;

                    let resultHTML = `
                        Ваша цена: ${userPrice.toLocaleString('ru-RU', { style: 'currency', currency: pgh_currentUserCurrencyISO.toUpperCase(), minimumFractionDigits: 0, maximumFractionDigits: 2 })}<br>
                        Цена друга: ${friendPrice.toLocaleString('ru-RU', { style: 'currency', currency: friendCurrencyISO.toUpperCase(), minimumFractionDigits: 0, maximumFractionDigits: 2 })}
                    `;

                    if (pgh_currentUserCurrencyISO !== friendCurrencyISO && exchangeRateUsed !== null) {
                         resultHTML += ` ≈ ${friendPriceInUserCurrency.toLocaleString('ru-RU', { style: 'currency', currency: pgh_currentUserCurrencyISO.toUpperCase(), minimumFractionDigits: 0, maximumFractionDigits: 2 })}`;
                         resultHTML += ` <small>(курс ≈ ${exchangeRateUsed.toFixed(4)})</small>`;
                    }
                     resultHTML += `<br>`;

                    if (userPrice > 0) {
                         resultHTML += `Разница: ${priceDifference > 0 ? '+' : ''}${priceDifference.toLocaleString('ru-RU', { style: 'currency', currency: pgh_currentUserCurrencyISO.toUpperCase(), minimumFractionDigits: 0, maximumFractionDigits: 2 })}`;
                         resultHTML += ` (${priceDifferencePercent === Infinity || priceDifferencePercent === -Infinity ? 'N/A' : (priceDifferencePercent * 100).toFixed(0)}%)`;
                     } else {
                        resultHTML += `Разница: N/A (ваша цена 0)`;
                     }

                     const resultClass = canGift ? 'pgh_result_giftable' : 'pgh_result_not_giftable';
                     const resultText = canGift ? '~Можно подарить~' : '~Нельзя подарить~';

                     resultHTML += `<div class="pgh_result_block ${resultClass}">${resultText}</div>`;

                     if (!canFriendReceiveGift && isWithinThreshold) {
                        resultHTML += `<small>Примечание: Steam не разрешает покупку этой игры в подарок для данного региона, несмотря на подходящую разницу цен.</small>`;
                     } else if (!isWithinThreshold) {
                         resultHTML += `<small>Примечание: Разница цен (${(priceDifferencePercent * 100).toFixed(0)}%) превышает допустимый порог Steam (${(PGH_GIFT_PRICE_DIFF_THRESHOLD * 100)}%).</small>`;
                     }

                    pgh_resultDiv.innerHTML = resultHTML;

                } catch (error) {
                    console.error("[PGH] Ошибка при получении/сравнении цен:", error);
                    pgh_resultDiv.innerHTML = `<div class="pgh_status_error">Ошибка: ${error.message}</div>`;
                } finally {
                     pgh_fetchBtn.disabled = !pgh_regionSelect.value;
                     pgh_regionSelect.disabled = false;
                }
            }

            function pgh_addGiftButton() {
                const targetArea = document.querySelector('.game_area_purchase_section .game_area_purchase_game_wrapper .game_purchase_action, #add_to_cart > .btn_addtocart > span');
                const referenceButtonContainer = targetArea?.closest('.game_purchase_action') || document.getElementById('add_to_cart');

                 if (!referenceButtonContainer) {
                    console.warn('[PGH] Не найден контейнер для кнопки подарка.');
                    const smButton = document.querySelector('.salesMaster_button');
                    if (smButton) {
                        if (smButton.parentElement.querySelector('.pgh_button')) return;
                         const giftButton = pgh_createButtonElement();
                         smButton.insertAdjacentElement('afterend', giftButton);
                         console.log('[PGH] Кнопка подарка добавлена после SalesMaster.');
                    } else {
                          console.warn('[PGH] SalesMaster кнопка тоже не найдена.');
                     }
                    return;
                 }

                if (referenceButtonContainer.parentElement.querySelector('.pgh_button')) return;

                const giftButton = pgh_createButtonElement();

                referenceButtonContainer.parentNode.insertBefore(giftButton, referenceButtonContainer);
                 console.log('[PGH] Кнопка подарка добавлена.');
            }

            function pgh_createButtonElement() {
                const giftButtonContainer = document.createElement('div');
                giftButtonContainer.className = 'pgh_button queue_control_button';
                giftButtonContainer.style.marginLeft = '3px';

                const giftButton = document.createElement('div');
                giftButton.className = 'btnv6_blue_hoverfade btn_medium';
                giftButton.style.cssText = 'height: 32px; padding: 0 0; font-size: 18px; display: flex; align-items: center; justify-content: center;';
                giftButton.title = 'Проверить возможность подарка другу';
                giftButton.innerHTML = '<span>GIFT</span>';
                giftButton.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    pgh_showModal();
                });

                giftButtonContainer.appendChild(giftButton);
                return giftButtonContainer;
            }

            function pgh_initialize() {
                pgh_addStyles();
                setTimeout(pgh_addGiftButton, 700);

                const observer = new MutationObserver((mutations) => {
                     mutations.forEach((mutation) => {
                         if (mutation.addedNodes.length > 0) {
                              if (document.querySelector('.game_area_purchase_section .game_area_purchase_game_wrapper') && !document.querySelector('.pgh_button')) {
                                   pgh_addGiftButton();
                              }
                         }
                     });
                 });

                 const mainPage = document.querySelector('#game_area_purchase');
                 if (mainPage) {
                     observer.observe(mainPage, { childList: true, subtree: true });
                 }
            }

            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', pgh_initialize);
            } else {
                pgh_initialize();
            }

        })();
    }

    // Скрипт для страницы игры (salesMaster; %; агрегатор цен из разных магазинов) | https://store.steampowered.com/app/*
    if (scriptsConfig.salesMaster && unsafeWindow.location.pathname.includes('/app/')) {
        (function() {
            'use strict';

            // --- Конфигурация SalesMaster (SM) ---
            const SM_STORAGE_PREFIX = 'salesMaster_v1_';
            const SM_EXCLUSION_STORAGE_KEY = SM_STORAGE_PREFIX + 'exclusions';
            const SM_FILTER_STORAGE_KEY = SM_STORAGE_PREFIX + 'filters';
            const SM_SORT_STORAGE_KEY = SM_STORAGE_PREFIX + 'sort';
            const SM_FILTER_DEBOUNCE_MS = 500;
            const SM_REQUEST_TIMEOUT_MS = 15000; // 15 секунд на запрос к магазину

            // --- Глобальные переменные SM ---
            let sm_currentResults = [];
            let sm_stores = {};
            let sm_activeRequests = 0;
            let sm_currentSort = GM_getValue(SM_SORT_STORAGE_KEY, {
                field: 'price',
                direction: 'asc'
            });
            let sm_exclusionKeywords = GM_getValue(SM_EXCLUSION_STORAGE_KEY, []);
            let sm_currentFilters = GM_getValue(SM_FILTER_STORAGE_KEY, {
                priceMin: '',
                priceMax: '',
                discountPercentMin: '',
                discountPercentMax: '',
                discountAmountMin: '',
                discountAmountMax: '',
                hasDiscount: false,
                stores: {}
            });
            let sm_filterDebounceTimeout;

            // --- Переменные для конвертации валют ---
            const SM_CURRENCY_MODE_STORAGE_KEY = SM_STORAGE_PREFIX + 'currencyMode';
            let sm_currentCurrencyMode = GM_getValue(SM_CURRENCY_MODE_STORAGE_KEY, 'RUB');
            let sm_exchangeRates = {};

            // --- DOM Элементы SM ---
            let sm_modal, sm_closeBtn, sm_searchBtn;
            let sm_resultsContainer, sm_resultsDiv, sm_statusDiv;
            let sm_filtersPanel, sm_exclusionTagsDiv, sm_exclusionTagsListDiv, sm_excludeInput, sm_addExcludeBtn;
            let sm_sortButtonsContainer;
            let sm_filterStoreCheckboxesContainer;

            // --- Вспомогательные функции SM ---
            function sm_parsePrice(priceStr) {
                if (!priceStr) return null;
                const cleaned = String(priceStr).replace(/[^0-9.,]/g, '').replace(',', '.');
                const price = parseFloat(cleaned);
                return isNaN(price) ? null : price;
            }

            function sm_parsePercent(percentStr) {
                if (!percentStr) return null;
                const cleaned = String(percentStr).replace(/[^\d.]/g, '');
                const percent = parseFloat(cleaned);
                return isNaN(percent) ? null : percent;
            }

            function sm_calculateMissingValues(item) {
                const price = item.currentPrice;
                let original = item.originalPrice;
                let percent = item.discountPercent;
                let amount = item.discountAmount;

                if (price === null) return item;

                // 1. Есть цена и процент -> считаем оригинал и сумму скидки
                if (price !== null && percent !== null && original === null) {
                    if (percent > 0 && percent < 100) {
                        original = price / (1 - percent / 100);
                    } else {
                        original = price;
                    }
                }

                // 2. Есть цена и оригинал -> считаем процент и сумму скидки
                if (price !== null && original !== null && percent === null && original > price) {
                    percent = ((original - price) / original) * 100;
                } else if (price !== null && original !== null && percent === null && original <= price) {
                    percent = 0;
                }

                // 3. Есть цена и сумма скидки -> считаем оригинал и процент
                if (price !== null && amount !== null && original === null) {
                    original = price + amount;
                }
                if (price !== null && amount !== null && percent === null && original !== null && original > 0) {
                    percent = (amount / original) * 100;
                }

                // 4. Всегда считаем сумму скидки, если есть цена и оригинал
                if (price !== null && original !== null && amount === null && original > price) {
                    amount = original - price;
                } else if (price !== null && original !== null && amount === null && original <= price) {
                    amount = 0;
                }

                item.originalPrice = original !== null ? parseFloat(original.toFixed(2)) : null;
                item.discountPercent = percent !== null ? parseFloat(percent.toFixed(1)) : null;
                item.discountAmount = amount !== null ? parseFloat(amount.toFixed(2)) : null;

                if (item.discountPercent !== null && item.discountPercent <= 0) {
                    item.discountPercent = 0;
                    item.discountAmount = 0;
                    if (item.originalPrice === null && item.currentPrice !== null) {
                        item.originalPrice = item.currentPrice;
                    }
                }
                if (item.originalPrice === null && item.currentPrice !== null) {
                    item.originalPrice = item.currentPrice;
                    item.discountPercent = 0;
                    item.discountAmount = 0;
                }


                return item;
            }

            function sm_getSteamGameName() {
                const appNameElement = document.querySelector('#appHubAppName');
                return appNameElement ? appNameElement.textContent.trim() : '';
            }

            function sm_logError(storeName, message, error = null) {
                console.error(`[SalesMaster][${storeName}] ${message}`, error || '');
            }

            function sm_debounce(func, wait) {
                let timeout;
                return function executedFunction(...args) {
                    const later = () => {
                        clearTimeout(timeout);
                        func(...args);
                    };
                    clearTimeout(timeout);
                    timeout = setTimeout(later, wait);
                };
            }

            // --- Функция для получения курсов валют ---
            async function sm_fetchExchangeRates(baseCurrency) {
                const lowerBase = baseCurrency.toLowerCase();
                if (sm_exchangeRates[lowerBase] && Object.keys(sm_exchangeRates[lowerBase]).length > 0) {
                    return sm_exchangeRates[lowerBase];
                }

                const apiUrl = `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/${lowerBase}.json`;
                return new Promise((resolve, reject) => {
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: apiUrl,
                        responseType: 'json',
                        timeout: SM_REQUEST_TIMEOUT_MS / 2,
                        onload: (response) => {
                            if (response.status >= 200 && response.status < 400 && response.response) {
                                const rates = response.response[lowerBase];
                                if (rates && typeof rates === 'object') {
                                    sm_exchangeRates[lowerBase] = rates;
                                    resolve(rates);
                                } else {
                                    reject(new Error(`Не найдены курсы для ${baseCurrency} в ответе API`));
                                }
                            } else {
                                reject(new Error(`Ошибка API валют: статус ${response.status}`));
                            }
                        },
                        onerror: (error) => reject(new Error('Сетевая ошибка API валют')),
                        ontimeout: () => reject(new Error('Таймаут запроса API валют'))
                    });
                });
            }

            // --- Создание UI SalesMaster ---

            function sm_updateCurrencyToggleButton() {
                const toggleBtn = document.getElementById('smCurrencyToggleBtn');
                if (!toggleBtn) return;
                if (sm_currentCurrencyMode === 'USD') {
                    toggleBtn.textContent = 'RUB';
                    toggleBtn.title = 'Переключиться на рубли';
                } else {
                    toggleBtn.textContent = 'USD';
                    toggleBtn.title = 'Переключиться на доллары США';
                }
            }

            function sm_showUsdSwitchConfirmation() {
                const hideWarning = GM_getValue('salesMaster_hideUsdWarning', false);
                if (hideWarning) {
                    sm_switchToUsdMode();
                    return;
                }

                const dialog = document.createElement('div');
                dialog.id = 'smUsdConfirmDialog';
                Object.assign(dialog.style, {
                    position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
                    backgroundColor: '#1f2c3a', color: '#c6d4df', padding: '25px', borderRadius: '5px',
                    boxShadow: '0 0 20px rgba(0,0,0,0.7)', zIndex: '10005', textAlign: 'left',
                    border: '1px solid #FFB300', maxWidth: '450px'
                });
                dialog.innerHTML = `
                    <h4 style="margin-top:0; color:#FFB300;">Переключение в режим USD</h4>
                    <p style="margin-bottom:20px; line-height:1.6;">Цены из всех магазинов будут конвертированы и отображены в долларах США (USD). Это может быть полезно для сравнения цен в международном контексте.<br><br>Продолжить?</p>
                    <div style="margin-bottom: 20px;"><label><input type="checkbox" id="smDontShowAgainUsd" style="margin-right:8px;">Больше не показывать</label></div>
                    <div style="text-align:right;">
                        <button id="smConfirmYes" class="salesMasterBtn" style="background-color:#FFB300; color:#1b2838; margin-right:10px;">Да</button>
                        <button id="smConfirmNo" class="salesMasterBtn">Отмена</button>
                    </div>
                `;
                document.body.appendChild(dialog);

                document.getElementById('smConfirmYes').onclick = () => {
                    if (document.getElementById('smDontShowAgainUsd').checked) {
                        GM_setValue('salesMaster_hideUsdWarning', true);
                    }
                    sm_switchToUsdMode();
                    dialog.remove();
                };
                document.getElementById('smConfirmNo').onclick = () => dialog.remove();
            }

            function sm_switchToUsdMode() {
                sm_currentCurrencyMode = 'USD';
                GM_setValue(SM_CURRENCY_MODE_STORAGE_KEY, 'USD');
                sm_updateCurrencyToggleButton();
                sm_applySort(sm_currentSort.field, sm_currentSort.direction);
                sm_renderResults();
                sm_updateFilterPlaceholders();
                sm_applyFilters();
                sm_updateSortButtonsState();
            }

            function sm_switchToRubMode() {
                sm_currentCurrencyMode = 'RUB';
                GM_setValue(SM_CURRENCY_MODE_STORAGE_KEY, 'RUB');
                sm_updateCurrencyToggleButton();
                sm_applySort(sm_currentSort.field, sm_currentSort.direction);
                sm_renderResults();
                sm_updateFilterPlaceholders();
                sm_applyFilters();
                sm_updateSortButtonsState();
            }

            function sm_handleCurrencyToggle() {
                if (sm_currentCurrencyMode === 'RUB') {
                    sm_showUsdSwitchConfirmation();
                } else {
                    sm_switchToRubMode();
                }
            }

            function sm_createModal() {
                const existingModal = document.querySelector('#salesMasterModal');
                if (existingModal) existingModal.remove();

                sm_modal = document.createElement('div');
                sm_modal.id = 'salesMasterModal';

                const container = document.createElement('div');
                container.id = 'salesMasterContainer';

                const header = document.createElement('div');
                header.id = 'salesMasterHeader';

                // --- Левая часть шапки ---
                sm_searchBtn = document.createElement('button');
                sm_searchBtn.textContent = 'Обновить %';
                sm_searchBtn.id = 'salesMasterSearchGoBtn';
                sm_searchBtn.className = 'salesMasterBtn';
                sm_searchBtn.title = 'Запросить цены с магазинов';
                sm_searchBtn.onclick = sm_triggerSearch;
                header.appendChild(sm_searchBtn);

                const headerStatusDiv = document.createElement('div');
                headerStatusDiv.id = 'salesMasterHeaderStatus';
                header.appendChild(headerStatusDiv);

                // --- Разделитель ---
                const spacer = document.createElement('div');
                spacer.style.flexGrow = '1';
                header.appendChild(spacer);

                // --- Правая часть шапки ---
                const rightControls = document.createElement('div');
                rightControls.style.display = 'flex';
                rightControls.style.alignItems = 'center';
                rightControls.style.gap = '10px';

                const insertTitleBtn = document.createElement('button');
                insertTitleBtn.id = 'smInsertTitleBtn';
                insertTitleBtn.className = 'salesMasterBtn smInsertTitleBtn';
                insertTitleBtn.textContent = 'Подставить название >';
                insertTitleBtn.title = 'Подставить название текущей игры в фильтр';
                insertTitleBtn.onclick = () => {
                    const gameName = sm_getSteamGameName();
                    const filterInput = document.getElementById('smTitleFilterInput');
                    if (gameName && filterInput) {
                        filterInput.value = gameName;
                        sm_applyFilters();
                        filterInput.focus();
                    }
                };
                rightControls.appendChild(insertTitleBtn);

                const titleFilterInput = document.createElement('input');
                titleFilterInput.type = 'text';
                titleFilterInput.id = 'smTitleFilterInput';
                titleFilterInput.placeholder = 'Фильтр по названию (слова через ;)';
                titleFilterInput.addEventListener('input', sm_debounce(sm_applyFilters, SM_FILTER_DEBOUNCE_MS));
                rightControls.appendChild(titleFilterInput);

                const currencyToggleBtn = document.createElement('button');
                currencyToggleBtn.id = 'smCurrencyToggleBtn';
                currencyToggleBtn.className = 'salesMasterBtn';
                currencyToggleBtn.onclick = sm_handleCurrencyToggle;
                rightControls.appendChild(currencyToggleBtn);

                sm_sortButtonsContainer = document.createElement('div');
                sm_sortButtonsContainer.id = 'salesMasterSortButtons';
                rightControls.appendChild(sm_sortButtonsContainer);

                const resetSortBtn = document.createElement('button');
                resetSortBtn.id = 'salesMasterResetSortBtn';
                resetSortBtn.className = 'salesMasterBtn';
                resetSortBtn.title = 'Сбросить сортировку (По Цене)';
                resetSortBtn.innerHTML = `<svg viewBox="0 0 24 24"><path fill="currentColor" d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6s-2.69 6-6 6s-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8s-3.58-8-8-8Z"/></svg>`;
                resetSortBtn.onclick = () => sm_resetSort(true);
                sm_sortButtonsContainer.appendChild(resetSortBtn);

                sm_createSortButton('price', 'Цена');
                sm_createSortButton('discountPercent', '% Скидки');
                sm_createSortButton('discountAmount', 'Скидка');
                sm_createSortButton('name', 'Название');

                header.appendChild(rightControls);
                container.appendChild(header);

                sm_resultsContainer = document.createElement('div');
                sm_resultsContainer.id = 'salesMasterResultsContainer';
                sm_resultsContainer.style.paddingTop = '0';
                sm_resultsDiv = document.createElement('div');
                sm_resultsDiv.id = 'salesMasterResults';
                sm_resultsContainer.appendChild(sm_resultsDiv);
                container.appendChild(sm_resultsContainer);
                sm_filtersPanel = document.createElement('div');
                sm_filtersPanel.id = 'salesMasterFiltersPanel';
                sm_filtersPanel.innerHTML = `
                    <div class="smFilterGroup"><h4>Цена, ${sm_getCurrencySymbol()} ${sm_createResetButtonHTML('price')}</h4><div class="smFilterRangeInputs"><input type="number" id="smFilterPriceMin" placeholder="от" min="0"><input type="number" id="smFilterPriceMax" placeholder="до" min="0"></div></div>
                    <div class="smFilterGroup"><h4>Скидка, % ${sm_createResetButtonHTML('discountPercent')}</h4><div class="smFilterRangeInputs"><input type="number" id="smFilterDiscountPercentMin" placeholder="от" min="0" max="100"><input type="number" id="smFilterDiscountPercentMax" placeholder="до" min="0" max="100"></div></div>
                    <div class="smFilterGroup"><h4>Скидка, ${sm_getCurrencySymbol()} ${sm_createResetButtonHTML('discountAmount')}</h4><div class="smFilterRangeInputs"><input type="number" id="smFilterDiscountAmountMin" placeholder="от" min="0"><input type="number" id="smFilterDiscountAmountMax" placeholder="до" min="0"></div></div>
                    <div class="smFilterGroup"><h4>Опции ${sm_createResetButtonHTML('options')}</h4><div class="smFilterCheckbox"><label><input type="checkbox" id="smFilterHasDiscount"> Только со скидкой</label></div></div>
                    <div class="smFilterGroup">
                        <h4>Магазины ${sm_createResetButtonHTML('stores')}</h4>
                        <div class="smStoreSelectAllControls">
                            <span class="smStoreSelectAllLink" id="smSelectAllStores">Отметить всё</span>
                            <span class="smStoreSelectSeparator">|</span>
                            <span class="smStoreSelectAllLink" id="smDeselectAllStores">Снять всё</span>
                        </div>
                        <div id="smFilterStoreCheckboxes"></div>
                    </div>
                    <button id="smResetAllFiltersBtn" class="salesMasterBtn">Сбросить все фильтры</button>
                `;
                sm_modal.appendChild(sm_filtersPanel);
                sm_exclusionTagsDiv = document.createElement('div');
                sm_exclusionTagsDiv.id = 'salesMasterExclusionTags';
                const exclusionInputGroup = document.createElement('div');
                exclusionInputGroup.className = 'smExclusionInputGroup';
                sm_excludeInput = document.createElement('input');
                sm_excludeInput.type = 'text';
                sm_excludeInput.id = 'salesMasterExcludeInput';
                sm_excludeInput.placeholder = 'Исключить слово';
                sm_excludeInput.onkeydown = (e) => { if (e.key === 'Enter') sm_addExclusionKeyword(); };
                sm_addExcludeBtn = document.createElement('button');
                sm_addExcludeBtn.id = 'salesMasterAddExcludeBtn';
                sm_addExcludeBtn.innerHTML = `<svg viewBox="0 0 20 20"><path fill="currentColor" d="M10 2.5a.75.75 0 0 1 .75.75v6h6a.75.75 0 0 1 0 1.5h-6v6a.75.75 0 0 1-1.5 0v-6h-6a.75.75 0 0 1 0-1.5h6v-6a.75.75 0 0 1 .75-.75Z" /></svg>`;
                sm_addExcludeBtn.onclick = sm_addExclusionKeyword;
                exclusionInputGroup.appendChild(sm_excludeInput);
                exclusionInputGroup.appendChild(sm_addExcludeBtn);
                sm_exclusionTagsDiv.appendChild(exclusionInputGroup);
                const exclusionActionsDiv = document.createElement('div');
                exclusionActionsDiv.className = 'smExclusionActions';
                const exportBtn = document.createElement('button');
                exportBtn.id = 'smExportExclusionsBtn';
                exportBtn.className = 'salesMasterBtn smExclusionActionBtn';
                exportBtn.title = 'Экспорт списка исключений';
                exportBtn.innerHTML = '←'
                exportBtn.onclick = sm_exportExclusions;
                exclusionActionsDiv.appendChild(exportBtn);
                const importBtn = document.createElement('button');
                importBtn.id = 'smImportExclusionsBtn';
                importBtn.className = 'salesMasterBtn smExclusionActionBtn';
                importBtn.title = 'Импорт списка исключений';
                importBtn.innerHTML = '→';
                importBtn.onclick = sm_showImportModal;
                exclusionActionsDiv.appendChild(importBtn);
                sm_exclusionTagsDiv.appendChild(exclusionActionsDiv);
                sm_exclusionTagsListDiv = document.createElement('div');
                sm_exclusionTagsListDiv.id = 'salesMasterExclusionTagsList';
                sm_exclusionTagsDiv.appendChild(sm_exclusionTagsListDiv);
                sm_modal.appendChild(sm_exclusionTagsDiv);
                sm_closeBtn = document.createElement('button');
                sm_closeBtn.id = 'salesMasterCloseBtn';
                sm_closeBtn.innerHTML = '&times;';
                sm_closeBtn.onclick = sm_hideModal;
                sm_modal.appendChild(sm_closeBtn);
                sm_modal.appendChild(container);
                document.body.appendChild(sm_modal);

                document.getElementById('smSelectAllStores')?.addEventListener('click', sm_selectAllStores);
                document.getElementById('smDeselectAllStores')?.addEventListener('click', sm_deselectAllStores);

                sm_setupFilterEventListeners();
                sm_applyLoadedFiltersToUI();
                sm_renderExclusionTags();
                sm_renderStoreCheckboxes();
                sm_updateSortButtonsState();
                sm_positionSidePanels();

                function handleEsc(event) {
                    if (event.key === 'Escape') {
                        const importModal = document.getElementById('smImportModal');
                        if (importModal) { importModal.remove(); }
                        else { sm_hideModal(); }
                    }
                }
                document.addEventListener('keydown', handleEsc);
                sm_modal._escHandler = handleEsc;
            }

            function sm_exportExclusions() {
                const keywordsString = sm_exclusionKeywords.join(',');
                if (!keywordsString) {
                    alert('Список исключений пуст.');
                    return;
                }
                try {
                    navigator.clipboard.writeText(keywordsString).then(() => {
                        const exportBtn = document.getElementById('smExportExclusionsBtn');
                        if (exportBtn) {
                            const originalContent = exportBtn.innerHTML;
                            exportBtn.innerHTML = 'Скопировано!';
                            exportBtn.disabled = true;
                            setTimeout(() => {
                                exportBtn.innerHTML = originalContent;
                                exportBtn.disabled = false;
                            }, 1500);
                        }
                    }, (err) => {
                        console.error('[SalesMaster] Не удалось скопировать в буфер обмена:', err);
                        prompt('Не удалось скопировать автоматически. Скопируйте вручную:', keywordsString);
                    });
                } catch (err) {
                    console.error('[SalesMaster] Ошибка доступа к буферу обмена:', err);
                    prompt('Не удалось скопировать автоматически. Скопируйте вручную:', keywordsString);
                }
            }

            function sm_showImportModal() {
                const existingModal = document.getElementById('smImportModal');
                if (existingModal) existingModal.remove();

                const importModal = document.createElement('div');
                importModal.id = 'smImportModal';
                importModal.innerHTML = `
                    <div class="smImportModalContent">
                        <h4>Импорт списка исключений</h4>
                        <p>Вставьте список слов, разделенных запятыми:</p>
                        <textarea id="smImportTextarea" rows="6"></textarea>
                        <div class="smImportModalActions">
                            <button id="smImportAcceptBtn" class="salesMasterBtn">Принять</button>
                            <button id="smImportCancelBtn" class="salesMasterBtn">Отмена</button>
                        </div>
                    </div>
                `;
                document.body.appendChild(importModal);

                document.getElementById('smImportAcceptBtn').onclick = sm_handleImport;
                document.getElementById('smImportCancelBtn').onclick = () => importModal.remove();
                document.getElementById('smImportTextarea').focus();
            }

            function sm_handleImport() {
                const textarea = document.getElementById('smImportTextarea');
                const importModal = document.getElementById('smImportModal');
                if (!textarea || !importModal) return;

                const text = textarea.value.trim();
                if (text) {
                    const importedKeywords = text.split(',')
                                               .map(k => k.trim().toLowerCase())
                                               .filter(k => k.length > 0);
                    sm_exclusionKeywords = [...new Set(importedKeywords)];
                    GM_setValue(SM_EXCLUSION_STORAGE_KEY, sm_exclusionKeywords);
                    sm_renderExclusionTags();
                    sm_applyFilters();
                    console.log('[SalesMaster] Список исключений импортирован.');
                } else {
                    alert("Поле ввода пустое. Импорт не выполнен.");
                }
                importModal.remove();
            }

            function sm_highlightErrorStores() {
                if (!sm_filterStoreCheckboxesContainer) return;

                sm_storeModules.filter(store => store && store.id).forEach(store => {
                    const checkboxContainer = sm_filterStoreCheckboxesContainer.querySelector(`#smStoreFilter-${store.id}`)?.closest('.smFilterCheckbox');
                    if (checkboxContainer) {
                        const storeStatus = sm_stores[store.id]?.status;
                        if (storeStatus === 'error') {
                            checkboxContainer.classList.add('sm-store-error');
                        } else {
                            checkboxContainer.classList.remove('sm-store-error');
                        }
                    }
                });
            }

            // --- Функции для управления выбором магазинов ---
            function sm_selectAllStores() {
                const storeCheckboxes = document.querySelectorAll('#smFilterStoreCheckboxes input[type="checkbox"]');
                if (!storeCheckboxes || storeCheckboxes.length === 0) return;

                let changed = false;
                storeCheckboxes.forEach(cb => {
                    if (!cb.checked) {
                        cb.checked = true;
                        if (cb.dataset.storeId) {
                            sm_currentFilters.stores[cb.dataset.storeId] = true;
                        }
                        changed = true;
                    }
                });

                if (changed) {
                    GM_setValue(SM_FILTER_STORAGE_KEY, sm_currentFilters);
                    sm_applyFilters();
                }
            }

            function sm_deselectAllStores() {
                const storeCheckboxes = document.querySelectorAll('#smFilterStoreCheckboxes input[type="checkbox"]');
                 if (!storeCheckboxes || storeCheckboxes.length === 0) return;

                let changed = false;
                storeCheckboxes.forEach(cb => {
                    if (cb.checked) {
                        cb.checked = false;
                         if (cb.dataset.storeId) {
                            sm_currentFilters.stores[cb.dataset.storeId] = false;
                        }
                        changed = true;
                    }
                });

                if (changed) {
                    GM_setValue(SM_FILTER_STORAGE_KEY, sm_currentFilters);
                    sm_applyFilters();
                }
            }

            function sm_positionSidePanels() {
                requestAnimationFrame(() => {
                    const header = document.getElementById('salesMasterHeader');
                    const resultsContainer = document.getElementById('salesMasterResultsContainer');
                    if (!header || !resultsContainer || !sm_filtersPanel || !sm_exclusionTagsDiv) return;

                    const headerRect = header.getBoundingClientRect();
                    const headerHeight = header.offsetHeight;
                    const topOffset = headerRect.top + headerHeight + 15;
                    const bottomOffset = 20;
                    const availableHeight = `calc(100vh - ${topOffset}px - ${bottomOffset}px)`;

                    sm_filtersPanel.style.position = 'fixed';
                    sm_filtersPanel.style.left = `15px`;
                    sm_filtersPanel.style.top = `${topOffset}px`;
                    sm_filtersPanel.style.maxHeight = availableHeight;
                    sm_filtersPanel.style.visibility = 'visible';

                    sm_exclusionTagsDiv.style.position = 'fixed';
                    sm_exclusionTagsDiv.style.right = `15px`;
                    sm_exclusionTagsDiv.style.top = `${topOffset}px`;
                    sm_exclusionTagsDiv.style.maxHeight = availableHeight;
                    sm_exclusionTagsDiv.style.visibility = 'visible';

                    const filterPanelWidth = sm_filtersPanel.offsetWidth;
                    const exclusionPanelWidth = sm_exclusionTagsDiv.offsetWidth;
                    const contentSidePadding = 25;

                    header.style.paddingLeft = `${filterPanelWidth + contentSidePadding}px`;
                    header.style.paddingRight = `${exclusionPanelWidth + contentSidePadding}px`;

                    resultsContainer.style.paddingLeft = `${filterPanelWidth + contentSidePadding}px`;
                    resultsContainer.style.paddingRight = `${exclusionPanelWidth + contentSidePadding}px`;
                    resultsContainer.style.paddingTop = `0`;
                    resultsContainer.style.paddingBottom = `20px`;
                    resultsContainer.style.height = `calc(100% - ${headerHeight}px)`;
                    resultsContainer.style.overflowY = 'auto';
                    resultsContainer.style.scrollbarColor = '#4b6f9c #17202d';
                    resultsContainer.style.scrollbarWidth = 'thin';


                });
            }

            function sm_createSortButton(field, text) {
                const btn = document.createElement('button');
                btn.className = 'salesMasterBtn sortBtn';
                btn.dataset.sort = field;
                btn.textContent = text;
                btn.onclick = () => sm_handleSort(field);
                sm_sortButtonsContainer.appendChild(btn);
            }

            function sm_createResetButtonHTML(filterKey) {
                return `<button class="smFilterResetBtn" title="Сбросить фильтр" data-filter-key="${filterKey}"><svg viewBox="0 0 24 24"><path fill="currentColor" d="M13 3a9 9 0 0 0-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.954 8.954 0 0 0 13 21a9 9 0 0 0 0-18zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"></path></svg></button>`;
            }

            function sm_renderStoreCheckboxes() {
                sm_filterStoreCheckboxesContainer = document.getElementById('smFilterStoreCheckboxes');
                if (!sm_filterStoreCheckboxesContainer) return;
                sm_filterStoreCheckboxesContainer.innerHTML = '';

                sm_storeModules.filter(store => store && typeof store.id === 'string').forEach(store => {
                    const div = document.createElement('div');
                    div.className = 'smFilterCheckbox';
                    const label = document.createElement('label');
                    const checkbox = document.createElement('input');
                    checkbox.type = 'checkbox';
                    checkbox.id = `smStoreFilter-${store.id}`;
                    checkbox.dataset.storeId = store.id;
                    checkbox.checked = sm_currentFilters.stores[store.id] !== false;
                    checkbox.addEventListener('change', sm_handleStoreFilterChange);

                    label.appendChild(checkbox);
                    label.appendChild(document.createTextNode(` ${store.name}`));
                    div.appendChild(label);
                    sm_filterStoreCheckboxesContainer.appendChild(div);
                });
            }

            function sm_handleStoreFilterChange(event) {
                const storeId = event.target.dataset.storeId;
                const isChecked = event.target.checked;
                sm_currentFilters.stores[storeId] = isChecked;
                GM_setValue(SM_FILTER_STORAGE_KEY, sm_currentFilters);
                sm_applyFilters();
            }


            async function sm_showModal() {
                if (!sm_modal) sm_createModal();

                try {
                    sm_updateStatus('Загрузка курсов валют...', true);
                    await sm_fetchExchangeRates('rub');
                    sm_updateStatus('Нажмите "Обновить %" для поиска цен...');
                } catch (e) {
                    sm_updateStatus('Ошибка загрузки курсов валют!', false);
                    console.error("[SalesMaster] Не удалось загрузить курсы валют при открытии модального окна:", e);
                }

                if (sm_currentResults.length > 0 || sm_resultsDiv.innerHTML !== '') {
                    sm_resultsDiv.innerHTML = '';
                    sm_currentResults = [];
                }
                const titleFilterInput = document.getElementById('smTitleFilterInput');
                if (titleFilterInput) titleFilterInput.value = '';

                document.body.style.overflow = 'hidden';
                sm_modal.style.display = 'block';
                sm_modal.scrollTop = 0;

                sm_renderExclusionTags();
                sm_applyLoadedFiltersToUI();
                sm_updateSortButtonsState();
                sm_renderStoreCheckboxes();
                sm_positionSidePanels();
                sm_updateCurrencyToggleButton();

                sm_applyFilters();
            }

            function sm_hideModal() {
                if (sm_modal) {
                    sm_modal.style.display = 'none';
                    if (sm_modal._escHandler) {
                        document.removeEventListener('keydown', sm_modal._escHandler);
                        delete sm_modal._escHandler;
                    }
                }
                document.body.style.overflow = '';
            }

            // --- Обновление статуса ---
            function sm_updateStatus(message, isLoading = false) {
                const headerStatusDiv = document.getElementById('salesMasterHeaderStatus');
                if (headerStatusDiv) {
                    headerStatusDiv.innerHTML = message + (isLoading ? ' <span class="spinner"></span>' : '');
                }
                if (sm_searchBtn) {
                    if (isLoading) {
                        sm_searchBtn.disabled = true;
                    } else {
                        sm_searchBtn.disabled = false;
                        sm_searchBtn.textContent = 'Обновить %';
                    }
                }
            }

            // --- Запуск поиска ---
            async function sm_triggerSearch() {
                const gameName = sm_getSteamGameName();
                if (!gameName) {
                    sm_updateStatus('Не удалось определить название игры на странице Steam.');
                    return;
                }

                const titleFilterInput = document.getElementById('smTitleFilterInput');
                if (titleFilterInput) titleFilterInput.value = '';

                sm_currentResults = [];
                sm_resultsDiv.innerHTML = '';
                sm_stores = {};
                sm_highlightErrorStores();
                sm_updateStatus(`Поиск "${gameName}"...`, true);
                sm_activeRequests = 0;


                const promises = [];
                let totalStoresToCheck = 0;

                sm_storeModules.filter(m => m && typeof m.fetch === 'function').forEach(storeModule => {
                    if (sm_currentFilters.stores[storeModule.id] !== false) {
                        totalStoresToCheck++;
                        sm_activeRequests++;
                        sm_stores[storeModule.id] = {
                            name: storeModule.name,
                            status: 'pending',
                            error: null
                        };
                        promises.push(
                            storeModule.fetch(gameName)
                            .then(results => {
                                sm_stores[storeModule.id].status = 'success';
                                return results;
                            })
                            .catch(error => {
                                sm_stores[storeModule.id].status = 'error';
                                sm_stores[storeModule.id].error = error.message || 'Неизвестная ошибка';
                                sm_logError(storeModule.name, `Ошибка при запросе: ${sm_stores[storeModule.id].error}`, error);
                                return [];
                            })
                            .finally(() => {
                                sm_activeRequests--;
                                sm_updateLoadingProgress(totalStoresToCheck);
                            })
                        );
                    } else {
                        sm_stores[storeModule.id] = {
                            name: storeModule.name,
                            status: 'skipped',
                            error: null
                        };
                    }
                });

                if (promises.length === 0) {
                    sm_updateStatus('Нет активных магазинов для поиска.');
                    return;
                }

                const resultsArrays = await Promise.all(promises);

                sm_currentResults = resultsArrays.flat();

                sm_updateLoadingProgress(totalStoresToCheck);
                if (sm_currentResults.length > 0) {
                    sm_applySort(sm_currentSort.field, sm_currentSort.direction);
                    sm_renderResults();
                    sm_updateFilterPlaceholders();
                } else {
                    sm_applyFilters();
                }
            }

            function sm_updateLoadingProgress(totalStores) {
                const completedStores = Object.values(sm_stores).filter(s => s.status !== 'pending').length;
                const skippedStores = Object.values(sm_stores).filter(s => s.status === 'skipped').length;
                const successStores = Object.values(sm_stores).filter(s => s.status === 'success').length;
                const errorStores = Object.values(sm_stores).filter(s => s.status === 'error');

                const searchedCompletedCount = completedStores - skippedStores;

                if (sm_activeRequests > 0) {
                    sm_updateStatus(`Загрузка... (${searchedCompletedCount}/${totalStores})`, true);
                } else {
                    let statusMessage = '';
                    if (sm_currentResults.length > 0) {
                        statusMessage = `Найдено ${sm_currentResults.length} предложений. `;
                    } else {
                         const gameName = sm_getSteamGameName();
                        if (gameName) {
                           statusMessage = `Предложений не найдено. `;
                        } else {
                           statusMessage = `Введите запрос или обновите для поиска.`;
                        }
                    }
                    if (errorStores.length > 0) {
                        statusMessage += `Ошибки в магазинах: ${errorStores.map(s => s.name).join(', ')}.`;
                    }
                    if (sm_currentResults.length === 0 && errorStores.length === 0 && sm_activeRequests === 0 && sm_getSteamGameName()) {
                         statusMessage = `По запросу "${sm_getSteamGameName()}" ничего не найдено в выбранных магазинах.`;
                    }

                    sm_updateStatus(statusMessage.trim(), false);
                    sm_highlightErrorStores();

                    const anyFilterActive = (parseFloat(sm_currentFilters.priceMin) || 0) > 0 || (parseFloat(sm_currentFilters.priceMax) || Infinity) < Infinity ||
                                            (parseFloat(sm_currentFilters.discountPercentMin) || 0) > 0 || (parseFloat(sm_currentFilters.discountPercentMax) || 100) < 100 ||
                                            (parseFloat(sm_currentFilters.discountAmountMin) || 0) > 0 || (parseFloat(sm_currentFilters.discountAmountMax) || Infinity) < Infinity ||
                                            sm_currentFilters.hasDiscount || sm_exclusionKeywords.length > 0 ||
                                            Object.values(sm_currentFilters.stores).some(v => v === false) ||
                                            (document.getElementById('smTitleFilterInput')?.value.trim() || '').length > 0;
                    const visibleItems = sm_resultsDiv.querySelectorAll('.salesMasterItem:not(.hidden-by-filter)').length;

                    if (visibleItems === 0 && sm_currentResults.length > 0 && anyFilterActive) {
                        const statusDivInHeader = document.getElementById('salesMasterHeaderStatus');
                        if (statusDivInHeader) {
                            let currentStatus = statusDivInHeader.textContent.replace(' Нет товаров, соответствующих фильтрам.', '');
                            statusDivInHeader.textContent = currentStatus.trim() + ' Нет товаров, соответствующих фильтрам.';
                        }
                    }
                }
            }

            // --- Сортировка ---
            function sm_handleSort(field) {
                const defaultDirections = {
                    price: 'asc',
                    discountPercent: 'desc',
                    discountAmount: 'desc',
                    name: 'asc'
                };
                let newDirection;

                if (sm_currentSort.field === field) {
                    newDirection = sm_currentSort.direction === 'asc' ? 'desc' : 'asc';
                } else {
                    newDirection = defaultDirections[field] || 'asc';
                }

                sm_currentSort.field = field;
                sm_currentSort.direction = newDirection;
                GM_setValue(SM_SORT_STORAGE_KEY, sm_currentSort);

                sm_applySort(field, newDirection);
                sm_renderResults();
                sm_updateSortButtonsState();
            }

            function sm_applySort(field, direction) {
                const dirMultiplier = direction === 'asc' ? 1 : -1;

                sm_currentResults.sort((a, b) => {
                    let valA, valB;

                    switch (field) {
                        case 'price':
                            valA = a.currentPrice ?? (direction === 'asc' ? Infinity : -Infinity);
                            valB = b.currentPrice ?? (direction === 'asc' ? Infinity : -Infinity);
                            break;
                        case 'discountPercent':
                            valA = a.discountPercent ?? -1;
                            valB = b.discountPercent ?? -1;
                            break;
                        case 'discountAmount':
                            const amountA = a.discountAmount;
                            const amountB = b.discountAmount;
                            if (amountA === null && amountB === null) valA = valB = 0;
                            else if (amountA === null) valA = direction === 'desc' ? -Infinity : Infinity;
                            else if (amountB === null) valB = direction === 'desc' ? -Infinity : Infinity;
                            else {
                                valA = amountA;
                                valB = amountB;
                            }
                            break;
                        case 'name':
                            valA = a.productName?.toLowerCase() || '';
                            valB = b.productName?.toLowerCase() || '';
                            return valA.localeCompare(valB) * dirMultiplier;
                        default:
                            return 0;
                    }

                    let comparisonResult = 0;
                    if (valA < valB) comparisonResult = -1;
                    else if (valA > valB) comparisonResult = 1;

                    comparisonResult *= dirMultiplier;

                    if (comparisonResult === 0 && field !== 'price') {
                        const priceA = a.currentPrice ?? Infinity;
                        const priceB = b.currentPrice ?? Infinity;
                        if (priceA < priceB) return -1;
                        if (priceA > priceB) return 1;
                    }
                    if (comparisonResult === 0 && field !== 'name') {
                        return (a.productName?.toLowerCase() || '').localeCompare(b.productName?.toLowerCase() || '');
                    }


                    return comparisonResult;
                });
            }

            function sm_updateSortButtonsState() {
                if (!sm_sortButtonsContainer) return;
                const buttons = sm_sortButtonsContainer.querySelectorAll('.sortBtn');

                buttons.forEach(btn => {
                    const btnField = btn.dataset.sort;
                    let baseText = '';

                    switch (btnField) {
                        case 'price':
                            baseText = 'Цена';
                            break;
                        case 'discountPercent':
                            baseText = '% Скидки';
                            break;
                        case 'discountAmount':
                            baseText = `Скидка ${sm_getCurrencySymbol()}`;
                            break;
                        case 'name':
                            baseText = 'Название';
                            break;
                    }

                    if (btnField === sm_currentSort.field) {
                        const arrow = sm_currentSort.direction === 'asc' ? ' ▲' : ' ▼';
                        btn.classList.add('active');
                        btn.textContent = baseText + arrow;
                    } else {
                        btn.classList.remove('active');
                        btn.textContent = baseText;
                    }
                });

                const resetBtn = sm_sortButtonsContainer.querySelector('#salesMasterResetSortBtn');
                if (resetBtn) {
                    if (sm_currentSort.field === 'price' && sm_currentSort.direction === 'asc') {
                        resetBtn.classList.add('active');
                    } else {
                        resetBtn.classList.remove('active');
                    }
                }
            }

            function sm_resetSort(render = true) {
                sm_currentSort = {
                    field: 'price',
                    direction: 'asc'
                };
                GM_setValue(SM_SORT_STORAGE_KEY, sm_currentSort);
                sm_updateSortButtonsState();
                if (render) {
                    sm_applySort(sm_currentSort.field, sm_currentSort.direction);
                    sm_renderResults();
                }
            }

            // --- Управление фильтрами ---
            function sm_getFilterStorageKey(key) {
                return `${SM_FILTER_STORAGE_KEY}_${key}`;
            }

            function sm_saveFilter(key, value) {
                sm_currentFilters[key] = value;
                GM_setValue(SM_FILTER_STORAGE_KEY, sm_currentFilters);
            }

            function sm_applyLoadedFiltersToUI() {
                if (!sm_filtersPanel) return;
                document.getElementById('smFilterPriceMin').value = sm_currentFilters.priceMin || '';
                document.getElementById('smFilterPriceMax').value = sm_currentFilters.priceMax || '';
                document.getElementById('smFilterDiscountPercentMin').value = sm_currentFilters.discountPercentMin || '';
                document.getElementById('smFilterDiscountPercentMax').value = sm_currentFilters.discountPercentMax || '';
                document.getElementById('smFilterDiscountAmountMin').value = sm_currentFilters.discountAmountMin || '';
                document.getElementById('smFilterDiscountAmountMax').value = sm_currentFilters.discountAmountMax || '';
                document.getElementById('smFilterHasDiscount').checked = sm_currentFilters.hasDiscount || false;

                if (sm_filterStoreCheckboxesContainer) {
                    sm_filterStoreCheckboxesContainer.querySelectorAll('input[type="checkbox"]').forEach(cb => {
                        const storeId = cb.dataset.storeId;
                        cb.checked = sm_currentFilters.stores[storeId] !== false;
                    });
                }

                sm_updateFilterPlaceholders();
            }

            function sm_setupFilterEventListeners() {
                if (!sm_filtersPanel) return;
                const debouncedApply = sm_debounce(sm_applyFilters, SM_FILTER_DEBOUNCE_MS);

                ['smFilterPriceMin', 'smFilterPriceMax', 'smFilterDiscountPercentMin', 'smFilterDiscountPercentMax', 'smFilterDiscountAmountMin', 'smFilterDiscountAmountMax'].forEach(id => {
                    const input = document.getElementById(id);
                    const filterKey = id.replace('smFilter', '').charAt(0).toLowerCase() + id.replace('smFilter', '').slice(1);
                    if (input) {
                        input.addEventListener('input', (e) => {
                            sm_saveFilter(filterKey, e.target.value);
                            debouncedApply();
                        });
                    }
                });

                const hasDiscountCheckbox = document.getElementById('smFilterHasDiscount');
                if (hasDiscountCheckbox) {
                    hasDiscountCheckbox.addEventListener('change', (e) => {
                        sm_saveFilter('hasDiscount', e.target.checked);
                        sm_applyFilters();
                    });
                }

                const resetAllBtn = document.getElementById('smResetAllFiltersBtn');
                if (resetAllBtn) resetAllBtn.addEventListener('click', () => sm_resetAllFilters(true));

                sm_filtersPanel.querySelectorAll('.smFilterResetBtn').forEach(btn => {
                    btn.addEventListener('click', (event) => sm_handleFilterReset(event));
                });

            }

            function sm_handleFilterReset(event) {
                const filterKey = event.currentTarget.dataset.filterKey;
                sm_resetFilterByKey(filterKey, true);
            }

            function sm_resetFilterByKey(key, apply = true) {
                const defaults = {
                    priceMin: '',
                    priceMax: '',
                    discountPercentMin: '',
                    discountPercentMax: '',
                    discountAmountMin: '',
                    discountAmountMax: '',
                    hasDiscount: false,
                    stores: {}
                };
                switch (key) {
                    case 'price':
                        sm_saveFilter('priceMin', defaults.priceMin);
                        if (document.getElementById('smFilterPriceMin')) document.getElementById('smFilterPriceMin').value = defaults.priceMin;
                        sm_saveFilter('priceMax', defaults.priceMax);
                        if (document.getElementById('smFilterPriceMax')) document.getElementById('smFilterPriceMax').value = defaults.priceMax;
                        break;
                    case 'discountPercent':
                        sm_saveFilter('discountPercentMin', defaults.discountPercentMin);
                        if (document.getElementById('smFilterDiscountPercentMin')) document.getElementById('smFilterDiscountPercentMin').value = defaults.discountPercentMin;
                        sm_saveFilter('discountPercentMax', defaults.discountPercentMax);
                        if (document.getElementById('smFilterDiscountPercentMax')) document.getElementById('smFilterDiscountPercentMax').value = defaults.discountPercentMax;
                        break;
                    case 'discountAmount':
                        sm_saveFilter('discountAmountMin', defaults.discountAmountMin);
                        if (document.getElementById('smFilterDiscountAmountMin')) document.getElementById('smFilterDiscountAmountMin').value = defaults.discountAmountMin;
                        sm_saveFilter('discountAmountMax', defaults.discountAmountMax);
                        if (document.getElementById('smFilterDiscountAmountMax')) document.getElementById('smFilterDiscountAmountMax').value = defaults.discountAmountMax;
                        break;
                    case 'options':
                        sm_saveFilter('hasDiscount', defaults.hasDiscount);
                        if (document.getElementById('smFilterHasDiscount')) document.getElementById('smFilterHasDiscount').checked = defaults.hasDiscount;
                        break;
                    case 'stores':
                        const storeCheckboxes = document.querySelectorAll('#smFilterStoreCheckboxes input[type="checkbox"]');
                        let updatedStores = {};
                        storeCheckboxes.forEach(cb => {
                            cb.checked = true;
                            updatedStores[cb.dataset.storeId] = true;
                        });
                        sm_currentFilters.stores = updatedStores;
                        GM_setValue(SM_FILTER_STORAGE_KEY, sm_currentFilters);
                        break;
                }
                if (apply) sm_applyFilters();
            }

            function sm_resetAllFilters(apply = true) {
                const filterKeys = ['price', 'discountPercent', 'discountAmount', 'options', 'stores'];
                filterKeys.forEach(key => sm_resetFilterByKey(key, false));
                if (apply) sm_applyFilters();
            }

            function sm_getCurrencySymbol() {
                return sm_currentCurrencyMode === 'USD' ? '$' : '₽';
            }

            function sm_updateFilterPlaceholders() {
                if (!sm_filtersPanel) return;
                const currencySymbol = sm_getCurrencySymbol();
                const resultsToScan = sm_currentResults || [];

                const priceHeader = sm_filtersPanel.querySelector('.smFilterGroup h4:first-child');
                if (priceHeader) priceHeader.innerHTML = `Цена, ${currencySymbol} ${sm_createResetButtonHTML('price')}`;
                const amountHeader = sm_filtersPanel.querySelector('.smFilterGroup:nth-child(3) h4');
                if (amountHeader) amountHeader.innerHTML = `Скидка, ${currencySymbol} ${sm_createResetButtonHTML('discountAmount')}`;
                sm_filtersPanel.querySelectorAll('.smFilterResetBtn').forEach(btn => {
                    btn.removeEventListener('click', sm_handleFilterReset);
                    btn.addEventListener('click', sm_handleFilterReset);
                });

                if (resultsToScan.length === 0) {
                    ['smFilterPriceMin', 'smFilterPriceMax', 'smFilterDiscountPercentMin', 'smFilterDiscountPercentMax', 'smFilterDiscountAmountMin', 'smFilterDiscountAmountMax'].forEach(id => {
                        const el = document.getElementById(id);
                        if (el) el.placeholder = '-';
                    });
                    return;
                }

                let minPrice = Infinity, maxPrice = -Infinity;
                let minDiscountPercent = 101, maxDiscountPercent = -1;
                let minDiscountAmount = Infinity, maxDiscountAmount = -Infinity;
                const rubToUsdRate = sm_exchangeRates?.rub?.usd || null;
                const isUsdMode = sm_currentCurrencyMode === 'USD';

                resultsToScan.forEach(item => {
                    let currentPrice = item.currentPrice;
                    let discountAmount = item.discountAmount;

                    if(isUsdMode && rubToUsdRate) {
                        if (currentPrice !== null) currentPrice *= rubToUsdRate;
                        if (discountAmount !== null) discountAmount *= rubToUsdRate;
                    }

                    if (currentPrice !== null) {
                        if (currentPrice < minPrice) minPrice = currentPrice;
                        if (currentPrice > maxPrice) maxPrice = currentPrice;
                    }
                    if (item.discountPercent !== null) {
                        if (item.discountPercent < minDiscountPercent) minDiscountPercent = item.discountPercent;
                        if (item.discountPercent > maxDiscountPercent) maxDiscountPercent = item.discountPercent;
                    }
                    if (discountAmount !== null) {
                        if (discountAmount < minDiscountAmount) minDiscountAmount = discountAmount;
                        if (discountAmount > maxDiscountAmount) maxDiscountAmount = discountAmount;
                    }
                });

                const setPlaceholder = (id, prefix, value, suffix = '', formatFn = Math.round) => {
                    const el = document.getElementById(id);
                    if (el) {
                        el.placeholder = (value === Infinity || value === -Infinity || value === 101 || value === -1) ? '-' : `${prefix} ${formatFn(value)}${suffix}`;
                    }
                };

                setPlaceholder('smFilterPriceMin', 'от', minPrice, '', Math.floor);
                setPlaceholder('smFilterPriceMax', 'до', maxPrice, '', Math.ceil);
                setPlaceholder('smFilterDiscountPercentMin', 'от', minDiscountPercent, '%', v => Math.max(0, Math.floor(v)));
                setPlaceholder('smFilterDiscountPercentMax', 'до', maxDiscountPercent, '%', v => Math.min(100, Math.ceil(v)));
                setPlaceholder('smFilterDiscountAmountMin', 'от', minDiscountAmount, '', Math.floor);
                setPlaceholder('smFilterDiscountAmountMax', 'до', maxDiscountAmount, '', Math.ceil);
            }

            function sm_applyFilters() {
                if (!sm_resultsDiv || !sm_currentResults) return;

                // Получаем фильтр по названию из поля ввода
                const titleFilterInput = document.getElementById('smTitleFilterInput');
                const rawTitleFilterText = titleFilterInput ? titleFilterInput.value.trim() : '';
                // Разбиваем на отдельные слова/фразы по ";" и приводим к нижнему регистру
                const titleFilterTerms = rawTitleFilterText
                    .split(';')
                    .map(term => term.trim().toLowerCase())
                    .filter(term => term.length > 0);

                // Получаем ключевые слова для исключения и фильтры
                const keywords = sm_exclusionKeywords.map(k => k.toLowerCase());
                const pMin = parseFloat(sm_currentFilters.priceMin) || 0;
                const pMax = parseFloat(sm_currentFilters.priceMax) || Infinity;
                const dpMin = parseFloat(sm_currentFilters.discountPercentMin) || 0;
                const dpMax = parseFloat(sm_currentFilters.discountPercentMax) || 100;
                const daMin = parseFloat(sm_currentFilters.discountAmountMin) || 0;
                const daMax = parseFloat(sm_currentFilters.discountAmountMax) || Infinity;
                const hasDiscountFilter = sm_currentFilters.hasDiscount || false;
                const activeStoreFilters = sm_currentFilters.stores;

                let visibleCount = 0;
                const items = sm_resultsDiv.querySelectorAll('.salesMasterItem');

                items.forEach(itemElement => {
                     const index = Array.from(sm_resultsDiv.children).indexOf(itemElement);
                     if (index < 0 || index >= sm_currentResults.length) {
                          itemElement.classList.add('hidden-by-filter');
                          return;
                     }
                     const itemData = sm_currentResults[index];
                     if (!itemData) {
                          itemElement.classList.add('hidden-by-filter');
                          return;
                     }

                    const titleElement = itemElement.querySelector('.sm-title');
                    const itemTitle = titleElement ? titleElement.textContent.trim().toLowerCase() : '';

                    let hideByTitleFilter = false;
                    if (titleFilterTerms.length > 0 && !titleFilterTerms.some(term => itemTitle.includes(term))) {
                        hideByTitleFilter = true;
                    }

                    let shouldHide = false;

                    // 1. Фильтр по магазину
                    if (activeStoreFilters[itemData.storeId] === false) {
                        shouldHide = true;
                    }

                    // 2. Фильтр по ключевым словам (исключения)
                    if (!shouldHide && keywords.length > 0) {
                        let textToSearch = itemTitle;

                        if (itemData.storeId === 'platimarket' && itemData.sellerName) {
                            textToSearch += ' ' + itemData.sellerName.toLowerCase();
                        }
                        if (keywords.some(keyword => textToSearch.includes(keyword))) {
                            shouldHide = true;
                        }
                    }

                    // 3. Фильтр по цене
                    if (!shouldHide && itemData.currentPrice !== null) {
                        if (itemData.currentPrice < pMin || itemData.currentPrice > pMax) {
                            shouldHide = true;
                        }
                    } else if (!shouldHide && itemData.currentPrice === null && (pMin > 0 || pMax < Infinity)) {
                         if (!(pMin === 0 && pMax === Infinity)) {
                           shouldHide = true;
                         }
                    }

                    // 4. Фильтр по % скидки
                    if (!shouldHide) {
                        const discountP = itemData.discountPercent ?? 0;
                        if (discountP < dpMin || discountP > dpMax) {
                            shouldHide = true;
                        }
                    }

                    // 5. Фильтр по сумме скидки
                    if (!shouldHide) {
                        const discountA = itemData.discountAmount ?? 0;
                        if (discountA < daMin || discountA > daMax) {
                            shouldHide = true;
                        }
                    }

                    // 6. Фильтр "Только со скидкой"
                    if (!shouldHide && hasDiscountFilter) {
                        if (!itemData.discountPercent || itemData.discountPercent <= 0) {
                            shouldHide = true;
                        }
                    }

                    // Применяем класс скрытия, если сработал любой фильтр ИЛИ фильтр по названию
                    if (shouldHide || hideByTitleFilter) {
                        itemElement.classList.add('hidden-by-filter');
                    } else {
                        itemElement.classList.remove('hidden-by-filter');
                        visibleCount++;
                    }
                });

                // Обновляем статус в шапке
                const totalLoadedCount = sm_currentResults.length;
                const anyFilterActive = pMin > 0 || pMax < Infinity || dpMin > 0 || dpMax < 100 || daMin > 0 || daMax < Infinity || hasDiscountFilter || keywords.length > 0 || Object.values(activeStoreFilters).some(v => v === false) || titleFilterTerms.length > 0;
                const errorStoresCount = Object.values(sm_stores).filter(s => s.status === 'error').length;

                let statusMessage = '';
                if (sm_activeRequests === 0) {
                    if (totalLoadedCount > 0) {
                        if (anyFilterActive) {
                            statusMessage = `Показано ${visibleCount} из ${totalLoadedCount} предложений. `;
                        } else {
                            statusMessage = `Найдено ${totalLoadedCount} предложений. `;
                        }
                    } else {
                         const gameName = sm_getSteamGameName();
                        if (gameName) {
                           statusMessage = `Предложений не найдено. `;
                        } else {
                           statusMessage = `Введите запрос или обновите для поиска.`;
                        }
                    }
                    if (errorStoresCount > 0) {
                        statusMessage += `(${errorStoresCount} маг. с ошибками).`;
                    }
                    sm_updateStatus(statusMessage.trim(), false);
                } else {
                }

                if (visibleCount === 0 && totalLoadedCount > 0 && anyFilterActive && sm_activeRequests === 0) {
                    const statusDivInHeader = document.getElementById('salesMasterHeaderStatus');
                    if (statusDivInHeader) {
                        let currentStatus = statusDivInHeader.textContent.replace(' Нет товаров, соответствующих фильтрам.', '');
                        statusDivInHeader.textContent = currentStatus.trim() + ' Нет товаров, соответствующих фильтрам.';
                    }
                }
            }


            // --- Фильтрация исключений ---
            function sm_addExclusionKeyword() {
                const keyword = sm_excludeInput.value.trim().toLowerCase();
                if (keyword && !sm_exclusionKeywords.includes(keyword)) {
                    sm_exclusionKeywords.push(keyword);
                    GM_setValue(SM_EXCLUSION_STORAGE_KEY, sm_exclusionKeywords);
                    sm_excludeInput.value = '';
                    sm_renderExclusionTags();
                    sm_applyFilters();
                }
            }

            function sm_removeExclusionKeyword(keywordToRemove) {
                sm_exclusionKeywords = sm_exclusionKeywords.filter(k => k !== keywordToRemove);
                GM_setValue(SM_EXCLUSION_STORAGE_KEY, sm_exclusionKeywords);
                sm_renderExclusionTags();
                sm_applyFilters();
            }

            function sm_renderExclusionTags() {
                if (!sm_exclusionTagsListDiv) return;
                sm_exclusionTagsListDiv.innerHTML = '';
                sm_exclusionKeywords.forEach(keyword => {
                    const tag = document.createElement('span');
                    tag.className = 'smExclusionTag';
                    tag.textContent = keyword;
                    tag.title = `Удалить "${keyword}"`;
                    tag.onclick = () => sm_removeExclusionKeyword(keyword);
                    sm_exclusionTagsListDiv.appendChild(tag);
                });
            }

           // --- Рендеринг результатов ---
            function sm_renderResults() {
                if (!sm_resultsDiv) return;
                sm_resultsDiv.innerHTML = '';
                if (sm_currentResults.length === 0 && sm_activeRequests === 0) {
                    sm_applyFilters();
                    return;
                }

                const fragment = document.createDocumentFragment();
                const isUsdMode = sm_currentCurrencyMode === 'USD';
                const rubToUsdRate = sm_exchangeRates['rub']?.usd || null;

                if (isUsdMode && !rubToUsdRate) {
                    sm_updateStatus('Не удалось загрузить курс RUB/USD для конвертации.', false);
                }

                sm_currentResults.forEach(item => {
                    const itemDiv = document.createElement('div');
                    itemDiv.className = 'salesMasterItem';
                    itemDiv.dataset.store = item.storeId;

                    if (item.storeId === 'steam_current_page') {
                        itemDiv.classList.add('steam-page-offer');
                    }

                    const link = document.createElement('a');
                    link.href = item.productUrl || item.storeUrl || '#';
                    link.target = '_blank';
                    link.rel = 'noopener noreferrer nofollow';

                    const imageWrapper = document.createElement('div');
                    imageWrapper.className = 'sm-card-image-wrapper';
                    const img = document.createElement('img');
                    let imgSrc = item.imageUrl;
                    if (imgSrc && !imgSrc.startsWith('http') && !imgSrc.startsWith('//')) {
                        try {
                            const storeBaseUrl = new URL(item.storeUrl || sm_storeModules.find(s => s.id === item.storeId)?.baseUrl || unsafeWindow.location.origin);
                            imgSrc = new URL(imgSrc, storeBaseUrl.origin).href;
                        } catch (e) {
                            imgSrc = 'https://via.placeholder.com/150x80?text=No+Image';
                        }
                    } else if (!imgSrc) {
                        imgSrc = 'https://via.placeholder.com/150x80?text=No+Image';
                    }
                    img.src = imgSrc;
                    img.alt = item.productName || 'Изображение товара';
                    img.loading = 'lazy';
                    img.onerror = function() {
                        this.onerror = null; this.src = 'https://via.placeholder.com/150x80?text=Load+Error'; this.style.objectFit = 'contain';
                    };
                    imageWrapper.appendChild(img);
                    link.appendChild(imageWrapper);

                    const priceDiv = document.createElement('div');
                    priceDiv.className = 'sm-price-container';
                    const currentPriceSpan = document.createElement('span');
                    currentPriceSpan.className = 'sm-current-price';

                    if (isUsdMode) {
                        if (item.currentPrice !== null && rubToUsdRate) {
                            const usdPrice = item.currentPrice * rubToUsdRate;
                            currentPriceSpan.textContent = `$${usdPrice.toFixed(2)}`;
                        } else {
                            currentPriceSpan.textContent = item.currentPrice === null ? 'Нет цены' : 'Нет курса';
                        }
                    } else {
                        currentPriceSpan.textContent = item.currentPrice !== null ? `${item.currentPrice.toLocaleString('ru-RU')} ₽` : 'Нет цены';
                    }
                    priceDiv.appendChild(currentPriceSpan);

                    if (item.discountPercent && item.discountPercent > 0) {
                        const discountBadge = document.createElement('span');
                        discountBadge.className = 'sm-discount-badge';
                        discountBadge.textContent = `-${Math.round(item.discountPercent)}%`;
                        priceDiv.appendChild(discountBadge);
                        if (item.originalPrice !== null) {
                            const originalPriceSpan = document.createElement('span');
                            originalPriceSpan.className = 'sm-original-price';
                            if (isUsdMode && rubToUsdRate) {
                                const usdOriginalPrice = item.originalPrice * rubToUsdRate;
                                originalPriceSpan.textContent = `$${usdOriginalPrice.toFixed(2)}`;
                            } else {
                                originalPriceSpan.textContent = `${item.originalPrice.toLocaleString('ru-RU')} ₽`;
                            }
                            priceDiv.appendChild(originalPriceSpan);
                        }
                    }
                    link.appendChild(priceDiv);

                    const titleDiv = document.createElement('div');
                    titleDiv.className = 'sm-title';
                    titleDiv.textContent = item.productName || 'Без названия';
                    titleDiv.title = item.productName || 'Без названия';
                    link.appendChild(titleDiv);

                    const storeInfoContainer = document.createElement('div');
                    storeInfoContainer.className = 'sm-store-info-container';
                    const storeDiv = document.createElement('div');
                    storeDiv.className = 'sm-store-name';
                    storeDiv.textContent = item.storeName || 'Неизвестный магазин';
                    storeDiv.title = `Магазин: ${item.storeName}`;
                    storeInfoContainer.appendChild(storeDiv);

                    if (item.storeId === 'platimarket' && item.sellerId && item.sellerName) {
                        const sellerLink = document.createElement('a');
                        sellerLink.className = 'sm-seller-link';
                        sellerLink.textContent = `Продавец: ${item.sellerName}`;
                        sellerLink.title = `Перейти к продавцу: ${item.sellerName}`;
                        try {
                            const safeSellerName = encodeURIComponent(item.sellerName.replace(/[^a-zA-Z0-9_\-.~]/g, '-')).replace(/%2F/g, '/');
                            sellerLink.href = `https://plati.market/seller/${safeSellerName}/${item.sellerId}`;
                            sellerLink.target = '_blank';
                            sellerLink.rel = 'noopener noreferrer nofollow';
                            sellerLink.onclick = (e) => { e.stopPropagation(); };
                            storeInfoContainer.appendChild(sellerLink);
                        } catch (e) {
                             const sellerText = document.createElement('div'); sellerText.className = 'sm-seller-link no-link'; sellerText.textContent = `Продавец: ${item.sellerName}`; storeInfoContainer.appendChild(sellerText);
                        }
                    } else if (item.storeId === 'ggsel' && item.sellerId && item.sellerName) {
                        const sellerLink = document.createElement('a');
                        sellerLink.className = 'sm-seller-link';
                        sellerLink.textContent = `Продавец: ${item.sellerName}`;
                        sellerLink.title = `Перейти к продавцу: ${item.sellerName}`;
                        sellerLink.href = `https://ggsel.net/sellers/${item.sellerId}`;
                        sellerLink.target = '_blank';
                        sellerLink.rel = 'noopener noreferrer nofollow';
                        sellerLink.onclick = (e) => { e.stopPropagation(); };
                        storeInfoContainer.appendChild(sellerLink);
                    }
                    link.appendChild(storeInfoContainer);

                    const buyButtonDiv = document.createElement('div');
                    buyButtonDiv.className = 'sm-buyButton';
                    buyButtonDiv.textContent = 'Перейти';
                    link.appendChild(buyButtonDiv);

                    itemDiv.appendChild(link);
                    fragment.appendChild(itemDiv);
                });

                sm_resultsDiv.appendChild(fragment);
                sm_applyFilters();
            }

            // --- Добавление кнопки SalesMaster ---
            function sm_addSalesMasterButton() {
                const actionsContainer = document.querySelector('#queueActionsCtn');
                // Ищем кнопку Plati как ориентир
                const referenceButton = actionsContainer?.querySelector('.plati_price_button, .vgt_price_button');
                const ignoreButtonContainer = actionsContainer?.querySelector('#ignoreBtn');

                if (!actionsContainer || (!referenceButton && !ignoreButtonContainer)) {
                    // Если нет ни Plati ни Ignore, попробуем вставить просто в actionsContainer
                    if (!actionsContainer) {
                        console.warn('SalesMaster Button: Could not find actions container.');
                        return;
                    }
                    console.warn('SalesMaster Button: Could not find reference button, appending to container.');
                }
                if (actionsContainer.querySelector('.salesMaster_button')) return;

                const smContainer = document.createElement('div');
                smContainer.className = 'salesMaster_button queue_control_button';
                smContainer.style.marginLeft = '3px';

                smContainer.innerHTML = `<div class="btnv6_blue_hoverfade btn_medium" style="height: 32px; padding: 0 5px; font-size: 18px; font-weight: bold;" title="Поиск скидок в других магазинах"><span>%</span></div>`;
                smContainer.querySelector('div').addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    sm_showModal();
                });

                // Логика вставки: после Plati, или после Ignore, или в конец actionsContainer
                if (referenceButton) {
                    referenceButton.insertAdjacentElement('afterend', smContainer);
                } else if (ignoreButtonContainer) {
                    ignoreButtonContainer.insertAdjacentElement('afterend', smContainer);
                } else if (actionsContainer) {
                    actionsContainer.appendChild(smContainer);
                }
            }

            // --- Стили SalesMaster ---
            function sm_addStyles() {
                GM_addStyle(`
                #salesMasterModal {
                	position: fixed;
                	top: 0;
                	left: 0;
                	width: 100%;
                	height: 100%;
                	background-color: rgba(20, 20, 25, 0.9);
                	backdrop-filter: blur(3px);
                	z-index: 9999;
                	display: none;
                	color: #c6d4df;
                	font-family: "Motiva Sans", Sans-serif, Arial;
                }

                #salesMasterModal * {
                	box-sizing: border-box;
                }

                #salesMasterContainer {
                	padding-top: 0;
                	height: 100%;
                	display: flex;
                	flex-direction: column;
                }

                #salesMasterCloseBtn {
                	position: fixed;
                	top: 15px;
                	right: 20px;
                	font-size: 35px;
                	color: #aaa;
                	background: none;
                	border: none;
                	cursor: pointer;
                	line-height: 1;
                	z-index: 10002;
                	padding: 5px;
                	transition: color 0.2s, transform 0.2s;
                }

                #salesMasterCloseBtn:hover {
                	color: #fff;
                	transform: scale(1.1);
                }

                /* --- Шапка --- */
                #salesMasterHeader {
                	display: flex;
                	align-items: center;
                	gap: 10px;
                	flex-wrap: wrap;
                	position: relative;
                	z-index: 1001;
                	background-color: rgba(27, 40, 56, 0.95);
                	backdrop-filter: blur(5px);
                	padding: 10px 15px;
                	border-bottom: 1px solid #3a4f6a;
                	border-radius: 0;
                	margin-left: 0;
                	margin-right: 0;
                	transition: padding-left 0.2s ease-out, padding-right 0.2s ease-out;
                	flex-shrink: 0;
                }

                #salesMasterHeaderStatus {
                	text-align: left;
                	font-size: 14px;
                	color: #aaa;
                	padding: 0 10px 0 0;
                	white-space: nowrap;
                	overflow: hidden;
                	text-overflow: ellipsis;
                	display: flex;
                	align-items: center;
                	justify-content: flex-start;
                	min-height: 36px;
                	flex-shrink: 0;
                }

                #salesMasterHeaderStatus .spinner {
                	margin-left: 8px;
                }

                #smTitleFilterInput {
                	width: 250px;
                	height: 36px;
                	padding: 6px 12px;
                	font-size: 14px;
                	background-color: rgba(10, 10, 15, 0.7);
                	border: 1px solid #3a4f6a;
                	color: #c6d4df;
                	border-radius: 3px;
                	outline: none;
                	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
                	margin-left: 5px;
                	flex-shrink: 0;
                }

                #smTitleFilterInput:focus {
                	border-color: #67c1f5;
                	background-color: rgba(0, 0, 0, 0.8);
                }

                #smTitleFilterInput::placeholder {
                	color: #777;
                	font-style: italic;
                	font-size: 13px;
                }

                .smInsertTitleBtn {
                	padding: 0 10px;
                	font-size: 12px;
                }

                #salesMasterSortButtons {
                	display: flex;
                	gap: 5px;
                	align-items: center;
                	margin-left: 10px;
                }

                /* --- Кнопки --- */
                .salesMasterBtn {
                	padding: 0 12px;
                	font-size: 13px;
                	color: #c6d4df;
                	border: 1px solid #4b6f9c;
                	border-radius: 3px;
                	cursor: pointer;
                	white-space: nowrap;
                	height: 36px;
                	display: inline-flex;
                	align-items: center;
                	justify-content: center;
                	flex-shrink: 0;
                	background-color: rgba(42, 71, 94, 0.8);
                	transition: background-color 0.2s, border-color 0.2s;
                	text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
                }

                .salesMasterBtn:hover:not(:disabled) {
                	background-color: rgba(67, 103, 133, 0.9);
                	border-color: #67c1f5;
                }

                .salesMasterBtn:disabled {
                	opacity: 0.6;
                	cursor: default;
                	background-color: rgba(42, 71, 94, 0.5);
                	border-color: #3a4f6a;
                }

                #salesMasterSearchGoBtn {
                	background-color: rgba(77, 136, 255, 0.8);
                	border-color: #4D88FF;
                }

                #salesMasterSearchGoBtn:hover:not(:disabled) {
                	background-color: rgba(51, 102, 204, 0.9);
                }

                .salesMasterBtn.sortBtn.active {
                	background-color: rgba(0, 123, 255, 0.8);
                	border-color: #007bff;
                }

                .salesMasterBtn.sortBtn.active:hover {
                	background-color: rgba(0, 86, 179, 0.9);
                }

                .sortBtn span {
                	margin-left: 5px;
                	font-size: 12px;
                	line-height: 1;
                }

                #salesMasterResetSortBtn {
                	background-color: rgba(119, 119, 119, 0.8);
                	border-color: #777;
                	padding: 0 8px;
                }

                #salesMasterResetSortBtn:hover {
                	background-color: rgba(136, 136, 136, 0.9);
                }

                #salesMasterResetSortBtn svg {
                	width: 14px;
                	height: 14px;
                	fill: currentColor;
                }

                #salesMasterResetSortBtn.active {
                	background-color: rgba(0, 123, 255, 0.8);
                	border-color: #007bff;
                }

                /* --- Боковые панели ("плавающие") --- */
                #salesMasterFiltersPanel,
                #salesMasterExclusionTags {
                	position: fixed;
                	top: 60px;
                	max-height: calc(100vh - 80px);
                	overflow-y: auto;
                	z-index: 1000;
                	padding: 15px;
                	scrollbar-width: thin;
                	scrollbar-color: #555 #2a2a30;
                	background-color: transparent;
                	backdrop-filter: none;
                	border-radius: 6px;
                	box-shadow: none;
                	border: none;
                	transition: top 0.2s ease-in-out, max-height 0.2s ease-in-out;
                	visibility: hidden;
                }

                #salesMasterFiltersPanel::before,
                #salesMasterExclusionTags::before {
                	content: '';
                	position: absolute;
                	top: 0;
                	left: 0;
                	right: 0;
                	bottom: 0;
                	background-color: rgba(23, 26, 33, 0.85);
                	backdrop-filter: blur(4px);
                	border-radius: 6px;
                	z-index: -1;
                }

                #salesMasterFiltersPanel::-webkit-scrollbar,
                #salesMasterExclusionTags::-webkit-scrollbar {
                	width: 5px;
                }

                #salesMasterFiltersPanel::-webkit-scrollbar-track,
                #salesMasterExclusionTags::-webkit-scrollbar-track {
                	background: rgba(42, 42, 48, 0.5);
                	border-radius: 3px;
                }

                #salesMasterFiltersPanel::-webkit-scrollbar-thumb,
                #salesMasterExclusionTags::-webkit-scrollbar-thumb {
                	background-color: rgba(85, 85, 85, 0.7);
                	border-radius: 3px;
                }

                #salesMasterFiltersPanel {
                	left: 15px;
                	width: 240px;
                }

                #salesMasterExclusionTags {
                	right: 15px;
                	width: 260px;
                }

                .smFilterGroup {
                	margin-bottom: 20px;
                }

                .smFilterGroup h4 {
                	font-size: 15px;
                	color: #67c1f5;
                	margin-bottom: 10px;
                	padding-bottom: 5px;
                	display: flex;
                	justify-content: space-between;
                	align-items: center;
                	font-weight: 500;
                	border-bottom: 1px solid #3a4f6a;
                }

                .smFilterResetBtn {
                	font-size: 12px;
                	color: #8f98a0;
                	background: none;
                	border: none;
                	cursor: pointer;
                	padding: 0 3px;
                	line-height: 1;
                }

                .smFilterResetBtn:hover {
                	color: #c6d4df;
                }

                .smFilterResetBtn svg {
                	width: 14px;
                	height: 14px;
                	vertical-align: middle;
                	fill: currentColor;
                }

                .smFilterRangeInputs {
                	display: flex;
                	gap: 8px;
                	align-items: center;
                }

                .smFilterRangeInputs input[type="number"] {
                	width: calc(50% - 4px);
                	padding: 8px 10px;
                	font-size: 14px;
                	background-color: rgba(10, 10, 15, 0.7);
                	border: 1px solid #3a4f6a;
                	color: #c6d4df;
                	border-radius: 3px;
                	height: 34px;
                	text-align: center;
                	-moz-appearance: textfield;
                	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
                	outline: none;
                }

                .smFilterRangeInputs input[type="number"]:focus {
                	border-color: #67c1f5;
                	background-color: rgba(0, 0, 0, 0.8);
                }

                .smFilterRangeInputs input[type="number"]::-webkit-outer-spin-button,
                .smFilterRangeInputs input[type="number"]::-webkit-inner-spin-button {
                	-webkit-appearance: none;
                	margin: 0;
                }

                .smFilterRangeInputs input[type="number"]::placeholder {
                	color: #777;
                	font-size: 12px;
                	text-align: center;
                }

                .smFilterCheckbox {
                	margin-bottom: 10px;
                }

                .smFilterCheckbox label {
                	display: flex;
                	align-items: center;
                	font-size: 14px;
                	cursor: pointer;
                	color: #c6d4df;
                }

                .smFilterCheckbox input[type="checkbox"] {
                	margin-right: 8px;
                	width: 18px;
                	height: 18px;
                	accent-color: #67c1f5;
                	cursor: pointer;
                	flex-shrink: 0;
                }

                .smFilterCheckbox.sm-store-error label {
                	background-color: rgba(139, 0, 0, 0.35);
                	border: 1px solid rgba(255, 100, 100, 0.3);
                	border-radius: 3px;
                	padding: 1px 4px;
                	margin: -1px -4px;
            	}

                #smFilterStoreCheckboxes {
                	max-height: 315px;
                	padding-right: 5px;
                	overflow-y: auto;
                }

                #smResetAllFiltersBtn {
                	width: 100%;
                	margin-top: 15px;
                	padding: 10px 15px;
                	height: auto;
                	font-size: 14px;
                	background-color: rgba(108, 117, 125, 0.6);
                	border: 1px solid #5a6268;
                	text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
                	color: #c6d4df;
                }

                #smResetAllFiltersBtn:hover {
                	background-color: rgba(90, 98, 104, 0.8);
                	border-color: #8f98a0;
                }

                .smExclusionInputGroup {
                	display: flex;
                	align-items: stretch;
                	border: 1px solid #3a4f6a;
                	border-radius: 4px;
                	background-color: rgba(10, 10, 15, 0.7);
                	overflow: hidden;
                	height: 36px;
                	flex-shrink: 0;
                	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
                	margin-bottom: 10px;
                }

                #salesMasterExcludeInput {
                	padding: 6px 12px;
                	font-size: 14px;
                	background-color: transparent;
                	border: none;
                	color: #c6d4df;
                	outline: none;
                	border-radius: 0;
                	flex-grow: 1;
                	width: auto;
                	height: auto;
                }

                #salesMasterExcludeInput:focus {
                	box-shadow: none;
                }

                #salesMasterAddExcludeBtn {
                	display: flex;
                	align-items: center;
                	justify-content: center;
                	padding: 0 12px;
                	background-color: #4b6f9c;
                	border: none;
                	border-left: 1px solid #3a4f6a;
                	cursor: pointer;
                	border-radius: 0;
                	color: #c6d4df;
                	height: auto;
                }

                #salesMasterAddExcludeBtn:hover {
                	background-color: #67c1f5;
                	color: #fff;
                }

                #salesMasterAddExcludeBtn svg {
                	width: 26px;
                	height: 26px;
                	fill: currentColor;
                    padding-right: 14px;
                }

                #salesMasterExclusionTagsList {
                	display: flex;
                	flex-direction: row;
                	flex-wrap: wrap;
                	align-content: flex-start;
                	gap: 10px;
                	overflow-y: auto;
                	flex-grow: 1;
                }

                .smExclusionTag {
                	display: inline-block;
                	background-color: rgba(75, 111, 156, 0.7);
                	color: #c6d4df;
                	padding: 6px 12px;
                	border-radius: 15px;
                	font-size: 14px;
                	cursor: pointer;
                	transition: background-color 0.2s;
                	border: 1px solid #4b6f9c;
                	white-space: nowrap;
                	text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
                }

                .smExclusionTag:hover {
                	background-color: rgba(220, 53, 69, 0.8);
                	border-color: rgba(255, 80, 90, 0.9);
                	color: #fff;
                }

                .smExclusionTag::after {
                	content: ' ×';
                	font-weight: bold;
                	margin-left: 4px;
                	font-size: 12px;
                }

                .smExclusionActions {
                    display: flex;
                    justify-content: flex-end;
                    gap: 8px;
                    margin-top: 10px;
                    margin-bottom: 10px;
                    padding-bottom: 10px;
                    border-bottom: 1px solid #3a4f6a;
                }

                .smExclusionActionBtn {
                    padding: 0 8px;
                    height: 30px;
                    width: 40px;
                    background-color: rgba(75, 111, 156, 0.7);
                    border-color: #4b6f9c;
                    font-size: 14px;
                    font-weight: bold;
                    line-height: 1;
                }

                #smImportModal {
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background-color: rgba(0, 0, 0, 0.7);
                    z-index: 10003;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }

                .smImportModalContent {
                    background-color: #1b2838;
                    padding: 25px;
                    border-radius: 5px;
                    border: 1px solid #67c1f5;
                    width: 90%;
                    max-width: 500px;
                    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
                }

                .smImportModalContent h4 {
                    margin-top: 0;
                    margin-bottom: 15px;
                    color: #67c1f5;
                    font-size: 16px;
                    text-align: center;
                }
                 .smImportModalContent p {
                    margin-bottom: 10px;
                    font-size: 14px;
                    color: #c6d4df;
                 }

                #smImportTextarea {
                    width: 100%;
                    padding: 10px;
                    font-size: 14px;
                    background-color: rgba(10, 10, 15, 0.7);
                	border: 1px solid #3a4f6a;
                	color: #c6d4df;
                	border-radius: 3px;
                    margin-bottom: 20px;
                    min-height: 100px;
                    resize: vertical;
                    outline: none;
                }
                #smImportTextarea:focus {
                    border-color: #67c1f5;
                }


                .smImportModalActions {
                    display: flex;
                    justify-content: flex-end;
                    gap: 10px;
                }

                 .smImportModalActions .salesMasterBtn {
                    padding: 8px 20px;
                    height: auto;
                    font-size: 14px;
                 }

                #smImportAcceptBtn {
                     background-color: rgba(77, 136, 255, 0.8);
                	 border-color: #4D88FF;
                }
                #smImportAcceptBtn:hover {
                    background-color: rgba(51, 102, 204, 0.9);
                }
                #smImportCancelBtn {
                    background-color: rgba(108, 117, 125, 0.6);
                	border: 1px solid #5a6268;
                }
                 #smImportCancelBtn:hover {
                	background-color: rgba(90, 98, 104, 0.8);
                	border-color: #8f98a0;
                }

                #salesMasterExclusionTagsList {
                    margin-top: 0;
                }


                /* --- Контейнер и статус результатов --- */
                #salesMasterResultsContainer {
                	position: relative;
                	flex-grow: 1;
                	padding-top: 15px;
                	transition: padding-left 0.2s ease-out, padding-right 0.2s ease-out;
                	overflow-y: auto;
                	scrollbar-color: #4b6f9c #17202d;
                	scrollbar-width: thin;
                }

                #salesMasterResultsContainer::-webkit-scrollbar {
                	width: 8px;
                }

                #salesMasterResultsContainer::-webkit-scrollbar-track {
                	background: #17202d;
                	border-radius: 4px;
                }

                #salesMasterResultsContainer::-webkit-scrollbar-thumb {
                	background-color: #4b6f9c;
                	border-radius: 4px;
                	border: 2px solid #17202d;
                }

                #salesMasterResultsContainer::-webkit-scrollbar-thumb:hover {
                	background-color: #67c1f5;
                }

                #salesMasterResultsStatus {
                	display: none !important;
                }

                #salesMasterResults {
                	display: grid;
                	grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
                	gap: 20px;
                	padding-top: 15px;
                	padding-bottom: 20px;
                }

                /* --- Класс для скрытия по фильтру названий --- */
                .salesMasterItem.hidden-by-filter {
                	display: none !important;
                }

                /* --- Карточка товара --- */
                .salesMasterItem {
                	background-color: rgba(42, 46, 51, 0.85);
                	backdrop-filter: blur(4px);
                	border-radius: 4px;
                	padding: 15px;
                	display: flex;
                	flex-direction: column;
                	transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
                	box-shadow: 0 3px 10px rgba(0, 0, 0, 0.4);
                	position: relative;
                	color: #c6d4df;
                	font-size: 14px;
                	min-height: 380px;
                	border: 1px solid #333941;
                }

                .salesMasterItem:hover {
                	transform: translateY(-3px);
                	box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
                	background-color: rgba(50, 55, 61, 0.9);
                	border-color: #67c1f5;
                }

                .salesMasterItem a {
                	text-decoration: none;
                	color: inherit;
                	display: flex;
                	flex-direction: column;
                	height: 100%;
                }

                /* --- Стили для выделения предложений со страницы Steam --- */
                .salesMasterItem.steam-page-offer {
                    background-color: #202c24;
                    border: 1px solid #354f3a;
                    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.4);
                    color: #c6d4df;
                    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
                }

                /* Кнопка в приглушенном зеленом стиле, похожем на стандартную синюю */
                .salesMasterItem.steam-page-offer .sm-buyButton {
                     background-color: #5c9d4f;
                     color: #1a2f1f;
                     font-weight: 600;
                     border: none;
                     transition: background-color 0.2s, color 0.2s;
                }
                 .salesMasterItem.steam-page-offer .sm-buyButton:hover {
                     background-color: #6ebf5f;
                     color: #0f1a0f;
                }

                .salesMasterItem.steam-page-offer:hover {
                    background-color: #304035;
                    border-color: #4a784d;
                    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
                    transform: translateY(-3px);
                }



                .sm-card-image-wrapper {
                	position: relative;
                	width: 100%;
                	aspect-ratio: 16 / 9;
                	margin-bottom: 12px;
                	background-color: #111;
                	border-radius: 3px;
                	overflow: hidden;
                	display: flex;
                	align-items: center;
                	justify-content: center;
                	border: 1px solid #333941;
                }

                .sm-card-image-wrapper img {
                	display: block;
                	max-width: 100%;
                	max-height: 100%;
                	width: auto;
                	height: auto;
                	object-fit: contain;
                	border-radius: 3px;
                }

                .sm-price-container {
                	display: flex;
                	flex-wrap: wrap;
                	align-items: baseline;
                	gap: 5px 10px;
                	margin-bottom: 10px;
                	min-height: 26px;
                }

                .sm-current-price {
                	font-size: 18px;
                	font-weight: 700;
                	color: #66c0f4;
                	line-height: 1;
                }

                .sm-original-price {
                	font-size: 14px;
                	color: #8f98a0;
                	text-decoration: line-through;
                	line-height: 1;
                }

                .sm-discount-badge {
                	background-color: #e2004b;
                	color: white;
                	padding: 3px 7px;
                	font-size: 13px;
                	border-radius: 3px;
                	font-weight: 600;
                	line-height: 1;
                }

                .sm-title {
                	font-size: 15px;
                	font-weight: 500;
                	line-height: 1.4;
                	height: 4.2em;
                	overflow: hidden;
                	text-overflow: ellipsis;
                	margin-bottom: 10px;
                	color: #e5e5e5;
                	display: -webkit-box;
                	-webkit-line-clamp: 3;
                	-webkit-box-orient: vertical;
                }

                /* --- Контейнер для магазина/продавца --- */
                .sm-store-info-container {
                    margin-top: auto;
                    padding-top: 10px;
                    text-align: right;
                    display: flex;
                    flex-direction: column;
                    align-items: flex-end;
                    gap: 3px;
                }

                /* --- Стиль названия магазина --- */
                .sm-store-name {
                    font-size: 12px;
                    color: #8f98a0;
                    text-align: right;
                }

                /* --- Стили для управления выбором магазинов --- */
                .smStoreSelectAllControls {
                    margin-top: -5px;
                    margin-bottom: 10px;
                    padding-top: 5px;
                    border-bottom: 1px solid #3a4f6a;
                    text-align: center;
                }

                .smStoreSelectAllLink {
                    font-size: 12px;
                    color: #8f98a0;
                    cursor: pointer;
                    text-decoration: none;
                    transition: color 0.2s;
                    padding: 0 5px;
                }

                .smStoreSelectAllLink:hover {
                    color: #c6d4df;
                    text-decoration: underline;
                }

                .smStoreSelectSeparator {
                    color: #5a6268;
                    margin: 0 3px;
                    font-size: 12px;
                }

                /* --- Стиль ссылки продавца --- */
                .sm-seller-link {
                    font-size: 12px;
                    color: #8f98a0;
                    text-align: right;
                    display: block;
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    text-decoration: none;
                    transition: color 0.2s;
                 }
                 .sm-seller-link:not(.no-link):hover {
                    color: #c6d4df;
                    text-decoration: underline;
                 }

                .sm-buyButton {
                	display: block;
                	text-align: center;
                	padding: 10px;
                	margin-top: 12px;
                	background-color: #67c1f5;
                	color: #1b2838;
                	border-radius: 3px;
                	font-size: 14px;
                	font-weight: 600;
                	transition: background-color 0.2s, color 0.2s;
                	margin-top: auto;
                	border: none;
                }

                .sm-buyButton:hover {
                	background-color: #8ad3f7;
                	color: #0e141b;
                }

                /* --- Адаптивность SM --- */
                @media (max-width: 1400px) {
                	#salesMasterResults {
                		grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
                	}
                }

                @media (max-width: 1100px) {
                	#salesMasterResults {
                		grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
                	}

                	#smTitleFilterInput {
                		max-width: 200px;
                	}
                }

                @media (max-width: 850px) {

                	#salesMasterFiltersPanel,
                	#salesMasterExclusionTags {
                		display: none;
                	}

                	#salesMasterHeader,
                	#salesMasterResultsContainer {
                		padding-left: 15px;
                		padding-right: 15px;
                	}

                	#salesMasterResults {
                		grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
                	}

                	#salesMasterHeader {
                		justify-content: space-between;
                	}

                	#smTitleFilterInput {
                		max-width: 180px;
                		margin-left: 5px;
                		margin-right: 5px;
                	}

                	.smInsertTitleBtn {
                		display: none;
                	}

                }

                @media (max-width: 600px) {
                	#salesMasterContainer {
                		width: 95%;
                		margin: 10px auto;
                		min-height: calc(100vh - 20px);
                	}

                	#salesMasterHeader {
                		flex-direction: column;
                		align-items: stretch;
                		padding-bottom: 5px;
                	}

                	#salesMasterHeaderStatus {
                		order: -2;
                		min-height: 25px;
                		padding: 5px 0;
                		font-size: 13px;
                		max-width: 100%;
                		text-align: center;
                		justify-content: center;
                		margin-bottom: 5px;
                	}

                	#smTitleFilterInput {
                		order: -1;
                		max-width: 100%;
                		margin: 0 0 10px 0;
                	}

                	.smInsertTitleBtn {
                		display: block;
                		order: -1;
                		margin: 0 0 5px 0;
                		width: 100%;
                	}

                	/* Показываем кнопку подстановки и делаем на всю ширину */
                	#salesMasterSortButtons {
                		width: 100%;
                		justify-content: space-around;
                		margin-top: 5px;
                		margin-left: 0;
                	}

                	.salesMasterBtn {
                		flex-grow: 1;
                		font-size: 13px;
                		padding: 8px 5px;
                		height: 36px;
                	}

                	#salesMasterResetSortBtn {
                		flex-grow: 0;
                		width: auto;
                		padding: 0 8px;
                	}

                	#salesMasterResults {
                		grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
                		gap: 10px;
                	}

                	.salesMasterItem {
                		min-height: 320px;
                		font-size: 13px;
                	}

                	.sm-current-price {
                		font-size: 15px;
                	}

                	.sm-title {
                		font-size: 13px;
                		height: 3.9em;
                		-webkit-line-clamp: 3;
                	}

                	.sm-store-name {
                		font-size: 11px;
                	}

                	.sm-buyButton {
                		font-size: 13px;
                		padding: 8px;
                	}
                }

                /* --- Кнопка % на странице --- */
                .salesMaster_button .btnv6_blue_hoverfade {
                	margin: 0;
                	padding: 0 10px;
                	font-size: 18px;
                	display: flex;
                	align-items: center;
                	justify-content: center;
                	transition: filter 0.2s;
                }

                .salesMaster_button .btnv6_blue_hoverfade:hover {
                	filter: brightness(1.1);
                }

                /* Спиннер */
                @keyframes salesMasterSpin {
                	0% {
                		transform: rotate(0deg);
                	}

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

                .spinner {
                	border: 2px solid rgba(255, 255, 255, 0.3);
                	border-radius: 50%;
                	border-top-color: #fff;
                	width: 1em;
                	height: 1em;
                	animation: salesMasterSpin 1s linear infinite;
                	display: inline-block;
                	vertical-align: middle;
                	margin-left: 5px;
                	line-height: 1;
                }
            `);
            }

            // --- Модули магазинов ---
            const sm_storeModules = [

                { // --- Модуль Steam ---
                    id: 'steam_current_page',
                    name: 'Steam',
                    baseUrl: 'https://store.steampowered.com',
                    searchUrlTemplate: '',
                    isEnabled: true,
                    fetch: async function(query) {
                        const storeModule = this;
                        const results = [];
                        const currencySymbol = sm_getCurrencySymbol();

                        const currencyMeta = document.querySelector('meta[itemprop="priceCurrency"]');
                        const pageCurrency = currencyMeta ? currencyMeta.content.toUpperCase() : 'RUB';

                        let exchangeRate = 1.0;

                        if (pageCurrency !== 'RUB') {
                            try {
                                const rates = await sm_fetchExchangeRates(pageCurrency);
                                if (rates && rates['rub']) {
                                    exchangeRate = parseFloat(rates['rub']);
                                    if (isNaN(exchangeRate) || exchangeRate <= 0) {
                                        sm_logError(storeModule.name, `Invalid exchange rate for ${pageCurrency} -> RUB: ${rates['rub']}`);
                                        exchangeRate = 1.0;
                                    }
                                } else {
                                    sm_logError(storeModule.name, `Could not get RUB rate for ${pageCurrency}`);
                                }
                            } catch (error) {
                                sm_logError(storeModule.name, `Error fetching exchange rates for ${pageCurrency}: ${error.message}`, error);
                            }
                        }

                        const headerImageElement = document.querySelector('#gameHeaderImageCtn img.game_header_image_full');
                        const mainImageUrl = headerImageElement ? headerImageElement.src : null;

                        const purchaseWrappers = document.querySelectorAll('.game_area_purchase_game_wrapper');

                        purchaseWrappers.forEach(wrapper => {
                            try {
                                const gamePurchaseDiv = wrapper.querySelector('.game_area_purchase_game, .game_area_purchase_game_dropdown_subscription');
                                if (!gamePurchaseDiv) return;

                                const titleElement = gamePurchaseDiv.querySelector('[id^="game_area_purchase_section_add_to_cart_title_"], [id^="bundle_purchase_label_"]');
                                let productName = null;
                                if (titleElement) {
                                    let cleanedText = titleElement.textContent.trim();
                                    cleanedText = cleanedText.replace(/^(Купить|Buy)[\s\u00A0]+/, '');
                                    cleanedText = cleanedText.replace(/\s*(—\s*НАБОР|BUNDLE)\s*\(\?\)\s*$/, '');
                                    productName = cleanedText.trim();
                                }

                                if (!productName) return;

                                let currentPrice = null;
                                let originalPrice = null;
                                let discountPercent = 0;
                                let imageUrl = mainImageUrl;

                                const priceSimpleElement = gamePurchaseDiv.querySelector('.game_purchase_price.price[data-price-final]');
                                const discountBlockElement = gamePurchaseDiv.querySelector('.discount_block.game_purchase_discount');

                                if (discountBlockElement) {
                                    const finalPriceText = discountBlockElement.querySelector('.discount_final_price')?.textContent;
                                    const originalPriceText = discountBlockElement.querySelector('.discount_original_price')?.textContent;
                                    const discountPercentText = discountBlockElement.querySelector('.discount_pct')?.textContent;
                                    const dataPriceFinal = discountBlockElement.dataset.priceFinal;
                                    const dataDiscount = discountBlockElement.dataset.discount;
                                    const dataBundleDiscount = discountBlockElement.dataset.bundlediscount;

                                    if (finalPriceText) {
                                        currentPrice = sm_parsePrice(finalPriceText);
                                    } else if (dataPriceFinal) {
                                        currentPrice = parseFloat(dataPriceFinal) / 100;
                                        if (isNaN(currentPrice)) currentPrice = null;
                                    }

                                    if (originalPriceText) {
                                        originalPrice = sm_parsePrice(originalPriceText);
                                    }

                                    if (discountPercentText) {
                                        discountPercent = sm_parsePercent(discountPercentText) || 0;
                                    } else if (dataDiscount) {
                                        discountPercent = parseFloat(dataDiscount) || 0;
                                    }

                                    if (discountPercent === 0 && dataBundleDiscount) {
                                        const bundleDiscountVal = parseFloat(dataBundleDiscount);
                                        if (bundleDiscountVal > 0) {
                                            discountPercent = bundleDiscountVal;
                                            if (originalPrice === null && currentPrice !== null) {
                                                originalPrice = currentPrice / (1 - discountPercent / 100);
                                            }
                                        }
                                    }

                                } else if (priceSimpleElement) {
                                    const dataPriceFinal = priceSimpleElement.dataset.priceFinal;
                                    if (dataPriceFinal) {
                                        currentPrice = parseFloat(dataPriceFinal) / 100;
                                        if (isNaN(currentPrice)) currentPrice = null;
                                    } else {
                                        currentPrice = sm_parsePrice(priceSimpleElement.textContent);
                                    }
                                    originalPrice = currentPrice;
                                    discountPercent = 0;
                                }

                                if (currentPrice !== null) {
                                    const finalCurrentPrice = parseFloat((currentPrice * exchangeRate).toFixed(2));
                                    const finalOriginalPrice = originalPrice !== null ? parseFloat((originalPrice * exchangeRate).toFixed(2)) : null;
                                    const effectiveOriginalPrice = (finalOriginalPrice === null || isNaN(finalOriginalPrice)) ? finalCurrentPrice : finalOriginalPrice;

                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name,
                                        storeUrl: storeModule.baseUrl,
                                        productName: productName,
                                        productUrl: unsafeWindow.location.href,
                                        imageUrl: imageUrl,
                                        currentPrice: finalCurrentPrice,
                                        originalPrice: effectiveOriginalPrice,
                                        discountPercent: discountPercent > 0 ? discountPercent : null,
                                        discountAmount: null,
                                        currency: 'RUB',
                                        isAvailable: true
                                    };

                                    results.push(sm_calculateMissingValues(data));
                                }

                            } catch (e) {
                                sm_logError(storeModule.name, `Error parsing purchase block for "${productName || 'unnamed element'}"`, e);
                            }
                        });

                        return results;
                    }
                },

                { // --- Модуль SteamBuy ---
                    id: 'steambuy',
                    name: 'SteamBuy',
                    baseUrl: 'https://steambuy.com',
                    searchUrlTemplate: 'https://steambuy.com/ajax/_get.php?a=search&q={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                responseType: 'json',
                                headers: {
                                    'Accept': 'application/json, text/javascript, */*; q=0.01',
                                    'X-Requested-With': 'XMLHttpRequest'
                                },
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400 && response.response) {
                                        const data = response.response;
                                        if (data.status === 'success' && typeof data.html === 'string') {
                                            resolve(this.parseHtml(data.html, this));
                                        } else if (data.status === 'false' && data.message && data.message.includes("ничего не найдено")) {
                                            resolve([]);
                                        } else if (data.status === 'empty') {
                                            resolve([]);
                                        } else if (data.status === 'success' && !data.html) {
                                            resolve([]);
                                        } else {
                                            reject(new Error(`API вернул неожиданный ответ: Статус ${data.status}, Сообщение: ${data.message || 'Нет сообщения'}`));
                                        }
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const items = doc.querySelectorAll('.search-result__item');

                        items.forEach(item => {
                            try {
                                const linkElement = item.querySelector('.search-result__link');
                                const imgElement = item.querySelector('.search-result__img img');
                                const titleElement = item.querySelector('.search-result__title');
                                const priceElement = item.querySelector('.search-result__cost');
                                const discountElement = item.querySelector('.search-result__discount');

                                const productName = titleElement?.textContent?.trim() || null;
                                const productUrlRaw = linkElement?.getAttribute('href') || null;
                                const currentPriceText = priceElement?.innerHTML.replace(/<span[^>]*>.*<\/span>/i, '').replace('р', '').trim();
                                const currentPrice = sm_parsePrice(currentPriceText);

                                let discountPercent = 0;
                                const discountText = discountElement?.textContent?.trim();
                                if (discountText && discountText !== '&nbsp;') {
                                    const parsedPercent = sm_parsePercent(discountText);
                                    if (parsedPercent !== null) {
                                        discountPercent = parsedPercent;
                                    }
                                }

                                const imageUrl = imgElement?.getAttribute('src') || null;

                                if (productName && productUrlRaw && currentPrice !== null) {
                                    const fullProductUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                    const productUrl = fullProductUrl + '?partner=234029';

                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name,
                                        storeUrl: storeModule.baseUrl,
                                        productName: productName,
                                        productUrl: productUrl,
                                        imageUrl: imageUrl,
                                        currentPrice: currentPrice,
                                        originalPrice: null,
                                        discountPercent: discountPercent,
                                        discountAmount: null,
                                        currency: 'RUB',
                                        isAvailable: true
                                    };
                                    results.push(sm_calculateMissingValues(data));
                                } else {}
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента из AJAX HTML', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля SteamBuy ---

                { // --- Модуль Playo ---
                    id: 'playo',
                    name: 'Playo',
                    baseUrl: 'https://playo.ru',
                    searchUrlTemplate: 'https://playo.ru/search/{query}/?search={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const urlEncodedQuery = encodeURIComponent(query).replace(/%20/g, '+');
                        const pathEncodedQuery = encodeURIComponent(query);
                        const searchUrl = this.searchUrlTemplate
                            .replace('{query}', pathEncodedQuery)
                            .replace('{query}', urlEncodedQuery);

                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const items = doc.querySelectorAll('.preview_list .preview_it');

                        items.forEach(item => {
                            try {
                                const linkElement = item.querySelector('a.link_preview');
                                const imgElement = item.querySelector('.img_prev img');
                                const titleElement = item.querySelector('.inf');
                                const priceElement = item.querySelector('.price');
                                const oldPriceElement = item.querySelector('.old_price');
                                const discountPercentElement = item.querySelector('.gmlst_dscnt_lbl');
                                const discountAmountElement = item.querySelector('.gmlst_dsnt_val_text');

                                const productUrlRaw = linkElement ? linkElement.getAttribute('href') : null;
                                const imageUrlRaw = imgElement ? imgElement.getAttribute('src') : null;
                                let productName = null;
                                if (titleElement) {
                                    const clonedTitle = titleElement.cloneNode(true);
                                    const economySpan = clonedTitle.querySelector('.gmlst_dsnt_val_text');
                                    if (economySpan) economySpan.remove();
                                    productName = clonedTitle.textContent.replace(/\s+/g, ' ').trim();
                                }

                                const currentPrice = priceElement ? sm_parsePrice(priceElement.textContent) : null;
                                const originalPrice = oldPriceElement ? sm_parsePrice(oldPriceElement.textContent) : null;
                                const discountPercent = discountPercentElement ? sm_parsePercent(discountPercentElement.textContent) : null;
                                const discountAmount = discountAmountElement ? sm_parsePrice(discountAmountElement.textContent) : null;

                                if (productName && productUrlRaw && currentPrice !== null) {
                                    const fullProductUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                    const productUrl = fullProductUrl + '?s=n3j6y08f';
                                    const imageUrl = imageUrlRaw.startsWith('/') ? storeModule.baseUrl + imageUrlRaw : imageUrlRaw;

                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name,
                                        storeUrl: storeModule.baseUrl,
                                        productName: productName,
                                        productUrl: productUrl,
                                        imageUrl: imageUrl,
                                        currentPrice: currentPrice,
                                        originalPrice: originalPrice,
                                        discountPercent: discountPercent,
                                        discountAmount: discountAmount,
                                        currency: 'RUB',
                                        isAvailable: true
                                    };
                                    results.push(sm_calculateMissingValues(data));
                                }
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента', e);
                            }
                        });
                        return results;
                    }
                },

                { // --- Модуль SteamPay ---
                    id: 'steampay',
                    name: 'SteamPay',
                    baseUrl: 'https://steampay.com',
                    searchUrlTemplate: 'https://steampay.com/search?q={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const items = doc.querySelectorAll('.catalog-item');

                        items.forEach(item => {
                            try {
                                const linkElement = item;
                                const imgElement = item.querySelector('.catalog-item__img img');
                                const nameElement = item.querySelector('.catalog-item__name');
                                const priceSpanElement = item.querySelector('.catalog-item__price-span');
                                const discountElement = item.querySelector('.catalog-item__discount');

                                const currentPriceText = priceSpanElement?.textContent?.trim();
                                const currentPrice = sm_parsePrice(currentPriceText);
                                if (currentPrice === null) {
                                    return;
                                }

                                let productName = null;
                                if (nameElement) {
                                    const nameClone = nameElement.cloneNode(true);
                                    const infoDiv = nameClone.querySelector('.catalog-item__info');
                                    if (infoDiv) infoDiv.remove();
                                    productName = nameClone.textContent?.trim();
                                }

                                const productUrl = linkElement?.getAttribute('href');
                                const imageUrl = imgElement?.getAttribute('src');
                                const discountPercent = discountElement ? sm_parsePercent(discountElement.textContent) : 0;

                                if (productName && productUrl) {
                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name,
                                        storeUrl: storeModule.baseUrl,
                                        productName: productName,
                                        productUrl: productUrl.startsWith('/') ? storeModule.baseUrl + productUrl : productUrl,
                                        imageUrl: imageUrl?.startsWith('/') ? storeModule.baseUrl + imageUrl : imageUrl,
                                        currentPrice: currentPrice,
                                        originalPrice: null,
                                        discountPercent: discountPercent,
                                        discountAmount: null,
                                        currency: 'RUB',
                                        isAvailable: true
                                    };
                                    results.push(sm_calculateMissingValues(data));
                                }
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля SteamPay ---

                { // --- Модуль Gabestore ---
                    id: 'gabestore',
                    name: 'Gabestore',
                    baseUrl: 'https://gabestore.ru',
                    searchUrlTemplate: 'https://gabestore.ru/result?ProductFilter%5Bsearch%5D={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const itemsContainer = doc.querySelector('.js-load-container');
                        const items = itemsContainer ? itemsContainer.querySelectorAll('.shop-item') : [];

                        items.forEach(item => {
                            try {
                                const nameLinkElement = item.querySelector('a.shop-item__name');
                                const imageLinkElement = item.querySelector('a.shop-item__image');
                                const imgElement = imageLinkElement?.querySelector('img');
                                const priceElement = item.querySelector('.shop-item__price-current');
                                const discountElement = item.querySelector('.shop-item__price-discount');

                                const productName = nameLinkElement?.textContent?.trim();
                                const productUrlRaw = nameLinkElement?.getAttribute('href') || imageLinkElement?.getAttribute('href');
                                const imageUrl = imgElement?.getAttribute('src');
                                const currentPrice = priceElement ? sm_parsePrice(priceElement.textContent) : null;
                                const discountPercent = discountElement ? sm_parsePercent(discountElement.textContent) : 0;

                                if (!productName || !productUrlRaw || currentPrice === null) {
                                    return;
                                }

                                const fullOriginalUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                const referralPrefix = 'https://codeaven.com/g/om6s6jfc50c1442ace4b215ab801b9/?erid=2bL9aMPo2e49hMef4peVT3sy3u&ulp=';
                                const productUrl = referralPrefix + encodeURIComponent(fullOriginalUrl);

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl,
                                    imageUrl: imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: null,
                                    discountPercent: discountPercent,
                                    discountAmount: null,
                                    currency: 'RUB',
                                    isAvailable: !item.querySelector('.btn--empty-item')
                                };

                                if (data.isAvailable) {
                                    results.push(sm_calculateMissingValues(data));
                                }

                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля Gabestore ---

                { // --- Модуль GamerBase ---
                    id: 'gamerbase',
                    name: 'GamersBase',
                    baseUrl: 'https://gamersbase.store',
                    searchUrlTemplate: 'https://gamersbase.store/ru/search/?isFullTextSearch=true&searchQuery={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const storeModule = this;

                        const searchByName = () => {
                            const searchUrl = storeModule.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                            return new Promise((resolve, reject) => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: searchUrl,
                                    timeout: SM_REQUEST_TIMEOUT_MS,
                                    onload: (response) => {
                                        if (response.status >= 200 && response.status < 400) {
                                            resolve(storeModule.parseHtml(response.responseText, storeModule));
                                        } else {
                                            reject(new Error(`[Fallback] HTTP статус ${response.status}`));
                                        }
                                    },
                                    onerror: (error) => reject(new Error('[Fallback] Сетевая ошибка')),
                                    ontimeout: () => reject(new Error('[Fallback] Таймаут запроса'))
                                });
                            });
                        };

                        const steamAppIdMatch = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
                        if (!steamAppIdMatch || !steamAppIdMatch[1]) {
                            return searchByName();
                        }
                        const currentAppId = steamAppIdMatch[1];
                        const xmlFeedUrl = "https://coreplatform.blob.core.windows.net/products-content/steam_pages_feed.xml";

                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: xmlFeedUrl,
                                responseType: 'text',
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        try {
                                            const parser = new DOMParser();
                                            const xml = parser.parseFromString(response.responseText, "application/xml");
                                            const match = Array.from(xml.querySelectorAll("game")).find(game => game.querySelector("steam_id")?.textContent === currentAppId);

                                            if (match) {
                                                const isAvailable = match.querySelector("available")?.textContent === "True";
                                                const price = sm_parsePrice(match.querySelector("price")?.textContent);
                                                const gameCode = match.querySelector("code_gb")?.textContent;

                                                if (isAvailable && price !== null && gameCode) {
                                                    const headerImageElement = document.querySelector('#gameHeaderImageCtn img.game_header_image_full');
                                                    const mainImageUrl = headerImageElement ? headerImageElement.src : null;
                                                    const fullOriginalUrl = `https://gamersbase.store/game/${gameCode}`;
                                                    const referralPrefix = 'https://lsuix.com/g/nzstwno2sac1442ace4bb0de1ddd64/?erid=2bL9aMPo2e49hMef4pfVDVxtYh&ulp=';
                                                    const productUrl = referralPrefix + encodeURIComponent(fullOriginalUrl);

                                                    let data = {
                                                        storeId: storeModule.id,
                                                        storeName: storeModule.name,
                                                        storeUrl: storeModule.baseUrl,
                                                        productName: query,
                                                        productUrl: productUrl,
                                                        imageUrl: mainImageUrl,
                                                        currentPrice: price,
                                                        originalPrice: null,
                                                        discountPercent: null,
                                                        discountAmount: null,
                                                        currency: 'RUB',
                                                        isAvailable: true
                                                    };
                                                    return resolve([sm_calculateMissingValues(data)]);
                                                }
                                            }
                                            searchByName().then(resolve).catch(reject);

                                        } catch (e) {
                                            sm_logError(storeModule.name, 'Ошибка парсинга XML, переход на поиск по названию.', e);
                                            searchByName().then(resolve).catch(reject);
                                        }
                                    } else {
                                        sm_logError(storeModule.name, `XML-фид недоступен (статус ${response.status}), переход на поиск по названию.`);
                                        searchByName().then(resolve).catch(reject);
                                    }
                                },
                                onerror: (error) => {
                                    sm_logError(storeModule.name, 'Сетевая ошибка XML, переход на поиск по названию.', error);
                                    searchByName().then(resolve).catch(reject);
                                },
                                ontimeout: () => {
                                    sm_logError(storeModule.name, 'Таймаут XML, переход на поиск по названию.');
                                    searchByName().then(resolve).catch(reject);
                                }
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const items = doc.querySelectorAll('.js-products-container .ui.cover');

                        items.forEach(item => {
                            try {
                                const linkElement = item.querySelector('a.cover-holder');
                                const imgElement = item.querySelector('.image img');
                                const buyButton = item.querySelector('.js-add-product');
                                const productDataJson = linkElement?.dataset.product || buyButton?.dataset.product;

                                if (!productDataJson) return;

                                const productData = JSON.parse(productDataJson);
                                if (!productData?.name || !productData?.priceData) return;

                                const productName = productData.name;
                                const productUrlRaw = linkElement?.getAttribute('href');
                                const imageUrl = imgElement?.getAttribute('src');
                                const currentPrice = sm_parsePrice(productData.priceData.actualPriceFormatted);
                                const originalPrice = sm_parsePrice(productData.priceData.standardPriceFormatted);
                                const discountPercent = productData.priceData.discountPercent || 0;
                                const currency = productData.priceData.currency || 'RUB';
                                const isAvailable = item.querySelector('.js-add-product.available-true') !== null;

                                if (productName && productUrlRaw && currentPrice !== null) {
                                    let fullOriginalUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                    const urlObject = new URL(fullOriginalUrl);
                                    if (urlObject.pathname.startsWith('/ru/')) {
                                        urlObject.pathname = urlObject.pathname.substring(3);
                                        fullOriginalUrl = urlObject.toString();
                                    }
                                    const referralPrefix = 'https://lsuix.com/g/nzstwno2sac1442ace4bb0de1ddd64/?erid=2bL9aMPo2e49hMef4pfVDVxtYh&ulp=';
                                    const productUrl = referralPrefix + encodeURIComponent(fullOriginalUrl);

                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name,
                                        storeUrl: storeModule.baseUrl,
                                        productName: productName,
                                        productUrl: productUrl,
                                        imageUrl: imageUrl,
                                        currentPrice: currentPrice,
                                        originalPrice: originalPrice,
                                        discountPercent: discountPercent,
                                        discountAmount: null,
                                        currency: currency,
                                        isAvailable: isAvailable
                                    };
                                    if (data.isAvailable) {
                                        results.push(sm_calculateMissingValues(data));
                                    }
                                }
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента или JSON в data-product', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля GamerBase ---

                { // --- Модуль Igromagaz ---
                    id: 'igromagaz',
                    name: 'Igromagaz',
                    baseUrl: 'https://www.igromagaz.ru',
                    searchUrlTemplate: 'https://www.igromagaz.ru/search/?q={query}&quantity_in=Y',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const items = doc.querySelectorAll('.product-card');

                        items.forEach(item => {
                            try {
                                const notAvailableElement = item.querySelector('.product-availability--not-available');
                                const notifyButton = item.querySelector('.button-notify-js');
                                if (notAvailableElement || notifyButton) {
                                    return;
                                }

                                const titleLinkElement = item.querySelector('a.product-title');
                                const imageLinkElement = item.querySelector('a.product-img');
                                const imgElement = imageLinkElement?.querySelector('img');
                                const priceElement = item.querySelector('.product-price__standart');
                                const oldPriceElement = item.querySelector('.product-price__fail');
                                const discountElement = item.querySelector('.sale-label');

                                const productName = titleLinkElement?.textContent?.trim();
                                const productUrl = titleLinkElement?.getAttribute('href') || imageLinkElement?.getAttribute('href');
                                const imageUrl = imgElement?.getAttribute('src');
                                const currentPrice = priceElement ? sm_parsePrice(priceElement.textContent) : null;
                                const originalPrice = oldPriceElement ? sm_parsePrice(oldPriceElement.textContent) : null;
                                const discountPercent = discountElement ? sm_parsePercent(discountElement.textContent) : null;

                                if (!productName || !productUrl || currentPrice === null) {
                                    return;
                                }

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl.startsWith('/') ? storeModule.baseUrl + productUrl : productUrl,
                                    imageUrl: imageUrl?.startsWith('/') ? storeModule.baseUrl + imageUrl : imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: originalPrice,
                                    discountPercent: discountPercent,
                                    discountAmount: null,
                                    currency: 'RUB',
                                    isAvailable: true
                                };
                                results.push(sm_calculateMissingValues(data));
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля Igromagaz ---

                { // --- Модуль GamesForFarm ---
                    id: 'gamesforfarm',
                    name: 'GamesForFarm',
                    baseUrl: 'https://gamesforfarm.com',
                    searchUrlTemplate: 'https://gamesforfarm.com/?search={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const container = doc.querySelector('#gamesCatalog');
                        if (!container) return results;

                        const items = container.querySelectorAll('.product__item');

                        items.forEach(item => {
                            try {
                                const linkElement = item.querySelector('.product__box-title a');
                                const imgElement = item.querySelector('.product__box-image img');
                                const priceElement = item.querySelector('.product__box-price');
                                const discountElement = item.querySelector('.product__box-prop.prop--discount');

                                let currentPrice = null;
                                if (priceElement) {
                                    const priceClone = priceElement.cloneNode(true);
                                    const currencySpan = priceClone.querySelector('span.sc-ru3bl');
                                    if (currencySpan) currencySpan.remove();
                                    currentPrice = sm_parsePrice(priceClone.textContent);
                                }

                                const productName = linkElement?.textContent?.trim();
                                const productUrl = linkElement?.getAttribute('href');
                                const imageUrl = imgElement?.dataset.src || imgElement?.getAttribute('src');
                                const discountPercent = discountElement ? sm_parsePercent(discountElement.textContent) : 0;

                                if (!productName || !productUrl || currentPrice === null) {
                                    return;
                                }

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl.startsWith('/') ? storeModule.baseUrl + productUrl : productUrl,
                                    imageUrl: imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: null,
                                    discountPercent: discountPercent,
                                    discountAmount: null,
                                    currency: 'RUB',
                                    isAvailable: true
                                };
                                results.push(sm_calculateMissingValues(data));
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля GamesForFarm ---


                { // --- Модуль Gamazavr ---
                    id: 'gamazavr',
                    name: 'Gamazavr',
                    baseUrl: 'https://gamazavr.ru',
                    searchUrlTemplate: 'https://gamazavr.ru/search/?query={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const container = doc.querySelector('.productsList');
                        if (!container) {
                            return results;
                        }

                        const items = container.querySelectorAll('.item');

                        items.forEach(item => {
                            try {
                                const descriptionLink = item.querySelector('.description a');
                                const imageLink = item.querySelector('a.img');
                                const imgElement = imageLink?.querySelector('img');
                                const priceElement = item.querySelector('.price');
                                const currentPriceElement = priceElement?.querySelector('b');
                                const originalPriceElement = priceElement?.querySelector('s');

                                const productName = descriptionLink?.querySelector('b')?.textContent?.trim();
                                const productUrlRaw = descriptionLink?.getAttribute('href');
                                const imageUrlRaw = imgElement?.getAttribute('src');

                                const currentPrice = currentPriceElement ? sm_parsePrice(currentPriceElement.textContent) : null;
                                const originalPrice = originalPriceElement ? sm_parsePrice(originalPriceElement.textContent) : null;

                                if (!productName || !productUrlRaw || currentPrice === null) {
                                    return;
                                }

                                const fullProductUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                const productUrl = fullProductUrl + '?partner=8293ebf587779da6';
                                const imageUrl = imageUrlRaw?.startsWith('/') ? storeModule.baseUrl + imageUrlRaw : imageUrlRaw;

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl,
                                    imageUrl: imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: originalPrice,
                                    discountPercent: null,
                                    discountAmount: null,
                                    currency: 'RUB',
                                    isAvailable: true
                                };
                                results.push(sm_calculateMissingValues(data));

                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента Gamazavr', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля Gamazavr ---

                { // --- Модуль GameRay ---
                    id: 'gameray',
                    name: 'GameRay',
                    baseUrl: 'https://gameray.ru',
                    searchUrlTemplate: 'https://gameray.ru/search/index.php?q={query}',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        let initialResults = [];

                        // --- Шаг 1: Получаем список игр со страницы поиска ---
                        try {
                            const response = await new Promise((resolve, reject) => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: searchUrl,
                                    timeout: SM_REQUEST_TIMEOUT_MS,
                                    onload: resolve,
                                    onerror: reject,
                                    ontimeout: () => reject(new Error('Таймаут запроса (поиск)')),
                                });
                            });

                            if (response.status >= 200 && response.status < 400) {
                                initialResults = this.parseSearchPage(response.responseText, this);
                            } else {
                                throw new Error(`HTTP статус ${response.status} (поиск)`);
                            }
                        } catch (error) {
                            sm_logError(this.name, `Ошибка на шаге 1 (поиск): ${error.message}`, error);
                            return [];
                        }

                        if (initialResults.length === 0) {
                            return [];
                        }

                        // --- Шаг 2: Запрашиваем каждую страницу товара для деталей ---
                        const detailPromises = initialResults.map(initialData =>
                            new Promise(async (resolve) => {
                                try {
                                    const productResponse = await new Promise((resolveFetch, rejectFetch) => {
                                        GM_xmlhttpRequest({
                                            method: "GET",
                                            url: initialData.fullProductUrl,
                                            timeout: SM_REQUEST_TIMEOUT_MS,
                                            onload: resolveFetch,
                                            onerror: rejectFetch,
                                            ontimeout: () => rejectFetch(new Error(`Таймаут запроса (${initialData.productName})`)),
                                        });
                                    });

                                    if (productResponse.status >= 200 && productResponse.status < 400) {
                                        resolve(this.parseProductPage(productResponse.responseText, initialData, this));
                                    } else {
                                        sm_logError(this.name, `Ошибка загрузки страницы товара ${initialData.productName} (Статус: ${productResponse.status})`);
                                        resolve(null);
                                    }
                                } catch (error) {
                                    sm_logError(this.name, `Ошибка загрузки страницы товара ${initialData.productName}: ${error.message}`, error);
                                    resolve(null);
                                }
                            })
                        );

                        const detailedResults = await Promise.allSettled(detailPromises);

                        const finalResults = detailedResults
                            .filter(result => result.status === 'fulfilled' && result.value !== null)
                            .map(result => result.value);

                        return finalResults;
                    },

                    parseSearchPage: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const container = doc.querySelector('.search-page') || doc.body;
                        const items = container.querySelectorAll('a.ec-clicker');

                        items.forEach(item => {
                            try {
                                const productName = item.dataset.name?.trim();
                                const productUrlRaw = item.getAttribute('href');
                                const imgElement = item.querySelector('img');
                                const imageUrlRaw = imgElement?.getAttribute('src');

                                if (productName && productUrlRaw && imageUrlRaw) {
                                    const fullProductUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                    const imageUrl = imageUrlRaw.startsWith('/') ? storeModule.baseUrl + imageUrlRaw : imageUrlRaw;

                                    results.push({
                                        productName: productName,
                                        fullProductUrl: fullProductUrl,
                                        imageUrl: imageUrl
                                    });
                                }
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента на странице поиска', e);
                            }
                        });
                        return results;
                    },

                    parseProductPage: function(htmlString, initialData, storeModule) {
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');

                        const pricingBlock = doc.querySelector('div.pricing');
                        if (!pricingBlock) {
                            sm_logError(storeModule.name, `Блок .pricing не найден для: ${initialData.productName}`);
                            return null;
                        }

                        const buyButton = pricingBlock.querySelector('a.buy-button');
                        const isAvailable = buyButton !== null;

                        if (!isAvailable) {
                            return null;
                        }

                        const priceElement = pricingBlock.querySelector('strong.price span[itemprop="price"]');
                        const originalPriceElement = pricingBlock.querySelector('strike.price_old');

                        const currentPrice = priceElement ? sm_parsePrice(priceElement.textContent) : null;
                        const originalPrice = originalPriceElement ? sm_parsePrice(originalPriceElement.textContent) : null;

                        if (currentPrice === null) {
                            sm_logError(storeModule.name, `Не найдена цена в блоке .pricing для: ${initialData.productName}`);
                            return null;
                        }

                        const productUrlWithRef = initialData.fullProductUrl + '?partner=93';

                        let finalData = {
                            storeId: storeModule.id,
                            storeName: storeModule.name,
                            storeUrl: storeModule.baseUrl,
                            productName: initialData.productName,
                            productUrl: productUrlWithRef,
                            imageUrl: initialData.imageUrl,
                            currentPrice: currentPrice,
                            originalPrice: originalPrice,
                            discountPercent: null,
                            discountAmount: null,
                            currency: 'RUB',
                            isAvailable: isAvailable
                        };

                        return sm_calculateMissingValues(finalData);
                    }
                }, // --- Конец модуля GameRay ---

                { // --- Модуль Kupikod ---
                        id: 'kupikod',
                        name: 'KupiKod',
                        baseUrl: 'https://kupikod.com',
                        apiGamesUrlTemplate: 'https://explorer.kupikod.com/backend/api/games?name={query}',
                        apiShopUrlTemplate: 'https://explorer.kupikod.com/backend/api/shop/products-list?name={query}',
                        isEnabled: true,
                        // Список суффиксов регионов для исключения (в нижнем регистре)
                        excludedRegionSuffixes: [
                            '-eu', '-us', '-arg', '-tr', '-no-ru-no-rb', '-no-ru-no-cis',
                            '-no-ru', '-euus', '-cis', '-uk', '-in', '-eg'
                        ],
                        // Список ключевых слов платформ для исключения (в нижнем регистре)
                        excludedPlatformKeywords: [
                            '-xbox-', '-origin-', '-uplay-', '-gog-', '-rockstar-',
                            '-battlestate-', '-nintendo-'
                        ],
                        fetch: async function(query) {
                            const storeModule = this;
                            const encodedQuery = encodeURIComponent(query);
                            const gamesUrl = storeModule.apiGamesUrlTemplate.replace('{query}', encodedQuery);
                            const shopUrl = storeModule.apiShopUrlTemplate.replace('{query}', encodedQuery);

                            const fetchPromise = (url) => new Promise((resolve, reject) => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: url,
                                    responseType: 'json',
                                    timeout: SM_REQUEST_TIMEOUT_MS,
                                    onload: (response) => {
                                        if (response.status >= 200 && response.status < 400 && response.response) {
                                            resolve(response.response);
                                        } else {
                                            sm_logError(storeModule.name, `HTTP статус ${response.status} для ${url}`);
                                            resolve(null);
                                        }
                                    },
                                    onerror: (error) => {
                                         sm_logError(storeModule.name, `Сетевая ошибка для ${url}`, error);
                                         resolve(null);
                                    },
                                    ontimeout: () => {
                                         sm_logError(storeModule.name, `Таймаут запроса для ${url}`);
                                         resolve(null);
                                    }
                                });
                            });

                            const [gamesResult, shopResult] = await Promise.allSettled([
                                fetchPromise(gamesUrl),
                                fetchPromise(shopUrl)
                            ]);

                            let finalResults = [];

                            if (gamesResult.status === 'fulfilled' && gamesResult.value?.data) {
                                try {
                                    finalResults = finalResults.concat(storeModule.parseGamesApi(gamesResult.value.data, storeModule));
                                } catch(e) {
                                     sm_logError(storeModule.name, 'Ошибка парсинга ответа Games API', e);
                                }
                            } else if (gamesResult.status === 'rejected') {
                            }

                            if (shopResult.status === 'fulfilled' && shopResult.value?.data) {
                                 try {
                                    finalResults = finalResults.concat(storeModule.parseShopApi(shopResult.value.data, storeModule));
                                 } catch(e) {
                                     sm_logError(storeModule.name, 'Ошибка парсинга ответа Shop API', e);
                                 }
                            } else if (shopResult.status === 'rejected') {
                            }

                            return finalResults;
                        },

                        // Парсер для ответа от /api/games (Steam-гифты)
                        parseGamesApi: function(items, storeModule) {
                            const results = [];
                            if (!Array.isArray(items)) {
                                 sm_logError(storeModule.name, 'Games API response data is not an array', items);
                                 return results;
                            }

                            const referralBase = "https://yknhc.com/g/lfofiog4lqc1442ace4b294cb5928a/";
                            const referralParams = "?erid=2bL9aMPo2e49hMef4phUQVF5W8&ulp=";

                            items.forEach(item => {
                                try {
                                    const productName = item.name?.trim();
                                    const slug = item.slug;
                                    const currentPrice = sm_parsePrice(item.min_price?.rub ?? null);
                                    const originalPriceRaw = sm_parsePrice(item.min_old_price?.rub ?? null);
                                    const originalPrice = (originalPriceRaw !== null && currentPrice !== null && originalPriceRaw > currentPrice) ? originalPriceRaw : null;
                                    const imageUrl = item.external_data?.header_image;

                                    if (!productName || !slug || currentPrice === null || !imageUrl) {
                                        return;
                                    }

                                    const originalProductUrl = `https://steam.kupikod.com/ru-ru/games/${slug}`;
                                    const productUrl = referralBase + referralParams + encodeURIComponent(originalProductUrl);

                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name + " (Гифты)",
                                        storeUrl: "https://steam.kupikod.com/",
                                        productName: productName,
                                        productUrl: productUrl,
                                        imageUrl: imageUrl,
                                        currentPrice: currentPrice,
                                        originalPrice: originalPrice,
                                        discountPercent: null,
                                        discountAmount: null,
                                        currency: 'RUB',
                                        isAvailable: true
                                    };
                                    results.push(sm_calculateMissingValues(data));
                                } catch (e) {
                                    sm_logError(storeModule.name, 'Ошибка парсинга элемента Games API', e);
                                }
                            });
                            return results;
                        },

                        // Парсер для ответа от /api/shop/products-list (Ключи)
                        parseShopApi: function(items, storeModule) {
                            const results = [];
                            if (!Array.isArray(items)) {
                                sm_logError(storeModule.name, 'Shop API response data is not an array', items);
                                return results;
                            }

                            const referralBase = "https://yknhc.com/g/lfofiog4lqc1442ace4b294cb5928a/";
                            const referralParams = "?erid=2bL9aMPo2e49hMef4phUQVF5W8&ulp=";

                            items.forEach(item => {
                                try {
                                    const productName = item.h1_title?.trim();
                                    const slug = item.slug?.toLowerCase();
                                    const currentPrice = sm_parsePrice(item.price ?? null);
                                    const originalPriceRaw = sm_parsePrice(item.old_price ?? null);
                                    const originalPrice = (originalPriceRaw !== null && originalPriceRaw > 0 && currentPrice !== null && originalPriceRaw > currentPrice) ? originalPriceRaw : null;
                                    const imageUrl = item.picture_url;

                                    if (!imageUrl || typeof imageUrl !== 'string' || imageUrl.includes('/apps//')) {
                                         return;
                                    }

                                    if (!productName || !slug || currentPrice === null) {
                                        return;
                                    }

                                    if (storeModule.excludedRegionSuffixes.some(suffix => slug.endsWith(suffix))) {
                                         return;
                                    }
                                     if (storeModule.excludedPlatformKeywords.some(keyword => slug.includes(keyword))) {
                                         return;
                                    }

                                    const originalProductUrl = `${storeModule.baseUrl}/shop/${item.slug}`;
                                    const productUrl = referralBase + referralParams + encodeURIComponent(originalProductUrl);

                                    let data = {
                                        storeId: storeModule.id,
                                        storeName: storeModule.name + " (Ключи)",
                                        storeUrl: storeModule.baseUrl,
                                        productName: productName,
                                        productUrl: productUrl,
                                        imageUrl: imageUrl,
                                        currentPrice: currentPrice,
                                        originalPrice: originalPrice,
                                        discountPercent: null,
                                        discountAmount: null,
                                        currency: 'RUB',
                                        isAvailable: true
                                    };
                                    results.push(sm_calculateMissingValues(data));
                                } catch (e) {
                                    sm_logError(storeModule.name, 'Ошибка парсинга элемента Shop API', e);
                                }
                            });
                            return results;
                        }
                    }, // --- Конец модуля Kupikod ---

                { // --- Модуль KeysForGamers ---
                    id: 'keysforgamers',
                    name: 'KeysForGamers',
                    baseUrl: 'https://keysforgamers.com',
                    apiUrl: 'https://keysforgamers.com/ru/product/search',
                    isEnabled: true,
                    fetch: async function(query) {
                        const storeModule = this;
                        let searchQuery = query;

                        const containsCyrillic = /[а-яё]/i.test(query);
                        if (containsCyrillic) {
                            sm_logError(storeModule.name, `Обнаружена кириллица в запросе "${query}". Пытаемся получить английское название...`);
                            const steamAppIdMatch = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);

                            if (steamAppIdMatch && steamAppIdMatch[1]) {
                                const currentAppId = steamAppIdMatch[1];
                                const apiUrl = `https://store.steampowered.com/api/appdetails?appids=${currentAppId}&l=english`;

                                try {
                                    const response = await new Promise((resolve, reject) => {
                                        GM_xmlhttpRequest({
                                            method: "GET",
                                            url: apiUrl,
                                            responseType: 'json',
                                            timeout: SM_REQUEST_TIMEOUT_MS,
                                            onload: resolve,
                                            onerror: reject,
                                            ontimeout: () => reject(new Error('Таймаут запроса к Steam API (AppDetails)')),
                                        });
                                    });

                                    if (response.status === 200 && response.response && response.response[currentAppId]?.success) {
                                        const englishName = response.response[currentAppId]?.data?.name;
                                        if (englishName && englishName.trim()) {
                                            searchQuery = englishName.trim();
                                            sm_logError(storeModule.name, `Используем английское название для поиска: "${searchQuery}"`);
                                        } else {
                                            sm_logError(storeModule.name, `Steam API вернул успех, но английское имя не найдено для AppID ${currentAppId}. Используем оригинальный запрос.`);
                                        }
                                    } else {
                                        sm_logError(storeModule.name, `Запрос к Steam API не удался или неверный ответ для AppID ${currentAppId} (Status: ${response.status}). Используем оригинальный запрос.`);
                                    }
                                } catch (error) {
                                    sm_logError(storeModule.name, `Ошибка при получении английского названия из Steam API: ${error.message}. Используем оригинальный запрос.`, error);
                                }
                            } else {
                                sm_logError(storeModule.name, 'Не удалось получить Steam AppID со страницы для запроса английского названия. Используем оригинальный запрос.');
                            }
                        }


                        let csrfToken = '';

                        try {
                            const mainPageResponse = await new Promise((resolve, reject) => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: storeModule.baseUrl + '/ru/',
                                    timeout: SM_REQUEST_TIMEOUT_MS,
                                    onload: resolve,
                                    onerror: reject,
                                    ontimeout: () => reject(new Error('Таймаут запроса (CSRF)')),
                                });
                            });
                            if (mainPageResponse.status >= 200 && mainPageResponse.status < 400) {
                                const parser = new DOMParser();
                                const doc = parser.parseFromString(mainPageResponse.responseText, 'text/html');
                                const csrfMetaTag = doc.querySelector('meta[name="csrf-token"]');
                                if (!csrfMetaTag) throw new Error('Мета-тег csrf-token не найден!');
                                csrfToken = csrfMetaTag.getAttribute('content');
                                if (!csrfToken) throw new Error('Не удалось получить значение csrf-token!');
                            } else {
                                throw new Error(`HTTP статус ${mainPageResponse.status} при получении CSRF`);
                            }

                        } catch (error) {
                            sm_logError(storeModule.name, `Ошибка получения CSRF токена: ${error.message}`, error);
                            throw error;
                        }

                        let allItems = [];
                        let currentPage = 1;
                        let totalPages = 1;

                        do {
                            const requestPayload = {
                                productTypes: [{ value: "6", id: "category-6" }],
                                regionData: [
                                    { value: "1", id: "region-1" },
                                    { value: "85", id: "region-85" },
                                    { value: "6", id: "region-6" }
                                ],
                                searchData: [{ value: searchQuery, id: "product-search" }],
                                sortData: [{ value: "4", id: "search_sort" }],
                                priceRange: [{ value: ["0.00", "99999.00"], id: ["min_price", "max_price"] }],
                                page: currentPage,
                                perPage: 24,
                                switchData: [],
                                marketplaceData: [],
                                otherTypesData: [],
                                hashData: [],
                                showMorePages: 0,
                                isMinPriceChanged: false,
                                isMaxPriceChanged: true,
                                minPriceValue: 0,
                                maxPriceValue: 99999.00
                            };
                            const requestHeaders = {
                                'Accept': 'application/json, text/plain, */*',
                                'Content-Type': 'application/json',
                                'X-Csrf-Token': csrfToken,
                                'X-Requested-With': 'XMLHttpRequest'
                            };

                            try {
                                const response = await new Promise((resolve, reject) => {
                                    GM_xmlhttpRequest({
                                        method: "POST",
                                        url: storeModule.apiUrl,
                                        headers: requestHeaders,
                                        data: JSON.stringify(requestPayload),
                                        responseType: 'json',
                                        timeout: SM_REQUEST_TIMEOUT_MS,
                                        onload: resolve,
                                        onerror: reject,
                                        ontimeout: () => reject(new Error(`Таймаут запроса (page: ${currentPage})`)),
                                    });
                                });

                                if (response.status >= 200 && response.status < 400 && response.response) {
                                    const data = response.response;
                                    if (data.catalogBody && typeof data.catalogBody === 'string') {
                                        const pageItems = storeModule.parseKFGHtml(data.catalogBody, storeModule);
                                        allItems = allItems.concat(pageItems);
                                    }
                                    totalPages = data.pages ?? totalPages;
                                    if (data.pages === undefined && currentPage === 1) totalPages = 1;
                                } else {
                                    throw new Error(`HTTP статус ${response.status} (page: ${currentPage})`);
                                }

                            } catch (error) {
                                sm_logError(storeModule.name, `Ошибка загрузки страницы ${currentPage}: ${error.message}`, error);
                                throw error;
                            }

                            currentPage++;
                            if (currentPage <= totalPages) await new Promise(res => setTimeout(res, 150));

                        } while (currentPage <= totalPages);

                        return allItems;
                    },
                    parseKFGHtml: function(htmlString, storeModule) {
                        const items = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const productElements = doc.querySelectorAll('.items-list .product-item');

                        productElements.forEach(element => {
                            try {
                                const titleElement = element.querySelector('.catalog-card__item-title');
                                const priceElement = element.querySelector('.catalog-card__price');
                                const linkElement = element.querySelector('.catalog-card__img-link, .product-card__link, .catalog-card__item-title a');
                                const imgElement = element.querySelector('.catalog-card__img img, .product-card img');

                                const productName = titleElement?.textContent?.trim();
                                const priceText = priceElement?.textContent?.trim();
                                const productUrlRaw = linkElement?.getAttribute('href');
                                const imageUrlRaw = imgElement?.getAttribute('src');

                                if (!productName || !priceText || !productUrlRaw || !imageUrlRaw) {
                                    return;
                                }

                                const cleanedPriceText = priceText.replace(/[₽$,]/g, '');
                                const currentPrice = sm_parsePrice(cleanedPriceText);

                                if (currentPrice === null) {
                                    sm_logError(storeModule.name, `Не удалось распарсить очищенную цену: ${cleanedPriceText}`, element.innerHTML);
                                    return;
                                }

                                const productUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                const imageUrl = imageUrlRaw.startsWith('/') ? storeModule.baseUrl + imageUrlRaw : imageUrlRaw;

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl,
                                    imageUrl: imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: null,
                                    discountPercent: null,
                                    discountAmount: null,
                                    currency: 'RUB',
                                    isAvailable: true
                                };

                                items.push(data);

                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга HTML элемента KeysForGamers', e);
                            }
                        });
                        return items;
                    }
                }, // --- Конец модуля KeysForGamers ---

                { // --- Модуль Zaka-zaka ---
                    id: 'zakazaka',
                    name: 'Zaka-zaka',
                    baseUrl: 'https://zaka-zaka.com',
                    searchUrlTemplate: 'https://zaka-zaka.com/search/ask/{query}/sort/price.asc',
                    isEnabled: true,
                    fetch: async function(query) {
                        const searchUrl = this.searchUrlTemplate.replace('{query}', encodeURIComponent(query));
                        return new Promise((resolve, reject) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: searchUrl,
                                timeout: SM_REQUEST_TIMEOUT_MS,
                                onload: (response) => {
                                    if (response.status >= 200 && response.status < 400) {
                                        resolve(this.parseHtml(response.responseText, this));
                                    } else {
                                        reject(new Error(`HTTP статус ${response.status}`));
                                    }
                                },
                                onerror: (error) => reject(new Error('Сетевая ошибка')),
                                ontimeout: () => reject(new Error('Таймаут запроса'))
                            });
                        });
                    },
                    parseHtml: function(htmlString, storeModule) {
                        const results = [];
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(htmlString, 'text/html');
                        const items = doc.querySelectorAll('.search-results .game-block');

                        items.forEach(item => {
                            try {
                                const linkElement = item;
                                const imageDiv = item.querySelector('.game-block-image');
                                const nameElement = item.querySelector('.game-block-name');
                                const priceElement = item.querySelector('.game-block-price');
                                const discountElement = item.querySelector('.game-block-discount');
                                const discountAmountElement = item.querySelector('.game-block-discount-sum');

                                const productName = nameElement?.textContent?.trim();
                                const productUrlRaw = linkElement?.getAttribute('href');
                                const currentPrice = priceElement ? sm_parsePrice(priceElement.textContent) : null;
                                const discountPercent = discountElement ? sm_parsePercent(discountElement.textContent) : 0;
                                const discountAmount = discountAmountElement ? Math.abs(sm_parsePrice(discountAmountElement.textContent) ?? 0) : null;

                                let imageUrl = null;
                                if (imageDiv?.style?.backgroundImage) {
                                    const match = imageDiv.style.backgroundImage.match(/url\("?(.+?)"?\)/);
                                    if (match && match[1]) {
                                        imageUrl = match[1].startsWith('/') ? storeModule.baseUrl + match[1] : match[1];
                                    }
                                }

                                if (!productName || !productUrlRaw || currentPrice === null) {
                                    return;
                                }

                                const fullOriginalUrl = productUrlRaw.startsWith('/') ? storeModule.baseUrl + productUrlRaw : productUrlRaw;
                                const referralPrefix = 'https://bednari.com/g/momptkjep9c1442ace4b02770293ab/?erid=2bL9aMPo2e49hMef4pgUXYbxvv&ulp=';
                                const productUrl = referralPrefix + encodeURIComponent(fullOriginalUrl);

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl,
                                    imageUrl: imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: null,
                                    discountPercent: discountPercent,
                                    discountAmount: discountAmount,
                                    currency: 'RUB',
                                    isAvailable: true
                                };
                                results.push(sm_calculateMissingValues(data));
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента', e);
                            }
                        });
                        return results;
                    }
                }, // --- Конец модуля Zaka-zaka ---

                { // --- Модуль Buka ---
                    id: 'buka',
                    name: 'Buka',
                    baseUrl: 'https://shop.buka.ru',
                    apiUrl: 'https://shop.buka.ru/api/f/v2/search/get-page',
                    isEnabled: true,
                    fetch: async function(query) {
                        let allItems = [];
                        let pageIndex = 0;
                        let hasNext = true;
                        const storeModule = this;

                        async function fetchBukaPage(currentIndex) {
                            const requestPayload = {
                                pageIndex: currentIndex,
                                filter: {
                                    term: query,
                                    area_id: 100001,
                                    channel: "WEB"
                                }
                            };
                            const requestHeaders = {
                                'Accept': '*/*',
                                'Content-Type': 'application/json'
                            };

                            try {
                                const response = await new Promise((resolve, reject) => {
                                    GM_xmlhttpRequest({
                                        method: "POST",
                                        url: storeModule.apiUrl,
                                        headers: requestHeaders,
                                        data: JSON.stringify(requestPayload),
                                        responseType: 'json',
                                        timeout: SM_REQUEST_TIMEOUT_MS,
                                        onload: resolve,
                                        onerror: reject,
                                        ontimeout: () => reject(new Error(`Таймаут запроса (pageIndex: ${currentIndex})`)),
                                    });
                                });

                                if (response.status >= 200 && response.status < 400 && response.response) {
                                    const data = response.response;
                                    const pageInfo = data.page;

                                    if (pageInfo && Array.isArray(pageInfo.rows)) {
                                        const processedItems = pageInfo.rows
                                            .map(item => storeModule.parseApiItem(item, storeModule))
                                            .filter(item => item !== null);

                                        allItems = allItems.concat(processedItems);
                                    }

                                    hasNext = pageInfo?.hasNext ?? false;
                                    if (hasNext) {
                                        await fetchBukaPage(currentIndex + 1);
                                    }

                                } else {
                                    throw new Error(`HTTP статус ${response.status} (pageIndex: ${currentIndex})`);
                                }
                            } catch (error) {
                                sm_logError(storeModule.name, `Ошибка загрузки страницы ${currentIndex}: ${error.message}`, error);
                                hasNext = false;
                            }
                        }

                        await fetchBukaPage(pageIndex);

                        return allItems;
                    },

                    parseApiItem: function(item, storeModule) {
                        try {
                            // --- Фильтрация ---
                            // 1. Проверяем тип (нужен цифровой, обычно type: 3)
                            if (item.type !== 3) return null;

                            // 2. Проверяем платформу (нужен PC)
                            const platformFilter = item.filters?.find(f => f.field === 'platform');
                            const isPC = platformFilter?.values?.some(v => v.title === 'PC');
                            if (!isPC) return null;

                            // 3. Проверяем статус продажи (доступен или предзаказ)
                            const saleState = item.saleState;
                            if (saleState !== 'available' && saleState !== 'pre-order') {
                                return null;
                            }

                            const productName = item.title?.trim();
                            const productUrlRaw = item.alias ? `/item/${item.alias}` : null;
                            const imageUrl = item.img;

                            const currentPrice = item.price?.actual ? sm_parsePrice(item.price.actual) : null;
                            const originalPrice = item.price?.old ? sm_parsePrice(item.price.old) : (currentPrice !== null ? currentPrice : null);
                            const discountPercent = item.price?.discount ? parseFloat(item.price.discount) : 0;

                            if (!productName || !productUrlRaw || !imageUrl || currentPrice === null) {
                                sm_logError(storeModule.name, 'Недостаточно данных в API ответе для элемента', item);
                                return null;
                            }

                            const fullProductUrl = storeModule.baseUrl + productUrlRaw;
                            const productUrlWithRef = fullProductUrl + '?ref=zoneofgames';

                            let data = {
                                storeId: storeModule.id,
                                storeName: storeModule.name,
                                storeUrl: storeModule.baseUrl,
                                productName: productName,
                                productUrl: productUrlWithRef,
                                imageUrl: imageUrl,
                                currentPrice: currentPrice,
                                originalPrice: originalPrice === currentPrice ? null : originalPrice,
                                discountPercent: discountPercent > 0 ? discountPercent : null,
                                discountAmount: null,
                                currency: 'RUB',
                                isAvailable: true
                            };

                            return sm_calculateMissingValues(data);

                        } catch (e) {
                            sm_logError(storeModule.name, 'Ошибка парсинга элемента API Buka', e);
                            return null;
                        }
                    }
                },

                { // --- Модуль GGSEL ---
                    id: 'ggsel',
                    name: 'GGSEL',
                    baseUrl: 'https://ggsel.net',
                    apiUrl: 'https://api4.ggsel.com/elastic/goods/query',
                    isEnabled: true,
                    fetch: async function(query) {
                        let allItems = [];
                        let searchAfter = [];
                        const limit = 60;
                        let hasMore = true;
                        let fetchedCount = 0;
                        const maxFetches = 5;
                        let fetchAttempts = 0;
                        const storeModule = this;

                        async function fetchGGSELPage(currentIndex) {
                            fetchAttempts++;
                            const requestPayload = {
                                search_term: query,
                                limit: limit,
                                search_after: searchAfter,
                                is_preorders: false,
                                with_filters: true,
                                with_categories: false,
                                sort: "sortByPriceUp",
                                content_type_ids: [48, 2],
                                with_forbidden: false,
                                min_price: "",
                                max_price: "",
                                currency: "wmr",
                                lang: "ru",
                                platforms: ["Steam"]
                            };
                            const requestHeaders = {
                                'Accept': 'application/json, text/plain, */*',
                                'Content-Type': 'application/json'
                            };

                            try {
                                const response = await new Promise((resolve, reject) => {
                                    GM_xmlhttpRequest({
                                        method: "POST",
                                        url: storeModule.apiUrl,
                                        headers: requestHeaders,
                                        data: JSON.stringify(requestPayload),
                                        responseType: 'json',
                                        timeout: SM_REQUEST_TIMEOUT_MS,
                                        onload: resolve,
                                        onerror: reject,
                                        ontimeout: () => reject(new Error(`Таймаут запроса (pageIndex: ${currentIndex})`)),
                                    });
                                });

                                if (response.status >= 200 && response.status < 400 && response.response?.data) {
                                    const data = response.response.data;
                                    if (data.items && Array.isArray(data.items)) {
                                        const processedItems = data.items
                                            .map(item => storeModule.parseApiItem(item, storeModule))
                                            .filter(item => item !== null);

                                        allItems = allItems.concat(processedItems);
                                        fetchedCount += data.items.length;

                                        if (data.items.length < limit || !data.last_sort || fetchedCount >= (data.total ?? fetchedCount)) {
                                            hasMore = false;
                                        } else {
                                            searchAfter = data.last_sort;
                                        }
                                    } else {
                                        hasMore = false;
                                    }
                                } else {
                                    throw new Error(`HTTP статус ${response.status} (pageIndex: ${currentIndex})`);
                                }
                            } catch (error) {
                                sm_logError(storeModule.name, `Ошибка загрузки страницы ${currentIndex}: ${error.message}`, error);
                                hasMore = false;
                            }

                            if (hasMore && fetchAttempts < maxFetches) {
                                 await new Promise(res => setTimeout(res, 150));
                                 await fetchGGSELPage(currentIndex + 1);
                             }
                        }

                        await fetchGGSELPage(0);

                        if (fetchAttempts >= maxFetches && hasMore) {
                             sm_logError(storeModule.name, `Достигнут лимит запросов пагинации (${maxFetches}). Возможно, показаны не все результаты.`);
                        }

                        return allItems;
                    },

                    parseApiItem: function(item, storeModule) {
                        try {
                            if (item.forbidden_type !== 0 || item.hidden_from_search || item.hidden_from_parents) {
                                return null;
                            }
                            if (item.content_type_id !== 48 && item.content_type_id !== 2) {
                                return null;
                            }

                            const productName = item.name?.trim();
                            const productUrlRaw = `${storeModule.baseUrl}/catalog/product/${item.id_goods}`;
                            const productUrl = `${productUrlRaw}?ai=234029`;

                            const imageUrl = item.images ? `https://img.ggsel.ru/${item.id_goods}/original/250x250/${item.images}` : null;

                            const currentPrice = item.price_wmr ? sm_parsePrice(item.price_wmr) : null;
                            const potentialOriginalPrice = item.category_discount ? sm_parsePrice(item.category_discount) : null;
                            const originalPrice = (potentialOriginalPrice && currentPrice !== null && potentialOriginalPrice > currentPrice) ? potentialOriginalPrice : null;

                            const sellerId = item.id_seller;
                            const sellerName = item.seller_name;

                            if (!productName || currentPrice === null || !imageUrl) {
                                sm_logError(storeModule.name, 'Недостаточно данных в элементе API GGSEL (после проверок)', item);
                                return null;
                            }

                            let data = {
                                storeId: storeModule.id,
                                storeName: storeModule.name,
                                storeUrl: storeModule.baseUrl,
                                productName: productName,
                                productUrl: productUrl,
                                imageUrl: imageUrl,
                                currentPrice: currentPrice,
                                originalPrice: originalPrice,
                                discountPercent: null,
                                discountAmount: null,
                                currency: 'RUB',
                                isAvailable: true,
                                sellerId: sellerId,
                                sellerName: sellerName
                            };

                            return sm_calculateMissingValues(data);

                        } catch (e) {
                            sm_logError(storeModule.name, 'Ошибка парсинга элемента API GGSEL', e);
                            return null;
                        }
                    }
                }, // --- Конец модуля GGSEL ---

                { // --- Модуль Plati.Market ---
                    id: 'platimarket',
                    name: 'Plati.Market',
                    baseUrl: 'https://plati.market',
                    apiUrlBase: 'https://api.digiseller.com/api/products/search2',
                    isEnabled: true,
                    fetch: async function(query) {
                        const MAX_RESULTS_PER_REQUEST = 500;

                        // --- Шаг 1: Узнаем общее количество товаров ---
                        const initialUrl = `${this.apiUrlBase}?query=${encodeURIComponent(query)}&searchmode=10&sortmode=2&pagesize=1`;
                        let totalItems = 0;

                        try {
                            const initialResponse = await new Promise((resolve, reject) => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: initialUrl,
                                    responseType: 'json',
                                    timeout: SM_REQUEST_TIMEOUT_MS,
                                    onload: (response) => {
                                        if (response.status >= 200 && response.status < 400 && response.response?.result?.total !== undefined) {
                                            resolve(response.response);
                                        } else {
                                            sm_logError(this.name, `Не удалось получить total_pages. Status: ${response.status}`, response);
                                            reject(new Error(`API Error: Status ${response.status}`));
                                        }
                                    },
                                    onerror: (error) => reject(new Error('Сетевая ошибка (initial request)')),
                                    ontimeout: () => reject(new Error('Таймаут запроса (initial request)'))
                                });
                            });
                            totalItems = parseInt(initialResponse.result.total, 10);
                        } catch (error) {
                            sm_logError(this.name, 'Ошибка на шаге 1 (получение total)', error);
                            return [];
                        }

                        if (totalItems === 0) {
                            return [];
                        }

                        // --- Шаг 2: Запрашиваем все (или до MAX_RESULTS_PER_REQUEST) товары ---
                        const resultsToFetch = Math.min(totalItems, MAX_RESULTS_PER_REQUEST);
                        if (resultsToFetch <= 0) return [];

                        const finalUrl = `${this.apiUrlBase}?query=${encodeURIComponent(query)}&searchmode=10&sortmode=2&pagesize=${resultsToFetch}`;

                        try {
                            const finalResponse = await new Promise((resolve, reject) => {
                                GM_xmlhttpRequest({
                                    method: "GET",
                                    url: finalUrl,
                                    responseType: 'json',
                                    timeout: SM_REQUEST_TIMEOUT_MS * 2,
                                    onload: (response) => {
                                        if (response.status >= 200 && response.status < 400 && response.response?.items?.item) {
                                            resolve(response.response);
                                        } else {
                                            sm_logError(this.name, `Не удалось получить items. Status: ${response.status}`, response);
                                            reject(new Error(`API Error: Status ${response.status}`));
                                        }
                                    },
                                    onerror: (error) => reject(new Error('Сетевая ошибка (final request)')),
                                    ontimeout: () => reject(new Error('Таймаут запроса (final request)'))
                                });
                            });

                            return this.parseApiResponse(finalResponse.items.item, this);

                        } catch (error) {
                            sm_logError(this.name, 'Ошибка на шаге 2 (получение items)', error);
                            return [];
                        }
                    },
                    parseApiResponse: function(items, storeModule) {
                        const results = [];
                        if (!Array.isArray(items)) {
                            sm_logError(storeModule.name, 'Ответ API не содержит массив items', items);
                            return results;
                        }

                        items.forEach(item => {
                            try {
                                const productName = item.name;
                                const productUrlRaw = item.url;
                                const currentPrice = sm_parsePrice(item.price_rur);
                                const currency = 'RUB';
                                const sellerId = item.seller_id;
                                const sellerName = item.seller_name;

                                if (!productName || !productUrlRaw || currentPrice === null) {
                                    return;
                                }

                                const productUrl = productUrlRaw + '?ai=234029';

                                const imageUrl = `https://graph.digiseller.ru/img.ashx?id_d=${item.id}&w=150&h=80`;

                                let data = {
                                    storeId: storeModule.id,
                                    storeName: storeModule.name,
                                    storeUrl: storeModule.baseUrl,
                                    productName: productName,
                                    productUrl: productUrl,
                                    imageUrl: imageUrl,
                                    currentPrice: currentPrice,
                                    originalPrice: currentPrice,
                                    discountPercent: 0,
                                    discountAmount: 0,
                                    currency: currency,
                                    isAvailable: true,
                                    sellerId: sellerId,
                                    sellerName: sellerName
                                };
                                results.push(sm_calculateMissingValues(data));
                            } catch (e) {
                                sm_logError(storeModule.name, 'Ошибка парсинга элемента API', e);
                            }
                        });
                        return results;
                    }
                } // --- Конец модуля Plati.Market ---


                // --- Сюда другие модули ---
            ];

            // --- Инициализация модуля SalesMaster ---
            sm_addStyles();
            const steamAppIdCheckSM = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
            if (steamAppIdCheckSM && steamAppIdCheckSM[1]) {
                setTimeout(sm_addSalesMasterButton, 500);
                sm_currentFilters = GM_getValue(SM_FILTER_STORAGE_KEY, {
                    priceMin: '',
                    priceMax: '',
                    discountPercentMin: '',
                    discountPercentMax: '',
                    discountAmountMin: '',
                    discountAmountMax: '',
                    hasDiscount: false,
                    stores: Object.fromEntries(sm_storeModules.map(s => [s.id, true]))
                });
                sm_storeModules.forEach(store => {
                    if (!(store.id in sm_currentFilters.stores)) {
                        sm_currentFilters.stores[store.id] = true;
                    }
                });

            }

        })();
    }

    // Скрипт для страницы игры (Plati; отображение цен с Plati.Market) | https://store.steampowered.com/app/*
    if (scriptsConfig.platiSales && unsafeWindow.location.pathname.includes('/app/')) {
        (function() {
            'use strict';

            // --- Конфигурация PlatiSearch (PS) ---
            const PS_API_BASE_URL = 'https://api.digiseller.com/api/products/search2';
            const PS_SUGGEST_API_URL = 'https://plati.market/api/suggest.ashx';
            const PS_IMAGE_DOMAIN = 'digiseller.mycdn.ink';
            const PS_RESULTS_PER_PAGE_CHECK = 1;
            const PS_DEFAULT_SORT_MODE = 2;
            const PS_SUGGEST_DEBOUNCE_MS = 300;
            const PS_FILTER_DEBOUNCE_MS = 500;
            const PS_FILTER_STORAGE_PREFIX = 'platiSalesFilter_v1_';
            const PS_EXCLUSION_STORAGE_KEY = 'platiSalesExclusions_v1_';
            const PS_LAST_SORT_STORAGE_KEY = 'platiSalesLastSort_v1_';
            const PS_CURRENCY_STORAGE_KEY = 'platiSalesCurrency_v1_';
            const PS_FILTER_PANEL_WIDTH = 230;
            const PS_EXCLUSION_PANEL_WIDTH = 250;
            const PS_SIDE_PANEL_HORIZONTAL_PADDING = 20;
            const PS_CONTENT_PADDING_BUFFER = 15;
            const PS_CONTENT_PADDING_LEFT = PS_FILTER_PANEL_WIDTH + PS_SIDE_PANEL_HORIZONTAL_PADDING + PS_CONTENT_PADDING_BUFFER;
            const PS_CONTENT_PADDING_RIGHT = PS_EXCLUSION_PANEL_WIDTH + PS_SIDE_PANEL_HORIZONTAL_PADDING + PS_CONTENT_PADDING_BUFFER;
            const PS_HEADER_APPROX_HEIGHT = 65;
            const PS_TOP_OFFSET_FOR_SIDE_PANELS = PS_HEADER_APPROX_HEIGHT + 25;
            const PS_BOTTOM_OFFSET_FOR_SIDE_PANELS = 20;
            const PS_ADV_SORT_CONTAINER_WIDTH = 230;
            const NEW_ITEM_THRESHOLD_DAYS = 7;

            // --- Глобальные переменные ---
            let ps_currentResults = [];
            let ps_currentSort = GM_getValue(PS_LAST_SORT_STORAGE_KEY, { field: 'relevance', direction: 'asc' });
            let ps_currentCurrency = GM_getValue(PS_CURRENCY_STORAGE_KEY, 'RUR');
            let ps_firstSortClick = {};
            ['price', 'sales', 'relevance', 'name', 'date_create', 'discount', 'seller_rating', 'review_ratio', 'good_reviews', 'bad_reviews', 'returns'].forEach(field => {
                ps_firstSortClick[field] = ps_currentSort.field !== field;
            });
            let ps_exclusionKeywords = GM_getValue(PS_EXCLUSION_STORAGE_KEY, []);
            let ps_currentFilters = ps_loadFilters();
            let ps_suggestDebounceTimeout;
            let ps_filterDebounceTimeout;
            let ps_advSortMenuTimeout;

            // --- DOM Элементы ---
            let ps_modal, ps_closeBtn, ps_searchInput, ps_searchBtn, ps_sortPriceBtn, ps_sortSalesBtn, ps_advSortBtnContainer, ps_advSortBtn, ps_advSortMenu, ps_currencySelect, ps_resetSortBtn;
            let ps_resultsContainer, ps_resultsDiv, ps_statusDiv, ps_excludeInput, ps_addExcludeBtn, ps_exclusionTagsDiv;
            let ps_suggestionsDiv;
            let ps_filtersPanel;
            let ps_filterPriceMin, ps_filterPriceMax, ps_filterSalesMin, ps_filterSalesMax, ps_filterRatingMin, ps_filterRatingMax;
            let ps_filterHideBadReviews, ps_filterHideReturns, ps_filterOnlyDiscount;
            let ps_filterDateSelect;
            let ps_resetAllFiltersBtn;
            let ps_exclusionTagsListDiv;

            // --- Описания сортировок ---
             const ps_advancedSorts = {
                 'price':        { name: 'По цене',          defaultDir: 'asc' },
                 'sales':        { name: 'По продажам',      defaultDir: 'desc'},
                 'relevance':    { name: 'По релевантности', defaultDir: 'asc' },
                 'name':         { name: 'По названию',      defaultDir: 'asc'  },
                 'date_create':  { name: 'По дате добавления', defaultDir: 'desc' },
                 'discount':     { name: 'По % в скид. системе', defaultDir: 'desc' },
                 'seller_rating':{ name: 'По рейтингу продавца', defaultDir: 'desc' },
                 'review_ratio': { name: 'По соотношению отзывов', defaultDir: 'desc' },
                 'good_reviews': { name: 'По кол-ву хор. отзывов', defaultDir: 'desc' },
                 'bad_reviews':  { name: 'По кол-ву плох. отзывов', defaultDir: 'asc'  },
                 'returns':      { name: 'По кол-ву возвратов', defaultDir: 'asc'  }
            };
            const ps_advSortOrder = ['name', 'date_create', 'discount', 'seller_rating', 'review_ratio', 'good_reviews', 'bad_reviews', 'returns'];
            const ps_dateFilterOptions = {
                 'all': 'За все время', '1d': 'За сутки', '2d': 'За 2 дня', '1w': 'За неделю', '1m': 'За месяц', '6m': 'За полгода', '1y': 'За год', '5y': 'За 5 лет', '10y': 'За 10 лет',
            };

            // --- Вспомогательные функции ---
            function formatPrice(priceStr) {
                if (!priceStr) return 0;
                return parseFloat(String(priceStr).replace(/[^\d,.]/g, '').replace(',', '.')) || 0;
            }
            function formatSales(salesStr) {
                if (!salesStr) return 0;
                return parseInt(String(salesStr).replace(/\D/g, ''), 10) || 0;
            }
             function parseSellerRating(ratingStr) {
                 if (!ratingStr) return 0;
                 return parseFloat(String(ratingStr).replace(',', '.')) || 0;
             }
             function calculateReviewRatio(item) {
                 const good = parseInt(item.cnt_good_responses || '0', 10);
                 const bad = parseInt(item.cnt_bad_responses || '0', 10);
                 const total = good + bad;
                 return total > 0 ? (good / total) : -1;
             }
             function parseDate(dateStr) {
                 if (!dateStr) return 0;
                 const parts = dateStr.split(' ');
                 if (parts.length !== 2) return 0;
                 const dateParts = parts[0].split('.');
                 const timeParts = parts[1].split(':');
                 if (dateParts.length !== 3 || timeParts.length !== 3) return 0;
                 try { return new Date(Date.UTC(dateParts[2], dateParts[1] - 1, dateParts[0], timeParts[0], timeParts[1], timeParts[2])).getTime(); }
                 catch (e) { return 0; }
             }
            function formatDateString(timestamp) {
                if (!timestamp || timestamp === 0) return 'N/A';
                try {
                    const date = new Date(timestamp);
                    const day = String(date.getUTCDate()).padStart(2, '0');
                    const month = String(date.getUTCMonth() + 1).padStart(2, '0');
                    const year = String(date.getUTCFullYear()).slice(-2);
                    return `${day}.${month}.${year}`;
                } catch (e) { return 'N/A'; }
            }
             function getPriceInSelectedCurrency(item, currency) {
                 let price = 0;
                 switch (currency) {
                     case 'USD': price = formatPrice(item.price_usd); break;
                     case 'EUR': price = formatPrice(item.price_eur); break;
                     case 'UAH': price = formatPrice(item.price_uah); break;
                     case 'RUR': default: price = formatPrice(item.price_rur); break;
                 }
                 if (price <= 0 && currency !== 'RUR') price = formatPrice(item.price_rur);
                 if (price <= 0 && currency !== 'USD') price = formatPrice(item.price_usd);
                 if (price <= 0 && currency !== 'EUR') price = formatPrice(item.price_eur);
                 return price > 0 ? price : Infinity;
             }
            function debounce(func, wait) {
                let timeout;
                return function executedFunction(...args) {
                    const later = () => { clearTimeout(timeout); func(...args); };
                    clearTimeout(timeout);
                    timeout = setTimeout(later, wait);
                };
            }
            function getSteamGameName() {
                 const appNameElement = document.querySelector('#appHubAppName');
                 return appNameElement ? appNameElement.textContent.trim() : '';
            }

            // --- Создание UI ---
            function createPlatiModal() {
                 const existingModal = document.querySelector('#platiSearchModal');
                 if (existingModal) existingModal.remove();

                 ps_modal = document.createElement('div');
                 ps_modal.id = 'platiSearchModal';

                 const container = document.createElement('div');
                 container.id = 'platiSearchContainer';

                 const header = document.createElement('div');
                 header.id = 'platiSearchHeader';

                 const searchInputContainer = document.createElement('div');
                 searchInputContainer.className = 'platiSearchInputContainer';
                 ps_searchInput = document.createElement('input');
                 ps_searchInput.id = 'platiSearchInput';
                 ps_searchInput.type = 'text';
                 ps_searchInput.placeholder = 'Введите название игры или товара...';
                 ps_searchInput.autocomplete = 'off';
                 ps_searchInput.onkeydown = (e) => { if (e.key === 'Enter') ps_triggerSearch(); };
                 ps_searchInput.oninput = () => {
                     clearTimeout(ps_suggestDebounceTimeout);
                     ps_suggestDebounceTimeout = setTimeout(() => ps_fetchSuggestions(ps_searchInput.value), PS_SUGGEST_DEBOUNCE_MS);
                 };
                 ps_searchInput.onblur = () => { setTimeout(() => { if (ps_suggestionsDiv) ps_suggestionsDiv.style.display = 'none'; }, 150); };

                 ps_suggestionsDiv = document.createElement('div');
                 ps_suggestionsDiv.id = 'platiSearchSuggestions';
                 searchInputContainer.appendChild(ps_searchInput);
                 searchInputContainer.appendChild(ps_suggestionsDiv);
                 header.appendChild(searchInputContainer);

                 ps_searchBtn = document.createElement('button');
                 ps_searchBtn.textContent = 'Найти';
                 ps_searchBtn.id = 'platiSearchGoBtn';
                 ps_searchBtn.className = 'platiSearchBtn';
                 ps_searchBtn.onclick = ps_triggerSearch;
                 header.appendChild(ps_searchBtn);

                 ps_resetSortBtn = document.createElement('button');
                 ps_resetSortBtn.id = 'platiResetSortBtn';
                 ps_resetSortBtn.className = 'platiSearchBtn';
                 ps_resetSortBtn.title = 'Сбросить сортировку (Релевантность)';
                 ps_resetSortBtn.innerHTML = `<svg viewBox="0 0 24 24"><path fill="currentColor" d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6s-2.69 6-6 6s-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8s-3.58-8-8-8Z"/></svg>`;
                 ps_resetSortBtn.onclick = () => ps_resetSort(true);
                 header.appendChild(ps_resetSortBtn);

                 ps_sortPriceBtn = document.createElement('button');
                 ps_sortPriceBtn.className = 'platiSearchBtn sortBtn';
                 ps_sortPriceBtn.dataset.sort = 'price';
                 ps_sortPriceBtn.onclick = () => ps_handleSort('price');
                 header.appendChild(ps_sortPriceBtn);

                 ps_sortSalesBtn = document.createElement('button');
                 ps_sortSalesBtn.className = 'platiSearchBtn sortBtn';
                 ps_sortSalesBtn.dataset.sort = 'sales';
                 ps_sortSalesBtn.onclick = () => ps_handleSort('sales');
                 header.appendChild(ps_sortSalesBtn);

                 ps_advSortBtnContainer = document.createElement('div');
                 ps_advSortBtnContainer.id = 'platiSearchAdvSortBtnContainer';
                 ps_advSortBtn = document.createElement('button');
                 ps_advSortBtn.id = 'platiSearchAdvSortBtn';
                 ps_advSortBtn.className = 'platiSearchBtn sortBtn';
                 ps_advSortBtnContainer.appendChild(ps_advSortBtn);
                 ps_advSortMenu = document.createElement('div');
                 ps_advSortMenu.id = 'platiSearchAdvSortMenu';
                 ps_advSortOrder.forEach(key => {
                     const sortInfo = ps_advancedSorts[key];
                     const menuItem = document.createElement('div');
                     menuItem.className = 'platiSearchSortMenuItem';
                     menuItem.dataset.sort = key;
                     menuItem.innerHTML = `${sortInfo.name} <span class="sortArrow"></span>`;
                     menuItem.onclick = () => ps_handleSort(key);
                     ps_advSortMenu.appendChild(menuItem);
                 });
                 ps_advSortBtnContainer.appendChild(ps_advSortMenu);
                 header.appendChild(ps_advSortBtnContainer);

                 ps_currencySelect = document.createElement('select');
                 ps_currencySelect.id = 'platiSearchCurrencySelect';
                 ['RUR', 'USD', 'EUR', 'UAH'].forEach(curr => {
                     const option = document.createElement('option');
                     option.value = curr; option.textContent = curr;
                     if (curr === ps_currentCurrency) option.selected = true;
                     ps_currencySelect.appendChild(option);
                 });
                 ps_currencySelect.onchange = ps_handleCurrencyChange;
                 header.appendChild(ps_currencySelect);

                 container.appendChild(header);

                 ps_resultsContainer = document.createElement('div');
                 ps_resultsContainer.id = 'platiSearchResultsContainer';
                 ps_statusDiv = document.createElement('div');
                 ps_statusDiv.id = 'platiSearchResultsStatus';
                 ps_resultsDiv = document.createElement('div');
                 ps_resultsDiv.id = 'platiSearchResults';
                 ps_resultsContainer.appendChild(ps_statusDiv);
                 ps_resultsContainer.appendChild(ps_resultsDiv);
                 container.appendChild(ps_resultsContainer);
                 ps_modal.appendChild(container);

                 ps_filtersPanel = document.createElement('div');
                 ps_filtersPanel.id = 'platiSearchFiltersPanel';
                 ps_filtersPanel.innerHTML = `
                    <div class="filterGroup"> <h4>Цена (${ps_currentCurrency}) ${ps_createResetButtonHTML('price')}</h4> <div class="filterRangeInputs"> <input type="number" id="psFilterPriceMin" placeholder="от" min="0"> <input type="number" id="psFilterPriceMax" placeholder="до" min="0"> </div> </div>
                    <div class="filterGroup"> <h4>Продажи ${ps_createResetButtonHTML('sales')}</h4> <div class="filterRangeInputs"> <input type="number" id="psFilterSalesMin" placeholder="от" min="0"> <input type="number" id="psFilterSalesMax" placeholder="до" min="0"> </div> </div>
                    <div class="filterGroup"> <h4>Рейтинг продавца ${ps_createResetButtonHTML('rating')}</h4> <div class="filterRangeInputs"> <input type="number" id="psFilterRatingMin" placeholder="от" step="0.1" min="0"> <input type="number" id="psFilterRatingMax" placeholder="до" step="0.1" min="0"> </div> </div>
                    <div class="filterGroup"> <h4>Опции ${ps_createResetButtonHTML('options')}</h4> <div class="filterCheckbox"> <label><input type="checkbox" id="psFilterHideBadReviews"> Скрыть с плох. отзывами</label> </div> <div class="filterCheckbox"> <label><input type="checkbox" id="psFilterHideReturns"> Скрыть с возвратами</label> </div> <div class="filterCheckbox"> <label><input type="checkbox" id="psFilterOnlyDiscount"> Участие в скидках</label> </div> </div>
                    <div class="filterGroup"> <h4>Дата добавления ${ps_createResetButtonHTML('date')}</h4> <div class="filterSelect"> <select id="psFilterDateSelect"> ${Object.entries(ps_dateFilterOptions).map(([key, text]) => `<option value="${key}">${text}</option>`).join('')} </select> </div> </div>
                    <button id="psResetAllFiltersBtn" class="platiSearchBtn">Сбросить все фильтры</button>
                 `;
                 ps_modal.appendChild(ps_filtersPanel);

                 ps_exclusionTagsDiv = document.createElement('div');
                 ps_exclusionTagsDiv.id = 'platiSearchExclusionTags';
                 const exclusionInputGroup = document.createElement('div');
                 exclusionInputGroup.className = 'exclusionInputGroup';
                 ps_excludeInput = document.createElement('input');
                 ps_excludeInput.type = 'text';
                 ps_excludeInput.id = 'platiSearchExcludeInput';
                 ps_excludeInput.placeholder = 'Исключить слово';
                 ps_excludeInput.onkeydown = (e) => { if (e.key === 'Enter') ps_addFilterKeyword(); };
                 ps_addExcludeBtn = document.createElement('button');
                 ps_addExcludeBtn.id = 'platiSearchAddExcludeBtn';
                 ps_addExcludeBtn.innerHTML = `<svg viewBox="0 0 20 20"><path d="M10 2.5a.75.75 0 0 1 .75.75v6h6a.75.75 0 0 1 0 1.5h-6v6a.75.75 0 0 1-1.5 0v-6h-6a.75.75 0 0 1 0-1.5h6v-6a.75.75 0 0 1 .75-.75Z" /></svg>`;
                 ps_addExcludeBtn.onclick = ps_addFilterKeyword;
                 exclusionInputGroup.appendChild(ps_excludeInput);
                 exclusionInputGroup.appendChild(ps_addExcludeBtn);
                 ps_exclusionTagsDiv.appendChild(exclusionInputGroup);
                 ps_exclusionTagsListDiv = document.createElement('div');
                 ps_exclusionTagsListDiv.id = 'platiExclusionTagsList';
                 ps_exclusionTagsDiv.appendChild(ps_exclusionTagsListDiv);
                 ps_modal.appendChild(ps_exclusionTagsDiv);

                 ps_closeBtn = document.createElement('button');
                 ps_closeBtn.id = 'platiSearchCloseBtn';
                 ps_closeBtn.innerHTML = '&times;';
                 ps_closeBtn.onclick = hidePlatiModal;
                 ps_modal.appendChild(ps_closeBtn);

                 document.body.appendChild(ps_modal);

                 // Назначение переменных элементам UI
                 ps_filterPriceMin = document.getElementById('psFilterPriceMin');
                 ps_filterPriceMax = document.getElementById('psFilterPriceMax');
                 ps_filterSalesMin = document.getElementById('psFilterSalesMin');
                 ps_filterSalesMax = document.getElementById('psFilterSalesMax');
                 ps_filterRatingMin = document.getElementById('psFilterRatingMin');
                 ps_filterRatingMax = document.getElementById('psFilterRatingMax');
                 ps_filterHideBadReviews = document.getElementById('psFilterHideBadReviews');
                 ps_filterHideReturns = document.getElementById('psFilterHideReturns');
                 ps_filterOnlyDiscount = document.getElementById('psFilterOnlyDiscount');
                 ps_filterDateSelect = document.getElementById('psFilterDateSelect');
                 ps_resetAllFiltersBtn = document.getElementById('psResetAllFiltersBtn');

                 ps_addFilterEventListeners();
                 applyLoadedFiltersToUI();
                 ps_updateSortButtonsState();

                 function handleEsc(event) { if (event.key === 'Escape') hidePlatiModal(); }
                 document.addEventListener('keydown', handleEsc);
                 ps_modal._escHandler = handleEsc;
            }

            function ps_createResetButtonHTML(filterKey) {
                 return `<button class="filterResetBtn" title="Сбросить фильтр" data-filter-key="${filterKey}"><svg viewBox="0 0 24 24"><path d="M13 3a9 9 0 0 0-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.954 8.954 0 0 0 13 21a9 9 0 0 0 0-18zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"></path></svg></button>`;
            }

            // --- Управление модальным окном ---
            function showPlatiModal() {
                 if (!ps_modal) createPlatiModal();
                 const gameName = getSteamGameName();
                 if (gameName && !ps_searchInput.value) { ps_searchInput.value = gameName; }

                 document.body.style.overflow = 'hidden';
                 ps_modal.style.display = 'block';
                 ps_modal.scrollTop = 0;

                 ps_renderExclusionTags();
                 applyLoadedFiltersToUI();
                 ps_updateFilterPlaceholders();
                 ps_updateSortButtonsState();

                 requestAnimationFrame(() => {
                    const header = document.getElementById('platiSearchHeader');
                    const headerRect = header ? header.getBoundingClientRect() : { bottom: PS_TOP_OFFSET_FOR_SIDE_PANELS };
                    const newTopOffset = headerRect.bottom + 5;
                    const availableHeight = `calc(100vh - ${newTopOffset}px - ${PS_BOTTOM_OFFSET_FOR_SIDE_PANELS}px)`;
                    if (ps_filtersPanel) { ps_filtersPanel.style.top = `${newTopOffset}px`; ps_filtersPanel.style.maxHeight = availableHeight;}
                    if (ps_exclusionTagsDiv) { ps_exclusionTagsDiv.style.top = `${newTopOffset}px`; ps_exclusionTagsDiv.style.maxHeight = availableHeight; }
                 });

                 if (ps_searchInput.value.trim()) { ps_triggerSearch(); }
                 else { ps_updateStatus('Введите запрос для поиска.'); }
            }
            function hidePlatiModal() {
                 if (ps_modal) {
                     ps_modal.style.display = 'none';
                     if (ps_suggestionsDiv) ps_suggestionsDiv.style.display = 'none';
                      if (ps_modal._escHandler) { document.removeEventListener('keydown', ps_modal._escHandler); delete ps_modal._escHandler; }
                 }
                 document.body.style.overflow = '';
            }

            // --- Обновление статуса ---
            function ps_updateStatus(message, isLoading = false) {
                if (ps_statusDiv) {
                    ps_statusDiv.innerHTML = message + (isLoading ? ' <span class="spinner"></span>' : '');
                    ps_statusDiv.style.display = 'block';
                    if(ps_currentResults.length === 0 && message && !isLoading) {
                        ps_resultsDiv.innerHTML = '';
                    }
                }
            }

            // --- Запуск поиска ---
            function ps_triggerSearch() {
                const query = ps_searchInput.value.trim();
                if (ps_suggestionsDiv) ps_suggestionsDiv.style.display = 'none';
                if (!query) {
                    ps_updateStatus('Пожалуйста, введите запрос.');
                    ps_currentResults = []; ps_renderResults(); return;
                }
                ps_currentResults = [];
                ps_resetSort(false);
                applyLoadedFiltersToUI();
                ps_renderResults();
                ps_updateStatus('Получение общего количества товаров...', true);
                ps_fetchTotalCount(query);
            }

            // --- Функции подсказок ---
            function ps_fetchSuggestions(query) {
                 const trimmedQuery = query.trim();
                 if (trimmedQuery.length < 2) {
                     if (ps_suggestionsDiv) { ps_suggestionsDiv.innerHTML = ''; ps_suggestionsDiv.style.display = 'none'; } return;
                 }
                 const params = new URLSearchParams({ q: trimmedQuery, v: 2 });
                 try { if (typeof plang !== 'undefined') params.append('lang', plang); if (typeof clientgeo !== 'undefined') params.append('geo', clientgeo); }
                 catch (e) { console.warn("PlatiSearch: Could not get plang/clientgeo for suggestions."); }

                 GM_xmlhttpRequest({
                     method: "GET", url: `${PS_SUGGEST_API_URL}?${params.toString()}`, timeout: 5000,
                     onload: function(response) {
                         try { ps_renderSuggestions(JSON.parse(response.responseText)); }
                         catch (e) { if (ps_suggestionsDiv) { ps_suggestionsDiv.innerHTML = ''; ps_suggestionsDiv.style.display = 'none'; } }
                     },
                     onerror: function(error) { if (ps_suggestionsDiv) { ps_suggestionsDiv.innerHTML = ''; ps_suggestionsDiv.style.display = 'none'; } },
                     ontimeout: function() { if (ps_suggestionsDiv) { ps_suggestionsDiv.innerHTML = ''; ps_suggestionsDiv.style.display = 'none'; } }
                 });
            }
            function ps_renderSuggestions(suggestions) {
                 if (!ps_suggestionsDiv) return;
                 if (!suggestions || !Array.isArray(suggestions) || suggestions.length === 0) {
                     ps_suggestionsDiv.innerHTML = ''; ps_suggestionsDiv.style.display = 'none'; return;
                 }
                 ps_suggestionsDiv.innerHTML = '';
                 let addedSuggestions = 0;
                 suggestions.forEach(suggestion => {
                     if (suggestion && suggestion.name && (suggestion.type === "Товары" || suggestion.type === "Search" || suggestion.type === "Игры")) {
                         const item = document.createElement('div');
                         item.className = 'suggestionItem';
                         item.textContent = suggestion.name;
                         item.onmousedown = (e) => {
                             e.preventDefault(); ps_searchInput.value = suggestion.name;
                             ps_suggestionsDiv.style.display = 'none'; ps_triggerSearch();
                         };
                         ps_suggestionsDiv.appendChild(item);
                         addedSuggestions++;
                     }
                 });
                 ps_suggestionsDiv.style.display = addedSuggestions > 0 ? 'block' : 'none';
            }

            // --- Запросы API ---
            function ps_fetchTotalCount(query) {
                 const params = new URLSearchParams({
                     query: query, searchmode: 10, sortmode: PS_DEFAULT_SORT_MODE,
                     pagesize: PS_RESULTS_PER_PAGE_CHECK, pagenum: 1, owner: 1,
                     details: 1, checkhidesales: 1, host: 'plati.market'
                 });
                 GM_xmlhttpRequest({
                     method: "GET", url: `${PS_API_BASE_URL}?${params.toString()}`, timeout: 15000, responseType: 'json',
                     onload: function(response) {
                         if (response.status >= 200 && response.status < 400 && response.response) {
                             const data = response.response;
                             if (data?.result?.total > 0) {
                                 const total = data.result.total;
                                 ps_updateStatus(`Найдено ${total} товаров. Загрузка...`, true);
                                 ps_fetchAllResults(query, total, PS_DEFAULT_SORT_MODE);
                             } else {
                                 ps_updateStatus(`По запросу "${query}" ничего не найдено.`);
                                 ps_currentResults = []; ps_renderResults(); ps_updateFilterPlaceholders(); ps_applyFilters();
                             }
                         } else { ps_updateStatus(`Ошибка получения общего количества товаров (Статус: ${response.status})`); }
                     },
                     onerror: function(error) { ps_updateStatus('Ошибка сети при получении общего количества товаров.'); },
                     ontimeout: function() { ps_updateStatus('Время ожидания ответа от сервера (количество) истекло.'); }
                 });
            }
            function ps_fetchAllResults(query, total, sortMode) {
                 const MAX_PAGE_SIZE = 1000;
                 const effectivePageSize = Math.min(total, MAX_PAGE_SIZE);
                 if (total > MAX_PAGE_SIZE) ps_updateStatus(`Найдено ${total} товаров. Загрузка первых ${MAX_PAGE_SIZE}...`, true);

                 const params = new URLSearchParams({
                     query: query, searchmode: 10, sortmode: sortMode, pagesize: effectivePageSize,
                     pagenum: 1, owner: 1, details: 1, checkhidesales: 1, host: 'plati.market'
                 });
                 GM_xmlhttpRequest({
                     method: "GET", url: `${PS_API_BASE_URL}?${params.toString()}`, timeout: 90000, responseType: 'json',
                     onload: function(response) {
                          if (!document.body.contains(ps_modal)) return;

                         if (response.status >= 200 && response.status < 400 && response.response) {
                             const data = response.response;
                             if (data?.items?.item && Array.isArray(data.items.item)) {
                                 ps_currentResults = data.items.item.map((item, index) => ({ ...item, originalIndex: index }));
                                 const loadedCount = ps_currentResults.length;
                                 ps_updateStatus(`Загружено ${loadedCount}${total > loadedCount ? ` из ${total}` : ''} товаров.`);
                                 ps_applySort(ps_currentSort.field, ps_currentSort.direction);
                                 ps_renderResults();
                                 ps_updateFilterPlaceholders();
                                 ps_applyFilters();
                             } else {
                                 ps_updateStatus(`Ошибка загрузки товаров: неверный формат ответа API.`);
                                 ps_currentResults = []; ps_renderResults(); ps_updateFilterPlaceholders(); ps_applyFilters();
                             }
                         } else { ps_updateStatus(`Ошибка загрузки товаров (Статус: ${response.status})`); }
                     },
                     onerror: function(error) { if (document.body.contains(ps_modal)) ps_updateStatus('Ошибка сети при загрузке товаров.'); },
                     ontimeout: function() { if (document.body.contains(ps_modal)) ps_updateStatus('Время ожидания ответа от сервера (товары) истекло.'); }
                 });
            }

            // --- Сортировка ---
             function ps_handleSort(field) {
                 let newDirection;
                 const sortInfo = ps_advancedSorts[field];
                 if (!sortInfo) return;

                 let currentDir = (ps_currentSort.field === field) ? ps_currentSort.direction : sortInfo.defaultDir;

                 if (ps_firstSortClick[field] || ps_currentSort.field !== field) {
                     newDirection = sortInfo.defaultDir;
                 } else {
                     newDirection = currentDir === 'desc' ? 'asc' : 'desc';
                 }

                 Object.keys(ps_firstSortClick).forEach(key => {
                     ps_firstSortClick[key] = (key !== field);
                 });
                 ps_firstSortClick[field] = false;

                 ps_currentSort.field = field;
                 ps_currentSort.direction = newDirection;
                 GM_setValue(PS_LAST_SORT_STORAGE_KEY, ps_currentSort);

                 ps_applySort(field, newDirection);
                 ps_renderResults();
                 ps_updateSortButtonsState();
             }

             function ps_updateSortButtonsState() {
                 const activeField = ps_currentSort.field;
                 const activeDirection = ps_currentSort.direction;

                  $(ps_sortPriceBtn).add(ps_sortSalesBtn).each(function() {
                     const $btn = $(this);
                     const btnField = $btn.data('sort');
                     const baseText = (btnField === 'price') ? 'Цена' : 'Продажи';
                     if (btnField === activeField) {
                         const arrow = activeDirection === 'asc' ? ' ▲' : ' ▼';
                         $btn.addClass('active').text(baseText + arrow).attr('data-dir', activeDirection);
                     } else {
                         const defaultDir = ps_advancedSorts[btnField].defaultDir;
                         const defaultArrow = defaultDir === 'asc' ? ' ▲' : ' ▼';
                         $btn.removeClass('active').text(baseText + defaultArrow).attr('data-dir', defaultDir);
                     }
                 });

                 let advBtnText = 'Доп. сорт.';
                 const $advButton = $(ps_advSortBtn);
                 const isAdvSortActive = ps_advancedSorts[activeField] && activeField !== 'price' && activeField !== 'sales' && activeField !== 'relevance';

                 if (isAdvSortActive) {
                     $advButton.addClass('active');
                     const arrow = activeDirection === 'asc' ? ' ▲' : ' ▼';
                     advBtnText = `${ps_advancedSorts[activeField].name}${arrow}`;
                 } else {
                     $advButton.removeClass('active');
                 }
                 $advButton.text(advBtnText);

                 $('#platiSearchAdvSortMenu .platiSearchSortMenuItem').each(function() {
                     const $item = $(this);
                     const itemField = $item.data('sort');
                     const baseText = ps_advancedSorts[itemField].name;
                     if (itemField === activeField) {
                         const arrow = activeDirection === 'asc' ? ' ▲' : ' ▼';
                         $item.addClass('active').html(`${baseText} <span class="sortArrow">${arrow}</span>`).attr('data-dir', activeDirection);
                     } else {
                         const defaultDir = ps_advancedSorts[itemField].defaultDir;
                         const defaultArrow = defaultDir === 'asc' ? ' ▲' : ' ▼';
                         $item.removeClass('active').html(`${baseText} <span class="sortArrow">${defaultArrow}</span>`).attr('data-dir', defaultDir);
                     }
                 });

                 if (activeField === 'relevance') {
                     $(ps_resetSortBtn).addClass('active');
                 } else {
                      $(ps_resetSortBtn).removeClass('active');
                 }
             }

            function ps_resetSort(render = true) {
                 ps_currentSort = { field: 'relevance', direction: 'asc' };
                 ps_firstSortClick = {
                     price: true, sales: true, relevance: false, name: true, date_create: true, discount: true,
                     seller_rating: true, review_ratio: true, good_reviews: true, bad_reviews: true, returns: true
                 };
                 GM_setValue(PS_LAST_SORT_STORAGE_KEY, ps_currentSort);
                 ps_updateSortButtonsState();

                 if (render) {
                     ps_applySort(ps_currentSort.field, ps_currentSort.direction);
                     ps_renderResults();
                 }
             }

            function ps_applySort(field, direction) {
                 const dirMultiplier = direction === 'asc' ? 1 : -1;
                 const selectedCurrency = ps_currencySelect ? ps_currencySelect.value.toUpperCase() : 'RUR';
                 ps_currentResults.sort((a, b) => {
                     let valA, valB;
                     const nameA = (a.name || '').toLowerCase();
                     const nameB = (b.name || '').toLowerCase();
                     const finalPriceA = getPriceInSelectedCurrency(a, selectedCurrency);
                     const finalPriceB = getPriceInSelectedCurrency(b, selectedCurrency);
                     let comparisonResult = 0;
                     switch (field) {
                         case 'price':         valA = finalPriceA; valB = finalPriceB; break;
                         case 'sales':         valA = formatSales(a.cnt_sell); valB = formatSales(b.cnt_sell); break;
                         case 'name':          comparisonResult = nameA.localeCompare(nameB) * dirMultiplier; break;
                         case 'date_create':   valA = parseDate(a.date_create); valB = parseDate(b.date_create); break;
                         case 'discount':      valA = parseInt(a.discount || '0', 10); valB = parseInt(b.discount || '0', 10); break;
                         case 'seller_rating': valA = parseSellerRating(a.seller_rating); valB = parseSellerRating(b.seller_rating); break;
                         case 'review_ratio':  valA = calculateReviewRatio(a); valB = calculateReviewRatio(b); break;
                         case 'good_reviews':  valA = parseInt(a.cnt_good_responses || '0', 10); valB = parseInt(b.cnt_good_responses || '0', 10); break;
                         case 'bad_reviews':   valA = parseInt(a.cnt_bad_responses || '0', 10); valB = parseInt(b.cnt_bad_responses || '0', 10); break;
                         case 'returns':       valA = parseInt(a.cnt_return || '0', 10); valB = parseInt(b.cnt_return || '0', 10); break;
                         case 'relevance':     valA = a.originalIndex; valB = b.originalIndex; break;
                         default: return 0;
                     }
                     if (field !== 'name') {
                         const fallbackAsc = Infinity; const fallbackDesc = -Infinity;
                         if (valA === null || valA === undefined || isNaN(valA) || valA === Infinity || valA === -Infinity) valA = direction === 'asc' ? fallbackAsc : fallbackDesc;
                         if (valB === null || valB === undefined || isNaN(valB) || valB === Infinity || valB === -Infinity) valB = direction === 'asc' ? fallbackAsc : fallbackDesc;
                         if (valA < valB) comparisonResult = -1; else if (valA > valB) comparisonResult = 1; else comparisonResult = 0;
                         comparisonResult *= dirMultiplier;
                     }
                     if (comparisonResult === 0) {
                         if (field !== 'name') { let nameCompare = nameA.localeCompare(nameB); if (nameCompare !== 0) return nameCompare; }
                         if (field !== 'price') { if (finalPriceA < finalPriceB) return -1; if (finalPriceA > finalPriceB) return 1; }
                         if (field !== 'relevance') { return a.originalIndex - b.originalIndex; }
                     }
                     return comparisonResult;
                 });
            }

            // --- Управление фильтрами ---
            function ps_getFilterStorageKey(key) {
                return `${PS_FILTER_STORAGE_PREFIX}${key}`;
            }

            function ps_loadFilters() {
                const defaults = {
                    priceMin: '',
                    priceMax: '',
                    salesMin: '',
                    salesMax: '',
                    ratingMin: '',
                    ratingMax: '',
                    hideBadReviews: false,
                    hideReturns: false,
                    onlyDiscount: false,
                    date: 'all'
                };
                let loaded = {};
                for (const key in defaults) {
                    loaded[key] = GM_getValue(ps_getFilterStorageKey(key), defaults[key]);
                }
                return loaded;
            }

            function ps_saveFilter(key, value) {
                ps_currentFilters[key] = value;
                GM_setValue(ps_getFilterStorageKey(key), value);
            }

            function applyLoadedFiltersToUI() {
                if (!ps_filtersPanel) return;
                ps_filterPriceMin.value = ps_currentFilters.priceMin;
                ps_filterPriceMax.value = ps_currentFilters.priceMax;
                ps_filterSalesMin.value = ps_currentFilters.salesMin;
                ps_filterSalesMax.value = ps_currentFilters.salesMax;
                ps_filterRatingMin.value = ps_currentFilters.ratingMin;
                ps_filterRatingMax.value = ps_currentFilters.ratingMax;
                ps_filterHideBadReviews.checked = ps_currentFilters.hideBadReviews;
                ps_filterHideReturns.checked = ps_currentFilters.hideReturns;
                ps_filterOnlyDiscount.checked = ps_currentFilters.onlyDiscount;
                ps_filterDateSelect.value = ps_currentFilters.date;
                const priceHeader = ps_filtersPanel.querySelector('.filterGroup h4');
                if (priceHeader && priceHeader.textContent.includes('Цена')) {
                    priceHeader.innerHTML = `Цена (${ps_currentCurrency}) ${ps_createResetButtonHTML('price')}`;
                    const resetButton = priceHeader.querySelector('.filterResetBtn');
                    if (resetButton) resetButton.onclick = ps_handleFilterReset;
                }
            }

            function ps_addFilterEventListeners() {
                if (!ps_filtersPanel) return;
                const debouncedApply = debounce(ps_applyFilters, PS_FILTER_DEBOUNCE_MS);
                ps_filterPriceMin.addEventListener('input', (e) => {
                    ps_saveFilter('priceMin', e.target.value);
                    debouncedApply();
                });
                ps_filterPriceMax.addEventListener('input', (e) => {
                    ps_saveFilter('priceMax', e.target.value);
                    debouncedApply();
                });
                ps_filterSalesMin.addEventListener('input', (e) => {
                    ps_saveFilter('salesMin', e.target.value);
                    debouncedApply();
                });
                ps_filterSalesMax.addEventListener('input', (e) => {
                    ps_saveFilter('salesMax', e.target.value);
                    debouncedApply();
                });
                ps_filterRatingMin.addEventListener('input', (e) => {
                    ps_saveFilter('ratingMin', e.target.value);
                    debouncedApply();
                });
                ps_filterRatingMax.addEventListener('input', (e) => {
                    ps_saveFilter('ratingMax', e.target.value);
                    debouncedApply();
                });
                ps_filterHideBadReviews.addEventListener('change', (e) => {
                    ps_saveFilter('hideBadReviews', e.target.checked);
                    ps_applyFilters();
                });
                ps_filterHideReturns.addEventListener('change', (e) => {
                    ps_saveFilter('hideReturns', e.target.checked);
                    ps_applyFilters();
                });
                ps_filterOnlyDiscount.addEventListener('change', (e) => {
                    ps_saveFilter('onlyDiscount', e.target.checked);
                    ps_applyFilters();
                });
                ps_filterDateSelect.addEventListener('change', (e) => {
                    ps_saveFilter('date', e.target.value);
                    ps_applyFilters();
                });
                ps_resetAllFiltersBtn.addEventListener('click', () => ps_resetAllFilters(true));
                ps_filtersPanel.querySelectorAll('.filterResetBtn').forEach(btn => {
                    btn.onclick = ps_handleFilterReset;
                });
            }

            function ps_handleFilterReset(event) {
                ps_resetFilterByKey(event.currentTarget.dataset.filterKey, true);
            }

            function ps_resetFilterByKey(key, apply = true) {
                switch (key) {
                    case 'price':
                        ps_saveFilter('priceMin', '');
                        if (ps_filterPriceMin) ps_filterPriceMin.value = '';
                        ps_saveFilter('priceMax', '');
                        if (ps_filterPriceMax) ps_filterPriceMax.value = '';
                        break;
                    case 'sales':
                        ps_saveFilter('salesMin', '');
                        if (ps_filterSalesMin) ps_filterSalesMin.value = '';
                        ps_saveFilter('salesMax', '');
                        if (ps_filterSalesMax) ps_filterSalesMax.value = '';
                        break;
                    case 'rating':
                        ps_saveFilter('ratingMin', '');
                        if (ps_filterRatingMin) ps_filterRatingMin.value = '';
                        ps_saveFilter('ratingMax', '');
                        if (ps_filterRatingMax) ps_filterRatingMax.value = '';
                        break;
                    case 'options':
                        ps_saveFilter('hideBadReviews', false);
                        if (ps_filterHideBadReviews) ps_filterHideBadReviews.checked = false;
                        ps_saveFilter('hideReturns', false);
                        if (ps_filterHideReturns) ps_filterHideReturns.checked = false;
                        ps_saveFilter('onlyDiscount', false);
                        if (ps_filterOnlyDiscount) ps_filterOnlyDiscount.checked = false;
                        break;
                    case 'date':
                        ps_saveFilter('date', 'all');
                        if (ps_filterDateSelect) ps_filterDateSelect.value = 'all';
                        break;
                }
                if (apply) ps_applyFilters();
            }

            function ps_resetAllFilters(apply = true) {
                const filterKeys = ['price', 'sales', 'rating', 'options', 'date'];
                filterKeys.forEach(key => ps_resetFilterByKey(key, false));
                if (apply) ps_applyFilters();
            }

            function ps_updateFilterPlaceholders() {
                if (!ps_filtersPanel || !ps_currentResults || ps_currentResults.length === 0) {
                    $('#psFilterPriceMin, #psFilterPriceMax, #psFilterSalesMin, #psFilterSalesMax, #psFilterRatingMin, #psFilterRatingMax').attr('placeholder', '-');
                    return;
                }
                let minPrice = Infinity,
                    maxPrice = -Infinity,
                    minSales = Infinity,
                    maxSales = -Infinity,
                    minRating = Infinity,
                    maxRating = -Infinity;
                const selectedCurrency = ps_currencySelect ? ps_currencySelect.value.toUpperCase() : 'RUR';
                ps_currentResults.forEach(item => {
                    const price = getPriceInSelectedCurrency(item, selectedCurrency);
                    const sales = formatSales(item.cnt_sell);
                    const rating = parseSellerRating(item.seller_rating);
                    if (price !== Infinity && price < minPrice) minPrice = price;
                    if (price !== Infinity && price > maxPrice) maxPrice = price;
                    if (sales < minSales) minSales = sales;
                    if (sales > maxSales) maxSales = sales;
                    if (rating > 0 && rating < minRating) minRating = rating;
                    if (rating > maxRating) maxRating = rating;
                });
                if (minRating === Infinity) minRating = 0;
                if (ps_filterPriceMin) ps_filterPriceMin.placeholder = minPrice === Infinity ? '-' : `от ${Math.floor(minPrice)}`;
                if (ps_filterPriceMax) ps_filterPriceMax.placeholder = maxPrice === -Infinity ? '-' : `до ${Math.ceil(maxPrice)}`;
                if (ps_filterSalesMin) ps_filterSalesMin.placeholder = minSales === Infinity ? '-' : `от ${minSales}`;
                if (ps_filterSalesMax) ps_filterSalesMax.placeholder = maxSales === -Infinity ? '-' : `до ${maxSales}`;
                if (ps_filterRatingMin) ps_filterRatingMin.placeholder = minRating === Infinity ? '-' : `от ${minRating.toFixed(1)}`;
                if (ps_filterRatingMax) ps_filterRatingMax.placeholder = maxRating === -Infinity ? '-' : `до ${maxRating.toFixed(1)}`;
            }

            function ps_getDateThreshold(periodKey) {
                const now = Date.now();
                let threshold = 0;
                const dayMs = 86400000;
                switch (periodKey) {
                    case '1d':
                        threshold = now - 1 * dayMs;
                        break;
                    case '2d':
                        threshold = now - 2 * dayMs;
                        break;
                    case '1w':
                        threshold = now - 7 * dayMs;
                        break;
                    case '1m':
                        threshold = now - 30 * dayMs;
                        break;
                    case '6m':
                        threshold = now - 182 * dayMs;
                        break;
                    case '1y':
                        threshold = now - 365 * dayMs;
                        break;
                    case '5y':
                        threshold = now - 5 * 365 * dayMs;
                        break;
                    case '10y':
                        threshold = now - 10 * 365 * dayMs;
                        break;
                    default:
                        threshold = 0;
                        break;
                }
                return threshold;
            }

            function ps_applyFilters() {
                if (!ps_resultsDiv || !ps_currentResults) return;
                const keywords = ps_exclusionKeywords.map(k => k.toLowerCase());
                const pMin = parseFloat(ps_currentFilters.priceMin) || 0;
                const pMax = parseFloat(ps_currentFilters.priceMax) || Infinity;
                const sMin = parseInt(ps_currentFilters.salesMin, 10) || 0;
                const sMax = parseInt(ps_currentFilters.salesMax, 10) || Infinity;
                const rMin = parseFloat(ps_currentFilters.ratingMin) || 0;
                const rMax = parseFloat(ps_currentFilters.ratingMax) || Infinity;
                const hideBad = ps_currentFilters.hideBadReviews;
                const hideRet = ps_currentFilters.hideReturns;
                const onlyDisc = ps_currentFilters.onlyDiscount;
                const datePeriod = ps_currentFilters.date;
                const dateThreshold = ps_getDateThreshold(datePeriod);
                const selectedCurrency = ps_currencySelect ? ps_currencySelect.value.toUpperCase() : 'RUR';
                let visibleCount = 0;
                const items = ps_resultsDiv.querySelectorAll('.platiSearchItem');
                items.forEach(itemElement => {
                    const itemId = itemElement.dataset.id;
                    const itemData = ps_currentResults.find(r => r.id === itemId);
                    if (!itemData) {
                        itemElement.classList.add('hidden-by-filter');
                        return;
                    }
                    let shouldHide = false;
                    if (!shouldHide && keywords.length > 0) {
                        const title = (itemData.name || '').toLowerCase();
                        const seller = (itemData.seller_name || '').toLowerCase();
                        if (keywords.some(keyword => (title + ' ' + seller).includes(keyword))) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide) {
                        const price = getPriceInSelectedCurrency(itemData, selectedCurrency);
                        if (price < pMin || price > pMax) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide) {
                        const sales = formatSales(itemData.cnt_sell);
                        if (sales < sMin || sales > sMax) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide) {
                        const rating = parseSellerRating(itemData.seller_rating);
                        if ((rating === 0 && (rMin > 0 || rMax < Infinity)) || rating < rMin || rating > rMax) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide && hideBad) {
                        if (parseInt(itemData.cnt_bad_responses || '0', 10) > 0) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide && hideRet) {
                        if (parseInt(itemData.cnt_return || '0', 10) > 0) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide && onlyDisc) {
                        if (parseInt(itemData.discount || '0', 10) <= 0) {
                            shouldHide = true;
                        }
                    }
                    if (!shouldHide && dateThreshold > 0) {
                        const itemDate = parseDate(itemData.date_create);
                        if (!itemDate || itemDate < dateThreshold) {
                            shouldHide = true;
                        }
                    }
                    if (shouldHide) {
                        itemElement.classList.add('hidden-by-filter');
                    } else {
                        itemElement.classList.remove('hidden-by-filter');
                        visibleCount++;
                    }
                });
                const totalLoadedCount = ps_currentResults.length;
                const anyFilterActive = pMin > 0 || pMax < Infinity || sMin > 0 || sMax < Infinity || rMin > 0 || rMax < Infinity || hideBad || hideRet || onlyDisc || datePeriod !== 'all' || keywords.length > 0;
                if (totalLoadedCount > 0) {
                    if (anyFilterActive) {
                        ps_updateStatus(`Показано ${visibleCount} из ${totalLoadedCount} товаров (фильтры/исключения применены).`);
                    } else {
                        ps_updateStatus(`Загружено ${totalLoadedCount} товаров.`);
                    }
                } else if (ps_searchInput && ps_searchInput.value.trim()) {} else {
                    ps_updateStatus(`Введите запрос для поиска.`);
                }
                if (visibleCount === 0 && totalLoadedCount > 0 && anyFilterActive) {
                    ps_statusDiv.textContent += ' Нет товаров, соответствующих критериям.';
                    ps_statusDiv.style.display = 'block';
                } else if (totalLoadedCount === 0 && ps_searchInput && ps_searchInput.value.trim()) {
                    ps_statusDiv.style.display = 'block';
                }
            }

            // --- Фильтрация исключений ---
            function ps_addFilterKeyword() {
                const keyword = ps_excludeInput.value.trim().toLowerCase();
                if (keyword && !ps_exclusionKeywords.includes(keyword)) {
                    ps_exclusionKeywords.push(keyword);
                    GM_setValue(PS_EXCLUSION_STORAGE_KEY, ps_exclusionKeywords);
                    ps_excludeInput.value = '';
                    ps_renderExclusionTags();
                    ps_applyFilters();
                }
            }

            function ps_removeFilterKeyword(keywordToRemove) {
                ps_exclusionKeywords = ps_exclusionKeywords.filter(k => k !== keywordToRemove);
                GM_setValue(PS_EXCLUSION_STORAGE_KEY, ps_exclusionKeywords);
                ps_renderExclusionTags();
                ps_applyFilters();
            }

            function ps_renderExclusionTags() {
                if (!ps_exclusionTagsListDiv) return;
                ps_exclusionTagsListDiv.innerHTML = '';
                ps_exclusionKeywords.forEach(keyword => {
                    const tag = document.createElement('span');
                    tag.className = 'exclusionTag';
                    tag.textContent = keyword;
                    tag.title = `Удалить "${keyword}"`;
                    tag.onclick = () => ps_removeFilterKeyword(keyword);
                    ps_exclusionTagsListDiv.appendChild(tag);
                });
            }

            // --- Рендеринг результатов ---
             function ps_renderResults() {
                 if (!ps_resultsDiv) return;
                 ps_resultsDiv.innerHTML = '';
                 if (ps_currentResults.length === 0) {
                     ps_applyFilters();
                     return;
                 }

                 const fragment = document.createDocumentFragment();
                 const now = Date.now();
                 const thresholdTime = now - NEW_ITEM_THRESHOLD_DAYS * 24 * 60 * 60 * 1000;
                 const selectedCurrency = ps_currencySelect ? ps_currencySelect.value.toUpperCase() : 'RUR';

                 ps_currentResults.forEach(item => {
                     const itemDiv = document.createElement('div');
                     itemDiv.className = 'platiSearchItem';
                     itemDiv.dataset.id = item.id;
                     const link = document.createElement('a');

                     const baseUrl = item.url || `https://plati.market/itm/${item.id}`;
                     link.href = baseUrl + '?ai=234029';

                     link.target = '_blank';
                     link.rel = 'noopener noreferrer nofollow';
                     const imageWrapper = document.createElement('div');
                     imageWrapper.className = 'card-image-wrapper';
                     const img = document.createElement('img');
                     const imgSrc = `https://${PS_IMAGE_DOMAIN}/imgwebp.ashx?id_d=${item.id}&w=164&h=164&dc=${item.ticks_last_change || Date.now()}`;
                     img.src = imgSrc;
                     img.alt = item.name || 'Изображение товара';
                     img.loading = 'lazy';
                     img.onerror = function() {
                         this.onerror = null;
                         this.src = 'https://plati.market/images/logo-plati.png';
                         this.style.objectFit = 'contain';
                     };
                     imageWrapper.appendChild(img);
                     const itemDate = parseDate(item.date_create);
                     if (itemDate && itemDate > thresholdTime) {
                         const newBadge = document.createElement('span');
                         newBadge.className = 'newItemBadge';
                         newBadge.textContent = 'New';
                         imageWrapper.appendChild(newBadge);
                     }
                     link.appendChild(imageWrapper);
                     const priceDiv = document.createElement('div');
                     priceDiv.className = 'price';
                     let displayPrice = getPriceInSelectedCurrency(item, selectedCurrency);
                     let currencySymbol;
                     switch (selectedCurrency) {
                         case 'USD':
                             currencySymbol = '$';
                             break;
                         case 'EUR':
                             currencySymbol = '€';
                             break;
                         case 'UAH':
                             currencySymbol = '₴';
                             break;
                         default:
                             currencySymbol = '₽';
                             break;
                     }
                     priceDiv.textContent = displayPrice !== Infinity ? `${displayPrice.toLocaleString('ru-RU', {minimumFractionDigits: 0, maximumFractionDigits: 2})} ${currencySymbol}` : 'Нет цены';
                     priceDiv.title = `Цена в ${selectedCurrency}`;
                     link.appendChild(priceDiv);
                     const titleDiv = document.createElement('div');
                     titleDiv.className = 'title';
                     titleDiv.textContent = item.name || 'Без названия';
                     titleDiv.title = item.name || 'Без названия';
                     link.appendChild(titleDiv);
                     const infoContainer = document.createElement('div');
                     infoContainer.className = 'cardInfoContainer';
                     const infoRow1 = document.createElement('div');
                     infoRow1.className = 'cardInfoRow1';
                     const infoRow2 = document.createElement('div');
                     infoRow2.className = 'cardInfoRow2';
                     const ratingVal = parseSellerRating(item.seller_rating);
                     const goodRev = parseInt(item.cnt_good_responses || '0');
                     const badRev = parseInt(item.cnt_bad_responses || '0');
                     const returns = parseInt(item.cnt_return || '0');
                     let salesCount = formatSales(item.cnt_sell);
                     infoRow1.innerHTML = `<span title="Рейтинг продавца">Рейт: ${ratingVal > 0 ? ratingVal.toLocaleString('ru-RU', {maximumFractionDigits: 0}) : 'N/A'}</span><span title="Отзывы (Хорошие/Плохие)">Отз: <span class="reviewsGood">${goodRev}</span>${badRev > 0 ? '/<span class="reviewsBad">' + badRev + '</span>' : ''}</span><span title="Возвраты">Возв: ${returns}</span>`;
                     infoRow2.innerHTML = `<span class="sales" title="Продажи">Прод: ${salesCount > 0 ? salesCount.toLocaleString('ru-RU') : '0'}</span><span class="dateAdded" title="Дата добавления">Доб: ${formatDateString(itemDate)}</span>`;
                     infoContainer.appendChild(infoRow1);
                     infoContainer.appendChild(infoRow2);
                     const sellerLink = document.createElement('a');
                     sellerLink.className = 'sellerLink';
                     sellerLink.textContent = `Продавец: ${item.seller_name || 'N/A'}`;
                     sellerLink.title = `Перейти к продавцу: ${item.seller_name || 'N/A'}`;
                     if (item.seller_id && item.seller_name) {
                         const safeSellerName = encodeURIComponent(item.seller_name.replace(/[^a-zA-Z0-9_\-.~]/g, '-')).replace(/%2F/g, '/');
                         sellerLink.href = `https://plati.market/seller/${safeSellerName}/${item.seller_id}/`;
                         sellerLink.target = '_blank';
                         sellerLink.rel = 'noopener noreferrer nofollow';
                         sellerLink.onclick = (e) => {
                             e.stopPropagation();
                         };
                     } else {
                         sellerLink.style.pointerEvents = 'none';
                     }
                     infoContainer.appendChild(sellerLink);
                     link.appendChild(infoContainer);
                     const buyButtonDiv = document.createElement('div');
                     buyButtonDiv.className = 'buyButton';
                     buyButtonDiv.textContent = 'Перейти';
                     link.appendChild(buyButtonDiv);
                     itemDiv.appendChild(link);
                     fragment.appendChild(itemDiv);
                 });
                 ps_resultsDiv.appendChild(fragment);
                 ps_applyFilters();
             }

            // --- Обработчики UI ---
            function ps_handleCurrencyChange() {
                ps_currentCurrency = ps_currencySelect.value.toUpperCase();
                GM_setValue(PS_CURRENCY_STORAGE_KEY, ps_currentCurrency);
                applyLoadedFiltersToUI();
                ps_updateFilterPlaceholders();
                if (ps_currentSort.field === 'price') {
                    ps_applySort(ps_currentSort.field, ps_currentSort.direction);
                }
                ps_renderResults();
            }

            // --- Добавление кнопки Plati ---
            function addPlatiButton() {
                const actionsContainer = document.querySelector('#queueActionsCtn');

                if (!actionsContainer || actionsContainer.querySelector('.plati_price_button')) {
                    return;
                }

                const ignoreButtonContainer = actionsContainer.querySelector('#ignoreBtn');

                const platiContainer = document.createElement('div');
                platiContainer.className = 'plati_price_button queue_control_button';
                platiContainer.style.marginLeft = '3px';
                platiContainer.innerHTML = `<div class="btnv6_blue_hoverfade btn_medium" style="height: 32px; padding: 0 5px;" title="Найти на Plati.Market"><span>Plati</span></div>`;
                platiContainer.querySelector('div').addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    showPlatiModal();
                });

                if (ignoreButtonContainer) {
                    ignoreButtonContainer.insertAdjacentElement('afterend', platiContainer);
                } else {
                    actionsContainer.appendChild(platiContainer);
                }
            }

            // --- Стили ---
             function addPlatiStyles() {
                 GM_addStyle(`
                    /* Стили спиннера */
                    @keyframes platiSpin {
                    	0% {
                    		transform: rotate(0deg);
                    	}

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

                    .spinner {
                    	border: 3px solid rgba(255, 255, 255, 0.3);
                    	border-radius: 50%;
                    	border-top-color: #fff;
                    	width: 1em;
                    	height: 1em;
                    	animation: platiSpin 1s linear infinite;
                    	display: inline-block;
                    	vertical-align: middle;
                    	margin-left: 5px;
                    }

                    .platiSearchBtn .spinner {
                    	width: 0.8em;
                    	height: 0.8em;
                    	border-width: 2px;
                    }

                    /* Стили модального окна */
                    #platiSearchModal {
                    	position: fixed;
                    	top: 0;
                    	left: 0;
                    	width: 100%;
                    	height: 100%;
                    	background-color: rgba(20, 20, 25, 0.98);
                    	z-index: 9999;
                    	display: none;
                    	color: #eee;
                    	font-family: "Motiva Sans", Sans-serif, Arial;
                    	overflow-y: auto;
                    	scrollbar-color: #67c1f5 #17202d;
                    	scrollbar-width: thin;
                    }

                    #platiSearchModal::-webkit-scrollbar {
                    	width: 8px;
                    }

                    #platiSearchModal::-webkit-scrollbar-track {
                    	background: #17202d;
                    	border-radius: 4px;
                    }

                    #platiSearchModal::-webkit-scrollbar-thumb {
                    	background-color: #4b6f9c;
                    	border-radius: 4px;
                    	border: 2px solid #17202d;
                    }

                    #platiSearchModal::-webkit-scrollbar-thumb:hover {
                    	background-color: #67c1f5;
                    }

                    #platiSearchModal * {
                    	box-sizing: border-box;
                    }

                    #platiSearchContainer {
                    	max-width: 1350px;
                    	margin: 0 auto;
                    	padding: 15px ${PS_SIDE_PANEL_HORIZONTAL_PADDING}px;
                    	position: relative;
                    	min-height: 100%;
                    }

                    #platiSearchCloseBtn {
                    	position: fixed;
                    	top: 15px;
                    	right: 20px;
                    	font-size: 35px;
                    	color: #aaa;
                    	background: none;
                    	border: none;
                    	cursor: pointer;
                    	line-height: 1;
                    	z-index: 10002;
                    	padding: 5px;
                    	transition: color 0.2s, transform 0.2s;
                    }

                    #platiSearchCloseBtn:hover {
                    	color: #fff;
                    	transform: scale(1.1);
                    }

                    /* Шапка */
                    #platiSearchHeader {
                    	display: flex;
                    	align-items: center;
                    	gap: 10px;
                    	margin-bottom: 15px;
                    	flex-wrap: wrap;
                    	position: relative;
                    	z-index: 5;
                    	border-bottom: 1px solid #444;
                    	padding-bottom: 15px;
                    	padding-left: ${PS_CONTENT_PADDING_LEFT}px;
                    	padding-right: ${PS_CONTENT_PADDING_RIGHT}px;
                    	margin-left: -${PS_CONTENT_PADDING_LEFT}px;
                    	margin-right: -${PS_CONTENT_PADDING_RIGHT}px;
                    	flex-shrink: 0;
                    }

                    .platiSearchInputContainer {
                    	position: relative;
                    	flex-grow: 0.7;
                    	min-width: 200px;
                    	flex-basis: 350px;
                    }

                    #platiSearchInput {
                    	width: 100%;
                    	padding: 10px 15px;
                    	font-size: 16px;
                    	background-color: #333;
                    	border: 1px solid #555;
                    	color: #eee;
                    	border-radius: 4px;
                    	height: 40px;
                    	outline: none;
                    }

                    #platiSearchInput:focus {
                    	border-color: #67c1f5;
                    }

                    #platiSearchSuggestions {
                    	position: absolute;
                    	top: 100%;
                    	left: 0;
                    	right: 0;
                    	background-color: #3a3a40;
                    	border: 1px solid #555;
                    	border-top: none;
                    	border-radius: 0 0 4px 4px;
                    	max-height: 300px;
                    	overflow-y: auto;
                    	z-index: 10000;
                    	display: none;
                    }

                    .suggestionItem {
                    	padding: 8px 15px;
                    	cursor: pointer;
                    	color: #eee;
                    	font-size: 14px;
                    	border-bottom: 1px solid #4a4a50;
                    }

                    .suggestionItem:last-child {
                    	border-bottom: none;
                    }

                    .suggestionItem:hover {
                    	background-color: #4a4a55;
                    }

                    /* Кнопки в шапке */
                    .platiSearchBtn {
                    	padding: 10px 15px;
                    	font-size: 14px;
                    	color: white;
                    	border: none;
                    	border-radius: 4px;
                    	cursor: pointer;
                    	white-space: nowrap;
                    	height: 40px;
                    	display: inline-flex;
                    	align-items: center;
                    	justify-content: center;
                    	flex-shrink: 0;
                    	background-color: #555;
                    	transition: background-color 0.2s;
                    }

                    .platiSearchBtn:hover:not(:disabled) {
                    	background-color: #666;
                    }

                    .platiSearchBtn:disabled {
                    	opacity: 0.6;
                    	cursor: default;
                    }

                    #platiSearchGoBtn {
                    	background-color: #4D88FF;
                    }

                    #platiSearchGoBtn:hover {
                    	background-color: #3366CC;
                    }

                    .platiSearchBtn.sortBtn.active {
                    	background-color: #007bff;
                    }

                    .platiSearchBtn.sortBtn.active:hover {
                    	background-color: #0056b3;
                    }

                    #platiResetSortBtn {
                    	background-color: #777;
                    	margin-right: 5px;
                    	padding: 0 10px;
                    }

                    #platiResetSortBtn:hover {
                    	background-color: #888;
                    }

                    #platiResetSortBtn svg {
                    	width: 16px;
                    	height: 16px;
                    	fill: currentColor;
                    }

                    #platiResetSortBtn.active {
                    	background-color: #007bff;
                    }

                    #platiSearchAdvSortBtnContainer {
                    	position: relative;
                    	flex-shrink: 0;
                    	width: ${PS_ADV_SORT_CONTAINER_WIDTH}px;
                    	display: flex;
                    	justify-content: center;
                    }

                    #platiSearchAdvSortBtn {
                    	width: 100%;
                    	justify-content: center;
                    	overflow: hidden;
                    	text-overflow: ellipsis;
                    }

                    #platiSearchCurrencySelect {
                    	margin-left: 10px;
                    	background-color: #333;
                    	color: #eee;
                    	border: 1px solid #555;
                    	border-radius: 4px;
                    	height: 40px;
                    	padding: 0 8px;
                    	font-size: 14px;
                    	cursor: pointer;
                    	flex-shrink: 0;
                    	outline: none;
                    }

                    #platiSearchCurrencySelect:focus {
                    	border-color: #67c1f5;
                    }

                    /* Меню доп сортировки */
                    #platiSearchAdvSortMenu {
                    	display: none;
                    	position: absolute;
                    	top: 100%;
                    	left: 0;
                    	background-color: #3a3a40;
                    	border: 1px solid #555;
                    	border-radius: 4px;
                    	min-width: 100%;
                    	z-index: 10001;
                    	padding: 5px 0;
                    	box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
                    }

                    #platiSearchAdvSortBtnContainer:hover #platiSearchAdvSortMenu {
                    	display: block;
                    }

                    .platiSearchSortMenuItem {
                    	display: block;
                    	padding: 8px 15px;
                    	color: #eee;
                    	font-size: 14px;
                    	cursor: pointer;
                    	white-space: nowrap;
                    	transition: background-color 0.1s;
                    }

                    .platiSearchSortMenuItem:hover {
                    	background-color: #4a4a55;
                    }

                    .platiSearchSortMenuItem.active {
                    	background-color: #007bff;
                    	color: white;
                    }

                    .platiSearchSortMenuItem .sortArrow {
                    	display: inline-block;
                    	margin-left: 5px;
                    	font-size: 12px;
                    }

                    /* Боковые панели */
                    #platiSearchFiltersPanel,
                    #platiSearchExclusionTags {
                    	position: fixed;
                    	top: ${PS_TOP_OFFSET_FOR_SIDE_PANELS}px;
                    	max-height: calc(100vh - ${PS_TOP_OFFSET_FOR_SIDE_PANELS}px - ${PS_BOTTOM_OFFSET_FOR_SIDE_PANELS}px);
                    	overflow-y: auto;
                    	z-index: 1000;
                    	padding: 10px;
                    	padding-right: 15px;
                    	scrollbar-width: thin;
                    	scrollbar-color: #555 #2a2a30;
                    	background-color: transparent;
                    	transition: top 0.2s ease-in-out;
                    }

                    #platiSearchFiltersPanel::-webkit-scrollbar,
                    #platiSearchExclusionTags::-webkit-scrollbar {
                    	width: 5px;
                    }

                    #platiSearchFiltersPanel::-webkit-scrollbar-track,
                    #platiSearchExclusionTags::-webkit-scrollbar-track {
                    	background: rgba(42, 42, 48, 0.5);
                    	border-radius: 3px;
                    }

                    #platiSearchFiltersPanel::-webkit-scrollbar-thumb,
                    #platiSearchExclusionTags::-webkit-scrollbar-thumb {
                    	background-color: rgba(85, 85, 85, 0.7);
                    	border-radius: 3px;
                    }

                    #platiSearchFiltersPanel {
                    	left: ${PS_SIDE_PANEL_HORIZONTAL_PADDING}px;
                    	width: ${PS_FILTER_PANEL_WIDTH}px;
                    }

                    #platiSearchExclusionTags {
                    	right: ${PS_SIDE_PANEL_HORIZONTAL_PADDING}px;
                    	width: ${PS_EXCLUSION_PANEL_WIDTH}px;
                    	display: flex;
                    	flex-direction: column;
                    	gap: 10px;
                    }

                    /* Фильтры */
                    .filterGroup {
                    	margin-bottom: 18px;
                    }

                    .filterGroup h4 {
                    	font-size: 15px;
                    	color: #ddd;
                    	margin-bottom: 8px;
                    	padding-bottom: 4px;
                    	display: flex;
                    	justify-content: space-between;
                    	align-items: center;
                    	text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
                    	font-weight: 500;
                    }

                    .filterResetBtn {
                    	font-size: 12px;
                    	color: #aaa;
                    	background: none;
                    	border: none;
                    	cursor: pointer;
                    	padding: 0 3px;
                    	line-height: 1;
                    }

                    .filterResetBtn:hover {
                    	color: #fff;
                    }

                    .filterResetBtn svg {
                    	width: 14px;
                    	height: 14px;
                    	vertical-align: middle;
                    	fill: currentColor;
                    }

                    .filterRangeInputs {
                    	display: flex;
                    	gap: 8px;
                    	align-items: center;
                    }

                    .filterRangeInputs input[type="number"] {
                    	width: calc(50% - 4px);
                    	padding: 6px 8px;
                    	font-size: 13px;
                    	background-color: rgba(51, 51, 51, 0.85);
                    	border: 1px solid #666;
                    	color: #eee;
                    	border-radius: 3px;
                    	height: 30px;
                    	text-align: center;
                    	-moz-appearance: textfield;
                    	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
                    	outline: none;
                    }

                    .filterRangeInputs input[type="number"]:focus {
                    	border-color: #67c1f5;
                    }

                    .filterRangeInputs input[type="number"]::-webkit-outer-spin-button,
                    .filterRangeInputs input[type="number"]::-webkit-inner-spin-button {
                    	-webkit-appearance: none;
                    	margin: 0;
                    }

                    .filterRangeInputs input[type="number"]::placeholder {
                    	color: #999;
                    	font-size: 11px;
                    	text-align: center;
                    }

                    .filterCheckbox {
                    	margin-bottom: 8px;
                    }

                    .filterCheckbox label {
                    	display: flex;
                    	align-items: center;
                    	font-size: 14px;
                    	cursor: pointer;
                    	color: #ccc;
                    	text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7);
                    }

                    .filterCheckbox input[type="checkbox"] {
                    	margin-right: 8px;
                    	width: 16px;
                    	height: 16px;
                    	accent-color: #007bff;
                    	cursor: pointer;
                    	flex-shrink: 0;
                    }

                    .filterSelect select {
                    	width: 100%;
                    	padding: 6px 8px;
                    	font-size: 13px;
                    	background-color: rgba(51, 51, 51, 0.85);
                    	border: 1px solid #666;
                    	color: #eee;
                    	border-radius: 3px;
                    	height: 30px;
                    	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
                    	outline: none;
                    }

                    .filterSelect select:focus {
                    	border-color: #67c1f5;
                    }

                    #psResetAllFiltersBtn {
                    	width: 100%;
                    	margin-top: 10px;
                    	padding: 8px 10px;
                    	height: auto;
                    	background-color: rgba(108, 117, 125, 0.8);
                    	border: 1px solid #888;
                    	text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
                    }

                    #psResetAllFiltersBtn:hover {
                    	background-color: rgba(90, 98, 104, 0.9);
                    }

                    /* Исключения */
                    .exclusionInputGroup {
                    	display: flex;
                    	align-items: stretch;
                    	border: 1px solid #555;
                    	border-radius: 4px;
                    	background-color: rgba(51, 51, 51, 0.85);
                    	overflow: hidden;
                    	height: 34px;
                    	flex-shrink: 0;
                    	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3);
                    }

                    .exclusionInputGroup #platiSearchExcludeInput {
                    	padding: 6px 10px;
                    	font-size: 13px;
                    	background-color: transparent;
                    	border: none;
                    	color: #eee;
                    	outline: none;
                    	border-radius: 0;
                    	flex-grow: 1;
                    	width: auto;
                    	height: auto;
                    }

                    .exclusionInputGroup #platiSearchExcludeInput:focus {
                    	box-shadow: none;
                    }

                    .exclusionInputGroup #platiSearchAddExcludeBtn {
                    	display: flex;
                    	align-items: center;
                    	justify-content: center;
                    	padding: 0 10px;
                    	background-color: #555;
                    	border: none;
                    	border-left: 1px solid #555;
                    	cursor: pointer;
                    	border-radius: 0;
                    	color: #eee;
                    	height: auto;
                    }

                    .exclusionInputGroup #platiSearchAddExcludeBtn:hover {
                    	background-color: #666;
                    }

                    .exclusionInputGroup #platiSearchAddExcludeBtn svg {
                    	width: 16px;
                    	height: 16px;
                    	fill: currentColor;
                    }

                    #platiExclusionTagsList {
                    	display: flex;
                    	flex-direction: row;
                    	flex-wrap: wrap;
                    	align-content: flex-start;
                    	gap: 8px;
                    	overflow-y: auto;
                    	flex-grow: 1;
                    }

                    .exclusionTag {
                    	display: inline-block;
                    	background-color: rgba(70, 70, 80, 0.9);
                    	color: #ddd;
                    	padding: 5px 10px;
                    	border-radius: 15px;
                    	font-size: 13px;
                    	cursor: pointer;
                    	transition: background-color 0.2s;
                    	border: 1px solid rgba(100, 100, 110, 0.9);
                    	white-space: nowrap;
                    	text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
                    }

                    .exclusionTag:hover {
                    	background-color: rgba(220, 53, 69, 0.9);
                    	border-color: rgba(200, 40, 50, 0.95);
                    	color: #fff;
                    }

                    .exclusionTag::after {
                    	content: ' ×';
                    	font-weight: bold;
                    	margin-left: 4px;
                    }

                    /* Результаты */
                    #platiSearchResultsContainer {
                    	position: relative;
                    	padding-left: ${PS_CONTENT_PADDING_LEFT}px;
                    	padding-right: ${PS_CONTENT_PADDING_RIGHT}px;
                    	margin-left: -${PS_CONTENT_PADDING_LEFT}px;
                    	margin-right: -${PS_CONTENT_PADDING_RIGHT}px;
                    }

                    #platiSearchResultsStatus {
                    	width: 100%;
                    	text-align: center;
                    	font-size: 18px;
                    	color: #aaa;
                    	padding: 50px 0;
                    	display: none;
                    	min-height: 100px;
                    	display: flex;
                    	align-items: center;
                    	justify-content: center;
                    	flex-direction: column;
                    }

                    #platiSearchResults {
                    	display: flex;
                    	flex-wrap: wrap;
                    	gap: 15px;
                    	justify-content: flex-start;
                    	padding-top: 10px;
                    }

                    /* Карточка товара */
                    .platiSearchItem {
                    	background-color: #2a2a30;
                    	border-radius: 8px;
                    	padding: 10px;
                    	width: calc(20% - 12px);
                    	min-width: 170px;
                    	display: flex;
                    	flex-direction: column;
                    	transition: transform 0.2s ease, box-shadow 0.2s ease;
                    	box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
                    	position: relative;
                    	color: #ccc;
                    	font-size: 13px;
                    	min-height: 340px;
                    	border: 1px solid transparent;
                    }

                    .platiSearchItem:hover {
                    	transform: translateY(-3px);
                    	box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
                    	border-color: #4b6f9c;
                    }

                    .platiSearchItem.hidden-by-filter {
                    	display: none !important;
                    }

                    .platiSearchItem a {
                    	text-decoration: none;
                    	color: inherit;
                    	display: flex;
                    	flex-direction: column;
                    	height: 100%;
                    }

                    .platiSearchItem .card-image-wrapper {
                    	position: relative;
                    	width: 100%;
                    	aspect-ratio: 1 / 1;
                    	margin-bottom: 8px;
                    	background-color: #444;
                    	border-radius: 6px;
                    	overflow: hidden;
                    }

                    .platiSearchItem img {
                    	position: absolute;
                    	top: 0;
                    	left: 0;
                    	width: 100%;
                    	height: 100%;
                    	object-fit: cover;
                    	border-radius: 6px;
                    }

                    .newItemBadge {
                    	position: absolute;
                    	top: 4px;
                    	left: 4px;
                    	background-color: #f54848;
                    	color: white;
                    	padding: 1px 5px;
                    	font-size: 10px;
                    	border-radius: 3px;
                    	font-weight: bold;
                    	z-index: 1;
                    	text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
                    }

                    .platiSearchItem .price {
                    	font-size: 16px;
                    	font-weight: 700;
                    	color: #a4d007;
                    	margin-bottom: 5px;
                    }

                    .platiSearchItem .title {
                    	font-size: 13px;
                    	font-weight: 500;
                    	line-height: 1.3;
                    	height: 3.9em;
                    	overflow: hidden;
                    	text-overflow: ellipsis;
                    	margin-bottom: 6px;
                    	color: #eee;
                    	display: -webkit-box;
                    	-webkit-line-clamp: 3;
                    	-webkit-box-orient: vertical;
                    }

                    .cardInfoContainer {
                    	margin-top: auto;
                    	padding-top: 6px;
                    }

                    .cardInfoRow1,
                    .cardInfoRow2 {
                    	display: flex;
                    	justify-content: space-between;
                    	flex-wrap: nowrap;
                    	gap: 8px;
                    	font-size: 12px;
                    	color: #bbb;
                    	margin-bottom: 4px;
                    }

                    .cardInfoRow1 span,
                    .cardInfoRow2 span {
                    	white-space: nowrap;
                    	overflow: hidden;
                    	text-overflow: ellipsis;
                    	flex-shrink: 1;
                    }

                    .cardInfoRow1 span:first-child,
                    .cardInfoRow2 span:first-child {
                    	flex-shrink: 0;
                    	margin-right: auto;
                    }

                    .reviewsGood {
                    	color: #6cff5c;
                    	font-weight: bold;
                    }

                    .reviewsBad {
                    	color: #f54848;
                    	margin-left: 2px;
                    	font-weight: bold;
                    }

                    .sales {
                    	font-weight: bold;
                    	color: #eee;
                    }

                    .sellerLink {
                    	display: block;
                    	font-size: 12px;
                    	color: #bbb;
                    	text-decoration: none;
                    	margin-bottom: 4px;
                    	white-space: nowrap;
                    	overflow: hidden;
                    	text-overflow: ellipsis;
                    	transition: color 0.2s;
                    }

                    .sellerLink:hover {
                    	color: #ddd;
                    	text-decoration: underline;
                    }

                    .platiSearchItem .buyButton {
                    	display: block;
                    	text-align: center;
                    	padding: 8px;
                    	margin-top: 8px;
                    	background-color: #007bff;
                    	color: white;
                    	border-radius: 4px;
                    	font-size: 13px;
                    	font-weight: 600;
                    	transition: background-color 0.2s;
                    }

                    .platiSearchItem .buyButton:hover {
                    	background-color: #0056b3;
                    }

                    /* Адаптивность */
                    @media (max-width: 1650px) {
                    	.platiSearchItem {
                    		width: calc(20% - 12px);
                    	}
                    }

                    @media (max-width: 1400px) {
                    	.platiSearchItem {
                    		width: calc(25% - 12px);
                    	}
                    }

                    @media (max-width: 1100px) {
                    	.platiSearchItem {
                    		width: calc(33.33% - 10px);
                    	}
                    }

                    @media (max-width: 850px) {

                    	#platiSearchFiltersPanel,
                    	#platiSearchExclusionTags {
                    		display: none;
                    	}

                    	#platiSearchHeader,
                    	#platiSearchResultsContainer {
                    		padding-left: 15px;
                    		padding-right: 15px;
                    		margin-left: 0;
                    		margin-right: 0;
                    	}

                    	.platiSearchItem {
                    		width: calc(50% - 8px);
                    	}

                    	#platiSearchHeader {
                    		justify-content: center;
                    	}
                    }

                    @media (max-width: 600px) {
                    	.platiSearchItem {
                    		width: 100%;
                    		min-height: auto;
                    	}

                    	#platiSearchHeader {
                    		gap: 5px;
                    	}

                    	.platiSearchInputContainer {
                    		flex-basis: 100%;
                    		order: -1;
                    	}

                    	.platiSearchBtn,
                    	#platiSearchCurrencySelect,
                    	#platiSearchAdvSortBtnContainer {
                    		width: calc(33.3% - 4px);
                    		font-size: 13px;
                    		padding: 8px 5px;
                    		height: 36px;
                    	}

                    	#platiSearchAdvSortBtnContainer {
                    		width: calc(33.3% - 4px);
                    	}

                    	#platiSearchAdvSortBtn {
                    		width: 100%;
                    	}

                    	#platiSearchAdvSortMenu {
                    		min-width: 200px;
                    		left: 50%;
                    		transform: translateX(-50%);
                    	}

                    	#platiResetSortBtn {
                    		width: auto;
                    		padding: 0 8px;
                    	}
                    }

                    /* Стили для кнопки Plati на странице Steam */
                    .plati_price_button .btnv6_blue_hoverfade {
                    	margin: 0;
                    	padding: 0 15px;
                    	font-size: 15px;
                    	display: flex;
                    	align-items: center;
                    	transition: filter 0.2s;
                    }

                    .plati_price_button .btnv6_blue_hoverfade:hover {
                    	filter: brightness(1.1);
                    }
                 `);
             }

            addPlatiStyles();
            const steamAppIdCheck = unsafeWindow.location.pathname.match(/\/app\/(\d+)/);
            if (steamAppIdCheck && steamAppIdCheck[1]) {
                addPlatiButton();
            }

        })();
    }

    }
})();