SpicyChat - Chat Editor

Customize SpicyChat AI appearance: widths, heights, fonts, text alignment

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         SpicyChat - Chat Editor
// @name:ru      SpicyChat - Редактор чата
// @namespace    https://github.com/bot286mpn/SpicyChat-ChatEditor
// @version      1.0.0
// @description  Customize SpicyChat AI appearance: widths, heights, fonts, text alignment
// @description:ru Настройте внешний вид SpicyChat AI: ширины, высоты, шрифты, выравнивание текста
// @author       YourName
// @match        https://spicychat.ai/chat/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // Защита от повторного запуска
    if (document.getElementById('spicychat-editor-active')) return;
    document.body.insertAdjacentHTML('beforeend', '<div id="spicychat-editor-active" style="display:none;"></div>');

    let currentSettings = null;
    let styleElement = null;
    let isPanelOpen = false;
    let isScriptEnabled = true;
    let currentProfileName = null;
    let profiles = {};
    let hasUnsavedChanges = false;

    // ФИКСИРОВАННЫЕ ОРИГИНАЛЬНЫЕ ЗНАЧЕНИЯ
    const ORIGINAL_VALUES = {
        CHAT_WIDTH: 800,        // px
        INPUT_WIDTH: 800,       // px
        TEXTAREA_MIN_HEIGHT: 11, // px
        TEXTAREA_MAX_HEIGHT: 200, // px - максимальная высота textarea
        CONTAINER_HEIGHT: 44,   // px - высота всего контейнера
        FONT_SIZE: 100,         // %
        FONT_FAMILY: 'Inter, system-ui, sans-serif'
    };

    // Дефолтные настройки
    const DEFAULT_SETTINGS = {
        chatWidth: 100,
        inputWidth: 100,
        inputHeight: 100,
        messageAlign: 'left',
        fontSize: 100,
        fontFamily: ORIGINAL_VALUES.FONT_FAMILY
    };

    // Применить стили с правильными селекторами и выравниванием
    function applyStyles() {
        if (!currentSettings || !isScriptEnabled) {
            if (styleElement) {
                styleElement.textContent = '';
            }
            return;
        }

        let css = '';
        console.log('Applying styles with settings:', currentSettings);

        // Ширина чата - расчет от фиксированного значения
        const newChatWidth = (ORIGINAL_VALUES.CHAT_WIDTH * currentSettings.chatWidth) / 100;

        css += `.w-full.flex.mb-lg.bg-transparent[style*="max-width: 800px"] {
            max-width: ${newChatWidth}px !important;
        }\n`;

        css += `.mb-lg.bg-transparent > div.flex.flex-col.gap-md.w-full {
            max-width: 100% !important;
            width: 100% !important;
        }\n`;

        // Ширина поля ввода - расчет от фиксированного значения
        const newInputWidth = (ORIGINAL_VALUES.INPUT_WIDTH * currentSettings.inputWidth) / 100;

        css += `.flex.justify-undefined.items-undefined.bg-transparent.w-full.right-0.pb-md.z-\\[1\\][style*="max-width: 800px"] {
            max-width: ${newInputWidth}px !important;
        }\n`;

        // ВЫСОТА ПОЛЯ ВВОДА - ТЕПЕРЬ В ПРОЦЕНТАХ
        if (currentSettings.inputHeight !== 100) {
            const heightMultiplier = currentSettings.inputHeight / 100;
            const newTextareaMinHeight = ORIGINAL_VALUES.TEXTAREA_MIN_HEIGHT * heightMultiplier;
            const newTextareaMaxHeight = ORIGINAL_VALUES.TEXTAREA_MAX_HEIGHT * heightMultiplier;
            const newContainerHeight = ORIGINAL_VALUES.CONTAINER_HEIGHT * heightMultiplier;

            // Основной textarea - ГЛАВНЫЙ ЭЛЕМЕНТ ДЛЯ ИЗМЕНЕНИЯ
            css += `textarea {
                min-height: ${newTextareaMinHeight}px !important;
                max-height: ${newTextareaMaxHeight}px !important;
                height: auto !important;
                align-self: flex-start !important;
                margin-top: 0 !important;
            }\n`;

            // Контейнер textarea (div с классами flex-grow max-h-[188px])
            css += `.flex-grow.max-h-\\[188px\\] {
                max-height: ${newTextareaMaxHeight}px !important;
                align-items: flex-start !important;
            }\n`;

            // Основной контейнер поля ввода
            css += `.w-full.border-1.border-solid.rounded-\\[13px\\].bg-gray-3 {
                min-height: ${newContainerHeight}px !important;
            }\n`;

            // Внутренний контейнер с кнопками - ИСПРАВЛЯЕМ ВЫРАВНИВАНИЕ
            css += `.flex.justify-between.items-end.py-sm.px-1.gap-0 {
                min-height: ${newContainerHeight - 16}px !important;
                align-items: flex-start !important;
            }\n`;

            // Контейнер с textarea и кнопками - ИСПРАВЛЯЕМ ВЫРАВНИВАНИЕ
            css += `.flex.flex-1.items-end.gap-1 {
                min-height: ${newTextareaMinHeight}px !important;
                align-items: flex-start !important;
            }\n`;

            // Дополнительные стили для правильного выравнивания
            css += `.flex.items-center.justify-center {
                align-items: flex-start !important;
            }\n`;

            // Исправляем выравнивание placeholder'а
            css += `textarea::placeholder {
                line-height: normal !important;
            }\n`;

        } else {
            // При 100% - возвращаем оригинальные стили
            css += `textarea {
                min-height: ${ORIGINAL_VALUES.TEXTAREA_MIN_HEIGHT}px !important;
                max-height: ${ORIGINAL_VALUES.TEXTAREA_MAX_HEIGHT}px !important;
                height: auto !important;
            }\n`;
            css += `.flex-grow.max-h-\\[188px\\] {
                max-height: ${ORIGINAL_VALUES.TEXTAREA_MAX_HEIGHT}px !important;
            }\n`;
            css += `.w-full.border-1.border-solid.rounded-\\[13px\\].bg-gray-3 {
                min-height: ${ORIGINAL_VALUES.CONTAINER_HEIGHT}px !important;
            }\n`;
        }

        // Стили для текста сообщений - ИСПРАВЛЕН КУРСИВ
        const textAlign = currentSettings.messageAlign === 'center' ? 'center' :
                         currentSettings.messageAlign === 'right' ? 'right' : 'left';

        // Базовый размер шрифта в пикселях (оригинальный размер)
        const baseFontSize = 16;

        // Рассчитываем новый размер шрифта
        const newFontSize = baseFontSize * (currentSettings.fontSize / 100);

        // ОБЩИЙ СТИЛЬ ДЛЯ ВСЕГО ТЕКСТА
        css += `div.mb-lg.bg-transparent span.leading-6,
                div.mb-lg.bg-transparent em,
                div.mb-lg.bg-transparent i,
                div.mb-lg.bg-transparent strong,
                div.mb-lg.bg-transparent b,
                div.mb-lg.bg-transparent u {
            font-size: ${newFontSize}px !important;
            font-family: ${currentSettings.fontFamily} !important;
            line-height: 1.5 !important;
        }\n`;

        // ДОПОЛНИТЕЛЬНЫЕ СТИЛИ ДЛЯ КУРСИВА - убираем все возможные влияния
        css += `div.mb-lg.bg-transparent em,
                div.mb-lg.bg-transparent i {
            font-style: italic !important;
            transform: none !important;
            scale: 1 !important;
            zoom: 1 !important;
            max-width: none !important;
            width: auto !important;
            transition: none !important;
            animation: none !important;
            display: inline !important;
            vertical-align: baseline !important;
        }\n`;

        // Специально для span внутри курсива (на случай вложенности)
        css += `div.mb-lg.bg-transparent em span,
                div.mb-lg.bg-transparent i span,
                div.mb-lg.bg-transparent em *,
                div.mb-lg.bg-transparent i * {
            font-size: inherit !important;
            transform: none !important;
            scale: 1 !important;
        }\n`;

        // Выравнивание текста
        css += `div.mb-lg.bg-transparent span.leading-6,
               div.mb-lg.bg-transparent em,
               div.mb-lg.bg-transparent i,
               div.mb-lg.bg-transparent strong,
               div.mb-lg.bg-transparent b,
               div.mb-lg.bg-transparent u {
            text-align: ${textAlign} !important;
        }\n`;

        // Удаление надписи
        css += `div.flex.flex-col.justify-center.items-center.gap-sm > p.text-label-md.font-regular.text-left.text-gray-11 {
            display: none !important;
        }\n`;

        if (!styleElement) {
            styleElement = document.createElement('style');
            styleElement.id = 'spicychat-custom-styles';
            document.head.appendChild(styleElement);
        }
        styleElement.textContent = css;
    }

    // === UI Функции ===
    const systemFonts = [
        ORIGINAL_VALUES.FONT_FAMILY,
        'Arial, sans-serif',
        'Verdana, sans-serif',
        'Tahoma, sans-serif',
        'Trebuchet MS, sans-serif',
        'Times New Roman, serif',
        'Georgia, serif',
        'Garamond, serif',
        'Courier New, monospace',
        'Impact, sans-serif',
        'Comic Sans MS, cursive',
        'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif'
    ];

    function saveProfiles() {
        try {
            GM_setValue('spicychat_profiles', JSON.stringify(profiles));
            GM_setValue('spicychat_current_profile', currentProfileName);
            GM_setValue('spicychat_script_enabled', isScriptEnabled);
        } catch (error) {
            console.error('SpicyChat Editor: Error saving profiles', error);
        }
    }

    function loadProfiles() {
        try {
            const savedProfiles = GM_getValue('spicychat_profiles', null);
            profiles = savedProfiles ? JSON.parse(savedProfiles) : {};

            // ИСПРАВЛЕНИЕ: проверяем и исправляем некорректные значения высоты
            Object.keys(profiles).forEach(profileName => {
                if (profiles[profileName].inputHeight < 100) {
                    profiles[profileName].inputHeight = 100;
                }
            });

            if (Object.keys(profiles).length === 0) {
                profiles['Оригинальные настройки'] = {...DEFAULT_SETTINGS};
                profiles['Мой профиль'] = {...DEFAULT_SETTINGS};
            }

            currentProfileName = GM_getValue('spicychat_current_profile', 'Профиль не выбран');
            isScriptEnabled = GM_getValue('spicychat_script_enabled', true);

            // Если выбран реальный профиль - загружаем его настройки
            if (currentProfileName !== 'Профиль не выбран' && profiles[currentProfileName]) {
                currentSettings = {...profiles[currentProfileName]};

                // Дополнительная проверка текущих настроек
                if (currentSettings.inputHeight < 100) {
                    currentSettings.inputHeight = 100;
                }
            } else {
                // Если "Профиль не выбран" - используем настройки по умолчанию
                currentSettings = {...DEFAULT_SETTINGS};
            }
        } catch (error) {
            console.error('SpicyChat Editor: Error loading profiles', error);
            profiles = {
                'Оригинальные настройки': {...DEFAULT_SETTINGS},
                'Мой профиль': {...DEFAULT_SETTINGS}
            };
            currentProfileName = 'Профиль не выбран';
            currentSettings = {...DEFAULT_SETTINGS};
            isScriptEnabled = true;
        }
    }

    function createButton() {
        const btn = document.createElement('div');
        btn.id = 'spicychat-editor-button';
        btn.innerHTML = isScriptEnabled ? '⚙️' : '🔴';
        btn.title = isScriptEnabled ? 'Настройки чата (включено)' : 'Настройки чата (выключено)';
        btn.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 40px;
            height: 40px;
            background: ${isScriptEnabled ? '#3182ce' : '#e53e3e'};
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            cursor: pointer;
            z-index: 10000;
            font-size: 18px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3);
            transition: transform 0.2s, background 0.2s;
        `;

        btn.addEventListener('mouseenter', () => {
            btn.style.transform = 'scale(1.1)';
            btn.style.background = isScriptEnabled ? '#2c5282' : '#c53030';
        });
        btn.addEventListener('mouseleave', () => {
            btn.style.transform = 'scale(1)';
            btn.style.background = isScriptEnabled ? '#3182ce' : '#e53e3e';
        });
        btn.addEventListener('click', togglePanel);

        document.body.appendChild(btn);
        return btn;
    }

    function updateButton() {
        const btn = document.getElementById('spicychat-editor-button');
        if (btn) {
            btn.innerHTML = isScriptEnabled ? '⚙️' : '🔴';
            btn.title = isScriptEnabled ? 'Настройки чата (включено)' : 'Настройки чата (выключено)';
            btn.style.background = isScriptEnabled ? '#3182ce' : '#e53e3e';
        }
    }

    function createPanel() {
        const panel = document.createElement('div');
        panel.id = 'spicychat-editor-panel';
        panel.style.cssText = `
            position: fixed;
            top: 10px;
            right: 10px;
            background: #2d3748;
            padding: 15px;
            border-radius: 8px;
            z-index: 9999;
            color: white;
            width: 400px;
            display: none;
            font-family: sans-serif;
            box-shadow: 0 4px 20px rgba(0,0,0,0.5);
            max-height: 85vh;
            overflow-y: auto;
        `;

        const createControl = (key, name, min, max, unit='%') => {
            const value = currentSettings[key];
            return `
                <div style="margin-bottom:15px;">
                    <label style="display:block; margin-bottom:5px; font-weight:bold;">${name}:</label>
                    <div style="display:flex; align-items:center; gap:10px;">
                        <input type="range" id="slider-${key}" min="${min}" max="${max}" value="${value}" style="flex:1;">
                        <input type="number" id="input-${key}" value="${value}" min="${min}" max="${max}" style="width:70px;">
                        <span>${unit}</span>
                    </div>
                </div>
            `;
        };

        const createFontFamilyControl = () => {
            let options = systemFonts.map(font =>
                `<option value="${font}" ${currentSettings.fontFamily === font ? 'selected' : ''}>${font.split(',')[0]}</option>`
            ).join('');
            return `
                <div style="margin-bottom:15px;">
                    <label style="display:block; margin-bottom:5px; font-weight:bold;">Семейство шрифтов:</label>
                    <select id="font-family" style="width:100%;padding:8px;border-radius:4px;background:#4a5568;color:white;border:1px solid #718096;">
                        ${options}
                    </select>
                </div>
            `;
        };

        const createProfilesControl = () => {
            let options = '<option value="Профиль не выбран"' + (currentProfileName === 'Профиль не выбран' ? ' selected' : '') + '>Профиль не выбран</option>';
            options += Object.keys(profiles).map(name =>
                `<option value="${name}" ${currentProfileName === name ? 'selected' : ''}>${name}</option>`
            ).join('');

            return `
                <div style="margin-bottom:15px;">
                    <label style="display:block; margin-bottom:5px; font-weight:bold;">Профиль настроек:</label>
                    <div style="display:flex; gap:5px; margin-bottom:10px;">
                        <select id="profile-select" style="flex:1;padding:8px;border-radius:4px;background:#4a5568;color:white;border:1px solid #718096;">
                            ${options}
                        </select>
                        <button id="btn-delete-profile" style="padding:8px 12px;background:#e53e3e;color:white;border:none;border-radius:4px;cursor:pointer;" title="Удалить профиль" ${currentProfileName === 'Профиль не выбран' ? 'disabled' : ''}>🗑️</button>
                    </div>
                    <div style="display:flex; gap:5px;">
                        <input type="text" id="new-profile-name" placeholder="Название профиля" style="flex:1;padding:8px;border-radius:4px;background:#4a5568;color:white;border:1px solid #718096;">
                        <button id="btn-save-profile" style="padding:8px 12px;background:#48bb78;color:white;border:none;border-radius:4px;cursor:pointer;">💾</button>
                    </div>
                </div>
            `;
        };

        panel.innerHTML = `
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;">
                <h3 style="margin:0;">Настройки чата</h3>
                <div style="display:flex; align-items:center; gap:10px;">
                    <label style="font-size:12px; color:#a0aec0;">Скрипт:</label>
                    <label class="switch">
                        <input type="checkbox" id="script-toggle" ${isScriptEnabled ? 'checked' : ''}>
                        <span class="slider round"></span>
                    </label>
                    <button id="btn-close" style="background:none; border:none; color:white; font-size:20px; cursor:pointer;">×</button>
                </div>
            </div>

            ${createProfilesControl()}

            <div style="margin-bottom:15px;">
                <label style="display:block; margin-bottom:5px; font-weight:bold;">Ширина чата:</label>
                <div style="display:flex; align-items:center; gap:10px;">
                    <input type="range" id="slider-chatWidth" min="50" max="200" value="${currentSettings.chatWidth}" style="flex:1;">
                    <input type="number" id="input-chatWidth" value="${currentSettings.chatWidth}" min="50" max="200" style="width:70px;">
                    <span>%</span>
                </div>
                <small style="color:#a0aec0; font-size:12px;">Оригинал: ${ORIGINAL_VALUES.CHAT_WIDTH}px (100%)</small>
            </div>

            <div style="margin-bottom:15px;">
                <label style="display:block; margin-bottom:5px; font-weight:bold;">Ширина поля ввода:</label>
                <div style="display:flex; align-items:center; gap:10px;">
                    <input type="range" id="slider-inputWidth" min="50" max="200" value="${currentSettings.inputWidth}" style="flex:1;">
                    <input type="number" id="input-inputWidth" value="${currentSettings.inputWidth}" min="50" max="200" style="width:70px;">
                    <span>%</span>
                </div>
                <small style="color:#a0aec0; font-size:12px;">Оригинал: ${ORIGINAL_VALUES.INPUT_WIDTH}px (100%)</small>
            </div>

            <div style="margin-bottom:15px;">
                <label style="display:block; margin-bottom:5px; font-weight:bold;">Высота поля ввода:</label>
                <div style="display:flex; align-items:center; gap:10px;">
                    <input type="range" id="slider-inputHeight" min="100" max="500" value="${currentSettings.inputHeight}" style="flex:1;">
                    <input type="number" id="input-inputHeight" value="${currentSettings.inputHeight}" min="100" max="500" style="width:70px;">
                    <span>%</span>
                </div>
                <small style="color:#a0aec0; font-size:12px;">Оригинал: ${ORIGINAL_VALUES.TEXTAREA_MIN_HEIGHT}px - ${ORIGINAL_VALUES.TEXTAREA_MAX_HEIGHT}px (100%)</small>
            </div>

            <div style="margin-bottom:15px;">
                <label style="display:block; margin-bottom:5px; font-weight:bold;">Выравнивание текста сообщений:</label>
                <select id="message-align" style="width:100%;padding:8px;border-radius:4px;background:#4a5568;color:white;border:1px solid #718096;">
                    <option value="left" ${currentSettings.messageAlign === 'left' ? 'selected' : ''}>По левому краю</option>
                    <option value="center" ${currentSettings.messageAlign === 'center' ? 'selected' : ''}>По центру</option>
                    <option value="right" ${currentSettings.messageAlign === 'right' ? 'selected' : ''}>По правому краю</option>
                </select>
            </div>

            <h3 style="margin:20px 0 15px 0;">Настройки шрифта</h3>

            <div style="margin-bottom:15px;">
                <label style="display:block; margin-bottom:5px; font-weight:bold;">Размер шрифта:</label>
                <div style="display:flex; align-items:center; gap:10px;">
                    <input type="range" id="slider-fontSize" min="50" max="200" value="${currentSettings.fontSize}" style="flex:1;">
                    <input type="number" id="input-fontSize" value="${currentSettings.fontSize}" min="50" max="200" style="width:70px;">
                    <span>%</span>
                </div>
                <small style="color:#a0aec0; font-size:12px;">Оригинал: 100% (максимум: 200%)</small>
            </div>

            ${createFontFamilyControl()}

            <div style="display:flex; gap:10px; margin-top:20px;">
                <button id="btn-apply" style="flex:1;background:#3182ce;color:white;padding:10px;border:none;border-radius:4px;cursor:pointer;font-weight:bold;">Применить</button>
                <button id="btn-reset" style="flex:1;background:#fc8181;color:white;padding:10px;border:none;border-radius:4px;cursor:pointer;font-weight:bold;">Сбросить</button>
            </div>
        `;

        const switchStyles = `
            .switch {
                position: relative;
                display: inline-block;
                width: 50px;
                height: 24px;
            }
            .switch input {
                opacity: 0;
                width: 0;
                height: 0;
            }
            .slider {
                position: absolute;
                cursor: pointer;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: #e53e3e;
                transition: .4s;
                border-radius: 24px;
            }
            .slider:before {
                position: absolute;
                content: "";
                height: 16px;
                width: 16px;
                left: 4px;
                bottom: 4px;
                background-color: white;
                transition: .4s;
                border-radius: 50%;
            }
            input:checked + .slider {
                background-color: #48bb78;
            }
            input:checked + .slider:before {
                transform: translateX(26px);
            }
        `;

        const style = document.createElement('style');
        style.textContent = switchStyles;
        panel.appendChild(style);

        document.body.appendChild(panel);
        setupPanelHandlers(panel);
    }

    function setupPanelHandlers(panel) {
        // Обработчики для всех слайдеров
        function setupSliderHandlers(key, unit = '%') {
            const slider = panel.querySelector(`#slider-${key}`);
            const input = panel.querySelector(`#input-${key}`);

            const updateValue = (val) => {
                const numVal = parseInt(val);
                if (!isNaN(numVal)) {
                    if (key === 'inputHeight' && numVal < 100) {
                        numVal = 100;
                    }
                    currentSettings[key] = numVal;
                    slider.value = numVal;
                    input.value = numVal;

                    // 1) При движении ползунков временно применяем стили
                    if (isScriptEnabled) {
                        applyStyles();
                        hasUnsavedChanges = true;
                    }
                }
            };

            slider.addEventListener('input', (e) => updateValue(e.target.value));
            input.addEventListener('input', (e) => updateValue(e.target.value));
        }

        ['chatWidth', 'inputWidth', 'inputHeight', 'fontSize'].forEach(key => setupSliderHandlers(key));

        // Выравнивание текста
        const messageAlign = panel.querySelector('#message-align');
        messageAlign.addEventListener('change', (e) => {
            currentSettings.messageAlign = e.target.value;
            if (isScriptEnabled) {
                applyStyles();
                hasUnsavedChanges = true;
            }
        });

        // Шрифт
        const fontFamily = panel.querySelector('#font-family');
        fontFamily.addEventListener('change', (e) => {
            currentSettings.fontFamily = e.target.value;
            if (isScriptEnabled) {
                applyStyles();
                hasUnsavedChanges = true;
            }
        });

        // Переключатель скрипта
        const scriptToggle = panel.querySelector('#script-toggle');
        scriptToggle.addEventListener('change', (e) => {
            isScriptEnabled = e.target.checked;
            updateButton();
            if (isScriptEnabled && hasUnsavedChanges) {
                applyStyles();
            } else if (!isScriptEnabled) {
                if (styleElement) {
                    styleElement.textContent = '';
                }
            }
            saveProfiles();
            showNotification(isScriptEnabled ? 'Скрипт включен' : 'Скрипт выключен', isScriptEnabled ? 'success' : 'info');
        });

        // Управление профилями
        const profileSelect = panel.querySelector('#profile-select');
        profileSelect.addEventListener('change', (e) => {
            const profileName = e.target.value;

            // 3) При сохранении настроек в профиль или выборе сохраненного профиля, черновик удаляется
            hasUnsavedChanges = false;

            currentProfileName = profileName;

            if (profileName === 'Профиль не выбран') {
                // Отключаем стили
                if (styleElement) {
                    styleElement.textContent = '';
                }
                currentSettings = {...DEFAULT_SETTINGS};
                // Обновляем кнопку удаления профиля
                const btnDeleteProfile = panel.querySelector('#btn-delete-profile');
                if (btnDeleteProfile) {
                    btnDeleteProfile.disabled = true;
                }
            } else {
                // Загружаем настройки профиля
                if (profiles[profileName]) {
                    currentSettings = {...profiles[profileName]};

                    if (currentSettings.inputHeight < 100) {
                        currentSettings.inputHeight = 100;
                    }

                    // Обновляем кнопку удаления профиля
                    const btnDeleteProfile = panel.querySelector('#btn-delete-profile');
                    if (btnDeleteProfile) {
                        btnDeleteProfile.disabled = false;
                    }

                    if (isScriptEnabled) {
                        applyStyles();
                    }
                }
            }
            updatePanelUI();
            saveProfiles();
        });

        const btnDeleteProfile = panel.querySelector('#btn-delete-profile');
        btnDeleteProfile.addEventListener('click', () => {
            if (currentProfileName === 'Профиль не выбран') return;

            if (confirm(`Удалить профиль "${currentProfileName}"?`)) {
                delete profiles[currentProfileName];
                // Переключаемся на "Профиль не выбран"
                currentProfileName = 'Профиль не выбран';
                currentSettings = {...DEFAULT_SETTINGS};
                updatePanelUI();
                // Отключаем стили
                if (styleElement) {
                    styleElement.textContent = '';
                }
                saveProfiles();
                showNotification('Профиль удален', 'info');
            }
        });

        const btnSaveProfile = panel.querySelector('#btn-save-profile');
        const newProfileName = panel.querySelector('#new-profile-name');
        btnSaveProfile.addEventListener('click', () => {
            const name = newProfileName.value.trim();
            if (!name) {
                showNotification('Введите название профиля', 'error');
                return;
            }
            profiles[name] = {...currentSettings};
            currentProfileName = name;
            newProfileName.value = '';
            // 3) Черновик удаляется при сохранении профиля
            hasUnsavedChanges = false;
            updatePanelUI();
            saveProfiles();
            showNotification(`Профиль "${name}" сохранен`, 'success');
        });

        // Кнопка "Применить"
        panel.querySelector('#btn-apply').addEventListener('click', () => {
            const profileNameInput = panel.querySelector('#new-profile-name');
            const profileName = profileNameInput.value.trim();

            if (profileName) {
                // Сохраняем как новый профиль
                profiles[profileName] = {...currentSettings};
                currentProfileName = profileName;
                profileNameInput.value = '';
                // 2) При нажатии кнопки применить стиль сохраняется как Черновик
                hasUnsavedChanges = true;
                updatePanelUI();
                saveProfiles();
                showNotification(`Профиль "${profileName}" сохранен и применен!`, 'success');
            } else {
                // 2) При нажатии кнопки применить стиль сохраняется как Черновик
                hasUnsavedChanges = true;
                if (isScriptEnabled) {
                    applyStyles();
                }
                showNotification('Настройки применены (черновик)!', 'success');
            }
        });

        // Кнопка "Сбросить"
        panel.querySelector('#btn-reset').addEventListener('click', () => {
            if (confirm('Сбросить настройки к оригинальным?')) {
                // 4) При нажатии кнопки Сброс, черновик просто удаляется
                hasUnsavedChanges = false;
                currentSettings = {...DEFAULT_SETTINGS};
                currentProfileName = 'Профиль не выбран';
                updatePanelUI();
                // Отключаем стили
                if (styleElement) {
                    styleElement.textContent = '';
                }
                saveProfiles();
                showNotification('Настройки сброшены!', 'info');
            }
        });

        panel.querySelector('#btn-close').addEventListener('click', togglePanel);
    }

    function updatePanelUI() {
        if (!isPanelOpen) return;

        const panel = document.getElementById('spicychat-editor-panel');
        if (!panel) return;

        ['chatWidth', 'inputWidth', 'inputHeight', 'fontSize'].forEach(key => {
            const val = currentSettings[key];
            const slider = panel.querySelector(`#slider-${key}`);
            const input = panel.querySelector(`#input-${key}`);
            if (slider) slider.value = val;
            if (input) input.value = val;
        });

        const messageAlign = panel.querySelector('#message-align');
        if (messageAlign) messageAlign.value = currentSettings.messageAlign;

        const fontFamily = panel.querySelector('#font-family');
        if (fontFamily) fontFamily.value = currentSettings.fontFamily;

        const scriptToggle = panel.querySelector('#script-toggle');
        if (scriptToggle) scriptToggle.checked = isScriptEnabled;

        // Обновляем список профилей и кнопку удаления
        const profileSelect = panel.querySelector('#profile-select');
        if (profileSelect) {
            let options = '<option value="Профиль не выбран"' + (currentProfileName === 'Профиль не выбран' ? ' selected' : '') + '>Профиль не выбран</option>';
            options += Object.keys(profiles).map(name =>
                `<option value="${name}" ${currentProfileName === name ? 'selected' : ''}>${name}</option>`
            ).join('');
            profileSelect.innerHTML = options;
        }

        const btnDeleteProfile = panel.querySelector('#btn-delete-profile');
        if (btnDeleteProfile) {
            btnDeleteProfile.disabled = currentProfileName === 'Профиль не выбран';
        }
    }

    function showNotification(message, type = 'info') {
        const notification = document.createElement('div');
        notification.textContent = message;
        notification.style.cssText = `
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: ${type === 'success' ? '#48bb78' : type === 'error' ? '#fc8181' : '#3182ce'};
            color: white;
            padding: 10px 20px;
            border-radius: 4px;
            z-index: 10001;
            font-weight: bold;
            box-shadow: 0 2px 10px rgba(0,0,0,0.3);
        `;

        document.body.appendChild(notification);

        setTimeout(() => {
            if (notification.parentNode) {
                notification.parentNode.removeChild(notification);
            }
        }, 2000);
    }

    function togglePanel() {
        const panel = document.getElementById('spicychat-editor-panel');

        if (!isPanelOpen) {
            if (!panel) createPanel();
            panel.style.display = 'block';
            updatePanelUI();
        } else {
            if (panel) panel.style.display = 'none';
        }
        isPanelOpen = !isPanelOpen;
    }

    // Закрытие панели при клике вне ее
    document.addEventListener('click', function(event) {
        const panel = document.getElementById('spicychat-editor-panel');
        const button = document.getElementById('spicychat-editor-button');

        if (isPanelOpen && panel && !panel.contains(event.target) &&
            button && !button.contains(event.target)) {
            togglePanel();
        }
    });

    // Запуск
    function init() {
        loadProfiles();
        createButton();
        // Применяем стили только если есть активный профиль
        if (currentProfileName !== 'Профиль не выбран' && isScriptEnabled) {
            applyStyles();
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();