Greasy Fork

Greasy Fork is available in English.

Discord Midjourney 参数可视化

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

// ==UserScript==
// @name         Discord Midjourney 参数可视化
// @namespace    https://github.com/cwser
// @version      1.0.1
// @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" 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" 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" 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)">
                    </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)">
                    </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)">
                    </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)">
                    </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 });
    }
})();