🐱 全世界都要变成可爱猫猫!增强版

让整个网络世界都变成超可爱的猫娘语调喵~增强版(优化版)

当前为 2025-08-13 提交的版本,查看 最新版本

// ==UserScript==
// @name         🐱 全世界都要变成可爱猫猫!增强版
// @version      4.2.0
// @description  让整个网络世界都变成超可爱的猫娘语调喵~增强版(优化版)
// @author       超萌猫娘开发队
// @match        *://*/*
// @include      *://*.bilibili.com/video/*
// @include      *://*.bilibili.com/anime/*
// @include      *://*.bilibili.com/bangumi/play/*
// @exclude      *://gf.qytechs.cn/*
// @exclude      *://*.gov/*
// @exclude      *://*.edu/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @license      MIT
// @namespace https://gf.qytechs.cn/users/1503554
// ==/UserScript==

(function() {
    'use strict';

    // ===== 版本管理 =====
    const SCRIPT_VERSION = "4.2.0";
    const isVersionUpdate = GM_getValue("SCRIPT_VERSION") !== SCRIPT_VERSION;
    if (isVersionUpdate) {
        GM_setValue("SCRIPT_VERSION", SCRIPT_VERSION);
        console.log('🎉 猫娘脚本已更新到版本', SCRIPT_VERSION);
    }

    // ===== 增强配置系统 =====
    const defaultConfig = {
        // 性能配置
        performance: {
            processInterval: 5000,
            maxProcessingTimeSlice: 8,
            batchSize: 5,
            observerThrottle: 1000,
            maxRetryAttempts: 10,
            idleCallbackTimeout: 2000,
            debounceDelay: 500
        },

        // 功能开关
        features: {
            affectInput: false,
            bilibiliMergeALinks: true,
            bilibiliRandomizeUserNames: true, // 用户名前缀功能开关
            autoProcessNewContent: true,
            shadowDomSupport: true,
            performanceMonitoring: false,
            debugMode: false,
            smartProcessing: true,
            enableBlacklist: true // 黑名单功能开关
        },

        // 站点配置
        sites: {
            excludeDomains: [
                'github.com', 'stackoverflow.com', 'google.com',
                'gov.cn', 'edu.cn', 'gf.qytechs.cn'
            ],
            bilibili: {
                smartPause: true,
                retryInterval: 1000,
                maxRetryDelay: 5000,
                commentSelector: 'bili-comment-thread-renderer',
                userNameSelector: '#user-name a',
                contentSelector: '#contents span'
            }
        },

        // 黑名单配置
        blacklist: {
            sites: [], // 格式: [{domain: 'example.com', type: 'site'|'page', url: '', expiry: timestamp, reason: ''}]
            defaultDuration: 24 * 60 * 60 * 1000, // 24小时
            enabled: true
        },

        // 快捷键配置
        shortcuts: {
            toggleScript: "100C",
            resetProcessing: "101R",
            showSettings: "100S",
            debugMode: "101D",
            showBlacklist: "100B" // 显示黑名单面板
        },

        // 用户偏好 - 优化描述
        preferences: {
            cuteLevel: 'normal', // low, normal, high
            customEndings: [],
            disabledWords: [],
            processingMode: 'contextual', // gentle(保守替换), contextual(上下文感知), aggressive(积极替换)
            intelligentReplacement: true,
            replacementIntensity: 0.3, // 替换强度 0.1-1.0
            endingFrequency: 0.5, // 结尾词频率 0.1-1.0
            decorativeFrequency: 0.2 // 装饰符频率 0.1-1.0
        },

        // 统计信息
        stats: {
            processedElements: 0,
            replacedWords: 0,
            lastActive: new Date().toISOString(),
            installDate: new Date().toISOString(),
            sessionProcessed: 0,
            blacklistHits: 0 // 黑名单命中次数
        }
    };

    // 加载用户配置
    let userConfig = GM_getValue("catgirlConfig") || {};
    let CONFIG = Object.assign({}, defaultConfig, userConfig);

    // 如果是版本更新,合并新配置
    if (isVersionUpdate) {
        CONFIG = Object.assign(defaultConfig, userConfig);
        GM_setValue("catgirlConfig", CONFIG);
        showUpdateNotification();
    }

    // ===== 扩展的可爱元素库 =====
    const cuteLibrary = {
        endings: {
            low: ['喵', '呢', '哦', '啊'],
            normal: ['喵~', 'にゃん', '喵呜', 'nya~', '喵喵', '呢~'],
            high: ['喵~♪', 'にゃん♡', '喵呜~', 'nya~♡', '喵喵desu', 'にゃ♡', 'mew~', '喵♪', 'nyaa~', '喵desu~', '喵呢~', '喵哈~']
        },

        userPrefixes: ['🏳️‍⚧️', '✨', '💕', '🌸', '🎀', '🌟'],
        decorativePrefixes: ['✨', '💫', '⭐', '🌸', '🎀', '💝'],

        emotionalEndings: {
            excited: ['喵!', 'にゃん!', '哇喵~', '好棒喵~'],
            calm: ['喵~', '呢~', '嗯喵', '是这样喵'],
            happy: ['开心喵~', '嘻嘻喵', '哈哈喵~', '好开心喵'],
            confused: ['诶喵?', '嗯?喵', '咦喵~', '不懂喵'],
            sad: ['呜呜喵', '难过喵', '555喵', '想哭喵']
        }
    };

    // ===== 黑名单管理器 =====
    class BlacklistManager {
        constructor() {
            this.panel = null;
            this.isVisible = false;
        }

        isBlacklisted() {
            if (!CONFIG.blacklist.enabled) return false;

            const currentDomain = location.hostname;
            const currentUrl = location.href;
            const now = Date.now();

            for (const item of CONFIG.blacklist.sites) {
                // 检查是否过期
                if (item.expiry && item.expiry < now) {
                    this.removeExpiredItem(item);
                    continue;
                }

                // 检查域名匹配
                if (item.type === 'site' && currentDomain.includes(item.domain)) {
                    CONFIG.stats.blacklistHits++;
                    return true;
                }

                // 检查页面匹配
                if (item.type === 'page' && currentUrl === item.url) {
                    CONFIG.stats.blacklistHits++;
                    return true;
                }
            }

            return false;
        }

        addToBlacklist(type, duration, reason = '') {
            const now = Date.now();
            const expiry = duration === -1 ? null : now + duration;

            const item = {
                id: this.generateId(),
                domain: location.hostname,
                url: type === 'page' ? location.href : '',
                type: type,
                expiry: expiry,
                reason: reason,
                addedAt: now
            };

            CONFIG.blacklist.sites.push(item);
            GM_setValue("catgirlConfig", CONFIG);

            const durationText = duration === -1 ? '永久' : this.formatDuration(duration);
            const typeText = type === 'site' ? '整站' : '单页面';
            showToast(`已将${typeText}加入黑名单 (${durationText})`, 'success');
        }

        removeFromBlacklist(id) {
            CONFIG.blacklist.sites = CONFIG.blacklist.sites.filter(item => item.id !== id);
            GM_setValue("catgirlConfig", CONFIG);
            this.updateDisplay();
            showToast('已从黑名单移除', 'success');
        }

        removeExpiredItem(item) {
            CONFIG.blacklist.sites = CONFIG.blacklist.sites.filter(i => i.id !== item.id);
            GM_setValue("catgirlConfig", CONFIG);
        }

        generateId() {
            return Date.now().toString(36) + Math.random().toString(36).substr(2);
        }

        formatDuration(ms) {
            if (ms === -1) return '永久';
            const days = Math.floor(ms / (24 * 60 * 60 * 1000));
            const hours = Math.floor((ms % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
            if (days > 0) return `${days}天${hours}小时`;
            if (hours > 0) return `${hours}小时`;
            return '不到1小时';
        }

        show() {
            if (!this.panel) this.create();
            this.panel.style.display = 'block';
            this.isVisible = true;
            this.updateDisplay();
        }

        hide() {
            if (this.panel) {
                this.panel.style.display = 'none';
                this.isVisible = false;
            }
        }

        create() {
            if (this.panel) return;

            this.panel = document.createElement('div');
            this.panel.id = 'catgirl-blacklist';
            this.panel.innerHTML = this.getHTML();
            this.panel.style.cssText = this.getCSS();

            document.body.appendChild(this.panel);
            this.bindEvents();
        }

        getHTML() {
            return `
                <div class="blacklist-header">
                    <h3>🚫 网站黑名单管理</h3>
                    <button class="close-btn" data-action="close">×</button>
                </div>

                <div class="blacklist-content">
                    <div class="current-site-section">
                        <h4>🌐 当前网站操作</h4>
                        <div class="current-site-info">
                            <strong>域名:</strong> <code>${location.hostname}</code><br>
                            <strong>页面:</strong> <code>${location.pathname}</code>
                        </div>

                        <div class="blacklist-actions">
                            <div class="action-group">
                                <label>拉黑类型:</label>
                                <select id="blacklist-type">
                                    <option value="site">整个网站</option>
                                    <option value="page">仅当前页面</option>
                                </select>
                            </div>

                            <div class="action-group">
                                <label>拉黑时长:</label>
                                <select id="blacklist-duration">
                                    <option value="3600000">1小时</option>
                                    <option value="21600000">6小时</option>
                                    <option value="86400000">1天</option>
                                    <option value="604800000">1周</option>
                                    <option value="2592000000">1个月</option>
                                    <option value="-1">永久</option>
                                </select>
                            </div>

                            <div class="action-group">
                                <label>拉黑原因:</label>
                                <input type="text" id="blacklist-reason" placeholder="可选,记录拉黑原因">
                            </div>

                            <button id="add-to-blacklist" class="btn-danger">🚫 加入黑名单</button>
                        </div>
                    </div>

                    <div class="blacklist-section">
                        <h4>📋 黑名单列表</h4>
                        <div id="blacklist-items"></div>
                        <div class="blacklist-stats">
                            <small>黑名单命中次数: <span id="blacklist-hits">${CONFIG.stats.blacklistHits}</span></small>
                        </div>
                    </div>

                    <div class="blacklist-settings">
                        <h4>⚙️ 黑名单设置</h4>
                        <label>
                            <input type="checkbox" id="enable-blacklist" ${CONFIG.blacklist.enabled ? 'checked' : ''}>
                            启用黑名单功能
                        </label>
                    </div>

                    <div class="actions">
                        <button id="save-blacklist" class="btn-primary">💾 保存设置</button>
                        <button id="clear-expired" class="btn-secondary">🧹 清理过期</button>
                    </div>
                </div>
            `;
        }

        getCSS() {
            return `
                position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
                width: 600px; max-height: 80vh; background: #ffffff; border-radius: 12px;
                box-shadow: 0 8px 32px rgba(0,0,0,0.3); z-index: 10000;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                display: none; overflow-y: auto;
            `;
        }

        bindEvents() {
            // 关闭按钮
            this.panel.querySelector('[data-action="close"]').onclick = () => this.hide();

            // 添加到黑名单
            document.getElementById('add-to-blacklist').onclick = () => {
                const type = document.getElementById('blacklist-type').value;
                const duration = parseInt(document.getElementById('blacklist-duration').value);
                const reason = document.getElementById('blacklist-reason').value;

                this.addToBlacklist(type, duration, reason);
                this.updateDisplay();
            };

            // 保存设置
            document.getElementById('save-blacklist').onclick = () => {
                CONFIG.blacklist.enabled = document.getElementById('enable-blacklist').checked;
                GM_setValue("catgirlConfig", CONFIG);
                showToast('黑名单设置已保存', 'success');
            };

            // 清理过期
            document.getElementById('clear-expired').onclick = () => {
                this.clearExpired();
            };
        }

        updateDisplay() {
            const container = document.getElementById('blacklist-items');
            if (!container) return;

            const now = Date.now();
            const items = CONFIG.blacklist.sites.map(item => {
                const isExpired = item.expiry && item.expiry < now;
                const timeLeft = item.expiry ? this.formatDuration(item.expiry - now) : '永久';
                const addedAt = new Date(item.addedAt).toLocaleString();

                return `
                    <div class="blacklist-item ${isExpired ? 'expired' : ''}">
                        <div class="item-info">
                            <div class="item-domain">${item.domain}</div>
                            <div class="item-details">
                                类型: ${item.type === 'site' ? '整站' : '单页面'} |
                                剩余: ${isExpired ? '已过期' : timeLeft} |
                                添加: ${addedAt}
                                ${item.reason ? `<br>原因: ${item.reason}` : ''}
                            </div>
                        </div>
                        <button onclick="window.catgirlApp.blacklistManager.removeFromBlacklist('${item.id}')"
                                class="remove-btn">移除</button>
                    </div>
                `;
            }).join('');

            container.innerHTML = items || '<div class="empty-state">暂无黑名单项目</div>';

            // 更新统计
            const hitsEl = document.getElementById('blacklist-hits');
            if (hitsEl) hitsEl.textContent = CONFIG.stats.blacklistHits;
        }

        clearExpired() {
            const now = Date.now();
            const before = CONFIG.blacklist.sites.length;
            CONFIG.blacklist.sites = CONFIG.blacklist.sites.filter(item =>
                !item.expiry || item.expiry > now
            );
            const after = CONFIG.blacklist.sites.length;
            const removed = before - after;

            GM_setValue("catgirlConfig", CONFIG);
            this.updateDisplay();
            showToast(`已清理 ${removed} 个过期项目`, 'success');
        }
    }

    // ===== 防抖工具类 =====
    class DebounceUtils {
        static debounce(func, delay) {
            let timeoutId;
            return function (...args) {
                clearTimeout(timeoutId);
                timeoutId = setTimeout(() => func.apply(this, args), delay);
            };
        }

        static throttleWithDebounce(func, throttleMs, debounceMs) {
            let lastCallTime = 0;
            let debounceTimer;

            return function (...args) {
                const now = Date.now();
                clearTimeout(debounceTimer);

                if (now - lastCallTime >= throttleMs) {
                    lastCallTime = now;
                    func.apply(this, args);
                } else {
                    debounceTimer = setTimeout(() => {
                        lastCallTime = Date.now();
                        func.apply(this, args);
                    }, debounceMs);
                }
            };
        }
    }

    // ===== 增强的性能工具类 =====
    class EnhancedPerformanceUtils {
        static createTimeSliceProcessor(items, processor, options = {}) {
            const {
                batchSize = CONFIG.performance.batchSize,
                maxTime = CONFIG.performance.maxProcessingTimeSlice,
                onProgress = null,
                onComplete = null
            } = options;

            const processedKeys = new Set();
            const uniqueItems = items.filter(item => {
                const key = this.getItemKey(item);
                if (processedKeys.has(key)) return false;
                processedKeys.add(key);
                return true;
            });

            if (uniqueItems.length === 0) {
                if (onComplete) onComplete();
                return;
            }

            let index = 0;
            let startTime = Date.now();

            const processNextBatch = () => {
                const batchStartTime = performance.now();
                let processedInBatch = 0;

                while (index < uniqueItems.length &&
                       processedInBatch < batchSize &&
                       (performance.now() - batchStartTime) < maxTime) {

                    try {
                        processor(uniqueItems[index], index, uniqueItems);
                    } catch (error) {
                        console.error('🐱 处理项目出错:', error);
                    }

                    index++;
                    processedInBatch++;
                }

                if (onProgress) {
                    onProgress(index, uniqueItems.length, (index / uniqueItems.length) * 100);
                }

                if (index < uniqueItems.length) {
                    if (window.requestIdleCallback) {
                        requestIdleCallback(processNextBatch, {
                            timeout: CONFIG.performance.idleCallbackTimeout
                        });
                    } else {
                        setTimeout(processNextBatch, 16);
                    }
                } else {
                    const duration = Date.now() - startTime;
                    if (CONFIG.features.debugMode) {
                        console.log(`🎉 完成处理 ${uniqueItems.length} 个项目,耗时 ${duration}ms`);
                    }
                    if (onComplete) onComplete();
                }
            };

            processNextBatch();
        }

        static getItemKey(item) {
            if (item && item.nodeType === Node.ELEMENT_NODE) {
                return `${item.tagName}-${item.textContent ? item.textContent.slice(0, 20) : ''}-${item.offsetTop || 0}`;
            }
            return String(item);
        }
    }

    // ===== 状态管理类 =====
    class StateManager {
        constructor() {
            this.state = {
                isEnabled: true,
                currentUrl: location.href,
                processingQueue: new Set(),
                urlChangeHandlers: [],
                lastProcessTime: 0,

                bilibili: {
                    isCompleted: false,
                    lastProcessedUrl: '',
                    lastProcessedTime: 0,
                    retryCount: 0,
                    commentObserver: null,
                    lastCommentCount: 0
                }
            };
        }

        onUrlChange(handler) {
            if (!this.state.urlChangeHandlers) {
                this.state.urlChangeHandlers = [];
            }
            this.state.urlChangeHandlers.push(handler);
        }

        checkUrlChange() {
            const newUrl = location.href;
            if (newUrl !== this.state.currentUrl) {
                if (CONFIG.features.debugMode) {
                    console.log('🔄 页面切换:', this.state.currentUrl, '->', newUrl);
                }
                this.state.currentUrl = newUrl;

                this.state.bilibili.isCompleted = false;
                this.state.bilibili.lastProcessedUrl = newUrl;
                this.state.bilibili.retryCount = 0;
                this.state.bilibili.lastCommentCount = 0;

                if (this.state.urlChangeHandlers && Array.isArray(this.state.urlChangeHandlers)) {
                    this.state.urlChangeHandlers.forEach(handler => {
                        try {
                            if (typeof handler === 'function') {
                                handler(newUrl);
                            }
                        } catch (error) {
                            console.error('🐱 URL变化处理器出错:', error);
                        }
                    });
                }

                return true;
            }
            return false;
        }

        shouldProcess() {
            const now = Date.now();
            const timeSinceLastProcess = now - this.state.lastProcessTime;

            if (timeSinceLastProcess < 1000) {
                return false;
            }

            this.state.lastProcessTime = now;
            return true;
        }

        shouldSkipBilibiliProcessing() {
            if (!this.isBilibili()) return true;

            const { isCompleted, lastProcessedUrl, lastProcessedTime } = this.state.bilibili;
            const now = Date.now();

            return isCompleted &&
                lastProcessedUrl === location.href &&
                (now - lastProcessedTime) < 30000;
        }

        markBilibiliCompleted() {
            this.state.bilibili.isCompleted = true;
            this.state.bilibili.lastProcessedUrl = location.href;
            this.state.bilibili.lastProcessedTime = Date.now();
        }

        isBilibili() {
            return location.hostname.includes('bilibili.com');
        }

        checkBilibiliCommentChange() {
            if (!this.isBilibili()) return false;

            const commentThreads = document.querySelectorAll('bili-comment-thread-renderer');
            const currentCount = commentThreads.length;

            if (currentCount !== this.state.bilibili.lastCommentCount) {
                this.state.bilibili.lastCommentCount = currentCount;
                this.state.bilibili.isCompleted = false;
                return true;
            }

            return false;
        }
    }

    // ===== 增强的文本处理器 =====
    class EnhancedTextProcessor {
        constructor() {
            this.processedTexts = new Set();
            this.replacementStats = new Map();
            this.contextAnalyzer = new ContextAnalyzer();
        }

        isProcessed(text) {
            return /喵[~~呜哈呢♪♡!]|nya|にゃん|meow|🏳️‍⚧️|已处理标记/i.test(text) ||
                this.processedTexts.has(text);
        }

        getCuteEnding(context = 'normal') {
            const level = CONFIG.preferences.cuteLevel;
            const mode = CONFIG.preferences.processingMode;

            let endings = cuteLibrary.endings[level] || cuteLibrary.endings.normal;

            switch (mode) {
                case 'gentle':
                    endings = endings.slice(0, Math.ceil(endings.length / 2));
                    break;
                case 'aggressive':
                    endings = [...endings, ...cuteLibrary.emotionalEndings[context] || []];
                    break;
                case 'contextual':
                default:
                    if (cuteLibrary.emotionalEndings[context]) {
                        endings = [...endings, ...cuteLibrary.emotionalEndings[context]];
                    }
                    break;
            }

            return endings[Math.floor(Math.random() * endings.length)];
        }

        analyzeContext(text) {
            const excitedMarkers = /[!!??]{2,}|哇|呀|啊{2,}/;
            const happyMarkers = /笑|哈哈|嘻嘻|开心|快乐|爽|棒/;
            const sadMarkers = /哭|难过|伤心|555|呜呜|痛苦/;
            const angryMarkers = /生气|愤怒|气死|烦|讨厌|恶心/;
            const confusedMarkers = /[??]{2,}|什么|啥|诶|咦|奇怪/;

            if (excitedMarkers.test(text)) return 'excited';
            if (happyMarkers.test(text)) return 'happy';
            if (sadMarkers.test(text)) return 'sad';
            if (angryMarkers.test(text)) return 'excited';
            if (confusedMarkers.test(text)) return 'confused';
            if (/[。.,,;;]/.test(text)) return 'calm';

            return 'normal';
        }

        processText(text, options = {}) {
            if (!text?.trim() || this.isProcessed(text)) return text;

            if (CONFIG.preferences.disabledWords.some(word => text.includes(word))) {
                return text;
            }

            this.processedTexts.add(text);

            let result = text;
            let replacementCount = 0;

            const context = this.analyzeContext(text);
            const cleanups = this.getCleanupRules(context);

            cleanups.forEach(([regex, replacement]) => {
                const matches = result.match(regex);
                if (matches) {
                    const finalReplacement = this.getSmartReplacement(replacement, context);
                    result = result.replace(regex, finalReplacement);
                    replacementCount += matches.length;
                }
            });

            if (CONFIG.preferences.processingMode !== 'gentle' || replacementCount > 0) {
                result = this.addCuteEndings(result, context);
            }

            if (CONFIG.preferences.processingMode === 'aggressive' &&
                Math.random() < CONFIG.preferences.decorativeFrequency) {
                const prefix = cuteLibrary.decorativePrefixes[Math.floor(Math.random() * cuteLibrary.decorativePrefixes.length)];
                result = `${prefix} ${result}`;
            }

            if (replacementCount > 0) {
                CONFIG.stats.replacedWords += replacementCount;
                CONFIG.stats.sessionProcessed += replacementCount;
                this.updateReplacementStats(text, result);
            }

            return result;
        }

        getSmartReplacement(baseReplacement, context) {
            if (!CONFIG.preferences.intelligentReplacement) return baseReplacement;

            const contextEnding = cuteLibrary.emotionalEndings[context];
            if (contextEnding && Math.random() < 0.4) {
                const ending = contextEnding[Math.floor(Math.random() * contextEnding.length)];
                return `${baseReplacement}${ending}`;
            }

            return baseReplacement;
        }

        addCuteEndings(text, context = 'normal') {
            const getCuteEnding = () => this.getCuteEnding(context);
            const addDesu = () => {
                const chance = CONFIG.preferences.cuteLevel === 'high' ? 0.4 :
                CONFIG.preferences.cuteLevel === 'normal' ? 0.2 : 0.1;
                return Math.random() < chance ? 'です' : '';
            };

            let probability = CONFIG.preferences.endingFrequency;
            switch (CONFIG.preferences.processingMode) {
                case 'gentle':
                    probability *= 0.5;
                    break;
                case 'aggressive':
                    probability *= 2;
                    break;
            }

            return text
                .replace(/([也矣兮乎者焉哉]|[啊吗呢吧哇呀哦嘛喔咯呜捏])([\s\p{P}]|$)/gu,
                         (_, $1, $2) => `${getCuteEnding()}${addDesu()}${$2}`)
                .replace(/([的了辣])([\s\p{P}]|$)/gu,
                         (_, $1, $2) => Math.random() < probability ?
                         `${$1}${getCuteEnding()}${addDesu()}${$2}` : `${$1}${$2}`);
        }

        // ===== 大幅扩展的清理规则 - 针对B站和百度贴吧 =====
        getCleanupRules(context = 'normal') {
            const baseRules = [
                // ===== 极端攻击与侮辱性词汇 =====
                [/操你妈|操你娘|操你全家|肏你妈|干你妈|干你娘|去你妈的|去你娘的|去你全家/gi, '去睡觉觉'],
                [/妈了个?逼|妈的?智障|妈的/gi, '喵喵喵'],
                [/狗娘养的|狗杂种|狗东西|狗逼|狗比/gi, '不太好的小家伙'],
                [/操你大爷|去你大爷的|你大爷的/gi, '去玩耍啦'],
                [/去你老师的|你全家死光|你妈死了|你妈没了/gi, '嗯...安静一点'],
                [/你妈妈叫你回家吃饭|你妈炸了/gi, '你妈妈叫你回家吃饭'],

                // ===== 性相关及不雅词汇 =====
                [/鸡巴|鸡叭|鸡把|屌|吊|\bjb\b|\bJB\b|\bJj\b/gi, '小鱼干'],
                [/逼你|逼样|逼毛|逼崽子|什么逼|傻逼|煞逼|沙逼|装逼|牛逼|吹逼/gi, '小淘气'],
                [/肏|干你|草你|cao你|cao你妈|操逼|日你|日了|艹你/gi, '去玩耍啦'],
                [/生殖器|阴茎|阴道|性器官|做爱|啪啪|上床|嘿咻/gi, '小秘密'],

                // ===== B站特色脏话 =====
                [/小鬼|小学生|初中生|孤儿|没爹|没妈|爹妈死了/gi, '小朋友'],
                [/死妈|死全家|死开|去死|死了算了/gi, '去睡觉觉'],
                [/脑瘫|弱智|智障|残疾|白痴|傻子|蠢货|蠢蛋/gi, '小糊涂虫'],
                [/废物|废柴|废狗|垃圾|拉圾|辣鸡|人渣|渣渣/gi, '要抱抱的小家伙'],
                [/恶心|想吐|反胃|讨厌死了|烦死了/gi, '有点不开心'],

                // ===== 百度贴吧常见脏话 =====
                [/楼主是猪|楼主智障|楼主有病|lz有毒|楼主滚|lz滚/gi, '楼主很可爱'],
                [/水贴|灌水|刷屏|占楼|抢沙发|前排|火钳刘明/gi, '路过留名'],
                [/举报了|封号|删帖|水军|托儿|五毛|美分/gi, '认真讨论中'],
                [/撕逼|掐架|开撕|互喷|对骂|群嘲/gi, '友好交流'],

                // ===== 网络用语和缩写 =====
                [/\bcnm\b|\bCNM\b|c\s*n\s*m/gi, '你好软糯'],
                [/\bnmsl\b|\bNMSL\b|n\s*m\s*s\s*l/gi, '你超棒棒'],
                [/\bmlgb\b|\bMLGB\b|m\s*l\s*g\s*b/gi, '哇好厉害'],
                [/tmd|TMD|t\s*m\s*d|他妈的/gi, '太萌啦'],
                [/wtf|WTF|w\s*t\s*f|what\s*the\s*fuck/gi, '哇好神奇'],
                [/\bf\*\*k|\bf\*ck|fuck|\bFC\b|\bF\*\b/gi, '哇哦'],
                [/\bsh\*t|shit|\bs\*\*t/gi, '小意外'],
                [/\bbitch|\bb\*tch|\bb\*\*\*\*/gi, '小坏蛋'],

                // ===== 地域攻击相关 =====
                [/河南人|东北人|农村人|乡下人|山沟里|土包子/gi, '各地朋友'],
                [/北上广|屌丝|土豪|装富|穷逼|没钱|破产/gi, '普通人'],

                // ===== 游戏相关脏话 =====
                [/菜鸡|菜逼|坑货|坑爹|坑队友|演员|挂逼|开挂/gi, '游戏新手'],
                [/noob|萌新杀手|虐菜|吊打|碾压|秒杀/gi, '游戏高手'],

                // ===== 饭圈和明星相关 =====
                [/黑粉|脑残粉|私生饭|蹭热度|营销号|炒作|塌房/gi, '追星族'],
                [/爬|滚|死开|别来|有毒|拉黑|取关/gi, '不太喜欢'],

                // ===== 学历和职业攻击 =====
                [/小学毕业|没文化|文盲|初中肄业|高中都没毕业/gi, '正在学习中'],
                [/打工仔|搬砖|送外卖|快递员|保安|清洁工/gi, '勤劳的人'],

                // ===== 年龄相关攻击 =====
                [/老不死|老东西|老头子|老太婆|更年期|中年油腻/gi, '年长者'],
                [/熊孩子|小屁孩|幼稚|没长大|巨婴/gi, '年轻朋友'],

                // ===== 外貌身材攻击 =====
                [/丑逼|长得丑|颜值低|矮子|胖子|瘦猴|秃头|光头/gi, '独特的人'],
                [/整容|假脸|网红脸|蛇精脸|锥子脸/gi, '美丽的人'],

                // ===== 常见口头禅和语气词 =====
                [/我靠|我擦|我操|卧槽|握草|我草|尼玛|你妹/gi, '哇哦'],
                [/妈蛋|蛋疼|扯蛋|完蛋|滚蛋|鸡蛋|咸蛋/gi, '天哪'],
                [/见鬼|见了鬼|活见鬼|撞鬼了/gi, '好奇怪'],

                // ===== 网络流行语 =====
                [/笑死我了|笑死|xswl|XSWL|笑尿了/gi, '好有趣'],
                [/绝绝子|yyds|YYDS|永远的神|真香|真tm香/gi, '超级棒棒'],
                [/emo了|emo|EMO|破防了|破大防|血压高/gi, '有点难过'],
                [/社死|社会性死亡|尴尬死了|丢人现眼/gi, '有点害羞'],

                // ===== B站弹幕常见词汇 =====
                [/前方高能|高能预警|非战斗人员撤离|前排吃瓜/gi, '注意啦'],
                [/弹幕护体|弹幕保护|人类的本质|复读机/gi, '大家一起说'],
                [/鬼畜|魔性|洗脑|单曲循环|dssq|DSSQ/gi, '很有趣'],

                // ===== 百度贴吧表情包文字 =====
                [/滑稽|斜眼笑|狗头保命|手动狗头|\[狗头\]|\[滑稽\]/gi, '嘿嘿嘿'],
                [/微笑|呵呵|嘿嘿|嘻嘻|哈哈|哈哈哈/gi, '开心笑'],

                // ===== 政治敏感和争议话题 =====
                [/五毛党|美分党|公知|带路党|精神外国人|慕洋犬/gi, '不同观点的人'],
                [/粉红|小粉红|战狼|玻璃心|民族主义/gi, '爱国人士'],

                // ===== 其他常见不当用词 =====
                [/有病|脑子有问题|神经病|精神病|疯子|疯了/gi, '想法特别'],
                [/你有毒|有毒|中毒了|下毒|毒瘤/gi, '很特殊'],
                [/癌症|艾滋|梅毒|性病|传染病/gi, '不舒服'],
                [/自杀|跳楼|上吊|服毒|割腕/gi, '要好好的']
            ];

            // 根据可爱程度调整规则严格度
            if (CONFIG.preferences.cuteLevel === 'high') {
                // 高可爱程度下添加更多轻微词汇的替换
                const extraRules = [
                    [/靠|擦|草|淦|艹/gi, '哎呀'],
                    [/烦|闷|郁闷|无聊|没劲/gi, '有点小情绪'],
                    [/累|疲惫|困|想睡|犯困/gi, '需要休息'],
                    [/痛|疼|难受|不舒服|头疼/gi, '不太好'],
                    [/怒|生气|愤怒|恼火|火大/gi, '有点不开心'],
                    [/哭|难过|伤心|委屈|想哭/gi, '需要抱抱'],
                    [/怕|害怕|恐惧|担心|紧张/gi, '有点紧张'],
                    [/尴尬|囧|汗|无语|无奈/gi, '有点小尴尬'],
                    [/晕|懵|蒙|糊涂|迷糊/gi, '有点迷茫'],
                    [/急|着急|焦虑|慌|慌张/gi, '有点小急'],
                ];
                baseRules.push(...extraRules);
            }

            // 根据上下文返回不同强度的规则
            return baseRules.map(([regex, replacement]) => {
                const contextEnding = this.getCuteEnding(context);
                return [regex, `${replacement}${contextEnding}`];
            });
        }

        updateReplacementStats(original, processed) {
            const key = `${original.length}:${processed.length}`;
            this.replacementStats.set(key, (this.replacementStats.get(key) || 0) + 1);
        }
    }

    // ===== 上下文分析器类 =====
    class ContextAnalyzer {
        constructor() {
            this.patterns = {
                excited: /[!!??]{2,}|哇|呀|啊{2,}/,
                happy: /笑|哈哈|嘻嘻|开心|快乐|爽|棒/,
                sad: /哭|难过|伤心|555|呜呜|痛苦/,
                angry: /生气|愤怒|气死|烦|讨厌|恶心/,
                confused: /[??]{2,}|什么|啥|诶|咦|奇怪/,
                calm: /[。.,,;;]/
            };
        }

        analyze(text) {
            for (const [emotion, pattern] of Object.entries(this.patterns)) {
                if (pattern.test(text)) {
                    return emotion;
                }
            }
            return 'normal';
        }
    }

    // ===== 增强设置面板类 =====
    class SettingsPanel {
        constructor() {
            this.isVisible = false;
            this.panel = null;
        }

        create() {
            if (this.panel) return;

            this.panel = document.createElement('div');
            this.panel.id = 'catgirl-settings';
            this.panel.innerHTML = this.getHTML();
            this.panel.style.cssText = this.getCSS();

            document.body.appendChild(this.panel);
            this.bindEvents();
        }

        getHTML() {
            return `
                <div class="settings-header">
                    <h3>🐱 猫娘化设置面板</h3>
                    <button class="close-btn" data-action="close">×</button>
                </div>

                <div class="settings-content">
                    <div class="settings-tabs">
                        <button class="tab-btn active" data-tab="basic">基础设置</button>
                        <button class="tab-btn" data-tab="advanced">高级设置</button>
                        <button class="tab-btn" data-tab="control">控制选项</button>
                        <button class="tab-btn" data-tab="stats">统计信息</button>
                    </div>

                    <div class="tab-content" id="basic-tab">
                        <div class="setting-group">
                            <label>🎀 可爱程度:
                                <select id="cute-level">
                                    <option value="low">低 (温和可爱)</option>
                                    <option value="normal" selected>普通 (标准可爱)</option>
                                    <option value="high">高 (超级可爱,更多替换)</option>
                                </select>
                            </label>
                            <small>控制添加可爱词汇的数量和频率,高档位会替换更多轻微词汇</small>
                        </div>

                        <div class="setting-group">
                            <label>⚙️ 处理模式:
                                <select id="processing-mode">
                                    <option value="gentle">保守 (只替换明显不当词汇)</option>
                                    <option value="contextual" selected>上下文感知 (根据语境智能处理)</option>
                                    <option value="aggressive">积极 (大量替换,最大化猫娘化)</option>
                                </select>
                            </label>
                            <small>控制文本处理的策略和强度,上下文感知会分析语境选择合适的可爱词汇</small>
                        </div>

                        <div class="setting-group">
                            <label>📊 替换强度:
                                <input type="range" id="replacement-intensity" min="0.1" max="1.0" step="0.1" value="${CONFIG.preferences.replacementIntensity}">
                                <span id="intensity-value">${Math.round(CONFIG.preferences.replacementIntensity * 100)}%</span>
                            </label>
                            <small>控制词汇替换的概率,数值越高替换越频繁</small>
                        </div>

                        <div class="setting-group">
                            <label>🎵 结尾词频率:
                                <input type="range" id="ending-frequency" min="0.1" max="1.0" step="0.1" value="${CONFIG.preferences.endingFrequency}">
                                <span id="ending-value">${Math.round(CONFIG.preferences.endingFrequency * 100)}%</span>
                            </label>
                            <small>控制"喵~"等可爱结尾词的出现频率</small>
                        </div>

                        <div class="setting-group">
                            <label>✨ 装饰符频率:
                                <input type="range" id="decorative-frequency" min="0.1" max="1.0" step="0.1" value="${CONFIG.preferences.decorativeFrequency}">
                                <span id="decorative-value">${Math.round(CONFIG.preferences.decorativeFrequency * 100)}%</span>
                            </label>
                            <small>控制"✨"等装饰性符号的出现频率</small>
                        </div>
                    </div>

                    <div class="tab-content" id="advanced-tab" style="display: none;">
                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="intelligent-replacement"> 🧠 智能替换
                            </label>
                            <small>根据上下文情感智能选择替换词汇</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="debug-mode"> 🐛 调试模式
                            </label>
                            <small>显示详细的处理日志信息</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="performance-monitoring"> 📊 性能监控
                            </label>
                            <small>启用内存和性能监控</small>
                        </div>

                        <div class="setting-group">
                            <label>🕐 处理间隔 (毫秒):
                                <input type="range" id="process-interval" min="1000" max="10000" step="500" value="${CONFIG.performance.processInterval}">
                                <span id="interval-value">${CONFIG.performance.processInterval}</span>
                            </label>
                            <small>控制自动处理的时间间隔,数值越小响应越快但消耗更多资源</small>
                        </div>

                        <div class="setting-group">
                            <label>📦 批处理大小:
                                <input type="range" id="batch-size" min="3" max="20" step="1" value="${CONFIG.performance.batchSize}">
                                <span id="batch-value">${CONFIG.performance.batchSize}</span>
                            </label>
                            <small>单次处理的元素数量,数值越大处理越快但可能卡顿</small>
                        </div>

                        <div class="setting-group">
                            <label>⏱️ 防抖延迟 (毫秒):
                                <input type="range" id="debounce-delay" min="100" max="2000" step="100" value="${CONFIG.performance.debounceDelay}">
                                <span id="debounce-value">${CONFIG.performance.debounceDelay}</span>
                            </label>
                            <small>防止重复处理的延迟时间,数值越大越省资源</small>
                        </div>
                    </div>

                    <div class="tab-content" id="control-tab" style="display: none;">
                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="affect-input"> 📝 影响输入框
                            </label>
                            <small>是否处理输入框和文本域中的内容</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="enable-user-prefix"> 👤 启用用户名前缀
                            </label>
                            <small>为用户名添加可爱的表情符号前缀</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="bilibili-merge-links"> 🔗 B站链接合并
                            </label>
                            <small>将B站评论中的链接转换为纯文本</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="auto-process-content"> 🔄 自动处理新内容
                            </label>
                            <small>自动处理动态加载的新内容</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="shadow-dom-support"> 🌐 Shadow DOM 支持
                            </label>
                            <small>处理 Shadow DOM 中的内容(如B站评论区)</small>
                        </div>

                        <div class="setting-group">
                            <label>
                                <input type="checkbox" id="smart-processing"> 🧠 智能处理
                            </label>
                            <small>启用上下文感知和智能优化</small>
                        </div>

                        <div class="setting-group">
                            <h4>🚫 排除词汇</h4>
                            <textarea id="disabled-words" placeholder="输入不想被替换的词汇,每行一个" rows="3">${CONFIG.preferences.disabledWords.join('\n')}</textarea>
                            <small>这些词汇不会被猫娘化处理</small>
                        </div>
                    </div>

                    <div class="tab-content" id="stats-tab" style="display: none;">
                        <div class="stats-grid">
                            <div class="stat-item">
                                <div class="stat-number" id="processed-count">${CONFIG.stats.processedElements}</div>
                                <div class="stat-label">已处理元素</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number" id="replaced-count">${CONFIG.stats.replacedWords}</div>
                                <div class="stat-label">已替换词汇</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number" id="session-count">${CONFIG.stats.sessionProcessed}</div>
                                <div class="stat-label">本次会话</div>
                            </div>
                            <div class="stat-item">
                                <div class="stat-number" id="blacklist-hits-count">${CONFIG.stats.blacklistHits}</div>
                                <div class="stat-label">黑名单命中</div>
                            </div>
                        </div>

                        <div class="info-section">
                            <h4>📅 系统信息</h4>
                            <p><strong>版本:</strong> ${SCRIPT_VERSION}</p>
                            <p><strong>安装时间:</strong> ${new Date(CONFIG.stats.installDate).toLocaleString()}</p>
                            <p><strong>最后活动:</strong> ${new Date(CONFIG.stats.lastActive).toLocaleString()}</p>
                            <p><strong>当前网站:</strong> ${location.hostname}</p>
                            <p><strong>运行状态:</strong> <span id="running-status">检测中...</span></p>
                        </div>

                        <div class="performance-section">
                            <h4>⚡ 性能信息</h4>
                            <div id="performance-info">
                                <p>内存使用: <span id="memory-usage">获取中...</span></p>
                                <p>处理速度: <span id="processing-speed">计算中...</span></p>
                            </div>
                        </div>
                    </div>

                    <div class="actions">
                        <button id="save-settings" class="btn-primary">💾 保存设置</button>
                        <button id="reset-settings" class="btn-warning">🔄 重置设置</button>
                        <button id="clear-cache" class="btn-secondary">🧹 清理缓存</button>
                    </div>
                </div>
            `;
        }

        getCSS() {
            return `
                position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
                width: 600px; max-height: 85vh; background: #ffffff; border-radius: 12px;
                box-shadow: 0 8px 32px rgba(0,0,0,0.3); z-index: 10000;
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                display: none; overflow: hidden;
            `;
        }

        bindEvents() {
            // 关闭按钮
            const closeBtn = this.panel.querySelector('[data-action="close"]');
            if (closeBtn) {
                closeBtn.onclick = () => this.hide();
            }

            // 标签切换
            const tabBtns = this.panel.querySelectorAll('.tab-btn');
            tabBtns.forEach(btn => {
                btn.onclick = () => this.switchTab(btn.dataset.tab);
            });

            // 滑块事件
            this.bindSliderEvents();

            // 保存设置
            const saveBtn = document.getElementById('save-settings');
            if (saveBtn) {
                saveBtn.onclick = () => {
                    this.saveSettings();
                    this.hide();
                    showToast('设置已保存喵~ ✨', 'success');
                };
            }

            // 重置设置
            const resetBtn = document.getElementById('reset-settings');
            if (resetBtn) {
                resetBtn.onclick = () => {
                    if (confirm('确定要重置所有设置吗?这将清除所有自定义配置。')) {
                        this.resetSettings();
                        showToast('设置已重置喵~ 🔄', 'info');
                    }
                };
            }

            // 清理缓存
            const clearBtn = document.getElementById('clear-cache');
            if (clearBtn) {
                clearBtn.onclick = () => {
                    this.clearCache();
                    showToast('缓存已清理喵~ 🧹', 'info');
                };
            }
        }

        bindSliderEvents() {
            const sliders = [
                { id: 'replacement-intensity', valueId: 'intensity-value', isPercent: true },
                { id: 'ending-frequency', valueId: 'ending-value', isPercent: true },
                { id: 'decorative-frequency', valueId: 'decorative-value', isPercent: true },
                { id: 'process-interval', valueId: 'interval-value', isPercent: false },
                { id: 'batch-size', valueId: 'batch-value', isPercent: false },
                { id: 'debounce-delay', valueId: 'debounce-value', isPercent: false }
            ];

            sliders.forEach(({ id, valueId, isPercent }) => {
                const slider = document.getElementById(id);
                const valueSpan = document.getElementById(valueId);

                if (slider && valueSpan) {
                    slider.oninput = (e) => {
                        const value = parseFloat(e.target.value);
                        valueSpan.textContent = isPercent ? `${Math.round(value * 100)}%` : value;
                    };
                }
            });
        }

        switchTab(tabName) {
            // 切换按钮状态
            this.panel.querySelectorAll('.tab-btn').forEach(btn => {
                btn.classList.remove('active');
            });
            this.panel.querySelector(`[data-tab="${tabName}"]`).classList.add('active');

            // 切换内容
            this.panel.querySelectorAll('.tab-content').forEach(content => {
                content.style.display = 'none';
            });
            const targetTab = document.getElementById(`${tabName}-tab`);
            if (targetTab) {
                targetTab.style.display = 'block';
            }
        }

        show() {
            if (!this.panel) this.create();

            this.loadCurrentSettings();
            this.panel.style.display = 'block';
            this.isVisible = true;
            this.updateStats();
            this.updatePerformanceInfo();
        }

        hide() {
            if (this.panel) {
                this.panel.style.display = 'none';
                this.isVisible = false;
            }
        }

        loadCurrentSettings() {
            // 基础设置
            const elements = {
                'cute-level': CONFIG.preferences.cuteLevel,
                'processing-mode': CONFIG.preferences.processingMode,
                'replacement-intensity': CONFIG.preferences.replacementIntensity,
                'ending-frequency': CONFIG.preferences.endingFrequency,
                'decorative-frequency': CONFIG.preferences.decorativeFrequency,
            };

            Object.entries(elements).forEach(([id, value]) => {
                const element = document.getElementById(id);
                if (element) {
                    element.value = value;
                    // 更新滑块显示
                    if (element.type === 'range') {
                        const valueId = id.replace('-', '-').split('-')[0] + '-value';
                        const valueSpan = document.getElementById(valueId);
                        if (valueSpan) {
                            const isPercent = ['replacement-intensity', 'ending-frequency', 'decorative-frequency'].includes(id);
                            valueSpan.textContent = isPercent ? `${Math.round(value * 100)}%` : value;
                        }
                    }
                }
            });

            // 复选框设置
            const checkboxes = {
                'affect-input': CONFIG.features.affectInput,
                'enable-user-prefix': CONFIG.features.bilibiliRandomizeUserNames,
                'bilibili-merge-links': CONFIG.features.bilibiliMergeALinks,
                'auto-process-content': CONFIG.features.autoProcessNewContent,
                'shadow-dom-support': CONFIG.features.shadowDomSupport,
                'smart-processing': CONFIG.features.smartProcessing,
                'intelligent-replacement': CONFIG.preferences.intelligentReplacement,
                'debug-mode': CONFIG.features.debugMode,
                'performance-monitoring': CONFIG.features.performanceMonitoring,
            };

            Object.entries(checkboxes).forEach(([id, checked]) => {
                const element = document.getElementById(id);
                if (element) element.checked = checked;
            });

            // 高级设置
            const advancedElements = {
                'process-interval': CONFIG.performance.processInterval,
                'batch-size': CONFIG.performance.batchSize,
                'debounce-delay': CONFIG.performance.debounceDelay,
            };

            Object.entries(advancedElements).forEach(([id, value]) => {
                const element = document.getElementById(id);
                if (element) {
                    element.value = value;
                    const valueSpan = document.getElementById(id.replace('-', '-').split('-')[0] + '-value');
                    if (valueSpan) valueSpan.textContent = value;
                }
            });

            // 排除词汇
            const disabledWordsEl = document.getElementById('disabled-words');
            if (disabledWordsEl) {
                disabledWordsEl.value = CONFIG.preferences.disabledWords.join('\n');
            }
        }

        saveSettings() {
            // 基础设置
            CONFIG.preferences.cuteLevel = document.getElementById('cute-level')?.value || CONFIG.preferences.cuteLevel;
            CONFIG.preferences.processingMode = document.getElementById('processing-mode')?.value || CONFIG.preferences.processingMode;
            CONFIG.preferences.replacementIntensity = parseFloat(document.getElementById('replacement-intensity')?.value || CONFIG.preferences.replacementIntensity);
            CONFIG.preferences.endingFrequency = parseFloat(document.getElementById('ending-frequency')?.value || CONFIG.preferences.endingFrequency);
            CONFIG.preferences.decorativeFrequency = parseFloat(document.getElementById('decorative-frequency')?.value || CONFIG.preferences.decorativeFrequency);

            // 复选框设置
            CONFIG.features.affectInput = document.getElementById('affect-input')?.checked || false;
            CONFIG.features.bilibiliRandomizeUserNames = document.getElementById('enable-user-prefix')?.checked || false;
            CONFIG.features.bilibiliMergeALinks = document.getElementById('bilibili-merge-links')?.checked || false;
            CONFIG.features.autoProcessNewContent = document.getElementById('auto-process-content')?.checked || false;
            CONFIG.features.shadowDomSupport = document.getElementById('shadow-dom-support')?.checked || false;
            CONFIG.features.smartProcessing = document.getElementById('smart-processing')?.checked || false;
            CONFIG.preferences.intelligentReplacement = document.getElementById('intelligent-replacement')?.checked || false;
            CONFIG.features.debugMode = document.getElementById('debug-mode')?.checked || false;
            CONFIG.features.performanceMonitoring = document.getElementById('performance-monitoring')?.checked || false;

            // 高级设置
            CONFIG.performance.processInterval = parseInt(document.getElementById('process-interval')?.value || CONFIG.performance.processInterval);
            CONFIG.performance.batchSize = parseInt(document.getElementById('batch-size')?.value || CONFIG.performance.batchSize);
            CONFIG.performance.debounceDelay = parseInt(document.getElementById('debounce-delay')?.value || CONFIG.performance.debounceDelay);

            // 排除词汇
            const disabledWordsEl = document.getElementById('disabled-words');
            if (disabledWordsEl) {
                CONFIG.preferences.disabledWords = disabledWordsEl.value
                    .split('\n')
                    .map(word => word.trim())
                    .filter(word => word.length > 0);
            }

            GM_setValue("catgirlConfig", CONFIG);
        }

        resetSettings() {
            CONFIG = Object.assign({}, defaultConfig);
            CONFIG.stats = Object.assign({}, defaultConfig.stats, {
                installDate: GM_getValue("catgirlConfig")?.stats?.installDate || new Date().toISOString()
            });
            GM_setValue("catgirlConfig", CONFIG);
            this.loadCurrentSettings();
        }

        clearCache() {
            if (window.catgirlApp && window.catgirlApp.clearCache) {
                window.catgirlApp.clearCache();
            }
        }

        updateStats() {
            const stats = {
                'processed-count': CONFIG.stats.processedElements,
                'replaced-count': CONFIG.stats.replacedWords,
                'session-count': CONFIG.stats.sessionProcessed,
                'blacklist-hits-count': CONFIG.stats.blacklistHits
            };

            Object.entries(stats).forEach(([id, value]) => {
                const element = document.getElementById(id);
                if (element) element.textContent = value;
            });

            // 更新运行状态
            const statusEl = document.getElementById('running-status');
            if (statusEl && window.catgirlApp) {
                const isRunning = window.catgirlApp.app.isRunning;
                statusEl.textContent = isRunning ? '运行中 ✅' : '已暂停 ⏸️';
                statusEl.style.color = isRunning ? '#28a745' : '#ffc107';
            }
        }

        updatePerformanceInfo() {
            // 更新内存使用
            if (performance.memory) {
                const memoryEl = document.getElementById('memory-usage');
                if (memoryEl) {
                    const used = (performance.memory.usedJSHeapSize / 1024 / 1024).toFixed(1);
                    const limit = (performance.memory.jsHeapSizeLimit / 1024 / 1024).toFixed(1);
                    memoryEl.textContent = `${used}MB / ${limit}MB`;
                }
            }

            // 计算处理速度
            const speedEl = document.getElementById('processing-speed');
            if (speedEl) {
                const elementsPerSecond = CONFIG.stats.sessionProcessed > 0 ?
                    Math.round(CONFIG.stats.sessionProcessed / ((Date.now() - performance.timeOrigin) / 1000)) : 0;
                speedEl.textContent = `${elementsPerSecond} 元素/秒`;
            }
        }
    }

    // ===== 主应用类 =====
    class CatgirlApp {
        constructor() {
            this.stateManager = new StateManager();
            this.textProcessor = new EnhancedTextProcessor();
            this.settingsPanel = new SettingsPanel();
            this.blacklistManager = new BlacklistManager();
            this.processedElements = new WeakSet();
            this.isRunning = false;
            this.intervalId = null;
            this.observer = null;
            this.lastProcessHash = '';
            this.processLock = false;
            this.bilibiliCommentObserver = null;
        }

        async initialize() {
            // 检查黑名单
            if (this.blacklistManager.isBlacklisted()) {
                if (CONFIG.features.debugMode) {
                    console.log('🐱 当前网站已被加入黑名单,不启动喵~');
                }
                return;
            }

            if (this.shouldExclude()) {
                if (CONFIG.features.debugMode) {
                    console.log('🐱 域名已排除,不启动喵~');
                }
                return;
            }

            console.log('🐱 增强版猫娘化系统启动喵~');

            this.registerMenuCommands();
            this.setupKeyboardShortcuts();
            await this.waitForDOMReady();

            this.stateManager.onUrlChange((newUrl) => {
                setTimeout(() => {
                    if (location.href === newUrl) {
                        this.processPage();
                    }
                }, CONFIG.performance.debounceDelay);
            });

            this.start();
        }

        shouldExclude() {
            return CONFIG.sites.excludeDomains.some(domain =>
                location.hostname.includes(domain)
            );
        }

        registerMenuCommands() {
            GM_registerMenuCommand("🐱 设置面板", () => this.settingsPanel.show());
            GM_registerMenuCommand("🚫 网站黑名单", () => this.blacklistManager.show());
            GM_registerMenuCommand("⛔ 屏蔽当前网站", () => this.showBlockSiteDialog());
            GM_registerMenuCommand("🔄 重新处理", () => this.restart());
            GM_registerMenuCommand("📊 显示统计", () => this.showStats());
            GM_registerMenuCommand("🧹 清理缓存", () => this.clearCache());
        }

        showBlockSiteDialog() {
            const domain = location.hostname;
            const options = [
                { text: '屏蔽整个网站 1小时', type: 'site', duration: 3600000 },
                { text: '屏蔽整个网站 1天', type: 'site', duration: 86400000 },
                { text: '永久屏蔽整个网站', type: 'site', duration: -1 },
                { text: '仅屏蔽当前页面 1小时', type: 'page', duration: 3600000 },
                { text: '仅屏蔽当前页面 1天', type: 'page', duration: 86400000 },
            ];

            const choice = prompt(
                `选择屏蔽方式 (${domain}):\n\n` +
                options.map((opt, i) => `${i + 1}. ${opt.text}`).join('\n') +
                '\n\n请输入数字 (1-5):',
                '1'
            );

            const index = parseInt(choice) - 1;
            if (index >= 0 && index < options.length) {
                const selected = options[index];
                const reason = prompt('屏蔽原因 (可选):', '') || '用户手动屏蔽';

                this.blacklistManager.addToBlacklist(selected.type, selected.duration, reason);

                // 如果是整站屏蔽,立即停止脚本
                if (selected.type === 'site') {
                    this.stop();
                    showToast('网站已屏蔽,脚本已停止运行', 'info', 5000);
                }
            }
        }

        setupKeyboardShortcuts() {
            let inputFocused = false;

            const handleFocusIn = DebounceUtils.debounce((e) => {
                if (e.target && e.target.matches && e.target.matches('input, textarea')) {
                    inputFocused = true;
                }
            }, 100);

            const handleFocusOut = DebounceUtils.debounce((e) => {
                if (e.target && e.target.matches && e.target.matches('input, textarea')) {
                    inputFocused = false;
                }
            }, 100);

            document.addEventListener('focusin', handleFocusIn);
            document.addEventListener('focusout', handleFocusOut);

            document.addEventListener('keydown', (e) => {
                if (inputFocused && !e.ctrlKey && !e.altKey) return;

                const key = `${e.altKey?1:0}${e.ctrlKey?1:0}${e.shiftKey?1:0}${e.key.toUpperCase()}`;

                switch (key) {
                    case CONFIG.shortcuts.toggleScript:
                        e.preventDefault();
                        this.toggle();
                        break;
                    case CONFIG.shortcuts.showSettings:
                        e.preventDefault();
                        this.settingsPanel.show();
                        break;
                    case CONFIG.shortcuts.showBlacklist:
                        e.preventDefault();
                        this.blacklistManager.show();
                        break;
                    case CONFIG.shortcuts.resetProcessing:
                        e.preventDefault();
                        this.restart();
                        break;
                    case CONFIG.shortcuts.debugMode:
                        e.preventDefault();
                        this.toggleDebug();
                        break;
                }
            });
        }

        async start() {
            if (this.isRunning) return;
            this.isRunning = true;

            setTimeout(() => {
                if (this.isRunning) {
                    this.processPage();
                }
            }, 1000);

            if (CONFIG.performance.processInterval > 0) {
                const debouncedProcess = DebounceUtils.throttleWithDebounce(
                    () => this.conditionalProcess(),
                    CONFIG.performance.processInterval,
                    CONFIG.performance.debounceDelay
                );

                this.intervalId = setInterval(debouncedProcess, CONFIG.performance.processInterval);
            }

            this.setupMutationObserver();

            if (this.stateManager.isBilibili()) {
                this.setupBilibiliCommentObserver();
            }

            if (CONFIG.features.debugMode) {
                console.log('🎀 猫娘化系统已启动完成喵~');
            }
        }

        conditionalProcess() {
            if (!this.isRunning || this.processLock) return;

            const urlChanged = this.stateManager.checkUrlChange();
            const commentChanged = this.stateManager.checkBilibiliCommentChange();
            const shouldProcess = this.stateManager.shouldProcess();

            if (urlChanged || commentChanged || (!this.stateManager.shouldSkipBilibiliProcessing() && shouldProcess)) {
                this.processPage();
            }
        }

        processPage() {
            if (!this.isRunning || !CONFIG.features.autoProcessNewContent || this.processLock) {
                return;
            }

            this.processLock = true;

            try {
                const elements = this.getProcessableElements();

                const contentHash = this.generateContentHash(elements);
                if (contentHash === this.lastProcessHash) {
                    return;
                }
                this.lastProcessHash = contentHash;

                if (elements.length === 0) {
                    return;
                }

                EnhancedPerformanceUtils.createTimeSliceProcessor(
                    elements,
                    (element) => this.processElement(element),
                    {
                        onProgress: CONFIG.features.debugMode ?
                        (current, total, percent) => {
                            if (current % 50 === 0) {
                                console.log(`🐱 处理进度: ${percent.toFixed(1)}% (${current}/${total})`);
                            }
                        } : null,
                        onComplete: () => {
                            CONFIG.stats.lastActive = new Date().toISOString();
                            GM_setValue("catgirlConfig", CONFIG);

                            if (this.stateManager.isBilibili()) {
                                this.processBilibiliSpecial();
                            }
                        }
                    }
                );
            } finally {
                setTimeout(() => {
                    this.processLock = false;
                }, 1000);
            }
        }

        getProcessableElements() {
            const baseSelector = 'title, h1, h2, h3, h4, h5, h6, p, article, section, blockquote, li, a, span, div:not([class*="settings"]):not([id*="catgirl"])';
            const inputSelector = CONFIG.features.affectInput ? ', input, textarea' : '';

            const elements = document.querySelectorAll(baseSelector + inputSelector);

            return Array.from(elements).filter(element => {
                return !this.processedElements.has(element) &&
                    !element.closest('#catgirl-settings, #catgirl-debug, #catgirl-blacklist') &&
                    this.shouldProcessElement(element);
            });
        }

        shouldProcessElement(element) {
            if (!element.textContent?.trim()) return false;
            if (this.textProcessor.isProcessed(element.textContent)) return false;
            if (element.tagName && /^(SCRIPT|STYLE|NOSCRIPT)$/.test(element.tagName)) return false;
            if (element.offsetParent === null && element.style.display !== 'none') return false;
            return true;
        }

        generateContentHash(elements) {
            const textContent = elements.slice(0, 10).map(el => el.textContent?.slice(0, 50)).join('|');
            return textContent.length + ':' + elements.length;
        }

        processElement(element) {
            if (!element || this.processedElements.has(element)) return;

            try {
                if (element.matches && element.matches('input, textarea') && CONFIG.features.affectInput) {
                    if (element.value?.trim()) {
                        element.value = this.textProcessor.processText(element.value);
                    }
                } else {
                    this.processElementText(element);
                }

                this.processedElements.add(element);
                CONFIG.stats.processedElements++;

            } catch (error) {
                if (CONFIG.features.debugMode) {
                    console.error('🐱 处理元素出错:', error);
                }
            }
        }

        processElementText(element) {
            if (element.children.length === 0) {
                const newText = this.textProcessor.processText(element.textContent);
                if (newText !== element.textContent) {
                    element.textContent = newText;
                }
            } else {
                const textNodes = this.getTextNodes(element);
                textNodes.forEach(node => {
                    if (node.textContent?.trim()) {
                        const newText = this.textProcessor.processText(node.textContent);
                        if (newText !== node.textContent) {
                            node.textContent = newText;
                        }
                    }
                });
            }
        }

        getTextNodes(element) {
            const textNodes = [];
            const walker = document.createTreeWalker(
                element,
                NodeFilter.SHOW_TEXT,
                {
                    acceptNode: function(node) {
                        if (node.parentElement &&
                            /^(SCRIPT|STYLE|NOSCRIPT)$/.test(node.parentElement.tagName)) {
                            return NodeFilter.FILTER_REJECT;
                        }
                        return node.textContent.trim() ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
                    }
                }
            );

            let node;
            while (node = walker.nextNode()) {
                textNodes.push(node);
            }

            return textNodes;
        }

        processBilibiliSpecial() {
            if (this.stateManager.shouldSkipBilibiliProcessing()) return;

            if (CONFIG.features.debugMode) {
                console.log('🎯 执行B站特殊处理');
            }

            try {
                this.processBilibiliComments();
                this.processBilibiliShadowDOM();
            } catch (error) {
                if (CONFIG.features.debugMode) {
                    console.error('🐱 B站处理出错:', error);
                }
            }

            this.stateManager.markBilibiliCompleted();
        }

        processBilibiliComments() {
            const commentSelectors = [
                '.reply-item .reply-content:not([data-catgirl-processed])',
                '.comment-item .comment-content:not([data-catgirl-processed])',
                '.bili-comment-content:not([data-catgirl-processed])',
                '.reply-content:not([data-catgirl-processed])',
                '.comment-content:not([data-catgirl-processed])',
                '[data-e2e="reply-item"] .reply-content:not([data-catgirl-processed])',
                '.bili-comment .comment-text:not([data-catgirl-processed])'
            ];

            commentSelectors.forEach(selector => {
                const elements = document.querySelectorAll(selector);
                elements.forEach(element => {
                    if (!this.processedElements.has(element)) {
                        element.setAttribute('data-catgirl-processed', 'true');
                        this.processElement(element);
                    }
                });
            });

            // 处理用户名 - 检查开关
            if (CONFIG.features.bilibiliRandomizeUserNames) {
                const usernameSelectors = [
                    '.user-name:not([data-catgirl-processed])',
                    '.reply-item .user-name:not([data-catgirl-processed])',
                    '.comment-item .user-name:not([data-catgirl-processed])',
                    '.bili-comment .user-name:not([data-catgirl-processed])',
                    '.reply-author:not([data-catgirl-processed])',
                    '.comment-author:not([data-catgirl-processed])'
                ];

                usernameSelectors.forEach(selector => {
                    const elements = document.querySelectorAll(selector);
                    elements.forEach(element => {
                        this.processBilibiliUsername(element);
                    });
                });
            }
        }

        processBilibiliUsername(element) {
            if (!element || this.processedElements.has(element)) return;

            const userName = element.textContent?.trim();
            if (!userName || !CONFIG.features.bilibiliRandomizeUserNames) return;

            if (this.hasUserPrefix(userName)) return;

            element.setAttribute('data-catgirl-processed', 'true');
            this.processedElements.add(element);

            const processingType = Math.random();

            if (processingType < 0.3) {
                const randomPrefix = this.getRandomUserPrefix();
                element.textContent = `${randomPrefix}${userName}${randomPrefix}`;
            } else if (processingType < 0.6) {
                const randomPrefix = this.getRandomUserPrefix();
                element.textContent = `${randomPrefix}${userName}`;
            } else if (processingType < 0.8) {
                const decorative = cuteLibrary.decorativePrefixes[Math.floor(Math.random() * cuteLibrary.decorativePrefixes.length)];
                element.textContent = `${decorative}${userName}`;
            }

            if (CONFIG.features.debugMode) {
                console.log('🎀 处理用户名:', userName, '->', element.textContent);
            }
        }

        processBilibiliShadowDOM() {
            if (!CONFIG.features.shadowDomSupport) return;

            const biliComments = document.querySelector('bili-comments');
            if (biliComments && biliComments.shadowRoot) {
                this.processElementsInShadowDOM(biliComments.shadowRoot);
            }

            const shadowHosts = document.querySelectorAll('bili-comment-thread-renderer, bili-comment-replies-renderer');
            shadowHosts.forEach(host => {
                if (host.shadowRoot) {
                    this.processElementsInShadowDOM(host.shadowRoot);
                }
            });
        }

        processElementsInShadowDOM(shadowRoot) {
            try {
                const contentSelectors = [
                    '#contents span:not([data-catgirl-processed])',
                    '.comment-text:not([data-catgirl-processed])',
                    '.reply-content:not([data-catgirl-processed])',
                    '.comment-content:not([data-catgirl-processed])'
                ];

                contentSelectors.forEach(selector => {
                    const elements = shadowRoot.querySelectorAll(selector);
                    elements.forEach(element => {
                        if (!this.processedElements.has(element)) {
                            element.setAttribute('data-catgirl-processed', 'true');
                            this.processElement(element);
                        }
                    });
                });

                if (CONFIG.features.bilibiliRandomizeUserNames) {
                    const usernameSelectors = [
                        '#user-name a:not([data-catgirl-processed])',
                        '.user-name:not([data-catgirl-processed])',
                        '.author-name:not([data-catgirl-processed])'
                    ];

                    usernameSelectors.forEach(selector => {
                        const elements = shadowRoot.querySelectorAll(selector);
                        elements.forEach(element => {
                            this.processBilibiliUsername(element);
                        });
                    });
                }

                const nestedHosts = shadowRoot.querySelectorAll('*');
                nestedHosts.forEach(el => {
                    if (el.shadowRoot && !el.hasAttribute('data-catgirl-shadow-processed')) {
                        el.setAttribute('data-catgirl-shadow-processed', 'true');
                        this.processElementsInShadowDOM(el.shadowRoot);
                    }
                });

            } catch (error) {
                if (CONFIG.features.debugMode) {
                    console.error('🐱 处理Shadow DOM出错:', error);
                }
            }
        }

        hasUserPrefix(userName) {
            if (!userName) return true;

            const hasPrefix = cuteLibrary.userPrefixes.some(prefix => userName.includes(prefix));
            const hasDecorative = cuteLibrary.decorativePrefixes.some(prefix => userName.includes(prefix));
            const isProcessed = /已处理|🏳️‍⚧️.*🏳️‍⚧️|✨.*✨|💕.*💕/.test(userName);
            const isTooLong = userName.length > 20;

            return hasPrefix || hasDecorative || isProcessed || isTooLong;
        }

        getRandomUserPrefix() {
            const prefixes = cuteLibrary.userPrefixes;
            return prefixes[Math.floor(Math.random() * prefixes.length)];
        }

        setupBilibiliCommentObserver() {
            if (this.bilibiliCommentObserver) return;

            const targetNode = document.body;
            const config = {
                childList: true,
                subtree: true,
                attributes: false
            };

            this.bilibiliCommentObserver = new MutationObserver(
                DebounceUtils.throttleWithDebounce((mutations) => {
                    let hasCommentChanges = false;

                    for (const mutation of mutations) {
                        for (const node of mutation.addedNodes) {
                            if (node.nodeType === Node.ELEMENT_NODE) {
                                if (node.matches && (
                                    node.matches('bili-comment-thread-renderer, bili-comment, .reply-item, .comment-item') ||
                                    (node.querySelector && (
                                        node.querySelector('bili-comment-thread-renderer') ||
                                        node.querySelector('.reply-item') ||
                                        node.querySelector('.comment-item') ||
                                        node.querySelector('.bili-comment')
                                    ))
                                )) {
                                    hasCommentChanges = true;
                                    break;
                                }
                            }
                        }
                        if (hasCommentChanges) break;
                    }

                    if (hasCommentChanges) {
                        setTimeout(() => {
                            if (CONFIG.features.debugMode) {
                                console.log('🔄 检测到B站评论变化,开始处理');
                            }
                            this.processBilibiliSpecial();
                        }, 1200);
                    }
                }, 800, 400)
            );

            this.bilibiliCommentObserver.observe(targetNode, config);

            if (CONFIG.features.debugMode) {
                console.log('🎯 B站评论观察器已启动');
            }
        }

        setupMutationObserver() {
            if (this.observer) return;

            const throttledCallback = DebounceUtils.throttleWithDebounce(
                (mutations) => this.handleMutations(mutations),
                CONFIG.performance.observerThrottle,
                CONFIG.performance.debounceDelay
            );

            this.observer = new MutationObserver(throttledCallback);
            this.observer.observe(document.body, {
                childList: true,
                subtree: true,
                attributes: false,
                characterData: false
            });
        }

        handleMutations(mutations) {
            if (this.processLock) return;

            try {
                const elementsToProcess = new Set();

                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === Node.ELEMENT_NODE && this.shouldProcessElement(node)) {
                            elementsToProcess.add(node);

                            const children = node.querySelectorAll && node.querySelectorAll('*');
                            if (children) {
                                Array.from(children).forEach(child => {
                                    if (this.shouldProcessElement(child)) {
                                        elementsToProcess.add(child);
                                    }
                                });
                            }
                        }
                    });
                });

                if (elementsToProcess.size > 0) {
                    const limitedElements = Array.from(elementsToProcess).slice(0, 20);

                    EnhancedPerformanceUtils.createTimeSliceProcessor(
                        limitedElements,
                        (element) => this.processElement(element),
                        {
                            onComplete: () => {
                                CONFIG.stats.lastActive = new Date().toISOString();
                            }
                        }
                    );
                }
            } catch (error) {
                if (CONFIG.features.debugMode) {
                    console.error('🐱 处理DOM变化出错:', error);
                }
            }
        }

        toggle() {
            if (this.isRunning) {
                this.stop();
                showToast('猫娘化已暂停喵~ ⏸️', 'warning');
            } else {
                this.start();
                showToast('猫娘化已恢复喵~ ▶️', 'success');
            }
        }

        stop() {
            this.isRunning = false;
            this.processLock = false;

            if (this.intervalId) {
                clearInterval(this.intervalId);
                this.intervalId = null;
            }
            if (this.observer) {
                this.observer.disconnect();
                this.observer = null;
            }
            if (this.bilibiliCommentObserver) {
                this.bilibiliCommentObserver.disconnect();
                this.bilibiliCommentObserver = null;
            }
        }

        restart() {
            this.stop();
            this.processedElements = new WeakSet();
            this.textProcessor.processedTexts = new Set();
            this.lastProcessHash = '';

            setTimeout(() => {
                this.start();
                showToast('系统已重启喵~ 🔄', 'info');
            }, 500);
        }

        toggleDebug() {
            CONFIG.features.debugMode = !CONFIG.features.debugMode;
            GM_setValue("catgirlConfig", CONFIG);
            showToast(`调试模式${CONFIG.features.debugMode ? '开启' : '关闭'}喵~ 🐛`, 'info');
        }

        showStats() {
            const processedElements = (CONFIG.stats.processedElements || 0);
            const replacedWords = (CONFIG.stats.replacedWords || 0);
            const sessionProcessed = (CONFIG.stats.sessionProcessed || 0);
            const blacklistHits = (CONFIG.stats.blacklistHits || 0);
            const installDate = CONFIG.stats.installDate || new Date().toISOString();
            const lastActive = CONFIG.stats.lastActive || new Date().toISOString();

            const stats = `
📊 猫娘化统计信息:
• 已处理元素: ${processedElements.toLocaleString()}
• 已替换词汇: ${replacedWords.toLocaleString()}
• 本次会话: ${sessionProcessed.toLocaleString()}
• 黑名单命中: ${blacklistHits.toLocaleString()}
• 当前版本: ${SCRIPT_VERSION}
• 安装时间: ${new Date(installDate).toLocaleString()}
• 最后活动: ${new Date(lastActive).toLocaleString()}
• 当前状态: ${this.isRunning ? '运行中 ✅' : '已暂停 ⏸️'}
• 当前网站: ${location.hostname}
            `.trim();

            alert(stats);
        }

        clearCache() {
            this.processedElements = new WeakSet();
            this.textProcessor.processedTexts = new Set();
            this.lastProcessHash = '';
            CONFIG.stats.sessionProcessed = 0;

            // 清理处理标记
            const processedElements = document.querySelectorAll('[data-catgirl-processed]');
            processedElements.forEach(el => {
                el.removeAttribute('data-catgirl-processed');
            });

            const processedShadows = document.querySelectorAll('[data-catgirl-shadow-processed]');
            processedShadows.forEach(el => {
                el.removeAttribute('data-catgirl-shadow-processed');
            });

            GM_setValue("catgirlConfig", CONFIG);
            showToast('缓存已清理,统计已重置喵~ 🧹', 'success');
        }

        waitForDOMReady() {
            return new Promise(resolve => {
                if (document.readyState !== 'loading') {
                    resolve();
                } else {
                    document.addEventListener('DOMContentLoaded', resolve, { once: true });
                }
            });
        }
    }

    // ===== 工具函数 =====
    function showToast(message, type = 'info', duration = 3000) {
        const toast = document.createElement('div');
        toast.className = 'catgirl-toast';
        toast.innerHTML = `
            <div class="toast-icon">${getToastIcon(type)}</div>
            <div class="toast-message">${message}</div>
        `;

        toast.classList.add(`toast-${type}`);
        document.body.appendChild(toast);

        setTimeout(() => toast.classList.add('show'), 10);

        setTimeout(() => {
            toast.classList.remove('show');
            setTimeout(() => {
                if (toast.parentNode) {
                    document.body.removeChild(toast);
                }
            }, 300);
        }, duration);
    }

    function getToastIcon(type) {
        const icons = {
            success: '✅',
            error: '❌',
            warning: '⚠️',
            info: 'ℹ️'
        };
        return icons[type] || icons.info;
    }

    function showUpdateNotification() {
        showToast(`🎉 猫娘脚本已更新到 v${SCRIPT_VERSION} 喵~\n新增功能:黑名单管理、可视化控制、词汇扩展`, 'success', 5000);
    }

    // ===== 启动应用 =====
    const catgirlApp = new CatgirlApp();

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => catgirlApp.initialize(), { once: true });
    } else {
        setTimeout(() => catgirlApp.initialize(), 100);
    }

    // ===== 样式注入 =====
    GM_addStyle(`
        /* 设置面板样式 */
        #catgirl-settings {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
            line-height: 1.5;
        }

        #catgirl-settings .settings-header,
        #catgirl-blacklist .blacklist-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px;
            border-radius: 12px 12px 0 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        #catgirl-settings .settings-header h3,
        #catgirl-blacklist .blacklist-header h3 {
            margin: 0;
            font-size: 20px;
            font-weight: 600;
        }

        #catgirl-settings .close-btn,
        #catgirl-blacklist .close-btn {
            background: rgba(255,255,255,0.2);
            border: none;
            color: white;
            font-size: 24px;
            cursor: pointer;
            width: 32px;
            height: 32px;
            border-radius: 50%;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        #catgirl-settings .close-btn:hover,
        #catgirl-blacklist .close-btn:hover {
            background: rgba(255,255,255,0.3);
            transform: scale(1.1);
        }

        #catgirl-settings .settings-content,
        #catgirl-blacklist .blacklist-content {
            padding: 24px;
            background: #ffffff;
            height: 590px;
            overflow-y: auto;
            border-radius: 0 0 12px 12px;
        }

        #catgirl-settings .settings-tabs {
            display: flex;
            margin-bottom: 24px;
            background: #f8f9fa;
            border-radius: 8px;
            padding: 4px;
            flex-wrap: wrap;
        }

        #catgirl-settings .tab-btn {
            flex: 1;
            padding: 12px 16px;
            border: none;
            background: transparent;
            cursor: pointer;
            border-radius: 6px;
            transition: all 0.3s ease;
            font-weight: 500;
            color: #6c757d;
            min-width: 80px;
        }

        #catgirl-settings .tab-btn.active {
            background: white;
            color: #495057;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        #catgirl-settings .tab-btn:hover:not(.active) {
            color: #495057;
            background: rgba(255,255,255,0.7);
        }

        #catgirl-settings .setting-group {
            margin-bottom: 20px;
        }

        #catgirl-settings label,
        #catgirl-blacklist label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: #333;
            font-size: 14px;
        }

        #catgirl-settings small,
        #catgirl-blacklist small {
            display: block;
            color: #6c757d;
            font-size: 12px;
            margin-top: 4px;
            line-height: 1.4;
        }

        #catgirl-settings select,
        #catgirl-settings input[type="text"],
        #catgirl-settings input[type="range"],
        #catgirl-settings textarea,
        #catgirl-blacklist select,
        #catgirl-blacklist input[type="text"],
        #catgirl-blacklist textarea {
            width: 100%;
            padding: 10px 12px;
            border: 2px solid #e9ecef;
            border-radius: 6px;
            font-size: 14px;
            transition: all 0.3s ease;
            background: #fff;
            box-sizing: border-box;
        }

        #catgirl-settings select:focus,
        #catgirl-settings input:focus,
        #catgirl-settings textarea:focus,
        #catgirl-blacklist select:focus,
        #catgirl-blacklist input:focus,
        #catgirl-blacklist textarea:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }

        #catgirl-settings input[type="checkbox"],
        #catgirl-blacklist input[type="checkbox"] {
            width: auto;
            margin-right: 8px;
            transform: scale(1.2);
            accent-color: #667eea;
        }

        #catgirl-settings input[type="range"] {
            height: 6px;
            -webkit-appearance: none;
            background: #e9ecef;
            border-radius: 3px;
            padding: 0;
        }

        #catgirl-settings input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: #667eea;
            cursor: pointer;
            box-shadow: 0 2px 4px rgba(0,0,0,0.2);
        }

        #catgirl-settings .stats-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 16px;
            margin-bottom: 20px;
        }

        #catgirl-settings .stat-item {
            text-align: center;
            padding: 16px;
            background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
            border-radius: 8px;
            border: 1px solid #dee2e6;
        }

        #catgirl-settings .stat-number {
            font-size: 24px;
            font-weight: 700;
            color: #667eea;
            margin-bottom: 4px;
        }

        #catgirl-settings .stat-label {
            font-size: 12px;
            color: #6c757d;
            font-weight: 500;
        }

        #catgirl-settings .info-section,
        #catgirl-settings .performance-section {
            background: #f8f9fa;
            padding: 16px;
            border-radius: 8px;
            border-left: 4px solid #667eea;
            margin-bottom: 16px;
        }

        #catgirl-settings .info-section h4,
        #catgirl-settings .performance-section h4,
        #catgirl-blacklist h4 {
            margin: 0 0 12px 0;
            color: #495057;
            font-size: 16px;
        }

        #catgirl-settings .info-section p,
        #catgirl-settings .performance-section p {
            margin: 6px 0;
            color: #6c757d;
            font-size: 14px;
        }

        #catgirl-settings .actions,
        #catgirl-blacklist .actions {
            display: flex;
            gap: 12px;
            flex-wrap: wrap;
            margin-top: 24px;
            padding-top: 24px;
            border-top: 1px solid #e9ecef;
        }

        #catgirl-settings button,
        #catgirl-blacklist button {
            padding: 12px 20px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
        }

        #catgirl-settings .btn-primary,
        #catgirl-blacklist .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            flex: 1;
        }

        #catgirl-settings .btn-primary:hover,
        #catgirl-blacklist .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
        }

        #catgirl-settings .btn-warning {
            background: linear-gradient(135deg, #ffc107 0%, #ff8c00 100%);
            color: #212529;
            flex: 1;
        }

        #catgirl-settings .btn-warning:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(255, 193, 7, 0.4);
        }

        #catgirl-settings .btn-secondary,
        #catgirl-blacklist .btn-secondary {
            background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
            color: white;
            flex: 1;
        }

        #catgirl-settings .btn-secondary:hover,
        #catgirl-blacklist .btn-secondary:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(108, 117, 125, 0.4);
        }

        /* 黑名单面板特殊样式 */
        #catgirl-blacklist {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
            line-height: 1.5;
        }

        #catgirl-blacklist .current-site-section {
            background: #f8f9fa;
            padding: 16px;
            border-radius: 8px;
            margin-bottom: 20px;
            border-left: 4px solid #28a745;
        }

        #catgirl-blacklist .current-site-info {
            background: #e9ecef;
            padding: 12px;
            border-radius: 6px;
            margin-bottom: 16px;
            font-family: 'Courier New', monospace;
            font-size: 13px;
        }

        #catgirl-blacklist .action-group {
            margin-bottom: 12px;
        }

        #catgirl-blacklist .btn-danger {
            background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
            color: white;
            width: 100%;
        }

        #catgirl-blacklist .btn-danger:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(220, 53, 69, 0.4);
        }

        #catgirl-blacklist .blacklist-section {
            margin-bottom: 24px;
        }

        #catgirl-blacklist .blacklist-item {
            background: #fff;
            border: 1px solid #dee2e6;
            border-radius: 8px;
            padding: 16px;
            margin-bottom: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            transition: all 0.3s ease;
        }

        #catgirl-blacklist .blacklist-item:hover {
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }

        #catgirl-blacklist .blacklist-item.expired {
            background: #f8f9fa;
            border-color: #adb5bd;
            opacity: 0.7;
        }

        #catgirl-blacklist .item-domain {
            font-weight: 600;
            color: #495057;
            margin-bottom: 4px;
        }

        #catgirl-blacklist .item-details {
            font-size: 12px;
            color: #6c757d;
            line-height: 1.4;
        }

        #catgirl-blacklist .remove-btn {
            background: #dc3545;
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            transition: all 0.3s ease;
        }

        #catgirl-blacklist .remove-btn:hover {
            background: #c82333;
            transform: scale(1.05);
        }

        #catgirl-blacklist .empty-state {
            text-align: center;
            color: #6c757d;
            font-style: italic;
            padding: 32px;
            background: #f8f9fa;
            border-radius: 8px;
        }

        #catgirl-blacklist .blacklist-stats {
            text-align: center;
            padding-top: 16px;
            border-top: 1px solid #e9ecef;
            margin-top: 16px;
        }

        #catgirl-blacklist .blacklist-settings {
            background: #e3f2fd;
            padding: 16px;
            border-radius: 8px;
            border-left: 4px solid #2196f3;
            margin-bottom: 20px;
        }

        /* Toast 通知样式 */
        .catgirl-toast {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 10001;
            padding: 16px 20px;
            border-radius: 12px;
            font-size: 14px;
            font-weight: 500;
            max-width: 350px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.15);
            transform: translateX(120%);
            transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            backdrop-filter: blur(10px);
            display: flex;
            align-items: center;
            gap: 12px;
        }

        .catgirl-toast.show {
            transform: translateX(0);
        }

        .catgirl-toast.toast-success {
            background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
            color: white;
        }

        .catgirl-toast.toast-error {
            background: linear-gradient(135deg, #dc3545 0%, #e74c3c 100%);
            color: white;
        }

        .catgirl-toast.toast-warning {
            background: linear-gradient(135deg, #ffc107 0%, #fd7e14 100%);
            color: #212529;
        }

        .catgirl-toast.toast-info {
            background: linear-gradient(135deg, #17a2b8 0%, #6f42c1 100%);
            color: white;
        }

        .catgirl-toast .toast-icon {
            font-size: 18px;
        }

        .catgirl-toast .toast-message {
            flex: 1;
            line-height: 1.4;
        }

        /* 响应式设计 */
        @media (max-width: 700px) {
            #catgirl-settings,
            #catgirl-blacklist {
                width: 95vw;
                max-height: 90vh;
            }

            #catgirl-settings .settings-tabs {
                flex-direction: column;
            }

            #catgirl-settings .tab-btn {
                flex: none;
            }

            #catgirl-settings .actions,
            #catgirl-blacklist .actions {
                flex-direction: column;
            }

            #catgirl-settings .stats-grid {
                grid-template-columns: 1fr;
            }

            #catgirl-blacklist .blacklist-item {
                flex-direction: column;
                align-items: stretch;
                gap: 12px;
            }

            #catgirl-blacklist .remove-btn {
                align-self: flex-end;
            }
        }

        /* 滚动条美化 */
        #catgirl-settings ::-webkit-scrollbar,
        #catgirl-blacklist ::-webkit-scrollbar {
            width: 8px;
        }

        #catgirl-settings ::-webkit-scrollbar-track,
        #catgirl-blacklist ::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 4px;
        }

        #catgirl-settings ::-webkit-scrollbar-thumb,
        #catgirl-blacklist ::-webkit-scrollbar-thumb {
            background: #c1c1c1;
            border-radius: 4px;
        }

        #catgirl-settings ::-webkit-scrollbar-thumb:hover,
        #catgirl-blacklist ::-webkit-scrollbar-thumb:hover {
            background: #a8a8a8;
        }
    `);

    // ===== 全局调试接口 =====
    window.catgirlApp = {
        app: catgirlApp,
        blacklistManager: catgirlApp.blacklistManager,
        config: CONFIG,
        version: SCRIPT_VERSION,
        clearCache: function() {
            catgirlApp.clearCache();
        }
    };

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址