Greasy Fork

Greasy Fork is available in English.

[Chat] Template Text Folders [20251014] +fix1.0

在AI页面上添加预设文本文件夹和按钮,提升输入效率。

// ==UserScript==
// @name         [Chat] Template Text Folders [20251014] +fix1.0
// @namespace    0_V userscripts/[Chat] Template Text Folders
// @version      [20251014]
// @description  在AI页面上添加预设文本文件夹和按钮,提升输入效率。
// @update-log   insertTextSmart Fixed
//
// @match        https://chatgpt.com/*
// @match        https://chat01.ai/*
//
// @match        https://claude.*/*
// @match        https://*.fuclaude.com/*
//
// @match        https://gemini.google.com/*
// @match        https://aistudio.google.com/*
//
// @match        https://copilot.microsoft.com/*
//
// @match        https://grok.com/*
// @match        https://grok.dairoot.cn/*
//
// @match        https://chat.deepseek.com/*
// @match        https://chat.mistral.ai/*
//
// @match        https://*.perplexity.ai/*
//
// @match        https://poe.com/*
// @match        https://kagi.com/assistant*
// @match        https://lmarena.ai/*
// @match        https://app.chathub.gg/*
// @match        https://monica.im/home*
//
// @match        https://setapp.typingcloud.com/*
//
// @match        https://*.mynanian.top/*
// @match        https://free.share-ai.top/*
// @match        https://chat.kelaode.ai/*
//
// @match        https://*.aivvm.*/*
// @match        https://linux.do/discourse-ai/ai-bot/*
//
// @match        https://cursor.com/*
//
// @match        https://www.notion.so/*
//
// @grant        none
// @icon         https://github.com/0-V-linuxdo/Chat_Template_Text_Folders/raw/refs/heads/main/Icon.svg
// ==/UserScript==

(function () {
    'use strict';

    console.log("🎉 [Chat] Template Text Folders [20251013] 🎉");

    let trustedHTMLPolicy = null;
    const resolveTrustedTypes = () => {
        if (trustedHTMLPolicy) {
            return trustedHTMLPolicy;
        }
        const globalObj = typeof window !== 'undefined' ? window : (typeof globalThis !== 'undefined' ? globalThis : null);
        const trustedTypesAPI = globalObj && globalObj.trustedTypes ? globalObj.trustedTypes : null;
        if (!trustedTypesAPI) {
            return null;
        }
        try {
            trustedHTMLPolicy = trustedTypesAPI.createPolicy('chat_template_text_folders_policy', {
                createHTML: (input) => input
            });
        } catch (error) {
            console.warn('[Chat] Template Text Folders Trusted Types policy creation failed', error);
            trustedHTMLPolicy = null;
        }
        return trustedHTMLPolicy;
    };

    const setTrustedHTML = (element, html) => {
        if (!element) {
            return;
        }
        const value = typeof html === 'string' ? html : (html == null ? '' : String(html));
        const policy = resolveTrustedTypes();
        if (policy) {
            element.innerHTML = policy.createHTML(value);
        } else {
            element.innerHTML = value;
        }
    };

    const UI_HOST_ID = 'cttf-ui-host';
    let latestThemeValues = null;
    let uiShadowRoot = null;
    let uiMainLayer = null;
    let uiOverlayLayer = null;

    const ensureUIRoot = () => {
        if (uiShadowRoot && uiShadowRoot.host && uiShadowRoot.host.isConnected) {
            return uiShadowRoot;
        }

        if (!document.body) {
            return null;
        }

        let hostElement = document.getElementById(UI_HOST_ID);
        if (!hostElement) {
            hostElement = document.createElement('div');
            hostElement.id = UI_HOST_ID;
            document.body.appendChild(hostElement);
        }

        uiShadowRoot = hostElement.shadowRoot;
        if (!uiShadowRoot) {
            uiShadowRoot = hostElement.attachShadow({ mode: 'open' });
            const baseStyle = document.createElement('style');
            baseStyle.textContent = `
                :host {
                    all: initial;
                    position: fixed;
                    inset: 0;
                    pointer-events: none;
                    z-index: 1000;
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                }
                :host *, :host *::before, :host *::after {
                    box-sizing: border-box;
                    font-family: inherit;
                }
                .cttf-dialog,
                .cttf-dialog * {
                    scrollbar-width: thin;
                    scrollbar-color: var(--cttf-scrollbar-thumb, rgba(120, 120, 120, 0.6)) transparent;
                }
                .cttf-dialog::-webkit-scrollbar,
                .cttf-dialog *::-webkit-scrollbar {
                    width: 6px;
                    height: 6px;
                    background: transparent;
                }
                .cttf-dialog::-webkit-scrollbar-track,
                .cttf-dialog *::-webkit-scrollbar-track {
                    background: transparent;
                    border: none;
                    margin: 0;
                }
                .cttf-dialog::-webkit-scrollbar-thumb,
                .cttf-dialog *::-webkit-scrollbar-thumb {
                    background-color: var(--cttf-scrollbar-thumb, rgba(120, 120, 120, 0.6));
                    border-radius: 999px;
                    border: none;
                }
                .cttf-dialog::-webkit-scrollbar-corner,
                .cttf-dialog *::-webkit-scrollbar-corner {
                    background: transparent;
                }
                .cttf-dialog::-webkit-scrollbar-button,
                .cttf-dialog *::-webkit-scrollbar-button {
                    display: none;
                }
                .hide-scrollbar {
                    scrollbar-width: none;
                }
                .hide-scrollbar::-webkit-scrollbar {
                    display: none;
                }
            `;
            uiShadowRoot.appendChild(baseStyle);
        }

        if (!uiMainLayer || !uiMainLayer.isConnected) {
            uiMainLayer = uiShadowRoot.getElementById('cttf-main-layer');
            if (!uiMainLayer) {
                uiMainLayer = document.createElement('div');
                uiMainLayer.id = 'cttf-main-layer';
                uiMainLayer.style.position = 'fixed';
                uiMainLayer.style.inset = '0';
                uiMainLayer.style.pointerEvents = 'none';
                uiShadowRoot.appendChild(uiMainLayer);
            }
        }

        if (!uiOverlayLayer || !uiOverlayLayer.isConnected) {
            uiOverlayLayer = uiShadowRoot.getElementById('cttf-overlay-layer');
            if (!uiOverlayLayer) {
                uiOverlayLayer = document.createElement('div');
                uiOverlayLayer.id = 'cttf-overlay-layer';
                uiOverlayLayer.style.position = 'fixed';
                uiOverlayLayer.style.inset = '0';
                uiOverlayLayer.style.pointerEvents = 'none';
                uiOverlayLayer.style.zIndex = '20000';
                uiShadowRoot.appendChild(uiOverlayLayer);
            }
        }

        if (latestThemeValues && hostElement) {
            Object.entries(latestThemeValues).forEach(([key, value]) => {
                hostElement.style.setProperty(toCSSVariableName(key), value);
            });
        }

        return uiShadowRoot;
    };

    const getShadowRoot = () => ensureUIRoot();

    const getMainLayer = () => {
        const root = ensureUIRoot();
        return root ? uiMainLayer : null;
    };

    const getOverlayLayer = () => {
        const root = ensureUIRoot();
        return root ? uiOverlayLayer : null;
    };

    const appendToMainLayer = (node) => {
        const container = getMainLayer();
        return container ? container.appendChild(node) : document.body.appendChild(node);
    };

    const appendToOverlayLayer = (node) => {
        const container = getOverlayLayer();
        if (container) {
            container.appendChild(node);
        } else {
            document.body.appendChild(node);
        }
        return node;
    };

    const queryUI = (selector) => {
        const root = getShadowRoot();
        return root ? root.querySelector(selector) : document.querySelector(selector);
    };

    const toCSSVariableName = (key) => `--${key.replace(/([A-Z])/g, '-$1').toLowerCase()}`;

    /**
     * 自动根据内容调整 textarea 高度,确保上下内边距空间充足。
     * @param {HTMLTextAreaElement} textarea
     * @param {{minRows?: number, maxRows?: number}} options
     */
    const autoResizeTextarea = (textarea, options = {}) => {
        if (!textarea) return;
        const { minRows = 1, maxRows = 5 } = options;
        textarea.style.height = 'auto';
        const styles = window.getComputedStyle(textarea);
        const lineHeight = parseFloat(styles.lineHeight) || (parseFloat(styles.fontSize) * 1.2) || 20;
        const paddingTop = parseFloat(styles.paddingTop) || 0;
        const paddingBottom = parseFloat(styles.paddingBottom) || 0;
        const borderTop = parseFloat(styles.borderTopWidth) || 0;
        const borderBottom = parseFloat(styles.borderBottomWidth) || 0;
        const minHeight = (lineHeight * minRows) + paddingTop + paddingBottom + borderTop + borderBottom;
        const maxHeight = (lineHeight * maxRows) + paddingTop + paddingBottom + borderTop + borderBottom;
        let targetHeight = textarea.scrollHeight;
        if (targetHeight < minHeight) {
            targetHeight = minHeight;
        } else if (targetHeight > maxHeight) {
            targetHeight = maxHeight;
            textarea.style.overflowY = 'auto';
        } else {
            textarea.style.overflowY = 'hidden';
        }
        textarea.style.minHeight = `${minHeight}px`;
        textarea.style.maxHeight = `${maxHeight}px`;
        textarea.style.height = `${targetHeight}px`;
    };

    const SVG_NS = 'http://www.w3.org/2000/svg';

    const createAutoFaviconIcon = () => {
        const svg = document.createElementNS(SVG_NS, 'svg');
        svg.setAttribute('viewBox', '0 0 32 32');
        svg.setAttribute('data-name', 'Layer 1');
        svg.setAttribute('id', 'Layer_1');
        svg.setAttribute('fill', '#000000');
        svg.setAttribute('xmlns', SVG_NS);
        svg.setAttribute('aria-hidden', 'true');
        svg.setAttribute('focusable', 'false');
        svg.style.width = '18px';
        svg.style.height = '18px';
        svg.style.display = 'block';

        const segments = [
            { d: 'M23.75,16A7.7446,7.7446,0,0,1,8.7177,18.6259L4.2849,22.1721A13.244,13.244,0,0,0,29.25,16', fill: '#00ac47' },
            { d: 'M23.75,16a7.7387,7.7387,0,0,1-3.2516,6.2987l4.3824,3.5059A13.2042,13.2042,0,0,0,29.25,16', fill: '#4285f4' },
            { d: 'M8.25,16a7.698,7.698,0,0,1,.4677-2.6259L4.2849,9.8279a13.177,13.177,0,0,0,0,12.3442l4.4328-3.5462A7.698,7.698,0,0,1,8.25,16Z', fill: '#ffba00' },
            { d: 'M16,8.25a7.699,7.699,0,0,1,4.558,1.4958l4.06-3.7893A13.2152,13.2152,0,0,0,4.2849,9.8279l4.4328,3.5462A7.756,7.756,0,0,1,16,8.25Z', fill: '#ea4435' },
            { d: 'M29.25,15v1L27,19.5H16.5V14H28.25A1,1,0,0,1,29.25,15Z', fill: '#4285f4' }
        ];

        segments.forEach(({ d, fill }) => {
            const path = document.createElementNS(SVG_NS, 'path');
            path.setAttribute('d', d);
            path.setAttribute('fill', fill);
            svg.appendChild(path);
        });

        return svg;
    };

    // 用于统一创建 overlay + dialog,样式与默认逻辑保持一致
    // 复用时只需传入自定义的内容与回调,外观也可统一
    function createUnifiedDialog(options) {
        const {
            title = '弹窗标题',
            width = '400px',
            maxHeight = '80vh',
            onClose = null, // 关闭时的回调
            closeOnOverlayClick = true
        } = options;

        // 创建overlay
        const overlay = document.createElement('div');
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100%';
        overlay.style.height = '100%';
        overlay.style.backgroundColor = 'var(--overlay-bg, rgba(0,0,0,0.5))';
        overlay.style.backdropFilter = 'blur(2px)';
        overlay.style.zIndex = '12000';
        overlay.style.display = 'flex';
        overlay.style.justifyContent = 'center';
        overlay.style.alignItems = 'center';
        overlay.style.opacity = '0';
        overlay.style.transition = 'opacity 0.3s ease';

        // 创建dialog
        const dialog = document.createElement('div');
        dialog.classList.add('cttf-dialog');
        dialog.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
        dialog.style.color = 'var(--text-color, #333333)';
        dialog.style.borderRadius = '4px';
        dialog.style.padding = '24px';
        dialog.style.boxShadow = '0 8px 24px var(--shadow-color, rgba(0,0,0,0.1))';
        dialog.style.border = '1px solid var(--border-color, #e5e7eb)';
        dialog.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
        dialog.style.width = width;
        dialog.style.maxWidth = '95vw';
        dialog.style.maxHeight = maxHeight;
        dialog.style.overflowY = 'auto';
        dialog.style.transform = 'scale(0.95)';

        // 标题
        const titleEl = document.createElement('h2');
        titleEl.textContent = title;
        titleEl.style.margin = '0';
        titleEl.style.marginBottom = '12px';
        titleEl.style.fontSize = '18px';
        titleEl.style.fontWeight = '600';
        dialog.appendChild(titleEl);

        // 向overlay添加dialog
        overlay.appendChild(dialog);

        // 将 overlay 挂载到 Shadow DOM 覆盖层
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);

        // 入场动画
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        if (closeOnOverlayClick) {
            overlay.addEventListener('click', (e) => {
                if (e.target === overlay) {
                    if (onClose) onClose();
                    overlay.remove();
                }
            });
        } else {
            overlay.addEventListener('click', (e) => {
                if (e.target === overlay) {
                    e.stopPropagation();
                    e.preventDefault();
                }
            });
        }

        return { overlay, dialog };
    }

    // 主题样式配置(使用CSS变量)
    const applyThemeToHost = (themeValues) => {
        const root = ensureUIRoot();
        const host = root ? root.host : null;
        if (!host) {
            return;
        }
        Object.entries(themeValues).forEach(([key, value]) => {
            host.style.setProperty(toCSSVariableName(key), value);
        });
    };

    const setCSSVariables = (currentTheme) => {
        latestThemeValues = currentTheme;
        const apply = () => applyThemeToHost(currentTheme);

        if (document.body) {
            apply();
        } else {
            window.addEventListener('DOMContentLoaded', apply, { once: true });
        }
    };

    const theme = {
        light: {
            folderBg: 'rgba(255, 255, 255, 0.8)',
            dialogBg: '#ffffff',
            textColor: '#333333',
            borderColor: '#e5e7eb',
            shadowColor: 'rgba(0, 0, 0, 0.1)',
            buttonBg: '#f3f4f6',
            buttonHoverBg: '#e5e7eb',
            dangerColor: '#ef4444',
            successColor: '#22c55e',
            addColor: '#fd7e14',
            primaryColor: '#3B82F6',
            infoColor: '#6366F1',
            cancelColor: '#6B7280',
            overlayBg: 'rgba(0, 0, 0, 0.5)',
            tabBg: '#f3f4f6',
            tabActiveBg: '#3B82F6',
            tabHoverBg: '#e5e7eb',
            tabBorder: '#e5e7eb'
        },
        dark: {
            folderBg: 'rgba(31, 41, 55, 0.8)',
            dialogBg: '#1f2937',
            textColor: '#e5e7eb',
            borderColor: '#374151',
            shadowColor: 'rgba(0, 0, 0, 0.3)',
            buttonBg: '#374151',
            buttonHoverBg: '#4b5563',
            dangerColor: '#dc2626',
            successColor: '#16a34a',
            addColor: '#fd7e14',
            primaryColor: '#2563EB',
            infoColor: '#4F46E5',
            cancelColor: '#4B5563',
            overlayBg: 'rgba(0, 0, 0, 0.7)',
            tabBg: '#374151',
            tabActiveBg: '#2563EB',
            tabHoverBg: '#4b5563',
            tabBorder: '#4b5563'
        }
    };

    const isDarkMode = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
    const getCurrentTheme = () => isDarkMode() ? theme.dark : theme.light;

    setCSSVariables(getCurrentTheme());

    const styles = {
        overlay: {
            position: 'fixed',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            backgroundColor: 'var(--overlay-bg, rgba(0, 0, 0, 0.5))',
            backdropFilter: 'blur(2px)',
            zIndex: 10000,
            display: 'flex',
            justifyContent: 'center',
            alignItems: 'center',
            transition: 'background-color 0.3s ease, opacity 0.3s ease'
        },
        dialog: {
            position: 'relative',
            backgroundColor: 'var(--dialog-bg, #ffffff)',
            color: 'var(--text-color, #333333)',
            borderRadius: '4px',
            padding: '24px',
            boxShadow: '0 8px 24px var(--shadow-color, rgba(0,0,0,0.1))',
            border: '1px solid var(--border-color, #e5e7eb)',
            transition: 'transform 0.3s ease, opacity 0.3s ease',
            maxWidth: '90vw',
            maxHeight: '80vh',
            overflow: 'auto'
        },
        button: {
            padding: '8px 16px',
            borderRadius: '4px',
            border: 'none',
            cursor: 'pointer',
            transition: 'background-color 0.2s ease, color 0.2s ease',
            fontSize: '14px',
            fontWeight: '500',
            backgroundColor: 'var(--button-bg, #f3f4f6)',
            color: 'var(--text-color, #333333)'
        }
    };

    // 默认按钮
    const userProvidedButtons = {
        "Review": {
            type: "template",
            text: "You are a code review expert:\n\n{clipboard}\n\nProvide constructive feedback and improvements.\n",
            color: "#E6E0FF",
            textColor: "#333333",
            autoSubmit: false // 新增字段
        },
        // ... (其他默认按钮保持不变)
        "解释": {
            type: "template",
            text: "Explain the following code concisely:\n\n{clipboard}\n\nFocus on key functionality and purpose.\n",
            color: "#ffebcc",
            textColor: "#333333",
            autoSubmit: false // 新增字段
        }
    };

    // 默认工具按钮
    const defaultToolButtons = {
        "剪切": {
            type: "tool",
            action: "cut",
            color: "#FFC1CC",
            textColor: "#333333"
        },
        "复制": {
            type: "tool",
            action: "copy",
            color: "#C1FFD7",
            textColor: "#333333"
        },
        "粘贴": {
            type: "tool",
            action: "paste",
            color: "#C1D8FF",
            textColor: "#333333"
        },
        "清空": {
            type: "tool",
            action: "clear",
            color: "#FFD1C1",
            textColor: "#333333"
        }
    };
    const TOOL_DEFAULT_ICONS = {
        cut: '✂️',
        copy: '📋',
        paste: '📥',
        clear: '✖️'
    };

    const generateDomainFavicon = (domain) => {
        if (!domain) return '';
        const trimmed = domain.replace(/^https?:\/\//, '').replace(/\/.*$/, '');
        return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(trimmed)}&sz=32`;
    };

    const createFaviconElement = (faviconUrl, label, fallbackEmoji = '🌐', options = {}) => {
        const { withBackground = true, size = 32 } = options || {};
        const normalizedSize = Math.max(16, Math.min(48, Number(size) || 32));
        const contentSize = Math.max(12, normalizedSize - 4);
        const emojiFontSize = Math.max(10, normalizedSize - 10);
        const borderRadius = Math.round(normalizedSize / 4);

        const wrapper = document.createElement('div');
        wrapper.style.width = `${normalizedSize}px`;
        wrapper.style.height = `${normalizedSize}px`;
        wrapper.style.borderRadius = `${borderRadius}px`;
        wrapper.style.overflow = 'hidden';
        wrapper.style.display = 'flex';
        wrapper.style.alignItems = 'center';
        wrapper.style.justifyContent = 'center';
        wrapper.style.backgroundColor = withBackground ? 'rgba(148, 163, 184, 0.15)' : 'transparent';
        wrapper.style.flexShrink = '0';

        if (faviconUrl) {
            const img = document.createElement('img');
            img.src = faviconUrl;
            img.alt = label || 'site icon';
            img.style.width = `${contentSize}px`;
            img.style.height = `${contentSize}px`;
            img.style.objectFit = 'cover';
            img.referrerPolicy = 'no-referrer';
            img.loading = 'lazy';
            img.onerror = () => {
                setTrustedHTML(wrapper, '');
                const emoji = document.createElement('span');
                emoji.textContent = fallbackEmoji;
                emoji.style.fontSize = `${emojiFontSize}px`;
                wrapper.appendChild(emoji);
            };
            wrapper.appendChild(img);
        } else {
            const emoji = document.createElement('span');
            emoji.textContent = fallbackEmoji;
            emoji.style.fontSize = `${emojiFontSize}px`;
            wrapper.appendChild(emoji);
        }

        return wrapper;
    };

    // 默认配置
    const defaultConfig = {
        folders: {
            "默认": {
                color: "#3B82F6",
                textColor: "#ffffff",
                hidden: false, // 新增隐藏状态字段
                buttons: userProvidedButtons
            },
            "🖱️": {
                color: "#FFD700", // 金色,可根据需求调整
                textColor: "#ffffff",
                hidden: false, // 新增隐藏状态字段
                buttons: defaultToolButtons
            }
        },
        folderOrder: ["默认", "🖱️"],
        domainAutoSubmitSettings: [
            {
                domain: "chatgpt.com",
                name: "ChatGPT",
                method: "模拟点击提交按钮",
                favicon: generateDomainFavicon("chatgpt.com")
            },
            {
                domain: "chathub.gg",
                name: "ChatHub",
                method: "Enter",
                favicon: generateDomainFavicon("chathub.gg")
            }
        ],
        /**
         * domainStyleSettings: 数组,每个元素结构示例:
         * {
         *   domain: "chatgpt.com",
         *   name: "ChatGPT自定义样式",
         *   height: 90,
         *   cssCode: ".some-class { color: red; }"
         * }
         */
        domainStyleSettings: []
    };

    defaultConfig.buttonBarHeight = 40;
    defaultConfig.buttonBarBottomSpacing = 0;

    let buttonConfig = JSON.parse(localStorage.getItem('chatGPTButtonFoldersConfig')) || JSON.parse(JSON.stringify(defaultConfig));

    if (!Array.isArray(buttonConfig.domainStyleSettings)) {
        buttonConfig.domainStyleSettings = [];
    }

    if (typeof buttonConfig.buttonBarHeight !== 'number') {
        buttonConfig.buttonBarHeight = defaultConfig.buttonBarHeight;
    }

    if (typeof buttonConfig.buttonBarBottomSpacing !== 'number') {
        buttonConfig.buttonBarBottomSpacing = defaultConfig.buttonBarBottomSpacing;
    }
    buttonConfig.buttonBarBottomSpacing = Math.max(-200, Math.min(200, Number(buttonConfig.buttonBarBottomSpacing) || 0));

    // 若本地无此字段,则初始化
    if (!buttonConfig.domainAutoSubmitSettings) {
        buttonConfig.domainAutoSubmitSettings = JSON.parse(
            JSON.stringify(defaultConfig.domainAutoSubmitSettings)
        );
        localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
    }

    // 确保所有按钮都有'type'字段
    const ensureButtonTypes = () => {
        let updated = false;
        Object.entries(buttonConfig.folders).forEach(([folderName, folderConfig]) => {
            // 确保文件夹有hidden字段
            if (typeof folderConfig.hidden !== 'boolean') {
                folderConfig.hidden = false;
                updated = true;
            }

            Object.entries(folderConfig.buttons).forEach(([btnName, btnConfig]) => {
                if (!btnConfig.type) {
                    if (folderName === "🖱️") {
                        btnConfig.type = "tool";
                        updated = true;
                    } else {
                        btnConfig.type = "template";
                        updated = true;
                    }
                }
                // 确保 'autoSubmit' 字段存在,对于模板按钮
                if (btnConfig.type === "template" && typeof btnConfig.autoSubmit !== 'boolean') {
                    btnConfig.autoSubmit = false;
                    updated = true;
                }
                if (btnConfig.type === "template" && typeof btnConfig.favicon !== 'string') {
                    btnConfig.favicon = '';
                    updated = true;
                }
            });
        });
        if (updated) {
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            console.log("✅ 已确保所有按钮具有'type'、'autoSubmit'、'favicon'配置,以及文件夹具有'hidden'字段。");
        }
    };

    const ensureDomainMetadata = () => {
        let updated = false;
        (buttonConfig.domainAutoSubmitSettings || []).forEach(rule => {
            if (!rule.favicon) {
                rule.favicon = generateDomainFavicon(rule.domain);
                updated = true;
            }
        });
        (buttonConfig.domainStyleSettings || []).forEach(item => {
            if (!item.favicon) {
                item.favicon = generateDomainFavicon(item.domain);
                updated = true;
            }
            if (typeof item.bottomSpacing !== 'number') {
                item.bottomSpacing = buttonConfig.buttonBarBottomSpacing;
                updated = true;
            } else {
                const clamped = Math.max(-200, Math.min(200, Number(item.bottomSpacing) || 0));
                if (clamped !== item.bottomSpacing) {
                    item.bottomSpacing = clamped;
                    updated = true;
                }
            }
        });
        if (updated) {
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            console.log("✅ 已为自动化与样式配置补全 favicon 信息。");
        }
    };

    ensureButtonTypes();
    ensureDomainMetadata();

    // 确保工具文件夹存在并包含必要的工具按钮
    const ensureToolFolder = () => {
        const toolFolderName = "🖱️";
        if (!buttonConfig.folders[toolFolderName]) {
            buttonConfig.folders[toolFolderName] = {
                color: "#FFD700",
                textColor: "#ffffff",
                buttons: defaultToolButtons
            };
            buttonConfig.folderOrder.push(toolFolderName);
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            console.log(`✅ 工具文件夹 "${toolFolderName}" 已添加到配置中。`);
        } else {
            // 确保工具按钮存在
            Object.entries(defaultToolButtons).forEach(([btnName, btnCfg]) => {
                if (!buttonConfig.folders[toolFolderName].buttons[btnName]) {
                    buttonConfig.folders[toolFolderName].buttons[btnName] = btnCfg;
                    console.log(`✅ 工具按钮 "${btnName}" 已添加到文件夹 "${toolFolderName}"。`);
                }
            });
        }
    };
    ensureToolFolder();

    // 变量:防止重复提交
    let isSubmitting = false;
    // 占位函数,避免在真正实现前调用报错
    let applyDomainStyles = () => {};
    let updateButtonBarLayout = () => {};

    const getAllTextareas = (root = document) => {
        let textareas = [];
        const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null, false);
        let node = walker.nextNode();
        while (node) {
            if (node.tagName && (node.tagName.toLowerCase() === 'textarea' || node.getAttribute('contenteditable') === 'true')) {
                textareas.push(node);
            }
            if (node.shadowRoot) {
                textareas = textareas.concat(getAllTextareas(node.shadowRoot));
            }
            node = walker.nextNode();
        }
        return textareas;
    };

    /**
     * 增强版插入文本到textarea或contenteditable元素中,支持现代编辑器
     * @param {HTMLElement} target - 目标元素
     * @param {string} finalText - 要插入的文本
     * @param {boolean} replaceAll - 是否替换全部内容
     */
    const insertTextSmart = (target, finalText, replaceAll = false) => {
        const normalizedText = finalText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');

        if (target.tagName.toLowerCase() === 'textarea') {
            // 处理textarea - 保持原有逻辑
            if (replaceAll) {
                const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value').set;
                nativeSetter.call(target, normalizedText);
                target.selectionStart = target.selectionEnd = normalizedText.length;
                const inputEvent = new InputEvent('input', {
                    bubbles: true,
                    cancelable: true,
                    inputType: 'insertReplacementText',
                    data: normalizedText,
                });
                target.dispatchEvent(inputEvent);
            } else {
                const start = target.selectionStart;
                const end = target.selectionEnd;
                const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value').set;
                nativeSetter.call(target, target.value.substring(0, start) + normalizedText + target.value.substring(end));
                target.selectionStart = target.selectionEnd = start + normalizedText.length;
                const inputEvent = new InputEvent('input', {
                    bubbles: true,
                    cancelable: true,
                    inputType: 'insertText',
                    data: normalizedText,
                });
                target.dispatchEvent(inputEvent);
            }
            target.focus();
        } else if (target.getAttribute('contenteditable') === 'true') {
            // 增强的contenteditable处理
            insertIntoContentEditable(target, normalizedText, replaceAll);
        }
    };

    /**
     * 专门处理contenteditable元素的文本插入
     * @param {HTMLElement} target - contenteditable元素
     * @param {string} text - 要插入的文本
     * @param {boolean} replaceAll - 是否替换全部内容
     */
    const insertIntoContentEditable = (target, text, replaceAll) => {
        // 检测编辑器类型
        const editorType = detectEditorType(target);

        target.focus();

        if (replaceAll) {
            // 替换全部内容
            clearContentEditable(target, editorType);
        }

        // 插入文本
        insertTextIntoEditor(target, text, editorType);

        // 触发事件和调整高度
        triggerEditorEvents(target, text, replaceAll);
        adjustEditorHeight(target, editorType);
    };

    /**
     * 检测编辑器类型
     * @param {HTMLElement} target
     * @returns {string} 编辑器类型
     */
    const detectEditorType = (target) => {
        // 检测ProseMirror
        if (target.classList.contains('ProseMirror') ||
            target.closest('.ProseMirror') ||
            target.querySelector('.ProseMirror-trailingBreak')) {
            return 'prosemirror';
        }

        // 检测其他特殊编辑器
        if (target.hasAttribute('data-placeholder') ||
            target.querySelector('[data-placeholder]')) {
            return 'modern';
        }

        // 默认简单contenteditable
        return 'simple';
    };

    /**
     * 清空contenteditable内容
     * @param {HTMLElement} target
     * @param {string} editorType
     */
    const clearContentEditable = (target, editorType) => {
        if (editorType === 'prosemirror') {
            // ProseMirror需要保持基本结构
            const firstP = target.querySelector('p');
            if (firstP) {
                setTrustedHTML(firstP, '<br class="ProseMirror-trailingBreak">');
                // 删除其他段落
                const otherPs = target.querySelectorAll('p:not(:first-child)');
                otherPs.forEach(p => p.remove());
            } else {
                setTrustedHTML(target, '<p><br class="ProseMirror-trailingBreak"></p>');
            }
        } else {
            setTrustedHTML(target, '');
        }
    };

    /**
     * 向编辑器插入文本
     * @param {HTMLElement} target
     * @param {string} text
     * @param {string} editorType
     */
    const insertTextIntoEditor = (target, text, editorType) => {
        const selection = window.getSelection();

        if (editorType === 'prosemirror') {
            insertIntoProseMirror(target, text, selection);
        } else {
            insertIntoSimpleEditor(target, text, selection);
        }

        // 确保光标位置正确
        const range = document.createRange();
        range.selectNodeContents(target);
        range.collapse(false);
        selection.removeAllRanges();
        selection.addRange(range);
    };

    /**
     * 向ProseMirror编辑器插入文本
     * @param {HTMLElement} target
     * @param {string} text
     * @param {Selection} selection
     */
    const insertIntoProseMirror = (target, text, selection) => {
        const lines = text.split('\n');
        let currentP = target.querySelector('p');

        if (!currentP) {
            currentP = document.createElement('p');
            target.appendChild(currentP);
        }

        // 清除现有内容但保持结构
        const trailingBreak = currentP.querySelector('.ProseMirror-trailingBreak');
        if (trailingBreak) {
            trailingBreak.remove();
        }

        lines.forEach((line, index) => {
            if (index > 0) {
                // 创建新段落
                currentP = document.createElement('p');
                target.appendChild(currentP);
            }

            if (line.trim() === '') {
                // 空行需要br
                const br = document.createElement('br');
                br.className = 'ProseMirror-trailingBreak';
                currentP.appendChild(br);
            } else {
                // 有内容的行
                currentP.appendChild(document.createTextNode(line));
                if (index === lines.length - 1) {
                    // 最后一行添加trailing break
                    const br = document.createElement('br');
                    br.className = 'ProseMirror-trailingBreak';
                    currentP.appendChild(br);
                }
            }
        });

        // 移除is-empty类
        target.classList.remove('is-empty', 'is-editor-empty');
        target.querySelectorAll('p').forEach(p => {
            p.classList.remove('is-empty', 'is-editor-empty');
        });
    };

    /**
     * 向简单编辑器插入文本
     * @param {HTMLElement} target
     * @param {string} text
     * @param {Selection} selection
     */
    const insertIntoSimpleEditor = (target, text, selection) => {
        const lines = text.split('\n');
        const fragment = document.createDocumentFragment();

        lines.forEach((line, index) => {
            if (line === '') {
                fragment.appendChild(document.createElement('br'));
            } else {
                fragment.appendChild(document.createTextNode(line));
            }

            if (index < lines.length - 1) {
                fragment.appendChild(document.createElement('br'));
            }
        });

        // 使用Selection API插入
        if (selection.rangeCount > 0) {
            const range = selection.getRangeAt(0);
            range.deleteContents();
            range.insertNode(fragment);
            range.collapse(false);
        } else {
            target.appendChild(fragment);
        }
    };

    /**
     * 触发编辑器事件
     * @param {HTMLElement} target
     * @param {string} text
     * @param {boolean} replaceAll
     */
    const triggerEditorEvents = (target, text, replaceAll) => {
        // 触发多种事件确保兼容性
        const events = [
            new InputEvent('beforeinput', {
                bubbles: true,
                cancelable: true,
                inputType: replaceAll ? 'insertReplacementText' : 'insertText',
                data: text
            }),
            new InputEvent('input', {
                bubbles: true,
                cancelable: true,
                inputType: replaceAll ? 'insertReplacementText' : 'insertText',
                data: text
            }),
            new Event('change', { bubbles: true }),
            new KeyboardEvent('keyup', { bubbles: true }),
            new Event('blur', { bubbles: true }),
            new Event('focus', { bubbles: true })
        ];

        events.forEach(event => {
            try {
                target.dispatchEvent(event);
            } catch (e) {
                console.warn('事件触发失败:', e);
            }
        });

        // 特殊处理:触发compositionend事件(某些框架需要)
        try {
            const compositionEvent = new CompositionEvent('compositionend', {
                bubbles: true,
                data: text
            });
            target.dispatchEvent(compositionEvent);
        } catch (e) {
            // CompositionEvent可能不被支持,忽略错误
        }
    };

    /**
     * 调整编辑器高度
     * @param {HTMLElement} target
     * @param {string} editorType
     */
    const adjustEditorHeight = (target, editorType) => {
        // 查找可能需要调整的容器
        const containers = [
            target,
            target.parentElement,
            target.closest('[style*="height"]'),
            target.closest('[style*="max-height"]'),
            target.closest('.overflow-hidden'),
            target.closest('[style*="overflow"]')
        ].filter(Boolean);

        containers.forEach(container => {
            try {
                // 移除可能阻止显示的样式
                if (container.style.height && container.style.height !== 'auto') {
                    const currentHeight = parseInt(container.style.height);
                    if (currentHeight < 100) { // 只调整明显过小的高度
                        container.style.height = 'auto';
                        container.style.minHeight = currentHeight + 'px';
                    }
                }

                // 确保显示滚动条
                if (container.style.overflowY === 'hidden') {
                    container.style.overflowY = 'auto';
                }

                // 对于特定的编辑器容器,强制最小高度
                if (editorType === 'prosemirror' && container === target) {
                    container.style.minHeight = '3rem';
                }

            } catch (e) {
                console.warn('高度调整失败:', e);
            }
        });

        // 触发resize事件
        setTimeout(() => {
            try {
                window.dispatchEvent(new Event('resize'));
                target.dispatchEvent(new Event('resize'));
            } catch (e) {
                console.warn('resize事件触发失败:', e);
            }
        }, 100);
    };

    /**
   * 轮询检测输入框内容是否与预期文本一致。
   * @param {HTMLElement} element - 要检测的textarea或contenteditable元素。
   * @param {string} expectedText - 期望出现的文本。
   * @param {number} interval - 轮询时间间隔(毫秒)。
   * @param {number} maxWait - 最大等待时长(毫秒),超时后reject。
   * @returns {Promise<void>} - 匹配成功resolve,否则reject。
   */
    async function waitForContentMatch(element, expectedText, interval = 100, maxWait = 3000) {
        return new Promise((resolve, reject) => {
            let elapsed = 0;
            const timer = setInterval(() => {
                elapsed += interval;
                const currentVal = (element.tagName.toLowerCase() === 'textarea')
                    ? element.value
                    : element.innerText; // contenteditable时用innerText

                if (currentVal === expectedText) {
                    clearInterval(timer);
                    resolve();
                } else if (elapsed >= maxWait) {
                    clearInterval(timer);
                    reject(new Error("waitForContentMatch: 超时,输入框内容未能匹配预期文本"));
                }
            }, interval);
        });
    }

    // 定义等待提交按钮的函数
    const waitForSubmitButton = async (maxAttempts = 10, delay = 300) => {
        for (let i = 0; i < maxAttempts; i++) {
            const submitButton = document.querySelector('button[type="submit"], button[data-testid="send-button"]');
            if (submitButton && !submitButton.disabled && submitButton.offsetParent !== null) {
                return submitButton;
            }
            await new Promise(resolve => setTimeout(resolve, delay));
        }
        return null;
    };

    // 定义等待时间和尝试次数
    const SUBMIT_WAIT_MAX_ATTEMPTS = 10;
    const SUBMIT_WAIT_DELAY = 300; // 毫秒

    const waitForElementBySelector = async (selector, maxAttempts = SUBMIT_WAIT_MAX_ATTEMPTS, delay = SUBMIT_WAIT_DELAY) => {
        if (!selector) return null;
        for (let i = 0; i < maxAttempts; i++) {
            let element = null;
            try {
                element = document.querySelector(selector);
            } catch (error) {
                console.warn(`⚠️ 自定义选择器 "${selector}" 解析失败:`, error);
                return null;
            }

            if (element) {
                const isDisabled = typeof element.disabled === 'boolean' && element.disabled;
                if (!isDisabled) {
                    return element;
                }
            }
            await new Promise(resolve => setTimeout(resolve, delay));
        }
        return null;
    };

    function simulateEnterKey() {
        const eventInit = {
            bubbles: true,
            cancelable: true,
            key: "Enter",
            code: "Enter",
            keyCode: 13,
            which: 13
        };
        const keyboardEvent = new KeyboardEvent('keydown', eventInit);
        document.activeElement.dispatchEvent(keyboardEvent);
    }

    function simulateCmdEnterKey() {
        const eventInit = {
            bubbles: true,
            cancelable: true,
            key: "Enter",
            code: "Enter",
            keyCode: 13,
            which: 13,
            metaKey: true
        };
        const keyboardEvent = new KeyboardEvent('keydown', eventInit);
        document.activeElement.dispatchEvent(keyboardEvent);
    }

    function simulateCtrlEnterKey() {
        const eventInit = {
            bubbles: true,
            cancelable: true,
            key: "Enter",
            code: "Enter",
            keyCode: 13,
            which: 13,
            ctrlKey: true
        };
        const keyboardEvent = new KeyboardEvent('keydown', eventInit);
        document.activeElement.dispatchEvent(keyboardEvent);
    }
    // 定义多种提交方式
    const submitForm = async () => {
        if (isSubmitting) {
            console.warn("⚠️ 提交正在进行中,跳过重复提交。");
            return false;
        }
        isSubmitting = true;
        try {
              const domainRules = buttonConfig.domainAutoSubmitSettings || [];
              const currentURL = window.location.href;
              const matchedRule = domainRules.find(rule => currentURL.includes(rule.domain));

              if (matchedRule) {
                  console.log("🔎 检测到本域名匹配的自动提交规则:", matchedRule);
                  switch (matchedRule.method) {
                      case "Enter": {
                          simulateEnterKey();
                          isSubmitting = false;
                          return true;
                      }
                      case "Cmd+Enter": {
                          const variant = matchedRule.methodAdvanced && matchedRule.methodAdvanced.variant === 'ctrl'
                              ? 'ctrl'
                              : 'cmd';
                          if (variant === 'ctrl') {
                              simulateCtrlEnterKey();
                              console.log("✅ 已根据自动化规则,触发 Ctrl + Enter 提交。");
                          } else {
                              simulateCmdEnterKey();
                              console.log("✅ 已根据自动化规则,触发 Cmd + Enter 提交。");
                          }
                          isSubmitting = false;
                          return true;
                      }
                      case "模拟点击提交按钮": {
                          const advanced = matchedRule.methodAdvanced || {};
                          const selector = typeof advanced.selector === 'string' ? advanced.selector.trim() : '';
                          if (advanced.variant === 'selector' && selector) {
                              const customButton = await waitForElementBySelector(selector, SUBMIT_WAIT_MAX_ATTEMPTS, SUBMIT_WAIT_DELAY);
                              if (customButton) {
                                  customButton.click();
                                  console.log(`✅ 已根据自动化规则,自定义选择器 "${selector}" 提交。`);
                                  isSubmitting = false;
                                  return true;
                              }
                              console.warn(`⚠️ 自定义选择器 "${selector}" 未匹配到提交按钮,尝试默认规则。`);
                          }
                          const submitButton = await waitForSubmitButton(SUBMIT_WAIT_MAX_ATTEMPTS, SUBMIT_WAIT_DELAY);
                          if (submitButton) {
                              submitButton.click();
                              console.log("✅ 已根据自动化规则,模拟点击提交按钮。");
                              isSubmitting = false;
                              return true;
                          } else {
                              console.warn("⚠️ 未找到提交按钮,进入fallback...");
                          }
                          break;
                      }
                      default:
                          console.warn("⚠️ 未知自动提交方式,进入fallback...");
                          break;
                  }
            }
            // 1. 尝试键盘快捷键提交
            const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
            const submitKeys = isMac ? ['Enter', 'Meta+Enter'] : ['Enter', 'Control+Enter'];
            for (const keyCombo of submitKeys) {
                const [key, modifier] = keyCombo.split('+');
                const eventInit = {
                    bubbles: true,
                    cancelable: true,
                    key: key,
                    code: key,
                    keyCode: key.charCodeAt(0),
                    which: key.charCodeAt(0),
                };
                if (modifier === 'Meta') eventInit.metaKey = true;
                if (modifier === 'Control') eventInit.ctrlKey = true;
                const keyboardEvent = new KeyboardEvent('keydown', eventInit);
                document.activeElement.dispatchEvent(keyboardEvent);
                console.log(`尝试通过键盘快捷键提交表单:${keyCombo}`);
                // 等待短暂时间,查看是否提交成功
                await new Promise(resolve => setTimeout(resolve, 500));
                // 检查是否页面已提交(可以通过某种标识来确认)
                // 这里假设页面会有某种变化,如URL变化或特定元素出现
                // 由于具体实现不同,这里仅提供日志
            }

            // 2. 尝试点击提交按钮
            const submitButton = await waitForSubmitButton(SUBMIT_WAIT_MAX_ATTEMPTS, SUBMIT_WAIT_DELAY);
            if (submitButton) {
                submitButton.click();
                console.log("✅ 自动提交已通过点击提交按钮触发。");
                return true;
            } else {
                console.warn("⚠️ 未找到提交按钮,尝试其他提交方式。");
            }

            // 3. 尝试调用JavaScript提交函数
            // 需要知道具体的提交函数名称,这里假设为 `submitForm`
            // 根据实际情况调整函数名称
            try {
                if (typeof submitForm === 'function') {
                    submitForm();
                    console.log("✅ 自动提交已通过调用JavaScript函数触发。");
                    return true;
                } else {
                    console.warn("⚠️ 未找到名为 'submitForm' 的提交函数。");
                }
            } catch (error) {
                console.error("调用JavaScript提交函数失败:", error);
            }

            // 4. 确保事件监听器触发
            // 重新触发 'submit' 事件
            try {
                const form = document.querySelector('form');
                if (form) {
                    const submitEvent = new Event('submit', {
                        bubbles: true,
                        cancelable: true
                    });
                    form.dispatchEvent(submitEvent);
                    console.log("✅ 自动提交已通过触发 'submit' 事件触发。");
                    return true;
                } else {
                    console.warn("⚠️ 未找到表单元素,无法触发 'submit' 事件。");
                }
            } catch (error) {
                console.error("触发 'submit' 事件失败:", error);
            }

            console.warn("⚠️ 所有自动提交方式均未成功。");
            return false;
        } finally {
            isSubmitting = false;
        }
    };

    const formatButtonDisplayLabel = (label) => {
        if (typeof label !== 'string') {
            return '';
        }
        const firstSpaceIndex = label.indexOf(' ');
        if (firstSpaceIndex > 0 && firstSpaceIndex < label.length - 1) {
            const leadingSegment = label.slice(0, firstSpaceIndex);
            const remainingText = label.slice(firstSpaceIndex + 1);

            // 如果前缀没有字母或数字(通常是emoji/符号),且长度不超过4,则将首个空格替换为不换行空格
            const hasAlphaNumeric = /[0-9A-Za-z\u4E00-\u9FFF]/.test(leadingSegment);
            if (!hasAlphaNumeric && leadingSegment.length <= 4 && remainingText.trim().length > 0) {
                return `${leadingSegment}\u00A0${remainingText}`;
            }
        }
        return label;
    };

    const extractButtonIconParts = (label) => {
        if (typeof label !== 'string') {
            return { iconSymbol: '', textLabel: '' };
        }

        const trimmedStart = label.trimStart();
        if (!trimmedStart) {
            return { iconSymbol: '', textLabel: '' };
        }

        const firstSpaceIndex = trimmedStart.indexOf(' ');
        if (firstSpaceIndex > 0) {
            const leadingSegment = trimmedStart.slice(0, firstSpaceIndex);
            const remaining = trimmedStart.slice(firstSpaceIndex + 1).trimStart();
            const hasAlphaNumeric = /[0-9A-Za-z\u4E00-\u9FFF]/.test(leadingSegment);
            if (!hasAlphaNumeric) {
                return {
                    iconSymbol: leadingSegment,
                    textLabel: remaining || trimmedStart
                };
            }
        }

        const charUnits = Array.from(trimmedStart);
        const firstChar = charUnits[0] || '';
        if (firstChar && !/[0-9A-Za-z\u4E00-\u9FFF]/.test(firstChar)) {
            const remaining = trimmedStart.slice(firstChar.length).trimStart();
            return {
                iconSymbol: firstChar,
                textLabel: remaining || trimmedStart
            };
        }

        return {
            iconSymbol: '',
            textLabel: trimmedStart
        };
    };

    const createCustomButtonElement = (name, config) => {
        const button = document.createElement('button');
        const { iconSymbol, textLabel } = extractButtonIconParts(name);
        const labelForDisplay = textLabel || name || '';
        const displayLabel = formatButtonDisplayLabel(labelForDisplay);
        let fallbackSymbolSource = iconSymbol || (Array.from(labelForDisplay.trim())[0] || '🔖');
        if (config.type === 'tool' && TOOL_DEFAULT_ICONS[config.action]) {
            fallbackSymbolSource = TOOL_DEFAULT_ICONS[config.action];
        }
        button.textContent = '';
        button.setAttribute('data-original-label', name);
        button.type = 'button';
        button.style.backgroundColor = config.color;
        button.style.color = config.textColor || '#333333';
        button.style.border = '1px solid rgba(0,0,0,0.1)';
        button.style.borderRadius = '4px';
        button.style.padding = '6px 12px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.transition = 'all 0.2s ease';
        button.style.boxShadow = '0 2px 4px rgba(0,0,0,0.05)';
        button.style.marginBottom = '6px';
        button.style.width = 'fit-content';
        button.style.textAlign = 'left';
        button.style.display = 'block';

        const contentWrapper = document.createElement('span');
        contentWrapper.style.display = 'inline-flex';
        contentWrapper.style.alignItems = 'center';
        contentWrapper.style.gap = '8px';

        const iconWrapper = document.createElement('span');
        iconWrapper.style.display = 'inline-flex';
        iconWrapper.style.alignItems = 'center';
        iconWrapper.style.justifyContent = 'center';
        iconWrapper.style.width = '18px';
        iconWrapper.style.height = '18px';
        iconWrapper.style.flexShrink = '0';
        iconWrapper.style.borderRadius = '4px';
        iconWrapper.style.overflow = 'hidden';

        const createFallbackIcon = (symbol) => {
            const fallbackSpan = document.createElement('span');
            fallbackSpan.textContent = symbol;
            fallbackSpan.style.fontSize = '14px';
            fallbackSpan.style.lineHeight = '1';
            fallbackSpan.style.display = 'inline-flex';
            fallbackSpan.style.alignItems = 'center';
            fallbackSpan.style.justifyContent = 'center';
            return fallbackSpan;
        };

        const faviconUrl = (config && typeof config.favicon === 'string') ? config.favicon.trim() : '';
        if (faviconUrl) {
            const img = document.createElement('img');
            img.src = faviconUrl;
            img.alt = (labelForDisplay || name || '').trim() || 'icon';
            img.style.width = '100%';
            img.style.height = '100%';
            img.style.objectFit = 'contain';
            img.loading = 'lazy';
            img.referrerPolicy = 'no-referrer';
            img.decoding = 'async';
            img.onerror = () => {
                iconWrapper.textContent = '';
                iconWrapper.appendChild(createFallbackIcon(fallbackSymbolSource));
            };
            iconWrapper.appendChild(img);
        } else {
            iconWrapper.appendChild(createFallbackIcon(fallbackSymbolSource));
        }

        const textSpan = document.createElement('span');
        textSpan.textContent = displayLabel;
        textSpan.style.display = 'inline-flex';
        textSpan.style.alignItems = 'center';

        contentWrapper.appendChild(iconWrapper);
        contentWrapper.appendChild(textSpan);
        button.appendChild(contentWrapper);
        // 鼠标悬停显示按钮模板文本
        button.title = config.text || '';
        // 确保嵌套元素不会拦截点击或拖拽事件
        contentWrapper.style.pointerEvents = 'none';
        textSpan.style.pointerEvents = 'none';
        iconWrapper.style.pointerEvents = 'none';
        return button;
    };

    const extractTemplateVariables = (text = '') => {
        if (typeof text !== 'string' || !text.includes('{')) {
            return [];
        }

        const matches = new Set();
        const fallbackMatches = text.match(/\{\{[A-Za-z0-9_-]+\}\|\{[A-Za-z0-9_-]+\}\}/g) || [];
        fallbackMatches.forEach(match => matches.add(match));

        let sanitized = text;
        fallbackMatches.forEach(match => {
            sanitized = sanitized.split(match).join(' ');
        });

        const singleMatches = sanitized.match(/\{[A-Za-z0-9_-]+\}/g) || [];
        singleMatches.forEach(match => matches.add(match));

        return Array.from(matches);
    };

    // 引入全局变量来跟踪当前打开的文件夹
    const currentlyOpenFolder = {
        name: null,
        element: null
    };

    const createCustomButton = (name, config, folderName) => {
        const button = createCustomButtonElement(name, config, folderName);
        button.setAttribute('draggable', 'true');
        button.setAttribute('data-button-name', name);
        button.setAttribute('data-folder-name', folderName);

        button.addEventListener('dragstart', (e) => {
            e.dataTransfer.setData('application/json', JSON.stringify({
                buttonName: name,
                sourceFolder: folderName,
                config: config
            }));
            e.currentTarget.style.opacity = '0.5';
        });

        button.addEventListener('dragend', (e) => {
            e.currentTarget.style.opacity = '1';
        });

        button.addEventListener('mousedown', (e) => {
            e.preventDefault();
            const focusedElement = document.activeElement;
            if (focusedElement && (focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                setTimeout(() => focusedElement.focus(), 0);
            }
        });

        button.addEventListener('mouseenter', () => {
            button.style.transform = 'scale(1.05)';
            button.style.boxShadow = '0 3px 6px rgba(0,0,0,0.1)';
        });

        button.addEventListener('mouseleave', () => {
            button.style.transform = 'scale(1)';
            button.style.boxShadow = '0 2px 4px rgba(0,0,0,0.05)';
        });

        // 处理按钮点击事件
        button.addEventListener('click', async (e) => {
            e.preventDefault();
            if (config.type === "template") {
                const focusedElement = document.activeElement;
                if (!focusedElement || !(focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                    console.warn("当前未聚焦到有效的 textarea 或 contenteditable 元素。");
                    return;
                }

                // 检查模板是否需要剪切板内容
                const needsClipboard = config.text.includes('{clipboard}') || config.text.includes('{{inputboard}|{clipboard}}');

                let clipboardText = '';
                if (needsClipboard) {
                    try {
                        clipboardText = await navigator.clipboard.readText();
                    } catch (err) {
                        console.error("无法访问剪贴板内容:", err);
                        alert("无法访问剪贴板内容。请检查浏览器权限。");
                        return;
                    }
                }

                // 改进的内容获取方式
                let inputBoxText = '';
                if (focusedElement.tagName.toLowerCase() === 'textarea') {
                    inputBoxText = focusedElement.value;
                } else {
                    // 遍历 contenteditable 元素的子节点,正确处理换行
                    const childNodes = Array.from(focusedElement.childNodes);
                    const textParts = [];
                    let lastWasBr = false;
                    childNodes.forEach((node, index) => {
                        if (node.nodeType === Node.TEXT_NODE) {
                            if (node.textContent.trim() === '') {
                                if (!lastWasBr && index > 0) {
                                    textParts.push('\n');
                                }
                            } else {
                                textParts.push(node.textContent);
                                lastWasBr = false;
                            }
                        } else if (node.nodeName === 'BR') {
                            textParts.push('\n');
                            lastWasBr = true;
                        } else if (node.nodeName === 'P' || node.nodeName === 'DIV') {
                            if (node.textContent.trim() === '') {
                                textParts.push('\n');
                            } else {
                                if (textParts.length > 0) {
                                    textParts.push('\n');
                                }
                                textParts.push(node.textContent);
                            }
                            lastWasBr = false;
                        }
                    });
                    inputBoxText = textParts.join('');
                }

                const selectionText = window.getSelection().toString();

                // 全新的安全变量替换逻辑 - 使用占位符防止嵌套替换
                let finalText = config.text;

                // 创建变量映射表 - 只有在需要时才包含剪切板内容
                const variableMap = {
                    '{{inputboard}|{clipboard}}': inputBoxText.trim() || clipboardText,
                    '{clipboard}': clipboardText,
                    '{inputboard}': inputBoxText,
                    '{selection}': selectionText
                };

                // 按照优先级顺序进行替换(复合变量优先)
                const replacementOrder = [
                    '{{inputboard}|{clipboard}}',
                    '{clipboard}',
                    '{inputboard}',
                    '{selection}'
                ];

                // 使用安全的占位符机制,确保一次性替换,避免嵌套
                const placeholderMap = new Map();
                let placeholderCounter = 0;

                // 第一阶段:将模板中的变量替换为唯一占位符
                replacementOrder.forEach(variable => {
                    if (finalText.includes(variable)) {
                        const placeholder = `__SAFE_PLACEHOLDER_${placeholderCounter++}__`;
                        placeholderMap.set(placeholder, variableMap[variable]);

                        // 使用 split().join() 确保精确匹配,避免正则表达式问题
                        finalText = finalText.split(variable).join(placeholder);
                    }
                });

                // 第二阶段:将占位符替换为实际值(此时不会再有嵌套问题)
                placeholderMap.forEach((value, placeholder) => {
                    finalText = finalText.split(placeholder).join(value);
                });

                // 统一换行符
                finalText = finalText.replace(/\r\n/g, '\n').replace(/\r/g, '\n');

                const containsInputboard = config.text.includes("{inputboard}") ||
                    config.text.includes("{{inputboard}|{clipboard}}");

                if (containsInputboard) {
                    insertTextSmart(focusedElement, finalText, true);
                    console.log(`✅ 使用 {inputboard} 变量,输入框内容已被替换。`);
                } else {
                    insertTextSmart(focusedElement, finalText, false);
                    console.log(`✅ 插入了预设文本。`);
                }

                // 若开启autoSubmit,则先检测是否完成替换,再延时后提交
                if (config.autoSubmit) {
                    try {
                        // 1. 等待输入框内容与 finalText 匹配,最多等待3秒
                        await waitForContentMatch(focusedElement, finalText, 100, 3000);

                        // 2. 再额外等待500ms,确保渲染/加载稳定
                        await new Promise(resolve => setTimeout(resolve, 500));

                        // 3. 调用自动提交
                        const success = await submitForm();
                        if (success) {
                            console.log("✅ 自动提交成功(已确认内容替换完成)。");
                        } else {
                            console.warn("⚠️ 自动提交失败。");
                        }
                    } catch (error) {
                        console.error("自动提交前检测文本匹配超时或错误:", error);
                    }
                }

            } else if (config.type === "tool") {
                const focusedElement = document.activeElement;
                if (!focusedElement || !(focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                    console.warn("当前未聚焦到有效的 textarea 或 contenteditable 元素。");
                    return;
                }
                switch (config.action) {
                    case "cut":
                        handleCut(focusedElement);
                        break;
                    case "copy":
                        handleCopy(focusedElement);
                        break;
                    case "paste":
                        handlePaste(focusedElement);
                        break;
                    case "clear":
                        handleClear(focusedElement);
                        break;
                    default:
                        console.warn(`未知的工具按钮动作: ${config.action}`);
                }
            }

            // 立即关闭弹窗
            if (currentlyOpenFolder.name === folderName && currentlyOpenFolder.element) {
                currentlyOpenFolder.element.style.display = 'none';
                currentlyOpenFolder.name = null;
                currentlyOpenFolder.element = null;
                console.log(`✅ 弹窗 "${folderName}" 已立即关闭。`);
            } else {
                console.warn(`⚠️ 弹窗 "${folderName}" 未被识别为当前打开的弹窗。`);
            }
        });

        return button;
    };

    // 工具按钮动作处理
    const handleCut = (element) => {
        let text = '';
        if (element.tagName.toLowerCase() === 'textarea') {
            text = element.value;
            insertTextSmart(element, '', true);
        } else {
            const textContent = [];
            const childNodes = Array.from(element.childNodes);
            childNodes.forEach((node, index) => {
                if (node.nodeType === Node.TEXT_NODE) {
                    textContent.push(node.textContent);
                } else if (node.nodeName === 'BR') {
                    textContent.push('\n');
                } else if (node.nodeName === 'P' || node.nodeName === 'DIV') {
                    if (index > -1) textContent.push('\n');
                    textContent.push(node.textContent);
                }
            });
            text = textContent.join('');
            insertTextSmart(element, '', true);
        }
        if (text) {
            navigator.clipboard.writeText(text).then(() => {
                console.log("✅ 已剪切输入框内容到剪贴板。");
                showTemporaryFeedback(element, '剪切成功');
            }).catch(err => {
                console.error("剪切失败:", err);
                alert("剪切失败,请检查浏览器权限。");
            });
        }
    };

    const handleCopy = (element) => {
        let text = '';
        if (element.tagName.toLowerCase() === 'textarea') {
            text = element.value;
        } else {
            const textContent = [];
            const childNodes = Array.from(element.childNodes);
            childNodes.forEach((node, index) => {
                if (node.nodeType === Node.TEXT_NODE) {
                    textContent.push(node.textContent);
                } else if (node.nodeName === 'BR') {
                    textContent.push('\n');
                } else if (node.nodeName === 'P' || node.nodeName === 'DIV') {
                    if (index > -1) textContent.push('\n');
                    textContent.push(node.textContent);
                }
            });
            text = textContent.join('');
        }
        if (text) {
            navigator.clipboard.writeText(text).then(() => {
                console.log("✅ 已复制输入框内容到剪贴板。");
                showTemporaryFeedback(element, '复制成功');
            }).catch(err => {
                console.error("复制失败:", err);
                alert("复制失败,请检查浏览器权限。");
            });
        }
    };

    const handlePaste = async (element) => {
        try {
            const clipboardText = await navigator.clipboard.readText();
            insertTextSmart(element, clipboardText);
            console.log("✅ 已粘贴剪贴板内容到输入框。");
            showTemporaryFeedback(element, '粘贴成功');
        } catch (err) {
            console.error("粘贴失败:", err);
            alert("粘贴失败,请检查浏览器权限。");
        }
    };

    const handleClear = (element) => {
        insertTextSmart(element, '', true);
        console.log("✅ 输入框内容已清空。");
        showTemporaryFeedback(element, '清空成功');
    };

    const showTemporaryFeedback = (element, message) => {
        const feedback = document.createElement('span');
        feedback.textContent = message;
        feedback.style.position = 'absolute';
        feedback.style.bottom = '10px';
        feedback.style.right = '10px';
        feedback.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        feedback.style.color = '#fff';
        feedback.style.padding = '4px 8px';
        feedback.style.borderRadius = '4px';
        feedback.style.zIndex = '10001';
        element.parentElement.appendChild(feedback);
        setTimeout(() => {
            feedback.remove();
        }, 1500);
    };

    const createFolderButton = (folderName, folderConfig) => {
        const folderButton = document.createElement('button');
        folderButton.innerText = folderName;
        folderButton.type = 'button';
        folderButton.style.backgroundColor = folderConfig.color;
        folderButton.style.color = folderConfig.textColor || '#ffffff';
        folderButton.style.border = 'none';
        folderButton.style.borderRadius = '4px';
        folderButton.style.padding = '6px 12px';
        folderButton.style.cursor = 'pointer';
        folderButton.style.fontSize = '14px';
        folderButton.style.fontWeight = '500';
        folderButton.style.transition = 'all 0.2s ease';
        folderButton.style.position = 'relative';
        folderButton.style.display = 'inline-flex';
        folderButton.style.alignItems = 'center';
        folderButton.style.whiteSpace = 'nowrap';
        folderButton.style.zIndex = '99';
        folderButton.classList.add('folder-button');
        folderButton.setAttribute('data-folder', folderName);

        folderButton.addEventListener('mousedown', (e) => {
            e.preventDefault();
        });

        folderButton.addEventListener('mouseleave', () => {
            folderButton.style.transform = 'scale(1)';
            folderButton.style.boxShadow = 'none';
        });

        const buttonListContainer = document.createElement('div');
        buttonListContainer.style.position = 'fixed';
        buttonListContainer.style.display = 'none';
        buttonListContainer.style.flexDirection = 'column';
        buttonListContainer.style.backgroundColor = 'var(--folder-bg, rgba(255, 255, 255, 0.8))';
        buttonListContainer.style.backdropFilter = 'blur(5px)';
        buttonListContainer.style.border = `1px solid var(--border-color, #e5e7eb)`;
        buttonListContainer.style.borderRadius = '8px';
        buttonListContainer.style.padding = '10px';
        buttonListContainer.style.paddingBottom = '2.5px';
        buttonListContainer.style.boxShadow = `0 4px 12px var(--shadow-color, rgba(0,0,0,0.1))`;
        buttonListContainer.style.zIndex = '100';
        buttonListContainer.style.maxHeight = '800px';
        buttonListContainer.style.overflowY = 'auto';
        buttonListContainer.style.transition = 'all 0.3s ease';
        buttonListContainer.classList.add('button-list');
        buttonListContainer.setAttribute('data-folder-list', folderName);
        buttonListContainer.style.pointerEvents = 'auto';

        Object.entries(folderConfig.buttons).forEach(([name, config]) => {
            const customButton = createCustomButton(name, config, folderName);
            buttonListContainer.appendChild(customButton);
        });

        folderButton.addEventListener('click', (e) => {
            e.preventDefault();
            // Toggle popup visibility
            if (currentlyOpenFolder.name === folderName) {
                // 如果当前文件夹已经打开,则关闭它
                buttonListContainer.style.display = 'none';
                currentlyOpenFolder.name = null;
                currentlyOpenFolder.element = null;
                console.log(`🔒 弹窗 "${folderName}" 已关闭。`);
            } else {
                // 关闭其他文件夹的弹窗
                if (currentlyOpenFolder.element) {
                    currentlyOpenFolder.element.style.display = 'none';
                    console.log(`🔒 弹窗 "${currentlyOpenFolder.name}" 已关闭。`);
                }
                // 打开当前文件夹的弹窗
                buttonListContainer.style.display = 'flex';
                currentlyOpenFolder.name = folderName;
                currentlyOpenFolder.element = buttonListContainer;
                console.log(`🔓 弹窗 "${folderName}" 已打开。`);
                // 动态定位弹窗位置
                const rect = folderButton.getBoundingClientRect();
                buttonListContainer.style.bottom = `40px`;
                buttonListContainer.style.left = `${rect.left + window.scrollX - 20}px`;
                console.log(`📍 弹窗位置设置为 Bottom: 40px, Left: ${rect.left + window.scrollX - 20}px`);
            }
        });

        document.addEventListener('click', (e) => {
            const path = typeof e.composedPath === 'function' ? e.composedPath() : [];
            const clickedInsideButton = path.includes(folderButton);
            const clickedInsideList = path.includes(buttonListContainer);
            if (!clickedInsideButton && !clickedInsideList) {
                // 点击了其他地方,关闭弹窗
                if (buttonListContainer.style.display !== 'none') {
                    buttonListContainer.style.display = 'none';
                    if (currentlyOpenFolder.name === folderName) {
                        currentlyOpenFolder.name = null;
                        currentlyOpenFolder.element = null;
                        console.log(`🔒 弹窗 "${folderName}" 已关闭(点击外部区域)。`);
                    }
                }
            }
        });

        appendToMainLayer(buttonListContainer);
        return folderButton;
    };

    const toggleFolder = (folderName, state) => {
        const buttonList = queryUI(`.button-list[data-folder-list="${folderName}"]`);
        if (!buttonList) {
            console.warn(`⚠️ 未找到与文件夹 "${folderName}" 关联的弹窗。`);
            return;
        }
        if (state) {
            // 打开当前文件夹的弹窗
            buttonList.style.display = 'flex';
            currentlyOpenFolder.name = folderName;
            currentlyOpenFolder.element = buttonList;
            console.log(`🔓 弹窗 "${folderName}" 已打开(toggleFolder)。`);
        } else {
            // 关闭当前文件夹的弹窗
            buttonList.style.display = 'none';
            if (currentlyOpenFolder.name === folderName) {
                currentlyOpenFolder.name = null;
                currentlyOpenFolder.element = null;
                console.log(`🔒 弹窗 "${folderName}" 已关闭(toggleFolder)。`);
            }
        }
        // 关闭其他文件夹的弹窗
        const root = getShadowRoot();
        const allButtonLists = root ? Array.from(root.querySelectorAll('.button-list')) : [];
        allButtonLists.forEach(bl => {
            if (bl.getAttribute('data-folder-list') !== folderName) {
                bl.style.display = 'none';
                const fname = bl.getAttribute('data-folder-list');
                if (currentlyOpenFolder.name === fname) {
                    currentlyOpenFolder.name = null;
                    currentlyOpenFolder.element = null;
                    console.log(`🔒 弹窗 "${fname}" 已关闭(toggleFolder 关闭其他弹窗)。`);
                }
            }
        });
    };

    const closeExistingOverlay = (overlay) => {
        if (overlay && overlay.parentElement) {
            // 添加关闭动画
            overlay.style.opacity = '0';

            // 立即标记为已关闭,避免重复操作
            overlay.setAttribute('data-closing', 'true');

            // 延时移除DOM元素,确保动画完成
            setTimeout(() => {
                if (overlay.parentElement && overlay.getAttribute('data-closing') === 'true') {
                    overlay.parentElement.removeChild(overlay);
                    console.log("🔒 弹窗已关闭并从DOM中移除");
                }
            }, 300);
        } else {
            console.warn("⚠️ 尝试关闭不存在的弹窗");
        }
    };

    let currentConfirmOverlay = null;
    let currentSettingsOverlay = null;
    let isSettingsFolderPanelCollapsed = false;
    let settingsDialogMainContainer = null;
    let currentConfigOverlay = null; // 新增的独立配置设置弹窗
    let currentStyleOverlay = null;

    const showDeleteFolderConfirmDialog = (folderName, rerenderFn) => {
        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }
        const folderConfig = buttonConfig.folders[folderName];
        if (!folderConfig) {
            alert(`文件夹 "${folderName}" 不存在。`);
            return;
        }
        // 构建文件夹内自定义按钮的垂直预览列表
        let buttonsPreviewHTML = '';
        Object.entries(folderConfig.buttons).forEach(([btnName, btnCfg]) => {
            buttonsPreviewHTML += `
                <div style="display: flex; align-items: center; margin-bottom: 8px;">
                    <button style="
                        background-color: ${btnCfg.color};
                        color: ${btnCfg.textColor};
                        border: 1px solid rgba(0,0,0,0.1);
                        border-radius: 4px;
                        padding: 4px 8px;
                        cursor: default;
                        font-size: 12px;
                        box-shadow: none;
                        margin-right: 8px;
                    " disabled>${btnName}</button>
                    <span style="font-size: 12px; color: var(--text-color);">${btnName}</span>
                </div>
            `;
        });

        const overlay = document.createElement('div');
        overlay.classList.add('confirm-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 11000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('confirm-dialog', 'cttf-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 20px 24px 16px 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 400px;
            max-width: 90vw;
        `;
        setTrustedHTML(dialog, `
            <h3 style="margin: 0 0 20px 0; font-size: 18px; font-weight: 600; color: var(--danger-color, #ef4444);">
                🗑️ 确认删除文件夹 "${folderName}"?
            </h3>
            <p style="margin: 8px 0; color: var(--text-color, #333333);">❗️ 注意:此操作无法撤销!<br/>(删除文件夹将同时删除其中的所有自定义按钮!)</p>
            <div style="margin: 16px 0; border: 1px solid var(--border-color, #e5e7eb); padding: 8px; border-radius:4px;">
                <!-- 将文件夹按钮预览和文字标签放在一行 -->
                <p style="margin:4px 0; display: flex; align-items: center; gap: 8px; color: var(--text-color, #333333);">
                    <strong>1️⃣ 文件夹按钮外观:</strong>
                    <button style="
                        background-color: ${folderConfig.color};
                        color: ${folderConfig.textColor};
                        border: none;
                        border-radius:4px;
                        padding:6px 12px;
                        cursor: default;
                        font-size:14px;
                        font-weight:500;
                        box-shadow: none;
                    " disabled>${folderName}</button>
                </p>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333);">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    按钮名称: ${folderName}
                </p>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333);">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    背景颜色: <span style="display:inline-block;width:16px;height:16px;background:${folderConfig.color};border:1px solid #333;vertical-align:middle;margin-right:4px;"></span>${folderConfig.color}
                </p>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333);">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    文字颜色: <span style="display:inline-block;width:16px;height:16px;background:${folderConfig.textColor};border:1px solid #333;vertical-align:middle;margin-right:4px;"></span>${folderConfig.textColor}
                </p>
                <hr style="margin: 8px 0; border: none; border-top: 1px solid var(--border-color, #e5e7eb);">
                <p style="margin:4px 0; color: var(--text-color, #333333);"><strong>2️⃣ 文件夹内,全部自定义按钮:</strong></p>
                <div style="display: flex; flex-direction: column; gap: 8px;">
                    ${buttonsPreviewHTML}
                </div>
            </div>
            <div style="
                display: flex;
                justify-content: flex-end;
                gap: 12px;
                border-top:1px solid var(--border-color, #e5e7eb);
                padding-top:16px;
            ">
                <button id="cancelDeleteFolder" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border-radius: 4px;
                ">取消</button>
                <button id="confirmDeleteFolder" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--danger-color, #ef4444);
                    color: white;
                    border-radius: 4px;
                ">删除</button>
            </div>
        `);
        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        // 动画效果
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        dialog.querySelector('#cancelDeleteFolder').addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
        });

        dialog.querySelector('#confirmDeleteFolder').addEventListener('click', () => {
            delete buttonConfig.folders[folderName];
            const idx = buttonConfig.folderOrder.indexOf(folderName);
            if (idx > -1) buttonConfig.folderOrder.splice(idx, 1);
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
            if (rerenderFn) rerenderFn();
            console.log(`🗑️ 文件夹 "${folderName}" 已删除。`);
            // 更新按钮栏
            updateButtonContainer();
        });
    };

    // 修改 删除按钮确认对话框,增加显示按钮名称、颜色信息及样式预览
    const showDeleteButtonConfirmDialog = (folderName, btnName, rerenderFn) => {
        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }
        const btnCfg = buttonConfig.folders[folderName].buttons[btnName];
        if (!btnCfg) {
            alert(`按钮 "${btnName}" 不存在于文件夹 "${folderName}" 中。`);
            return;
        }
        const overlay = document.createElement('div');
        overlay.classList.add('confirm-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 11000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('confirm-dialog', 'cttf-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 20px 24px 16px 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 400px;
            max-width: 90vw;
        `;
        setTrustedHTML(dialog, `
            <h3 style="margin: 0 0 20px 0; font-size: 18px; font-weight: 600; color: var(--danger-color, #ef4444);">
                🗑️ 确认删除按钮 "${btnName}"?
            </h3>
            <p style="margin: 8px 0; color: var(--text-color, #333333);">❗️ 注意:此操作无法撤销!</p>
            <div style="margin: 16px 0; border: 1px solid var(--border-color, #e5e7eb); padding: 8px; border-radius:4px;">
                <p style="margin:4px 0; display: flex; align-items: center; gap: 8px; color: var(--text-color, #333333);">
                    <strong>1️⃣ 自定义按钮外观:</strong>
                    <button style="
                        background-color: ${btnCfg.color};
                        color: ${btnCfg.textColor};
                        border: none;
                        border-radius: 4px;
                        padding: 6px 12px;
                        cursor: default;
                        font-size: 12px;
                        box-shadow: none;
                    " disabled>${btnName}</button>
                </p>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333);">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    按钮名称: ${btnName}
                </p>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333);">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    按钮背景颜色: <span style="display:inline-block;width:16px;height:16px;background:${btnCfg.color};border:1px solid #333;vertical-align:middle;margin-right:4px;"></span>${btnCfg.color}
                </p>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333);">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    按钮文字颜色: <span style="display:inline-block;width:16px;height:16px;background:${btnCfg.textColor};border:1px solid #333;vertical-align:middle;margin-right:4px;"></span>${btnCfg.textColor}
                </p>
                <hr style="margin: 8px 0; border: none; border-top: 1px solid var(--border-color, #e5e7eb);">
                <p style="margin:4px 0; color: var(--text-color, #333333);"><strong>2️⃣ 按钮对应的文本模板:</strong></p>
                <textarea readonly style="
                    width:100%;
                    height:150px;
                    background-color: var(--button-bg, #f3f4f6);
                    color: var(--text-color, #333333);
                    border:1px solid var(--border-color, #e5e7eb);
                    border-radius:4px;
                    resize: vertical;
                ">${btnCfg.text || ''}</textarea>
            </div>
            <div style="
                display:flex;
                justify-content: flex-end;
                gap: 12px;
                border-top:1px solid var(--border-color, #e5e7eb);
                padding-top:16px;
            ">
                <button id="cancelDeleteButton" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border-radius:4px;
                ">取消</button>
                <button id="confirmDeleteButton" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--danger-color, #ef4444);
                    color: white;
                    border-radius:4px;
                ">删除</button>
            </div>
        `);
        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        // 动画效果
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        dialog.querySelector('#cancelDeleteButton').addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
        });

        dialog.querySelector('#confirmDeleteButton').addEventListener('click', () => {
            delete buttonConfig.folders[folderName].buttons[btnName];
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
            if (rerenderFn) rerenderFn();
            console.log(`🗑️ 按钮 "${btnName}" 已删除。`);
            // 更新按钮栏
            updateButtonContainer();
            updateCounters(); // 更新所有计数器
        });
    };

    const showButtonEditDialog = (folderName, btnName = '', btnConfig = {}, rerenderFn) => {
        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }
        // 禁止编辑/删除工具文件夹中的工具按钮
        if (folderName === "🖱️" && btnConfig.type === "tool") {
            alert('工具文件夹中的工具按钮无法编辑或删除。');
            return;
        }
        const isEdit = btnName !== '';

        // Create overlay and dialog containers
        const overlay = document.createElement('div');
        overlay.classList.add('edit-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 11000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('edit-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 500px;
            max-width: 90vw;
        `;

        const initialName = btnName || '';
        const initialColor = btnConfig.color || '#FFC1CC';
        const initialTextColor = btnConfig.textColor || '#333333';
        const initialAutoSubmit = btnConfig.autoSubmit || false; // 新增字段
        const initialFavicon = typeof btnConfig.favicon === 'string' ? btnConfig.favicon : '';

        // 预览部分
        const previewSection = `
            <div style="
                margin: -24px -24px 20px -24px;
                padding: 16px 24px;
                background-color: var(--button-bg, #f3f4f6);
                border-bottom: 1px solid var(--border-color, #e5e7eb);
                border-radius: 4px 4px 0 0;
                display: flex;
                align-items: center;
                gap: 16px;
            ">
                <div style="
                    font-size: 18px;
                    font-weight: 600;
                    color: var(--text-color, #333333);
                    display: flex;
                    align-items: center;
                    gap: 8px;
                ">
                    ${isEdit ? '✏️ 编辑按钮:' : '🆕 新建按钮:'}
                </div>
                <div id="buttonPreview" style="
                    display: inline-flex;
                    padding: 4px;
                    border-radius: 4px;
                    background-color: var(--dialog-bg, #ffffff);
                ">
                    <button id="previewButton" style="
                        background-color: ${initialColor};
                        color: ${initialTextColor};
                        border: none;
                        border-radius: 4px;
                        padding: 6px 12px;
                        cursor: default;
                        font-size: 14px;
                        transition: all 0.2s ease;
                    ">${initialName || '预览按钮'}</button>
                </div>
            </div>
        `;

        // Tab content for text template
        const textTemplateTab = `
        <div id="textTemplateTab" class="tab-content" style="display: block;">
            <div style="
                width: 100%;
                padding: 12px;
                border-radius: 4px;
                border: 1px solid var(--border-color, #e5e7eb);
                background-color: var(--button-bg, #f3f4f6);
            ">
                <div style="
                    display: flex;
                    align-items: center;
                    gap: 12px;
                    margin-bottom: 12px;
                ">
                    <label style="
                        font-size: 14px;
                        font-weight: 500;
                        color: var(--text-color, #333333);
                        white-space: nowrap;
                    ">插入变量:</label>
                    <div id="quickInsertButtons" style="
                        display: flex;
                        gap: 8px;
                        flex-wrap: wrap;
                    ">
                        <button type="button" data-insert="{inputboard}" style="
                            ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                            background-color: var(--primary-color, #3B82F6);
                            color: white;
                            border-radius: 4px;
                            font-size: 12px;
                            padding: 4px 8px;
                            transition: all 0.2s ease;
                            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
                        ">📝 输入框</button>
                        <button type="button" data-insert="{clipboard}" style="
                            ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                            background-color: var(--primary-color, #3B82F6);
                            color: white;
                            border-radius: 4px;
                            font-size: 12px;
                            padding: 4px 8px;
                            transition: all 0.2s ease;
                            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
                        ">📋 剪贴板</button>
                        <button type="button" data-insert="{selection}" style="
                            ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                            background-color: var(--primary-color, #3B82F6);
                            color: white;
                            border-radius: 4px;
                            font-size: 12px;
                            padding: 4px 8px;
                            transition: all 0.2s ease;
                            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
                        ">🔍 选中</button>
                        <button type="button" data-insert="{{inputboard}|{clipboard}}" style="
                            ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                            background-color: var(--primary-color, #3B82F6);
                            color: white;
                            border-radius: 4px;
                            font-size: 12px;
                            padding: 4px 8px;
                            transition: all 0.2s ease;
                            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
                        ">🔄 输入框/剪贴板</button>
                    </div>
                </div>
                <textarea id="buttonText" style="
                    width: 100%;
                    height: 150px;
                    padding: 8px;
                    border-radius: 4px;
                    border: 1px solid var(--border-color, #e5e7eb);
                    background-color: var(--dialog-bg, #ffffff);
                    color: var(--text-color, #333333);
                    resize: vertical;
                ">${btnConfig.text || ''}</textarea>
            </div>
        </div>`;

        // Tab content for style settings
        const styleSettingsTab = `
            <div id="styleSettingsTab" class="tab-content" style="display: none;">
                <div style="margin-bottom: 20px;">
                    <label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: var(--text-color, #333333);">按钮名称:</label>
                    <input type="text" id="buttonName" value="${btnName}" style="
                        width: 100%;
                        padding: 8px;
                        border-radius: 4px;
                        border: 1px solid var(--border-color, #e5e7eb);
                        background-color: var(--button-bg, #f3f4f6);
                        color: var(--text-color, #333333);
                    ">
                </div>
                <div style="margin-bottom: 20px;">
                    <label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: var(--text-color, #333333);">按钮图标:</label>
                    <div style="display: flex; align-items: flex-start; gap: 12px;">
                        <div id="buttonFaviconPreview" style="
                            width: 40px;
                            height: 40px;
                            border-radius: 10px;
                            display: flex;
                            align-items: center;
                            justify-content: center;
                            background-color: transparent;
                            flex-shrink: 0;
                        "></div>
                        <div style="flex: 1 1 auto; display: flex; flex-direction: column;">
                            <textarea id="buttonFaviconInput" rows="1" style="
                                width: 100%;
                                padding: 10px 12px;
                                border: 1px solid var(--border-color, #d1d5db);
                                border-radius: 6px;
                                background-color: var(--dialog-bg, #ffffff);
                                box-shadow: inset 0 1px 2px rgba(0,0,0,0.03);
                                transition: border-color 0.2s ease, box-shadow 0.2s ease;
                                outline: none;
                                font-size: 14px;
                                line-height: 1.5;
                                resize: vertical;
                                overflow-y: hidden;
                            " placeholder="支持 https:// 链接或 data: URL">${initialFavicon}</textarea>
                            <div style="
                                margin-top: 6px;
                                font-size: 12px;
                                color: var(--muted-text-color, #6b7280);
                            ">留空时将根据按钮名称中的符号展示默认图标。</div>
                        </div>
                    </div>
                </div>
                <div style="margin-bottom: 20px;">
                    <label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: var(--text-color, #333333);">按钮背景颜色:</label>
                    <input type="color" id="buttonColor" value="${btnConfig.color || '#FFC1CC'}" style="
                        width: 100px;
                        height: 40px;
                        border: 1px solid var(--border-color, #e5e7eb);
                        border-radius: 4px;
                        cursor: pointer;
                        background-color: var(--button-bg, #f3f4f6);
                    ">
                </div>
                <div style="margin-bottom: 0px;">
                    <label style="display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: var(--text-color, #333333);">按钮文字颜色:</label>
                    <input type="color" id="buttonTextColor" value="${btnConfig.textColor || '#333333'}" style="
                        width: 100px;
                        height: 40px;
                        border: 1px solid var(--border-color, #e5e7eb);
                        border-radius: 4px;
                        cursor: pointer;
                        background-color: var(--button-bg, #f3f4f6);
                    ">
                </div>
            </div>
        `;

        // 新增的提交设置子标签页
        const submitSettingsTab = `
            <div id="submitSettingsTab" class="tab-content" style="display: none;">
                <div style="margin-bottom: 20px;">
                    <label style="
                        display: flex;
                        align-items: center;
                        font-size: 14px;
                        font-weight: 500;
                        color: var(--text-color, #333333);
                        cursor: pointer;
                        gap: 6px;
                    ">
                        <input type="checkbox" id="autoSubmitCheckbox" style="cursor: pointer;" ${initialAutoSubmit ? 'checked' : ''}>
                        自动提交 (在填充后自动提交内容)
                    </label>
                </div>
            </div>
        `;

        // Tab navigation
        const tabNavigation = `
            <div style="
                display: flex;
                gap: 10px;
                margin-bottom: 20px;
                border-bottom: 1px solid var(--border-color, #e5e7eb);
            ">
                <button class="tab-button active" data-tab="textTemplateTab" style="
                    ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                    background-color: var(--primary-color, #3B82F6);
                    color: white;
                    border-radius: 4px 4px 0 0;
                    border-bottom: 2px solid transparent;
                ">文本模板</button>
                <button class="tab-button" data-tab="styleSettingsTab" style="
                    ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                    background-color: var(--button-bg, #f3f4f6);
                    color: var(--text-color, #333333);
                    border-radius: 4px 4px 0 0;
                    border-bottom: 2px solid transparent;
                ">样式设置</button>
                <button class="tab-button" data-tab="submitSettingsTab" style="
                    ${Object.entries(styles.button).map(([k,v]) => `${k}:${v}`).join(';')};
                    background-color: var(--button-bg, #f3f4f6);
                    color: var(--text-color, #333333);
                    border-radius: 4px 4px 0 0;
                    border-bottom: 2px solid transparent;
                ">提交设置</button>
            </div>
        `;

        // Footer buttons
        const footerButtons = `
            <div style="
                display: flex;
                justify-content: space-between;
                align-items: center;
                gap: 12px;
                margin-top: 20px;
                padding-top: 20px;
                border-top: 1px solid var(--border-color, #e5e7eb);
            ">
                <button id="cancelButtonEdit" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border-radius: 4px;
                ">取消</button>
                <button id="saveButtonEdit" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--success-color, #22c55e);
                    color: white;
                    border-radius: 4px;
                ">确认</button>
            </div>
        `;

        // Combine all sections
        setTrustedHTML(dialog, `
            ${previewSection}
            ${tabNavigation}
            ${textTemplateTab}
            ${styleSettingsTab}
            ${submitSettingsTab}
            ${footerButtons}
        `);

        // Add tab switching functionality
        const setupTabs = () => {
            const tabButtons = dialog.querySelectorAll('.tab-button');
            const tabContents = dialog.querySelectorAll('.tab-content');
            tabButtons.forEach(button => {
                button.addEventListener('click', () => {
                    const tabId = button.dataset.tab;
                    // Update button styles
                    tabButtons.forEach(btn => {
                        if (btn === button) {
                            btn.style.backgroundColor = 'var(--primary-color, #3B82F6)';
                            btn.style.color = 'white';
                            btn.style.borderBottom = '2px solid var(--primary-color, #3B82F6)';
                        } else {
                            btn.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
                            btn.style.color = 'var(--text-color, #333333)';
                            btn.style.borderBottom = '2px solid transparent';
                        }
                    });
                    // Show/hide content
                    tabContents.forEach(content => {
                        content.style.display = content.id === tabId ? 'block' : 'none';
                    });
                });
            });
        };

        // Rest of the existing dialog setup code...
        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        // Setup tabs
        setupTabs();

        // Setup preview updates
        const setupPreviewUpdates = () => {
            const previewButton = dialog.querySelector('#previewButton');
            const buttonNameInput = dialog.querySelector('#buttonName');
            const buttonColorInput = dialog.querySelector('#buttonColor');
            const buttonTextColorInput = dialog.querySelector('#buttonTextColor');
            const autoSubmitCheckbox = dialog.querySelector('#autoSubmitCheckbox'); // 新增引用
            const buttonFaviconInput = dialog.querySelector('#buttonFaviconInput');
            const buttonFaviconPreview = dialog.querySelector('#buttonFaviconPreview');

            const updateFaviconPreview = () => {
                if (!buttonFaviconPreview) return;
                const currentName = buttonNameInput?.value.trim() || initialName || '';
                const faviconValue = buttonFaviconInput?.value.trim() || '';
                const { iconSymbol } = extractButtonIconParts(currentName);
                const fallbackSymbol = iconSymbol || (Array.from(currentName.trim())[0] || '🔖');
                const previewElement = createFaviconElement(
                    faviconValue,
                    currentName,
                    fallbackSymbol,
                    { withBackground: false }
                );
                setTrustedHTML(buttonFaviconPreview, '');
                buttonFaviconPreview.appendChild(previewElement);
            };

            buttonNameInput?.addEventListener('input', (e) => {
                previewButton.textContent = e.target.value || '预览按钮';
                updateFaviconPreview();
            });

            buttonColorInput?.addEventListener('input', (e) => {
                previewButton.style.backgroundColor = e.target.value;
            });

            buttonTextColorInput?.addEventListener('input', (e) => {
                previewButton.style.color = e.target.value;
            });

            // 监听“自动提交”开关变化
            autoSubmitCheckbox?.addEventListener('change', (e) => {
                console.log(`✅ 自动提交开关已设置为 ${e.target.checked}`);
            });

            if (buttonFaviconInput) {
                autoResizeTextarea(buttonFaviconInput, { minRows: 1, maxRows: 4 });
                buttonFaviconInput.addEventListener('input', () => {
                    autoResizeTextarea(buttonFaviconInput, { minRows: 1, maxRows: 4 });
                    updateFaviconPreview();
                });
            }

            updateFaviconPreview();
        };
        setupPreviewUpdates();

        // Setup quick insert buttons
        const setupQuickInsert = () => {
            const buttonText = dialog.querySelector('#buttonText');
            const quickInsertButtons = dialog.querySelector('#quickInsertButtons');
            quickInsertButtons?.addEventListener('click', (e) => {
                const button = e.target.closest('button[data-insert]');
                if (!button) return;
                e.preventDefault();
                const insertText = button.dataset.insert;
                const start = buttonText.selectionStart;
                const end = buttonText.selectionEnd;
                buttonText.value = buttonText.value.substring(0, start) +
                                   insertText +
                                   buttonText.value.substring(end);
                buttonText.selectionStart = buttonText.selectionEnd = start + insertText.length;
                buttonText.focus();
            });
            quickInsertButtons?.addEventListener('mousedown', (e) => {
                if (e.target.closest('button[data-insert]')) {
                    e.preventDefault();
                }
            });
        };
        setupQuickInsert();

        // Animation effect
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        // Setup buttons
        dialog.querySelector('#cancelButtonEdit')?.addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
        });

        dialog.querySelector('#saveButtonEdit')?.addEventListener('click', () => {
            const newBtnName = dialog.querySelector('#buttonName').value.trim();
            const newBtnColor = dialog.querySelector('#buttonColor').value;
            const newBtnTextColor = dialog.querySelector('#buttonTextColor').value;
            const newBtnText = dialog.querySelector('#buttonText').value.trim();
            const autoSubmit = dialog.querySelector('#autoSubmitCheckbox')?.checked || false; // 获取自动提交状态
            const newBtnFavicon = (dialog.querySelector('#buttonFaviconInput')?.value || '').trim();

            if (!newBtnName) {
                alert('请输入按钮名称!');
                return;
            }

            if (!isValidColor(newBtnColor) || !isValidColor(newBtnTextColor)) {
                alert('请选择有效的颜色!');
                return;
            }

            if (newBtnName !== btnName && buttonConfig.folders[folderName].buttons[newBtnName]) {
                alert('按钮名称已存在!');
                return;
            }

            // Get all buttons order
            const currentButtons = { ...buttonConfig.folders[folderName].buttons };

            if (btnConfig.type === "tool") {
                // 工具按钮不允许更改类型和动作
                buttonConfig.folders[folderName].buttons[newBtnName] = {
                    type: "tool",
                    action: btnConfig.action,
                    color: newBtnColor,
                    textColor: newBtnTextColor
                };
            } else {
                // 处理模板按钮
                // Handle button rename
                if (btnName && newBtnName !== btnName) {
                    const newButtons = {};
                    Object.keys(currentButtons).forEach(key => {
                        if (key === btnName) {
                            newButtons[newBtnName] = {
                                text: newBtnText,
                                color: newBtnColor,
                                textColor: newBtnTextColor,
                                type: "template",
                                autoSubmit: autoSubmit,
                                favicon: newBtnFavicon
                            };
                        } else {
                            newButtons[key] = currentButtons[key];
                        }
                    });
                    buttonConfig.folders[folderName].buttons = newButtons;
                } else {
                    // Update existing button
                    if (btnName) {
                        buttonConfig.folders[folderName].buttons[btnName] = {
                            text: newBtnText,
                            color: newBtnColor,
                            textColor: newBtnTextColor,
                            type: "template",
                            autoSubmit: autoSubmit,
                            favicon: newBtnFavicon
                        };
                    } else {
                        // Create new button
                        buttonConfig.folders[folderName].buttons[newBtnName] = {
                            text: newBtnText,
                            color: newBtnColor,
                            textColor: newBtnTextColor,
                            type: "template",
                            autoSubmit: autoSubmit,
                            favicon: newBtnFavicon
                        };
                    }
                }
            }

            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
            if (rerenderFn) rerenderFn();
            console.log(`✅ 按钮 "${newBtnName}" 已保存。`);
            updateButtonContainer();
            updateCounters(); // 更新所有计数器
        });
    };

    function isValidColor(color) {
        const s = new Option().style;
        s.color = color;
        return s.color !== '';
    }

    const showFolderEditDialog = (folderName = '', folderConfig = {}, rerenderFn) => {
        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }
        const isNew = !folderName;
        const overlay = document.createElement('div');
        overlay.classList.add('folder-edit-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 11000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('folder-edit-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 500px;
            max-width: 90vw;
        `;

        const initialName = folderName || '';
        const initialColor = folderConfig.color || '#3B82F6';
        const initialTextColor = folderConfig.textColor || '#ffffff';

        // 预览部分
        const previewSection = `
            <div style="
                margin: -24px -24px 20px -24px;
                padding: 16px 24px;
                background-color: var(--button-bg, #f3f4f6);
                border-bottom: 1px solid var(--border-color, #e5e7eb);
                border-radius: 4px 4px 0 0;
                display: flex;
                align-items: center;
                gap: 16px;
            ">
                <div style="
                    font-size: 18px;
                    font-weight: 600;
                    color: var(--text-color, #333333);
                    display: flex;
                    align-items: center;
                    gap: 8px;
                ">
                    ${isNew ? '🆕 新建文件夹:' : '✏️ 编辑文件夹:'}
                </div>
                <div id="folderPreview" style="
                    display: inline-flex;
                    padding: 4px;
                    border-radius: 4px;
                    background-color: var(--dialog-bg, #ffffff);
                ">
                    <button id="previewButton" style="
                        background-color: ${initialColor};
                        color: ${initialTextColor};
                        border: none;
                        border-radius: 4px;
                        padding: 6px 12px;
                        cursor: default;
                        font-size: 14px;
                        transition: all 0.2s ease;
                    ">${initialName || '预览文件夹'}</button>
                </div>
            </div>
        `;

        // 设置部分
        const settingsSection = `
            <div style="
                display:flex;
                flex-direction:column;
                gap:20px;
                margin-bottom:20px;
            ">
                <div style="margin-bottom: 20px;">
                    <label style="
                        display: block;
                        margin-bottom: 8px;
                        font-size: 14px;
                        font-weight: 500;
                        color: var(--text-color, #333333);
                    ">文件夹名称:</label>
                    <input type="text" id="folderNameInput" value="${initialName}" style="
                        width: 100%;
                        padding: 8px;
                        border-radius: 4px;
                        border: 1px solid var(--border-color, #e5e7eb);
                        background-color: var(--button-bg, #f3f4f6);
                        color: var(--text-color, #333333);
                    ">
                </div>
                <div style="margin-bottom: 20px;">
                    <label style="
                        display: block;
                        margin-bottom: 8px;
                        font-size: 14px;
                        font-weight: 500;
                        color: var(--text-color, #333333);
                    ">按钮背景颜色:</label>
                    <input type="color" id="folderColorInput" value="${initialColor}" style="
                        width: 100px;
                        height: 40px;
                        border: 1px solid var(--border-color, #e5e7eb);
                        border-radius: 4px;
                        cursor: pointer;
                        background-color: var(--button-bg, #f3f4f6);
                    ">
                </div>
                <div style="margin-bottom: 0px;">
                    <label style="
                        display: block;
                        margin-bottom: 8px;
                        font-size: 14px;
                        font-weight: 500;
                        color: var(--text-color, #333333);
                    ">按钮文字颜色:</label>
                    <input type="color" id="folderTextColorInput" value="${initialTextColor}" style="
                        width: 100px;
                        height: 40px;
                        border: 1px solid var(--border-color, #e5e7eb);
                        border-radius: 4px;
                        cursor: pointer;
                        background-color: var(--button-bg, #f3f4f6);
                    ">
                </div>
            </div>
        `;

        // 底部按钮
        const footerButtons = `
            <div style="
                display: flex;
                justify-content: space-between;
                align-items: center;
                gap: 12px;
                margin-top: 20px;
                padding-top: 20px;
                border-top: 1px solid var(--border-color, #e5e7eb);
            ">
                <button id="cancelFolderEdit" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border-radius: 4px;
                ">取消</button>
                <button id="saveFolderEdit" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--success-color, #22c55e);
                    color: white;
                    border-radius: 4px;
                ">确认</button>
            </div>
        `;

        // Combine all sections
        setTrustedHTML(dialog, `
            ${previewSection}
            ${settingsSection}
            ${footerButtons}
        `);

        // 添加事件监听器
        const setupPreviewUpdates = () => {
            const previewButton = dialog.querySelector('#previewButton');
            const folderNameInput = dialog.querySelector('#folderNameInput');
            const folderColorInput = dialog.querySelector('#folderColorInput');
            const folderTextColorInput = dialog.querySelector('#folderTextColorInput');

            folderNameInput?.addEventListener('input', (e) => {
                previewButton.textContent = e.target.value || '预览文件夹';
            });

            folderColorInput?.addEventListener('input', (e) => {
                previewButton.style.backgroundColor = e.target.value;
            });

            folderTextColorInput?.addEventListener('input', (e) => {
                previewButton.style.color = e.target.value;
            });
        };
        setupPreviewUpdates();

        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        // Animation effect
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        // Setup buttons
        dialog.querySelector('#cancelFolderEdit').addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
        });

        // 在showFolderEditDialog函数的保存按钮点击事件中
        dialog.querySelector('#saveFolderEdit').addEventListener('click', () => {
            const newFolderName = dialog.querySelector('#folderNameInput').value.trim();
            const newColor = dialog.querySelector('#folderColorInput').value;
            const newTextColor = dialog.querySelector('#folderTextColorInput').value;

            if (!newFolderName) {
                alert('请输入文件夹名称');
                return;
            }

            if (isNew && buttonConfig.folders[newFolderName]) {
                alert("该文件夹已存在!");
                return;
            }

            if (!isNew && newFolderName !== folderName && buttonConfig.folders[newFolderName]) {
                alert("该文件夹已存在!");
                return;
            }

            if (!isNew && newFolderName !== folderName) {
                const oldButtons = buttonConfig.folders[folderName].buttons;
                buttonConfig.folders[newFolderName] = {
                    ...buttonConfig.folders[folderName],
                    color: newColor,
                    textColor: newTextColor,
                    buttons: { ...oldButtons }
                };
                delete buttonConfig.folders[folderName];
                const idx = buttonConfig.folderOrder.indexOf(folderName);
                if (idx > -1) {
                    buttonConfig.folderOrder[idx] = newFolderName;
                }
            } else {
                buttonConfig.folders[newFolderName] = buttonConfig.folders[newFolderName] || { buttons: {} };
                buttonConfig.folders[newFolderName].color = newColor;
                buttonConfig.folders[newFolderName].textColor = newTextColor;

                // 确保新建文件夹有hidden字段且默认为false
                if (typeof buttonConfig.folders[newFolderName].hidden !== 'boolean') {
                    buttonConfig.folders[newFolderName].hidden = false;
                }

                // 在isNew分支中把新建的文件夹名加入folderOrder
                if (isNew) {
                    buttonConfig.folderOrder.push(newFolderName);
                }
            }

            // 确保所有按钮都有'type'字段和'autoSubmit'字段
            Object.entries(buttonConfig.folders).forEach(([folderName, folderCfg]) => {
                Object.entries(folderCfg.buttons).forEach(([btnName, btnCfg]) => {
                    if (!btnCfg.type) {
                        if (folderName === "🖱️") {
                            btnCfg.type = "tool";
                        } else {
                            btnCfg.type = "template";
                        }
                    }
                    if (btnCfg.type === "template" && typeof btnCfg.autoSubmit !== 'boolean') {
                        btnCfg.autoSubmit = false;
                    }
                });
            });

            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
            if (rerenderFn) rerenderFn(newFolderName);
            console.log(`✅ 文件夹 "${newFolderName}" 已保存。`);
            updateButtonContainer();
            updateCounters(); // 更新所有计数器
        });
    };

    const createSettingsButton = () => {
        const button = document.createElement('button');
        button.innerText = '⚙️';
        button.type = 'button';
        button.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
        button.style.color = 'var(--text-color, #333333)';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.padding = '5px 10px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.marginLeft = '10px';
        button.addEventListener('click', showUnifiedSettingsDialog);
        return button;
    };

    const createCutButton = () => {
        const button = document.createElement('button');
        button.innerText = '✂️';
        button.type = 'button';
        button.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
        button.style.color = 'var(--text-color, #333333)';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.padding = '5px 10px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.marginLeft = '10px';
        button.title = '剪切输入框内容';
        // 阻止mousedown默认行为以维持输入框焦点
        button.addEventListener('mousedown', (e) => {
            e.preventDefault();
        });
        button.addEventListener('click', async (e) => {
            e.preventDefault();
            e.stopPropagation();
            const focusedElement = document.activeElement;
            if (!focusedElement || !(focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                console.warn("当前未聚焦到有效的 textarea 或 contenteditable 元素。");
                return;
            }
            let text = '';
            if (focusedElement.tagName.toLowerCase() === 'textarea') {
                text = focusedElement.value;
                // 清空textarea内容
                const nativeSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value').set;
                nativeSetter.call(focusedElement, '');
                const inputEvent = new InputEvent('input', {
                    bubbles: true,
                    cancelable: true,
                    inputType: 'deleteContent'
                });
                focusedElement.dispatchEvent(inputEvent);
            } else {
                // 处理contenteditable元素
                const childNodes = Array.from(focusedElement.childNodes);
                const textParts = [];
                childNodes.forEach((node, index) => {
                    if (node.nodeType === Node.TEXT_NODE) {
                        textParts.push(node.textContent);
                    } else if (node.nodeName === 'BR') {
                        textParts.push('\n');
                    } else if (node.nodeName === 'P' || node.nodeName === 'DIV') {
                        if (index > -1) textParts.push('\n');
                        textParts.push(node.textContent);
                    }
                });
                text = textParts.join('');
                // 清空contenteditable内容
                setTrustedHTML(focusedElement, '');
            }
            if (text) {
                navigator.clipboard.writeText(text).then(() => {
                    console.log("✅ 已剪切输入框内容到剪贴板。");
                    showTemporaryFeedback(focusedElement, '剪切成功');
                }).catch(err => {
                    console.error("剪切失败:", err);
                    alert("剪切失败,请检查浏览器权限。");
                });
            }
            // 确保输入框保持焦点
            focusedElement.focus();
            // 如果是textarea,还需要设置光标位置到开始处
            if (focusedElement.tagName.toLowerCase() === 'textarea') {
                focusedElement.selectionStart = focusedElement.selectionEnd = 0;
            }
            console.log("✅ 输入框内容已清空。");
            showTemporaryFeedback(focusedElement, '清空成功');
        });
        return button;
    };

    const createCopyButton = () => {
        const button = document.createElement('button');
        button.innerText = '🅲';
        button.type = 'button';
        button.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
        button.style.color = 'var(--text-color, #333333)';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.padding = '5px 10px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.marginLeft = '10px';
        button.title = '复制输入框内容';
        // 阻止mousedown默认行为以维持输入框焦点
        button.addEventListener('mousedown', (e) => {
            e.preventDefault();
        });
        button.addEventListener('click', async (e) => {
            e.preventDefault();
            e.stopPropagation();
            const focusedElement = document.activeElement;
            if (!focusedElement || !(focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                console.warn("当前未聚焦到有效的 textarea 或 contenteditable 元素。");
                return;
            }
            let text = '';
            if (focusedElement.tagName.toLowerCase() === 'textarea') {
                text = focusedElement.value;
            } else {
                const textContent = [];
                const childNodes = Array.from(focusedElement.childNodes);
                childNodes.forEach((node, index) => {
                    if (node.nodeType === Node.TEXT_NODE) {
                        textContent.push(node.textContent);
                    } else if (node.nodeName === 'BR') {
                        textContent.push('\n');
                    } else if (node.nodeName === 'P' || node.nodeName === 'DIV') {
                        if (index > -1) textContent.push('\n');
                        textContent.push(node.textContent);
                    }
                });
                text = textContent.join('');
            }
            if (text) {
                navigator.clipboard.writeText(text).then(() => {
                    console.log("✅ 已复制输入框内容到剪贴板。");
                    showTemporaryFeedback(focusedElement, '复制成功');
                }).catch(err => {
                    console.error("复制失败:", err);
                    alert("复制失败,请检查浏览器权限。");
                });
            }
            // 确保输入框保持焦点
            focusedElement.focus();
        });
        return button;
    };

    const createPasteButton = () => {
        const button = document.createElement('button');
        button.innerText = '🆅';
        button.type = 'button';
        button.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
        button.style.color = 'var(--text-color, #333333)';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.padding = '5px 10px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.marginLeft = '10px';
        button.title = '粘贴剪切板内容';
        // 阻止mousedown默认行为以维持输入框焦点
        button.addEventListener('mousedown', (e) => {
            e.preventDefault();
        });
        button.addEventListener('click', async (e) => {
            e.preventDefault();
            e.stopPropagation();
            const focusedElement = document.activeElement;
            if (!focusedElement || !(focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                console.warn("当前未聚焦到有效的 textarea 或 contenteditable 元素。");
                return;
            }
            try {
                const clipboardText = await navigator.clipboard.readText();
                // 使用现有的insertTextSmart函数插入文本
                insertTextSmart(focusedElement, clipboardText);
                // 添加视觉反馈
                const originalText = button.innerText;
                button.innerText = '✓';
                button.style.backgroundColor = 'var(--success-color, #22c55e)';
                button.style.color = 'white';
                setTimeout(() => {
                    button.innerText = originalText;
                    button.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
                    button.style.color = 'var(--text-color, #333333)';
                }, 1000);
                console.log("✅ 已粘贴剪贴板内容到输入框。");
            } catch (err) {
                console.error("访问剪切板失败:", err);
                alert("粘贴失败,请检查浏览器权限。");
            }
            // 确保输入框保持焦点
            focusedElement.focus();
        });
        return button;
    };

    const createClearButton = () => {
        const button = document.createElement('button');
        button.innerText = '✖️';
        button.type = 'button';
        button.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
        button.style.color = 'var(--text-color, #333333)';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.padding = '5px 10px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.marginLeft = '10px';
        button.title = '清空输入框';
        // 添加mousedown事件处理器来阻止焦点切换
        button.addEventListener('mousedown', (e) => {
            e.preventDefault();
        });
        button.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation(); // 阻止事件冒泡
            const focusedElement = document.activeElement;
            if (!focusedElement || !(focusedElement.tagName === 'TEXTAREA' || focusedElement.getAttribute('contenteditable') === 'true')) {
                console.warn("当前未聚焦到有效的 textarea 或 contenteditable 元素。");
                return;
            }
            // 使用现有的insertTextSmart函数清空内容
            insertTextSmart(focusedElement, '', true);
            // 确保立即重新聚焦
            focusedElement.focus();
            // 如果是textarea,还需要设置光标位置到开始处
            if (focusedElement.tagName.toLowerCase() === 'textarea') {
                focusedElement.selectionStart = focusedElement.selectionEnd = 0;
            }
            console.log("✅ 输入框内容已清空。");
            showTemporaryFeedback(focusedElement, '清空成功');
        });
        return button;
    };

    // 新增的配置设置按钮和弹窗
    const createConfigSettingsButton = () => {
        const button = document.createElement('button');
        button.innerText = '🛠️ 配置管理';
        button.type = 'button';
        button.style.backgroundColor = 'var(--info-color, #4F46E5)';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.padding = '5px 10px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.addEventListener('click', showConfigSettingsDialog);
        return button;
    };

    function exportConfig() {
        const date = new Date();
        const yyyy = date.getFullYear();
        const mm = String(date.getMonth() + 1).padStart(2, '0');
        const dd = String(date.getDate()).padStart(2, '0');
        const hh = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        const ss = String(date.getSeconds()).padStart(2, '0');
        const fileName = `[Chat] Template Text Folders「${yyyy}-${mm}-${dd}」「${hh}:${minutes}:${ss}」.json`;
        const dataStr = JSON.stringify(buttonConfig, null, 2);
        const blob = new Blob([dataStr], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = fileName;
        a.click();
        URL.revokeObjectURL(url);
        console.log("📤 配置已导出。");
    }

    // 新增:显示导入配置预览确认对话框
    function showImportConfirmDialog(importedConfig, onConfirm, onCancel) {
        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }

        // 计算导入配置的统计信息
        const importFolderCount = Object.keys(importedConfig.folders || {}).length;
        const importButtonCount = Object.values(importedConfig.folders || {}).reduce((sum, folder) => {
            return sum + Object.keys(folder.buttons || {}).length;
        }, 0);

        // 计算当前配置的统计信息
        const currentFolderCount = Object.keys(buttonConfig.folders).length;
        const currentButtonCount = Object.values(buttonConfig.folders).reduce((sum, folder) => {
            return sum + Object.keys(folder.buttons).length;
        }, 0);

        const overlay = document.createElement('div');
        overlay.classList.add('import-confirm-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 13000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('import-confirm-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 8px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 480px;
            max-width: 90vw;
            transform: scale(0.95);
            position: relative;
            z-index: 13001;
        `;

        setTrustedHTML(dialog, `
            <div style="
                display: flex;
                align-items: center;
                gap: 12px;
                margin-bottom: 20px;
            ">
                <h3 style="
                    margin: 0;
                    font-size: 18px;
                    font-weight: 600;
                    color: var(--info-color, #4F46E5);
                    display: flex;
                    align-items: center;
                    gap: 8px;
                ">
                    📥 确认导入配置
                </h3>
            </div>

            <div style="
                background-color: var(--button-bg, #f3f4f6);
                border-radius: 8px;
                padding: 16px;
                margin-bottom: 20px;
                border: 1px solid var(--border-color, #e5e7eb);
            ">
                <h4 style="
                    margin: 0 0 12px 0;
                    font-size: 14px;
                    font-weight: 600;
                    color: var(--text-color, #333333);
                ">📊 配置对比</h4>

                <div style="
                    display: grid;
                    grid-template-columns: 1fr 1fr;
                    gap: 16px;
                    margin-bottom: 12px;
                ">
                    <div style="
                        background-color: var(--dialog-bg, #ffffff);
                        padding: 12px;
                        border-radius: 6px;
                        border: 1px solid var(--border-color, #e5e7eb);
                    ">
                        <div style="
                            font-size: 12px;
                            color: var(--text-color, #666);
                            margin-bottom: 8px;
                            font-weight: 500;
                        ">当前配置</div>
                        <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 4px;">
                            <span style="
                                background-color: var(--primary-color, #3B82F6);
                                color: white;
                                border-radius: 50%;
                                width: 18px;
                                height: 18px;
                                font-size: 10px;
                                font-weight: 600;
                                display: flex;
                                align-items: center;
                                justify-content: center;
                            ">${currentFolderCount}</span>
                            <span style="font-size: 13px; color: var(--text-color, #333);">个文件夹</span>
                        </div>
                        <div style="display: flex; align-items: center; gap: 8px;">
                            <span style="
                                background-color: var(--success-color, #22c55e);
                                color: white;
                                border-radius: 50%;
                                width: 18px;
                                height: 18px;
                                font-size: 10px;
                                font-weight: 600;
                                display: flex;
                                align-items: center;
                                justify-content: center;
                            ">${currentButtonCount}</span>
                            <span style="font-size: 13px; color: var(--text-color, #333);">个按钮</span>
                        </div>
                    </div>

                    <div style="
                        background-color: var(--dialog-bg, #ffffff);
                        padding: 12px;
                        border-radius: 6px;
                        border: 1px solid var(--info-color, #4F46E5);
                        position: relative;
                    ">
                        <div style="
                            font-size: 12px;
                            color: var(--info-color, #4F46E5);
                            margin-bottom: 8px;
                            font-weight: 600;
                        ">导入配置</div>
                        <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 4px;">
                            <span style="
                                background-color: var(--primary-color, #3B82F6);
                                color: white;
                                border-radius: 50%;
                                width: 18px;
                                height: 18px;
                                font-size: 10px;
                                font-weight: 600;
                                display: flex;
                                align-items: center;
                                justify-content: center;
                            ">${importFolderCount}</span>
                            <span style="font-size: 13px; color: var(--text-color, #333);">个文件夹</span>
                        </div>
                        <div style="display: flex; align-items: center; gap: 8px;">
                            <span style="
                                background-color: var(--success-color, #22c55e);
                                color: white;
                                border-radius: 50%;
                                width: 18px;
                                height: 18px;
                                font-size: 10px;
                                font-weight: 600;
                                display: flex;
                                align-items: center;
                                justify-content: center;
                            ">${importButtonCount}</span>
                            <span style="font-size: 13px; color: var(--text-color, #333);">个按钮</span>
                        </div>
                    </div>
                </div>
            </div>

            <div style="
                background-color: #fef3c7;
                border: 1px solid #fbbf24;
                border-radius: 6px;
                padding: 12px;
                margin-bottom: 20px;
            ">
                <div style="
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    color: #92400e;
                    font-size: 13px;
                ">
                    <span style="font-size: 16px;">⚠️</span>
                    <strong>注意:导入配置将完全替换当前配置,此操作无法撤销!</strong>
                </div>
            </div>

            <div style="
                display: flex;
                justify-content: flex-end;
                gap: 12px;
            ">
                <button id="cancelImport" style="
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border: none;
                    border-radius: 6px;
                    padding: 8px 16px;
                    cursor: pointer;
                    font-size: 14px;
                    font-weight: 500;
                    transition: all 0.2s ease;
                ">取消</button>
                <button id="confirmImport" style="
                    background-color: var(--info-color, #4F46E5);
                    color: white;
                    border: none;
                    border-radius: 6px;
                    padding: 8px 16px;
                    cursor: pointer;
                    font-size: 14px;
                    font-weight: 500;
                    transition: all 0.2s ease;
                ">确认导入</button>
            </div>
        `);

        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        // 动画效果
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        // 按钮事件
        dialog.querySelector('#cancelImport').addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
            if (onCancel) onCancel();
        });

        dialog.querySelector('#confirmImport').addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;

            // 添加短暂延时,确保弹窗关闭动画完成后再执行导入
            setTimeout(() => {
                if (onConfirm) {
                    onConfirm();
                }
            }, 100);
        });

        // 点击外部忽略
        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) {
                e.stopPropagation();
                e.preventDefault();
            }
        });
    }

    function importConfig(rerenderFn) {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json,application/json';
        input.addEventListener('change', (e) => {
            const file = e.target.files[0];
            if (!file) return;
            const reader = new FileReader();
            reader.onload = (evt) => {
                try {
                    const importedConfig = JSON.parse(evt.target.result);
                    if (importedConfig && typeof importedConfig === 'object') {
                        if (!importedConfig.folders || !importedConfig.folderOrder) {
                            alert('导入的配置文件无效!缺少必要字段。');
                            return;
                        }

                        // 显示预览确认对话框
                        showImportConfirmDialog(
                            importedConfig,
                            () => {
                                // 用户确认导入
                                try {
                                    // 替换现有配置
                                    buttonConfig = importedConfig;

                                    // 确保所有按钮都有'type'字段和'autoSubmit'字段
                                    Object.entries(buttonConfig.folders).forEach(([folderName, folderConfig]) => {
                                        // 确保文件夹有hidden字段
                                        if (typeof folderConfig.hidden !== 'boolean') {
                                            folderConfig.hidden = false;
                                        }

                                        Object.entries(folderConfig.buttons).forEach(([btnName, btnCfg]) => {
                                            if (!btnCfg.type) {
                                                if (folderName === "🖱️") {
                                                    btnCfg.type = "tool";
                                                } else {
                                                    btnCfg.type = "template";
                                                }
                                            }
                                            if (btnCfg.type === "template" && typeof btnCfg.autoSubmit !== 'boolean') {
                                                btnCfg.autoSubmit = false;
                                            }
                                        });
                                    });

                                    // 保存配置
                                    localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));

                                    // 重新渲染设置面板(如果打开)
                                    if (rerenderFn) {
                                        // 重置选中的文件夹为第一个
                                        selectedFolderName = buttonConfig.folderOrder[0] || null;
                                        rerenderFn();
                                    }

                                    console.log("📥 配置已成功导入。");

                                    // 更新按钮栏
                                    updateButtonContainer();
                                    // 应用新配置下的域名样式
                                    try { applyDomainStyles(); } catch (_) {}

                                    // 立即更新所有计数器
                                    setTimeout(() => {
                                        updateCounters();
                                        console.log("📊 导入后计数器已更新。");

                                        // 延时执行回调函数,确保所有渲染完成
                                        setTimeout(() => {
                                            if (rerenderFn) {
                                                rerenderFn();
                                            }
                                        }, 150);
                                    }, 100);

                                } catch (error) {
                                    console.error('导入配置时发生错误:', error);
                                    alert('导入配置时发生错误,请检查文件格式。');
                                }
                            },
                            () => {
                                // 用户取消导入
                                console.log("❌ 用户取消了配置导入。");
                            }
                        );

                    } else {
                        alert('导入的配置文件内容无效!');
                    }
                } catch (error) {
                    console.error('解析配置文件失败:', error);
                    alert('导入的配置文件解析失败!请确认文件格式正确。');
                }
            };
            reader.readAsText(file);
        });
        input.click();
    }

    // 新增的单独配置设置弹窗
    const showConfigSettingsDialog = () => {
        if (currentConfigOverlay) {
            closeExistingOverlay(currentConfigOverlay);
        }
        const overlay = document.createElement('div');
        overlay.classList.add('config-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 12000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('config-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 400px;
            max-width: 90vw;
        `;

        setTrustedHTML(dialog, `
            <h3 style="margin:0 0 20px 0;font-size:18px;font-weight:600; color: var(--text-color, #333333);">🛠️ 配置管理</h3>
            <div style="
                display:flex;
                flex-direction:column;
                gap:20px;
                margin-bottom:20px;
            ">
                <!-- 重置按钮部分 -->
                <div style="
                    display:flex;
                    flex-direction:row;
                    align-items:center;
                    padding-bottom:16px;
                    border-bottom:1px solid var(--border-color, #e5e7eb);
                ">
                    <span style="margin-right:12px;color: var(--text-color, #333333);">恢复默认设置:</span>
                    <button id="resetSettingsBtn" style="
                        ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                        background-color: var(--cancel-color, #6B7280);
                        color: white;
                        border-radius:4px;
                    ">↩️ 重置</button>
                </div>
                <!-- 导入导出部分 -->
                <div style="
                    display:flex;
                    flex-direction:row;
                    align-items:center;
                ">
                    <span style="margin-right:12px;color: var(--text-color, #333333);">配置导入导出:</span>
                    <div style="display:flex;gap:8px;">
                        <button id="importConfigBtn" style="
                            ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                            background-color: var(--add-color, #fd7e14);
                            color: white;
                            border-radius:4px;
                        ">📥 导入</button>
                        <button id="exportConfigBtn" style="
                            ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                            background-color: var(--success-color, #22c55e);
                            color: white;
                            border-radius:4px;
                        ">📤 导出</button>
                    </div>
                </div>
            </div>
        `);

        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfigOverlay = overlay;

        overlay.addEventListener('click', (event) => {
            if (event.target === overlay) {
                closeExistingOverlay(overlay);
                if (currentConfigOverlay === overlay) {
                    currentConfigOverlay = null;
                }
                console.log("✅ 配置管理弹窗已通过点击外部关闭");
            }
        });

        // 动画效果
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        dialog.querySelector('#importConfigBtn').addEventListener('click', () => {
            importConfig(() => {
                // 重新渲染主设置面板
                if (currentSettingsOverlay) {
                    selectedFolderName = buttonConfig.folderOrder[0] || null;
                    renderFolderList();
                    renderButtonList();
                    // 确保计数器也被更新
                    setTimeout(() => {
                        updateCounters();
                    }, 50);
                }

                // 导入成功后关闭配置管理弹窗
                if (currentConfigOverlay) {
                    closeExistingOverlay(currentConfigOverlay);
                    currentConfigOverlay = null;
                    console.log("✅ 配置管理弹窗已自动关闭");
                }
            });
        });

        dialog.querySelector('#exportConfigBtn').addEventListener('click', () => {
            exportConfig();
            // 导出完成后关闭配置管理弹窗
            setTimeout(() => {
                if (currentConfigOverlay) {
                    closeExistingOverlay(currentConfigOverlay);
                    currentConfigOverlay = null;
                    console.log("✅ 配置管理弹窗已在导出后关闭");
                }
            }, 500); // 给导出操作一些时间完成
        });

        dialog.querySelector('#resetSettingsBtn').addEventListener('click', () => {
            if (confirm('确认重置所有配置为默认设置吗?')) {
                // 先关闭配置管理弹窗,提升用户体验
                if (currentConfigOverlay) {
                    closeExistingOverlay(currentConfigOverlay);
                    currentConfigOverlay = null;
                    console.log("✅ 配置管理弹窗已在重置前关闭");
                }

                // 执行配置重置
                buttonConfig = JSON.parse(JSON.stringify(defaultConfig));
                // 重置folderOrder
                buttonConfig.folderOrder = Object.keys(buttonConfig.folders);
                // 确保所有按钮都有'type'字段和'autoSubmit'字段
                Object.entries(buttonConfig.folders).forEach(([folderName, folderConfig]) => {
                    Object.entries(folderConfig.buttons).forEach(([btnName, btnCfg]) => {
                        if (!btnCfg.type) {
                            if (folderName === "🖱️") {
                                btnCfg.type = "tool";
                            } else {
                                btnCfg.type = "template";
                            }
                        }
                        if (btnCfg.type === "template" && typeof btnCfg.autoSubmit !== 'boolean') {
                            btnCfg.autoSubmit = false;
                        }
                    });
                });
                localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));

                // 重新渲染设置面板(如果还打开着)
                if (currentSettingsOverlay) {
                    selectedFolderName = buttonConfig.folderOrder[0] || null;
                    renderFolderList();
                    renderButtonList();
                }

                console.log("🔄 配置已重置为默认设置。");

                // 更新按钮栏
                updateButtonContainer();
                // 重置后应用默认/匹配样式
                try { applyDomainStyles(); } catch (_) {}

                // 立即更新计数器
                setTimeout(() => {
                    updateCounters();
                    console.log("📊 重置后计数器已更新。");

                    // 在所有更新完成后显示成功提示
                    setTimeout(() => {
                        alert('已重置为默认配置');
                    }, 50);
                }, 100);
            }
        });
    };

    let selectedFolderName = buttonConfig.folderOrder[0] || null; // 在设置面板中使用
    let folderListContainer, buttonListContainer; // 在渲染函数中定义

    const renderFolderList = () => {
        if (!folderListContainer) return;
        setTrustedHTML(folderListContainer, '');
        const foldersArray = buttonConfig.folderOrder.map(fname => [fname, buttonConfig.folders[fname]]).filter(([f,c])=>c);
        foldersArray.forEach(([fname, fconfig]) => {
            const folderItem = document.createElement('div');
            folderItem.style.cssText = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 8px;
                border-radius: 4px;
                margin: 4px 0;
                background-color: ${selectedFolderName === fname ? (isDarkMode() ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0,0,0,0.1)') : 'transparent'};
                cursor: move;
                direction: ltr;
                min-height: 36px;
            `;
            folderItem.classList.add('folder-item');
            folderItem.setAttribute('draggable', 'true');
            folderItem.setAttribute('data-folder', fname);

            const {container: leftInfo, folderPreview} = (function createFolderPreview(fname, fconfig){
                const container = document.createElement('div');
                container.style.display = 'flex';
                container.style.alignItems = 'center';
                container.style.gap = '8px';
                container.style.flex = '1';
                container.style.minWidth = '0'; // 允许收缩
                container.style.paddingRight = '8px';

                const folderPreview = document.createElement('button');
                folderPreview.textContent = fname;
                folderPreview.style.backgroundColor = fconfig.color;
                folderPreview.style.color = fconfig.textColor || '#ffffff';
                folderPreview.style.border = 'none';
                folderPreview.style.borderRadius = '4px';
                folderPreview.style.padding = '4px 8px';
                folderPreview.style.fontSize = '14px';
                folderPreview.style.cursor = 'grab';
                folderPreview.style.whiteSpace = 'nowrap';
                folderPreview.style.overflow = 'hidden';
                folderPreview.style.textOverflow = 'ellipsis';
                folderPreview.style.maxWidth = '140px';

                container.appendChild(folderPreview);
                return {container, folderPreview};
            })(fname, fconfig);

            const rightBtns = document.createElement('div');
            rightBtns.style.display = 'flex';
            rightBtns.style.gap = '4px'; // 增加按钮间的间距
            rightBtns.style.alignItems = 'center';
            rightBtns.style.width = '130px'; // 与标签栏保持一致的宽度
            rightBtns.style.justifyContent = 'flex-start'; // 改为左对齐
            rightBtns.style.paddingLeft = '8px'; // 添加左侧padding与标签栏对齐
            rightBtns.style.paddingRight = '12px'; // 添加右侧padding

            // 创建隐藏状态勾选框容器
            const hiddenCheckboxContainer = document.createElement('div');
            hiddenCheckboxContainer.style.display = 'flex';
            hiddenCheckboxContainer.style.alignItems = 'center';
            hiddenCheckboxContainer.style.justifyContent = 'center';
            hiddenCheckboxContainer.style.width = '36px'; // 与标签栏"显示"列宽度一致
            hiddenCheckboxContainer.style.marginRight = '4px'; // 添加右边距
            hiddenCheckboxContainer.style.padding = '2px';
            hiddenCheckboxContainer.style.borderRadius = '3px';
            hiddenCheckboxContainer.style.cursor = 'pointer';
            hiddenCheckboxContainer.title = '勾选后该文件夹将在主界面显示';

            const hiddenCheckbox = document.createElement('input');
            hiddenCheckbox.type = 'checkbox';
            hiddenCheckbox.checked = !fconfig.hidden; // 勾选表示显示
            hiddenCheckbox.style.cursor = 'pointer';
            hiddenCheckbox.style.accentColor = 'var(--primary-color, #3B82F6)';
            hiddenCheckbox.style.margin = '0';
            hiddenCheckbox.style.transform = 'scale(1.1)'; // 稍微放大勾选框以便操作

            // 删除了checkboxText元素,不再显示"显示"文字

            // 关键修复:先添加change事件监听器到checkbox
            hiddenCheckbox.addEventListener('change', (e) => {
                e.stopPropagation();
                e.stopImmediatePropagation();
                const newHiddenState = !hiddenCheckbox.checked;
                fconfig.hidden = newHiddenState;
                localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
                console.log(`✅ 文件夹 "${fname}" 的隐藏状态已设置为 ${fconfig.hidden}`);
                updateButtonContainer();
            });

            // 为checkbox添加click事件,确保优先处理
            hiddenCheckbox.addEventListener('click', (e) => {
                e.stopPropagation();
                e.stopImmediatePropagation();
            });

            // 容器点击事件,点击容器时切换checkbox状态
            hiddenCheckboxContainer.addEventListener('click', (e) => {
                e.stopPropagation();
                e.stopImmediatePropagation();

                // 如果点击的不是checkbox本身,则手动切换checkbox状态
                if (e.target !== hiddenCheckbox) {
                    hiddenCheckbox.checked = !hiddenCheckbox.checked;
                    // 手动触发change事件
                    const changeEvent = new Event('change', { bubbles: false });
                    hiddenCheckbox.dispatchEvent(changeEvent);
                }
            });

            hiddenCheckboxContainer.appendChild(hiddenCheckbox);
            // 不再添加checkboxText


            // 创建编辑按钮
            const editFolderBtn = document.createElement('button');
            editFolderBtn.textContent = '✏️';
            editFolderBtn.style.cssText = `
                background: none;
                border: none;
                cursor: pointer;
                font-size: 14px;
                color: var(--primary-color, #3B82F6);
                width: 36px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-right: 4px;
            `;
            editFolderBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                showFolderEditDialog(fname, fconfig, (newFolderName) => {
                    selectedFolderName = newFolderName;
                    renderFolderList();
                    renderButtonList();
                });
            });

            const deleteFolderBtn = document.createElement('button');
            deleteFolderBtn.textContent = '🗑️';
            deleteFolderBtn.style.cssText = `
                background: none;
                border: none;
                cursor: pointer;
                font-size: 14px;
                color: var(--danger-color, #ef4444);
                width: 36px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
            `;
            deleteFolderBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                showDeleteFolderConfirmDialog(fname, () => {
                    const allFolders = buttonConfig.folderOrder;
                    selectedFolderName = allFolders[0] || null;
                    renderFolderList();
                    renderButtonList();
                    updateCounters(); // 更新所有计数器
                });
            });

            rightBtns.appendChild(hiddenCheckboxContainer);
            rightBtns.appendChild(editFolderBtn);
            rightBtns.appendChild(deleteFolderBtn);

            folderItem.appendChild(leftInfo);
            folderItem.appendChild(rightBtns);

            // 修改folderItem的点击事件,排除右侧按钮区域
            folderItem.addEventListener('click', (e) => {
                // 如果点击的是右侧按钮区域,不触发文件夹选择
                if (rightBtns.contains(e.target)) {
                    return;
                }
                selectedFolderName = fname;
                renderFolderList();
                renderButtonList();
            });

            folderItem.addEventListener('dragstart', (e) => {
                e.dataTransfer.setData('text/plain', fname);
                folderItem.style.opacity = '0.5';
            });

            folderItem.addEventListener('dragover', (e) => {
                e.preventDefault();
            });

            folderItem.addEventListener('dragenter', () => {
                folderItem.style.border = `2px solid var(--primary-color, #3B82F6)`;
            });

            folderItem.addEventListener('dragleave', () => {
                folderItem.style.border = 'none';
            });

            folderItem.addEventListener('drop', (e) => {
                e.preventDefault();
                const draggedFolder = e.dataTransfer.getData('text/plain');
                if (draggedFolder && draggedFolder !== fname) {
                    const draggedIndex = buttonConfig.folderOrder.indexOf(draggedFolder);
                    const targetIndex = buttonConfig.folderOrder.indexOf(fname);
                    if (draggedIndex > -1 && targetIndex > -1) {
                        const [removed] = buttonConfig.folderOrder.splice(draggedIndex, 1);
                        buttonConfig.folderOrder.splice(targetIndex, 0, removed);
                        localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
                        renderFolderList();
                        renderButtonList();
                        console.log(`🔄 文件夹顺序已更新:${draggedFolder} 移动到 ${fname} 前。`);
                        // 更新按钮栏
                        updateButtonContainer();
                    }
                }
                // Check if a button is being dropped onto this folder
                const buttonData = e.dataTransfer.getData('application/json');
                if (buttonData) {
                    try {
                        const { buttonName: draggedBtnName, sourceFolder } = JSON.parse(buttonData);
                        if (draggedBtnName && sourceFolder && sourceFolder !== fname) {
                            // Move the button from sourceFolder to fname
                            const button = buttonConfig.folders[sourceFolder].buttons[draggedBtnName];
                            if (button) {
                                // Remove from source
                                delete buttonConfig.folders[sourceFolder].buttons[draggedBtnName];
                                // Add to target
                                buttonConfig.folders[fname].buttons[draggedBtnName] = button;
                                localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
                                renderFolderList();
                                renderButtonList();
                                console.log(`🔄 按钮 "${draggedBtnName}" 已从 "${sourceFolder}" 移动到 "${fname}"。`);
                                // Update button container
                                updateButtonContainer();
                            }
                        }
                    } catch (error) {
                        console.error("解析拖放数据失败:", error);
                    }
                }
                folderItem.style.border = 'none';
            });

            folderItem.addEventListener('dragend', () => {
                folderItem.style.opacity = '1';
            });

            folderListContainer.appendChild(folderItem);
        });
    };

    // 升级:更新所有计数显示的函数
    const updateCounters = () => {
        // 计算统计数据
        const totalFolders = Object.keys(buttonConfig.folders).length;
        const totalButtons = Object.values(buttonConfig.folders).reduce((sum, folder) => {
            return sum + Object.keys(folder.buttons).length;
        }, 0);

        // 更新文件夹总数计数
        const folderCountBadge = queryUI('#folderCountBadge');
        if (folderCountBadge) {
            folderCountBadge.textContent = totalFolders.toString();
            folderCountBadge.title = `共有 ${totalFolders} 个文件夹`;
        }

        // 更新按钮总数计数
        const totalButtonCountBadge = queryUI('#totalButtonCountBadge');
        if (totalButtonCountBadge) {
            totalButtonCountBadge.textContent = totalButtons.toString();
            totalButtonCountBadge.title = `所有文件夹共有 ${totalButtons} 个按钮`;
        }

        // 更新当前文件夹按钮数计数
        if (selectedFolderName && buttonConfig.folders[selectedFolderName]) {
            const currentFolderButtonCount = Object.keys(buttonConfig.folders[selectedFolderName].buttons).length;
            const currentFolderBadge = queryUI('#currentFolderButtonCount');
            if (currentFolderBadge) {
                currentFolderBadge.textContent = currentFolderButtonCount.toString();
                currentFolderBadge.title = `"${selectedFolderName}" 文件夹有 ${currentFolderButtonCount} 个按钮`;
            }
        }

        console.log(`📊 计数器已更新: ${totalFolders}个文件夹, ${totalButtons}个按钮总数`);
    };

    const renderButtonList = () => {
        if (!buttonListContainer) return;
        setTrustedHTML(buttonListContainer, '');
        if (!selectedFolderName) return;
        const currentFolderConfig = buttonConfig.folders[selectedFolderName];
        if (!currentFolderConfig) return;

    const rightHeader = document.createElement('div');
    rightHeader.style.display = 'flex';
    rightHeader.style.justifyContent = 'space-between';
    rightHeader.style.alignItems = 'center';
    rightHeader.style.marginBottom = '8px';

    const folderNameLabel = document.createElement('h3');
    folderNameLabel.style.display = 'flex';
    folderNameLabel.style.alignItems = 'center';
    folderNameLabel.style.gap = '10px';
    folderNameLabel.style.margin = '0';

    const folderNameText = document.createElement('span');
    setTrustedHTML(folderNameText, `➤ <strong>${selectedFolderName}</strong>`);

    const buttonCountBadge = document.createElement('span');
    buttonCountBadge.id = 'currentFolderButtonCount';
    buttonCountBadge.style.cssText = `
        background-color: var(--info-color, #6366F1);
        color: white;
        border-radius: 50%;
        width: 20px;
        height: 20px;
        font-size: 11px;
        font-weight: 600;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        cursor: help;
        transition: all 0.2s ease;
    `;

    // 计算当前文件夹的按钮数量
    const buttonCount = Object.keys(currentFolderConfig.buttons).length;
    buttonCountBadge.textContent = buttonCount.toString();
    buttonCountBadge.title = `"${selectedFolderName}" 文件夹有 ${buttonCount} 个按钮`;

    // 添加hover效果
    buttonCountBadge.addEventListener('mouseenter', () => {
        buttonCountBadge.style.transform = 'scale(1.15)';
        buttonCountBadge.style.boxShadow = '0 2px 5px rgba(0,0,0,0.15)';
    });
    buttonCountBadge.addEventListener('mouseleave', () => {
        buttonCountBadge.style.transform = 'scale(1)';
        buttonCountBadge.style.boxShadow = '0 1px 3px rgba(0,0,0,0.1)';
    });

    folderNameLabel.appendChild(folderNameText);
    folderNameLabel.appendChild(buttonCountBadge);

    const addNewButtonBtn = document.createElement('button');
    Object.assign(addNewButtonBtn.style, styles.button, {
        backgroundColor: 'var(--add-color, #fd7e14)',
        color: 'white',
        borderRadius: '4px'
    });
    addNewButtonBtn.textContent = '+ 新建按钮';
    addNewButtonBtn.addEventListener('click', () => {
        showButtonEditDialog(selectedFolderName, '', {}, () => {
            renderButtonList();
        });
    });

    rightHeader.appendChild(folderNameLabel);
    rightHeader.appendChild(addNewButtonBtn);

    buttonListContainer.appendChild(rightHeader);

    // 新增:创建包含标签栏和内容的容器,滚动条将出现在此容器右侧
    const contentWithHeaderContainer = document.createElement('div');
    contentWithHeaderContainer.style.cssText = `
        flex: 1;
        display: flex;
        flex-direction: column;
        overflow-y: auto;
        border: 1px solid var(--border-color, #e5e7eb);
        border-radius: 4px;
    `;

    // 创建按钮列表标签栏 - 固定在滚动容器顶部
    const buttonHeaderBar = document.createElement('div');
    buttonHeaderBar.style.cssText = `
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 6px 8px;
        background-color: var(--button-bg, #f3f4f6);
        border-bottom: 1px solid var(--border-color, #e5e7eb);
        border-radius: 4px 4px 0 0;
        font-size: 12px;
        font-weight: 500;
        color: var(--text-color, #333333);
        position: sticky;
        top: 0;
        z-index: 2;
        flex-shrink: 0;
    `;

    const leftButtonHeaderLabel = document.createElement('div');
    leftButtonHeaderLabel.textContent = '按钮预览';
    leftButtonHeaderLabel.style.flex = '1';
    leftButtonHeaderLabel.style.textAlign = 'left';
    leftButtonHeaderLabel.style.paddingLeft = 'calc(8px + 1em)';

    const rightButtonHeaderLabels = document.createElement('div');
    rightButtonHeaderLabels.style.display = 'flex';
    rightButtonHeaderLabels.style.gap = '4px';
    rightButtonHeaderLabels.style.alignItems = 'center';
    rightButtonHeaderLabels.style.width = '240px';
    rightButtonHeaderLabels.style.paddingLeft = '8px';
    rightButtonHeaderLabels.style.paddingRight = '12px';

    const variableLabel = document.createElement('div');
    variableLabel.textContent = '变量';
    variableLabel.style.width = '110px';
    variableLabel.style.textAlign = 'center';
    variableLabel.style.fontSize = '12px';
    variableLabel.style.marginLeft = '-1em';
    const autoSubmitLabel = document.createElement('div');
    autoSubmitLabel.textContent = '自动提交';
    autoSubmitLabel.style.width = '64px';
    autoSubmitLabel.style.textAlign = 'center';
    autoSubmitLabel.style.fontSize = '12px';
    autoSubmitLabel.style.marginLeft = 'calc(-0.5em)';

    const editButtonLabel = document.createElement('div');
    editButtonLabel.textContent = '修改';
    editButtonLabel.style.width = '40px';
    editButtonLabel.style.textAlign = 'center';
    editButtonLabel.style.fontSize = '12px';

    const deleteButtonLabel = document.createElement('div');
    deleteButtonLabel.textContent = '删除';
    deleteButtonLabel.style.width = '36px';
    deleteButtonLabel.style.textAlign = 'center';
    deleteButtonLabel.style.fontSize = '12px';

    rightButtonHeaderLabels.appendChild(variableLabel);
    rightButtonHeaderLabels.appendChild(autoSubmitLabel);
    rightButtonHeaderLabels.appendChild(editButtonLabel);
    rightButtonHeaderLabels.appendChild(deleteButtonLabel);

    buttonHeaderBar.appendChild(leftButtonHeaderLabel);
    buttonHeaderBar.appendChild(rightButtonHeaderLabels);

    // 修改:内容区域不再需要自己的滚动条和边框
    const btnScrollArea = document.createElement('div');
    btnScrollArea.style.cssText = `
        flex: 1;
        padding: 8px;
        overflow-y: visible;
        min-height: 0;
    `;

    const currentFolderButtons = Object.entries(currentFolderConfig.buttons);
    const createButtonPreview = (btnName, btnCfg) => {
        const btnEl = createCustomButtonElement(btnName, btnCfg);
        btnEl.style.marginBottom = '0px';
        btnEl.style.marginRight = '8px';
        btnEl.style.cursor = 'grab';
        btnEl.style.flexShrink = '1';
        btnEl.style.minWidth = '0';
        btnEl.style.maxWidth = '100%';
        btnEl.style.whiteSpace = 'normal';
        btnEl.style.wordBreak = 'break-word';
        btnEl.style.overflow = 'visible';
        btnEl.style.lineHeight = '1.4';
        btnEl.style.overflowWrap = 'anywhere';
        btnEl.style.display = 'inline-flex';
        btnEl.style.flexWrap = 'wrap';
        btnEl.style.alignItems = 'center';
        btnEl.style.justifyContent = 'flex-start';
        btnEl.style.columnGap = '6px';
        btnEl.style.rowGap = '2px';
        btnEl.style.alignSelf = 'flex-start';
        return btnEl;
    };

    currentFolderButtons.forEach(([btnName, cfg]) => {
        const btnItem = document.createElement('div');
        btnItem.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            margin-bottom: 8px;
            padding: 4px;
            border: 1px solid var(--border-color, #e5e7eb);
            border-radius: 4px;
            background-color: var(--button-bg, #f3f4f6);
            cursor: move;
            width: 100%;
            box-sizing: border-box;
            overflow: visible;
        `;
        btnItem.setAttribute('draggable', 'true');
        btnItem.setAttribute('data-button-name', btnName);

        const leftPart = document.createElement('div');
        leftPart.style.display = 'flex';
        leftPart.style.alignItems = 'flex-start';
        leftPart.style.gap = '8px';
        leftPart.style.flex = '1';
        leftPart.style.minWidth = '0';
        leftPart.style.overflow = 'visible';

        const previewWrapper = document.createElement('div');
        previewWrapper.style.display = 'flex';
        previewWrapper.style.alignItems = 'flex-start';
        previewWrapper.style.flex = '1 1 auto';
        previewWrapper.style.maxWidth = '100%';
        previewWrapper.style.minWidth = '0';
        previewWrapper.style.overflow = 'visible';
        previewWrapper.style.alignSelf = 'flex-start';

        const btnPreview = createButtonPreview(btnName, cfg);
        previewWrapper.appendChild(btnPreview);
        leftPart.appendChild(previewWrapper);

        const opsDiv = document.createElement('div');
        opsDiv.style.display = 'flex';
        opsDiv.style.gap = '4px';
        opsDiv.style.alignItems = 'center';
        opsDiv.style.width = '240px';
        opsDiv.style.paddingLeft = '8px';
        opsDiv.style.paddingRight = '12px';
        opsDiv.style.flexShrink = '0';

        const variableInfoContainer = document.createElement('div');
        variableInfoContainer.style.display = 'flex';
        variableInfoContainer.style.alignItems = 'center';
        variableInfoContainer.style.justifyContent = 'center';
        variableInfoContainer.style.flexDirection = 'column';
        variableInfoContainer.style.width = '110px';
        variableInfoContainer.style.fontSize = '12px';
        variableInfoContainer.style.lineHeight = '1.2';
        variableInfoContainer.style.wordBreak = 'break-word';
        variableInfoContainer.style.textAlign = 'center';
        variableInfoContainer.style.color = 'var(--text-color, #333333)';

        if (cfg.type === 'template') {
            const variablesUsed = extractTemplateVariables(cfg.text || '');
            if (variablesUsed.length > 0) {
                const displayText = variablesUsed.join('、');
                variableInfoContainer.textContent = displayText;
                variableInfoContainer.title = `模板变量: ${displayText}`;
            } else {
                variableInfoContainer.textContent = '无';
                variableInfoContainer.title = '未使用模板变量';
            }
        } else {
            variableInfoContainer.textContent = '—';
            variableInfoContainer.title = '工具按钮不使用模板变量';
        }

        // 创建"自动提交"开关容器
        const autoSubmitContainer = document.createElement('div');
        autoSubmitContainer.style.display = 'flex';
        autoSubmitContainer.style.alignItems = 'center';
        autoSubmitContainer.style.justifyContent = 'center';
        autoSubmitContainer.style.width = '60px';

        const autoSubmitCheckbox = document.createElement('input');
        autoSubmitCheckbox.type = 'checkbox';
        autoSubmitCheckbox.checked = cfg.autoSubmit || false;
        autoSubmitCheckbox.style.cursor = 'pointer';
        autoSubmitCheckbox.style.accentColor = 'var(--primary-color, #3B82F6)';
        autoSubmitCheckbox.style.margin = '0';
        autoSubmitCheckbox.style.transform = 'scale(1.1)';
        autoSubmitCheckbox.addEventListener('change', () => {
            cfg.autoSubmit = autoSubmitCheckbox.checked;
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
            console.log(`✅ 按钮 "${btnName}" 的自动提交已设置为 ${autoSubmitCheckbox.checked}`);
        });

        autoSubmitContainer.appendChild(autoSubmitCheckbox);

        // 创建编辑按钮
        const editBtn = document.createElement('button');
        editBtn.textContent = '✏️';
        editBtn.style.cssText = `
            background: none;
            border: none;
            cursor: pointer;
            color: var(--primary-color, #3B82F6);
            font-size: 14px;
            width: 36px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
        `;
        editBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            showButtonEditDialog(selectedFolderName, btnName, cfg, () => {
                renderButtonList();
            });
        });

        // 创建删除按钮
        const deleteBtn = document.createElement('button');
        deleteBtn.textContent = '🗑️';
        deleteBtn.style.cssText = `
            background: none;
            border: none;
            cursor: pointer;
            color: var(--danger-color, #ef4444);
            font-size: 14px;
            width: 36px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
        `;
        deleteBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            showDeleteButtonConfirmDialog(selectedFolderName, btnName, () => {
                renderButtonList();
            });
        });

        opsDiv.appendChild(variableInfoContainer);
        opsDiv.appendChild(autoSubmitContainer);
        opsDiv.appendChild(editBtn);
        opsDiv.appendChild(deleteBtn);

        btnItem.appendChild(leftPart);
        btnItem.appendChild(opsDiv);

        btnItem.addEventListener('dragstart', (e) => {
            e.dataTransfer.setData('application/json', JSON.stringify({
                buttonName: btnName,
                sourceFolder: selectedFolderName
            }));
            btnItem.style.opacity = '0.5';
        });

        btnItem.addEventListener('dragover', (e) => {
            e.preventDefault();
        });

        btnItem.addEventListener('dragenter', () => {
            btnItem.style.border = `2px solid var(--primary-color, #3B82F6)`;
        });

        btnItem.addEventListener('dragleave', () => {
            btnItem.style.border = `1px solid var(--border-color, #e5e7eb)`;
        });

        btnItem.addEventListener('drop', (e) => {
            e.preventDefault();
            const data = JSON.parse(e.dataTransfer.getData('application/json'));
            const { buttonName: draggedBtnName } = data;
            if (draggedBtnName && draggedBtnName !== btnName) {
                const buttonsKeys = Object.keys(buttonConfig.folders[selectedFolderName].buttons);
                const draggedIndex = buttonsKeys.indexOf(draggedBtnName);
                const targetIndex = buttonsKeys.indexOf(btnName);
                if (draggedIndex > -1 && targetIndex > -1) {
                    const reordered = [...buttonsKeys];
                    reordered.splice(draggedIndex, 1);
                    reordered.splice(targetIndex, 0, draggedBtnName);
                    const newOrderedMap = {};
                    reordered.forEach(k => {
                        newOrderedMap[k] = buttonConfig.folders[selectedFolderName].buttons[k];
                    });
                    buttonConfig.folders[selectedFolderName].buttons = newOrderedMap;
                    localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
                    renderButtonList();
                    console.log(`🔄 按钮顺序已更新:${draggedBtnName} 移动到 ${btnName} 前。`);
                    // 更新按钮栏
                    updateButtonContainer();
                }
            }
            btnItem.style.border = `1px solid var(--border-color, #e5e7eb)`;
        });

        btnItem.addEventListener('dragend', () => {
            btnItem.style.opacity = '1';
        });

        btnScrollArea.appendChild(btnItem);
    });

    // 修改:将标签栏和内容区域添加到新的容器中
    contentWithHeaderContainer.appendChild(buttonHeaderBar);
    contentWithHeaderContainer.appendChild(btnScrollArea);

    // 修改:将新容器添加到主容器中
    buttonListContainer.appendChild(contentWithHeaderContainer);
};

    function updateButtonBarHeight(newHeight) {
        const clamped = Math.min(150, Math.max(50, newHeight)); // 限制范围
        buttonConfig.buttonBarHeight = clamped;
        localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));

        // 更新容器高度
        const container = queryUI('.folder-buttons-container');
        if (container) {
            container.style.height = clamped + 'px';
            try {
                updateButtonBarLayout(container, clamped);
            } catch (err) {
                console.warn('更新按钮栏布局失败:', err);
            }
        }
        console.log("🔧 按钮栏高度已更新为", clamped, "px");
        try {
            applyDomainStyles();
        } catch (err) {
            console.warn('应用域名样式失败:', err);
        }
    }

    const showUnifiedSettingsDialog = () => {
        if (settingsDialogMainContainer) {
            settingsDialogMainContainer.style.minHeight = '';
            settingsDialogMainContainer = null;
        }
        if (currentSettingsOverlay) {
            closeExistingOverlay(currentSettingsOverlay);
            currentSettingsOverlay = null;
        }
        const overlay = document.createElement('div');
        overlay.classList.add('settings-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 11000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('settings-dialog');
        dialog.classList.add('cttf-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 920px;
            max-width: 95vw;
            max-height: 80vh;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        `;

        const header = document.createElement('div');
        header.style.display = 'flex';
        header.style.justifyContent = 'space-between';
        header.style.alignItems = 'center';
        header.style.marginBottom = '16px';

        const title = document.createElement('h2');
        title.style.display = 'flex';
        title.style.alignItems = 'center';
        title.style.gap = '12px';
        title.style.margin = '0';
        title.style.fontSize = '20px';
        title.style.fontWeight = '600';

        const titleText = document.createElement('span');
        titleText.textContent = "⚙️ 设置面板";

        const collapseToggleBtn = document.createElement('button');
        collapseToggleBtn.type = 'button';
        collapseToggleBtn.style.cssText = `
            background-color: transparent;
            color: var(--text-color, #333333);
            border: none;
            border-radius: 4px;
            padding: 4px;
            width: 28px;
            height: 28px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
        `;
        collapseToggleBtn.title = '折叠左侧设置区域';
        collapseToggleBtn.setAttribute('aria-label', collapseToggleBtn.title);
        const collapseToggleSVG = `<svg fill="currentColor" viewBox="0 0 56 56" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M 7.7148 49.5742 L 48.2852 49.5742 C 53.1836 49.5742 55.6446 47.1367 55.6446 42.3086 L 55.6446 13.6914 C 55.6446 8.8633 53.1836 6.4258 48.2852 6.4258 L 7.7148 6.4258 C 2.8398 6.4258 .3554 8.8398 .3554 13.6914 L .3554 42.3086 C .3554 47.1602 2.8398 49.5742 7.7148 49.5742 Z M 7.7851 45.8008 C 5.4413 45.8008 4.1288 44.5586 4.1288 42.1211 L 4.1288 13.8789 C 4.1288 11.4414 5.4413 10.1992 7.7851 10.1992 L 18.2148 10.1992 L 18.2148 45.8008 Z M 48.2147 10.1992 C 50.5350 10.1992 51.8708 11.4414 51.8708 13.8789 L 51.8708 42.1211 C 51.8708 44.5586 50.5350 45.8008 48.2147 45.8008 L 21.8944 45.8008 L 21.8944 10.1992 Z M 13.7148 18.8945 C 14.4179 18.8945 15.0507 18.2617 15.0507 17.5820 C 15.0507 16.8789 14.4179 16.2696 13.7148 16.2696 L 8.6757 16.2696 C 7.9726 16.2696 7.3632 16.8789 7.3632 17.5820 C 7.3632 18.2617 7.9726 18.8945 8.6757 18.8945 Z M 13.7148 24.9649 C 14.4179 24.9649 15.0507 24.3320 15.0507 23.6289 C 15.0507 22.9258 14.4179 22.3398 13.7148 22.3398 L 8.6757 22.3398 C 7.9726 22.3398 7.3632 22.9258 7.3632 23.6289 C 7.3632 24.3320 7.9726 24.9649 8.6757 24.9649 Z M 13.7148 31.0118 C 14.4179 31.0118 15.0507 30.4258 15.0507 29.7227 C 15.0507 29.0196 14.4179 28.4102 13.7148 28.4102 L 8.6757 28.4102 C 7.9726 28.4102 7.3632 29.0196 7.3632 29.7227 C 7.3632 30.4258 7.9726 31.0118 8.6757 31.0118 Z"></path></g></svg>`;
        setTrustedHTML(collapseToggleBtn, collapseToggleSVG);
        collapseToggleBtn.style.flex = '0 0 auto';
        collapseToggleBtn.style.flexShrink = '0';
        collapseToggleBtn.style.width = '28px';
        collapseToggleBtn.style.height = '28px';
        collapseToggleBtn.style.minWidth = '28px';
        collapseToggleBtn.style.minHeight = '28px';
        collapseToggleBtn.style.maxWidth = '28px';
        collapseToggleBtn.style.maxHeight = '28px';
        collapseToggleBtn.style.padding = '0';
        collapseToggleBtn.style.lineHeight = '0';
        collapseToggleBtn.style.boxSizing = 'border-box';
        collapseToggleBtn.style.aspectRatio = '1 / 1';
        const collapseToggleIcon = collapseToggleBtn.querySelector('svg');
        if (collapseToggleIcon) {
            collapseToggleIcon.style.width = '16px';
            collapseToggleIcon.style.height = '16px';
            collapseToggleIcon.style.display = 'block';
            collapseToggleIcon.style.flex = '0 0 auto';
        }

        // 计数器容器
        const countersContainer = document.createElement('div');
        countersContainer.style.display = 'flex';
        countersContainer.style.gap = '8px';
        countersContainer.style.alignItems = 'center';

        // 文件夹总数计数器(圆形)
        const folderCountBadge = document.createElement('span');
        folderCountBadge.id = 'folderCountBadge';
        folderCountBadge.style.cssText = `
            background-color: var(--primary-color, #3B82F6);
            color: white;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            font-size: 12px;
            font-weight: 600;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            cursor: help;
            transition: all 0.2s ease;
        `;

        // 按钮总数计数器(圆形)
        const totalButtonCountBadge = document.createElement('span');
        totalButtonCountBadge.id = 'totalButtonCountBadge';
        totalButtonCountBadge.style.cssText = `
            background-color: var(--success-color, #22c55e);
            color: white;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            font-size: 12px;
            font-weight: 600;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            cursor: help;
            transition: all 0.2s ease;
        `;

        // 计算初始数据
        const totalFolders = Object.keys(buttonConfig.folders).length;
        const totalButtons = Object.values(buttonConfig.folders).reduce((sum, folder) => {
            return sum + Object.keys(folder.buttons).length;
        }, 0);

        // 设置计数和提示
        folderCountBadge.textContent = totalFolders.toString();
        folderCountBadge.title = `共有 ${totalFolders} 个文件夹`;

        totalButtonCountBadge.textContent = totalButtons.toString();
        totalButtonCountBadge.title = `所有文件夹共有 ${totalButtons} 个按钮`;

        // 添加hover效果
        [folderCountBadge, totalButtonCountBadge].forEach(badge => {
            badge.addEventListener('mouseenter', () => {
                badge.style.transform = 'scale(1.1)';
                badge.style.boxShadow = '0 3px 6px rgba(0,0,0,0.15)';
            });
            badge.addEventListener('mouseleave', () => {
                badge.style.transform = 'scale(1)';
                badge.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
            });
        });

        countersContainer.appendChild(folderCountBadge);
        countersContainer.appendChild(totalButtonCountBadge);

        title.appendChild(collapseToggleBtn);
        title.appendChild(titleText);
        title.appendChild(countersContainer);

        const headerBtnsWrapper = document.createElement('div');
        headerBtnsWrapper.style.display = 'flex';
        headerBtnsWrapper.style.gap = '10px';

        // 新建自动化按钮
        const automationBtn = document.createElement('button');
        automationBtn.innerText = '⚡ 自动化';
        automationBtn.type = 'button';
        automationBtn.style.backgroundColor = 'var(--info-color, #4F46E5)';
        automationBtn.style.color = 'white';
        automationBtn.style.border = 'none';
        automationBtn.style.borderRadius = '4px';
        automationBtn.style.padding = '5px 10px';
        automationBtn.style.cursor = 'pointer';
        automationBtn.style.fontSize = '14px';
        automationBtn.addEventListener('click', () => {
            showAutomationSettingsDialog();
        });
        headerBtnsWrapper.appendChild(automationBtn);

        // 样式管理按钮
        const styleMgmtBtn = document.createElement('button');
        styleMgmtBtn.innerText = '🎨 样式管理';
        styleMgmtBtn.type = 'button';
        styleMgmtBtn.style.backgroundColor = 'var(--info-color, #4F46E5)';
        styleMgmtBtn.style.color = 'white';
        styleMgmtBtn.style.border = 'none';
        styleMgmtBtn.style.borderRadius = '4px';
        styleMgmtBtn.style.padding = '5px 10px';
        styleMgmtBtn.style.cursor = 'pointer';
        styleMgmtBtn.style.fontSize = '14px';
        styleMgmtBtn.addEventListener('click', () => {
            showStyleSettingsDialog();
        });
        headerBtnsWrapper.appendChild(styleMgmtBtn);

        // 原有创建配置管理按钮
        const openConfigBtn = createConfigSettingsButton();
        headerBtnsWrapper.appendChild(openConfigBtn);

        // 原有保存关闭按钮
        const saveSettingsBtn = document.createElement('button');
        Object.assign(saveSettingsBtn.style, styles.button, {
            backgroundColor: 'var(--success-color, #22c55e)',
            color: 'white',
            borderRadius: '4px'
        });
        saveSettingsBtn.textContent = '💾 关闭并保存';
        saveSettingsBtn.addEventListener('click', () => {
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));

            // 关闭所有相关弹窗
            if (currentConfigOverlay) {
                closeExistingOverlay(currentConfigOverlay);
                currentConfigOverlay = null;
            }

            if (settingsDialogMainContainer) {
                settingsDialogMainContainer.style.minHeight = '';
                settingsDialogMainContainer = null;
            }

            closeExistingOverlay(overlay);
            currentSettingsOverlay = null;
            attachButtons();
            console.log("✅ 设置已保存并关闭设置面板。");
            updateButtonContainer();
        });
        headerBtnsWrapper.appendChild(saveSettingsBtn);

        header.appendChild(title);
        header.appendChild(headerBtnsWrapper);

        const mainContainer = document.createElement('div');
        mainContainer.style.display = 'flex';
        mainContainer.style.flex = '1';
        mainContainer.style.overflow = 'hidden';
        mainContainer.style.flexWrap = 'nowrap';
        mainContainer.style.overflowX = 'auto';
        mainContainer.style.borderTop = `1px solid var(--border-color, #e5e7eb)`;
        settingsDialogMainContainer = mainContainer;

        const folderPanel = document.createElement('div');
        folderPanel.style.display = 'flex';
        folderPanel.style.flexDirection = 'column';
        folderPanel.style.width = '280px';
        folderPanel.style.minWidth = '280px';
        folderPanel.style.marginRight = '12px';
        folderPanel.style.overflowY = 'auto';
        folderPanel.style.padding = '2px 8px 4px 2px';

        // 新增:创建文件夹列表标签栏
        const folderHeaderBar = document.createElement('div');
        folderHeaderBar.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 6px 8px;
            background-color: var(--button-bg, #f3f4f6);
            border: 1px solid var(--border-color, #e5e7eb);
            border-radius: 4px 4px 0 0;
            margin: 0 0 -1px 0;
            font-size: 12px;
            font-weight: 500;
            color: var(--text-color, #333333);
            border-bottom: 1px solid var(--border-color, #e5e7eb);
            position: sticky;
            top: 0;
            z-index: 1;
        `;

        const leftHeaderLabel = document.createElement('div');
        leftHeaderLabel.textContent = '文件夹名称';
        leftHeaderLabel.style.flex = '1';
        leftHeaderLabel.style.textAlign = 'left';
        leftHeaderLabel.style.paddingLeft = 'calc(8px + 1em)';

        const rightHeaderLabels = document.createElement('div');
        rightHeaderLabels.style.display = 'flex';
        rightHeaderLabels.style.gap = '0px';
        rightHeaderLabels.style.alignItems = 'center';
        rightHeaderLabels.style.width = '140px'; // 增加宽度以提供更多间距
        rightHeaderLabels.style.paddingLeft = '8px'; // 添加左侧padding,向左移动标签
        rightHeaderLabels.style.paddingRight = '12px'; // 增加右侧间距

        const showLabel = document.createElement('div');
        showLabel.textContent = '显示';
        showLabel.style.width = '36px'; // 稍微减小宽度
        showLabel.style.textAlign = 'center';
        showLabel.style.fontSize = '12px';
        showLabel.style.marginRight = '4px'; // 添加右边距

        const editLabel = document.createElement('div');
        editLabel.textContent = '修改';
        editLabel.style.width = '36px'; // 稍微减小宽度
        editLabel.style.textAlign = 'center';
        editLabel.style.fontSize = '12px';
        editLabel.style.marginRight = '4px'; // 添加右边距

        const deleteLabel = document.createElement('div');
        deleteLabel.textContent = '删除';
        deleteLabel.style.width = '36px'; // 稍微减小宽度
        deleteLabel.style.textAlign = 'center';
        deleteLabel.style.fontSize = '12px';

        rightHeaderLabels.appendChild(showLabel);
        rightHeaderLabels.appendChild(editLabel);
        rightHeaderLabels.appendChild(deleteLabel);

        folderHeaderBar.appendChild(leftHeaderLabel);
        folderHeaderBar.appendChild(rightHeaderLabels);

        folderListContainer = document.createElement('div');
        folderListContainer.style.flex = '1';
        folderListContainer.style.overflowY = 'auto';
        folderListContainer.style.padding = '8px';
        folderListContainer.style.direction = 'rtl';
        folderListContainer.style.border = '1px solid var(--border-color, #e5e7eb)';
        folderListContainer.style.borderTop = 'none';
        folderListContainer.style.borderRadius = '0 0 4px 4px';

        const folderAddContainer = document.createElement('div');
        folderAddContainer.style.padding = '8px';
        folderAddContainer.style.display = 'flex';
        folderAddContainer.style.justifyContent = 'center';

        const addNewFolderBtn = document.createElement('button');
        Object.assign(addNewFolderBtn.style, styles.button, {
            backgroundColor: 'var(--add-color, #fd7e14)',
            color: 'white',
            borderRadius: '4px'
        });
        addNewFolderBtn.textContent = '+ 新建文件夹';
        addNewFolderBtn.addEventListener('click', () => {
            showFolderEditDialog('', {}, (newFolderName) => {
                selectedFolderName = newFolderName;
                renderFolderList();
                renderButtonList();
                console.log(`🆕 新建文件夹 "${newFolderName}" 已添加。`);
            });
        });
        folderAddContainer.appendChild(addNewFolderBtn);

        folderPanel.appendChild(folderHeaderBar);
        folderPanel.appendChild(folderListContainer);
        folderPanel.appendChild(folderAddContainer);

        buttonListContainer = document.createElement('div');
        buttonListContainer.style.flex = '1';
        buttonListContainer.style.overflowY = 'auto';
        buttonListContainer.style.display = 'flex';
        buttonListContainer.style.flexDirection = 'column';
        buttonListContainer.style.padding = '8px 8px 4px 8px';
        buttonListContainer.style.minWidth = '520px'; // 加宽右侧区域以提供更多内容空间

        const updateFolderPanelVisibility = () => {
            const container = settingsDialogMainContainer || mainContainer;
            if (isSettingsFolderPanelCollapsed) {
                if (container) {
                    const currentHeight = container.offsetHeight;
                    if (currentHeight > 0) {
                        container.style.minHeight = `${currentHeight}px`;
                    } else {
                        window.requestAnimationFrame(() => {
                            if (!isSettingsFolderPanelCollapsed) return;
                            const activeContainer = settingsDialogMainContainer || container;
                            if (!activeContainer) return;
                            const measuredHeight = activeContainer.offsetHeight;
                            if (measuredHeight > 0) {
                                activeContainer.style.minHeight = `${measuredHeight}px`;
                            }
                        });
                    }
                }
                folderPanel.style.display = 'none';
                collapseToggleBtn.title = '展开左侧设置区域';
                collapseToggleBtn.setAttribute('aria-label', '展开左侧设置区域');
            } else {
                folderPanel.style.display = 'flex';
                collapseToggleBtn.title = '折叠左侧设置区域';
                collapseToggleBtn.setAttribute('aria-label', '折叠左侧设置区域');
                if (container) {
                    container.style.minHeight = '';
                }
            }
        };

        collapseToggleBtn.addEventListener('click', () => {
            isSettingsFolderPanelCollapsed = !isSettingsFolderPanelCollapsed;
            updateFolderPanelVisibility();
        });

        updateFolderPanelVisibility();

        renderFolderList();
        renderButtonList();

        mainContainer.appendChild(folderPanel);
        mainContainer.appendChild(buttonListContainer);

        const footer = document.createElement('div');
        footer.style.display = 'none';
        dialog.appendChild(header);
        dialog.appendChild(mainContainer);
        dialog.appendChild(footer);

        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentSettingsOverlay = overlay;

        // 动画效果
        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);
    };

let currentAutomationOverlay = null;
/**
 *
 * 弹窗:自动化设置,显示所有 domainAutoSubmitSettings,并可删除、点击添加
 */
function showAutomationSettingsDialog() {
    // 若已存在则先关闭
    if (currentAutomationOverlay) {
        closeExistingOverlay(currentAutomationOverlay);
    }

    // 使用 createUnifiedDialog 统一创建 overlay + dialog
    const { overlay, dialog } = createUnifiedDialog({
        title: '⚡ 自动化设置',
        width: '750px',  // 保留你想要的宽度
        onClose: () => {
            currentAutomationOverlay = null;
        },
        closeOnOverlayClick: false
    });
    currentAutomationOverlay = overlay;

    // 这里是新写法:在 dialog 里 appendChild 内部内容
    // 注意,createUnifiedDialog 已经注入了 overlay 与动画

    // 1) 构建内容区, 并插入到 dialog
    const infoDiv = document.createElement('div');
    infoDiv.style.textAlign = 'right';
    infoDiv.style.marginBottom = '10px';

    // 原先的 "关闭并保存" 按钮
    const closeAutomationBtn = document.createElement('button');
    closeAutomationBtn.id = 'closeAutomationBtn';
    closeAutomationBtn.textContent = '💾 关闭并保存';
    closeAutomationBtn.style.cssText = `
        background-color: var(--success-color, #22c55e);
        color: #fff;
        border: none;
        border-radius: 4px;
        padding: 6px 12px;
        cursor: pointer;
        position: absolute; /* 若想固定在右上角,可再自行定位 */
        top: 20px;
        right: 20px;
    `;
    closeAutomationBtn.addEventListener('click', () => {
        localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
        closeExistingOverlay(overlay);
        currentAutomationOverlay = null;
    });
    infoDiv.appendChild(closeAutomationBtn);
    dialog.appendChild(infoDiv);

    // 2) 列表容器 + 渲染 domainAutoSubmitSettings
    const listContainer = document.createElement('div');
    listContainer.style.cssText = `
        border: 1px solid var(--border-color, #e5e7eb);
        border-radius: 8px;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        background-color: var(--dialog-bg, #ffffff);
        max-height: 320px;
    `;

    const listHeader = document.createElement('div');
    listHeader.style.cssText = `
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 6px 12px;
        background-color: var(--button-bg, #f3f4f6);
        border-bottom: 1px solid var(--border-color, #e5e7eb);
        font-size: 12px;
        font-weight: 500;
        color: var(--text-color, #333333);
        flex-shrink: 0;
    `;

    const headerColumns = [
        { label: '图标', flex: '0 0 32px', justify: 'center' },
        { label: '网站|网址', flex: '1 1 0%', justify: 'flex-start', paddingLeft: '8px' },
        { label: '提交方式', flex: '0 0 120px', justify: 'center' },
        { label: '修改', flex: '0 0 40px', justify: 'center' },
        { label: '删除', flex: '0 0 40px', justify: 'center' }
    ];

    headerColumns.forEach(({ label, flex, justify, paddingLeft }) => {
        const column = document.createElement('div');
        column.textContent = label;
        column.style.display = 'flex';
        column.style.alignItems = 'center';
        column.style.justifyContent = justify;
        column.style.flex = flex;
        column.style.fontSize = '12px';
        column.style.fontWeight = '600';
        if (paddingLeft) {
            column.style.paddingLeft = paddingLeft;
        }
        listHeader.appendChild(column);
    });

    const listBody = document.createElement('div');
    listBody.style.cssText = `
        display: flex;
        flex-direction: column;
        gap: 8px;
        padding: 8px;
        overflow-y: auto;
        max-height: 260px;
    `;
    listBody.classList.add('hide-scrollbar');

    listContainer.appendChild(listHeader);
    listContainer.appendChild(listBody);
    dialog.appendChild(listContainer);

    const keyboardMethodPattern = /(enter|shift|caps|ctrl|control|cmd|meta|option|alt|space|tab|esc|escape|delete|backspace|home|end|page ?up|page ?down|arrow|up|down|left|right)/i;

    const createKeyCapElement = (label) => {
        const keyEl = document.createElement('span');
        keyEl.textContent = label;
        keyEl.style.cssText = `
            display: inline-flex;
            align-items: center;
            justify-content: center;
            min-width: 28px;
            padding: 3px 8px;
            border-radius: 6px;
            border: 1px solid rgba(255, 255, 255, 0.2);
            background: linear-gradient(180deg, rgba(17,17,17,0.95), rgba(45,45,45,0.95));
            box-shadow: inset 0 -1px 0 rgba(255,255,255,0.12), 0 2px 4px rgba(0,0,0,0.45);
            font-size: 12px;
            font-weight: 600;
            color: #ffffff;
            font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
            line-height: 1.2;
            white-space: nowrap;
        `;
        return keyEl;
    };

    const createMethodDisplay = (rawMethod) => {
        const methodValue = (rawMethod || '').trim();
        const container = document.createElement('div');
        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.justifyContent = 'center';
        container.style.gap = '6px';
        container.style.flexWrap = 'wrap';
        container.style.maxWidth = '100%';
        container.style.fontSize = '12px';
        container.style.fontWeight = '600';

        if (!methodValue) {
            const placeholder = document.createElement('span');
            placeholder.textContent = '-';
            placeholder.style.color = 'var(--muted-text-color, #6b7280)';
            placeholder.style.fontWeight = '500';
            container.appendChild(placeholder);
            return container;
        }

        if (methodValue === '模拟点击提交按钮') {
            const clickBadge = document.createElement('span');
            clickBadge.textContent = '模拟点击';
            clickBadge.style.cssText = `
                padding: 4px 12px;
                border-radius: 20px;
                background: linear-gradient(180deg, rgba(253,224,71,0.85), rgba(251,191,36,0.9));
                border: 1px solid rgba(217,119,6,0.4);
                box-shadow: inset 0 -1px 0 rgba(217,119,6,0.35), 0 1px 2px rgba(217,119,6,0.25);
                color: rgba(120,53,15,0.95);
                font-weight: 700;
                font-size: 12px;
                letter-spacing: 0.02em;
                white-space: nowrap;
            `;
            container.appendChild(clickBadge);
            return container;
        }

        const shouldUseKeyStyle = keyboardMethodPattern.test(methodValue) || methodValue.includes('+') || methodValue.includes('/');

        if (!shouldUseKeyStyle) {
            const pill = document.createElement('span');
            pill.textContent = methodValue;
            pill.style.cssText = `
                padding: 4px 10px;
                background-color: rgba(59,130,246,0.12);
                color: var(--primary-color, #3B82F6);
                border-radius: 999px;
                white-space: nowrap;
            `;
            container.appendChild(pill);
            return container;
        }

        const combos = methodValue.split('/').map(segment => segment.trim()).filter(Boolean);
        combos.forEach((combo, comboIdx) => {
            if (comboIdx > 0) {
                const divider = document.createElement('span');
                divider.textContent = '/';
                divider.style.color = 'var(--muted-text-color, #6b7280)';
                divider.style.fontSize = '11px';
                divider.style.fontWeight = '600';
                container.appendChild(divider);
            }

            const comboWrapper = document.createElement('div');
            comboWrapper.style.display = 'flex';
            comboWrapper.style.alignItems = 'center';
            comboWrapper.style.justifyContent = 'center';
            comboWrapper.style.gap = '4px';

            const keys = combo.split('+').map(part => part.trim()).filter(Boolean);
            if (!keys.length) {
                keys.push(combo);
            }

            keys.forEach((keyLabel, keyIdx) => {
                if (keyIdx > 0) {
                    const plusSign = document.createElement('span');
                    plusSign.textContent = '+';
                    plusSign.style.color = 'var(--muted-text-color, #6b7280)';
                    plusSign.style.fontSize = '11px';
                    plusSign.style.fontWeight = '600';
                    comboWrapper.appendChild(plusSign);
                }
                comboWrapper.appendChild(createKeyCapElement(keyLabel));
            });

            container.appendChild(comboWrapper);
        });

        return container;
    };

    const showAutomationRuleDeleteConfirmDialog = (rule, onConfirm) => {
        if (!rule) {
            if (typeof onConfirm === 'function') {
                onConfirm();
            }
            return;
        }
        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }

        const overlay = document.createElement('div');
        overlay.classList.add('confirm-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 13000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('confirm-dialog', 'cttf-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 420px;
            max-width: 90vw;
        `;

        const ruleName = rule.name || rule.domain || '未命名规则';
        const ruleDomain = rule.domain || '(未指定网址)';
        const faviconUrl = rule.favicon || generateDomainFavicon(rule.domain);

        setTrustedHTML(dialog, `
            <h3 style="margin: 0 0 20px 0; font-size: 18px; font-weight: 600; color: var(--danger-color, #ef4444);">
                🗑️ 确认删除自动化规则 "${ruleName}"?
            </h3>
            <p style="margin: 8px 0; color: var(--text-color, #333333);">❗️ 注意:此操作无法撤销!</p>
            <div style="margin: 16px 0; border: 1px solid var(--border-color, #e5e7eb); padding: 12px; border-radius:6px; background-color: var(--button-bg, #f3f4f6);">
                <div style="display:flex; align-items:center; gap:12px; margin-bottom:12px;">
                    <div style="
                        width:32px;
                        height:32px;
                        border-radius:8px;
                        display:flex;
                        align-items:center;
                        justify-content:center;
                        overflow:hidden;
                        flex-shrink:0;
                    ">
                        <img src="${faviconUrl}" alt="${ruleName}" style="width:24px; height:24px; object-fit:contain;" referrerpolicy="no-referrer">
                    </div>
                    <div style="display:flex; flex-direction:column; gap:4px;">
                        <span style="font-size:14px; font-weight:600; color: var(--text-color, #333333);">${ruleName}</span>
                        <span style="font-size:12px; color: var(--muted-text-color, #6b7280);">${ruleDomain}</span>
                    </div>
                </div>
                <p style="margin:4px 0; position:relative; padding-left:12px; color: var(--text-color, #333333); display:flex; align-items:center; gap:8px; flex-wrap:wrap;">
                    <span style="position:absolute; left:0; top:50%; transform:translateY(-50%); width:4px; height:4px; background-color: var(--text-color, #333333); border-radius:50%;"></span>
                    自动提交方式:<span class="cttf-automation-method-container"></span>
                </p>
            </div>
            <div style="
                display:flex;
                justify-content: flex-end;
                gap: 12px;
                border-top:1px solid var(--border-color, #e5e7eb);
                padding-top:16px;
            ">
                <button id="cancelAutomationRuleDelete" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border-radius:4px;
                ">取消</button>
                <button id="confirmAutomationRuleDelete" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--danger-color, #ef4444);
                    color: white;
                    border-radius:4px;
                ">删除</button>
            </div>
        `);

        const methodPlaceholder = dialog.querySelector('.cttf-automation-method-container');
        if (methodPlaceholder) {
            const methodDisplay = createMethodDisplay(rule.method);
            methodDisplay.style.justifyContent = 'flex-start';
            methodPlaceholder.replaceWith(methodDisplay);
        }

        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        const cancelBtn = dialog.querySelector('#cancelAutomationRuleDelete');
        if (cancelBtn) {
            cancelBtn.addEventListener('click', () => {
                closeExistingOverlay(overlay);
                currentConfirmOverlay = null;
            });
        }

        const confirmBtn = dialog.querySelector('#confirmAutomationRuleDelete');
        if (confirmBtn) {
            confirmBtn.addEventListener('click', () => {
                if (typeof onConfirm === 'function') {
                    onConfirm();
                }
                closeExistingOverlay(overlay);
                currentConfirmOverlay = null;
            });
        }
    };

    function renderDomainRules() {
        setTrustedHTML(listBody, '');
        const rules = buttonConfig.domainAutoSubmitSettings;
        let metadataPatched = false;

        if (!rules.length) {
            const emptyState = document.createElement('div');
            emptyState.textContent = '暂无自动化规则,点击下方“+ 新建”开始配置。';
            emptyState.style.cssText = `
                padding: 18px;
                border-radius: 6px;
                border: 1px dashed var(--border-color, #e5e7eb);
                background-color: var(--button-bg, #f3f4f6);
                color: var(--muted-text-color, #6b7280);
                font-size: 13px;
                text-align: center;
            `;
            listBody.appendChild(emptyState);
            return;
        }

        rules.forEach((rule, idx) => {
            const item = document.createElement('div');
            item.style.cssText = `
                display: flex;
                justify-content: flex-start;
                align-items: center;
                gap: 8px;
                padding: 8px 10px;
                border: 1px solid var(--border-color, #e5e7eb);
                border-radius: 6px;
                background-color: var(--button-bg, #f3f4f6);
                transition: border-color 0.2s ease, box-shadow 0.2s ease;
            `;
            item.addEventListener('mouseenter', () => {
                item.style.borderColor = 'var(--primary-color, #3B82F6)';
                item.style.boxShadow = '0 3px 8px rgba(0,0,0,0.1)';
            });
            item.addEventListener('mouseleave', () => {
                item.style.borderColor = 'var(--border-color, #e5e7eb)';
                item.style.boxShadow = 'none';
            });

            const faviconUrl = rule.favicon || generateDomainFavicon(rule.domain);
            if (!rule.favicon && rule.domain) {
                rule.favicon = faviconUrl;
                metadataPatched = true;
            }
            const faviconBadge = createFaviconElement(faviconUrl, rule.name || rule.domain, '🌐', { withBackground: false, size: 26 });
            faviconBadge.title = rule.domain || '';

            const iconColumn = document.createElement('div');
            iconColumn.style.display = 'flex';
            iconColumn.style.alignItems = 'center';
            iconColumn.style.justifyContent = 'center';
            iconColumn.style.flex = '0 0 30px';
            iconColumn.appendChild(faviconBadge);

            const infoColumn = document.createElement('div');
            infoColumn.style.display = 'flex';
            infoColumn.style.flexDirection = 'column';
            infoColumn.style.gap = '4px';
            infoColumn.style.minWidth = '0';
            infoColumn.style.flex = '1 1 0%';

            const nameEl = document.createElement('span');
            nameEl.textContent = rule.name || rule.domain || '未命名规则';
            nameEl.style.fontWeight = '600';
            nameEl.style.fontSize = '14px';
            nameEl.style.color = 'var(--text-color, #1f2937)';

            const domainEl = document.createElement('span');
            domainEl.textContent = rule.domain || '';
            domainEl.style.fontSize = '12px';
            domainEl.style.color = 'var(--muted-text-color, #6b7280)';
            domainEl.style.whiteSpace = 'nowrap';
            domainEl.style.overflow = 'hidden';
            domainEl.style.textOverflow = 'ellipsis';
            domainEl.style.maxWidth = '260px';
            domainEl.title = rule.domain || '';

            infoColumn.appendChild(nameEl);
            infoColumn.appendChild(domainEl);

            const methodDisplay = createMethodDisplay(rule.method || '-');

            const editBtn = document.createElement('button');
            editBtn.textContent = '✏️';
            editBtn.style.cssText = `
                background: none;
                border: none;
                cursor: pointer;
                color: var(--primary-color, #3B82F6);
                font-size: 14px;
                width: 32px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 4px;
                transition: background-color 0.2s ease;
            `;
            editBtn.addEventListener('mouseenter', () => {
                editBtn.style.backgroundColor = 'rgba(59,130,246,0.12)';
            });
            editBtn.addEventListener('mouseleave', () => {
                editBtn.style.backgroundColor = 'transparent';
            });
            editBtn.addEventListener('click', () => {
                const ruleToEdit = buttonConfig.domainAutoSubmitSettings[idx];
                showDomainRuleEditorDialog(ruleToEdit, (newData) => {
                    buttonConfig.domainAutoSubmitSettings[idx] = newData;
                    renderDomainRules();
                });
            });

            const deleteBtn = document.createElement('button');
            deleteBtn.textContent = '🗑️';
            deleteBtn.style.cssText = `
                background: none;
                border: none;
                cursor: pointer;
                color: var(--danger-color, #ef4444);
                font-size: 14px;
                width: 32px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 4px;
                transition: background-color 0.2s ease;
            `;
            deleteBtn.addEventListener('mouseenter', () => {
                deleteBtn.style.backgroundColor = 'rgba(239,68,68,0.12)';
            });
            deleteBtn.addEventListener('mouseleave', () => {
                deleteBtn.style.backgroundColor = 'transparent';
            });
            deleteBtn.addEventListener('click', () => {
                const ruleToDelete = buttonConfig.domainAutoSubmitSettings[idx];
                showAutomationRuleDeleteConfirmDialog(ruleToDelete, () => {
                    buttonConfig.domainAutoSubmitSettings.splice(idx, 1);
                    localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
                    renderDomainRules();
                });
            });

            const methodColumn = document.createElement('div');
            methodColumn.style.display = 'flex';
            methodColumn.style.alignItems = 'center';
            methodColumn.style.justifyContent = 'center';
            methodColumn.style.flex = '0 0 120px';
            methodColumn.appendChild(methodDisplay);

            const editColumn = document.createElement('div');
            editColumn.style.display = 'flex';
            editColumn.style.alignItems = 'center';
            editColumn.style.justifyContent = 'center';
            editColumn.style.flex = '0 0 40px';
            editColumn.appendChild(editBtn);

            const deleteColumn = document.createElement('div');
            deleteColumn.style.display = 'flex';
            deleteColumn.style.alignItems = 'center';
            deleteColumn.style.justifyContent = 'center';
            deleteColumn.style.flex = '0 0 40px';
            deleteColumn.appendChild(deleteBtn);

            item.appendChild(iconColumn);
            item.appendChild(infoColumn);
            item.appendChild(methodColumn);
            item.appendChild(editColumn);
            item.appendChild(deleteColumn);
            listBody.appendChild(item);
        });
        if (metadataPatched) {
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
        }
    }
    renderDomainRules();

    // 3) 新建按钮
    const addDiv = document.createElement('div');
    addDiv.style.marginTop = '12px';
    addDiv.style.textAlign = 'left';

    const addBtn = document.createElement('button');
    addBtn.textContent = '+ 新建';
    addBtn.style.cssText = `
        background-color: var(--add-color, #fd7e14);
        color: #fff;
        border: none;
        border-radius: 4px;
        padding: 6px 12px;
        cursor: pointer;
    `;
    addBtn.addEventListener('click', () => {
        showDomainRuleEditorDialog({}, (newData) => {
            buttonConfig.domainAutoSubmitSettings.push(newData);
            renderDomainRules();
        });
    });
    addDiv.appendChild(addBtn);
    dialog.appendChild(addDiv);

}


function showStyleSettingsDialog() {
    // 若已存在则关闭
    if (currentStyleOverlay) {
        closeExistingOverlay(currentStyleOverlay);
    }

    // 使用统一弹窗
    const { overlay, dialog } = createUnifiedDialog({
        title: '🎨 样式管理',
        width: '750px',
        onClose: () => {
            currentStyleOverlay = null;
        },
        closeOnOverlayClick: false
    });
    currentStyleOverlay = overlay;

    // 说明文字
    const desc = document.createElement('p');
    desc.textContent = '您可根据不同网址,自定义按钮栏高度和注入CSS样式。';
    dialog.appendChild(desc);

    // 列表容器
    const styleListContainer = document.createElement('div');
    styleListContainer.style.cssText = `
        border: 1px solid var(--border-color, #e5e7eb);
        border-radius: 8px;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        background-color: var(--dialog-bg, #ffffff);
        max-height: 320px;
        margin-bottom: 12px;
    `;

    const styleHeader = document.createElement('div');
    styleHeader.style.cssText = `
        display: flex;
        justify-content: flex-start;
        align-items: center;
        gap: 8px;
        padding: 6px 12px;
        background-color: var(--button-bg, #f3f4f6);
        border-bottom: 1px solid var(--border-color, #e5e7eb);
        font-size: 12px;
        font-weight: 500;
        color: var(--text-color, #333333);
        flex-shrink: 0;
    `;

    const headerColumns = [
        { label: '图标', flex: '0 0 32px', textAlign: 'center' },
        { label: '网站|网址', flex: '0.7 1 0%', textAlign: 'left', paddingLeft: '4px' },
        { label: '自定义css', flex: '3 1 0%', textAlign: 'center' },
        { label: '高度|底部', flex: '0 0 110px', textAlign: 'center' },
        { label: '修改', flex: '0 0 40px', textAlign: 'center' },
        { label: '删除', flex: '0 0 40px', textAlign: 'center' }
    ];
    headerColumns.forEach((col) => {
        const column = document.createElement('div');
        column.textContent = col.label;
        column.style.display = 'flex';
        column.style.alignItems = 'center';
        column.style.justifyContent = col.textAlign === 'right' ? 'flex-end'
            : col.textAlign === 'center' ? 'center'
                : 'flex-start';
        column.style.textAlign = col.textAlign;
        column.style.flex = col.flex;
        column.style.fontSize = '12px';
        column.style.fontWeight = '600';
        if (col.paddingLeft) {
            column.style.paddingLeft = col.paddingLeft;
        }
        styleHeader.appendChild(column);
    });

    const styleListBody = document.createElement('div');
    styleListBody.style.cssText = `
        display: flex;
        flex-direction: column;
        gap: 8px;
        padding: 8px;
        overflow-y: auto;
        max-height: 260px;
    `;
    styleListBody.classList.add('hide-scrollbar');

    styleListContainer.appendChild(styleHeader);
    styleListContainer.appendChild(styleListBody);
    dialog.appendChild(styleListContainer);

    const showStyleRuleDeleteConfirmDialog = (styleItem, onConfirm) => {
        if (!styleItem) {
            if (typeof onConfirm === 'function') {
                onConfirm();
            }
            return;
        }

        if (currentConfirmOverlay) {
            closeExistingOverlay(currentConfirmOverlay);
        }

        const overlay = document.createElement('div');
        overlay.classList.add('confirm-overlay');
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: var(--overlay-bg, rgba(0, 0, 0, 0.5));
            backdrop-filter: blur(2px);
            z-index: 13000;
            display: flex;
            justify-content: center;
            align-items: center;
            opacity: 0;
            transition: opacity 0.3s ease;
        `;

        const dialog = document.createElement('div');
        dialog.classList.add('confirm-dialog', 'cttf-dialog');
        dialog.style.cssText = `
            background-color: var(--dialog-bg, #ffffff);
            color: var(--text-color, #333333);
            border-radius: 4px;
            padding: 24px;
            box-shadow: 0 8px 24px var(--shadow-color, rgba(0,0,0,0.1));
            border: 1px solid var(--border-color, #e5e7eb);
            transition: transform 0.3s ease, opacity 0.3s ease;
            width: 420px;
            max-width: 90vw;
        `;

        const styleName = styleItem.name || styleItem.domain || '未命名样式';
        const styleDomain = styleItem.domain || '(未指定网址)';
        const styleHeight = styleItem.height ? `${styleItem.height}px` : '默认高度';
        const rawStyleBottomSpacing = (typeof styleItem.bottomSpacing === 'number') ? styleItem.bottomSpacing : buttonConfig.buttonBarBottomSpacing;
        const clampedStyleBottomSpacing = Math.max(-200, Math.min(200, Number(rawStyleBottomSpacing) || 0));
        const styleBottomSpacing = `${clampedStyleBottomSpacing}px`;
        const faviconUrl = styleItem.favicon || generateDomainFavicon(styleItem.domain);
        const cssRaw = (styleItem.cssCode || '').trim();
        const cssContent = cssRaw || '(未配置自定义 CSS)';
        const cssLineCount = cssContent.split('\n').length;
        const cssTextareaHeight = Math.min(Math.max(cssLineCount, 6), 24) * 18;
        const escapeHtml = (str = '') => String(str)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');

        setTrustedHTML(dialog, `
            <div style="display:flex; flex-direction:column; gap:8px; margin-bottom:4px;">
                <h3 style="margin:0; font-size:18px; font-weight:700; color: var(--danger-color, #ef4444); display:flex; align-items:center; gap:8px;">
                    <span aria-hidden="true">🗑️</span>
                    <span>确认删除样式 "${escapeHtml(styleName)}"?</span>
                </h3>
                <p style="margin:0; color: var(--text-color, #333333); font-size:13px;">❗️ 注意:此操作无法撤销!</p>
            </div>
            <div style="margin: 0 0 22px 0; border: 1px solid var(--border-color, #e5e7eb); padding: 18px; border-radius:8px; background-color: var(--button-bg, #f3f4f6); display:flex; flex-direction:column; gap:16px;">
                <div style="display:flex; align-items:center; gap:12px; margin-bottom:16px;">
                    <div style="
                        width:32px;
                        height:32px;
                        border-radius:8px;
                        display:flex;
                        align-items:center;
                        justify-content:center;
                        overflow:hidden;
                        flex-shrink:0;
                    ">
                        <img src="${faviconUrl}" alt="${escapeHtml(styleName)}" style="width:24px; height:24px; object-fit:contain;" referrerpolicy="no-referrer">
                    </div>
                    <div style="display:flex; flex-direction:column; gap:4px; min-width:0;">
                        <span style="font-size:14px; font-weight:600; color: var(--text-color, #333333);">${escapeHtml(styleName)}</span>
                        <span style="font-size:12px; color: var(--muted-text-color, #6b7280); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:220px;" title="${escapeHtml(styleDomain)}">${escapeHtml(styleDomain)}</span>
                    </div>
                </div>
                <div style="display:flex; flex-wrap:wrap; gap:12px; margin-bottom:16px;">
                    <div style="display:flex; align-items:center; gap:8px;">
                        <span style="font-size:12px; font-weight:600; color: var(--muted-text-color, #6b7280); white-space:nowrap;">按钮栏高度</span>
                        <span style="
                            padding:6px 12px;
                            background-color: rgba(16,185,129,0.16);
                            color: var(--success-color, #22c55e);
                            border-radius:999px;
                            font-size:12px;
                            font-weight:600;
                            white-space:nowrap;
                        ">${escapeHtml(styleHeight)}</span>
                    </div>
                    <div style="display:flex; align-items:center; gap:8px;">
                        <span style="font-size:12px; font-weight:600; color: var(--muted-text-color, #6b7280); white-space:nowrap;">距页面底部</span>
                        <span style="
                            padding:6px 12px;
                            background-color: rgba(59,130,246,0.16);
                            color: var(--primary-color, #3B82F6);
                            border-radius:999px;
                            font-size:12px;
                            font-weight:600;
                            white-space:nowrap;
                        " title="按钮栏距页面底部的间距">${escapeHtml(styleBottomSpacing)}</span>
                    </div>
                </div>
                <div style="display:flex; flex-direction:column; gap:8px;">
                    <label style="font-size:13px; font-weight:600; color: var(--text-color, #333333); display:flex; align-items:center; gap:6px;">
                        <span aria-hidden="true">🧶</span>
                        <span>自定义 CSS</span>
                    </label>
                    <textarea readonly style="
                        width:100%;
                        min-height:${cssTextareaHeight}px;
                        max-height:360px;
                        background-color: rgba(255,255,255,0.92);
                        color: var(--text-color, #1f2937);
                        border:1px solid var(--border-color, #d1d5db);
                        border-radius:6px;
                        padding:12px;
                        font-size:13px;
                        line-height:1.6;
                        resize:vertical;
                        font-family: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
                        box-shadow: inset 0 1px 2px rgba(15,23,42,0.08);
                        white-space:pre-wrap;
                        word-break:break-word;
                        overflow-wrap:break-word;
                    ">${escapeHtml(cssContent)}</textarea>
                </div>
            </div>
            <div style="
                display:flex;
                justify-content: flex-end;
                gap: 12px;
                border-top:1px solid var(--border-color, #e5e7eb);
                padding-top:16px;
                margin-top:4px;
            ">
                <button id="cancelStyleRuleDelete" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--cancel-color, #6B7280);
                    color: white;
                    border-radius:4px;
                ">取消</button>
                <button id="confirmStyleRuleDelete" style="
                    ${Object.entries(styles.button).map(([key, value]) => `${key}:${value}`).join(';')};
                    background-color: var(--danger-color, #ef4444);
                    color: white;
                    border-radius:4px;
                ">删除</button>
            </div>
        `);

        overlay.appendChild(dialog);
        overlay.style.pointerEvents = 'auto';
        appendToOverlayLayer(overlay);
        currentConfirmOverlay = overlay;

        setTimeout(() => {
            overlay.style.opacity = '1';
            dialog.style.transform = 'scale(1)';
        }, 10);

        dialog.querySelector('#cancelStyleRuleDelete')?.addEventListener('click', () => {
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
        });

        dialog.querySelector('#confirmStyleRuleDelete')?.addEventListener('click', () => {
            if (typeof onConfirm === 'function') {
                onConfirm();
            }
            closeExistingOverlay(overlay);
            currentConfirmOverlay = null;
        });
    };

    function renderDomainStyles() {
        setTrustedHTML(styleListBody, '');
        const styles = buttonConfig.domainStyleSettings;
        let metadataPatched = false;

        if (!styles.length) {
            const emptyState = document.createElement('div');
            emptyState.textContent = '尚未配置任何样式,点击下方“+ 新建”添加。';
            emptyState.style.cssText = `
                padding: 18px;
                border-radius: 6px;
                border: 1px dashed var(--border-color, #e5e7eb);
                background-color: var(--button-bg, #f3f4f6);
                color: var(--muted-text-color, #6b7280);
                font-size: 13px;
                text-align: center;
            `;
            styleListBody.appendChild(emptyState);
            return;
        }

        styles.forEach((item, idx) => {
            const row = document.createElement('div');
            row.style.cssText = `
                display: flex;
                justify-content: flex-start;
                align-items: center;
                gap: 8px;
                padding: 8px 10px;
                border: 1px solid var(--border-color, #e5e7eb);
                border-radius: 6px;
                background-color: var(--button-bg, #f3f4f6);
                transition: border-color 0.2s ease, box-shadow 0.2s ease;
            `;
            row.addEventListener('mouseenter', () => {
                row.style.borderColor = 'var(--info-color, #6366F1)';
                row.style.boxShadow = '0 3px 8px rgba(0,0,0,0.1)';
            });
            row.addEventListener('mouseleave', () => {
                row.style.borderColor = 'var(--border-color, #e5e7eb)';
                row.style.boxShadow = 'none';
            });

            const faviconUrl = item.favicon || generateDomainFavicon(item.domain);
            if (!item.favicon && item.domain) {
                item.favicon = faviconUrl;
                metadataPatched = true;
            }
            const faviconBadge = createFaviconElement(faviconUrl, item.name || item.domain, '🎨', { withBackground: false, size: 26 });
            faviconBadge.title = item.domain || '自定义样式';

            const iconColumn = document.createElement('div');
            iconColumn.style.display = 'flex';
            iconColumn.style.alignItems = 'center';
            iconColumn.style.justifyContent = 'center';
            iconColumn.style.flex = '0 0 30px';
            iconColumn.appendChild(faviconBadge);

            const siteColumn = document.createElement('div');
            siteColumn.style.display = 'flex';
            siteColumn.style.flexDirection = 'column';
            siteColumn.style.gap = '4px';
            siteColumn.style.minWidth = '100px';
            siteColumn.style.flex = '0.7 1 0%';

            const nameEl = document.createElement('span');
            nameEl.textContent = item.name || '未命名样式';
            nameEl.style.fontWeight = '600';
            nameEl.style.fontSize = '14px';
            nameEl.style.color = 'var(--text-color, #1f2937)';

            const domainEl = document.createElement('span');
            domainEl.textContent = item.domain || '未设置域名';
            domainEl.style.fontSize = '12px';
            domainEl.style.color = 'var(--muted-text-color, #6b7280)';
            domainEl.style.whiteSpace = 'nowrap';
            domainEl.style.overflow = 'hidden';
            domainEl.style.textOverflow = 'ellipsis';
            domainEl.style.maxWidth = '100%';

            const cssSnippet = (item.cssCode || '').replace(/\s+/g, ' ').trim();
            const snippetText = cssSnippet
                ? (cssSnippet.length > 80 ? `${cssSnippet.slice(0, 80)}…` : cssSnippet)
                : '无自定义CSS';

            const cssPreview = document.createElement('code');
            cssPreview.textContent = snippetText;
            cssPreview.style.cssText = `
                display: block;
                width: 100%;
                font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
                font-size: 12px;
                color: var(--muted-text-color, #6b7280);
                background-color: rgba(17,24,39,0.04);
                border-radius: 4px;
                padding: 4px 6px;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                max-width: 100%;
            `;
            cssPreview.title = item.cssCode || '无自定义CSS';

            siteColumn.appendChild(nameEl);
            siteColumn.appendChild(domainEl);

            const cssColumn = document.createElement('div');
            cssColumn.style.cssText = `
                flex: 3 1 0%;
                min-width: 0;
                max-width: 100%;
                display: flex;
                align-items: center;
                padding-right: 12px;
            `;
            cssColumn.appendChild(cssPreview);

        const heightColumn = document.createElement('div');
        heightColumn.style.display = 'flex';
        heightColumn.style.alignItems = 'center';
        heightColumn.style.justifyContent = 'center';
        heightColumn.style.flex = '0 0 110px';
        heightColumn.style.gap = '6px';
        heightColumn.style.flexWrap = 'wrap';

        const heightBadge = document.createElement('span');
        heightBadge.textContent = item.height ? `${item.height}px` : '默认高度';
        heightBadge.style.cssText = `
            padding: 4px 10px;
            background-color: rgba(16,185,129,0.12);
            color: var(--success-color, #22c55e);
            border-radius: 999px;
            font-size: 12px;
            font-weight: 600;
            white-space: nowrap;
        `;

        const bottomSpacingValue = (typeof item.bottomSpacing === 'number') ? item.bottomSpacing : buttonConfig.buttonBarBottomSpacing;
        const clampedBottomSpacingValue = Math.max(-200, Math.min(200, Number(bottomSpacingValue) || 0));
        const bottomBadge = document.createElement('span');
        bottomBadge.textContent = `${clampedBottomSpacingValue}px`;
        bottomBadge.title = '按钮栏距页面底部间距';
        bottomBadge.style.cssText = `
            padding: 4px 10px;
            background-color: rgba(59,130,246,0.12);
            color: var(--primary-color, #3B82F6);
            border-radius: 999px;
            font-size: 12px;
            font-weight: 600;
            white-space: nowrap;
        `;

            const editBtn = document.createElement('button');
            editBtn.textContent = '✏️';
            editBtn.style.cssText = `
                background: none;
                border: none;
                cursor: pointer;
                color: var(--primary-color, #3B82F6);
                font-size: 14px;
                width: 32px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 4px;
                transition: background-color 0.2s ease;
            `;
            editBtn.addEventListener('mouseenter', () => {
                editBtn.style.backgroundColor = 'rgba(59,130,246,0.12)';
            });
            editBtn.addEventListener('mouseleave', () => {
                editBtn.style.backgroundColor = 'transparent';
            });
            editBtn.addEventListener('click', () => {
                showEditDomainStyleDialog(idx);
            });

            const deleteBtn = document.createElement('button');
            deleteBtn.textContent = '🗑️';
            deleteBtn.style.cssText = `
                background: none;
                border: none;
                cursor: pointer;
                color: var(--danger-color, #ef4444);
                font-size: 14px;
                width: 32px;
                height: 32px;
                display: flex;
                align-items: center;
                justify-content: center;
                border-radius: 4px;
                transition: background-color 0.2s ease;
            `;
            deleteBtn.addEventListener('mouseenter', () => {
                deleteBtn.style.backgroundColor = 'rgba(239,68,68,0.12)';
            });
            deleteBtn.addEventListener('mouseleave', () => {
                deleteBtn.style.backgroundColor = 'transparent';
            });
            deleteBtn.addEventListener('click', () => {
                const styleToDelete = buttonConfig.domainStyleSettings[idx];
                showStyleRuleDeleteConfirmDialog(styleToDelete, () => {
                    buttonConfig.domainStyleSettings.splice(idx, 1);
                    localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
                    renderDomainStyles();
                    // 删除后应用默认/其他匹配样式
                    try { applyDomainStyles(); } catch (_) {}
                });
            });

        heightColumn.appendChild(heightBadge);
        heightColumn.appendChild(bottomBadge);

            const editColumn = document.createElement('div');
            editColumn.style.display = 'flex';
            editColumn.style.alignItems = 'center';
            editColumn.style.justifyContent = 'center';
            editColumn.style.flex = '0 0 40px';
            editColumn.appendChild(editBtn);

            const deleteColumn = document.createElement('div');
            deleteColumn.style.display = 'flex';
            deleteColumn.style.alignItems = 'center';
            deleteColumn.style.justifyContent = 'center';
            deleteColumn.style.flex = '0 0 40px';
            deleteColumn.appendChild(deleteBtn);

            row.appendChild(iconColumn);
            row.appendChild(siteColumn);
            row.appendChild(cssColumn);
            row.appendChild(heightColumn);
            row.appendChild(editColumn);
            row.appendChild(deleteColumn);
            styleListBody.appendChild(row);
        });
        if (metadataPatched) {
            localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
        }
    }
    renderDomainStyles();

    // 新建
    const addStyleBtn = document.createElement('button');
    addStyleBtn.textContent = '+ 新建';
    addStyleBtn.style.cssText = `
        background-color: var(--add-color, #fd7e14);
        color: #fff;
        border: none;
        border-radius: 4px;
        padding: 6px 12px;
        cursor: pointer;
        margin-bottom: 12px;
    `;
    addStyleBtn.addEventListener('click', () => {
        showEditDomainStyleDialog(); // 新建
    });
    dialog.appendChild(addStyleBtn);

    // 右上角关闭并保存
    const closeSaveBtn = document.createElement('button');
    closeSaveBtn.textContent = '💾 关闭并保存';
    closeSaveBtn.style.cssText = `
        background-color: var(--success-color, #22c55e);
        color: white;
        border: none;
        border-radius: 4px;
        padding: 6px 12px;
        cursor: pointer;
        position: absolute;
        top: 20px;
        right: 20px;
    `;
    closeSaveBtn.addEventListener('click', () => {
        localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
        // 关闭前应用一次,确保当前页面即时生效
        try { applyDomainStyles(); } catch (_) {}
        closeExistingOverlay(overlay);
        currentStyleOverlay = null;
    });
    dialog.style.position = 'relative';
    dialog.appendChild(closeSaveBtn);

}

    /**
     * 新建/编辑域名样式对话框
     * @param {number} index - 可选,若存在则为编辑,否则新建
     */
let currentAddDomainOverlay = null; // 保持原有声明
function showEditDomainStyleDialog(index) {
    if (currentAddDomainOverlay) {
        closeExistingOverlay(currentAddDomainOverlay);
    }
    const isEdit = typeof index === 'number';
    const styleItem = isEdit
        ? { ...buttonConfig.domainStyleSettings[index] }
        : {
            domain: window.location.hostname,
            name: document.title || '新样式',
            height: 40,
            bottomSpacing: buttonConfig.buttonBarBottomSpacing,
            cssCode: '',
            favicon: generateDomainFavicon(window.location.hostname)
        };
    const presetStyleDomain = styleItem.domain || '';
    if (!styleItem.favicon) {
        styleItem.favicon = generateDomainFavicon(presetStyleDomain);
    }
    if (typeof styleItem.bottomSpacing !== 'number') {
        styleItem.bottomSpacing = buttonConfig.buttonBarBottomSpacing;
    }

    const { overlay, dialog } = createUnifiedDialog({
        title: isEdit ? '✏️ 编辑自定义样式' : '🆕 新建自定义样式',
        width: '480px',
        onClose: () => {
            currentAddDomainOverlay = null;
        },
        closeOnOverlayClick: false
    });
    currentAddDomainOverlay = overlay;

    const container = document.createElement('div');
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.gap = '16px';
    container.style.marginBottom = '16px';
    container.style.padding = '16px';
    container.style.borderRadius = '6px';
    container.style.border = '1px solid var(--border-color, #e5e7eb)';
    container.style.backgroundColor = 'var(--button-bg, #f3f4f6)';

    const tabsHeader = document.createElement('div');
    tabsHeader.style.display = 'flex';
    tabsHeader.style.gap = '8px';
    tabsHeader.style.flexWrap = 'wrap';

    const tabConfig = [
        { id: 'basic', label: '基础信息' },
        { id: 'layout', label: '布局设置' },
        { id: 'css', label: '自定义 CSS' }
    ];

    const tabButtons = [];
    const tabPanels = new Map();

    const tabsBody = document.createElement('div');
    tabsBody.style.position = 'relative';

    tabConfig.forEach(({ id, label }) => {
        const button = document.createElement('button');
        button.type = 'button';
        button.dataset.tabId = id;
        button.textContent = label;
        button.style.padding = '8px 14px';
        button.style.borderRadius = '20px';
        button.style.border = '1px solid var(--border-color, #d1d5db)';
        button.style.backgroundColor = 'transparent';
        button.style.color = 'var(--muted-text-color, #6b7280)';
        button.style.cursor = 'pointer';
        button.style.fontSize = '13px';
        button.style.fontWeight = '500';
        button.addEventListener('click', () => setActiveTab(id));
        tabButtons.push(button);
        tabsHeader.appendChild(button);

        const panel = document.createElement('div');
        panel.dataset.tabId = id;
        panel.style.display = 'none';
        panel.style.flexDirection = 'column';
        panel.style.gap = '12px';
        tabPanels.set(id, panel);
        tabsBody.appendChild(panel);
    });

    container.appendChild(tabsHeader);
    container.appendChild(tabsBody);

    function setActiveTab(targetId) {
        tabButtons.forEach((button) => {
            const isActive = button.dataset.tabId === targetId;
            button.style.backgroundColor = isActive ? 'var(--dialog-bg, #ffffff)' : 'transparent';
            button.style.color = isActive ? 'var(--text-color, #1f2937)' : 'var(--muted-text-color, #6b7280)';
            button.style.fontWeight = isActive ? '600' : '500';
            button.style.boxShadow = isActive ? '0 2px 6px rgba(15, 23, 42, 0.08)' : 'none';
        });
        tabPanels.forEach((panel, panelId) => {
            panel.style.display = panelId === targetId ? 'flex' : 'none';
        });
    }

    setActiveTab('basic');

    const nameLabel = document.createElement('label');
    nameLabel.textContent = '备注名称:';
    nameLabel.style.display = 'flex';
    nameLabel.style.flexDirection = 'column';
    nameLabel.style.gap = '6px';
    nameLabel.style.fontSize = '13px';
    nameLabel.style.fontWeight = '600';
    nameLabel.style.color = 'var(--text-color, #1f2937)';
    const nameInput = document.createElement('input');
    nameInput.type = 'text';
    nameInput.value = styleItem.name || '';
    nameInput.style.width = '100%';
    nameInput.style.height = '40px';
    nameInput.style.padding = '0 12px';
    nameInput.style.border = '1px solid var(--border-color, #d1d5db)';
    nameInput.style.borderRadius = '6px';
    nameInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    nameInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    nameInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    nameInput.style.outline = 'none';
    nameInput.style.fontSize = '14px';
    nameLabel.appendChild(nameInput);
    tabPanels.get('basic').appendChild(nameLabel);

    const domainLabel = document.createElement('label');
    domainLabel.textContent = '网址:';
    domainLabel.style.display = 'flex';
    domainLabel.style.flexDirection = 'column';
    domainLabel.style.gap = '6px';
    domainLabel.style.fontSize = '13px';
    domainLabel.style.fontWeight = '600';
    domainLabel.style.color = 'var(--text-color, #1f2937)';
    const domainInput = document.createElement('input');
    domainInput.type = 'text';
    domainInput.value = styleItem.domain || '';
    domainInput.style.width = '100%';
    domainInput.style.height = '40px';
    domainInput.style.padding = '0 12px';
    domainInput.style.border = '1px solid var(--border-color, #d1d5db)';
    domainInput.style.borderRadius = '6px';
    domainInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    domainInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    domainInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    domainInput.style.outline = 'none';
    domainInput.style.fontSize = '14px';
    domainLabel.appendChild(domainInput);
    tabPanels.get('basic').appendChild(domainLabel);

    const faviconLabel2 = document.createElement('label');
    faviconLabel2.textContent = '站点图标:';
    faviconLabel2.style.display = 'flex';
    faviconLabel2.style.flexDirection = 'column';
    faviconLabel2.style.gap = '6px';
    faviconLabel2.style.fontSize = '13px';
    faviconLabel2.style.fontWeight = '600';
    faviconLabel2.style.color = 'var(--text-color, #1f2937)';

    const faviconFieldWrapper2 = document.createElement('div');
    faviconFieldWrapper2.style.display = 'flex';
    faviconFieldWrapper2.style.alignItems = 'flex-start';
    faviconFieldWrapper2.style.gap = '12px';

    const faviconPreviewHolder2 = document.createElement('div');
    faviconPreviewHolder2.style.width = '40px';
    faviconPreviewHolder2.style.height = '40px';
    faviconPreviewHolder2.style.borderRadius = '10px';
    faviconPreviewHolder2.style.display = 'flex';
    faviconPreviewHolder2.style.alignItems = 'center';
    faviconPreviewHolder2.style.justifyContent = 'center';
    faviconPreviewHolder2.style.backgroundColor = 'transparent';
    faviconPreviewHolder2.style.flexShrink = '0';

    const faviconControls2 = document.createElement('div');
    faviconControls2.style.display = 'flex';
    faviconControls2.style.flexDirection = 'column';
    faviconControls2.style.gap = '8px';
    faviconControls2.style.flex = '1';

    const faviconInput2 = document.createElement('textarea');
    faviconInput2.rows = 1;
    faviconInput2.style.flex = '1 1 auto';
    faviconInput2.style.padding = '10px 12px';
    faviconInput2.style.border = '1px solid var(--border-color, #d1d5db)';
    faviconInput2.style.borderRadius = '6px';
    faviconInput2.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    faviconInput2.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    faviconInput2.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    faviconInput2.style.outline = 'none';
    faviconInput2.style.fontSize = '14px';
    faviconInput2.style.lineHeight = '1.5';
    faviconInput2.style.resize = 'vertical';
    faviconInput2.style.overflowY = 'hidden';
    faviconInput2.placeholder = '可填写自定义图标地址';
    faviconInput2.value = styleItem.favicon || '';
    const resizeFaviconTextarea2 = () => autoResizeTextarea(faviconInput2, { minRows: 1, maxRows: 4 });

    const faviconActionsRow2 = document.createElement('div');
    faviconActionsRow2.style.display = 'flex';
    faviconActionsRow2.style.alignItems = 'center';
    faviconActionsRow2.style.gap = '8px';
    faviconActionsRow2.style.flexWrap = 'nowrap';
    faviconActionsRow2.style.fontSize = '12px';
    faviconActionsRow2.style.color = 'var(--muted-text-color, #6b7280)';
    faviconActionsRow2.style.justifyContent = 'flex-start';

    const faviconHelp2 = document.createElement('span');
    faviconHelp2.textContent = '留空时系统将使用该网址的默认 Favicon。';
    faviconHelp2.style.flex = '1';
    faviconHelp2.style.minWidth = '0';
    faviconHelp2.style.marginRight = '12px';

    const autoFaviconBtn2 = document.createElement('button');
    autoFaviconBtn2.type = 'button';
    autoFaviconBtn2.setAttribute('aria-label', '自动获取站点图标');
    autoFaviconBtn2.title = '自动获取站点图标';
    autoFaviconBtn2.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    autoFaviconBtn2.style.color = '#fff';
    autoFaviconBtn2.style.border = '1px solid var(--border-color, #d1d5db)';
    autoFaviconBtn2.style.borderRadius = '50%';
    autoFaviconBtn2.style.width = '32px';
    autoFaviconBtn2.style.height = '32px';
    autoFaviconBtn2.style.display = 'flex';
    autoFaviconBtn2.style.alignItems = 'center';
    autoFaviconBtn2.style.justifyContent = 'center';
    autoFaviconBtn2.style.cursor = 'pointer';
    autoFaviconBtn2.style.boxShadow = '0 2px 6px rgba(59, 130, 246, 0.16)';
    autoFaviconBtn2.style.flexShrink = '0';
    autoFaviconBtn2.style.padding = '0';

    const autoFaviconIcon2 = createAutoFaviconIcon();
    autoFaviconBtn2.appendChild(autoFaviconIcon2);

    faviconActionsRow2.appendChild(faviconHelp2);
    faviconActionsRow2.appendChild(autoFaviconBtn2);

    faviconControls2.appendChild(faviconInput2);
    faviconControls2.appendChild(faviconActionsRow2);

    faviconFieldWrapper2.appendChild(faviconPreviewHolder2);
    faviconFieldWrapper2.appendChild(faviconControls2);

    faviconLabel2.appendChild(faviconFieldWrapper2);
    tabPanels.get('basic').appendChild(faviconLabel2);

    let faviconManuallyEdited2 = false;
    const updateStyleFaviconPreview = () => {
        const imgUrl = faviconInput2.value.trim() || generateDomainFavicon(domainInput.value.trim());
        setTrustedHTML(faviconPreviewHolder2, '');
        faviconPreviewHolder2.appendChild(
            createFaviconElement(
                imgUrl,
                nameInput.value.trim() || domainInput.value.trim() || '样式',
                '🎨',
                { withBackground: false }
            )
        );
    };
    updateStyleFaviconPreview();
    resizeFaviconTextarea2();
    requestAnimationFrame(resizeFaviconTextarea2);

    const getStyleFallbackFavicon = () => generateDomainFavicon(domainInput.value.trim());

    autoFaviconBtn2.addEventListener('click', () => {
        const autoUrl = getStyleFallbackFavicon();
        faviconInput2.value = autoUrl;
        faviconManuallyEdited2 = false;
        updateStyleFaviconPreview();
        resizeFaviconTextarea2();
    });

    domainInput.addEventListener('input', () => {
        if (!faviconManuallyEdited2) {
            faviconInput2.value = getStyleFallbackFavicon();
        }
        updateStyleFaviconPreview();
        resizeFaviconTextarea2();
    });

    faviconInput2.addEventListener('input', () => {
        faviconManuallyEdited2 = true;
        updateStyleFaviconPreview();
        resizeFaviconTextarea2();
    });
    nameInput.addEventListener('input', updateStyleFaviconPreview);

    const heightLabel = document.createElement('label');
    heightLabel.textContent = '按钮栏高度 (px):';
    heightLabel.style.display = 'flex';
    heightLabel.style.flexDirection = 'column';
    heightLabel.style.gap = '6px';
    heightLabel.style.fontSize = '13px';
    heightLabel.style.fontWeight = '600';
    heightLabel.style.color = 'var(--text-color, #1f2937)';
    const heightInput = document.createElement('input');
    heightInput.type = 'number';
    heightInput.min = '20';
    heightInput.max = '200';
    heightInput.step = '1';
    heightInput.value = styleItem.height;
    heightInput.style.width = '100%';
    heightInput.style.height = '40px';
    heightInput.style.padding = '0 12px';
    heightInput.style.border = '1px solid var(--border-color, #d1d5db)';
    heightInput.style.borderRadius = '6px';
    heightInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    heightInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    heightInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    heightInput.style.outline = 'none';
    heightInput.style.fontSize = '14px';
    heightLabel.appendChild(heightInput);
    tabPanels.get('layout').appendChild(heightLabel);

    const bottomSpacingLabel = document.createElement('label');
    bottomSpacingLabel.textContent = '按钮距页面底部间距 (px):';
    bottomSpacingLabel.style.display = 'flex';
    bottomSpacingLabel.style.flexDirection = 'column';
    bottomSpacingLabel.style.gap = '6px';
    bottomSpacingLabel.style.fontSize = '13px';
    bottomSpacingLabel.style.fontWeight = '600';
    bottomSpacingLabel.style.color = 'var(--text-color, #1f2937)';
    const bottomSpacingInput = document.createElement('input');
    bottomSpacingInput.type = 'number';
    bottomSpacingInput.min = '-200';
    bottomSpacingInput.max = '200';
    bottomSpacingInput.step = '1';
    bottomSpacingInput.value = styleItem.bottomSpacing ?? buttonConfig.buttonBarBottomSpacing ?? 0;
    bottomSpacingInput.style.width = '100%';
    bottomSpacingInput.style.height = '40px';
    bottomSpacingInput.style.padding = '0 12px';
    bottomSpacingInput.style.border = '1px solid var(--border-color, #d1d5db)';
    bottomSpacingInput.style.borderRadius = '6px';
    bottomSpacingInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    bottomSpacingInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    bottomSpacingInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    bottomSpacingInput.style.outline = 'none';
    bottomSpacingInput.style.fontSize = '14px';
    bottomSpacingLabel.appendChild(bottomSpacingInput);
    tabPanels.get('layout').appendChild(bottomSpacingLabel);

    const cssLabel = document.createElement('label');
    cssLabel.textContent = '自定义 CSS:';
    cssLabel.style.display = 'flex';
    cssLabel.style.flexDirection = 'column';
    cssLabel.style.gap = '6px';
    cssLabel.style.fontSize = '13px';
    cssLabel.style.fontWeight = '600';
    cssLabel.style.color = 'var(--text-color, #1f2937)';
    const cssTextarea = document.createElement('textarea');
    cssTextarea.value = styleItem.cssCode || '';
    cssTextarea.style.width = '100%';
    cssTextarea.style.minHeight = '120px';
    cssTextarea.style.padding = '12px';
    cssTextarea.style.border = '1px solid var(--border-color, #d1d5db)';
    cssTextarea.style.borderRadius = '6px';
    cssTextarea.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    cssTextarea.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    cssTextarea.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    cssTextarea.style.outline = 'none';
    cssTextarea.style.resize = 'vertical';
    cssTextarea.style.fontSize = '13px';
    cssTextarea.style.lineHeight = '1.5';
    cssLabel.appendChild(cssTextarea);
    tabPanels.get('css').appendChild(cssLabel);

    dialog.appendChild(container);

    const footer2 = document.createElement('div');
    footer2.style.display = 'flex';
    footer2.style.justifyContent = 'space-between';
    footer2.style.alignItems = 'center';
    footer2.style.gap = '12px';
    footer2.style.marginTop = '20px';
    footer2.style.paddingTop = '20px';
    footer2.style.borderTop = '1px solid var(--border-color, #e5e7eb)';

    const cancelBtn2 = document.createElement('button');
    cancelBtn2.textContent = '取消';
    cancelBtn2.style.backgroundColor = 'var(--cancel-color, #6B7280)';
    cancelBtn2.style.color = '#fff';
    cancelBtn2.style.border = 'none';
    cancelBtn2.style.borderRadius = '4px';
    cancelBtn2.style.padding = '8px 16px';
    cancelBtn2.style.fontSize = '14px';
    cancelBtn2.style.cursor = 'pointer';
    cancelBtn2.addEventListener('click', () => {
        closeExistingOverlay(overlay);
        currentAddDomainOverlay = null;
    });
    footer2.appendChild(cancelBtn2);

    const saveBtn2 = document.createElement('button');
    saveBtn2.textContent = isEdit ? '保存' : '创建';
    saveBtn2.style.backgroundColor = 'var(--success-color,#22c55e)';
    saveBtn2.style.color = '#fff';
    saveBtn2.style.border = 'none';
    saveBtn2.style.borderRadius = '4px';
    saveBtn2.style.padding = '8px 16px';
    saveBtn2.style.fontSize = '14px';
    saveBtn2.style.cursor = 'pointer';
    saveBtn2.addEventListener('click', () => {
        const sanitizedDomain = domainInput.value.trim();
        const updatedItem = {
            domain: sanitizedDomain,
            name: nameInput.value.trim() || '未命名样式',
            height: parseInt(heightInput.value, 10) || 40,
            bottomSpacing: (() => {
                const parsed = Number(bottomSpacingInput.value);
                if (Number.isFinite(parsed)) {
                    return Math.max(-200, Math.min(200, parsed));
                }
                return buttonConfig.buttonBarBottomSpacing;
            })(),
            cssCode: cssTextarea.value,
            favicon: faviconInput2.value.trim() || generateDomainFavicon(sanitizedDomain)
        };
        if (isEdit) {
            buttonConfig.domainStyleSettings[index] = updatedItem;
        } else {
            buttonConfig.domainStyleSettings.push(updatedItem);
        }
        localStorage.setItem('chatGPTButtonFoldersConfig', JSON.stringify(buttonConfig));
        // 保存后立即生效
        try { applyDomainStyles(); } catch (_) {}
        closeExistingOverlay(overlay);
        currentAddDomainOverlay = null;
        showStyleSettingsDialog(); // 刷新列表
    });
    footer2.appendChild(saveBtn2);

    dialog.appendChild(footer2);
}


// =============== [新增] showDomainRuleEditorDialog 统一新建/编辑弹窗 ===============
function showDomainRuleEditorDialog(ruleData, onSave) {
    // ruleData 若为空对象,则视为新建,否则编辑
    // 统一使用 createUnifiedDialog
    const isEdit = !!ruleData && ruleData.domain;
    const presetDomain = isEdit ? (ruleData.domain || '') : (window.location.hostname || '');
    const presetFavicon = (isEdit && ruleData.favicon) ? ruleData.favicon : generateDomainFavicon(presetDomain);

    const { overlay, dialog } = createUnifiedDialog({
        title: isEdit ? '✏️ 编辑自动化规则' : '🆕 新建新网址规则',
        width: '480px',
        onClose: () => {
            // 关闭时的回调可写在此
        },
        closeOnOverlayClick: false
    });

    function createAutoSubmitMethodConfigUI(initialMethod = 'Enter', initialAdvanced = null) {
        const methodSection = document.createElement('div');
        methodSection.style.display = 'flex';
        methodSection.style.flexDirection = 'column';
        methodSection.style.gap = '8px';

        const titleRow = document.createElement('div');
        titleRow.style.display = 'flex';
        titleRow.style.alignItems = 'center';
        titleRow.style.justifyContent = 'space-between';

        const methodTitle = document.createElement('div');
        methodTitle.textContent = '自动提交方式:';
        methodTitle.style.fontSize = '13px';
        methodTitle.style.fontWeight = '600';
        methodTitle.style.color = 'var(--text-color, #1f2937)';
        titleRow.appendChild(methodTitle);

        const expandButton = document.createElement('button');
        expandButton.type = 'button';
        expandButton.title = '展开/折叠高级选项';
        expandButton.textContent = '▼';
        expandButton.style.width = '28px';
        expandButton.style.height = '28px';
        expandButton.style.padding = '0';
        expandButton.style.display = 'flex';
        expandButton.style.alignItems = 'center';
        expandButton.style.justifyContent = 'center';
        expandButton.style.border = '1px solid transparent';
        expandButton.style.borderRadius = '4px';
        expandButton.style.background = 'transparent';
        expandButton.style.cursor = 'pointer';
        expandButton.style.transition = 'background-color 0.2s ease, border-color 0.2s ease';
        expandButton.addEventListener('mouseenter', () => {
            expandButton.style.backgroundColor = 'var(--button-bg, #f3f4f6)';
            expandButton.style.borderColor = 'var(--border-color, #d1d5db)';
        });
        expandButton.addEventListener('mouseleave', () => {
            expandButton.style.backgroundColor = 'transparent';
            expandButton.style.borderColor = 'transparent';
        });
        titleRow.appendChild(expandButton);
        methodSection.appendChild(titleRow);

        const methodOptionsWrapper = document.createElement('div');
        methodOptionsWrapper.style.display = 'flex';
        methodOptionsWrapper.style.flexWrap = 'wrap';
        methodOptionsWrapper.style.gap = '15px';
        methodSection.appendChild(methodOptionsWrapper);

        const advancedContainer = document.createElement('div');
        advancedContainer.style.display = 'none';
        advancedContainer.style.flexDirection = 'column';
        advancedContainer.style.gap = '10px';
        advancedContainer.style.marginTop = '8px';
        advancedContainer.style.padding = '12px';
        advancedContainer.style.borderRadius = '6px';
        advancedContainer.style.border = '1px solid var(--border-color, #d1d5db)';
        advancedContainer.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
        advancedContainer.style.boxShadow = 'inset 0 1px 2px rgba(15, 23, 42, 0.04)';
        advancedContainer.style.transition = 'opacity 0.2s ease';
        advancedContainer.style.opacity = '0';
        methodSection.appendChild(advancedContainer);

        const methodOptions = [
            { value: 'Enter', text: 'Enter' },
            { value: 'Cmd+Enter', text: 'Cmd+Enter' },
            { value: '模拟点击提交按钮', text: '模拟点击提交按钮' }
        ];

        const methodRadioName = `autoSubmitMethod_${Math.random().toString(36).slice(2, 8)}`;
        const uniqueSuffix = Math.random().toString(36).slice(2, 8);

        const getDefaultAdvancedForMethod = (method) => {
            if (method === 'Cmd+Enter') {
                return { variant: 'cmd' };
            }
            if (method === '模拟点击提交按钮') {
                return { variant: 'default', selector: '' };
            }
            return null;
        };

        const normalizeAdvancedForMethod = (method, advanced) => {
            const defaults = getDefaultAdvancedForMethod(method);
            if (!defaults) return null;
            const normalized = { ...defaults };
            if (advanced && typeof advanced === 'object') {
                if (method === 'Cmd+Enter') {
                    if (advanced.variant && ['cmd', 'ctrl'].includes(advanced.variant)) {
                        normalized.variant = advanced.variant;
                    }
                } else if (method === '模拟点击提交按钮') {
                    if (advanced.variant && ['default', 'selector'].includes(advanced.variant)) {
                        normalized.variant = advanced.variant;
                    }
                    if (advanced.selector && typeof advanced.selector === 'string') {
                        normalized.selector = advanced.selector;
                    }
                }
            }
            if (method === '模拟点击提交按钮' && normalized.variant !== 'selector') {
                normalized.selector = '';
            }
            return normalized;
        };

        let selectedMethod = initialMethod || methodOptions[0].value;
        if (!methodOptions.some(option => option.value === selectedMethod)) {
            methodOptions.push({ value: selectedMethod, text: selectedMethod });
        }

        let advancedState = normalizeAdvancedForMethod(selectedMethod, initialAdvanced);

        const shouldExpandInitially = () => {
            if (!advancedState) return false;
            if (selectedMethod === 'Cmd+Enter') {
                return advancedState.variant === 'ctrl';
            }
            if (selectedMethod === '模拟点击提交按钮') {
                return advancedState.variant === 'selector' && advancedState.selector;
            }
            return false;
        };

        let isExpanded = shouldExpandInitially();

        const renderAdvancedContent = () => {
            setTrustedHTML(advancedContainer, '');
            if (!isExpanded) {
                advancedContainer.style.display = 'none';
                advancedContainer.style.opacity = '0';
                return;
            }

            advancedContainer.style.display = 'flex';
            advancedContainer.style.opacity = '1';

            const advancedTitle = document.createElement('div');
            advancedTitle.textContent = '高级选项:';
            advancedTitle.style.fontSize = '12px';
            advancedTitle.style.fontWeight = '600';
            advancedTitle.style.opacity = '0.75';
            advancedContainer.appendChild(advancedTitle);

            if (selectedMethod === 'Enter') {
                const tip = document.createElement('div');
                tip.textContent = 'Enter 提交方式没有额外配置。';
                tip.style.fontSize = '12px';
                tip.style.color = 'var(--muted-text-color, #6b7280)';
                advancedContainer.appendChild(tip);
                return;
            }

            if (selectedMethod === 'Cmd+Enter') {
                const variants = [
                    { value: 'cmd', label: 'Cmd + Enter', desc: '使用 macOS / Meta 键组合模拟提交' },
                    { value: 'ctrl', label: 'Ctrl + Enter', desc: '使用 Windows / Linux 控制键组合模拟提交' }
                ];
                const variantGroup = document.createElement('div');
                variantGroup.style.display = 'flex';
                variantGroup.style.flexDirection = 'column';
                variantGroup.style.gap = '8px';

                const variantRadioName = `autoSubmitCmdVariant_${uniqueSuffix}`;
                variants.forEach(variant => {
                    const label = document.createElement('label');
                    label.style.display = 'flex';
                    label.style.alignItems = 'flex-start';
                    label.style.gap = '8px';
                    label.style.cursor = 'pointer';

                    const radio = document.createElement('input');
                    radio.type = 'radio';
                    radio.name = variantRadioName;
                    radio.value = variant.value;
                    radio.checked = advancedState?.variant === variant.value;
                    radio.style.marginTop = '2px';
                    radio.style.cursor = 'pointer';
                    radio.addEventListener('change', () => {
                        if (radio.checked) {
                            advancedState = { variant: variant.value };
                        }
                    });

                    const textContainer = document.createElement('div');
                    textContainer.style.display = 'flex';
                    textContainer.style.flexDirection = 'column';
                    textContainer.style.gap = '2px';

                    const labelText = document.createElement('span');
                    labelText.textContent = variant.label;
                    labelText.style.fontSize = '13px';
                    labelText.style.fontWeight = '600';

                    const descText = document.createElement('span');
                    descText.textContent = variant.desc;
                    descText.style.fontSize = '12px';
                    descText.style.opacity = '0.75';

                    textContainer.appendChild(labelText);
                    textContainer.appendChild(descText);
                    label.appendChild(radio);
                    label.appendChild(textContainer);
                    variantGroup.appendChild(label);
                });

                advancedContainer.appendChild(variantGroup);
                return;
            }

            if (selectedMethod === '模拟点击提交按钮') {
                const variants = [
                    { value: 'default', label: '默认方法', desc: '自动匹配常见的提交按钮进行点击。' },
                    { value: 'selector', label: '自定义 CSS 选择器', desc: '使用自定义选择器定位需要点击的提交按钮。' }
                ];

                const variantGroup = document.createElement('div');
                variantGroup.style.display = 'flex';
                variantGroup.style.flexDirection = 'column';
                variantGroup.style.gap = '8px';

                const variantRadioName = `autoSubmitClickVariant_${uniqueSuffix}`;
                variants.forEach(variant => {
                    const label = document.createElement('label');
                    label.style.display = 'flex';
                    label.style.alignItems = 'flex-start';
                    label.style.gap = '8px';
                    label.style.cursor = 'pointer';

                    const radio = document.createElement('input');
                    radio.type = 'radio';
                    radio.name = variantRadioName;
                    radio.value = variant.value;
                    radio.checked = advancedState?.variant === variant.value;
                    radio.style.marginTop = '2px';
                    radio.style.cursor = 'pointer';
                    radio.addEventListener('change', () => {
                        if (radio.checked) {
                            advancedState = normalizeAdvancedForMethod(selectedMethod, { variant: variant.value, selector: advancedState?.selector || '' });
                            renderAdvancedContent();
                        }
                    });

                    const textContainer = document.createElement('div');
                    textContainer.style.display = 'flex';
                    textContainer.style.flexDirection = 'column';
                    textContainer.style.gap = '2px';

                    const labelText = document.createElement('span');
                    labelText.textContent = variant.label;
                    labelText.style.fontSize = '13px';
                    labelText.style.fontWeight = '600';

                    const descText = document.createElement('span');
                    descText.textContent = variant.desc;
                    descText.style.fontSize = '12px';
                    descText.style.opacity = '0.75';

                    textContainer.appendChild(labelText);
                    textContainer.appendChild(descText);
                    label.appendChild(radio);
                    label.appendChild(textContainer);
                    variantGroup.appendChild(label);
                });

                advancedContainer.appendChild(variantGroup);

                if (advancedState?.variant === 'selector') {
                    const selectorInput = document.createElement('input');
                    selectorInput.type = 'text';
                    selectorInput.placeholder = '如:button.send-btn 或 form button[type="submit"]';
                    selectorInput.value = advancedState.selector || '';
                    selectorInput.style.width = '100%';
                    selectorInput.style.height = '40px';
                    selectorInput.style.padding = '0 12px';
                    selectorInput.style.border = '1px solid var(--border-color, #d1d5db)';
                    selectorInput.style.borderRadius = '6px';
                    selectorInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
                    selectorInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
                    selectorInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
                    selectorInput.style.outline = 'none';
                    selectorInput.style.fontSize = '14px';
                    selectorInput.addEventListener('input', () => {
                        advancedState = normalizeAdvancedForMethod(selectedMethod, {
                            variant: 'selector',
                            selector: selectorInput.value
                        });
                    });
                    advancedContainer.appendChild(selectorInput);

                    const hint = document.createElement('div');
                    hint.textContent = '请输入能唯一定位提交按钮的 CSS 选择器。';
                    hint.style.fontSize = '12px';
                    hint.style.color = 'var(--muted-text-color, #6b7280)';
                    advancedContainer.appendChild(hint);
                }
                return;
            }

            const tip = document.createElement('div');
            tip.textContent = '当前提交方式没有可配置的高级选项。';
            tip.style.fontSize = '12px';
            tip.style.color = 'var(--muted-text-color, #6b7280)';
            advancedContainer.appendChild(tip);
        };

        methodOptions.forEach(option => {
            const radioLabel = document.createElement('label');
            radioLabel.style.display = 'inline-flex';
            radioLabel.style.alignItems = 'center';
            radioLabel.style.cursor = 'pointer';

            const radio = document.createElement('input');
            radio.type = 'radio';
            radio.name = methodRadioName;
            radio.value = option.value;
            radio.checked = selectedMethod === option.value;
            radio.style.marginRight = '6px';
            radio.style.cursor = 'pointer';
            radio.addEventListener('change', () => {
                if (radio.checked) {
                    selectedMethod = option.value;
                    advancedState = normalizeAdvancedForMethod(selectedMethod, null);
                    renderAdvancedContent();
                }
            });

            radioLabel.appendChild(radio);
            radioLabel.appendChild(document.createTextNode(option.text));
            methodOptionsWrapper.appendChild(radioLabel);
        });

        expandButton.addEventListener('click', () => {
            isExpanded = !isExpanded;
            expandButton.textContent = isExpanded ? '▲' : '▼';
            expandButton.setAttribute('aria-expanded', String(isExpanded));
            renderAdvancedContent();
        });

        expandButton.setAttribute('aria-expanded', String(isExpanded));
        expandButton.textContent = isExpanded ? '▲' : '▼';
        renderAdvancedContent();

        return {
            container: methodSection,
            getConfig: () => {
                const normalized = normalizeAdvancedForMethod(selectedMethod, advancedState);
                let advancedForSave = null;
                if (selectedMethod === 'Cmd+Enter' && normalized && normalized.variant && normalized.variant !== 'cmd') {
                    advancedForSave = { variant: normalized.variant };
                } else if (selectedMethod === '模拟点击提交按钮' && normalized) {
                    if (normalized.variant === 'selector') {
                        advancedForSave = {
                            variant: 'selector',
                            selector: typeof normalized.selector === 'string' ? normalized.selector : ''
                        };
                    } else if (normalized.variant !== 'default') {
                        advancedForSave = { variant: normalized.variant };
                    }
                }
                return {
                    method: selectedMethod,
                    advanced: advancedForSave
                };
            }
        };
    }

    // 创建表单容器
    const container = document.createElement('div');
    container.style.display = 'flex';
    container.style.flexDirection = 'column';
    container.style.gap = '12px';
    container.style.marginBottom = '16px';
    container.style.padding = '16px';
    container.style.borderRadius = '6px';
    container.style.border = '1px solid var(--border-color, #e5e7eb)';
    container.style.backgroundColor = 'var(--button-bg, #f3f4f6)';

    // 网址
    const domainLabel = document.createElement('label');
    domainLabel.textContent = '网址:';
    domainLabel.style.display = 'flex';
    domainLabel.style.flexDirection = 'column';
    domainLabel.style.gap = '6px';
    domainLabel.style.fontSize = '13px';
    domainLabel.style.fontWeight = '600';
    domainLabel.style.color = 'var(--text-color, #1f2937)';
    const domainInput = document.createElement('input');
    domainInput.type = 'text';
    domainInput.style.width = '100%';
    domainInput.style.height = '40px';
    domainInput.style.padding = '0 12px';
    domainInput.style.border = '1px solid var(--border-color, #d1d5db)';
    domainInput.style.borderRadius = '6px';
   domainInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    domainInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    domainInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    domainInput.style.outline = 'none';
    domainInput.style.fontSize = '14px';
    domainInput.value = presetDomain;
    domainLabel.appendChild(domainInput);
    container.appendChild(domainLabel);

    let nameInputRef = null;

    // 备注名称
    const nameLabel = document.createElement('label');
    nameLabel.textContent = '备注名称:';
    nameLabel.style.display = 'flex';
    nameLabel.style.flexDirection = 'column';
    nameLabel.style.gap = '6px';
    nameLabel.style.fontSize = '13px';
    nameLabel.style.fontWeight = '600';
    nameLabel.style.color = 'var(--text-color, #1f2937)';
    nameInputRef = document.createElement('input');
    nameInputRef.type = 'text';
    nameInputRef.style.width = '100%';
    nameInputRef.style.height = '40px';
    nameInputRef.style.padding = '0 12px';
    nameInputRef.style.border = '1px solid var(--border-color, #d1d5db)';
    nameInputRef.style.borderRadius = '6px';
    nameInputRef.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    nameInputRef.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    nameInputRef.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    nameInputRef.style.outline = 'none';
    nameInputRef.style.fontSize = '14px';
    nameInputRef.value = isEdit ? (ruleData.name || '') : (document.title || '新网址规则');
    nameLabel.appendChild(nameInputRef);
    container.appendChild(nameLabel);

    // favicon
    const faviconLabel = document.createElement('label');
    faviconLabel.textContent = '站点图标:';
    faviconLabel.style.display = 'flex';
    faviconLabel.style.flexDirection = 'column';
    faviconLabel.style.gap = '6px';
    faviconLabel.style.fontSize = '13px';
    faviconLabel.style.fontWeight = '600';
    faviconLabel.style.color = 'var(--text-color, #1f2937)';

    const faviconFieldWrapper = document.createElement('div');
    faviconFieldWrapper.style.display = 'flex';
    faviconFieldWrapper.style.alignItems = 'flex-start';
    faviconFieldWrapper.style.gap = '12px';

    const faviconPreviewHolder = document.createElement('div');
    faviconPreviewHolder.style.width = '40px';
    faviconPreviewHolder.style.height = '40px';
    faviconPreviewHolder.style.borderRadius = '10px';
    faviconPreviewHolder.style.display = 'flex';
    faviconPreviewHolder.style.alignItems = 'center';
    faviconPreviewHolder.style.justifyContent = 'center';
    faviconPreviewHolder.style.backgroundColor = 'transparent';
    faviconPreviewHolder.style.flexShrink = '0';

    const faviconControls = document.createElement('div');
    faviconControls.style.display = 'flex';
    faviconControls.style.flexDirection = 'column';
    faviconControls.style.gap = '8px';
    faviconControls.style.flex = '1';

    const faviconInput = document.createElement('textarea');
    faviconInput.rows = 1;
    faviconInput.style.flex = '1 1 auto';
    faviconInput.style.padding = '10px 12px';
    faviconInput.style.border = '1px solid var(--border-color, #d1d5db)';
    faviconInput.style.borderRadius = '6px';
    faviconInput.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    faviconInput.style.boxShadow = 'inset 0 1px 2px rgba(0,0,0,0.03)';
    faviconInput.style.transition = 'border-color 0.2s ease, box-shadow 0.2s ease';
    faviconInput.style.outline = 'none';
    faviconInput.style.fontSize = '14px';
    faviconInput.style.lineHeight = '1.5';
    faviconInput.style.resize = 'vertical';
    faviconInput.style.overflowY = 'hidden';
    faviconInput.placeholder = 'https:// 或 data:image/svg+xml;base64...';
    faviconInput.value = presetFavicon || '';
    const resizeFaviconTextarea = () => autoResizeTextarea(faviconInput, { minRows: 1, maxRows: 4 });

    const faviconActionsRow = document.createElement('div');
    faviconActionsRow.style.display = 'flex';
    faviconActionsRow.style.alignItems = 'center';
    faviconActionsRow.style.gap = '8px';
    faviconActionsRow.style.flexWrap = 'nowrap';
    faviconActionsRow.style.fontSize = '12px';
    faviconActionsRow.style.color = 'var(--muted-text-color, #6b7280)';
    faviconActionsRow.style.justifyContent = 'flex-start';

    const faviconHelp = document.createElement('span');
    faviconHelp.textContent = '留空时将自动根据网址生成 Google Favicon。';
    faviconHelp.style.flex = '1';
    faviconHelp.style.minWidth = '0';
    faviconHelp.style.marginRight = '12px';

    const autoFaviconBtn = document.createElement('button');
    autoFaviconBtn.type = 'button';
    autoFaviconBtn.setAttribute('aria-label', '自动获取站点图标');
    autoFaviconBtn.title = '自动获取站点图标';
    autoFaviconBtn.style.backgroundColor = 'var(--dialog-bg, #ffffff)';
    autoFaviconBtn.style.border = '1px solid var(--border-color, #d1d5db)';
    autoFaviconBtn.style.borderRadius = '50%';
    autoFaviconBtn.style.width = '32px';
    autoFaviconBtn.style.height = '32px';
    autoFaviconBtn.style.display = 'flex';
    autoFaviconBtn.style.alignItems = 'center';
    autoFaviconBtn.style.justifyContent = 'center';
    autoFaviconBtn.style.cursor = 'pointer';
    autoFaviconBtn.style.boxShadow = '0 2px 6px rgba(59, 130, 246, 0.16)';
    autoFaviconBtn.style.flexShrink = '0';
    autoFaviconBtn.style.padding = '0';

    const autoFaviconIcon = createAutoFaviconIcon();
    autoFaviconBtn.appendChild(autoFaviconIcon);

    faviconActionsRow.appendChild(faviconHelp);
    faviconActionsRow.appendChild(autoFaviconBtn);

    faviconControls.appendChild(faviconInput);
    faviconControls.appendChild(faviconActionsRow);

    faviconFieldWrapper.appendChild(faviconPreviewHolder);
    faviconFieldWrapper.appendChild(faviconControls);

    faviconLabel.appendChild(faviconFieldWrapper);
    container.appendChild(faviconLabel);

    let faviconManuallyEdited = false;
    const updateFaviconPreview = () => {
        const currentFavicon = faviconInput.value.trim();
        setTrustedHTML(faviconPreviewHolder, '');
        faviconPreviewHolder.appendChild(
            createFaviconElement(
                currentFavicon || generateDomainFavicon(domainInput.value.trim()),
                (nameInputRef ? nameInputRef.value.trim() : '') || domainInput.value.trim() || '自动化',
                '⚡',
                { withBackground: false }
            )
        );
    };

    const getFallbackFavicon = () => generateDomainFavicon(domainInput.value.trim());

    autoFaviconBtn.addEventListener('click', () => {
        const autoUrl = getFallbackFavicon();
        faviconInput.value = autoUrl;
        faviconManuallyEdited = false;
        updateFaviconPreview();
        resizeFaviconTextarea();
    });

    domainInput.addEventListener('input', () => {
        if (!faviconManuallyEdited) {
            faviconInput.value = getFallbackFavicon();
        }
        updateFaviconPreview();
        resizeFaviconTextarea();
    });

    faviconInput.addEventListener('input', () => {
        faviconManuallyEdited = true;
        updateFaviconPreview();
        resizeFaviconTextarea();
    });

    nameInputRef.addEventListener('input', updateFaviconPreview);

    updateFaviconPreview();
    resizeFaviconTextarea();
    requestAnimationFrame(resizeFaviconTextarea);

    const methodConfigUI = createAutoSubmitMethodConfigUI(
        (isEdit && ruleData.method) ? ruleData.method : 'Enter',
        isEdit ? ruleData.methodAdvanced : null
    );
    container.appendChild(methodConfigUI.container);

    // 确认 & 取消 按钮
    const btnRow = document.createElement('div');
    btnRow.style.display = 'flex';
    btnRow.style.justifyContent = 'space-between';
    btnRow.style.alignItems = 'center';
    btnRow.style.gap = '12px';
    btnRow.style.marginTop = '20px';
    btnRow.style.paddingTop = '20px';
    btnRow.style.borderTop = '1px solid var(--border-color, #e5e7eb)';

    const cancelBtn = document.createElement('button');
    cancelBtn.textContent = '取消';
    cancelBtn.style.backgroundColor = 'var(--cancel-color,#6B7280)';
    cancelBtn.style.color = '#fff';
    cancelBtn.style.border = 'none';
    cancelBtn.style.borderRadius = '4px';
    cancelBtn.style.padding = '8px 16px';
    cancelBtn.style.fontSize = '14px';
    cancelBtn.style.cursor = 'pointer';
    cancelBtn.addEventListener('click', () => {
        overlay.remove();
    });

    const confirmBtn = document.createElement('button');
    confirmBtn.textContent = '确认';
    confirmBtn.style.backgroundColor = 'var(--success-color,#22c55e)';
    confirmBtn.style.color = '#fff';
    confirmBtn.style.border = 'none';
    confirmBtn.style.borderRadius = '4px';
    confirmBtn.style.padding = '8px 16px';
    confirmBtn.style.fontSize = '14px';
    confirmBtn.style.cursor = 'pointer';
    confirmBtn.addEventListener('click', () => {
        const sanitizedDomain = domainInput.value.trim();
        const sanitizedName = nameInputRef.value.trim();
        const methodConfig = methodConfigUI.getConfig();
        const methodAdvanced = methodConfig.advanced;
        const newData = {
            domain: sanitizedDomain,
            name: sanitizedName,
            method: methodConfig.method,
            favicon: faviconInput.value.trim() || generateDomainFavicon(sanitizedDomain)
        };

        if(!newData.domain || !newData.name) {
            alert('请输入网址和备注名称!');
            return;
        }

        if (methodConfig.method === '模拟点击提交按钮' && methodAdvanced && methodAdvanced.variant === 'selector') {
            const trimmedSelector = methodAdvanced.selector ? methodAdvanced.selector.trim() : '';
            if (!trimmedSelector) {
                alert('请输入有效的 CSS 选择器!');
                return;
            }
            try {
                document.querySelector(trimmedSelector);
            } catch (err) {
                alert('CSS 选择器语法错误,请检查后再试!');
                return;
            }
            methodAdvanced.selector = trimmedSelector;
        }

        if (methodAdvanced) {
            newData.methodAdvanced = methodAdvanced;
        }

        // 回调保存
        if(onSave) onSave(newData);
        // 关闭
        overlay.remove();
    });

    btnRow.appendChild(cancelBtn);
    btnRow.appendChild(confirmBtn);

    // 组装
    dialog.appendChild(container);
    dialog.appendChild(btnRow);

}

function isValidDomainInput(str) {
    // 简易:包含'.' 不含空格 即视为有效
    if (str.includes(' ')) return false;
    if (!str.includes('.')) return false;
    return true;
}

    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
        setCSSVariables(getCurrentTheme());
        updateStylesOnThemeChange();
        console.log("🌓 主题模式已切换,样式已更新。");
    });

    const createButtonContainer = () => {
        const root = getShadowRoot();
        let existingContainer = root ? root.querySelector('.folder-buttons-container') : null;
        if (existingContainer) {
            // 使用updateButtonContainer来处理已存在的容器
            updateButtonContainer();
            return existingContainer;
        }
        // 创建新容器
        const buttonContainer = document.createElement('div');
        buttonContainer.classList.add('folder-buttons-container');
        buttonContainer.style.pointerEvents = 'auto';

        // 设置固定定位和位置
        buttonContainer.style.position = 'fixed';
        buttonContainer.style.right = '0px';
        buttonContainer.style.width = '100%';
        buttonContainer.style.zIndex = '1000'; // 确保按钮容器始终显示在顶层

        // 基本样式
        buttonContainer.style.display = 'flex';
        buttonContainer.style.flexWrap = 'nowrap';  // 改为不换行
        buttonContainer.style.overflowX = 'auto';   // 横向滚动
        buttonContainer.style.overflowY = 'hidden'; // 禁止纵向滚动
        buttonContainer.style.gap = '10px';
        buttonContainer.style.marginTop = '0px';
        buttonContainer.style.height = buttonConfig.buttonBarHeight + 'px';

        // 滚动条处理
        buttonContainer.style.scrollbarWidth = 'none';        // for Firefox
        buttonContainer.style.msOverflowStyle = 'none';       // for IE/Edge
        buttonContainer.classList.add('hide-scrollbar');      // 用于自定义::-webkit-scrollbar

        // 内容布局
        buttonContainer.style.justifyContent = 'center';
        buttonContainer.style.alignItems = 'center';
        buttonContainer.style.padding = '6px 15px';

        // 移除原有的背景色和阴影,设置为透明
        buttonContainer.style.backgroundColor = 'transparent';
        buttonContainer.style.boxShadow = 'none';
        buttonContainer.style.borderRadius = '4px';

        // 添加所有未隐藏的文件夹按钮
        buttonConfig.folderOrder.forEach((name) => {
            const config = buttonConfig.folders[name];
            if (config && !config.hidden) { // 只显示未隐藏的文件夹
                const folderButton = createFolderButton(name, config);
                buttonContainer.appendChild(folderButton);
            }
        });

        // 按顺序添加功能按钮
        // 现在所有工具按钮都在 '🖱️' 文件夹内,不再直接添加
        // 仅添加设置和清空按钮
        buttonContainer.appendChild(createSettingsButton());
        buttonContainer.appendChild(createClearButton());

        // 初始记录 paddingY,确保偏移计算有默认值
        buttonContainer.dataset.barPaddingY = '6';
        applyBarBottomSpacing(
            buttonContainer,
            buttonConfig.buttonBarBottomSpacing,
            buttonConfig.buttonBarBottomSpacing
        );

        return buttonContainer;
    };

    const updateButtonContainer = () => {
        const root = getShadowRoot();
        let existingContainer = root ? root.querySelector('.folder-buttons-container') : null;
        if (existingContainer) {
            // 保存所有功能按钮的引用
            const settingsButton = existingContainer.querySelector('button:nth-last-child(2)');
            const clearButton = existingContainer.querySelector('button:last-child');

            // 清空容器
            setTrustedHTML(existingContainer, '');

            // 重新添加未隐藏的文件夹按钮
            buttonConfig.folderOrder.forEach((name) => {
                const config = buttonConfig.folders[name];
                if (config && !config.hidden) { // 只显示未隐藏的文件夹
                    const folderButton = createFolderButton(name, config);
                    existingContainer.appendChild(folderButton);
                }
            });

            // 按正确顺序重新添加功能按钮
            if (settingsButton) existingContainer.appendChild(settingsButton);
            if (clearButton) existingContainer.appendChild(clearButton);

            console.log("✅ 按钮栏已更新(已过滤隐藏文件夹)。");
        } else {
            console.warn("⚠️ 未找到按钮容器,无法更新按钮栏。");
        }
        try {
            applyDomainStyles();
        } catch (err) {
            console.warn('应用域名样式失败:', err);
        }
    };

    const attachButtonsToTextarea = (textarea) => {
        // 仅附加一次按钮容器
        let buttonContainer = queryUI('.folder-buttons-container');
        if (!buttonContainer) {
            buttonContainer = createButtonContainer();
            // 插入按钮容器到 textarea 的父元素之后
            // 根据ChatGPT的DOM结构,可能需要调整插入位置
            // textarea.parentElement.insertBefore(buttonContainer, textarea.nextSibling);
            // console.log("✅ 按钮容器已附加到 textarea 元素。");
            appendToMainLayer(buttonContainer);
            // 创建后立即根据域名样式调整高度/注入CSS
            try { applyDomainStyles(); } catch (_) {}
            console.log("✅ 按钮容器已固定到窗口底部。");
        } else {
            console.log("ℹ️ 按钮容器已存在,跳过附加。");
        }
        textarea.addEventListener('contextmenu', (e) => {
            e.preventDefault();
        });
    };

    let attachTimeout;
    const attachButtons = () => {
        if (attachTimeout) clearTimeout(attachTimeout);
        attachTimeout = setTimeout(() => {
            const textareas = getAllTextareas();
            console.log(`🔍 扫描到 ${textareas.length} 个 textarea 或 contenteditable 元素。`);
            if (textareas.length === 0) {
                console.warn("⚠️ 未找到任何 textarea 或 contenteditable 元素。");
                return;
            }
            attachButtonsToTextarea(textareas[textareas.length - 1]);
            console.log("✅ 按钮已附加到最新的 textarea 或 contenteditable 元素。");
        }, 300);
    };

    const observeShadowRoots = (node) => {
        if (node.shadowRoot) {
            const shadowObserver = new MutationObserver(() => {
                attachButtons();
            });
            shadowObserver.observe(node.shadowRoot, {
                childList: true,
                subtree: true,
            });
            node.shadowRoot.querySelectorAll('*').forEach(child => observeShadowRoots(child));
        }
    };

    const clampBarSpacingValue = (value, fallback = 0) => {
        const parsed = Number(value);
        if (Number.isFinite(parsed)) {
            return Math.max(-200, Math.min(200, parsed));
        }
        const fallbackParsed = Number(fallback);
        if (Number.isFinite(fallbackParsed)) {
            return Math.max(-200, Math.min(200, fallbackParsed));
        }
        return 0;
    };

    const applyBarBottomSpacing = (container, spacing, fallbackSpacing = 0) => {
        if (!container) return 0;
        const desiredSpacing = clampBarSpacingValue(spacing, fallbackSpacing);
        const paddingY = Number(container.dataset.barPaddingY) || 0;
        const adjustedBottom = desiredSpacing - paddingY;
        container.style.transform = 'translateY(0)';
        container.style.bottom = `${adjustedBottom}px`;
        container.dataset.barBottomSpacing = String(desiredSpacing);
        return desiredSpacing;
    };

    // 根据目标高度调整底部按钮栏的布局和内部按钮尺寸
    updateButtonBarLayout = (container, targetHeight) => {
        if (!container) return;
        const numericHeight = Number(targetHeight);
        if (!Number.isFinite(numericHeight) || numericHeight <= 0) return;

        const barHeight = Math.max(32, Math.round(numericHeight));
        const scale = Math.max(0.6, Math.min(2.5, barHeight / 40));

        const paddingYBase = Math.round(6 * scale);
        const paddingYMax = Math.max(4, Math.floor((barHeight - 24) / 2));
        const paddingY = Math.min(Math.max(4, Math.min(20, paddingYBase)), paddingYMax);
        const paddingX = Math.max(12, Math.min(48, Math.round(15 * scale)));
        const gapSize = Math.max(6, Math.min(28, Math.round(10 * scale)));

        container.style.padding = `${paddingY}px ${paddingX}px`;
        container.style.gap = `${gapSize}px`;

        const innerHeight = Math.max(20, barHeight - paddingY * 2);
        const fontSize = Math.max(12, Math.min(22, Math.round(14 * scale)));
        let verticalPadding = Math.max(4, Math.min(18, Math.round(6 * scale)));
        const maxVerticalPadding = Math.max(4, Math.floor((innerHeight - fontSize) / 2));
        if (verticalPadding > maxVerticalPadding) {
            verticalPadding = Math.max(4, maxVerticalPadding);
        }
        const horizontalPadding = Math.max(12, Math.min(56, Math.round(12 * scale)));
        const borderRadius = Math.max(4, Math.min(20, Math.round(4 * scale)));
        const lineHeight = Math.max(fontSize + 2, innerHeight - verticalPadding * 2);

        const buttons = Array.from(container.children).filter(node => node.tagName === 'BUTTON');
        buttons.forEach(btn => {
            btn.style.minHeight = `${innerHeight}px`;
            btn.style.height = `${innerHeight}px`;
            btn.style.padding = `${verticalPadding}px ${horizontalPadding}px`;
            btn.style.fontSize = `${fontSize}px`;
            btn.style.borderRadius = `${borderRadius}px`;
            btn.style.lineHeight = `${lineHeight}px`;
            if (!btn.style.display) btn.style.display = 'inline-flex';
            if (!btn.style.alignItems) btn.style.alignItems = 'center';
        });

        container.dataset.barHeight = String(barHeight);
        container.dataset.barPaddingY = String(verticalPadding);
    };

    // 应用当前域名样式(高度 + 自定义 CSS),可在多处复用
    applyDomainStyles = () => {
        try {
            const container = queryUI('.folder-buttons-container');
            const currentHost = window.location.hostname || '';
            // 若容器未创建,先跳过
            if (!container) return;

            const fallbackSpacing = clampBarSpacingValue(
                typeof buttonConfig.buttonBarBottomSpacing === 'number'
                    ? buttonConfig.buttonBarBottomSpacing
                    : (defaultConfig && typeof defaultConfig.buttonBarBottomSpacing === 'number'
                        ? defaultConfig.buttonBarBottomSpacing
                        : 0)
            );

            // 清理当前域名下已注入的旧样式,避免重复叠加
            try {
                document.querySelectorAll('style[data-domain-style]').forEach(el => {
                    const d = el.getAttribute('data-domain-style') || '';
                    if (d && currentHost.includes(d)) {
                        el.remove();
                    }
                });
            } catch (e) {
                console.warn('清理旧样式失败:', e);
            }

            const matchedStyle = (buttonConfig.domainStyleSettings || []).find(s => s && currentHost.includes(s.domain));
            if (matchedStyle) {
                // 1) 按域名样式设置按钮栏高度
                const clamped = Math.min(200, Math.max(20, matchedStyle.height || buttonConfig.buttonBarHeight || (defaultConfig && defaultConfig.buttonBarHeight) || 40));
                container.style.height = clamped + 'px';
                updateButtonBarLayout(container, clamped);
                console.log(`✅ 已根据 ${matchedStyle.name} 设置按钮栏高度:${clamped}px`);
                applyBarBottomSpacing(container, matchedStyle.bottomSpacing, fallbackSpacing);

                // 2) 注入自定义 CSS(若有)
                if (matchedStyle.cssCode) {
                    const styleEl = document.createElement('style');
                    styleEl.setAttribute('data-domain-style', matchedStyle.domain);
                    styleEl.textContent = matchedStyle.cssCode;
                    document.head.appendChild(styleEl);
                    console.log(`✅ 已注入自定义CSS至 <head> 来自:${matchedStyle.name}`);
                }
            } else {
                // 未匹配到样式时,回退到全局按钮栏高度
                const fallback = (buttonConfig && typeof buttonConfig.buttonBarHeight === 'number')
                    ? buttonConfig.buttonBarHeight
                    : (defaultConfig && defaultConfig.buttonBarHeight) || 40;
                const clampedDefault = Math.min(200, Math.max(20, fallback));
                container.style.height = clampedDefault + 'px';
                updateButtonBarLayout(container, clampedDefault);
                console.log(`ℹ️ 未匹配到样式规则,使用默认按钮栏高度:${clampedDefault}px`);
                applyBarBottomSpacing(container, fallbackSpacing, fallbackSpacing);
            }
        } catch (err) {
            console.warn('应用域名样式时出现问题:', err);
        }
    };

    const initialize = () => {
        attachButtons();
        const observer = new MutationObserver((mutations) => {
            let triggered = false;
            mutations.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach((node) => {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            observeShadowRoots(node);
                            triggered = true;
                        }
                    });
                }
            });
            if (triggered) {
                attachButtons();
                console.log("🔔 DOM 发生变化,尝试重新附加按钮。");
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
        });
        console.log("🔔 MutationObserver 已启动,监听 DOM 变化。");

        // 先尝试一次;再延迟一次,保证容器创建完成后也能生效
        try { applyDomainStyles(); } catch (_) {}
        setTimeout(() => { try { applyDomainStyles(); } catch (_) {} }, 350);
    };

    window.addEventListener('load', () => {
        console.log("⏳ 页面已完全加载,开始初始化脚本。");
        initialize();
    });

    // 动态更新样式以适应主题变化
    const updateStylesOnThemeChange = () => {
        // Since we're using CSS variables, the styles are updated automatically
        // Just update the button container to apply new styles
        updateButtonContainer();
        // 重新应用一次域名样式,防止主题切换后高度或注入样式丢失
        try { applyDomainStyles(); } catch (_) {}
    };

    // Initial setting of CSS variables
    setCSSVariables(getCurrentTheme());
})();