Greasy Fork

Greasy Fork is available in English.

Discord Midjourney 参数可视化

在 Discord Midjourney 频道添加一个参数面板...

当前为 2025-05-23 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Discord Midjourney 参数可视化
// @namespace    https://github.com/cwser
// @version      1.0.2
// @description  在 Discord Midjourney 频道添加一个参数面板...
// @author       cwser
// @match        https://discord.com/*
// @grant        unsafeWindow
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
// 参数定义
    let params = {
        prompt: '',
        ar: '1:1',
        stylize: 100,
        weird: 0,
        chaos: 0,
        mode: 'standard',
        version: 'v7',
        speed: 'relax',
        draft: false,
        noPrompt: '',
        cref: [], // 每一项将是 { url: string, weight: string, enabled: boolean }
        sref: [], // 每一项将是 { url: string, weight: string, enabled: boolean }
        oref: [], // 每一项将是 { url: string, weight: string, enabled: boolean }
        iref: [], // iref 似乎未在UI中使用,但保留定义
        directImages: [], // 每一项将是 { url: string, weight: string, enabled: boolean }
        tile: false,
        seed: '',
        quality: 1,
        stop: 100,
        visibility: '',
        personalParams: '',
        r: 1,
        includeImagine: false // 用于控制是否添加 /imagine prompt: 前缀
    };

    // 主题相关变量
    let currentThemeMode = 'discord'; // 选项: 'light', 'dark', 'discord', 'system'
    const themeStorageKey = 'mjPanelThemePreference_v3'; // 更新存储键
    const themeModes = ['light', 'dark', 'discord', 'system'];
    const themeTextMap = {
        'light': '浅色模式',
        'dark': '深色模式',
        'discord': '跟随Discord',
        'system': '跟随系统'
    };
    const sunIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><circle cx="8" cy="8" r="4"/><path d="M8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zM1.61 4.032a.5.5 0 0 1 .707-.707L3.732 4.739a.5.5 0 1 1-.707.707L1.61 4.032zm12.056-.707a.5.5 0 0 1 .707.707l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414zM8 12a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2a.5.5 0 0 1 .5-.5zm-6.39.261a.5.5 0 0 1 .707.707L3.732 11.26a.5.5 0 0 1-.707-.707L1.61 11.968zm12.056.707a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1-.707.707l-1.414-1.414zM0 8a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1H.5A.5.5 0 0 1 0 8zm12 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/></svg>`;
    const moonIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/><path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.312 6.19l-1.162-.387a.217.217 0 0 1 0-.412l1.162.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774.258c.346.115.617-.386.732-.732L13.863.1z"/></svg>`;
    const discordIconSVG = `<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.488c-1.54-.83-3.263-1.463-5.086-1.854a.934.934 0 00-1.003.693c-.21 1.207-.662 2.343-1.204 3.392-2.816-.087-4.804-1.53-4.804-1.53s-.103.2-.186.377C7.659 7.992 7.136 9.31 7.136 9.31s-1.482-.532-2.884-1.318c0 0-1.19 3.204 2.42 6.03 0 0-1.806 1.27-3.68 1.744a17.56 17.56 0 003.032 1.22c1.45.463 2.938.717 4.465.717 1.526 0 3.016-.254 4.465-.717.046-.016.09-.03.135-.046l.004-.002c.03-.01.06-.018.09-.027.08-.026.157-.05.237-.078.068-.025.136-.05.203-.076.085-.034.17-.066.253-.1.07-.03.14-.06.208-.09.087-.04.173-.078.26-.118.062-.03.124-.06.185-.09.09-.046.18-.09.268-.14.06-.034.12-.07.178-.1.092-.05.183-.1.273-.156.053-.033.106-.065.158-.1.088-.055.175-.11.26-.17.046-.03.092-.06.137-.093.082-.06.163-.12.242-.185.04-.03.08-.06.118-.09.075-.062.148-.124.22-.188.035-.03.068-.06.103-.09.067-.06.132-.12.196-.183.026-.025.05-.05.076-.075.168-.16.33-.322.488-.488.093-.1.184-.2.27-.3.027-.03.053-.06.078-.09.13-.15.255-.3.375-.456.023-.03.046-.06.067-.09.102-.14.2-.28.293-.42.018-.028.036-.055.052-.083.078-.13.15-.26.218-.39.01-.02.02-.04.03-.06.06-.11.112-.22.162-.33.005-.01.01-.02.015-.03.044-.1.082-.19.118-.29.002-.006.004-.01.005-.016.03-.08.056-.16.08-.24.022-.07.04-.14.056-.21.015-.06.027-.12.038-.18.01-.05.018-.09.025-.14.006-.04.01-.08.014-.12.003-.03.005-.06.006-.09.002-.04.002-.07 0-.11s0-.03-.002-.045c-.06-1.597-.27-3.143-.62-4.618zm-4.603 7.06c-1.232 0-2.232-1.022-2.232-2.282s.998-2.282 2.232-2.282c1.232 0 2.232 1.022 2.232 2.282s-1.002 2.282-2.232 2.282zm-5.94-2.282c0 1.26.998 2.282 2.232 2.282s2.232-1.022 2.232-2.282S10.94 7.026 9.707 7.026c-1.232 0-2.232 1.022-2.232 2.282z"/></svg>`;
    const systemIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M5 4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H5zm-.5 7.5A.5.5 0 0 1 4 11V5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-.5.5H4.5z"/><path d="M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13zM1 3.5a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9z"/></svg>`;

    const themeIcons = {
        'light': sunIconSVG,
        'dark': moonIconSVG,
        'discord': discordIconSVG,
        'system': systemIconSVG
    };

    let systemThemeMediaQuery = null;
    let discordThemeObserver = null;

// 定义权重参数前缀的映射
    const weightPrefixes = {
        'cref': '--cw',
        'sref': '--sw',
        'oref': '--ow',
        'directImages': '--iw' // directImages 使用 --iw
    };

// 显示 Toast 提示
    function showToast(message) {
        const toast = document.createElement('div');
        toast.textContent = message;
        toast.className = 'mj-toast'; // 使用类进行样式化
        toast.style.cssText = `transform: translateY(-20px); opacity: 0;`; // 初始状态,CSS会覆盖
        document.body.appendChild(toast);
        // 触发入场动画
        setTimeout(() => { toast.style.transform = 'translateY(0)'; toast.style.opacity = '1'; }, 10);
        // 触发离场动画并在动画结束后移除
        setTimeout(() => {
            toast.style.transform = 'translateY(-20px)'; toast.style.opacity = '0';
            setTimeout(() => { if (document.body.contains(toast)) document.body.removeChild(toast); }, 300);
        }, 2000);
    }

// 创建设置按钮
    function createSettingButton() {
        const button = document.createElement('button');
        button.textContent = 'MJ参数';
        button.id = 'mj-floating-settings-button';
        button.addEventListener('click', toggleControlPanel);
        document.body.appendChild(button);
        button.addEventListener('mouseenter', () => button.style.transform = 'scale(1.05)');
        button.addEventListener('mouseleave', () => button.style.transform = 'scale(1)');
    }

// 切换控制面板显示/隐藏
    function toggleControlPanel() {
        const panel = document.getElementById('mj-control-panel');
        if (panel) {
            if (panel.style.display === 'none') {
                panel.style.display = 'block'; panel.style.opacity = '0'; panel.style.transform = 'translateY(10px)';
                setTimeout(() => { panel.style.opacity = '1'; panel.style.transform = 'translateY(0)'; }, 10); // 入场动画
            } else {
                const themeMenu = document.getElementById('theme-options-menu');
                if (themeMenu) themeMenu.style.display = 'none'; // 关闭主题菜单
                panel.style.opacity = '0'; panel.style.transform = 'translateY(10px)'; // 离场动画
                setTimeout(() => { panel.style.display = 'none'; }, 200); // 动画完成后隐藏
            }
        }
    }

// 重置参数为默认值
    function resetParams() {
        params = {
            prompt: '', ar: '1:1', stylize: 100, weird: 0, chaos: 0, mode: 'standard',
            version: 'v7', speed: 'relax', draft: false, noPrompt: '', cref: [],
            sref: [], oref: [], iref: [], directImages: [], tile: false, seed: '',
            quality: 1, stop: 100, visibility: '', personalParams: '', r: 1,
            includeImagine: false
        };
    }

// 更新最终的提示词参数字符串
    function updatePromptParams() {
        const { prompt, ar, stylize, weird, chaos, mode, draft, noPrompt, version, speed, tile, seed, quality, stop, visibility, personalParams, includeImagine } = params;
        // 直接从全局params对象获取数组,因为它们现在包含更多状态 (url, weight, enabled)
        const { cref, sref, oref, directImages } = params;

        const otherParts = [
            ar ? `--ar ${ar}` : '',
            `--s ${stylize}`, // 假设stylize总是有值,且其默认值100是期望的
            weird !== 0 ? `--w ${weird}` : '',
            chaos !== 0 ? `--c ${chaos}` : '',
            mode !== 'standard' ? `--${mode}` : '',
            draft ? '--draft' : '',
            noPrompt ? `--no ${noPrompt}` : '',
            version.startsWith('niji') ? `--niji ${version.replace('niji', '')}` : `--v ${version.replace('v', '')}`,
            speed ? `--${speed}` : '', // 假设 'relax' 是默认值,如果不想显示默认的relax,这里需要调整
            tile ? '--tile' : '',
            seed ? `--seed ${seed}` : '',
            quality !== 1 ? `--q ${quality}` : '',
            stop !== 100 ? `--stop ${stop}` : '',
            visibility ? `--${visibility}` : '',
            personalParams ? `--p ${personalParams}` : '',
            params.r > 1 ? `--r ${params.r}` : ''
        ].filter(Boolean);

        const formatImageWithWeight = (url, weightValue, prefix) => {
            const weightStr = (typeof weightValue === 'string' || typeof weightValue === 'number') ? String(weightValue).trim() : '';
            return `${url}${weightStr !== '' ? ` ${prefix} ${weightStr}` : ''}`;
        };

        const directImageUrls = directImages
            .filter(item => item.enabled) // 只包含启用的
            .map(item => formatImageWithWeight(item.url, item.weight, '--iw'))
            .join(' ');

        const crefUrls = cref
            .filter(item => item.enabled)
            .map(item => `--cref ${formatImageWithWeight(item.url, item.weight, '--cw')}`);

        const srefUrls = sref
            .filter(item => item.enabled)
            .map(item => `--sref ${formatImageWithWeight(item.url, item.weight, '--sw')}`);

        const orefUrls = oref
            .filter(item => item.enabled)
            .map(item => `--oref ${formatImageWithWeight(item.url, item.weight, '--ow')}`);

        const promptField = document.getElementById('prompt-params');
        if (promptField) {
            const allParts = [
                directImageUrls,
                prompt.trim(),
                ...crefUrls,
                ...srefUrls,
                ...orefUrls,
                ...otherParts
            ].filter(Boolean);

            let finalPromptString = allParts.join(' ').trim().replace(/\s+/g, ' '); // 规范化空格
            if (includeImagine && finalPromptString) {
                finalPromptString = `/imagine prompt: ${finalPromptString}`;
            }
            promptField.value = finalPromptString;
        }
    }


    // 获取实际生效的暗黑模式状态
    function getEffectiveDarkModeState() {
        switch (currentThemeMode) {
            case 'light': return false;
            case 'dark': return true;
            case 'discord': return document.documentElement.classList.contains('theme-dark');
            case 'system':
                return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
            default:
                return document.documentElement.classList.contains('theme-dark');
        }
    }

    // 应用当前主题
    function applyCurrentTheme() {
        const panel = document.getElementById('mj-control-panel');
        if (!panel) return;

        const effectiveDarkMode = getEffectiveDarkModeState();
        panel.classList.toggle('dark-mode', effectiveDarkMode);
        localStorage.setItem(themeStorageKey, currentThemeMode);

        const themeTriggerButton = document.getElementById('theme-dropdown-trigger');
        const themeTriggerIcon = document.getElementById('theme-trigger-icon');
        const themeTriggerText = document.getElementById('theme-trigger-text');

        if (themeTriggerIcon) {
            let iconToShow = themeIcons[currentThemeMode] || sunIconSVG;
            if (currentThemeMode === 'discord' || currentThemeMode === 'system') {
                iconToShow = effectiveDarkMode ? moonIconSVG : sunIconSVG;
            }
            themeTriggerIcon.innerHTML = iconToShow;
        }
        if (themeTriggerText) {
            themeTriggerText.textContent = themeTextMap[currentThemeMode] || '未知主题';
        }
        if (themeTriggerButton) {
            themeTriggerButton.title = `切换主题 (当前: ${themeTextMap[currentThemeMode]})`;
        }

        const themeOptions = document.querySelectorAll('#theme-options-menu button');
        themeOptions.forEach(opt => {
            opt.classList.toggle('active', opt.dataset.theme === currentThemeMode);
        });

        refreshPreviews(); // 主题变化时也刷新预览,确保预览内控件样式正确
        setInitialActiveButtons();
        updateToggleVisuals('tile-toggle-switch', 'tile');
        updateToggleVisuals('draft-toggle-switch', 'draft');
        updateToggleVisuals('imagine-toggle-switch', 'includeImagine');
        setupDynamicThemeListeners();
    }

    // 处理系统主题变化
    function handleSystemThemeChange() {
        if (currentThemeMode === 'system') applyCurrentTheme();
    }

    // 处理Discord主题变化
    function handleDiscordThemeChange(mutationsList) {
         if (currentThemeMode === 'discord') {
            for (const mutation of mutationsList) {
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    applyCurrentTheme();
                    break;
                }
            }
        }
    }

    // 设置动态主题监听器
    function setupDynamicThemeListeners() {
        if (systemThemeMediaQuery) {
            systemThemeMediaQuery.removeEventListener ? systemThemeMediaQuery.removeEventListener('change', handleSystemThemeChange) : systemThemeMediaQuery.removeListener(handleSystemThemeChange);
            systemThemeMediaQuery = null;
        }
        if (discordThemeObserver) {
            discordThemeObserver.disconnect();
            discordThemeObserver = null;
        }

        if (currentThemeMode === 'system' && window.matchMedia) {
            systemThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
            systemThemeMediaQuery.addEventListener ? systemThemeMediaQuery.addEventListener('change', handleSystemThemeChange) : systemThemeMediaQuery.addListener(handleSystemThemeChange);
        } else if (currentThemeMode === 'discord' && typeof MutationObserver !== "undefined") {
            discordThemeObserver = new MutationObserver(handleDiscordThemeChange);
            discordThemeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
        }
    }

// 创建控制面板HTML结构
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.id = 'mj-control-panel';
        panel.style.cssText = `
            display: none; position: fixed; right: 20px; bottom: 80px;
            width: 1080px; max-width: calc(100% - 40px);
            border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
            padding: 20px; z-index: 10000; border: 1px solid #E5E7EB;
            max-height: 90vh; overflow-y: auto; font-family: sans-serif;
            transition: opacity 0.2s ease, transform 0.2s ease;
        `;
        panel.innerHTML = `
            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:20px;">
                <h3 class="panel-title" style="margin:0; font-size:18px; font-weight:600;">Midjourney 参数设置</h3>
                <div class="panel-divider" style="flex:1; height:1px; margin:0 16px;"></div>
                <div style="position:relative;"> <button id="theme-dropdown-trigger" title="切换主题模式" class="theme-trigger-btn">
                        <span id="theme-trigger-icon" style="display: inline-flex; align-items: center; margin-right: 6px;"></span>
                        <span id="theme-trigger-text"></span>
                    </button>
                    <div id="theme-options-menu" class="theme-options-menu" style="display:none;">
                        <button data-theme="light" class="theme-option-button">${themeIcons.light} ${themeTextMap.light}</button>
                        <button data-theme="dark" class="theme-option-button">${themeIcons.dark} ${themeTextMap.dark}</button>
                        <button data-theme="discord" class="theme-option-button">${themeIcons.discord} ${themeTextMap.discord}</button>
                        <button data-theme="system" class="theme-option-button">${themeIcons.system} ${themeTextMap.system}</button>
                    </div>
                </div>
            </div>
            <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap:20px;">
                <div class="panel-section">
                    <p class="section-title">图片尺寸 (--ar)</p>
                    <div style="display:flex; align-items:center; gap:20px;">
                        <div style="position:relative; width:100px; height:100px;">
                            <div id="ratio-preview-bg" class="ratio-preview-bg"></div>
                            <div id="ratio-preview" style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:100px; height:100px;">
                                <div id="ratio-box" class="ratio-box">1:1</div>
                            </div>
                        </div>
                        <div style="flex:1;">
                            <div id="size-buttons" style="display:flex; gap:8px; margin-bottom:8px;"></div>
                            <input type="range" id="ratio-slider" min="0" max="10" value="5" style="width:100%;">
                        </div>
                    </div>
                </div>
                <div class="panel-section">
                    <p class="section-title">美学参数</p>
                    <div style="display:flex; flex-direction:column; gap:12px;">
                        <div style="display:flex; align-items:center; justify-content:space-between;">
                            <label for="stylize" style="flex:1; margin-right:12px;">风格化 (--s)</label>
                            <input type="range" id="stylize" name="stylize" min="0" max="1000" value="100" step="50" style="flex:3;">
                            <span id="stylize-value" class="param-value-display" style="width:40px; text-align:right;">100</span>
                        </div>
                        <div style="display:flex; align-items:center; justify-content:space-between;">
                            <label for="weird" style="flex:1; margin-right:12px;">奇特化 (--w)</label>
                            <input type="range" id="weird" name="weird" min="0" max="3000" value="0" step="100" style="flex:3;">
                            <span id="weird-value" class="param-value-display" style="width:40px; text-align:right;">0</span>
                        </div>
                        <div style="display:flex; align-items:center; justify-content:space-between;">
                            <label for="chaos" style="flex:1; margin-right:12px;">多样性 (--c)</label>
                            <input type="range" id="chaos" name="chaos" min="0" max="100" value="0" step="5" style="flex:3;">
                            <span id="chaos-value" class="param-value-display" style="width:40px; text-align:right;">0</span>
                        </div>
                    </div>
                </div>
                <div class="panel-section" style="display: flex; flex-direction: column; gap: 10px;">
                    <p class="section-title">模型设置</p>
                    <div style="display:flex; gap:10px; align-items:center;">
                        <label style="flex:1;">速度
                            <div class="btn-group">
                                <button data-value="relax" class="speed-btn">标准</button>
                                <button data-value="fast" class="speed-btn">快速</button>
                                <button data-value="turbo" class="speed-btn">极速</button>
                            </div>
                        </label>
                        <label style="flex:1;">模式
                            <div class="btn-group">
                                <button data-value="standard" class="mode-btn">标准</button>
                                <button data-value="raw" class="mode-btn">原始</button>
                            </div>
                        </label>
                    </div>
                    <div style="display:flex; gap:10px; align-items:center;">
                        <label style="flex:1;">草稿 (--draft)
                            <div class="toggle-switch" id="draft-toggle-switch">
                                <div class="toggle-dot"></div>
                            </div>
                        </label>
                        <label for="version-select" style="flex:2;">版本 (--v, --niji)
                            <select id="version-select" name="version-select">
                                <option value="v7">v7</option> <option value="v6.1">v6.1</option> <option value="v6">v6</option>
                                <option value="v5.2">v5.2</option> <option value="v5.1">v5.1</option> <option value="v5">v5</option>
                                <option value="v4">v4</option> <option value="v3">v3</option> <option value="v2">v2</option>
                                <option value="v1">v1</option> <option value="niji6">niji6</option> <option value="niji5">niji5</option>
                                <option value="niji4">niji4</option>
                            </select>
                        </label>
                    </div>
                </div>
                <div class="panel-section">
                    <p class="section-title">角色参考 (--cref)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="cref-url" placeholder="粘贴角色图片URL"><input type="number" id="cref-weight" placeholder="权重 (--cw) 0-100">
                    </div>
                    <button id="cref-add" class="action-button">添加</button>
                    <div id="cref-preview" class="ref-preview-container"></div>
                </div>
                <div class="panel-section">
                    <p class="section-title">风格参考 (--sref)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                         <input type="text" id="sref-url" placeholder="图片URL, 'random'或数字码"><input type="number" id="sref-weight" placeholder="权重 (--sw) 0-100">
                    </div>
                    <button id="sref-add" class="action-button">添加</button>
                    <div id="sref-preview" class="ref-preview-container"></div>
                </div>
                <div class="panel-section">
                    <p class="section-title">全方位参考 (--oref)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="oref-url" placeholder="粘贴全方位参考图片URL"><input type="number" id="oref-weight" placeholder="权重 (--ow) 0-1000">
                    </div>
                    <button id="oref-add" class="action-button">添加</button>
                    <div id="oref-preview" class="ref-preview-container"></div>
                </div>
                <div class="panel-section">
                    <p class="section-title">图像参考 (URL --iw)</p>
                    <div style="display:flex; gap:8px; margin-bottom:8px;">
                        <input type="text" id="direct-image-url" placeholder="粘贴图像URL"><input type="number" id="direct-image-weight" placeholder="权重 (--iw) 0-3">
                    </div>
                    <button id="direct-image-add" class="action-button">添加</button>
                    <div id="direct-image-preview" class="ref-preview-container"></div>
                </div>
                <div class="panel-section" style="grid-column: span 2;">
                    <p class="section-title">更多参数</p>
                    <div style="display:grid; grid-template-columns: 1fr 1fr; gap:16px;">
                        <div>
                            <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                                <div class="toggle-switch" id="tile-toggle-switch"><div class="toggle-dot"></div></div>
                                <label>重复图案 (--tile)</label>
                            </div>
                            <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                                <label for="seed-input">种子 (--seed)</label>
                                <input type="number" id="seed-input" name="seed-input" placeholder="0-4294967295" min="0" max="4294967295">
                            </div>
                            <div style="display:flex; align-items:center; gap:8px; margin-bottom:16px;">
                                <label for="personal-params">个性化 (--p)</label>
                                <input type="text" id="personal-params" name="personal-params" placeholder="输入个性化参数">
                            </div>
                        </div>
                        <div>
                            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
                                <label for="quality-slider">质量 (--q)</label>
                                <input type="range" id="quality-slider" name="quality-slider" min="0" max="4" step="1" value="2"><span id="quality-value" class="param-value-display">1</span>
                            </div>
                            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
                                <label for="stop-slider">停止 (--stop)</label>
                                <input type="range" id="stop-slider" name="stop-slider" min="10" max="100" step="1" value="100"><span id="stop-value" class="param-value-display">100</span>
                            </div>
                             <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
                                <label for="r-slider">批量任务 (--r)</label>
                                <input type="range" id="r-slider" name="r-slider" min="1" max="10" value="1"><span id="r-value" class="param-value-display">1</span>
                            </div>
                        </div>
                    </div>
                     <p class="section-title" style="margin-top:10px;">可见性 (--public, --stealth)</p>
                    <div class="btn-group"> <button data-value="" class="visibility-btn">默认</button>
                        <button data-value="public" class="visibility-btn">公开</button>
                        <button data-value="stealth" class="visibility-btn">隐身</button>
                    </div>
                </div>
            </div>
            <div style="margin-top:20px; border-top:1px solid; padding-top:16px;" class="results-section-divider">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
                    <p class="section-title" style="margin:0;">最终参数</p>
                    <div style="display:flex; align-items:center; gap:8px;">
                        <label for="imagine-toggle-switch" style="font-size: 13px; user-select:none; cursor:pointer;" class="imagine-label">添加 /imagine</label>
                        <div class="toggle-switch" id="imagine-toggle-switch">
                            <div class="toggle-dot"></div>
                        </div>
                    </div>
                </div>
                <div style="display:flex; gap:10px;">
                    <div style="flex:1;">
                        <p class="section-title">提示词</p>
                        <textarea id="main-prompt" placeholder="输入主要提示词..."></textarea>
                    </div>
                    <div style="flex:1;">
                        <p class="section-title">排除词 (--no)</p>
                        <textarea id="no-prompt" placeholder="输入需要排除的元素,多个用空格分隔"></textarea>
                    </div>
                    <div style="flex:1;">
                        <textarea id="prompt-params" readonly style="margin-top:27.5px;"></textarea>
                    </div>
                </div>
            </div>
            <div style="margin-top:16px; display:flex; gap:10px;">
                <button id="copy-btn" class="action-button-primary">拷贝参数</button>
                <button id="clear-btn" class="action-button-secondary">清空参数</button>
            </div>
        `;
        document.body.appendChild(panel);

        const savedTheme = localStorage.getItem(themeStorageKey);
        if (savedTheme && themeModes.includes(savedTheme)) {
            currentThemeMode = savedTheme;
        } else {
            currentThemeMode = 'discord'; // 默认跟随Discord
        }

        bindControlEvents();
        applyCurrentTheme(); // 初始化时应用主题

        // 点击面板外部关闭主题菜单
        document.addEventListener('click', function(event) {
            const themeMenu = document.getElementById('theme-options-menu');
            const themeTrigger = document.getElementById('theme-dropdown-trigger');
            if (themeMenu && themeTrigger && themeMenu.style.display === 'block') {
                if (!themeMenu.contains(event.target) && !themeTrigger.contains(event.target)) {
                    themeMenu.style.display = 'none';
                }
            }
        });
    }

    function setInitialActiveButtons() {
        const buttonGroups = [
            { className: 'speed-btn', param: 'speed', defaultValue: 'relax' },
            { className: 'mode-btn', param: 'mode', defaultValue: 'standard' },
            { className: 'visibility-btn', param: 'visibility', defaultValue: '' }
        ];
        buttonGroups.forEach(group => {
            const buttons = document.querySelectorAll(`#mj-control-panel .${group.className}`);
            let currentParamValue = params[group.param] === undefined ? group.defaultValue : params[group.param];
            buttons.forEach(btn => {
                btn.classList.toggle('active', btn.dataset.value === currentParamValue);
            });
        });
        // 确保比例滑块在初始化时触发input事件来更新预览和参数
        const ratioSlider = document.getElementById('ratio-slider');
        if (ratioSlider) ratioSlider.dispatchEvent(new Event('input'));
    }

    function updateToggleVisuals(switchId, property) {
        const switchEl = document.getElementById(switchId);
        if (!switchEl) return;
        // 确保 params[property] 是布尔值进行比较
        switchEl.classList.toggle('active', !!params[property]);
    }

    const setupRefSection = (idPrefix, paramKey) => {
        const $ = id => document.getElementById(id);
        const addBtn = $(`${idPrefix}-add`);
        const urlInput = $(`${idPrefix}-url`);
        const weightInput = $(`${idPrefix}-weight`); // 这是用于添加新条目的权重输入框
        const previewContainerId = `${idPrefix}-preview`;

        if (!addBtn || !urlInput || !weightInput) return;

        addBtn.onclick = () => {
            const url = urlInput.value.trim();
            const weight = weightInput.value.trim(); // 新条目的初始权重
            let toastMessage = `请输入${paramKey === 'sref' ? 'URL或代码' : 'URL'}`;
            if (!url) { showToast(toastMessage); return; }

            const isImageUrl = /^https?:\/\/.+\.(jpg|jpeg|png|webp|gif|svg|bmp|tiff|ico)(\?.*)?$/i.test(url);
            const isSrefCode = paramKey === 'sref' && (/^\d+$/.test(url) || url.toLowerCase() === 'random');

            if (paramKey !== 'sref' && !isImageUrl) { showToast('请输入有效的图片URL'); return; }
            if (paramKey === 'sref' && !isImageUrl && !isSrefCode) { showToast("sref请输入有效图片URL, 'random'或数字代码"); return; }

            const targetArray = params[paramKey];
            if (!Array.isArray(targetArray)) return; // 应该不会发生

            const itemUrl = (paramKey === 'sref' && isSrefCode) ? (url.toLowerCase() === 'random' ? 'random' : url) : url;

            if (!targetArray.some(item => item.url === itemUrl)) {
                const newItem = { url: itemUrl, weight: weight, enabled: true }; // 添加 enabled 状态
                targetArray.push(newItem);

                const currentWeightPrefix = weightPrefixes[paramKey];
                if (paramKey === 'sref' && isSrefCode) {
                    addPreviewSrefCode(previewContainerId, newItem, paramKey); // 传递整个 newItem 对象
                } else {
                    addPreviewImage(previewContainerId, newItem, paramKey, currentWeightPrefix); // 传递整个 newItem 对象
                }
                urlInput.value = ''; weightInput.value = ''; // 清空外部输入框
                updatePromptParams();
            } else {
                showToast(`该${(paramKey === 'sref' && isSrefCode) ? '代码' : 'URL'}已添加`);
            }
        };
    };


    function bindControlEvents() {
        const $ = id => document.getElementById(id);

        // 主题切换
        const themeTriggerButton = $('theme-dropdown-trigger');
        const themeOptionsMenu = $('theme-options-menu');
        if (themeTriggerButton && themeOptionsMenu) {
            themeTriggerButton.addEventListener('click', (event) => {
                event.stopPropagation(); // 防止触发 document 的 click 事件
                themeOptionsMenu.style.display = themeOptionsMenu.style.display === 'none' ? 'block' : 'none';
            });

            document.querySelectorAll('.theme-option-button').forEach(button => {
                button.addEventListener('click', () => {
                    currentThemeMode = button.dataset.theme;
                    applyCurrentTheme();
                    themeOptionsMenu.style.display = 'none'; // 关闭菜单
                });
            });
        }


        if ($('main-prompt')) $('main-prompt').oninput = e => { params.prompt = e.target.value; updatePromptParams(); };

        const bindSliderEvent = (id, property, displayId = null, isFloat = false) => {
            const slider = $(id); if (!slider) return;
            slider.oninput = e => {
                const value = isFloat ? parseFloat(e.target.value) : parseInt(e.target.value, 10);
                params[property] = value;
                if (displayId && $(displayId)) $(displayId).textContent = e.target.value;
                updatePromptParams();
            };
        };
        bindSliderEvent('stylize', 'stylize', 'stylize-value');
        bindSliderEvent('weird', 'weird', 'weird-value');
        bindSliderEvent('chaos', 'chaos', 'chaos-value');
        bindSliderEvent('stop-slider', 'stop', 'stop-value');
        bindSliderEvent('r-slider', 'r', 'r-value');

        const qualitySlider = $('quality-slider'); const qualityValueDisplay = $('quality-value');
        const qualityMap = [0.25, 0.5, 1, 2, 4];
        if (qualitySlider && qualityValueDisplay) {
            // 初始化
            const initialQualityValue = params.quality;
            const initialSliderIndex = qualityMap.indexOf(initialQualityValue);
            if (initialSliderIndex !== -1) {
                qualitySlider.value = initialSliderIndex;
                qualityValueDisplay.textContent = initialQualityValue;
            } else { // 如果 params.quality 不是预设值,则重置为1
                params.quality = 1;
                qualitySlider.value = qualityMap.indexOf(1); // Should be 2
                qualityValueDisplay.textContent = params.quality;
            }

            qualitySlider.oninput = e => {
                const sliderIndex = parseInt(e.target.value, 10);
                if (sliderIndex >= 0 && sliderIndex < qualityMap.length) {
                    params.quality = qualityMap[sliderIndex];
                    if (qualityValueDisplay) qualityValueDisplay.textContent = params.quality;
                    updatePromptParams();
                }
            };
        }


        const bindRadioGroup = (groupClass, property) => {
            document.querySelectorAll(`#mj-control-panel .${groupClass}`).forEach(btn => {
                btn.addEventListener('click', () => {
                    document.querySelectorAll(`#mj-control-panel .${groupClass}`).forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    params[property] = btn.dataset.value;
                    updatePromptParams();
                });
            });
        };
        bindRadioGroup('speed-btn', 'speed');
        bindRadioGroup('mode-btn', 'mode');
        bindRadioGroup('visibility-btn', 'visibility');

        const bindToggleSwitchEvent = (switchId, property) => {
            const switchEl = $(switchId); if (!switchEl) return;
            switchEl.addEventListener('click', () => {
                params[property] = !params[property];
                updateToggleVisuals(switchId, property); // 更新视觉
                updatePromptParams();
            });
        };
        bindToggleSwitchEvent('tile-toggle-switch', 'tile');
        bindToggleSwitchEvent('draft-toggle-switch', 'draft');
        bindToggleSwitchEvent('imagine-toggle-switch', 'includeImagine');


        if ($('version-select')) $('version-select').onchange = e => { params.version = e.target.value; updatePromptParams(); };
        if ($('no-prompt')) $('no-prompt').oninput = e => { params.noPrompt = e.target.value.trim(); updatePromptParams(); };

        if ($('copy-btn')) {
            $('copy-btn').onclick = () => {
                const textarea = $('prompt-params');
                if (!textarea || !textarea.value) { showToast('没有参数可以拷贝'); return; }
                textarea.select();
                try {
                    if (navigator.clipboard && navigator.clipboard.writeText) {
                        navigator.clipboard.writeText(textarea.value)
                            .then(() => showToast('参数已复制!'))
                            .catch(() => { showToast('复制失败!请尝试手动复制。'); legacyCopy(textarea); });
                    } else {
                        legacyCopy(textarea); // 兼容旧版浏览器
                    }
                } catch (err) {
                    console.error('复制尝试失败:', err);
                    // showToast('复制异常!请尝试手动复制。'); // 已经在 legacyCopy 中处理
                }
            };
        }
        function legacyCopy(textareaElement) {
            try {
                const successful = document.execCommand('copy');
                showToast(successful ? '参数已复制 (兼容模式)!' : '复制失败 (兼容模式)!请手动复制。');
            } catch (err) {
                showToast('复制异常 (兼容模式)!请手动复制。');
            }
        }


        const sizeMap = ['1:2', '9:16', '2:3', '3:4', '5:6', '1:1', '6:5', '4:3', '3:2', '16:9', '2:1'];
        if ($('clear-btn')) {
            $('clear-btn').onclick = () => {
                resetParams(); // 重置数据模型
                // 更新UI元素以反映重置后的默认值
                if ($('main-prompt')) $('main-prompt').value = params.prompt;
                if ($('stylize')) $('stylize').value = params.stylize; if ($('stylize-value')) $('stylize-value').textContent = params.stylize;
                if ($('weird')) $('weird').value = params.weird; if ($('weird-value')) $('weird-value').textContent = params.weird;
                if ($('chaos')) $('chaos').value = params.chaos; if ($('chaos-value')) $('chaos-value').textContent = params.chaos;
                if ($('version-select')) $('version-select').value = params.version;
                if ($('no-prompt')) $('no-prompt').value = params.noPrompt;

                if ($('ratio-slider')) { // 更新比例滑块和预览
                    const defaultRatioIndex = sizeMap.indexOf(params.ar);
                    $('ratio-slider').value = defaultRatioIndex !== -1 ? defaultRatioIndex : 5; // 5 is '1:1'
                    $('ratio-slider').dispatchEvent(new Event('input')); // 触发更新
                }
                // 清空参考URL和权重的输入框
                ['cref-url', 'cref-weight', 'sref-url', 'sref-weight', 'oref-url', 'oref-weight', 'direct-image-url', 'direct-image-weight']
                    .forEach(id => { if ($(id)) $(id).value = ''; });
                if ($('seed-input')) $('seed-input').value = params.seed;

                // 更新质量滑块
                if ($('quality-slider')) {
                    const resetSliderIndex = qualityMap.indexOf(params.quality); // params.quality is 1
                     $('quality-slider').value = resetSliderIndex !== -1 ? resetSliderIndex : qualityMap.indexOf(1); // index for 1 is 2
                     const qvDisplay = $('quality-value');
                     if(qvDisplay) qvDisplay.textContent = params.quality;
                }
                if ($('stop-slider')) $('stop-slider').value = params.stop; if ($('stop-value')) $('stop-value').textContent = params.stop;
                if ($('personal-params')) $('personal-params').value = params.personalParams;
                if ($('r-slider')) $('r-slider').value = params.r; if ($('r-value')) $('r-value').textContent = params.r;

                // 更新所有切换开关的视觉状态
                updateToggleVisuals('tile-toggle-switch', 'tile');
                updateToggleVisuals('draft-toggle-switch', 'draft');
                updateToggleVisuals('imagine-toggle-switch', 'includeImagine');
                setInitialActiveButtons(); // 重置按钮组状态
                refreshPreviews(); // 清空并重建所有参考图预览
                updatePromptParams(); // 更新最终参数显示
                showToast('所有参数已重置为默认值');
            };
        }

        setupRefSection('cref', 'cref');
        setupRefSection('sref', 'sref');
        setupRefSection('oref', 'oref');
        setupRefSection('direct-image', 'directImages');


        const ratioPresets = { '1:2': { width: 50, height: 100 }, '9:16': { width: 56.25, height: 100 }, '2:3': { width: 66.67, height: 100 }, '3:4': { width: 75, height: 100 }, '5:6': { width: 83.33, height: 100 }, '1:1': { width: 100, height: 100 }, '6:5': { width: 100, height: 83.33 }, '4:3': { width: 100, height: 75 }, '3:2': { width: 100, height: 66.67 }, '16:9': { width: 100, height: 56.25 }, '2:1': { width: 100, height: 50 }};
        const ratioSlider = $('ratio-slider');
        if (ratioSlider) {
            ratioSlider.oninput = e => {
                const ratio = sizeMap[+e.target.value] || '1:1'; params.ar = ratio;
                const box = $('ratio-box'); const preset = ratioPresets[ratio] || { width: 100, height: 100 };
                if(box) { box.style.width = `${preset.width}px`; box.style.height = `${preset.height}px`; box.textContent = ratio; }
                // 更新按钮组的激活状态
                document.querySelectorAll('#size-buttons button').forEach(btn => {
                    btn.classList.toggle('active', btn.dataset.value === ratio);
                });
                updatePromptParams();
            };
        }

        const sizeButtonGroup = $('size-buttons');
        if (sizeButtonGroup) {
            const presetMap = { '纵向': '1:2', '正方形': '1:1', '横向': '2:1' };
            ['纵向', '正方形', '横向'].forEach((label) => {
                const btn = document.createElement('button'); btn.textContent = label;
                btn.dataset.value = presetMap[label];
                btn.onclick = () => {
                    const ratio = presetMap[label]; const sliderIndex = sizeMap.indexOf(ratio);
                    if (sliderIndex !== -1 && ratioSlider) {
                        ratioSlider.value = sliderIndex;
                        ratioSlider.dispatchEvent(new Event('input')); // 触发滑块的input事件来更新所有
                    }
                };
                sizeButtonGroup.appendChild(btn);
            });
        }


        if ($('seed-input')) {
            $('seed-input').oninput = e => {
                const value = e.target.value.trim();
                if (/^\d*$/.test(value) && (value === '' || (parseInt(value) >= 0 && parseInt(value) <= 4294967295))) {
                    params.seed = value; // 允许为空字符串,表示不设置seed
                } else {
                    // 如果输入无效,则恢复到上一个有效值
                    e.target.value = params.seed;
                }
                updatePromptParams();
            };
        }
        if ($('personal-params')) $('personal-params').oninput = e => { params.personalParams = e.target.value.trim(); updatePromptParams(); };

        // 点击最终参数文本区直接复制
        const promptParamsTextarea = $('prompt-params');
        if (promptParamsTextarea) {
            promptParamsTextarea.addEventListener('click', () => {
                if (!promptParamsTextarea.value) { showToast('没有参数可以拷贝'); return; }
                if (navigator.clipboard && navigator.clipboard.writeText) {
                    navigator.clipboard.writeText(promptParamsTextarea.value)
                        .then(() => showToast('参数已复制!'))
                        .catch(() => { showToast('复制失败!'); legacyCopy(promptParamsTextarea);});
                } else {
                    legacyCopy(promptParamsTextarea);
                }
            });
        }

        // 给所有输入框、文本区、下拉框添加聚焦时的视觉效果
        document.querySelectorAll('#mj-control-panel input[type="text"], #mj-control-panel input[type="number"], #mj-control-panel textarea, #mj-control-panel select').forEach(el => {
            el.addEventListener('focus', (e) => e.target.classList.add('focused'));
            el.addEventListener('blur', (e) => e.target.classList.remove('focused'));
        });

        // 初始化切换开关的状态
        updateToggleVisuals('tile-toggle-switch', 'tile');
        updateToggleVisuals('draft-toggle-switch', 'draft');
        updateToggleVisuals('imagine-toggle-switch', 'includeImagine');
        // 初始化按钮组和滑块状态
        setInitialActiveButtons();
        if (ratioSlider) { // 确保比例滑块在加载时也正确设置其初始值和预览
            const initialRatioIndex = sizeMap.indexOf(params.ar);
            ratioSlider.value = initialRatioIndex !== -1 ? initialRatioIndex : 5; // 5 is '1:1'
            ratioSlider.dispatchEvent(new Event('input'));
        }
    }

    // 添加图片预览到容器 (包含启用/禁用和权重调整)
    function addPreviewImage(containerId, item, paramKey, currentWeightPrefix) {
        const container = document.getElementById(containerId); if (!container) return;
        const imgContainer = document.createElement('div');
        imgContainer.className = 'ref-image-container';
        imgContainer.style.animation = 'fadeIn 0.3s ease';
        if (item.enabled === false) { // 显式检查 false
            imgContainer.classList.add('disabled-ref-item');
        }

        const img = document.createElement('img');
        img.src = item.url;
        img.className = 'ref-image-preview';

        img.onerror = () => { // 处理图片加载失败
            const errorDiv = document.createElement('div');
            errorDiv.textContent = '无效图';
            errorDiv.className = 'ref-image-error';
            if (imgContainer.contains(img)) imgContainer.removeChild(img); // 移除损坏的img标签
            // 尝试在控件前插入错误提示,如果控件容器已创建
            const controlsNode = imgContainer.querySelector('.ref-item-controls');
            if (controlsNode) {
                imgContainer.insertBefore(errorDiv, controlsNode);
            } else { // 否则,作为第一个子元素插入(或根据实际布局调整)
                 imgContainer.insertBefore(errorDiv, imgContainer.firstChild);
            }
        };

        // 控件容器 (用于权重输入和禁用开关)
        const controlsContainer = document.createElement('div');
        controlsContainer.className = 'ref-item-controls';

        // 权重输入框
        const weightInputPreview = document.createElement('input');
        weightInputPreview.type = 'number';
        weightInputPreview.className = 'ref-item-weight-input';
        weightInputPreview.placeholder = 'W'; // 简短占位符
        weightInputPreview.value = item.weight || '';
        weightInputPreview.title = `调整权重 (${currentWeightPrefix || weightPrefixes[paramKey] || '--iw'})`;
        weightInputPreview.oninput = (e) => {
            item.weight = e.target.value.trim();
            updatePromptParams();
            // 更新旁边的徽章文本
            const badge = imgContainer.querySelector('.ref-weight-badge');
            if (badge) {
                const wP = (currentWeightPrefix ? currentWeightPrefix.replace('--', '') : (weightPrefixes[paramKey] ? weightPrefixes[paramKey].replace('--','') : 'iw'));
                badge.textContent = item.weight && item.weight.trim() !== '' ? `${wP}:${item.weight}` : `${wP}:默认`;
            }
        };
        weightInputPreview.onclick = (e) => e.stopPropagation(); // 防止点击输入框时触发容器的事件

        // 禁用/启用 开关
        const disableToggle = document.createElement('div');
        disableToggle.className = 'ref-item-disable-toggle toggle-switch'; // 复用 .toggle-switch 样式
        if (item.enabled) disableToggle.classList.add('active');
        disableToggle.title = item.enabled ? '点击禁用' : '点击启用';
        const toggleDot = document.createElement('div');
        toggleDot.className = 'toggle-dot';
        disableToggle.appendChild(toggleDot);

        disableToggle.onclick = (e) => {
            e.stopPropagation();
            item.enabled = !item.enabled;
            disableToggle.classList.toggle('active', item.enabled);
            imgContainer.classList.toggle('disabled-ref-item', !item.enabled);
            disableToggle.title = item.enabled ? '点击禁用' : '点击启用';
            updatePromptParams();
        };

        controlsContainer.appendChild(weightInputPreview);
        controlsContainer.appendChild(disableToggle);

        // 权重徽章 (保持原有逻辑,显示前缀和权重)
        const weightBadge = document.createElement('div');
        weightBadge.className = 'ref-weight-badge';
        const wP = (currentWeightPrefix ? currentWeightPrefix.replace('--', '') : (weightPrefixes[paramKey] ? weightPrefixes[paramKey].replace('--','') : 'iw'));
        weightBadge.textContent = item.weight && item.weight.trim() !== '' ? `${wP}:${item.weight}` : `${wP}:默认`;

        // 删除按钮
        const deleteBtn = document.createElement('button');
        deleteBtn.className = 'ref-delete-btn';
        deleteBtn.innerHTML = '&times;';
        deleteBtn.title = '删除此参考';
        deleteBtn.onclick = function(e) {
            e.stopPropagation();
            imgContainer.style.animation = 'fadeOut 0.2s ease forwards';
            setTimeout(() => {
                const targetArray = params[paramKey];
                if (Array.isArray(targetArray)) {
                    const index = targetArray.findIndex(i => i.url === item.url); // 通过url查找
                    if (index !== -1) {
                        targetArray.splice(index, 1);
                        if (container.contains(imgContainer)) container.removeChild(imgContainer);
                        updatePromptParams();
                    }
                }
            }, 200);
        };

        imgContainer.appendChild(img); // 先添加图片本身
        imgContainer.appendChild(controlsContainer); // 再添加控件容器
        imgContainer.appendChild(weightBadge); // 然后是权重徽章
        imgContainer.appendChild(deleteBtn); // 最后是删除按钮
        container.appendChild(imgContainer);
    }

    // 添加sref代码预览到容器 (包含启用/禁用和权重调整)
    function addPreviewSrefCode(containerId, item, paramKey) {
        const container = document.getElementById(containerId); if (!container) return;
        const codeContainer = document.createElement('div');
        codeContainer.className = 'ref-code-container';
        codeContainer.style.animation = 'fadeIn 0.3s ease';
        if (item.enabled === false) { // 显式检查 false
             codeContainer.classList.add('disabled-ref-item');
        }

        const codeText = document.createElement('span');
        codeText.className = 'ref-code-text-main'; // 给文本加个class方便控制样式
        codeText.textContent = `sref:${item.url}`;

        // 控件容器
        const controlsContainer = document.createElement('div');
        controlsContainer.className = 'ref-item-controls sref-controls'; // 可以添加 sref 特有的 class

        // sref 权重输入框
        const weightInputPreview = document.createElement('input');
        weightInputPreview.type = 'number';
        weightInputPreview.className = 'ref-item-weight-input sref-weight-input';
        weightInputPreview.placeholder = 'W';
        weightInputPreview.value = item.weight || '';
        weightInputPreview.title = '调整权重 (--sw)';
        weightInputPreview.oninput = (e) => {
            item.weight = e.target.value.trim();
            updatePromptParams();
            const badge = codeContainer.querySelector('.ref-code-weight-badge');
            if (badge) {
                 badge.textContent = item.weight && item.weight.trim() !== '' ? `sw:${item.weight}` : 'sw:默认';
            }
        };
        weightInputPreview.onclick = (e) => e.stopPropagation();

        // sref 禁用/启用 开关
        const disableToggle = document.createElement('div');
        disableToggle.className = 'ref-item-disable-toggle toggle-switch';
        if (item.enabled) disableToggle.classList.add('active');
        disableToggle.title = item.enabled ? '点击禁用' : '点击启用';
        const toggleDot = document.createElement('div');
        toggleDot.className = 'toggle-dot';
        disableToggle.appendChild(toggleDot);

        disableToggle.onclick = (e) => {
            e.stopPropagation();
            item.enabled = !item.enabled;
            disableToggle.classList.toggle('active', item.enabled);
            codeContainer.classList.toggle('disabled-ref-item', !item.enabled);
            disableToggle.title = item.enabled ? '点击禁用' : '点击启用';
            updatePromptParams();
        };

        controlsContainer.appendChild(weightInputPreview);
        controlsContainer.appendChild(disableToggle);

        // sref 权重徽章
        const weightBadge = document.createElement('div');
        weightBadge.className = 'ref-code-weight-badge';
        weightBadge.textContent = item.weight && item.weight.trim() !== '' ? `sw:${item.weight}` : 'sw:默认';

        // sref 删除按钮
        const deleteBtn = document.createElement('button');
        deleteBtn.className = 'ref-code-delete-btn';
        deleteBtn.innerHTML = '&times;';
        deleteBtn.title = '删除此参考';
        deleteBtn.onclick = function(e) {
            e.stopPropagation(); codeContainer.style.animation = 'fadeOut 0.2s ease forwards';
            setTimeout(() => {
                const targetArray = params[paramKey]; // paramKey 应该是 'sref'
                const index = targetArray.findIndex(i => i.url === item.url);
                if (index !== -1) {
                    targetArray.splice(index, 1);
                    if (container.contains(codeContainer)) container.removeChild(codeContainer);
                    updatePromptParams();
                }
            }, 200);
        };

        codeContainer.appendChild(codeText);        // sref代码文本
        codeContainer.appendChild(controlsContainer); // 控件(权重输入+开关)
        codeContainer.appendChild(weightBadge);     // 权重徽章
        codeContainer.appendChild(deleteBtn);       // 删除按钮
        container.appendChild(codeContainer);
    }


    // 刷新所有参考图/代码的预览区域
    function refreshPreviews() {
        const refTypes = [
            { idPrefix: 'cref', paramKey: 'cref', previewId: 'cref-preview' },
            { idPrefix: 'sref', paramKey: 'sref', previewId: 'sref-preview' },
            { idPrefix: 'oref', paramKey: 'oref', previewId: 'oref-preview' },
            { idPrefix: 'direct-image', paramKey: 'directImages', previewId: 'direct-image-preview' }
        ];
        refTypes.forEach(ref => {
            const container = document.getElementById(ref.previewId); if (!container) return;
            container.innerHTML = ''; // 清空现有预览
            const items = params[ref.paramKey];
            if (items && Array.isArray(items)) {
                items.forEach(item => { // item 是 {url, weight, enabled}
                    const currentWeightPrefix = weightPrefixes[ref.paramKey];
                    // 确保 enabled 属性存在,默认为 true
                    if (typeof item.enabled === 'undefined') {
                        item.enabled = true;
                    }

                    if (ref.paramKey === 'sref' && (item.url === 'random' || /^\d+$/.test(item.url))) {
                        addPreviewSrefCode(ref.previewId, item, ref.paramKey);
                    } else {
                        addPreviewImage(ref.previewId, item, ref.paramKey, currentWeightPrefix);
                    }
                });
            }
        });
    }

    // 注入CSS样式
    function injectStyles() {
        const styleSheet = document.createElement("style");
        styleSheet.type = "text/css";
        styleSheet.innerText = `
            /* 入场/出场动画 */
            @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
            @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(5px); } }

            /* MJ参数浮动按钮 */
            #mj-floating-settings-button {
                position: fixed; right: 20px; bottom: 20px; padding: 10px 20px;
                background-color: #5865F2; color: white; border: none; border-radius: 8px;
                cursor: pointer; z-index: 9999; box-shadow: 0 4px 12px rgba(0,0,0,0.15);
                transition: background-color 0.2s ease, transform 0.2s ease; font-family: sans-serif;
            }
            #mj-floating-settings-button:hover { background-color: #4752C4; transform: scale(1.05); }

            /* Toast提示样式 */
            .mj-toast {
                position: fixed; top: 20px; right: 20px; padding: 10px 16px; border-radius: 6px;
                z-index: 99999; transition: all 0.3s ease; font-family: sans-serif;
            }
            #mj-control-panel:not(.dark-mode) ~ body .mj-toast, .mj-toast { /* 默认浅色面板下的Toast,或无面板时的Toast */
                background: #2B2D31; color: #DCDDDE; box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            }
            #mj-control-panel.dark-mode ~ body .mj-toast { /* 深色面板下的Toast */
                 background: #DCDDDE; color: #2B2D31; box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            }

            /* 面板基础样式 */
            #mj-control-panel { background: white; color: #111827; border-color: #E0E0E0; }
            #mj-control-panel .panel-title { color: #111827; }
            #mj-control-panel .panel-divider { background: #e5e7eb; }
            #mj-control-panel .panel-section { background: #f9fafb; padding:16px; border-radius:8px;}
            #mj-control-panel .section-title { margin:0 0 8px 0; font-weight:500; color: #1F2937; }
            #mj-control-panel label, #mj-control-panel .param-value-display, #mj-control-panel .imagine-label { color: #1F2937; }
            #mj-control-panel input[type="text"], #mj-control-panel input[type="number"],
            #mj-control-panel textarea, #mj-control-panel select {
                background: white; color: #111827; border: 1px solid #D1D5DB;
                padding: 6px 4px; border-radius: 6px; box-sizing: border-box;
                transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
                font-size: 14px;
            }
            /* Remove spinners from number inputs in the panel */
            #mj-control-panel input[type=number]::-webkit-inner-spin-button,
            #mj-control-panel input[type=number]::-webkit-outer-spin-button {
                -webkit-appearance: none;
                margin: 0;
            }
            #mj-control-panel input[type=number] {
                -moz-appearance: textfield; /* Firefox */
            }
            #mj-control-panel select {
                -webkit-appearance: none; -moz-appearance: none; appearance: none;
                background-image: url('data:image/svg+xml;charset=US-ASCII,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="%23374151" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/></svg>');
                background-repeat: no-repeat; background-position: right 0.7em top 50%; background-size: 0.8em auto;
                padding-right: 2.5em; /* 为下拉箭头腾出空间 */
            }
            #mj-control-panel input[type="text"].focused, #mj-control-panel input[type="number"].focused,
            #mj-control-panel textarea.focused, #mj-control-panel select.focused { border-color: #4f46e5; /* Indigo-600 */ }
            #mj-control-panel textarea { resize: vertical; height: 80px; width:100%; padding:10px; }
            #mj-control-panel #prompt-params { background:#f9fafb; cursor:pointer; } /* 提示参数区背景和光标 */
            #mj-control-panel .results-section-divider { border-top-color: #e5e7eb; }

            /* 主题切换触发按钮 */
            #mj-control-panel .theme-trigger-btn {
                padding: 6px 12px; border-radius: 6px; border: 1px solid #D1D5DB; /* Gray-300 */
                background-color: white; color: #1F2937; /* Gray-800 */ font-size: 13px;
                cursor: pointer; display: inline-flex; align-items: center;
                transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
            }
            #mj-control-panel .theme-trigger-btn:hover { border-color: #4f46e5; /* Indigo-600 */ }
            #mj-control-panel .theme-trigger-btn svg { width: 16px; height: 16px; }

            /* 主题选项菜单 */
            #mj-control-panel .theme-options-menu {
                position: absolute; top: calc(100% + 5px); right: 0;
                background-color: white; border: 1px solid #D1D5DB; /* Gray-300 */
                border-radius: 6px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);
                z-index: 10010; min-width: 180px; padding: 4px;
            }
            #mj-control-panel .theme-option-button {
                display: flex; align-items: center; width: 100%;
                padding: 8px 12px; text-align: left; background: none; border: none;
                cursor: pointer; font-size: 13px; color: #1F2937; /* Gray-800 */ border-radius: 4px;
                transition: background-color 0.15s ease, color 0.15s ease;
            }
            #mj-control-panel .theme-option-button svg { margin-right: 8px; width:16px; height:16px; opacity: 0.7; }
            #mj-control-panel .theme-option-button:hover { background-color: #f0f0f0; /* Lighter gray for hover */ }
            #mj-control-panel .theme-option-button.active { background-color: #eef2ff; /* Indigo-50 */ color: #4338ca; /* Indigo-700 */ font-weight: 500; }
            #mj-control-panel .theme-option-button.active svg { opacity: 1; }


            /* 比例预览 浅色 */
            #mj-control-panel .ratio-preview-bg { position:absolute; top:0; left:0; width:100px; height:100px; border:2px dashed #d1d5db; border-radius:12px; }
            #mj-control-panel .ratio-box { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); background:#f3f4f6; border:2px solid #374151; border-radius:6px; display:flex; align-items:center; justify-content:center; font-size:12px; color:#374151; padding:2px 4px; min-width:20px; min-height:12px; box-sizing: border-box; }

            /* 滑块 浅色 */
            #mj-control-panel input[type="range"] { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 100%;}
            #mj-control-panel input[type="range"]::-webkit-slider-runnable-track { background: #E5E7EB; height: 0.4rem; border-radius: 0.2rem; }
            #mj-control-panel input[type="range"]::-moz-range-track { background: #E5E7EB; height: 0.4rem; border-radius: 0.2rem; }
            #mj-control-panel input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; margin-top: -0.3rem; background-color: #4f46e5; height: 1rem; width: 1rem; border-radius: 50%; border: 1px solid #3730a3; }
            #mj-control-panel input[type="range"]::-moz-range-thumb { border: none; border-radius: 50%; background-color: #4f46e5; height: 1rem; width: 1rem; border: 1px solid #3730a3;}

            /* 按钮组 浅色 (通用) */
            #mj-control-panel .btn-group { display:flex; border-radius:6px; overflow:hidden; border:1px solid #d1d5db; }
            #mj-control-panel .btn-group button { flex:1; padding:6px 10px; background:white; border:none; cursor:pointer; color: #374151; transition: background-color 0.2s, color 0.2s; font-size: 13px;}
            #mj-control-panel .btn-group button:not(:last-child) { border-right: 1px solid #d1d5db; }
            #mj-control-panel .btn-group button.active { background: #4f46e5; color: white; }

            /* 切换开关 浅色 */
            #mj-control-panel .toggle-switch { position:relative; width:40px; height:20px; border-radius:10px; background:#e5e7eb; cursor:pointer; margin-top: 4px; transition: background-color 0.2s ease; }
            #mj-control-panel .toggle-switch .toggle-dot { position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%; background:white; box-shadow:0 1px 3px rgba(0,0,0,0.2); transition:all 0.2s ease; }
            #mj-control-panel .toggle-switch.active { background:#4f46e5; }
            #mj-control-panel .toggle-switch.active .toggle-dot { transform: translateX(20px); }

            /* 操作按钮 浅色 */
            #mj-control-panel .action-button, #mj-control-panel .action-button-primary, #mj-control-panel .action-button-secondary { padding:4px 8px; border:none; border-radius:4px; cursor:pointer; transition:all 0.2s ease; }
            #mj-control-panel .action-button { background:#4f46e5; color:white; } /* 添加参考的小按钮 */
            #mj-control-panel .action-button:hover { background:#4338CA; }
            #mj-control-panel .action-button-primary { flex:1; padding:8px; border-radius:6px; background:#4f46e5; color:white; } /* 拷贝 */
            #mj-control-panel .action-button-primary:hover { background:#4338CA; }
            #mj-control-panel .action-button-secondary { flex:1; padding:8px; border-radius:6px; background:#E5E7EB; color:#374151; border: 1px solid #D1D5DB; } /* 清空 */
            #mj-control-panel .action-button-secondary:hover { background:#D1D5DB; }
            #mj-control-panel #size-buttons button { padding: 4px 12px; border-radius: 6px; cursor: pointer; transition: all 0.2s ease; background: white; color: #374151; border: 1px solid #D1D5DB; font-size: 13px;}
            #mj-control-panel #size-buttons button.active { background: #4f46e5; color: white; border-color: #4f46e5; }
            #mj-control-panel #size-buttons button:hover:not(.active) { background: #f0f0f0; }


            /* 参考图预览 浅色 (包含新控件的样式调整) */
            #mj-control-panel .ref-preview-container { margin-top:10px; display:flex; flex-wrap:wrap; gap:12px; /* 增加gap以便容纳控件 */ }
            #mj-control-panel .ref-image-container, #mj-control-panel .ref-code-container {
                position: relative;
                margin: 4px;
                padding-bottom: 26px; /* 为底部控件留出空间 */
                min-height: 60px; /* 确保有基础高度 */
                min-width: 80px; /* MODIFIED: Ensures enough space for controls */
            }
            #mj-control-panel .ref-image-preview { width: 60px; height: 60px; object-fit: cover; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); border: 1px solid #E5E7EB; display: block; /* 防止底部有多余空间 */ }
            #mj-control-panel .ref-image-preview:hover { transform: scale(1.05); box-shadow: 0 2px 6px rgba(0,0,0,0.15); }
            #mj-control-panel .ref-image-error { width:60px; height:60px; display:flex; align-items:center; justify-content:center; border-radius:4px; font-size:10px; text-align:center; background: #F3F4F6; color: #757575; border: 1px solid #E5E7EB; box-sizing: border-box; }

            #mj-control-panel .ref-weight-badge { /* 权重徽章现在位于图片/代码的上方或 کنار */
                position: absolute; top: -2px; left: -2px; /* 调整到左上角,稍微偏移 */
                background: rgba(255,255,255,0.85); color: #374151; font-size: 9px;
                padding: 1px 3px; border-radius: 4px 0 4px 0;
                border-bottom: 1px solid #4f46e5; border-right: 1px solid #4f46e5;
                z-index: 1; /* 确保在图片之上 */
            }
            #mj-control-panel .ref-delete-btn {
                position: absolute; top: -6px; right: -6px;
                background: rgba(239, 68, 68, 0.85); color: white; border: none; border-radius: 50%;
                width: 18px; height: 18px; font-size: 12px; line-height: 18px; text-align:center;
                cursor:pointer; transition:all 0.2s ease; opacity: 0.8;
                display:flex; align-items:center; justify-content:center; box-shadow: 0 1px 2px rgba(0,0,0,0.2);
                z-index: 2; /* 最高层 */
            }
            #mj-control-panel .ref-delete-btn:hover { opacity: 1; transform: scale(1.1); background: rgb(220, 38, 38); }

            /* 参考代码预览 浅色 */
            #mj-control-panel .ref-code-container { /* 基础样式已在上面与 ref-image-container 合并 */
                border-radius: 4px; padding-top: 10px; /* 给徽章留出空间 */
                background: #F3F4F6; color: #111827; border: 1px solid #E0E0E0;
                min-width: 80px; /* 给代码和控件一些最小宽度, this is consistent with the shared rule now */
                box-sizing: border-box;
            }
            #mj-control-panel .ref-code-text-main { /* sref代码文本样式 */
                display: block; text-align: center; font-family: monospace; font-size: 11px;
                margin-bottom: 2px; /* 与下方控件的间距 */
                word-break: break-all;
                padding: 0 4px;
            }
            #mj-control-panel .ref-code-weight-badge {
                position: absolute; top: -2px; left: -2px; /* 与图片徽章样式统一 */
                font-size: 9px; padding: 1px 3px; border-radius: 4px 0 4px 0;
                background: rgba(79, 70, 229, 0.1); color: #4f46e5;
                border-bottom: 1px solid #4f46e5; border-right: 1px solid #4f46e5;
                z-index: 1;
            }
            #mj-control-panel .ref-code-delete-btn { /* 删除按钮样式已全局定义,这里可微调 */
                 /* 与图片删除按钮一致 */
            }

            /* 新增:参考项内部控件容器 */
            #mj-control-panel .ref-item-controls {
                position: absolute;
                bottom: 2px; /* 放置在容器底部 */
                left: 2px;
                right: 2px;
                display: flex;
                gap: 4px;
                align-items: center;
                justify-content: space-between; /* 权重输入和开关两端对齐 */
                padding: 0 3px;
                height: 20px; /* 控制容器高度 */
            }
            #mj-control-panel .ref-code-container .ref-item-controls {
                /* sref代码的控件容器可能需要微调 */
                justify-content: space-around; /* 或者根据需要调整 */
            }

            /* 新增:参考项内部权重输入框 (MODIFIED WIDTH) */
            #mj-control-panel .ref-item-weight-input {
                width: 40px; /* MODIFIED: 较小宽度, 原36px */
                padding: 1px 3px;
                font-size: 10px;
                border-radius: 3px;
                border: 1px solid #D1D5DB; /* Gray-300 */
                box-sizing: border-box;
                text-align: center;
                height: 18px; /* 匹配开关高度 */
            }

            /* 新增:参考项内部禁用/启用开关 (基于全局 .toggle-switch 调整) */
            #mj-control-panel .ref-item-disable-toggle {
                width: 30px; /* 更小尺寸 */
                height: 16px;
                border-radius: 8px;
                margin-top: 0; /* 移除全局开关的 margin-top */
            }
            #mj-control-panel .ref-item-disable-toggle .toggle-dot {
                width: 12px;
                height: 12px;
                top: 2px;
                left: 2px;
            }
            #mj-control-panel .ref-item-disable-toggle.active .toggle-dot {
                transform: translateX(14px); /* 调整滑动距离 */
            }

            /* 新增:禁用状态的参考项视觉效果 */
            #mj-control-panel .disabled-ref-item {
                opacity: 0.5;
                filter: grayscale(50%); /* 轻微灰度 */
            }
            #mj-control-panel .disabled-ref-item .ref-image-preview,
            #mj-control-panel .disabled-ref-item .ref-code-text-main {
                 /* 如果需要,可以进一步改变图片或文本自身的样式 */
            }


            /* 暗黑模式样式 */
            #mj-control-panel.dark-mode { background: #2B2D31; color: #DCDDDE; border-color: #202225; }
            #mj-control-panel.dark-mode .panel-title { color: #DCDDDE; }
            #mj-control-panel.dark-mode .panel-divider { background: #40444B; }
            #mj-control-panel.dark-mode .panel-section { background: #202225; }
            #mj-control-panel.dark-mode .section-title { color: #DCDDDE; }
            #mj-control-panel.dark-mode label, #mj-control-panel.dark-mode .param-value-display, #mj-control-panel.dark-mode .imagine-label { color: #DCDDDE; }

            #mj-control-panel.dark-mode input[type="text"],
            #mj-control-panel.dark-mode input[type="number"],
            #mj-control-panel.dark-mode textarea {
                background: #202225; color: #DCDDDE; border-color: #40444B;
            }
            /* 暗黑模式下 select 特殊处理 */
            #mj-control-panel.dark-mode select {
                background-color: #202225 !important; color: #DCDDDE !important; border: 1px solid #40444B !important;
                box-shadow: none !important; -webkit-appearance: none !important; -moz-appearance: none !important; appearance: none !important;
                background-image: url('data:image/svg+xml;charset=US-ASCII,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="%23DCDDDE" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z"/></svg>') !important;
                /* 其他 background 属性继承自浅色或已在上面设置,确保 padding-right 覆盖 */
                padding-right: 2.5em !important;
            }
            #mj-control-panel.dark-mode input[type="text"]::placeholder,
            #mj-control-panel.dark-mode input[type="number"]::placeholder,
            #mj-control-panel.dark-mode textarea::placeholder { color: #72767d; opacity: 1; }
            #mj-control-panel.dark-mode input[type="text"].focused,
            #mj-control-panel.dark-mode input[type="number"].focused,
            #mj-control-panel.dark-mode textarea.focused,
            #mj-control-panel.dark-mode select.focused {
                border-color: #7289DA !important; /* Discord 紫色 */
            }
            #mj-control-panel.dark-mode #prompt-params { background:#202225; }
            #mj-control-panel.dark-mode .results-section-divider { border-top-color: #40444B; }

            /* 暗黑模式主题切换 */
            #mj-control-panel.dark-mode .theme-trigger-btn {
                border-color: #2D2F34; background-color: #2B2D31; color: #DCDDDE;
            }
            #mj-control-panel.dark-mode .theme-trigger-btn:hover { border-color: #7289DA; }
            #mj-control-panel.dark-mode .theme-options-menu {
                background-color: #2B2D31; border-color: #202225;
            }
            #mj-control-panel.dark-mode .theme-option-button { color: #DCDDDE; }
            #mj-control-panel.dark-mode .theme-option-button:hover { background-color: #393c43; }
            #mj-control-panel.dark-mode .theme-option-button.active { background-color: #404EED; color: white; }


            #mj-control-panel.dark-mode .ratio-preview-bg { border-color: #40444B; }
            #mj-control-panel.dark-mode .ratio-box { background: #40444B; color: #DCDDDE; border-color: #70747A; }

            #mj-control-panel.dark-mode input[type="range"]::-webkit-slider-runnable-track { background: #40444B; }
            #mj-control-panel.dark-mode input[type="range"]::-moz-range-track { background: #40444B; }
            #mj-control-panel.dark-mode input[type="range"]::-webkit-slider-thumb { background-color: #7289DA; border-color: #5865F2; }
            #mj-control-panel.dark-mode input[type="range"]::-moz-range-thumb { background-color: #7289DA; border-color: #5865F2; }

            #mj-control-panel.dark-mode .btn-group { border-color: #2D2F34; }
            #mj-control-panel.dark-mode .btn-group button { background: #40444B; color: #DCDDDE; }
            #mj-control-panel.dark-mode .btn-group button:not(:last-child) { border-right-color: #2D2F34; }
            #mj-control-panel.dark-mode .btn-group button.active { background: #5865F2; color: white; }

            #mj-control-panel.dark-mode .toggle-switch { background: #4E4F52; }
            #mj-control-panel.dark-mode .toggle-switch .toggle-dot { background: #B9BBBE; }
            #mj-control-panel.dark-mode .toggle-switch.active { background: #5865F2; }
            #mj-control-panel.dark-mode .toggle-switch.active .toggle-dot { transform: translateX(20px); } /* 全局开关滑动距离 */

            #mj-control-panel.dark-mode .action-button { background:#5865F2; color:white; }
            #mj-control-panel.dark-mode .action-button:hover { background:#4752C4; }
            #mj-control-panel.dark-mode .action-button-primary { background:#5865F2; color:white; border: 1px solid #5865F2;} /* 确保有边框或调整 */
            #mj-control-panel.dark-mode .action-button-primary:hover { background:#4752C4; }
            #mj-control-panel.dark-mode .action-button-secondary { background:#40444B; color:#DCDDDE; border: 1px solid #2D2F34; }
            #mj-control-panel.dark-mode .action-button-secondary:hover { background:#4F545C; }
            #mj-control-panel.dark-mode #size-buttons button { background: #40444B; color: #DCDDDE; border-color: #2D2F34; }
            #mj-control-panel.dark-mode #size-buttons button.active { background: #5865F2; color: white; border-color: #5865F2; }
            #mj-control-panel.dark-mode #size-buttons button:hover:not(.active) { background: #4f545c; }


            #mj-control-panel.dark-mode .ref-image-preview { border-color: #40444B; }
            #mj-control-panel.dark-mode .ref-image-preview:hover { box-shadow: 0 2px 6px rgba(0,0,0,0.3); }
            #mj-control-panel.dark-mode .ref-image-error { background: #40444B; color: #aaa; border: 1px solid #555; }
            #mj-control-panel.dark-mode .ref-weight-badge {
                background: rgba(0,0,0,0.75); color: #DCDDDE;
                border-bottom-color: #5865F2; border-right-color: #5865F2;
            }
            #mj-control-panel.dark-mode .ref-delete-btn { background: rgba(239, 68, 68, 0.7); }
            #mj-control-panel.dark-mode .ref-delete-btn:hover { background: rgb(239, 68, 68); }

            #mj-control-panel.dark-mode .ref-code-container { background: #202225; color: #DCDDDE; border-color: #2D2F34; }
            #mj-control-panel.dark-mode .ref-code-weight-badge {
                background: rgba(88, 101, 242, 0.3); color: #B9BBBE;
                border-bottom-color: #5865F2; border-right-color: #5865F2;
            }
            #mj-control-panel.dark-mode .ref-code-delete-btn { background: rgba(239, 68, 68, 0.3); color: #FAA0A0; }
            #mj-control-panel.dark-mode .ref-code-delete-btn:hover { background: rgba(239, 68, 68, 0.5); }

            /* 暗黑模式下参考项内部控件 */
            #mj-control-panel.dark-mode .ref-item-weight-input {
                background-color: #2B2D31; /* 更暗的背景 */
                border-color: #40444B; /* 与其他输入框一致的边框 */
                color: #DCDDDE;
            }
            #mj-control-panel.dark-mode .ref-item-disable-toggle {
                background: #4E4F52; /* 与全局开关一致 */
            }
            #mj-control-panel.dark-mode .ref-item-disable-toggle .toggle-dot {
                background: #B9BBBE; /* 与全局开关一致 */
            }
            #mj-control-panel.dark-mode .ref-item-disable-toggle.active {
                background: #5865F2; /* 与全局开关一致 */
            }
             #mj-control-panel.dark-mode .ref-item-disable-toggle.active .toggle-dot {
                transform: translateX(14px); /* 调整滑动距离 */
            }

        `;
        document.head.appendChild(styleSheet);
    }

    // 初始化函数
    function init() {
        injectStyles();
        resetParams(); // 确保 params 对象在创建UI前已初始化
        createSettingButton();
        createControlPanel(); // 创建面板并绑定事件
        // applyCurrentTheme(); // 已在 createControlPanel 内部调用
        // updatePromptParams(); // 已在 createControlPanel -> bindControlEvents -> setInitialActiveButtons/ratioSlider.oninput 中间接触发,或者直接在 bindControlEvents 后调用一次
        updatePromptParams(); // 确保首次加载时最终参数区正确显示
    }

    // 确保 Discord 加载完毕后再执行初始化
    const discordAppMount = document.getElementById('app-mount');
    if (discordAppMount) {
        setTimeout(init, 500); // 如果 app-mount 已存在,稍作延迟后初始化
    } else {
        // 监听 window load 事件作为后备
        window.addEventListener('load', () => setTimeout(init, 500), { once: true });
    }
})();