豆瓣+TMDB影视工具(AI增强)

影视信息提取与排版工具,添加AI文字生成功能

// ==UserScript==
// @name         豆瓣+TMDB影视工具(AI增强)
// @namespace    tampermonkey
// @version      1.0
// @description  影视信息提取与排版工具,添加AI文字生成功能
// @author       绘梦
// @match        https://pan1.me/?thread-create-*.htm
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @grant        GM_log
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @connect      www.douban.com
// @connect      accounts.douban.com
// @connect      search.douban.com
// @connect      movie.douban.com
// @connect      m.douban.com
// @connect      doubanio.com
// @connect      search.doubanio.com
// @connect      tv.douban.com
// @connect      doubanio.com
// @run-at       document-end
// @license      MIT  // 新增:声明MIT许可证
// ==/UserScript==

(function () {
    'use strict';
    // === Douban anti-crawl limiter ===
    // 兼顾速度与风控:放宽总频率,但引入“批量节流”与图片并发池
    const D_RATE = { maxPerMin: 26, minDelay: 380, maxDelay: 900 };
    let dLastTs = 0, dTokens = D_RATE.maxPerMin, dWindow = Date.now();
    let doubanCooldownUntil = 0;
    function inCooldown() { return Date.now() < doubanCooldownUntil; }
    function triggerCooldown(sec = 90) { doubanCooldownUntil = Date.now() + sec*1000; }
    function waitDoubanSlot() {
        return new Promise(res => {
            const refill = () => {
                const now = Date.now();
                if (now - dWindow >= 60000) { dWindow = now; dTokens = D_RATE.maxPerMin; }
                if (dTokens > 0) {
                    dTokens--;
                    const jitter = D_RATE.minDelay + Math.floor(Math.random()*(D_RATE.maxDelay-D_RATE.minDelay));
                    const gap = Math.max(0, D_RATE.minDelay - (now - dLastTs));
                    const delay = Math.max(jitter, gap);
                    setTimeout(()=>{ dLastTs = Date.now(); res(); }, delay);
                } else setTimeout(refill, 300);
            };
            refill();
        });
    }
    const UA_POOL = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15'
    ];
    function isDoubanUrl(u){ try{ return /douban\.(com|io)|doubanio\.com/.test(new URL(u).hostname) || /douban/gi.test(u); }catch(_){ return /douban/.test(String(u)); } }
    function doubanRequest(opts){
        return new Promise(async (resolve,reject)=>{
            if (!opts || !opts.url) return reject(new Error('bad-opts'));
            const isDouban = isDoubanUrl(opts.url);
            if (isDouban && inCooldown()) return reject(new Error('cooldown'));
            if (isDouban) await waitDoubanSlot();
            GM_xmlhttpRequest({
                ...opts,
                headers: {
                    'User-Agent': UA_POOL[Math.floor(Math.random()*UA_POOL.length)],
                    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
                    'Referer': 'https://movie.douban.com/',
                    ...(opts.headers||{})
                },
                onload: (res)=>{
                    if (isDouban) {
                        const txt = res.responseText || '';
                        const guarded = (res.finalUrl && /accounts\.|j\/app\/user\/check/.test(res.finalUrl)) || /请证明你是人类|嗯…/.test(txt);
                        if (guarded) { triggerCooldown(90); reject(new Error('douban-guard')); return; }
                    }
                    resolve(res);
                },
                onerror: (e)=> reject(e),
                ontimeout: ()=> reject(new Error('timeout'))
            });
        });
    }

    // 默认配置(用户可以通过配置界面修改)
    // 预连接常用域名,降低首包延迟
    try {
        (function preconnectHosts(hosts){
            try {
                const head = document.head || document.getElementsByTagName('head')[0];
                if (!head) return;
                hosts.forEach(h => {
                    try {
                        const l1 = document.createElement('link'); l1.rel = 'preconnect'; l1.href = h; l1.crossOrigin = 'anonymous'; head.appendChild(l1);
                        const l2 = document.createElement('link'); l2.rel = 'dns-prefetch'; l2.href = h; head.appendChild(l2);
                    } catch(e) {}
                });
            } catch (e) {}
        })([
            'https://movie.douban.com',
            'https://search.douban.com',
            'https://m.douban.com',
            'https://www.douban.com',
            'https://doubanio.com',
            'https://api.themoviedb.org',
            'https://www.themoviedb.org',
            'https://image.tmdb.org'
        ]);
    } catch (e) {}
    const DEFAULT_CONFIG = {
        TMDB: {
            API_KEY: '',
            ACCESS_TOKEN: '',
            BASE_URL: 'https://api.themoviedb.org/3',
            IMAGE_BASE_URL: 'https://image.tmdb.org/t/p/',
            POSTER_SIZE: 'w780',
            STILL_SIZE: 'w780',
            // 新增:列表与选中分级尺寸,提升“看板加载速度+选中质量”
            LIST_POSTER_SIZE: 'w342',
            LIST_STILL_SIZE: 'w300',
            SELECTED_POSTER_SIZE: 'original',
            SELECTED_STILL_SIZE: 'original',
            DOUBAN_QUALITY: {
                PRIORITY: ['raw', 'l', 'm'],
                TIMEOUT: 3000,
                RETRY: 1
            },
            IMAGE_CANDIDATES_COUNT: 5,
            POSTER_PER_ROW: 5,
            STILL_PER_ROW: 5
        },
        AI: {
            API_ENDPOINT: 'https://api.openai.com/v1/chat/completions',
            DEFAULT_MODEL: 'gpt-3.5-turbo',
            API_KEY: '',
            PROVIDER: 'openai',
            FEATURES: [
                { id: 'summary', name: '生成剧情简介', placeholder: '请输入剧情简介要求,例如:详细、简洁、适合推荐等' },
                { id: 'comment', name: '生成评论摘要', placeholder: '请输入评论摘要要求,例如:正面、客观、有深度等' },
                { id: 'tagline', name: '生成宣传标语', placeholder: '请输入宣传标语要求,例如:吸引人、简洁有力等' },
                { id: 'analysis', name: '生成深度分析', placeholder: '请输入分析要求,例如:主题分析、角色分析、视听语言分析等' },
                { id: 'post_format', name: '资源帖排版美化', placeholder: '请输入排版要求,例如:适合论坛发布、美观、信息完整等' },
                { id: 'content_optimize', name: '内容优化建议', placeholder: '请输入优化方向,例如:SEO优化、吸引流量、符合平台规范等' },
                { id: 'format_check', name: '排版合规检查', placeholder: '请输入检查重点,例如:版权信息、敏感词、排版结构等' },
                { id: 'modular_design', name: '模块化排版设计', placeholder: '请输入设计需求,例如:分章节、醒目重点、便于阅读等' }
            ],
            // API获取指南(2025年版)
            API_GUIDE: {
                zhihu: 'https://www.zhihu.com/question/492416413', // AI API汇总
                official: {
                    glm4: 'https://console.baai.ac.cn/',
                    qwen: 'https://modelscope.cn/',
                    xunfei: 'https://www.xfyun.cn/',
                    huggingface: 'https://huggingface.co/',
                    gemini: 'https://makersuite.google.com/'
                }
            },
            // 影视资源帖排版美化智能体框架设定
            POST_FORMAT_GUIDELINES: {
                // 核心工具矩阵:按能力分级的编辑器选型
                BASIC_EDITORS: [
                    {name: '键盘喵速排', features: ['影视推荐专属模板库', '拖拽式操作', '发布前自动检测高风险字符', '响应式布局模块']},
                    {name: 'Canva影视模板库', features: ['16:9黄金比例优化', '一键替换海报素材', '移动端缩略图自动生成']},
                    {name: '163Editor', features: ['双视图编辑模式', '引用块展示影评', '电影评分组件', '实时敏感词检测']}
                ],
                ADVANCED_TOOLS: [
                    {name: 'VS Code插件组合', features: ['Prettier自动格式化', 'Stylelint CSS兼容性检测', 'Live Server实时预览', 'HTML Snippets代码片段']},
                    {name: 'CKEditor4', features: ['精准表格工具', '海报自动压缩', '代码块功能', '可配置影视专用样式']}
                ],
                MARKDOWN_WORKFLOW: [
                    {name: 'Typora+Marked.js', features: ['::: movie语法块', '图片对齐指令', '标准标题层级', '自动过滤危险HTML标签']},
                    {name: 'Markdown2Html', features: ['theme: cinema参数', '图片自适应', '防盗链优化', '模板复用功能']}
                ],

                // 辅助工具链:从美化到合规的全流程支持
                VISUAL_ENHANCEMENT: {
                    COLOR_SYSTEM: {
                        horror: ['#2d3142', '#ef8354'],
                        romance: ['#f8b195', '#f8e1d1'],
                        action: ['#335c67', '#e09f3e'],
                        drama: ['#3a0ca3', '#4361ee'],
                        comedy: ['#ffb347', '#fdfd96'],
                        sciFi: ['#4169e1', '#87cefa'],
                        fantasy: ['#9370db', '#e6e6fa'],
                        anime: ['#ff69b4', '#ffb6c1'],
                        documentary: ['#708090', '#d3d3d3']
                    },
                    IMAGE_OPTIMIZATION: {
                        MAX_WIDTH: 800,
                        MAX_SIZE_KB: 500,
                        QUALITY: 85,
                        UNIFORM_BORDER: '2px solid #e0e0e0',
                        UNIFORM_RADIUS: '5px'
                    },
                    TYPOGRAPHY: {
                        FONT_FAMILY: 'Microsoft Yahei, sans-serif',
                        LINE_HEIGHT: 1.7,
                        PARAGRAPH_SPACING: '20px',
                        HIGHLIGHT_STYLE: 'background:#fff380;padding:0 3px;border-radius:2px'
                    }
                },

                COMPLIANCE_CHECKS: {
                    SENSITIVE_WORDS: {
                        TOOL: 'sensitive-word',
                        KEYWORDS: ['盗版', '枪版', '百度云', '网盘'],
                        REPLACEMENTS: {
                            '百度云': '合规平台',
                            '免费观看': '正版渠道观看',
                            '资源获取': '内容获取'
                        }
                    },
                    COPYRIGHT_RISK: [
                        '优先使用官方宣传海报',
                        '注明"用于影视推荐合理使用"',
                        '用户影评注明来源',
                        '专业影评引用保留作者署名且不超过原文1/3',
                        '仅推荐正规视频平台链接'
                    ],
                    PLATFORM_RULES: {
                        COMMON: ['避免特殊符号(★、→等)', '评分使用文本或CSS实现', '包含"支持正版影视"声明'],
                        MOBILE_OPTIMIZATION: ['按钮最小尺寸44×44px', '删除PC端悬浮效果', '增大触摸区域']
                    }
                },

                // 模块化排版框架:影视资源帖专属结构
                CORE_MODULES: {
                    POSTER_AREA: {
                        HTML: '<div class="poster-container"><img src="海报URL" alt="电影名称海报" class="responsive-poster"><p class="poster-caption">电影官方海报 | 来源:豆瓣电影</p></div>',
                        CSS: '.poster-container {position: relative; padding-bottom: 56.25%; overflow: hidden;} .responsive-poster {position: absolute; width: 100%; height: 100%; object-fit: cover; border-radius: 8px;}'
                    },
                    INFO_CARD: {
                        HTML: '<div class="info-grid"><div class="info-item"><strong>导演</strong>:张艺谋</div><div class="info-item"><strong>类型</strong>:剧情 / 历史</div><div class="info-item"><strong>上映</strong>:2023-09-30</div><div class="info-item"><strong>评分</strong>:<span class="score">9.2</span></div></div>',
                        CSS: '.info-grid {display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; padding: 15px;} .score {background: #2a9d8f; color: white; padding: 2px 8px; border-radius: 12px;}'
                    },
                    SYNOPSIS: {
                        HTML: '<div class="synopsis"><p class="safe-content">影片讲述了...(无剧透版本)</p><details class="full-content"><summary>点击查看完整剧情</summary><p>完整剧情描述...</p></details></div>',
                        CSS: 'summary {list-style: none; color: #2a9d8f; cursor: pointer;} summary::-webkit-details-marker {display: none;}'
                    },
                    REVIEWS: {
                        HTML: '<div class="reviews"><div class="official-review"><p class="reviewer">【官方推荐】</p><p class="content">专业影评内容...</p></div><div class="user-review"><p class="reviewer">观众 @电影爱好者</p><p class="content">用户评论内容...</p></div></div>',
                        CSS: '.official-review {border-left: 3px solid #2a9d8f; padding-left: 15px; margin-bottom: 15px;} .user-review {border-left: 3px solid #94a3b8; padding-left: 15px;} .reviewer {font-weight: bold; margin-bottom: 5px;}'
                    }
                },

                // 合规发布流程:从编辑到上线的校验清单
                PUBLISH_FLOW: {
                    PREPROCESSING: [
                        '素材合规检查:校验海报使用权,符合"宣传性质合理使用"原则',
                        '主题色设定:根据影片类型确定三色体系,全文色彩不超过4种',
                        '模块规划:按"头图→信息卡→剧情→影评→资源提示"搭建框架'
                    ],
                    EDITING: [
                        '文本净化:运行sensitive-word工具扫描全文,替换风险表述',
                        '样式统一:格式化代码,确保margin统一为25px,padding为15px',
                        '响应式测试:在375px、768px、1200px三个断点预览'
                    ],
                    FINAL_CHECK: [
                        '功能测试:点击所有折叠面板和链接按钮,检查交互正常',
                        '合规复查:确认无特殊符号,包含"支持正版影视"声明',
                        '多平台适配:生成掘金版、公众号版、知乎版等不同版本'
                    ]
                },

                // 避坑指南:影视排版高频问题解决方案
                PITFALL_GUIDE: {
                    TECHNICAL_ISSUES: [
                        '图片溢出:使用object-fit: cover裁剪中心区域,配合max-width: 100%',
                        '代码过滤:平台过滤style标签时,转换为内联样式',
                        '加载速度:海报采用渐进式加载,长文本使用分段加载'
                    ],
                    EXPERIENCE_OPTIMIZATION: [
                        '阅读体验:剧情文本行高1.7倍,段落间距20px',
                        '重点突出:使用主色加粗而非特殊符号标注重点内容',
                        '特殊符号:统一替换为【】,评分星星用★文本替代'
                    ],
                    PLATFORM_ADAPTATION: [
                        '掘金:保留代码高亮,优化图片懒加载',
                        '微信公众号:简化样式,优化防盗链格式',
                        '知乎:优化首图尺寸,调整段落间距'
                    ]
                }
            }
        }
    };

    // 配置管理功能
    function getConfig() {
        const config = {
            TMDB: {
                ...DEFAULT_CONFIG.TMDB,
                API_KEY: GM_getValue('tmdb_api_key', ''),
                ACCESS_TOKEN: GM_getValue('tmdb_access_token', '')
            },
            AI: {
                ...DEFAULT_CONFIG.AI,
                API_ENDPOINT: GM_getValue('ai_api_endpoint', DEFAULT_CONFIG.AI.API_ENDPOINT),
                API_KEY: GM_getValue('ai_api_key', ''),
                DEFAULT_MODEL: GM_getValue('ai_model', DEFAULT_CONFIG.AI.DEFAULT_MODEL),
                PROVIDER: GM_getValue('ai_provider', 'openai')
            }
        };
        return config;
    }

    function saveConfig(config) {
        GM_setValue('tmdb_api_key', config.TMDB.API_KEY);
        GM_setValue('tmdb_access_token', config.TMDB.ACCESS_TOKEN);
        GM_setValue('ai_api_endpoint', config.AI.API_ENDPOINT);
        GM_setValue('ai_api_key', config.AI.API_KEY);
        GM_setValue('ai_model', config.AI.DEFAULT_MODEL);
        GM_setValue('ai_provider', config.AI.PROVIDER);
    }

    // 创建配置管理界面
    function createConfigDialog() {
        const dialog = document.createElement('div');
        dialog.id = 'config-dialog';
        dialog.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 50;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Microsoft YaHei', sans-serif;
        `;

        const configPanel = document.createElement('div');
        configPanel.style.cssText = `
            background: white;
            border-radius: 10px;
            padding: 30px;
            max-width: 600px;
            width: 90%;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
        `;

        const currentConfig = getConfig();

        configPanel.innerHTML = `
            <h2 style="margin: 0 0 20px 0; color: #333; text-align: center;">🔧 脚本配置管理</h2>

            <div style="margin-bottom: 25px;">
                <h3 style="color: #2563eb; margin: 0 0 15px 0; border-bottom: 2px solid #e5e7eb; padding-bottom: 8px;">📡 TMDB API 配置</h3>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; font-weight: bold; color: #374151;">API Key:</label>
                    <input type="text" id="tmdb-api-key" value="${currentConfig.TMDB.API_KEY}"
                           style="width: 100%; padding: 8px; border: 1px solid #d1d5db; border-radius: 5px; font-size: 14px;"
                           placeholder="请输入您的TMDB API Key">
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; font-weight: bold; color: #374151;">Access Token:</label>
                    <input type="text" id="tmdb-access-token" value="${currentConfig.TMDB.ACCESS_TOKEN}"
                           style="width: 100%; padding: 8px; border: 1px solid #d1d5db; border-radius: 5px; font-size: 14px;"
                           placeholder="请输入您的TMDB Access Token">
                </div>

                <div style="background: #f3f4f6; padding: 10px; border-radius: 5px; margin-bottom: 15px;">
                    <p style="margin: 0; font-size: 12px; color: #6b7280;">
                        <strong>获取方法:</strong><br>
                        1. 登录(不可用)/注册(不可用)TMDB账号:访问 <a href="https://www.themoviedb.org/" target="_blank" style="color: #2563eb;">TMDB官网</a> ,登录(不可用)或注册(不可用)账号。<br>
                        2. 进入API设置:点击右上角头像→Settings→左侧API选项。<br>
                        3. 获取v3 API Key:在"API Keys (v3 auth)"区域,创建并复制Key。<br>
                        4. 获取v4 Access Token:在"Access Tokens (v4 auth)"区域,生成并复制Token。<br>
                        <br>
                        注意:遵守TMDB服务条款,界面可能微调。
                    </p>
                </div>
                <div style="margin-top:10px; padding:10px; background:#f9fafb; border-radius:6px; border-left:3px solid #8b5cf6;">
                    <p style="margin:0; font-size:12px; color:#6b7280;">
                        <strong>推荐服务商:</strong><br>
                        • <strong>OpenAI:</strong> <a href="https://platform.openai.com/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>Claude:</strong> <a href="https://console.anthropic.com/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>Gemini:</strong> <a href="https://makersuite.google.com/app/apikey" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>豆包:</strong> <a href="https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>通义千问:</strong> <a href="https://dashscope.console.aliyun.com/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>智谱AI (GLM):</strong> <a href="https://open.bigmodel.cn/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>讯飞星火:</strong> <a href="https://console.xfyun.cn/services/bm3" target="_blank" style="color:#2563eb;">获取API Key</a>
                    </p>
                </div>
            </div>

            <div style="margin-bottom: 25px;">
                <h3 style="color: #2563eb; margin: 0 0 15px 0; border-bottom: 2px solid #e5e7eb; padding-bottom: 8px;">🤖 AI API 配置</h3>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; font-weight: bold; color: #374151;">API端点:</label>
                    <select id="ai-provider" style="width: 100%; padding: 8px; border: 1px solid #d1d5db; border-radius: 5px; font-size: 14px; margin-bottom: 10px;">
                        <option value="openai" ${currentConfig.AI.PROVIDER === 'openai' ? 'selected' : ''}>OpenAI</option>
                        <option value="claude" ${currentConfig.AI.PROVIDER === 'claude' ? 'selected' : ''}>Claude (Anthropic)</option>
                        <option value="gemini" ${currentConfig.AI.PROVIDER === 'gemini' ? 'selected' : ''}>Gemini (Google)</option>
                        <option value="doubao" ${currentConfig.AI.PROVIDER === 'doubao' ? 'selected' : ''}>豆包</option>
                        <option value="tongyi" ${currentConfig.AI.PROVIDER === 'tongyi' ? 'selected' : ''}>通义千问</option>
                        <option value="glm" ${currentConfig.AI.PROVIDER === 'glm' ? 'selected' : ''}>智谱AI (GLM)</option>
                        <option value="spark" ${currentConfig.AI.PROVIDER === 'spark' ? 'selected' : ''}>讯飞星火</option>
                        <option value="qwen" ${currentConfig.AI.PROVIDER === 'qwen' ? 'selected' : ''}>通义千问 (Qwen)</option>
                        <option value="zhipu" ${currentConfig.AI.PROVIDER === 'zhipu' ? 'selected' : ''}>智谱AI</option>
                        <option value="custom" ${currentConfig.AI.PROVIDER === 'custom' ? 'selected' : ''}>自定义</option>
                    </select>
                    <div style="color: #6b7280; font-size: 12px; margin-top: 5px;">选择您使用的AI服务提供商,不同提供商可能需要不同的API端点和参数设置</div>
                    <input type="text" id="ai-api-endpoint" value="${currentConfig.AI.API_ENDPOINT}"
                           style="width: 100%; padding: 8px; border: 1px solid #d1d5db; border-radius: 5px; font-size: 14px;"
                           placeholder="API端点地址">
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; font-weight: bold; color: #374151;">API Key:</label>
                    <input type="password" id="ai-api-key" value="${currentConfig.AI.API_KEY}"
                           style="width: 100%; padding: 8px; border: 1px solid #d1d5db; border-radius: 5px; font-size: 14px;"
                           placeholder="请输入您的AI API Key">
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px; font-weight: bold; color: #374151;">模型名称:</label>
                    <input type="text" id="ai-model" value="${currentConfig.AI.DEFAULT_MODEL}"
                           style="width: 100%; padding: 8px; border: 1px solid #d1d5db; border-radius: 5px; font-size: 14px;"
                           placeholder="例如: gpt-3.5-turbo, claude-3-sonnet-20240229">
                </div>

                <div style="background: #f3f4f6; padding: 10px; border-radius: 5px; margin-bottom: 15px;">
                    <p style="margin: 0; font-size: 12px; color: #6b7280;">
                        <strong>推荐服务商:</strong><br>
                        • <strong>OpenAI:</strong> <a href="https://platform.openai.com/" target="_blank" style="color: #2563eb;">获取API Key</a><br>
                        • <strong>Claude:</strong> <a href="https://console.anthropic.com/" target="_blank" style="color: #2563eb;">获取API Key</a><br>
                        • <strong>Gemini:</strong> <a href="https://makersuite.google.com/app/apikey" target="_blank" style="color: #2563eb;">获取API Key</a><br>
                        • <strong>豆包:</strong> <a href="https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D" target="_blank" style="color: #2563eb;">获取API Key</a><br>
                        • <strong>通义千问:</strong> <a href="https://dashscope.console.aliyun.com/" target="_blank" style="color: #2563eb;">获取API Key</a><br>
                        • <strong>智谱AI (GLM):</strong> <a href="https://open.bigmodel.cn/" target="_blank" style="color: #2563eb;">获取API Key</a><br>
                        • <strong>讯飞星火:</strong> <a href="https://console.xfyun.cn/services/bm3" target="_blank" style="color: #2563eb;">获取API Key</a>
                    </p>
                </div>
            </div>

            <div style="text-align: center; margin-top: 30px;">
                <button id="save-config" style="background: #10b981; color: white; border: none; padding: 12px 30px; border-radius: 5px; font-size: 16px; cursor: pointer; margin-right: 10px;">
                    💾 保存配置
                </button>
                <button id="close-config" style="background: #6b7280; color: white; border: none; padding: 12px 30px; border-radius: 5px; font-size: 16px; cursor: pointer;">
                    ❌ 关闭
                </button>
            </div>
        `;

        dialog.appendChild(configPanel);
        document.body.appendChild(dialog);

        // 绑定事件
        document.getElementById('save-config').onclick = () => {
            const newConfig = {
                TMDB: {
                    ...DEFAULT_CONFIG.TMDB,
                    API_KEY: document.getElementById('tmdb-api-key').value.trim(),
                    ACCESS_TOKEN: document.getElementById('tmdb-access-token').value.trim()
                },
                AI: {
                    ...DEFAULT_CONFIG.AI,
                    API_ENDPOINT: document.getElementById('ai-api-endpoint').value.trim(),
                    API_KEY: document.getElementById('ai-api-key').value.trim(),
                    DEFAULT_MODEL: document.getElementById('ai-model').value.trim(),
                    PROVIDER: document.getElementById('ai-provider').value
                }
            };

            saveConfig(newConfig);
            showNotification('配置已保存!', 'success');
            document.body.removeChild(dialog);
        };

        document.getElementById('close-config').onclick = () => {
            document.body.removeChild(dialog);
        };

        // 提供商选择变化时更新端点
        document.getElementById('ai-provider').onchange = () => {
            const provider = document.getElementById('ai-provider').value;
            const endpointInput = document.getElementById('ai-api-endpoint');

            switch(provider) {
                case 'openai':
                    endpointInput.value = 'https://api.openai.com/v1/chat/completions';
                    break;
                case 'claude':
                    endpointInput.value = 'https://api.anthropic.com/v1/messages';
                    break;
                case 'gemini':
                    endpointInput.value = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent';
                    break;
                default:
                    endpointInput.value = '';
            }
        };

        // 点击背景关闭
        dialog.onclick = (e) => {
            if (e.target === dialog) {
                document.body.removeChild(dialog);
            }
        };
    }

    const COMMON_HEADERS = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        // 避免跳转到 app/user/check 等登录(不可用)检测页
        'Sec-Fetch-Mode': 'navigate',
        'Sec-Fetch-Site': 'same-origin'
    };

    // 存储变量
    let selectedPosterUrl = '';
    let selectedStillUrl = '';
    // AI区域多选集合(不影响主流程单选逻辑)
    let aiSelectedPosterUrls = new Set();
    let aiSelectedStillUrls = new Set();
    // AI侧独立的影片信息,避免与主流程共享状态
    let aiCurrentMovieInfo = null;
    // AI请求控制器(用于终止)
    let aiCurrentRequest = null;
    let aiAbortReject = null;
    // 主功能与AI隔离标记
    let isMainFlowActive = false;
    // 控制台防刷屏:仅提示一次未检测到编辑器
    let editorNotFoundLogged = false;
    // 防重复绑定AI事件
    let aiEventsBound = false;
    let currentMovieInfo = null;
    let currentComments = [];
    let sourceCodeElement = null;
    let panelObserver = null;
    let isPanelInitialized = false;
    let currentEditor = null;
    let posterPage = 1; // 海报当前页(初始1)
    let stillPage = 1;  // 剧照当前页(初始1)
    let isLoadingPosters = false;
    let isLoadingStills = false;
    let posterContainer = null;
    let stillContainer = null;
    let panel = null;
    let selectedPosterEl = null;
    let selectedStillEl = null;

    // 排版美化样式库
    const FORMAT_STYLES = [
        {
            name: '主标题',
            icon: 'fa-header',
            tag: 'h1',
            category: '标题',
            styles: {
                'color': '#1e40af',
                'font-size': '24px',
                'font-weight': 'bold',
                'margin': '20px 0 15px 0',
                'padding-bottom': '8px',
                'border-bottom': '2px solid #dbeafe'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '主标题示例';
                return `<h1 style="color:#1e40af;font-size:24px;font-weight:bold;margin:20px 0 15px 0;padding-bottom:8px;border-bottom:2px solid #dbeafe;">${content}</h1>`;
            }
        },
        {
            name: '副标题',
            icon: 'fa-header',
            tag: 'h2',
            category: '标题',
            styles: {
                'color': '#2563eb',
                'font-size': '20px',
                'font-weight': 'bold',
                'margin': '18px 0 12px 0',
                'padding-bottom': '5px',
                'border-bottom': '1px solid #dbeafe'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '副标题示例';
                return `<h2 style="color:#2563eb;font-size:20px;font-weight:bold;margin:18px 0 12px 0;padding-bottom:5px;border-bottom:1px solid #dbeafe;">${content}</h2>`;
            }
        },
        {
            name: '三级标题',
            icon: 'fa-header',
            tag: 'h3',
            category: '标题',
            styles: {
                'color': '#3b82f6',
                'font-size': '18px',
                'font-weight': 'bold',
                'margin': '15px 0 10px 0'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '三级标题示例';
                return `<h3 style="color:#3b82f6;font-size:18px;font-weight:bold;margin:15px 0 10px 0;">${content}</h3>`;
            }
        },
        {
            name: '正文段落',
            icon: 'fa-paragraph',
            tag: 'p',
            category: '文本',
            styles: {
                'color': '#333',
                'font-size': '14px',
                'line-height': '1.8',
                'margin': '8px 0',
                'text-indent': '2em'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '这是一段正文示例,包含标准的段落格式和首行缩进,适合用于大部分内容的展示。';
                return `<p style="color:#333;font-size:14px;line-height:1.8;margin:8px 0;text-indent:2em;">${content}</p>`;
            }
        },
        {
            name: '引用文本',
            icon: 'fa-quote-right',
            tag: 'blockquote',
            category: '文本',
            styles: {
                'color': '#666',
                'font-size': '13px',
                'line-height': '1.6',
                'margin': '10px 0',
                'padding': '10px 15px',
                'border-left': '3px solid #2196F3',
                'background': '#f8f9fa'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '这是一段引用文本示例,通常用于引用他人的话语或特殊说明内容。';
                return `<blockquote style="color:#666;font-size:13px;line-height:1.6;margin:10px 0;padding:10px 15px;border-left:3px solid #2196F3;background:#f8f9fa;">${content}</blockquote>`;
            }
        },
        {
            name: '无序列表',
            icon: 'fa-list-ul',
            tag: 'ul',
            category: '列表',
            styles: {
                'margin': '10px 0 10px 20px',
                'padding': '0'
            },
            itemStyles: {
                'color': '#444',
                'font-size': '14px',
                'line-height': '1.7',
                'margin': '5px 0',
                'list-style-type': 'disc'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '列表项1\n列表项2\n列表项3';
                const items = content.split('\n').map(item =>
                    `<li style="color:#444;font-size:14px;line-height:1.7;margin:5px 0;list-style-type:disc;">${item.trim()}</li>`
                ).join('');
                return `<ul style="margin:10px 0 10px 20px;padding:0;">${items}</ul>`;
            }
        },
        {
            name: '有序列表',
            icon: 'fa-list-ol',
            tag: 'ol',
            category: '列表',
            styles: {
                'margin': '10px 0 10px 20px',
                'padding': '0'
            },
            itemStyles: {
                'color': '#444',
                'font-size': '14px',
                'line-height': '1.7',
                'margin': '5px 0'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '步骤一\n步骤二\n步骤三';
                const items = content.split('\n').map(item =>
                    `<li style="color:#444;font-size:14px;line-height:1.7;margin:5px 0;">${item.trim()}</li>`
                ).join('');
                return `<ol style="margin:10px 0 10px 20px;padding:0;">${items}</ol>`;
            }
        },
        {
            name: '分隔线',
            icon: 'fa-minus',
            tag: 'hr',
            category: '布局',
            styles: {
                'border': 'none',
                'border-top': '1px solid #e0e0e0',
                'margin': '20px 0',
                'height': '1px'
            },
            preview: true,
            apply: () => {
                return `<hr style="border:none;border-top:1px solid #e0e0e0;margin:20px 0;height:1px;">`;
            }
        },
        {
            name: '高亮文本',
            icon: 'fa-highlighter',
            tag: 'span',
            category: '文本',
            styles: {
                'background': '#fff380',
                'padding': '0 3px',
                'border-radius': '2px'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '需要高亮的文本';
                return `<span style="background:#fff380;padding:0 3px;border-radius:2px;">${content}</span>`;
            }
        },
        {
            name: '链接样式',
            icon: 'fa-link',
            tag: 'a',
            category: '文本',
            styles: {
                'color': '#2563eb',
                'text-decoration': 'none',
                'border-bottom': '1px dashed #93c5fd',
                'padding': '0 1px'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '链接文本';
                return `<a href="#" style="color:#2563eb;text-decoration:none;border-bottom:1px dashed #93c5fd;padding:0 1px;">${content}</a>`;
            }
        },
        {
            name: '居中文本',
            icon: 'fa-align-center',
            tag: 'div',
            category: '布局',
            styles: {
                'text-align': 'center',
                'margin': '10px 0',
                'color': '#4b5563'
            },
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '这段文本会居中显示';
                return `<div style="text-align:center;margin:10px 0;color:#4b5563;">${content}</div>`;
            }
        },
        {
            name: '影视卡片',
            icon: 'fa-film',
            tag: 'div',
            category: '特殊',
            preview: true,
            apply: (selectedText) => {
                const title = selectedText || '影视名称';
                return `
<div style="border:1px solid #e5e7eb;border-radius:6px;padding:15px;margin:15px 0;box-shadow:0 1px 3px rgba(0,0,0,0.05);">
  <h3 style="margin-top:0;color:#1e40af;">${title}</h3>
  <p style="margin-bottom:0;color:#4b5563;font-size:14px;">这里可以添加影视的简要说明或推荐理由...</p>
</div>
                `;
            }
        },
        {
            name: '装饰标题',
            icon: 'fa-magic',
            tag: 'h3',
            category: '标题',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '装饰标题示例';
                return `<h3 style="position:relative;color:#db2777;font-size:18px;font-weight:700;margin:18px 0 12px 0;padding-left:10px;">
  <span style="position:absolute;left:0;top:3px;width:4px;height:18px;background:#f472b6;border-radius:2px;"></span>
  ${content}
</h3>`;
            }
        },
        {
            name: '序号标题',
            icon: 'fa-list-ol',
            tag: 'h3',
            category: '标题',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '01 序号标题示例';
                return `<h3 style="color:#1e40af;font-size:18px;font-weight:700;margin:16px 0;">${content}</h3>`;
            }
        },
        {
            name: '信息提示',
            icon: 'fa-info-circle',
            tag: 'div',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '这是信息提示内容';
                return `<div style="background:#eff6ff;border:1px solid #bfdbfe;color:#1e40af;padding:10px 12px;border-radius:8px;">${content}</div>`;
            }
        },
        {
            name: '成功提示',
            icon: 'fa-check-circle',
            tag: 'div',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '操作已成功完成';
                return `<div style="background:#ecfdf5;border:1px solid #a7f3d0;color:#065f46;padding:10px 12px;border-radius:8px;">${content}</div>`;
            }
        },
        {
            name: '警告提示',
            icon: 'fa-exclamation-triangle',
            tag: 'div',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '请注意可能的风险';
                return `<div style="background:#fff7ed;border:1px solid #fed7aa;color:#9a3412;padding:10px 12px;border-radius:8px;">${content}</div>`;
            }
        },
        {
            name: '错误提示',
            icon: 'fa-times-circle',
            tag: 'div',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '发生错误,请重试';
                return `<div style="background:#fef2f2;border:1px solid #fecaca;color:#991b1b;padding:10px 12px;border-radius:8px;">${content}</div>`;
            }
        },
        {
            name: '代码块',
            icon: 'fa-code',
            tag: 'pre',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = (selectedText || 'const hello = "world";').replace(/</g,'&lt;').replace(/>/g,'&gt;');
                return `<pre style="background:#0b1021;color:#e5e7eb;padding:12px;border-radius:8px;overflow:auto;font:12px/1.6 Consolas,Monaco,monospace;">${content}</pre>`;
            }
        },
        {
            name: '任务清单',
            icon: 'fa-tasks',
            tag: 'ul',
            category: '列表',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '[ ] 待办一\n[x] 已完成项\n[ ] 待办二';
                const items = content.split('\n').map(line => {
                    const done = /\[x\]/i.test(line);
                    const text = line.replace(/\[[ xX]\]\s*/,'');
                    return `<li style="list-style:none;margin:6px 0;font-size:14px;color:#374151;">
  <span style="display:inline-block;width:14px;height:14px;margin-right:8px;border:1px solid #d1d5db;border-radius:3px;background:${done?'#10b981':'#fff'};"></span>${text}
</li>`;
                }).join('');
                return `<ul style="margin:10px 0 10px 4px;padding:0;">${items}</ul>`;
            }
        },
        {
            name: '标签云',
            icon: 'fa-tags',
            tag: 'div',
            category: '列表',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '剧情|动作|冒险|爱情|科幻|动画';
                const chips = content.split(/\||,|\s+/).filter(Boolean).slice(0,12).map(t => `<span style="display:inline-block;margin:4px 6px 0 0;padding:3px 10px;border-radius:12px;background:#fff0f6;border:1px solid #fbcfe8;font-size:12px;color:#be185d;">${t}</span>`).join('');
                return `<div style="margin:8px 0;">${chips}</div>`;
            }
        },
        {
            name: '两列栅格',
            icon: 'fa-columns',
            tag: 'div',
            category: '布局',
            preview: true,
            apply: (selectedText) => {
                const a = '左侧内容';
                const b = '右侧内容';
                return `<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:10px 0;">
  <div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:10px;color:#374151;">${a}</div>
  <div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:10px;color:#374151;">${b}</div>
</div>`;
            }
        },
        {
            name: '三列栅格',
            icon: 'fa-th',
            tag: 'div',
            category: '布局',
            preview: true,
            apply: () => {
                return `<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:10px 0;">
  <div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:10px;color:#374151;">区块A</div>
  <div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:10px;color:#374151;">区块B</div>
  <div style="background:#fff;border:1px solid #e5e7eb;border-radius:8px;padding:10px;color:#374151;">区块C</div>
</div>`;
            }
        },
        {
            name: '图片说明卡',
            icon: 'fa-image',
            tag: 'div',
            category: '布局',
            preview: true,
            apply: () => {
                return `<div style="display:flex;gap:12px;align-items:flex-start;border:1px solid #e5e7eb;border-radius:8px;padding:10px;">
  <img src="https://picsum.photos/120/80" style="width:120px;height:80px;border-radius:6px;object-fit:cover;" alt="图"/>
  <div style="color:#4b5563;font-size:14px;line-height:1.7;">这里是配图说明文字,可替换为剧情简介、片段描述或使用说明。</div>
</div>`;
            }
        },
        {
            name: '强调按钮',
            icon: 'fa-hand-pointer-o',
            tag: 'a',
            category: '特殊',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '点此查看';
                return `<a href="#" style="display:inline-block;background:linear-gradient(135deg,#ec4899 0%,#be185d 100%);color:#fff;padding:8px 14px;border-radius:8px;text-decoration:none;box-shadow:0 2px 6px rgba(236,72,153,.25);">${content}</a>`;
            }
        },
        {
            name: '下载按钮',
            icon: 'fa-download',
            tag: 'a',
            category: '特殊',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '下载资源';
                return `<a href="#" style="display:inline-block;background:#10b981;color:#fff;padding:8px 14px;border-radius:8px;text-decoration:none;box-shadow:0 2px 6px rgba(16,185,129,.25);">${content}</a>`;
            }
        },
        {
            name: '流程步骤',
            icon: 'fa-arrow-right',
            tag: 'ol',
            category: '列表',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '准备素材\n编辑排版\n发布分享';
                const items = content.split('\n').map((t, i) => `<li style="counter-increment:step;margin:8px 0;padding-left:28px;position:relative;color:#374151;">
  <span style="position:absolute;left:0;top:0;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:#ec4899;color:#fff;font-size:12px;">${i+1}</span>${t}
</li>`).join('');
                return `<ol style="list-style:none;margin:10px 0;padding:0;">${items}</ol>`;
            }
        },
        {
            name: '折叠面板',
            icon: 'fa-chevron-down',
            tag: 'details',
            category: '布局',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '这里是可展开的详细说明内容';
                return `<details style="border:1px solid #e5e7eb;border-radius:8px;padding:10px;background:#fff;">
  <summary style="cursor:pointer;color:#db2777;font-weight:600;outline:none;">点击展开/收起</summary>
  <div style="margin-top:8px;color:#4b5563;font-size:14px;line-height:1.7;">${content}</div>
</details>`;
            }
        },
        {
            name: '两列表格',
            icon: 'fa-table',
            tag: 'table',
            category: '布局',
            preview: true,
            apply: () => {
                return `<table style="width:100%;border-collapse:collapse;margin:10px 0;">
  <tr>
    <td style="width:30%;background:#fff0f6;border:1px solid #fbcfe8;padding:8px;color:#be185d;">属性</td>
    <td style="border:1px solid #fbcfe8;padding:8px;color:#374151;">值</td>
  </tr>
  <tr>
    <td style="background:#fff0f6;border:1px solid #fbcfe8;padding:8px;color:#be185d;">导演</td>
    <td style="border:1px solid #fbcfe8;padding:8px;color:#374151;">——</td>
  </tr>
</table>`;
            }
        },
        {
            name: '引用卡片',
            icon: 'fa-quote-left',
            tag: 'div',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = selectedText || '这是一段加框的引用卡片内容,用于强调引用。';
                return `<div style="border-left:4px solid #93c5fd;background:#f0f9ff;padding:10px 12px;border-radius:6px;color:#1e40af;">${content}</div>`;
            }
        },
        {
            name: '下沉首字',
            icon: 'fa-bold',
            tag: 'p',
            category: '文本',
            preview: true,
            apply: (selectedText) => {
                const content = (selectedText || '首字下沉示例段落,用于提升视觉层次与阅读趣味。');
                const first = content.slice(0,1);
                const rest = content.slice(1);
                return `<p style="font-size:14px;line-height:1.9;color:#333;margin:10px 0;">
  <span style="float:left;font-size:36px;line-height:1;height:36px;margin:6px 8px 0 0;color:#db2777;font-weight:700;">${first}</span>${rest}
</p>`;
            }
        },
        {
            name: '图片区块',
            icon: 'fa-picture-o',
            tag: 'div',
            category: '布局',
            preview: true,
            apply: () => {
                return `<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:10px 0;">
  ${[1,2,3,4].map(i=>`<img src="https://picsum.photos/200/120?${i}" style="width:100%;height:120px;object-fit:cover;border-radius:6px;" alt="图${i}"/>`).join('')}
</div>`;
            }
        },
        {
            name: '免责声明',
            icon: 'fa-shield',
            tag: 'div',
            category: '特殊',
            preview: true,
            apply: () => {
                return `<div style="background:#fff7ed;border:1px dashed #fdba74;color:#9a3412;padding:10px 12px;border-radius:8px;font-size:12px;">
仅供学习与交流,禁止用于商业用途,版权归原平台与权利人所有。
</div>`;
            }
        },
        {
            name: '按钮组',
            icon: 'fa-bars',
            tag: 'div',
            category: '特殊',
            preview: true,
            apply: () => {
                return `<div style="display:flex;gap:8px;flex-wrap:wrap;margin:8px 0;">
  <a href="#" style="background:#ec4899;color:#fff;padding:6px 12px;border-radius:6px;text-decoration:none;">主操作</a>
  <a href="#" style="background:#9ca3af;color:#fff;padding:6px 12px;border-radius:6px;text-decoration:none;">次操作</a>
</div>`;
            }
        },
        {
            name: '彩色分隔条',
            icon: 'fa-minus',
            tag: 'hr',
            category: '布局',
            preview: true,
            apply: () => `<div style="height:6px;background:linear-gradient(90deg,#ec4899,#a78bfa,#60a5fa,#34d399);border-radius:999px;margin:16px 0;"></div>`
        }
    ];

    // 自动填充和保存相关函数
    function autoClickSourceBtn() {
        return new Promise((resolve) => {
            const modalSourceBtn = document.querySelector('#myModal-code .btn, #source-code-btn');
            if (modalSourceBtn && modalSourceBtn.textContent.includes('源代码')) {
                modalSourceBtn.click();
                setTimeout(() => resolve(true), 600);
                return;
            }

            const textButtons = [...document.querySelectorAll('button'), ...document.querySelectorAll('a')]
                .filter(elem => elem.textContent.trim().includes('源代码'));
            if (textButtons.length > 0) {
                textButtons[0].click();
                setTimeout(() => resolve(true), 300);
                return;
            }

            const tinyMceBtn = document.querySelector('.tox-tbtn[title="源代码"]');
            const oldTinyMceBtn = Array.from(document.querySelectorAll('.mce-btn')).find(elem => elem.textContent.includes('源代码'));
            const ckSourceLabel = document.querySelector('.cke_button__source_label');

            if (tinyMceBtn) {
                tinyMceBtn.click();
                setTimeout(() => resolve(true), 300);
            } else if (oldTinyMceBtn) {
                oldTinyMceBtn.click();
                setTimeout(() => resolve(true), 300);
            } else if (ckSourceLabel && ckSourceLabel.closest('.cke_button')) {
                ckSourceLabel.closest('.cke_button').click();
                setTimeout(() => resolve(true), 300);
            } else {
                resolve(true);
            }
        });
    }

    // 关闭TinyMCE/CKEditor等源代码对话框或退出源码模式
    function closeSourceDialogIfAny() {
        try {
            // TinyMCE 源代码对话框常见关闭按钮
            const closeBtns = [
                '.tox-dialog__footer .tox-button',
                '.tox-dialog__close',
                '.modal .close',
                '.dialog .close',
                '[aria-label="Close"]'
            ];
            for (const sel of closeBtns) {
                const el = document.querySelector(sel);
                if (el) { el.click(); break; }
            }
        } catch (_) {}
        try {
            // 如果仍在源码模式,尝试再次点击按钮退出
            const btn = document.querySelector('.tox-tbtn[title="源代码"], #source-code-btn');
            if (btn) btn.click();
        } catch (_) {}
    }

    function autoFillSourceBox(html) {
        return new Promise((resolve) => {
            // 内容非空:确保HTML内容不为空
            const safeHtml = html || `<div style="padding: 20px; background-color: #f8f9fa; border-radius: 4px;">内容已自动生成</div>`;

            let retryCount = 0;
            const maxRetry = 20;
            const interval = 300;

            const tryFill = setInterval(() => {
                retryCount++;
                const editorSelectors = [
                    '#myModal-code textarea',
                    'textarea.tox-textarea',
                    'textarea.mce-textbox',
                    'textarea.cke_source',
                    'textarea[name="message"]',
                    'textarea[name="content"]',
                    '#editor_content',
                    '#content',
                    'textarea[rows="20"][cols="80"]',
                    '.CodeMirror textarea',
                    '.editor-textarea',
                    // 扩展选择器范围,增强兼容性
                    '.content-editor textarea',
                    '.article-editor textarea',
                    'div[contenteditable="true"]',
                    '[role="textbox"]'
                ];

                let targetBox = null;
                for (const selector of editorSelectors) {
                    const elem = document.querySelector(selector);
                    if (elem && elem.style.display !== 'none' && elem.offsetParent !== null) {
                        targetBox = elem;
                        sourceCodeElement = elem;
                        currentEditor = getCurrentEditor();
                        break;
                    }
                }

                if (targetBox) {
                    const codeMirror = targetBox.closest('.CodeMirror');
                    if (codeMirror) {
                        // 处理CodeMirror编辑器的多种情况
                        if (codeMirror.CodeMirror) {
                            // 标准CodeMirror实例
                            try {
                                codeMirror.CodeMirror.setValue(safeHtml);
                                codeMirror.CodeMirror.getDoc().markClean();
                                codeMirror.CodeMirror.getDoc().changed();

                                // 触发额外的事件来模拟真实用户输入
                                codeMirror.CodeMirror.focus();
                                codeMirror.CodeMirror.refresh();

                                // 尝试通过编辑器的内部API触发变化通知,但避免触发验证
                                if (codeMirror.CodeMirror.on) {
                                    try {
                                        codeMirror.CodeMirror.on('change', codeMirror.CodeMirror.getDoc());
                                    } catch (e) {
                                        // 静默忽略可能的错误
                                    }
                                }
                            } catch (cmError) {
                                console.log('CodeMirror编辑器操作失败:', cmError);
                                // 降级处理:直接操作textarea
                                targetBox.value = safeHtml;
                                triggerNonBubblingEvents(targetBox);
                            }
                        } else {
                            // 直接操作textarea(更贴近用户输入行为)
                            targetBox.value = safeHtml;
                            triggerNonBubblingEvents(targetBox);
                        }
                    } else {
                        // 普通文本框处理或contenteditable元素
                        if (targetBox.isContentEditable) {
                            // 处理contenteditable元素
                            targetBox.innerHTML = safeHtml;
                            triggerNonBubblingEvents(targetBox);
                        } else {
                            // 普通文本框处理
                            targetBox.value = safeHtml;
                            triggerNonBubblingEvents(targetBox);
                        }
                    }

                    // 增加短暂延迟确保所有事件都被处理
                    setTimeout(() => {
                        clearInterval(tryFill);
                        resolve(true);
                    }, 500); // 延长延迟时间,确保更可靠的填充
                    return;
                }

                if (retryCount >= maxRetry) {
                    clearInterval(tryFill);
                    // 粘贴失败时自动复制内容到剪贴板
                    try {
                        navigator.clipboard.writeText(safeHtml).then(() => {
                            showStatus('内容自动复制到剪贴板,请手动粘贴!', true);
                        }).catch(err => {
                            showStatus('内容粘贴失败,剪贴板复制也失败,请手动复制内容!', true);
                            console.error('剪贴板写入失败:', err);
                        });
                    } catch (e) {
                        showStatus('内容粘贴失败,请手动复制内容!', true);
                        console.error('自动复制功能失败:', e);
                    }
                    resolve(false);
                }
            }, interval);
        });
    }

    // 触发阻断:创建不冒泡的事件并触发,防止触发表单验证
    function triggerNonBubblingEvents(element) {
        if (!element) return;

        // 创建不冒泡的事件
        const createNonBubblingEvent = (type, eventType = 'Event') => {
            let event;
            if (eventType === 'KeyboardEvent') {
                event = new KeyboardEvent(type, {
                    bubbles: false,
                    cancelable: true,
                    key: 'Enter'
                });
            } else {
                event = new Event(type, {
                    bubbles: false,
                    cancelable: true
                });
            }

            // 定义空的stopPropagation方法,确保事件不会冒泡
            Object.defineProperty(event, 'stopPropagation', {
                value: function() {},
                writable: false
            });

            return event;
        };

        try {
            // 触发基础事件
            element.dispatchEvent(createNonBubblingEvent('focus'));
            element.dispatchEvent(createNonBubblingEvent('input'));
            element.dispatchEvent(createNonBubblingEvent('change'));
            element.dispatchEvent(createNonBubblingEvent('compositionend'));

            // 触发键盘事件
            element.dispatchEvent(createNonBubblingEvent('keydown', 'KeyboardEvent'));
            element.dispatchEvent(createNonBubblingEvent('keypress', 'KeyboardEvent'));
            element.dispatchEvent(createNonBubblingEvent('keyup', 'KeyboardEvent'));

            // 短暂聚焦然后失焦,完成编辑过程
            element.focus();
            if (element.setSelectionRange && typeof element.value === 'string') {
                element.setSelectionRange(element.value.length, element.value.length);
            }

            setTimeout(() => {
                element.dispatchEvent(createNonBubblingEvent('blur'));
            }, 100);
        } catch (eventError) {
            console.log('触发事件时发生错误:', eventError);
        }
    }

    function autoClickSaveBtn() {
        return new Promise((resolve) => {
            const saveButtons = [
                ...document.querySelectorAll('button'),
                ...document.querySelectorAll('a')
            ].filter(elem => {
                const text = elem.textContent.trim();
                return text === '保存' || text === '保存草稿' || text === '保存内容';
            });

            if (saveButtons.length > 0) {
                saveButtons[0].click();
                setTimeout(() => resolve(true), 500);
                return;
            }

            const commonSaveBtn = document.querySelector('button.save, .save-button, [type="submit"][value="保存"]');
            if (commonSaveBtn && !commonSaveBtn.textContent.includes('发布')) {
                commonSaveBtn.click();
                setTimeout(() => resolve(true), 500);
                return;
            }

            resolve(false);
        });
    }

    // 统一写入助手:尽最大努力把HTML写入任一编辑器(TinyMCE/CodeMirror/textarea/iframe/contenteditable)
    async function writeHtmlToAnyEditor(html) {
        try {
            const safeHtml = html || '';
            // 1) TinyMCE 优先
            try {
                const tiny = window.tinymce || window.tinyMCE;
                let ed = null;
                if (tiny) {
                    ed = tiny.activeEditor || (tiny.editors && tiny.editors[0]) || (tiny.EditorManager && tiny.EditorManager.activeEditor) || null;
                    if (!ed && typeof tiny.get === 'function') {
                        // 尝试根据textarea id获取
                        const ta = document.querySelector('textarea[id]');
                        if (ta) { ed = tiny.get(ta.id) || ed; }
                    }
                }
                if (ed && typeof ed.setContent === 'function') {
                    ed.setContent(safeHtml);
                    try { if (typeof ed.setDirty === 'function') ed.setDirty(true); } catch(_) {}
                    try { if (tiny && typeof tiny.triggerSave === 'function') tiny.triggerSave(); } catch(_) {}
                    return true;
                }
            } catch (_) {}

            // 2) 使用现有的getCurrentEditor工具(CodeMirror/textarea)
            try {
                const editor = getCurrentEditor && getCurrentEditor();
                if (editor) {
                    if (editor.type === 'codemirror' && editor.instance && typeof editor.instance.setValue === 'function') {
                        editor.instance.setValue(safeHtml);
                        return true;
                    } else if (editor.instance) {
                        editor.instance.value = safeHtml;
                        editor.instance.dispatchEvent(new Event('input', { bubbles: true }));
                        return true;
                    }
                }
            } catch(_) {}

            // 3) TinyMCE iframe 兜底
            try {
                const iframe = document.querySelector('.tox-edit-area iframe, iframe.tox-edit-area__iframe, .mce-edit-area iframe');
                if (iframe && iframe.contentDocument && iframe.contentDocument.body) {
                    iframe.contentDocument.body.innerHTML = safeHtml;
                    iframe.contentDocument.body.dispatchEvent(new Event('input', { bubbles: true }));
                    return true;
                }
            } catch(_) {}

            // 4) contenteditable 兜底
            try {
                const editable = document.querySelector('[contenteditable="true"], [contenteditable=true]');
                if (editable) { editable.innerHTML = safeHtml; return true; }
            } catch(_) {}

            // 5) 直接向可见textarea写入
            try {
                const ta = Array.from(document.querySelectorAll('textarea')).find(t => t.offsetParent !== null);
                if (ta) { ta.value = safeHtml; ta.dispatchEvent(new Event('input', { bubbles: true })); return true; }
            } catch(_) {}

            return false;
        } catch (e) { return false; }
    }

    function autoFillTitleInput(title) {
        return new Promise((resolve) => {
            const titleInput = document.querySelector('input[placeholder="标题"], input[name="title"], #title');
            if (!titleInput) {
                resolve(false);
                return;
            }
            titleInput.value = title || (currentMovieInfo?.title || '影视内容分享');
            titleInput.dispatchEvent(new Event('input', { bubbles: true }));
            titleInput.dispatchEvent(new Event('change', { bubbles: true }));
            const keydownEvent = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true });
            const keyupEvent = new KeyboardEvent('keyup', { key: 'Enter', bubbles: true });
            titleInput.dispatchEvent(keydownEvent);
            titleInput.dispatchEvent(keyupEvent);
            resolve(true);
        });
    }

    async function fillAndSaveSource(html, enableAutoSave = false) {
        try {
            // 边界隔离:此函数主要负责内容填充,根据enableAutoSave参数决定是否执行保存操作

            // 内容非空:确保标题不为空,即使没有影视信息也提供默认值
            const movieTitle = currentMovieInfo?.title || '影视内容分享';
            await autoFillTitleInput(movieTitle);

            showStatus('正在切换到源代码模式...', false);
            const switched = await autoClickSourceBtn();

            if (!switched) {
                showStatus('未检测到源代码按钮,尝试直接填充...', false);
            }

            showStatus('正在填充内容到编辑框...', false);

            // 内容非空:确保HTML内容不为空
            const safeHtml = html || `<div style="padding: 20px; background-color: #f8f9fa; border-radius: 4px;">内容已自动生成</div>`;
            const filled = await autoFillSourceBox(safeHtml);

            if (filled) {
                // 轻量延迟,确保内容写入完成
                await new Promise(resolve => setTimeout(resolve, 120));

                // 内容非空:检查并填充所有可能的必填字段,扩展选择器范围
                const allInputSelectors = [
                    'input[required]:not([type="hidden"])',
                    'textarea[required]:not([type="hidden"])',
                    'input[placeholder*="必填"], textarea[placeholder*="必填"]',
                    'input[name="content"], textarea[name="content"]',
                    'input[name="text"], textarea[name="text"]',
                    'input[data-required="true"], textarea[data-required="true"]',
                    '[ng-required="true"]',
                    '.required-field',
                    '.required-input',
                    '#content-input, #text-input',
                    '.editor-container textarea',
                    '.main-content textarea'
                ];

                // 合并所有选择器
                const allInputs = document.querySelectorAll(allInputSelectors.join(','));

                // 内容非空:预填充所有可能的输入框
                allInputs.forEach(input => {
                    // 检查元素是否可见且无内容
                    if (!input.value.trim() && input.style.display !== 'none' && input.offsetParent !== null) {
                        // 为不同类型的输入框提供合适的默认值
                        if (input.type === 'text' || input.type === 'textarea' || input.tagName.toLowerCase() === 'textarea') {
                            // 为文本输入框填充更详细的默认内容
                            const placeholder = input.getAttribute('placeholder') || '内容已自动生成';
                            input.value = placeholder;

                            // 触发阻断:阻止事件冒泡,防止触发表单验证
                            const createBubblesBlockedEvent = (type) => {
                                const event = new Event(type, { bubbles: false, cancelable: true });
                                Object.defineProperty(event, 'stopPropagation', {
                                    value: function() {}
                                });
                                return event;
                            };

                            // 触发更多事件以模拟真实用户输入,但阻止冒泡
                            const events = [
                                createBubblesBlockedEvent('focus'),
                                createBubblesBlockedEvent('input'),
                                createBubblesBlockedEvent('change'),
                                createBubblesBlockedEvent('blur')
                            ];

                            events.forEach(event => {
                                input.dispatchEvent(event);
                            });

                            // 特殊事件:键盘事件和组合事件,同样阻止冒泡
                            const createKeyboardEventNoBubbles = (type, key) => {
                                const event = new KeyboardEvent(type, { key, bubbles: false });
                                Object.defineProperty(event, 'stopPropagation', {
                                    value: function() {}
                                });
                                return event;
                            };

                            const keyboardEvents = [
                                createKeyboardEventNoBubbles('keydown', 'a'),
                                createKeyboardEventNoBubbles('keypress', 'a'),
                                createKeyboardEventNoBubbles('keyup', 'a')
                            ];

                            keyboardEvents.forEach(event => {
                                input.dispatchEvent(event);
                            });
                        }
                    }
                });

                // 额外检查并设置编辑器内容的标记,防止验证时认为内容为空
                if (window.editor && typeof window.editor.setContent === 'function') {
                    try {
                        window.editor.setContent(safeHtml);
                        // 强制设置编辑器内部状态为已编辑
                        if (window.editor && typeof window.editor.isDirty === 'function') {
                            window.editor.isDirty = () => true;
                        }
                    } catch (editorError) {
                        console.log('设置编辑器内容失败:', editorError);
                    }
                }

                // 快速保存:先尝试直接保存,失败再回退补齐必填项后再保存
                if (enableAutoSave) {
                    let saved = await autoClickSaveBtn();
                    if (!saved) {
                        const selectors = [
                            'input[required]:not([type="hidden"])',
                            'textarea[required]:not([type="hidden"])',
                            'input[placeholder*="必填"], textarea[placeholder*="必填"]',
                            'input[name="content"], textarea[name="content"]',
                            'input[name="text"], textarea[name="text"]',
                            'input[data-required="true"], textarea[data-required="true"]',
                            '[ng-required="true"]',
                            '.required-field',
                            '.required-input',
                            '#content-input, #text-input',
                            '.editor-container textarea',
                            '.main-content textarea'
                        ];
                        document.querySelectorAll(selectors.join(',')).forEach(input => {
                            if (!input.value || !String(input.value).trim()) {
                                const placeholder = input.getAttribute('placeholder') || '内容已自动生成';
                                input.value = placeholder;
                                input.dispatchEvent(new Event('input', { bubbles: true }));
                                input.dispatchEvent(new Event('change', { bubbles: true }));
                            }
                        });
                        await new Promise(r => setTimeout(r, 120));
                        saved = await autoClickSaveBtn();
                    }
                    showStatus(saved ? '内容填充完成并已自动保存' : '内容填充完成,请手动保存', !saved);
                } else {
                    showStatus('内容填充完成', false);
                }
                return true;
            } else {
                // 异常兜底:复制到剪贴板并显示手动粘贴按钮
                try {
                    GM_setClipboard(safeHtml);
                } catch (clipboardError) {
                    console.log('复制到剪贴板失败:', clipboardError);
                }
                showStatus('自动填充失败,内容已复制到剪贴板,请手动粘贴', true);
                const pasteBtn = document.getElementById('paste-btn');
                if (pasteBtn) pasteBtn.style.display = 'inline-block';
                return false;
            }
        } catch (error) {
            console.error('填充过程中发生错误:', error);
            // 异常兜底:尝试从localStorage恢复备份
            try {
                const backupHtml = localStorage.getItem('backup-movie-html');
                if (backupHtml) {
                    GM_setClipboard(backupHtml);
                    showStatus('处理过程中出现错误,已将备份内容复制到剪贴板,请手动粘贴', true);
                    const pasteBtn = document.getElementById('paste-btn');
                    if (pasteBtn) pasteBtn.style.display = 'inline-block';
                } else {
                    showStatus('处理过程中出现错误,请刷新页面重试', true);
                }
            } catch (restoreError) {
                showStatus('处理过程中出现错误,请刷新页面重试', true);
            }
            return false;
        }
    }

    // 内容生成函数
    function generateHTML(movie, comments, posterDataURL, stillDataURL) {
        // 强制将TMDB缩略图升级为original,避免排版放大模糊
        const finalPosterUrl = posterDataURL ? toTMDBOriginal(posterDataURL) : 'https://picsum.photos/680/480?default-poster';
        const finalStillUrl = stillDataURL ? toTMDBOriginal(stillDataURL) : 'https://picsum.photos/800/450?default-still';
        const runtime = movie.runtime === 'null' || !movie.runtime ? '未知片长' : movie.runtime;

        let imdbHtml = '';
        if (movie.imdbId && movie.imdbId !== '暂无') {
            imdbHtml = `<span>&nbsp;</span><strong style="box-sizing: border-box; font-weight: bolder;">IMDb:</strong><span style="box-sizing: border-box; color: rgb(0, 2, 255);"><a style="box-sizing: border-box; color: rgb(0, 2, 255); text-decoration: none; background-color: transparent; transition: 0.2s;" href="https://www.imdb.com/title/${movie.imdbId}/" target="_blank" rel="noopener"><span>&nbsp;</span>${movie.imdbId}</a></span>`;
        }

        const introHtml = movie.intro
            .split('\n')
            .filter(para => para.trim())
            .map(para => `<div style="box-sizing: border-box; color: rgb(33, 37, 41); font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">${para.trim()}</div>`)
            .join('');

        let commentsHtml = '';
        // 统一为“观众热评”,并与模板1一致:TMDB无热评时回退为简介/标语摘录
        const isTmdbSrc = (movie && (movie.source === 'TMDB' || (movie.url && movie.url.includes('themoviedb.org')) || movie.tmdbId));
        const firstRaw = Array.isArray(comments) && comments.length > 0 ? comments[0] : null;
        let firstText = '';
        if (firstRaw) {
            if (typeof firstRaw === 'string') {
                firstText = firstRaw;
            } else if (typeof firstRaw === 'object') {
                firstText = (
                    firstRaw.content ||
                    firstRaw.text ||
                    firstRaw.comment ||
                    firstRaw.quote ||
                    ''
                ).toString();
            }
        }
        let commentInnerHtml = '';
        if (firstText && firstText.trim()) {
            commentInnerHtml = firstText.trim();
        } else if (isTmdbSrc) {
            let snippet = (movie.intro || movie.tagline || '').toString().trim();
            if (snippet.length > 80) snippet = snippet.slice(0, 78) + '…';
            const rvLink = movie.tmdbId ? `https://www.themoviedb.org/${movie.mediaType || 'movie'}/${movie.tmdbId}/reviews` : '';
            const moreHtml = rvLink ? ` <a href="${rvLink}" target="_blank" rel="noopener" style="color:#e64a19;text-decoration:none;border-bottom:1px dashed #ffccbc;">更多评价</a>` : '';
            commentInnerHtml = snippet
                ? `<p style="margin:0 0 8px 0;">${snippet}</p><p style="margin:0;text-align:right;color:#e64a19;font-style:italic;font-size:14px;">—— 看点摘录${moreHtml}</p>`
                : '暂无热评,分享你的观影感受吧~';
        } else {
            commentInnerHtml = '暂无热评,分享你的观影感受吧~';
        }
        commentsHtml = `
<h3 style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0.5rem; font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-weight: 500; line-height: 1.2; color: rgb(33, 37, 41); font-size: 1.5rem;">观众热评:</h3>
<div style="box-sizing: border-box; color: rgb(33, 37, 41); font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-size: 14px; line-height:1.8;">${commentInnerHtml}</div>`;

        // 处理额外信息(新添加的字段)
        let additionalInfo = '';
        let hasAdditionalInfo = false;
        const additionalInfoItems = [];

        // 原始标题
        if (movie.originalTitle && movie.originalTitle !== movie.title) {
            additionalInfoItems.push(`<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">原始名称:</strong>${movie.originalTitle}</p>`);
            hasAdditionalInfo = true;
        }

        // 奖项信息
        if (movie.awards && movie.awards.length > 0) {
            additionalInfoItems.push(`<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">主要奖项:</strong>${movie.awards.slice(0, 3).join(';')}</p>`);
            hasAdditionalInfo = true;
        }

        // 关键字
        if (movie.keywords && movie.keywords !== '') {
            additionalInfoItems.push(`<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">关键字:</strong>${movie.keywords}</p>`);
            hasAdditionalInfo = true;
        }

        // 预算和票房(电影)
        if (movie.budget && movie.budget !== '未知') {
            additionalInfoItems.push(`<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">预算:</strong>${movie.budget}</p>`);
            hasAdditionalInfo = true;
        }

        if (movie.revenue && movie.revenue !== '未知') {
            additionalInfoItems.push(`<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">票房:</strong>${movie.revenue}</p>`);
            hasAdditionalInfo = true;
        }

        // 流媒体平台信息
        if (movie.streamingPlatforms && movie.streamingPlatforms.length > 0) {
            additionalInfoItems.push(`<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">流媒体平台:</strong>${movie.streamingPlatforms.join('、')}</p>`);
            hasAdditionalInfo = true;
        }

        // 如果有额外信息,构建HTML
        if (hasAdditionalInfo) {
            additionalInfo = `<div style="box-sizing: border-box; margin-top: 15px; padding: 15px; background-color: rgb(248, 249, 250); border-radius: 0.5rem; border: 1px solid rgb(222, 226, 230);">
${additionalInfoItems.join('\n')}
</div>`;
        }

        return `
<div class="card border" style="box-sizing: border-box; position: relative; display: flex; flex-direction: column; min-width: 0px; overflow-wrap: break-word; background: none 0% 0% / auto repeat scroll padding-box border-box rgb(255, 255, 255); border: none; border-radius: 0.75rem; margin-bottom: 1rem; box-shadow: rgba(46, 45, 116, 0.05) 0px 0.25rem 1.875rem; color: rgb(33, 37, 41); font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">
<div class="movie-info" style="box-sizing: border-box; flex: 1 1 400px; padding: 20px;"><img class="lazy img-responsive" style="box-sizing: border-box; vertical-align: middle; border: 1px solid transparent; max-width: 100%; -webkit-user-drag: none; margin-bottom: 0.5rem; height: auto; width: 100%; cursor: pointer; image-rendering: -webkit-optimize-contrast; image-rendering: crisp-edges;" src="${finalPosterUrl}" data-original="${finalPosterUrl}"><br style="box-sizing: border-box;">
<div class="movie-info-content" style="box-sizing: border-box; word-break: break-word; overflow-wrap: anywhere;">
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">名称:</strong>${movie.title}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">又名:</strong>${movie.alsoKnown || '无'}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">导演:</strong>${movie.director}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">编剧:</strong>${movie.writer}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">主演:</strong>${movie.actor}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">类型:</strong>${movie.genreTags.join('、') || '未知'}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">制片地区:</strong>${movie.region}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">上映时间:</strong>${movie.release}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">影视语言:</strong>${movie.lang}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">评分:</strong><span style="box-sizing: border-box; color: rgb(0, 132, 255); font-weight: 600;"><span>&nbsp;</span>${movie.rating}</span><span>&nbsp;</span><strong style="box-sizing: border-box; font-weight: bolder;">豆瓣ID:</strong><span style="box-sizing: border-box; color: rgb(0, 2, 255);"><a style="box-sizing: border-box; color: rgb(0, 2, 255); text-decoration: none; background-color: transparent; transition: 0.2s;" href="${movie.mediaType === 'tv' ? 'https://tv.douban.com/subject/' : 'https://movie.douban.com/subject/'}${movie.doubanId || movie.tmdbId}/" target="_blank" rel="noopener"><span>&nbsp;</span>${movie.doubanId || movie.tmdbId}</a></span>${imdbHtml}</p>
<p style="box-sizing: border-box; margin: 0.2rem 0px; line-height: 1.7;"><strong style="box-sizing: border-box; font-weight: bolder;">片长:</strong>${runtime}</p>
${additionalInfo}
</div>
</div>
</div>
<h3 style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0.5rem; font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-weight: 500; line-height: 1.2; color: rgb(33, 37, 41); font-size: 1.75rem; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">影视简介:</h3>
<div style="background:#ffffff; color:#1f2937; line-height:1.8; font-size:14px; border:1px solid #e5e7eb; border-radius:8px; padding:12px; box-shadow:0 1px 3px rgba(0,0,0,0.04);">
${introHtml}
</div>
<div style="box-sizing: border-box; color: rgb(33, 37, 41); font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">&nbsp;</div>
<div style="box-sizing: border-box; color: rgb(33, 37, 41); font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">
<h3 style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0.5rem; font-family: 'Helvetica Neue', Helvetica, 'Microsoft Yahei', 'Hiragino Sans GB', 'WenQuanYi Micro Hei', 微软雅黑, 华文细黑, STHeiti, sans-serif; font-weight: 500; line-height: 1.2; color: rgb(33, 37, 41); font-size: 1.75rem; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">精彩剧照:</h3>
<img src="${finalStillUrl}" style="box-sizing: border-box; vertical-align: middle; border-style: none; max-width: 100%; height: auto; border-radius: 4px; margin-bottom: 1rem;" alt="${movie.title} 剧照">
</div>
${commentsHtml}
        `;
    }

    // 创建AI功能面板内容(不创建独立面板,只返回HTML内容)
    function createAIPanelContent() {
        return `

        <!-- AI功能选择 -->
        <div style="margin-bottom:8px;">
            <label style="display:inline-block; width:80px; font-weight:500; color:#4b5563; font-size:12px;">功能类型:</label>
            <select id="ai-function-select" style="width:calc(100% - 90px); padding:4px; border:1px solid #d1d5db; border-radius:3px; font-size:12px; max-height: 200px;">
                <option value="post_format" selected>资源帖排版美化</option>
                <option value="free_text">无预设生成</option>
            </select>
        </div>

        <!-- 风格选择 -->
        <div style="margin-bottom:8px;">
            <label style="display:inline-block; width:80px; font-weight:500; color:#4b5563; font-size:12px;">输出风格:</label>
            <select id="ai-style-select" style="width:calc(100% - 90px); padding:4px; border:1px solid #d1d5db; border-radius:3px; font-size:12px;">
                <option value="">自动(不指定)</option>
                <option value="专业严谨">专业严谨</option>
                <option value="简洁实用">简洁实用</option>
                <option value="活泼有趣">活泼有趣</option>
                <option value="学术深度">学术深度</option>
                <option value="幽默风趣">幽默风趣</option>
                <option value="文艺细腻">文艺细腻</option>
                <option value="复古胶片">复古胶片</option>
                <option value="赛博科幻">赛博科幻</option>
                <option value="国潮风格">国潮风格</option>
                <option value="万象合流">万象合流(跨文化全风格自适应)</option>
            </select>
        </div>

        <!-- AI提示输入 -->
        <div style="margin-bottom:8px;">
            <label style="display:block; font-weight:500; color:#4b5563; font-size:12px; margin-bottom:4px;">生成提示:</label>
            <textarea id="ai-prompt-input" rows="3" placeholder="请输入剧情简介要求,例如:详细、简洁、适合推荐等" style="width:100%; padding:6px; border:1px solid #d1d5db; border-radius:4px; font-size:12px; resize:vertical;"></textarea>
        </div>

        <!-- AI检索与图片选择(精简版) -->
        <div style="margin-bottom:8px; padding:8px; background:#fff; border:1px solid #e5e7eb; border-radius:4px;">
            <div id="ai-toggle-row" style="display:flex; gap:12px; align-items:stretch; margin-bottom:8px; flex-wrap:wrap;">
                <label class="ai-flag" style="display:flex; align-items:center; gap:6px; padding:6px 10px; border:1px solid #e5e7eb; border-radius:6px; background:#f9fafb; font-size:12px; color:#374151;">
                    <input type="checkbox" id="ai-auto-title" checked>
                    <span>选片名入提示</span>
                </label>
                <label class="ai-flag" id="ai-deep-wrap" style="display:flex; align-items:center; gap:6px; padding:6px 10px; border:1px solid #e5e7eb; border-radius:6px; background:#f9fafb; font-size:12px; color:#374151;">
                    <input type="checkbox" id="ai-deep-think">
                    <span>深度思考</span>
                </label>
                <label class="ai-flag" id="ai-web-wrap" style="display:flex; align-items:center; gap:6px; padding:6px 10px; border:1px solid #e5e7eb; border-radius:6px; background:#f9fafb; font-size:12px; color:#374151;">
                    <input type="checkbox" id="ai-web-browse">
                    <span>联网补充</span>
                </label>
                <span id="ai-feature-tip" style="align-self:center; font-size:11px; color:#9ca3af;"></span>
            </div>
            <div style="display:flex; gap:6px; align-items:center; margin-bottom:6px;">
                <input id="ai-search-input" type="text" placeholder="输入片名或粘贴链接(自动弹出结果)" style="flex:1; padding:6px; border:1px solid #d1d5db; border-radius:4px; font-size:12px;">
            </div>
            <div id="ai-search-status" style="display:none; font-size:12px; color:#6b7280; margin-bottom:6px;">正在加载...</div>
            <div id="ai-search-results" style="display:none; border:1px solid #e5e7eb; border-radius:6px; background:#fff; max-height:260px; overflow:auto; margin-bottom:6px;">
            </div>
            <div id="ai-image-selection" style="display:none; margin-top:4px;">
                <div style="margin-bottom:8px;">
                    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:4px;">
                        <strong style="font-size:12px; color:#374151;">🖼️ 海报(可多选)</strong>
                        <button id="ai-load-more-posters" style="display:none; background:#f472b6; color:#fff; border:none; padding:4px 8px; border-radius:6px; font-size:12px; cursor:pointer;">加载更多海报</button>
                    </div>
                    <div id="ai-poster-candidates" style="display:grid; grid-template-columns:repeat(5,1fr); gap:8px; min-height:120px; background:#fff; border:1px solid #f3d5d9; border-radius:6px; padding:6px;"></div>
                </div>
                <div>
                    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:4px;">
                        <strong style="font-size:12px; color:#374151;">🎬 剧照(可多选)</strong>
                        <button id="ai-load-more-stills" style="display:none; background:#f472b6; color:#fff; border:none; padding:4px 8px; border-radius:6px; font-size:12px; cursor:pointer;">加载更多剧照</button>
                    </div>
                    <div id="ai-still-candidates" style="display:grid; grid-template-columns:repeat(5,1fr); gap:8px; min-height:120px; background:#fff; border:1px solid #f3d5d9; border-radius:6px; padding:6px;"></div>
                </div>
            </div>
        </div>

        <!-- AI生成按钮 -->
        <div style="margin-bottom:8px;">
            <button id="generate-ai-text" style="background:#6366f1; color:white; border:none; padding:6px 16px; border-radius:4px; cursor:pointer; font-size:12px;">
                <i class="fa fa-magic" style="margin-right:5px;"></i>生成AI文本
            </button>
            <button id="abort-ai-generate" style="background:#ef4444; color:white; border:none; padding:6px 12px; border-radius:4px; cursor:pointer; font-size:12px; margin-left:8px; display:none;">
                终止
            </button>
            <button id="ai-clear" style="background:#ef4444; color:white; border:none; padding:6px 12px; border-radius:4px; cursor:pointer; font-size:12px; margin-left:8px;">
                清理
            </button>
        </div>

        <!-- AI结果展示区域 -->
        <div id="ai-result-area" style="display:none; margin-top:10px; padding:8px; background:#fff; border:1px solid #e5e7eb; border-radius:4px;">
            <h5 style="margin:0 0 6px 0; color:#4b5563; font-size:12px;">生成结果:</h5>
            <div id="ai-result-content" style="font-size:12px; line-height:1.6; color:#374151; min-height:50px; max-height:200px; overflow-y:auto;"></div>
            <div style="margin-top:6px; display:flex; gap:8px;">
                <button id="copy-ai-result" style="background:#3b82f6; color:white; border:none; padding:3px 10px; border-radius:3px; cursor:pointer; font-size:11px;">
                    <i class="fa fa-copy" style="margin-right:3px;"></i>复制结果
                </button>
                <button id="insert-ai-result" style="background:#8b5cf6; color:white; border:none; padding:3px 10px; border-radius:3px; cursor:pointer; font-size:11px;">
                    <i class="fa fa-pencil" style="margin-right:3px;"></i>插入到编辑框
                </button>
            </div>
        </div>`;
    }

    // 切换标签页功能
    function switchTab(tabId) {
        // 隐藏所有内容区域
        document.getElementById('main-content-area').style.display = 'none';
        document.getElementById('ai-content-area').style.display = 'none';
        document.getElementById('settings-content-area').style.display = 'none';

        // 获取标签元素
        const mainTab = document.getElementById('main-tab');
        const aiTab = document.getElementById('ai-tab');
        const settingsTab = document.getElementById('settings-tab');

        // 重置所有标签样式
        [mainTab, aiTab, settingsTab].forEach(tab => {
            // 完全重置所有内联样式
            tab.style.background = '#fff';
            tab.style.color = '#6b7280';
            tab.style.fontWeight = 'normal';
            tab.style.boxShadow = 'none';
            tab.style.borderBottom = '1px solid #f3d5d9';
            tab.style.backgroundImage = 'none';
        });

        // 显示选中的内容区域并激活对应的标签
        if (tabId === 'main') {
            document.getElementById('main-content-area').style.display = 'block';
            mainTab.style.background = 'linear-gradient(135deg, #ec4899 0%, #be185d 100%)';
            mainTab.style.color = 'white';
            mainTab.style.fontWeight = '500';
            mainTab.style.boxShadow = '0 -2px 6px rgba(236, 72, 153, 0.3)';
            mainTab.style.borderBottom = 'none';
            showStatus('控制面板已准备就绪', false, 'main');
            // 进入主功能:隔离AI
            isMainFlowActive = true;
        } else if (tabId === 'ai') {
            document.getElementById('ai-content-area').style.display = 'block';
            aiTab.style.background = 'linear-gradient(135deg, #8b5cf6 0%, #6d28d9 100%)';
            aiTab.style.color = 'white';
            aiTab.style.fontWeight = '500';
            aiTab.style.boxShadow = '0 -2px 6px rgba(139, 92, 246, 0.3)';
            aiTab.style.borderBottom = 'none';
            // 进入AI:解除隔离
            isMainFlowActive = false;
            // 重新绑定AI事件监听器,确保按钮可以正常响应
            bindAIEventListeners();
        } else if (tabId === 'settings') {
            document.getElementById('settings-content-area').style.display = 'block';
            settingsTab.style.background = 'linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)';
            settingsTab.style.color = 'white';  // 确保文字颜色为白色
            settingsTab.style.fontWeight = '500';
            settingsTab.style.boxShadow = '0 -2px 6px rgba(99, 102, 241, 0.3)';
            settingsTab.style.borderBottom = 'none';
            showStatus('设置面板已准备就绪', false, 'settings');
            // 重新绑定设置面板事件监听器,确保按钮可以正常响应
            bindSettingsEventListeners();
        }
    }

    // 确保switchTab函数在全局作用域可访问 - 使用更可靠的方式暴露给外部HTML调用
    if (typeof unsafeWindow !== 'undefined') {
        // 在Tampermonkey等用户脚本管理器中使用unsafeWindow
        unsafeWindow.switchTab = switchTab;
    } else {
        // 标准浏览器环境下使用window
        window.switchTab = switchTab;
    }
    // 额外添加到document对象作为后备方案
    document.switchTab = switchTab;


    // 控制面板创建与定位 - 精准放置到标记位置(空值修复版+美化版)
    function createPanel() {
        panel = document.createElement('div');
        panel.id = 'douban-tmdb-panel';
        panel.style.cssText = `
        background: #fff; border: 1px solid #f3d5d9; border-radius: 8px;
        padding: 15px; margin: 20px 0; box-shadow: 0 2px 8px rgba(236, 72, 153, 0.08);
        z-index: 0; position: static;
        box-sizing: border-box;
        width: 100%; min-width: 320px; max-width: 1400px; /* 扩大宽屏最大宽度,优化搜索结果显示 */
        transition: margin-bottom 0.15s cubic-bezier(0.4, 0, 0.2, 1);
        overflow: visible;
        transform: none !important;
        transform-origin: unset !important;
    `;

        // 添加响应式CSS规则(精简与合并断点,移除极端断点)
        const responsiveCSS = `
        <style>


        /* 仅竖排时允许过渡,恢复横排时不做过渡 */
        #input-container.stacked-animate {
            transition: gap 160ms ease, flex-direction 160ms ease, align-items 160ms ease;
        }
        #input-container.no-transition {
            transition: none !important;
        }
        /* 修复点:当横排闪切时,连同子元素一起禁用过渡/动画,消除迟滞感 */
        #input-container.no-transition * {
            transition: none !important;
            animation: none !important;
        }
        /* 修复点:全局级别的临时禁用过渡(通过给body加类名触发),用于竖→横闪切时彻底清零动画 */
        body.no-transition-global *, body.no-transition-global *::before, body.no-transition-global *::after {
            transition: none !important;
            animation: none !important;
        }
        /* 修复点:>800px 时预置为横排顶部对齐,避免JS接管前出现"先居中"一帧 */
        @media screen and (min-width: 801px) {
            #input-container { flex-direction: row !important; align-items: flex-start !important; gap: 15px !important; }
            /* 搜索容器与链接容器:强制顶部对齐 */
            div[style*="flex: 1 1 250px"][style*="min-width: 200px"][style*="position: relative"],
            #media-url-container { display: flex !important; align-items: flex-start !important; }
            /* 包装器避免横排时拉到中线 */
            #media-url-wrapper { align-items: stretch !important; }
            /* 修复点:横排时彻底移除输入框自身过渡,避免宽度变化被动画化 */
            #search-movie, #media-url, #fetch-btn { transition: none !important; }
            /* 终极修复:横排模式下,输入区整棵子树禁用过渡/动画,保证阈值切换"闪切" */
            #input-container, #input-container * { transition: none !important; animation: none !important; }
        }

        /* <= 800px:垂直布局与全宽输入 */
        @media screen and (max-width: 800px) {
            #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                flex-direction: column !important;
                gap: 12px !important;
                align-items: stretch !important;
            }
            #input-container {
                flex-direction: column !important;
                align-items: stretch !important;
                gap: 12px !important;
            }
            #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                flex: none !important;
                width: 100% !important;
                min-width: auto !important;
            }
            #media-url-container {
                width: 100% !important;
                flex: none !important;
                min-width: auto !important;
                display: flex !important;
                flex-direction: column !important;
                align-items: stretch !important;
            }
            #media-url-wrapper {
                flex-direction: column !important;
                align-items: stretch !important;
                gap: 8px !important;
                width: 100% !important;
            }
            #search-movie,
            #media-url {
                width: 100% !important;
                min-width: 150px !important;
                font-size: 12px !important;
                padding: 6px 10px !important;
            }
            #fetch-btn {
                border-radius: 6px !important;
                width: 100% !important;
                margin-left: 0 !important;
                font-size: 12px !important;
                padding: 6px 10px !important;
                flex-shrink: 0 !important;
            }
            #search-results {
                position: relative !important;
                top: 0 !important;
                left: 0 !important;
                right: 0 !important;
                width: 100% !important;
                margin: 4px 0 0 0 !important;
                z-index: 1000 !important;
            }
            label[style*="width:70px"] {
                width: 70px !important;
                font-size: 11px !important;
            }
        }

        /* <= 650px:标签更紧凑,输入框减小内边距 */
        @media screen and (max-width: 650px) {
            #search-movie,
            #media-url {
                font-size: 12px !important;
                padding: 6px 10px !important;
            }
        }

        /* <= 360px:极窄屏输入区紧凑优化(不修改#search-results) */
        @media screen and (max-width: 360px) {
            #input-container { gap: 8px !important; }
            label[style*="width:70px"],
            #media-url-label { width: 60px !important; font-size: 11px !important; }
            #search-movie, #media-url { padding: 5px 8px !important; font-size: 12px !important; }
        }

        /* <= 320px:超窄屏输入区兜底(不修改#search-results) */
        @media screen and (max-width: 320px) {
            #input-container { gap: 6px !important; }
            label[style*="width:70px"],
            #media-url-label { width: 56px !important; font-size: 10.5px !important; }
            #search-movie, #media-url { padding: 4px 7px !important; font-size: 11.5px !important; }
        }
        </style>
        `;
        panel.innerHTML = responsiveCSS + panel.innerHTML;
        panel.innerHTML = `
        <!-- 标签页导航 -->
        <div style="display:flex; margin:0 0 20px 0; border-bottom:1px solid #f3d5d9; flex-wrap: wrap; gap: 2px;">
                    <button id="main-tab" onclick="switchTab('main')" style="padding:8px 16px; border:none; background:linear-gradient(135deg, #ec4899 0%, #be185d 100%); color:white; font-size:12px; font-weight:500; cursor:pointer; border-radius:8px 8px 0 0; transition: background 0.2s ease, box-shadow 0.2s ease; box-shadow: 0 -2px 6px rgba(236, 72, 153, 0.3); flex: 1 1 auto; min-width: 120px;">🎬 豆瓣+TMDB影视工具</button>
            <button id="ai-tab" onclick="switchTab('ai')" style="padding:8px 16px; border:none; background:#fff; color:#be185d; font-size:12px; cursor:pointer; border-radius:8px 8px 0 0; transition: background 0.2s ease, color 0.2s ease; border-bottom: 1px solid #f3d5d9; flex: 1 1 auto; min-width: 120px;">🤖 AI文字生成工具</button>
            <button id="settings-tab" onclick="switchTab('settings')" style="padding:8px 16px; border:none; background:#fff; color:#6b7280; font-size:12px; cursor:pointer; border-radius:8px 8px 0 0; transition: background 0.2s ease, color 0.2s ease; border-bottom: 1px solid #f3d5d9; flex: 1 1 auto; min-width: 80px;">⚙️ 设置</button>
            <style>
                #main-tab,
                #ai-tab,
                #settings-tab {
                    font-family: 'Microsoft YaHei', sans-serif;
                    margin-right: 4px;
                    position: relative;
                    overflow: hidden;
                }
                #main-tab:hover:not(#main-tab[style*="background:linear-gradient"]),
                #ai-tab:hover:not(#ai-tab[style*="background:linear-gradient"]),
                #settings-tab:hover:not(#settings-tab[style*="background:linear-gradient"]) {
                    background-color: #fff5f7;
                    transform: translateY(-1px);
                    border-bottom-color: #f472b6;
                }
                #main-tab::after,
                #ai-tab::after,
                #settings-tab::after {
                    content: '';
                    position: absolute;
                    bottom: -2px;
                    left: 0;
                    width: 100%;
                    height: 3px;
                    background: linear-gradient(90deg, #ec4899, #8b5cf6);
                    transform: scaleX(0);
                    transition: transform 0.3s ease;
                    z-index: 1;
                }
                #main-tab:hover::after,
                #ai-tab:hover::after,
                #settings-tab:hover::after {
                    transform: scaleX(1);
                }

                /* 响应式标签页按钮 */
                @media screen and (max-width: 600px) {
                    #main-tab, #ai-tab, #settings-tab {
                        padding: 6px 10px !important;
                        font-size: 11px !important;
                        min-width: 80px !important;
                    }
                }

                @media screen and (max-width: 480px) {
                    #main-tab, #ai-tab, #settings-tab {
                        padding: 5px 8px !important;
                        font-size: 10px !important;
                        min-width: 60px !important;
                    }
                }
            </style>
        </div>
        <!-- 主功能区域(新增预览模式开关) -->
        <div id="main-content-area" style="display:block;">
            <!-- 排版美化工具区域 -->
            <div style="margin-bottom:20px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                <h4 style="margin:0 0 12px 0; color:#be185d; font-size:14px; font-weight:600; display:flex; justify-content:space-between; align-items:center;">
                    🎨 排版美化工具
                    <span id="format-preview-toggle" style="font-size:12px; color:#db2777; cursor:pointer; text-decoration:underline; transition: color 0.2s ease;">显示预览</span>
                </h4>

                <!-- 样式分类标签 -->
                <div id="format-categories" style="display:flex; gap:8px; margin-bottom:10px; overflow-x:auto; padding-bottom:4px; border-bottom:1px solid #f3d5d9;">
                    <!-- 分类标签通过JS生成 -->
                </div>

                <!-- 样式按钮区域 -->
                <div style="display:flex; flex-wrap:wrap; gap:6px;" id="format-buttons">
                    <!-- 美化按钮通过JS生成 -->
                </div>


                <!-- 样式预览区域 -->
                <div id="format-preview" style="margin-top:10px; padding:10px; background:#fff; border:1px solid #f3d5d9; border-radius:8px; display:none; max-height:200px; overflow-y:auto; font-family:'Microsoft YaHei', sans-serif;">
                    <div style="text-align:center; color:#6b7280; font-size:13px;">选择样式查看预览效果</div>
                </div>
            </div>

            <!-- 输入区(添加预览模式控制和日志容器) -->
            <div style="margin-bottom:20px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                <!-- 搜索框和链接框的水平对齐容器 -->
                <div style="display:flex; gap:15px; margin-bottom:12px; align-items:flex-start; min-width: 0; flex-wrap: wrap;" id="input-container">
                    <!-- 搜索影片区域 -->
                    <div style="flex: 1 1 250px; display:flex; align-items:center; min-width: 200px; overflow: visible;">
                         <label style="width:70px; font-weight:500; color:#6b7280; margin-right:8px; flex-shrink: 0; font-size: 12px; line-height: 1.5; text-align: right; padding-right: 4px;">搜索影片:</label>
                        <div style="flex:1; display:flex; align-items:center; min-width: 0; position: relative;">
                            <input type="search" id="search-movie" placeholder="完美世界" style="width: 100%; padding:6px 10px; border:1px solid #d1d5db; border-radius:6px; font-size:12px; font-weight:400; color:#374151; transition: all 0.2s ease; outline:none; background:#fff; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05); line-height: 1.5;">
                            <div id="search-loading" style="position:absolute; right:10px; top:35%; transform: translateY(-50%); color:#6b7280; display:none; font-size: 11px; font-weight:500; background: rgba(255, 255, 255, 0.9); padding: 2px 6px; border-radius: 4px; z-index: 1001;">
                                <i>搜索中...</i>
                            </div>
                        </div>
                    </div>
                    <!-- 影视链接区域 -->
                    <div style="flex: 1 1 250px; display:flex; align-items:center; min-width: 200px;" id="media-url-container">
                         <label style="width:70px; font-weight:500; color:#6b7280; margin-right:8px; flex-shrink: 0; font-size: 12px; line-height: 1.5; text-align: right; padding-right: 4px;" id="media-url-label">影视链接:</label>
                        <div style="flex:1; display:flex; align-items:center; min-width: 0;" id="media-url-wrapper">
                            <input type="text"
                                   id="media-url"
                                   name="dummy-media-url"
                                   placeholder="豆瓣或TMDB链接"
                                   autocomplete="new-password"
                                   spellcheck="false"
                                   data-lpignore="true"
                                   data-form-type="other"
                                   aria-label="影视链接输入框"
                                   aria-autocomplete="none"
                                   data-passwordmanager="false"
                                   data-disable-pwdmgr="true"
                                   data-1password-ignore="true"
                                   data-lastpass-ignore="true"
                                   data-autofill="disabled"
                                   onfocus="this.removeAttribute('readonly');"
                                   onblur="this.removeAttribute('readonly');"
                                    style="flex:1; min-width: 100px; padding:6px 10px; border:1px solid #d1d5db; border-radius:6px; font-size:12px; font-weight:400; color:#374151; transition: all 0.2s ease; outline:none; background:#fff; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05); line-height: 1.5;">
                            <button id="fetch-btn" style="display:none; opacity:0.6; pointer-events:none; background:#ec4899; color:white; border:none; padding:6px 12px; border-radius:6px; cursor:not-allowed; font-size:12px; font-weight:500; transition: all 0.3s ease; flex-shrink: 0; line-height: 1.5; margin-left: 4px;">提取</button>
                        </div>
                    </div>
                </div>
                <!-- 搜索结果显示框独立容器,确保不影响输入框对齐 -->
                <div id="search-results" style="position:relative; top:0; left:0; right:0; z-index:1000; background:#fff; border:1px solid #f3d5d9; border-radius:6px; max-height:400px; overflow-y:auto; display:none; visibility:hidden; opacity:0; box-shadow: 0 4px 12px rgba(0,0,0,0.15); margin-top:8px; width:100%;"></div>

                <style>
                    #search-movie:focus,
                    #media-url:focus {
                        border-color: #f472b6;
                        box-shadow: 0 0 0 2px rgba(244, 114, 182, 0.1);
                    }
                    #media-url:focus + #fetch-btn {
                        background:#db2777;
                    }
                    #fetch-btn.active {
                        opacity:1;
                        pointer-events:auto;
                        cursor:pointer;
                        background:#db2777;
                    }

                     /* 响应式搜索区域 - 极窄窗口优化 */
        @media screen and (max-width: 800px) {
            /* 强制搜索区域垂直布局 - 更早触发 */
            #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                flex-direction: column !important;
                gap: 12px !important;
                align-items: stretch !important;
            }

            /* 确保每个区域内部改为垂直排列(标签在上,输入框在下) */
            #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="display:flex"][style*="align-items:center"] {
                flex-direction: column !important;
                align-items: stretch !important;
            }

            /* 调整标签样式,适应垂直布局 */
            #douban-tmdb-panel div[style*="flex: 1 1 250px"] label {
                width: auto !important;
                margin-right: 0 !important;
                margin-bottom: 4px !important;
                text-align: left !important;
                padding-right: 0 !important;
            }

            /* 调整搜索中指示器位置,适应垂直布局 - 提高优先级 */
            #douban-tmdb-panel #search-loading {
                position: absolute !important;
                right: 10px !important;
                top: 35% !important;
                transform: translateY(-50%) !important;
                z-index: 1001 !important;
            }

            /* 确保搜索框容器有正确的定位基准 */
            #douban-tmdb-panel div[style*="flex:1"][style*="position: relative"] {
                position: relative !important;
            }

            /* 确保输入框容器在移动端保持对齐 */
            #input-container {
                flex-direction: column !important;
                align-items: stretch !important;
                gap: 12px !important;
            }


                         /* 搜索和链接输入容器全宽显示 */
                         #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                             flex: none !important;
                             width: 100% !important;
                             min-width: auto !important;
                         }

                         /* 影视链接容器优化 */
                         #media-url-container {
                             width: 100% !important;
                             flex: none !important;
                             min-width: auto !important;
                             display: flex !important;
                             flex-direction: column !important;
                             align-items: stretch !important;
                         }

                         /* 影视链接包装器优化 - 强制垂直布局 */
                         #media-url-wrapper {
                             flex-direction: column !important;
                             align-items: stretch !important;
                             gap: 8px !important;
                             width: 100% !important;
                         }

                         /* 搜索输入框优化 */
                         #search-movie {
                             width: 100% !important;
                             min-width: 150px !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                         }

                         /* 影视链接输入框优化 */
                         #media-url {
                             width: 100% !important;
                             min-width: 150px !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                             border-radius: 6px !important;
                         }

                         /* 提取按钮优化 */
                         #fetch-btn {
                             border-radius: 6px !important;
                             width: 100% !important;
                             margin-left: 0 !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                             flex-shrink: 0 !important;
                         }

                         /* 搜索结果框位置调整 - 独立容器,确保输入框水平对齐 */
            #search-results {
                        position: relative !important;
                        top: 0 !important;
                        left: 0 !important;
                        right: 0 !important;
                        width: 100% !important;
                        margin-top: 8px !important;
                        margin-left: 0 !important;
                        margin-right: 0 !important;
                        z-index: 1000 !important;
                        margin-top: 4px !important;
            }

                         /* 标签文字优化 */
                         label[style*="width:70px"] {
                             width: 70px !important;
                             font-size: 11px !important;
                         }
                     }

                     @media screen and (max-width: 800px) {
                         /* 强制搜索区域垂直布局 - 提前触发 */
                         #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                             flex-direction: column !important;
                             gap: 12px !important;
                             align-items: stretch !important;
                         }

                         /* 确保每个区域内部改为垂直排列(标签在上,输入框在下) */
                         #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="display:flex"][style*="align-items:center"] {
                             flex-direction: column !important;
                             align-items: stretch !important;
                         }

                         /* 调整标签样式,适应垂直布局 */
                         #douban-tmdb-panel div[style*="flex: 1 1 250px"] label {
                             width: auto !important;
                             margin-right: 0 !important;
                             margin-bottom: 4px !important;
                             text-align: left !important;
                             padding-right: 0 !important;
                         }

                         /* 调整搜索中指示器位置,适应垂直布局 - 提高优先级 */
                         #douban-tmdb-panel #search-loading {
                             position: absolute !important;
                             right: 10px !important;
                             top: 35% !important;
                             transform: translateY(-50%) !important;
                             z-index: 1001 !important;
                         }

                         /* 确保搜索框容器有正确的定位基准 */
                         #douban-tmdb-panel div[style*="flex:1"][style*="position: relative"] {
                             position: relative !important;
                         }

                         /* 搜索和链接输入容器全宽显示 */
                         #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                             flex: none !important;
                             width: 100% !important;
                             min-width: auto !important;
                         }

                         /* 影视链接容器优化 */
                         #media-url-container {
                             width: 100% !important;
                             flex: none !important;
                             min-width: auto !important;
                         }

                         /* 影视链接包装器优化 - 强制垂直布局 */
                         #media-url-wrapper {
                             flex-direction: column !important;
                             align-items: stretch !important;
                             gap: 8px !important;
                             width: 100% !important;
                         }

                         /* 搜索输入框优化 */
                         #search-movie {
                             width: 100% !important;
                             min-width: 150px !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                         }

                         /* 影视链接输入框优化 */
                         #media-url {
                             width: 100% !important;
                             min-width: 150px !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                             border-radius: 6px !important;
                         }

                         /* 提取按钮优化 */
                         #fetch-btn {
                             border-radius: 6px !important;
                             width: 100% !important;
                             margin-left: 0 !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                             flex-shrink: 0 !important;
                         }

                         /* 搜索结果框位置调整 - 独立容器,确保输入框水平对齐 */
            #search-results {
                        position: relative !important;
                        top: 0 !important;
                        left: 0 !important;
                        right: 0 !important;
                        width: 100% !important;
                        margin-top: 8px !important;
                        margin-left: 0 !important;
                        margin-right: 0 !important;
                        z-index: 1000 !important;
                        margin-top: 4px !important;
            }

                         /* 标签文字优化 */
                         label[style*="width:70px"] {
                             width: 70px !important;
                             font-size: 11px !important;
                         }
                     }

                     @media screen and (max-width: 650px) {
                         /* 强制搜索区域垂直布局 */
                         #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                             flex-direction: column !important;
                             gap: 12px !important;
                             align-items: stretch !important;
                         }

                         /* 搜索和链接输入容器全宽显示 */
                         #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                             flex: none !important;
                             width: 100% !important;
                             min-width: auto !important;
                         }

                         /* 影视链接容器优化 */
                         #media-url-container {
                             width: 100% !important;
                             flex: none !important;
                             min-width: auto !important;
                         }

                         /* 影视链接包装器优化 - 强制垂直布局 */
                         #media-url-wrapper {
                             flex-direction: column !important;
                             align-items: stretch !important;
                             gap: 8px !important;
                             width: 100% !important;
                         }

                         /* 搜索输入框优化 */
                         #search-movie {
                             width: 100% !important;
                             min-width: 150px !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                         }

                         /* 影视链接输入框优化 */
                         #media-url {
                             width: 100% !important;
                             min-width: 150px !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                             border-radius: 6px !important;
                         }

                         /* 提取按钮优化 */
                         #fetch-btn {
                             border-radius: 6px !important;
                             width: 100% !important;
                             margin-left: 0 !important;
                             font-size: 12px !important;
                             padding: 6px 10px !important;
                             flex-shrink: 0 !important;
                         }

                         /* 搜索结果框位置调整 - 独立容器,确保输入框水平对齐 */
            #search-results {
                        position: relative !important;
                        top: 0 !important;
                        left: 0 !important;
                        right: 0 !important;
                        width: 100% !important;
                        margin-top: 8px !important;
                        margin-left: 0 !important;
                        margin-right: 0 !important;
                        z-index: 1000 !important;
                        margin-top: 4px !important;
            }

                         /* 标签文字优化 */
                         label[style*="width:70px"] {
                             width: 70px !important;
                             font-size: 11px !important;
                         }
                     }
                </style>

                <!-- 搜索结果交互效果CSS -->
                <style>
                    /* 搜索结果框初始状态 - 独立容器,确保输入框水平对齐 */
                    #search-results {
                        opacity: 0 !important;
                        transform: translate3d(0, -8px, 0) scale(0.98) !important;
                        transition: opacity 0.2s ease-out, transform 0.2s ease-out, max-height 0.2s ease-out !important;
                        overflow-x: hidden !important;
                        overflow-y: hidden !important;
                        max-height: 0 !important; /* 初始折叠,避免空白 */
                        transform-origin: top center !important;
                        will-change: opacity, transform, max-height !important;
                        contain: layout style paint !important;
                        position: relative !important;
                        margin-top: 8px !important;
                        margin-left: 0 !important;
                        margin-right: 0 !important;
                    }

                    /* 搜索结果框显示动画 - 独立容器版本 */
                    #search-results.show {
                        opacity: 1 !important;
                        transform: translate3d(0, 0, 0) scale(1) !important;
                        max-height: 60vh !important; /* 展开时自适应视口高度 */
                        overflow-y: auto !important;
                        overscroll-behavior: contain !important; /* 防止滚动穿透父容器 */
                    }

                    /* 搜索结果项悬停效果 */
                    .search-item {
                        transition: opacity 0.08s ease-out, background-color 0.08s ease-out, transform 0.08s ease-out !important;
                        position: relative !important;
                        overflow: hidden !important;
                        max-width: 100% !important;
                        opacity: 0.8 !important;
                        will-change: opacity, background-color, transform !important;
                        contain: layout style !important;
                    }

                    /* 搜索结果项悬停时的效果 */
                    .search-item:hover {
                        opacity: 1 !important;
                        background-color: rgba(236, 72, 153, 0.05) !important;
                        transform: translate3d(2px, 0, 0) !important;
                    }

                    /* 控制面板展开状态的视觉指示 - 内嵌搜索结果显示框 */
                    #douban-tmdb-panel.expanded {
                        box-shadow: 0 4px 20px rgba(236, 72, 153, 0.15) !important;
                        border-color: rgba(236, 72, 153, 0.3) !important;
                        overflow: visible !important;
                    }
                        box-sizing: border-box !important;
                        min-height: 70px !important;
                        align-items: flex-start !important;
                    }

                    /* 窄屏幕下的搜索结果项优化 */
                    @media screen and (max-width: 500px) {
                        .search-item {
                            padding: 8px !important;
                            gap: 8px !important;
                            min-height: 60px !important;
                        }

                        .poster-placeholder {
                            width: 28px !important;
                            height: 42px !important;
                            flex-shrink: 0 !important;
                        }

                        .search-item strong {
                            font-size: 11px !important;
                            line-height: 1.2 !important;
                        }

                        .search-item div[style*="color:#6b7280"] {
                            font-size: 10px !important;
                        }
                    }

                    @media screen and (max-width: 400px) {
                        .search-item {
                            padding: 6px !important;
                            gap: 6px !important;
                            min-height: 50px !important;
                        }

                        .poster-placeholder {
                            width: 24px !important;
                            height: 36px !important;
                        }

                        .search-item strong {
                            font-size: 10px !important;
                        }

                        .search-item div[style*="color:#6b7280"] {
                            font-size: 9px !important;
                        }
                    }

                    .search-item:hover {
                        background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%) !important;
                        transform: translateX(4px) !important;
                        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;
                        border-left: 3px solid #ec4899 !important;
                    }

                    /* 海报图片悬停效果 */
                    .search-item:hover .poster-placeholder {
                        transform: scale(1.05) !important;
                        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
                    }

                    /* 标题文字样式 - 允许换行 */
                    .search-item strong {
                        white-space: normal !important;
                        overflow: visible !important;
                        text-overflow: unset !important;
                        max-width: 100% !important;
                        display: block !important;
                        line-height: 1.3 !important;
                        word-wrap: break-word !important;
                        word-break: break-word !important;
                    }

                    /* 标题文字悬停效果 */
                    .search-item:hover strong {
                        color: #ec4899 !important;
                        font-weight: 600 !important;
                    }

                    /* 元数据文字样式 */
                    .search-item div[style*="color:#6b7280"] {
                        white-space: nowrap !important;
                        overflow: hidden !important;
                        text-overflow: ellipsis !important;
                        max-width: 100% !important;
                    }

                    /* 元数据悬停效果 */
                    .search-item:hover div[style*="color:#6b7280"] {
                        color: #4b5563 !important;
                    }

                    /* 加载状态动画 */
                    .search-item.loading {
                        opacity: 0.7 !important;
                        pointer-events: none !important;
                    }

                    .search-item.loading::after {
                        content: '' !important;
                        position: absolute !important;
                        top: 0 !important;
                        left: -100% !important;
                        width: 100% !important;
                        height: 100% !important;
                        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent) !important;
                        animation: shimmer 1.5s infinite !important;
                    }

                    @keyframes shimmer {
                        0% { left: -100%; }
                        100% { left: 100%; }
                    }

                    /* 滚动条美化 */
                    #search-results::-webkit-scrollbar {
                        width: 6px !important;
                    }

                    #search-results::-webkit-scrollbar-track {
                        background: #f1f5f9 !important;
                        border-radius: 3px !important;
                    }

                    #search-results::-webkit-scrollbar-thumb {
                        background: #cbd5e1 !important;
                        border-radius: 3px !important;
                    }

                    #search-results::-webkit-scrollbar-thumb:hover {
                        background: #94a3b8 !important;
                    }

                    /* 防止横向滚动条 */
                    #search-results {
                        overflow-x: hidden !important;
                        word-wrap: break-word !important;
                        word-break: break-word !important;
                    }

                    /* 搜索结果容器宽度控制 */
                    .results-container {
                        max-width: 100% !important;
                        overflow-x: hidden !important;
                    }

                    /* 搜索中指示器基础样式已在上方统一定义 */

                    /* 父容器定位强化(解决定位基准缺失问题) */
                    /* 强制搜索输入框的父容器为定位基准,确保#search-loading不跑偏 */
                    #search-movie.parentNode,
                    div[style*="position: relative"]:has(#search-movie) {
                        position: relative !important;
                        overflow: visible !important; /* 允许提示框正常显示,不被父容器裁剪 */
                        z-index: 1 !important; /* 确保父容器z-index较低,不遮挡导航栏 */
                    }

                    /* 响应式样式:搜索中指示器自适应 */
                    @media screen and (max-width: 800px) {
                        #search-loading {
                            right: 6px !important;
                            font-size: 11px !important;
                            padding: 1px 4px !important;
                            /* 移除极端断点宽度限制,避免过度压缩 */
                            max-width: 100% !important;
                            top: calc(35% + 15px) !important; /* 上下布局时向下偏移 */
                        }
                        #search-results { max-height: 350px !important; }
                    }
                    @media screen and (max-width: 650px) {
                        #search-loading {
                            right: 4px !important;
                            font-size: 10px !important;
                            padding: 1px 3px !important;
                            max-width: 45px !important;
                            top: calc(35% + 12px) !important;
                        }
                        #search-results { max-height: 300px !important; }
                    }
                    @media screen and (max-width: 400px) {
                        #search-loading {
                            right: 2px !important;
                            font-size: 9px !important;
                            padding: 1px 2px !important;
                            max-width: 40px !important;
                            background: rgba(255, 255, 255, 0.98) !important;
                        }
                        #search-results { max-height: 250px !important; }
                    }
                    @media screen and (max-width: 300px) {
                        #search-loading {
                            max-width: 30px !important;
                            font-size: 8px !important;
                        }
                        #search-loading i::after {
                            content: "搜索..." !important;
                            font-style: normal !important;
                        }
                        #search-loading i {
                            font-size: 0 !important;
                        }
                    }

                    /* 空状态提示 */
                    .search-results-empty {
                        text-align: center !important;
                        padding: 20px !important;
                        color: #9ca3af !important;
                        font-style: italic !important;
                    }

                    /* 搜索结果项点击反馈 */
                    .search-item:active {
                        transform: translateX(2px) scale(0.98) !important;
                        background: #e2e8f0 !important;
                    }
                </style>

                <!-- 防止密码管理器干扰的隐藏字段 -->
                <input type="password" style="display:none !important; position:absolute; left:-9999px;" aria-hidden="true" aria-label="ignore" autocomplete="new-password">
                <input type="password" style="display:none !important; position:absolute; left:-9999px;" aria-hidden="true" aria-label="ignore" autocomplete="new-password">
                <input type="password" style="display:none !important; position:absolute; left:-9999px;" aria-hidden="true" aria-label="ignore" autocomplete="new-password">

                <!-- 额外的分散注意力字段 -->
                <input type="text" style="display:none !important; position:absolute; left:-9999px;" name="dummy-username" value="" aria-hidden="true">
                <input type="text" style="display:none !important; position:absolute; left:-9999px;" name="dummy-email" value="" aria-hidden="true">

                <textarea id="backup-html" style="display:none;"></textarea>
                <style>
                    #fetch-btn:hover { background:#db2777; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(236, 72, 153, 0.3); }
                    #paste-btn:hover { background:#be185d; transform: translateY(-1px); box-shadow: 0 2px 8px rgba(219, 39, 119, 0.3); }
                    #load-more-posters:hover { background:#ec4899; transform: translateY(-1px); box-shadow: 0 2px 6px rgba(244, 114, 182, 0.3); }
                    #load-more-stills:hover { background:#ec4899; transform: translateY(-1px); box-shadow: 0 2px 6px rgba(244, 114, 182, 0.3); }
                    #clear-btn:hover { background:#ef4444; border:1px solid #f472b6; }
                    #emerald-city-format:hover { background:linear-gradient(135deg, #db2777 0%, #9d174d 100%); }
                    #confirm-images-btn:hover { background:linear-gradient(135deg, #be185d 0%, #831843 100%); }
                </style>
                <script>
                    (function(){
                        try {
                            const panelEl = document.getElementById('douban-tmdb-panel');
                            if (!panelEl) return;
                            const inputContainerEl = document.getElementById('input-container');

                            function log(message){
                                const time = new Date().toLocaleTimeString();
                                const line = document.createElement('div');
                                line.textContent = '[' + time + '] ' + message;
                                logBox.appendChild(line);
                                logBox.scrollTop = logBox.scrollHeight;
                            }

                            // 预览模式已移除

                            let resizeTimer;
                            function applyDirectionalTransition(){
                                if (!inputContainerEl) return;
                                // 根据当前布局状态决定是否添加过渡
                                var dir = (function(){
                                    var w = window.innerWidth;
                                    if (w <= 800) return 'vertical';
                                    return 'horizontal';
                                })();
                                var was = inputContainerEl.getAttribute('data-layout') || '';
                                if (dir === 'vertical' && was !== 'vertical') {
                                    // 横排 -> 竖排:添加过渡
                                    inputContainerEl.classList.add('stacked-animate');
                                    inputContainerEl.classList.remove('no-transition');
                                } else if (dir === 'horizontal' && was !== 'horizontal') {
                                    // 竖排 -> 横排:禁止过渡,直接闪切
                                    inputContainerEl.classList.add('no-transition');
                                    inputContainerEl.classList.remove('stacked-animate');
                                    // 临时全局禁用过渡,彻底清空一帧动画
                                    try { document.body.classList.add('no-transition-global'); } catch (e) {}
                                    // 同步禁用外层面板的过渡,避免高度/内边距的缓动引发"漂移感"
                                    try {
                                        var panelEl = document.getElementById('douban-tmdb-panel');
                                        if (panelEl) panelEl.style.setProperty('transition', 'none', 'important');
                                    } catch (e) {}
                                    // 小延时后移除 no-transition,避免后续动画被禁
                                    setTimeout(function(){
                                        inputContainerEl.classList.remove('no-transition');
                                        try {
                                            var panelEl2 = document.getElementById('douban-tmdb-panel');
                                            if (panelEl2) panelEl2.style.removeProperty('transition');
                                        } catch (e) {}
                                        try { document.body.classList.remove('no-transition-global'); } catch (e) {}
                                    }, 160);
                                }
                                inputContainerEl.setAttribute('data-layout', dir);
                            }

                            // 初始化记录一次
                            applyDirectionalTransition();

                            window.addEventListener('resize', () => {
                                if (!toggle.checked) return;
                                // 800px阈值切换:横排→竖排无过渡且不延迟
                                log('窗口尺寸=' + window.innerWidth + 'x' + window.innerHeight);
                                applyDirectionalTransition();
                            });
                            // 首次也执行一次,确保无预览下仍能按规则切换
                            window.addEventListener('resize', applyDirectionalTransition);
                        } catch (e) { /* 静默失败以避免影响主流程 */ }
                    })();
                </script>
            </div>

            <!-- 选择海报区域 -->
              <div id="image-selection" style="margin-top:0; display:none;">
                <div style="margin-bottom:15px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
                        <h4 style="color:#db2777; margin:0; font-size:14px; font-weight:600; display:flex; align-items:center;">🖼️ 海报选择(点击选中)</h4>
                    </div>
                    <div id="poster-candidates" style="display: grid; grid-template-columns: repeat(5, 1fr); gap:14px; padding:8px; margin-bottom:8px; border:1px solid #f3d5d9; border-radius:8px; min-height:200px; max-height: clamp(320px, 60vh, 800px); overflow-y:auto; background:#fff;"></div>
                    <button id="load-more-posters" style="display: none; background:#f472b6; color:white; border:none; padding:6px 14px; border-radius:8px; cursor:pointer; font-size:12px; margin-bottom:5px; transition: background 0.2s ease, transform 0.2s ease;">加载更多海报</button>
                </div>

                <div style="margin-bottom:15px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                    <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
                        <h4 style="color:#db2777; margin:0; font-size:14px; font-weight:600; display:flex; align-items:center;">🎬 剧照选择(点击选中)</h4>
                    </div>
                    <div id="still-candidates" style="display: none; grid-template-columns: repeat(5, 1fr); gap:14px; padding:8px; margin-bottom:8px; border:1px solid #f3d5d9; border-radius:8px; min-height:200px; max-height: clamp(320px, 60vh, 800px); overflow-y:auto; background:#fff;"></div>
                    <button id="load-more-stills" style="display: none; background:#f472b6; color:white; border:none; padding:6px 14px; border-radius:8px; cursor:pointer; font-size:12px; margin-bottom:5px; transition: background 0.2s ease, transform 0.2s ease;">加载更多剧照</button>
                </div>

                <!-- 核心功能按钮组 -->
                <div style="display:flex; justify-content:flex-end; margin-top:15px; flex-wrap:wrap; gap:12px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                    <button id="clear-btn" style="background:#f87171; color:white; border:none; padding:8px 16px; border-radius:8px; cursor:pointer; font-size:13px; transition: all 0.3s ease;">清除</button>
                    <button id="emerald-city-format" style="background:linear-gradient(135deg, #ec4899 0%, #be185d 100%); color:white; border:none; padding:8px 18px; border-radius:8px; cursor:pointer; font-size:13px; font-weight:bold; transition: all 0.3s ease;">
                        <i class="fa fa-magic" style="margin-right:5px;"></i>粉黛仙境排版美化
                    </button>
                    <button id="confirm-images-btn" style="background:linear-gradient(135deg, #db2777 0%, #9d174d 100%); color:white; border:none; padding:8px 18px; border-radius:8px; cursor:pointer; font-size:13px; transition: all 0.3s ease;">
                        <i class="fa fa-heart" style="margin-right:5px;"></i>确认选择并填充(自动保存)
                    </button>
                </div>
            </div>

            <div id="status" style="margin-top:15px; padding:8px; border-radius:8px; font-size:12px; display:none; transition: all 0.3s ease;"></div>
        </div>

        <!-- AI功能区域 -->
        <div id="ai-content-area" style="display:none;">
            <div style="display:flex; justify-content:space-between; align-items:center; margin:0 0 15px 0; font-size:14px; font-weight:600; color:#be185d; border-bottom:1px solid #f3d5d9; padding-bottom:8px;">
                🤖 AI文字生成工具
                <!-- 已按需移除“设置智能体”入口,避免冗余功能按钮 -->
                <style>
                    /* 已移除设置智能体按钮,无需hover样式 */
                </style>
            </div>
            <div id="ai-panel-container"></div>
            <div id="status" style="margin-top:12px; padding:8px; border-radius:8px; font-size:12px; display:none;"></div>
        </div>
        <!-- 设置功能区域 -->
        <div id="settings-content-area" style="display:none;">
            <div style="display:flex; justify-content:space-between; align-items:center; margin:0 0 15px 0; font-size:14px; font-weight:600; color:#8b5cf6; border-bottom:1px solid #f3d5d9; padding-bottom:8px;">
                ⚙️ 脚本设置
            </div>

            <!-- TMDB API 配置 -->
            <div style="margin-bottom:20px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                <h4 style="margin:0 0 12px 0; color:#8b5cf6; font-size:14px; font-weight:600;">🔑 TMDB API 配置</h4>
                <div style="display:flex; flex-wrap:wrap; gap:15px;">
                    <div style="flex:1; min-width:250px;">
                        <label style="display:block; margin-bottom:5px; font-weight:500; color:#6b7280; font-size:13px;">API Key:</label>
                        <input type="text" id="tmdb-api-key" placeholder="输入您的TMDB API Key" style="width:100%; padding:8px; border:1px solid #f3d5d9; border-radius:8px; font-size:13px; transition: border-color 0.2s ease; outline:none;">
                    </div>
                    <div style="flex:1; min-width:250px;">
                        <label style="display:block; margin-bottom:5px; font-weight:500; color:#6b7280; font-size:13px;">Access Token:</label>
                        <input type="text" id="tmdb-base-url" placeholder="输入您的TMDB Access Token" style="width:100%; padding:8px; border:1px solid #f3d5d9; border-radius:8px; font-size:13px; transition: border-color 0.2s ease; outline:none;">
                    </div>
                </div>
                <div style="margin-top:10px; padding:10px; background:#f9fafb; border-radius:6px; border-left:3px solid #f59e0b;">
                    <p style="margin:0; font-size:12px; color:#6b7280;">
                        <strong>获取方法:</strong><br>
                        1. 登录(不可用)/注册(不可用)TMDB账号:访问 <a href="https://www.themoviedb.org/" target="_blank" style="color: #2563eb;">TMDB官网</a> ,登录(不可用)或注册(不可用)账号。<br>
                        2. 进入API设置:点击右上角头像→Settings→左侧API选项。<br>
                        3. 获取v3 API Key:在"API Keys (v3 auth)"区域,创建并复制Key。<br>
                        4. 获取v4 Access Token:在"Access Tokens (v4 auth)"区域,生成并复制Token。<br>
                        <br>
                        注意:遵守TMDB服务条款,界面可能微调。
                    </p>
                </div>
            </div>

            <!-- AI API 配置 -->
            <div style="margin-bottom:20px; padding:15px; background:#fff; border-radius:8px; border:1px solid #f3d5d9;">
                <h4 style="margin:0 0 12px 0; color:#8b5cf6; font-size:14px; font-weight:600;">🤖 AI API 配置</h4>
                <div style="display:flex; flex-wrap:wrap; gap:15px;">
                    <div style="flex:1; min-width:250px;">
                        <label style="display:block; margin-bottom:5px; font-weight:500; color:#6b7280; font-size:13px;">API Key:</label>
                        <input type="text" id="ai-api-key" placeholder="输入您的AI API Key" style="width:100%; padding:8px; border:1px solid #f3d5d9; border-radius:8px; font-size:13px; transition: border-color 0.2s ease; outline:none;">
                    </div>
                    <div style="flex:1; min-width:250px;">
                        <label style="display:block; margin-bottom:5px; font-weight:500; color:#6b7280; font-size:13px;">API 端点:</label>
                        <input type="text" id="ai-api-endpoint" placeholder="AI API 端点 URL" style="width:100%; padding:8px; border:1px solid #f3d5d9; border-radius:8px; font-size:13px; transition: border-color 0.2s ease; outline:none;">
                    </div>
                    <div style="flex:1; min-width:250px;">
                        <label style="display:block; margin-bottom:5px; font-weight:500; color:#6b7280; font-size:13px;">AI 提供商:</label>
                        <select id="ai-provider" style="width:100%; padding:8px; border:1px solid #f3d5d9; border-radius:8px; font-size:13px; transition: border-color 0.2s ease; outline:none; background-color: #fff;">
                            <option value="openai">OpenAI</option>
                            <option value="anthropic">Anthropic</option>
                            <option value="google">Google Gemini</option>
                            <option value="doubao">豆包</option>
                            <option value="tongyi">通义千问</option>
                            <option value="glm">智谱AI (GLM)</option>
                            <option value="spark">讯飞星火</option>
                            <option value="qwen">通义千问 (Qwen)</option>
                            <option value="zhipu">智谱AI</option>
                            <option value="custom">自定义</option>
                        </select>
                        <div style="color: #6b7280; font-size: 12px; margin-top: 5px;">选择您使用的AI服务提供商</div>
                    </div>
                    <div style="flex:1; min-width:250px;">
                        <label style="display:block; margin-bottom:5px; font-weight:500; color:#6b7280; font-size:13px;">AI 模型:</label>
                        <input type="text" id="ai-model" placeholder="AI 模型名称" style="width:100%; padding:8px; border:1px solid #f3d5d9; border-radius:8px; font-size:13px; transition: border-color 0.2s ease; outline:none;">
                    </div>
                </div>
                <div style="margin-top:10px; padding:10px; background:#f9fafb; border-radius:6px; border-left:3px solid #8b5cf6;">
                    <p style="margin:0; font-size:12px; color:#6b7280;">
                        <strong>推荐服务商:</strong><br>
                        • <strong>OpenAI:</strong> <a href="https://platform.openai.com/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>Claude:</strong> <a href="https://console.anthropic.com/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>Gemini:</strong> <a href="https://makersuite.google.com/app/apikey" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>豆包:</strong> <a href="https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>通义千问:</strong> <a href="https://dashscope.console.aliyun.com/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>智谱AI (GLM):</strong> <a href="https://open.bigmodel.cn/" target="_blank" style="color:#2563eb;">获取API Key</a><br>
                        • <strong>讯飞星火:</strong> <a href="https://console.xfyun.cn/services/bm3" target="_blank" style="color:#2563eb;">获取API Key</a>
                    </p>
                </div>
            </div>

            <!-- 功能按钮 -->
            <div style="display:flex; justify-content:flex-end; margin-top:20px; gap:12px;">
                <button id="reset-config-btn" style="background:#f59e0b; color:white; border:none; padding:8px 16px; border-radius:8px; cursor:pointer; font-size:13px; transition: all 0.3s ease;">重置为默认设置</button>
                <button id="save-config-btn" style="background:#a855f7; color:white; border:none; padding:8px 18px; border-radius:8px; cursor:pointer; font-size:13px; transition: all 0.3s ease;">保存设置</button>
            </div>
            <style>
                #reset-config-btn:hover { background:#d97706; transform: translateY(-1px); box-shadow: 0 2px 6px rgba(245, 158, 11, 0.3); }
                #save-config-btn:hover { background:#9333ea; transform: translateY(-1px); box-shadow: 0 2px 6px rgba(168, 85, 247, 0.3); }
                #tmdb-api-key:focus, #tmdb-base-url:focus, #ai-api-key:focus, #ai-api-endpoint:focus, #ai-model:focus, #ai-provider:focus {
                    border-color: #f472b6;
                    box-shadow: 0 0 0 2px rgba(244, 114, 182, 0.1);
                }
            </style>

            <div id="settings-status" style="margin-top:15px; padding:8px; border-radius:8px; font-size:12px; display:none; transition: all 0.3s ease;"></div>
        </div>
    `;
        return panel;
    }

    // 插入面板到标题输入框下方(精准定位+空值修复)
    function insertPanelInMarkedPosition() {
        if (isPanelInitialized) return;

        panel = createPanel();

        let targetContainer = document.body; // 默认值

        // 优先尝试在标题输入框下方插入
        const subjectInput = document.getElementById('subject');
        if (subjectInput && subjectInput.offsetParent !== null) {
            // 移除旧面板
            const oldPanel = document.getElementById('douban-tmdb-panel');
            const oldAIPanel = document.getElementById('ai-text-generation-panel');
            if (oldPanel) oldPanel.remove();
            if (oldAIPanel) oldAIPanel.remove();

            // 将新面板插入到标题输入框之后
            if (subjectInput.nextSibling) {
                subjectInput.parentNode.insertBefore(panel, subjectInput.nextSibling);
            } else {
                subjectInput.parentNode.appendChild(panel);
            }

            // 设置目标容器为标题输入框的父元素
            targetContainer = subjectInput.parentNode;
        } else {
            // 如果标题输入框不存在,使用原有的回退逻辑
            const targetContainers = [
                document.querySelector('.main-content'),
                (document.querySelector('#thread-create-form') || {}).parentElement,
                (document.querySelector('.post-form') || {}).parentElement,
                document.querySelector('.panel-default'),
                document.body
            ];

            for (const container of targetContainers) {
                if (container && container.offsetParent !== null) {
                    targetContainer = container;
                    break;
                }
            }

            if (!targetContainer) {
                targetContainer = document.body;
                console.warn('无法找到目标容器,已 fallback 到 document.body');
            }

            // 移除旧面板
            const oldPanel = targetContainer.querySelector('#douban-tmdb-panel');
            const oldAIPanel = targetContainer.querySelector('#ai-text-generation-panel');
            if (oldPanel) targetContainer.removeChild(oldPanel);
            if (oldAIPanel) targetContainer.removeChild(oldAIPanel);

            // 插入新面板
            targetContainer.appendChild(panel);
        }

        posterContainer = document.getElementById('poster-candidates');
        stillContainer = document.getElementById('still-candidates');
        initFormatTools();
        bindEventListeners();
        bindAIEventListeners(); // 绑定AI相关事件监听器
        setupMutationObserver(targetContainer);
        isPanelInitialized = true;
        showStatus('控制面板已放置在可用位置', false);
        return true;
    }
    insertPanelInMarkedPosition();

    // 监听父容器变化,确保面板位置不移动
    function setupMutationObserver(parent) {
        if (panelObserver) {
            panelObserver.disconnect();
        }

        panelObserver = new MutationObserver((mutations) => {
            mutations.forEach(mutation => {
                const panel = document.getElementById('douban-tmdb-panel');
                if (!panel || !parent.contains(panel)) {
                    parent.appendChild(panel || createPanel());
                    posterContainer = document.getElementById('poster-candidates');
                    stillContainer = document.getElementById('still-candidates');
                    initFormatTools();
                    bindEventListeners();
                    bindAIEventListeners(); // 重新绑定AI相关事件监听器
                }
            });
        });

        panelObserver.observe(parent, {
            childList: true,
            attributes: true,
            subtree: true,
            characterData: true
        });
    }

    // 确保switchTab函数在全局作用域可访问
    window.switchTab = switchTab;

    // 工具函数 - 支持向不同面板显示状态消息
    function showStatus(text, isError = false, target = 'main') {
        // 检查当前激活的标签页
        let activeTab = 'main';
        if (document.getElementById('main-tab').style.background.includes('linear-gradient')) {
            activeTab = 'main';
        } else if (document.getElementById('ai-tab').style.background.includes('linear-gradient')) {
            activeTab = 'ai';
        } else if (document.getElementById('settings-tab') && document.getElementById('settings-tab').style.background.includes('linear-gradient')) {
            activeTab = 'settings';
        }

        // 如果指定了目标,则使用指定的目标;否则使用当前激活的标签页
        const targetTab = target === 'all' ? activeTab : target;

        // 获取对应的状态元素
        let statusElement = null;
        if (targetTab === 'main') {
            statusElement = document.querySelector('#main-content-area #status');
        } else if (targetTab === 'ai') {
            statusElement = document.querySelector('#ai-content-area #status');
        } else if (targetTab === 'settings') {
            statusElement = document.querySelector('#settings-content-area #settings-status');
        }

        if (!statusElement) return;

        // 设置状态消息(避免强制重排:先写样式,再写内容)
        statusElement.style.willChange = 'opacity, transform';
        statusElement.style.transform = 'translateY(0)';
        statusElement.style.opacity = '1';
        statusElement.style.display = 'block';
        statusElement.style.cssText = `
            margin-top:10px; padding:8px; border-radius:6px; font-size:12px; transition: opacity .2s ease, transform .2s ease;
            ${isError ? 'background:#fee2e2; color:#b91c1c; border:1px solid #fecaca;' : 'background:#fef2f2; color:#be185d; border:1px solid #fecdd3;'}
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
        `;
        requestAnimationFrame(()=>{ statusElement.textContent = text; });

        // 2秒后自动隐藏(使用过渡,避免卡顿)
        setTimeout(() => {
            if (statusElement && statusElement.textContent === text) {
                statusElement.style.transform = 'translateY(-4px)';
                statusElement.style.opacity = '0';
                setTimeout(() => {
                    if (!statusElement || statusElement.textContent !== text) return;
                    statusElement.style.display = 'none';
                    statusElement.style.opacity = '1';
                    statusElement.style.transform = 'translateY(0)';
                }, 220);
            }
        }, 2000);
    }

    function debounce(func, wait) {
        let timeout;
        return function () {
            const context = this;
            const args = arguments;
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(context, args), wait);
        };
    }

    function safeGet(obj, path, defaultValue = '') {
        try {
            return path.split('.').reduce((o, k) => o[k], obj) || defaultValue;
        } catch (e) {
            return defaultValue;
        }
    }

    // 图片获取函数
    const IMG_CACHE = new Map();
    const IMG_QUEUE = [];
    let IMG_ACTIVE = 0;
    const IMG_LIMIT = 8; // 图片请求并发上限(加速首屏)

    function pumpImageQueue() {
        try {
            while (IMG_ACTIVE < IMG_LIMIT && IMG_QUEUE.length > 0) {
                const { task, resolve, reject } = IMG_QUEUE.shift();
                IMG_ACTIVE++;
                Promise.resolve()
                    .then(task)
                    .then(result => { IMG_ACTIVE--; resolve(result); pumpImageQueue(); })
                    .catch(err => { IMG_ACTIVE--; reject(err); pumpImageQueue(); });
            }
        } catch (e) { IMG_ACTIVE = Math.max(0, IMG_ACTIVE - 1); }
    }

    function scheduleImageTask(task) {
        return new Promise((resolve, reject) => {
            IMG_QUEUE.push({ task, resolve, reject });
            pumpImageQueue();
        });
    }
    function normalizeImageUrl(url) {
        try {
            if (!url) return '';
            let u = String(url).trim();
            if (u.startsWith('//')) u = 'https:' + u;
            if (u.includes('doubanio.com') && !/^https?:/.test(u)) u = 'https:' + u;
            return u;
        } catch (e) { return url; }
    }
    // 控制豆瓣图片下载并发(防止瞬时并发触发风控,同时保持速度)
    const D_IMG_CONCURRENCY = 5;
    let dImgActive = 0;
    const dImgQueue = [];
    function runDoubanImageTask(task){
        return new Promise((resolve)=>{
            const exec = ()=>{
                dImgActive++;
                task().then(resolve).finally(()=>{
                    dImgActive--;
                    const next = dImgQueue.shift();
                    if (next) next();
                });
            };
            if (dImgActive < D_IMG_CONCURRENCY) exec(); else dImgQueue.push(exec);
        });
    }

    function getImageDataURLWithQuality(url) {
        return scheduleImageTask(() => runDoubanImageTask(() => new Promise((resolve) => {
            if (!url) { resolve('https://picsum.photos/800/450?default-still'); return; }
            let baseUrl = normalizeImageUrl(url);
            // 内存级缓存,命中直接返回
            if (IMG_CACHE.has(baseUrl)) { resolve(IMG_CACHE.get(baseUrl)); return; }
            if (baseUrl.includes('doubanio.com') && baseUrl.includes('/m/')) {
                const config = getConfig();
                const qualityUrls = config.TMDB.DOUBAN_QUALITY.PRIORITY.map(quality =>
                    baseUrl.replace('/m/', `/${quality}/`)
                );
                const tryQuality = (index, retryCount = 0) => {
                    if (index >= qualityUrls.length) {
                        getFallbackImageDataURL(baseUrl).then((d)=>{ IMG_CACHE.set(baseUrl, d); resolve(d); });
                        return;
                    }
                    const currentUrl = qualityUrls[index];
                    doubanRequest({
                        method: 'GET',
                        url: currentUrl,
                        headers: { ...COMMON_HEADERS, 'Referer': 'https://movie.douban.com/' },
                        responseType: 'blob',
                        timeout: config.TMDB.DOUBAN_QUALITY.TIMEOUT
                    }).then((res)=>{
                            if (res.status === 200 && res.response) {
                                const reader = new FileReader();
                                reader.onload = (e) => { IMG_CACHE.set(baseUrl, e.target.result); resolve(e.target.result); };
                                reader.readAsDataURL(res.response);
                            } else if (retryCount < config.TMDB.DOUBAN_QUALITY.RETRY) {
                            setTimeout(() => tryQuality(index, retryCount + 1), 600);
                            } else {
                                tryQuality(index + 1);
                            }
                    }).catch(()=>{
                            if (retryCount < config.TMDB.DOUBAN_QUALITY.RETRY) {
                            setTimeout(() => tryQuality(index, retryCount + 1), 600);
                            } else {
                                tryQuality(index + 1);
                        }
                    });
                };
                tryQuality(0);
                return;
            }
            getFallbackImageDataURL(baseUrl).then((d)=>{ IMG_CACHE.set(baseUrl, d); resolve(d); });
        })));
    }

    function shouldConvertToDataURL(url) {
        try {
            const u = normalizeImageUrl(url);
            // 仅对豆瓣域名转DataURL;TMDB直接走CDN缩略图,避免慢
            return /doubanio\.com/.test(u);
        } catch (e) { return false; }
    }
    // 将豆瓣大图转为缩略图路径(m尺寸)
    function toDoubanThumb(url) {
        try {
            let u = normalizeImageUrl(url);
            u = u.replace(/\/raw\//, '/m/').replace(/\/l\//, '/m/');
            if (!/\/m\//.test(u)) u = u.replace(/\/s\//, '/m/');
            return u;
        } catch (e) { return url; }
    }
    // 获取用于展示的缩略图(豆瓣转为dataURL避免防盗链;TMDB返回CDN小图)
    function getThumbnailForDisplay(url) {
        try {
            const base = normalizeImageUrl(url);
            if (shouldConvertToDataURL(base)) {
                const m = toDoubanThumb(base);
                // 使用带Referer的请求转为dataURL,避免豆瓣直链防盗链导致空白
                return getFallbackImageDataURL(m);
            }
            const tm = toTMDBThumb(base);
            if (tm && tm.src) return Promise.resolve(tm.src);
            return Promise.resolve(base);
        } catch (e) { return Promise.resolve(url); }
    }
    // 懒加载占位图(1x1透明gif)
    const LAZY_PLACEHOLDER = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';

    // 候选图片懒加载观察器
    let posterObserver = null;
    let stillObserver = null;

    function initCandidateObservers() {
        try {
            const posterRoot = document.getElementById('poster-candidates') || null;
            const stillRoot = document.getElementById('still-candidates') || null;
            if (!posterObserver && posterRoot) {
                posterObserver = new IntersectionObserver(async (entries) => {
                    for (const entry of entries) {
                        if (entry.isIntersecting) {
                            const card = entry.target;
                            if (!card || card.dataset.loaded === '1') continue;
                            const rawUrl = card.dataset.rawUrl || card.dataset.url;
                            const img = card.querySelector('img');
                            if (!rawUrl || !img) { posterObserver.unobserve(card); continue; }
                            try {
                                if (shouldConvertToDataURL(rawUrl)) {
                                    const du = await getImageDataURLWithQuality(rawUrl);
                                    img.src = du;
                                    card.dataset.url = du;
                                    if (card === selectedPosterEl && selectedPosterUrl === rawUrl) {
                                        selectedPosterUrl = du;
                                    }
                                } else {
                                    // 列表小图,选中或升级时再换大图
                                    img.src = rawUrl;
                                    card.dataset.url = rawUrl;
                                }
                                card.dataset.loaded = '1';
                            } catch (e) {}
                            finally { posterObserver.unobserve(card); }
                        }
                    }
                }, { root: posterRoot, rootMargin: '200px', threshold: 0.05 });
            }
            if (!stillObserver && stillRoot) {
                stillObserver = new IntersectionObserver(async (entries) => {
                    for (const entry of entries) {
                        if (entry.isIntersecting) {
                            const card = entry.target;
                            if (!card || card.dataset.loaded === '1') continue;
                            const rawUrl = card.dataset.rawUrl || card.dataset.url;
                            const img = card.querySelector('img');
                            if (!rawUrl || !img) { stillObserver.unobserve(card); continue; }
                            try {
                                if (shouldConvertToDataURL(rawUrl)) {
                                    const du = await getImageDataURLWithQuality(rawUrl);
                                    img.src = du;
                                    card.dataset.url = du;
                                    if (card === selectedStillEl && selectedStillUrl === rawUrl) {
                                        selectedStillUrl = du;
                                    }
                                } else {
                                    img.src = rawUrl;
                                    card.dataset.url = rawUrl;
                                }
                                card.dataset.loaded = '1';
                            } catch (e) {}
                            finally { stillObserver.unobserve(card); }
                        }
                    }
                }, { root: stillRoot, rootMargin: '200px', threshold: 0.05 });
            }
        } catch (e) {}
    }

    function observeCandidateCard(card, type) {
        try {
            if (type === 'poster' && posterObserver) posterObserver.observe(card);
            if (type === 'still' && stillObserver) stillObserver.observe(card);
        } catch (e) {}
    }

    function disconnectCandidateObservers() {
        try { if (posterObserver) { posterObserver.disconnect(); posterObserver = null; } } catch (e) {}
        try { if (stillObserver)  { stillObserver.disconnect();  stillObserver  = null; } } catch (e) {}
    }

    async function primeFirstCandidates() {
        try {
            // 立即加载首图,确保不点击也能拿到有效 dataURL
            if (selectedPosterEl && selectedPosterEl.dataset && selectedPosterEl.dataset.rawUrl && selectedPosterEl.dataset.loaded !== '1') {
                const rawUrl = selectedPosterEl.dataset.rawUrl;
                const img = selectedPosterEl.querySelector('img');
                if (img) {
                    try {
                        const src = shouldConvertToDataURL(rawUrl) ? await getImageDataURLWithQuality(rawUrl) : rawUrl.replace(`/${config.TMDB.LIST_POSTER_SIZE}/`, `/${config.TMDB.SELECTED_POSTER_SIZE}/`);
                        img.src = src;
                        selectedPosterEl.dataset.url = src;
                        selectedPosterEl.dataset.loaded = '1';
                        if (selectedPosterUrl === rawUrl) selectedPosterUrl = src;
                    } catch (e) {}
                }
            }
            if (selectedStillEl && selectedStillEl.dataset && selectedStillEl.dataset.rawUrl && selectedStillEl.dataset.loaded !== '1') {
                const rawUrl = selectedStillEl.dataset.rawUrl;
                const img = selectedStillEl.querySelector('img');
                if (img) {
                    try {
                        const src = shouldConvertToDataURL(rawUrl) ? await getImageDataURLWithQuality(rawUrl) : rawUrl.replace(`/${config.TMDB.LIST_STILL_SIZE}/`, `/${config.TMDB.SELECTED_STILL_SIZE}/`);
                        img.src = src;
                        selectedStillEl.dataset.url = src;
                        selectedStillEl.dataset.loaded = '1';
                        if (selectedStillUrl === rawUrl) selectedStillUrl = src;
                    } catch (e) {}
                }
            }
        } catch (e) {}
    }
    // TMDB缩略图:w92 + 2x(w154)
    function toTMDBThumb(url) {
        try {
            if (!url) return null;
            const u = normalizeImageUrl(url);
            const m = u.match(/\/t\/p\/(?:original|w\d+|h\d+)\/([^\?\s]+)$/);
            if (!m) return null;
            const tail = m[1];
            const base = 'https://image.tmdb.org/t/p';
            // 提升首屏清晰度:列表小图用w154,2x用w342(仍远小于w780),性能与质量平衡
            return { src: `${base}/w154/${tail}`, srcset: `${base}/w342/${tail} 2x` };
        } catch (e) { return null; }
    }

    // 将TMDB图片URL统一升级为original(用于最终排版,避免放大模糊)
    function toTMDBOriginal(url) {
        try {
            if (!url) return url;
            const u = normalizeImageUrl(url);
            if (!/image\.tmdb\.org\/t\/p\//.test(u)) return url;
            return u.replace(/\/t\/p\/(?:w\d+|h\d+|original)\//, '/t/p/original/');
        } catch (e) { return url; }
    }
    // TMDB结果缓存(热评/列表等)
    const TMDB_REVIEW_CACHE = new Map();

    // 图片有效性验证函数(减少豆瓣请求,避免检测)
    function validateImageUrl(url) {
        return new Promise((resolve) => {
            if (!url || url.includes('picsum.photos')) {
                resolve(false);
                return;
            }

            // 对豆瓣图片采用保守策略,减少HEAD请求
            if (url.includes('doubanio.com')) {
                // 豆瓣图片:仅基于URL格式判断,不发送验证请求
                const isValidFormat = /doubanio\.com.*\.(jpg|jpeg|png|webp)/i.test(url) &&
                                     !url.includes('default') &&
                                     !url.includes('error');
                console.log('豆瓣图片保守验证:', url, isValidFormat);
                resolve(isValidFormat);
                return;
            }

            // 非豆瓣图片才进行HEAD请求验证
            GM_xmlhttpRequest({
                method: 'HEAD',
                url: url,
                headers: {
                    ...COMMON_HEADERS,
                    'Referer': url.includes('themoviedb.org') ? 'https://www.themoviedb.org/' : ''
                },
                timeout: 3000,
                onload: (res) => {
                    const isValid = res.status === 200 &&
                        res.responseHeaders.toLowerCase().includes('image/');
                    resolve(isValid);
                },
                onerror: () => resolve(false),
                ontimeout: () => resolve(false)
            });
        });
    }

    function getFallbackImageDataURL(url) {
        return new Promise(async (resolve) => {
            // 豆瓣图片跳过预验证,直接尝试下载(避免触发检测)
            if (url.includes('doubanio.com')) {
                console.log('豆瓣图片跳过预验证,直接下载:', url);
            } else {
                // 非豆瓣图片才进行预验证
                const isValid = await validateImageUrl(url);
                if (!isValid) {
                    console.log('图片URL无效,跳过下载:', url);
                    resolve('https://picsum.photos/800/450?error-still');
                    return;
                }
            }

            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                headers: {
                    ...COMMON_HEADERS,
                    'Referer': url.includes('doubanio.com') ? 'https://movie.douban.com/' :
                        url.includes('themoviedb.org') ? 'https://www.themoviedb.org/' : ''
                },
                responseType: 'blob',
                timeout: 5000, // 增加到5秒
                onload: (res) => {
                    if (res.status === 200 && res.response && res.response.size > 0) {
                        // 验证blob是否为有效图片
                        if (res.response.type.startsWith('image/')) {
                            const reader = new FileReader();
                            reader.onload = (e) => {
                                // 进一步验证DataURL
                                const dataUrl = e.target.result;
                                if (dataUrl && dataUrl.length > 100) { // 最小有效长度检查
                                    resolve(dataUrl);
                                } else {
                                    console.log('生成的DataURL无效:', url);
                                    resolve('https://picsum.photos/800/450?error-still');
                                }
                            };
                            reader.onerror = () => {
                                console.log('FileReader读取失败:', url);
                                resolve('https://picsum.photos/800/450?error-still');
                            };
                            reader.readAsDataURL(res.response);
                        } else {
                            console.log('响应不是图片类型:', res.response.type, url);
                            resolve('https://picsum.photos/800/450?error-still');
                        }
                    } else {
                        console.log('图片请求失败或空响应:', res.status, url);
                        resolve('https://picsum.photos/800/450?error-still');
                    }
                },
                onerror: (e) => {
                    console.log('图片请求网络错误:', e, url);
                    resolve('https://picsum.photos/800/450?error-still');
                },
                ontimeout: () => {
                    console.log('图片请求超时:', url);
                    resolve('https://picsum.photos/800/450?error-still');
                }
            });
        });
    }

    // 【修复1】海报加载逻辑:按页截取(每次5张,不重复)
    async function getDoubanOfficialPosters(subjectUrl, page = 1) {
        return new Promise(resolve => {
            try {
                const config = getConfig();
                const posterPage = page; // 使用传入的页码
                const urlObj = new URL(subjectUrl);
                const photosUrl = subjectUrl.replace(/\/subject\/(\d+)\/?$/, '/subject/$1/photos?type=R');
                // 豆瓣海报请求URL(走防爬封装)
                doubanRequest({
                    method: 'GET',
                    url: photosUrl,
                    headers: { ...COMMON_HEADERS, 'Referer': subjectUrl, 'Host': urlObj.hostname },
                    timeout: 8000
                }).then((res)=>{
                        try {
                            // 豆瓣海报页面请求成功
                            const doc = new DOMParser().parseFromString(res.responseText, 'text/html');

                            // 尝试多种选择器
                            let posterImgs = [];

                              // 尝试1: 原有选择器
                             let imgs = Array.from(doc.querySelectorAll('.poster-col3 li img, .article img'));
                             console.log('选择器1找到图片数量:', imgs.length);

                             if (imgs.length === 0) {
                                 // 尝试2: 更通用的选择器
                                 imgs = Array.from(doc.querySelectorAll('img[src*="doubanio.com"], img[data-src*="doubanio.com"], img[srcset*="doubanio.com"]'));
                                 console.log('选择器2找到图片数量:', imgs.length);
                             }

                             if (imgs.length === 0) {
                                 // 尝试3: 查找所有img标签
                                 imgs = Array.from(doc.querySelectorAll('img, source'));
                                 console.log('选择器3找到所有图片数量:', imgs.length);
                                 // 过滤出豆瓣图片
                                 imgs = imgs.map(el => {
                                     if (el.tagName.toLowerCase() === 'source') return el.srcset || '';
                                     return el.getAttribute('data-src') || el.getAttribute('data-origin') || el.src || '';
                                 }).filter(u => u.includes('doubanio.com'));
                                 console.log('过滤后的豆瓣图片数量:', imgs.length);
                             }

                             // 尝试4: 如果还是没有,从页面主体区域查找
                             if (imgs.length === 0) {
                                 console.log('前面方法都失败,尝试从主内容区域查找');
                                 const mainContent = doc.querySelector('#wrapper') || doc.querySelector('.main') || doc.body;
                                 if (mainContent) {
                                     imgs = Array.from(mainContent.querySelectorAll('img')).filter(img =>
                                         img.src &&
                                         img.src.includes('doubanio.com') &&
                                         (img.src.includes('/movie_poster_') || img.src.includes('/public/p'))
                                     );
                                     console.log('主内容区域找到的图片数量:', imgs.length);
                                 }
                             }

                            posterImgs = imgs
                                .map(el => {
                                    let src = (typeof el === 'string') ? el : (el.getAttribute?.('data-src') || el.getAttribute?.('data-origin') || el.src || '');
                                    if (src && src.includes(' ')) { // 从srcset提取最清晰一项
                                        const parts = src.split(',').map(s => s.trim());
                                        src = parts[parts.length - 1].split(' ')[0];
                                    }
                                    if (src.includes('/m/')) src = src.replace('/m/', '/l/');
                                    return src;
                                })
                                .filter(Boolean)
                                // 按当前页截取:(页号-1)*5 到 页号*5
                                .slice((posterPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, posterPage * config.TMDB.IMAGE_CANDIDATES_COUNT);

                            // 最终海报数据
                            console.log('最终海报数据:', posterImgs);
                            resolve(posterImgs.length ? posterImgs : []);
                        } catch (e) {
                            console.error('解析豆瓣海报页面失败:', e);
                            resolve([]);
                        }
                }).catch((error)=>{
                        console.error('获取豆瓣海报请求错误:', error);
                        resolve([]);
                });
            } catch (e) {
                console.error('无效的豆瓣主题URL:', subjectUrl, e);
                resolve([]);
            }
        });
    }

    // 【修复2】剧照加载逻辑:按页截取(每次5张,不重复)+ 宽高适配
    function getDoubanStillsList(url, page = 1) {
        return new Promise(resolve => {
            try {
                const urlObj = new URL(url);
                const stillsUrl = url.replace(/\/subject\/(\d+)\/?$/, '/subject/$1/photos?type=still');
                // 豆瓣剧照请求URL(走防爬封装)
                doubanRequest({
                    method: 'GET',
                    url: stillsUrl,
                    headers: { ...COMMON_HEADERS, 'Referer': url, 'Host': urlObj.hostname },
                    timeout: 8000
                }).then((res)=>{
                        try {
                            // 豆瓣剧照页面请求成功
                            const doc = new DOMParser().parseFromString(res.responseText, 'text/html');

                            let finalStills = [];

                             // 尝试1: 查找带剧照标记的图片
                             let labeledStills = Array.from(doc.querySelectorAll('.poster-col3 li img[data-title*="剧照"], .article img[data-title*="剧照"]'))
                                 .map(img => img.getAttribute('data-src') || img.getAttribute('data-origin') || img.src)
                                 .filter(Boolean);
                             console.log('标记为剧照的图片数量:', labeledStills.length);

                             if (labeledStills.length > 0) {
                                 finalStills = labeledStills;
                             } else {
                                 // 尝试2: 所有poster-col3下的图片
                                 let allImgs = Array.from(doc.querySelectorAll('.poster-col3 li img, .article img'))
                                     .map(img => img.getAttribute('data-src') || img.getAttribute('data-origin') || img.src)
                                     .filter(Boolean);
                                 console.log('poster-col3下的所有图片数量:', allImgs.length);

                                 if (allImgs.length === 0) {
                                     // 尝试3: 查找所有豆瓣图片
                                     allImgs = Array.from(doc.querySelectorAll('img[src*="doubanio.com"], img[data-src*="doubanio.com"], img[srcset*="doubanio.com"]'))
                                         .map(el => el.getAttribute('data-src') || el.getAttribute('data-origin') || el.src || el.srcset || '')
                                         .map(s => (s && s.includes(' ')) ? s.split(',').map(p=>p.trim()).pop().split(' ')[0] : s)
                                         .filter(Boolean);
                                     console.log('所有豆瓣图片数量:', allImgs.length);
                                 }

                                finalStills = allImgs;
                            }

                            // 按当前页截取:(页号-1)*5 到 页号*5
                            const config = getConfig();
                            const stillPage = page; // 使用传入的页码
                            const pageStills = finalStills.slice((stillPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, stillPage * config.TMDB.IMAGE_CANDIDATES_COUNT);

                            // 最终剧照数据
                            console.log('最终剧照数据:', pageStills);
                            resolve(pageStills);
                        } catch (e) {
                            console.error('解析豆瓣剧照页面失败:', e);
                            resolve([]);
                        }
                }).catch((error)=>{
                        console.error('获取豆瓣剧照请求错误:', error);
                        resolve([]);
                });
            } catch (e) {
                console.error('无效的豆瓣URL:', url, e);
                resolve([]);
            }
        });
    }

    // 【修复3】TMDB剧照加载逻辑:按页截取(统一分页逻辑)
    function getTMDBStillsList(mediaType, id, page = 1) {
        return new Promise(resolve => {
            const config = getConfig();
            const stillPage = page; // 使用传入的页码
            const stillCutsUrl = `${config.TMDB.BASE_URL}/${mediaType}/${id}/images?api_key=${config.TMDB.API_KEY}&include_image_language=zh,en&image_type=still_cuts&sort_by=primary`;
            GM_xmlhttpRequest({
                method: 'GET',
                url: stillCutsUrl,
                headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                timeout: 10000,
                onload: (res) => {
                    try {
                        const data = JSON.parse(res.responseText);
                        const stillCuts = safeGet(data, 'still_cuts', []);
                        // 按当前页截取剧照(每次5张)
                        let currentPageStills = stillCuts
                            .map(img => `${config.TMDB.IMAGE_BASE_URL}${config.TMDB.LIST_STILL_SIZE}/${img.file_path}`)
                            .filter(Boolean)
                            .slice((stillPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, stillPage * config.TMDB.IMAGE_CANDIDATES_COUNT);

                        if (currentPageStills.length >= config.TMDB.IMAGE_CANDIDATES_COUNT) {
                            resolve(currentPageStills);
                            return;
                        }

                        // 补充backdrops(按当前页截取)
                        const backdropsUrl = `${config.TMDB.BASE_URL}/${mediaType}/${id}/images?api_key=${config.TMDB.API_KEY}&include_image_language=zh,en&image_type=backdrop&sort_by=vote_average.desc`;
                        GM_xmlhttpRequest({
                            method: 'GET',
                            url: backdropsUrl,
                            headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                            onload: (res) => {
                                try {
                                    const data = JSON.parse(res.responseText);
                                    const backdrops = safeGet(data, 'backdrops', []);
                                    const backdropPageStills = backdrops
                                        .map(img => `${config.TMDB.IMAGE_BASE_URL}${config.TMDB.LIST_STILL_SIZE}/${img.file_path}`)
                                        .filter(Boolean)
                                        .slice((stillPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, stillPage * config.TMDB.IMAGE_CANDIDATES_COUNT);

                                    currentPageStills = [...currentPageStills, ...backdropPageStills].slice(0, config.TMDB.IMAGE_CANDIDATES_COUNT);
                                    if (currentPageStills.length >= config.TMDB.IMAGE_CANDIDATES_COUNT) {
                                        resolve(currentPageStills);
                                        return;
                                    }

                                    // 补充posters(按当前页截取)
                                    const postersUrl = `${config.TMDB.BASE_URL}/${mediaType}/${id}/images?api_key=${config.TMDB.API_KEY}&include_image_language=zh,en&image_type=poster&sort_by=primary`;
                                    GM_xmlhttpRequest({
                                        method: 'GET',
                                        url: postersUrl,
                                        headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                                        onload: (res) => {
                                            try {
                                                const data = JSON.parse(res.responseText);
                                                const posters = safeGet(data, 'posters', []);
                                                const posterPageStills = posters.slice(1)
                                                    .map(img => `${config.TMDB.IMAGE_BASE_URL}${config.TMDB.LIST_STILL_SIZE}/${img.file_path}`)
                                                    .filter(Boolean)
                                                    .slice((stillPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, stillPage * config.TMDB.IMAGE_CANDIDATES_COUNT);

                                                currentPageStills = [...currentPageStills, ...posterPageStills].slice(0, config.TMDB.IMAGE_CANDIDATES_COUNT);
                                                resolve(currentPageStills);
                                            } catch (e) {
                                                resolve(currentPageStills);
                                            }
                                        },
                                        onerror: () => resolve(currentPageStills),
                                        ontimeout: () => resolve(currentPageStills)
                                    });
                                } catch (e) {
                                    resolve(currentPageStills);
                                }
                            },
                            onerror: () => resolve(currentPageStills),
                            ontimeout: () => resolve(currentPageStills)
                        });
                    } catch (e) {
                        resolve([]);
                    }
                },
                onerror: () => resolve([]),
                ontimeout: () => resolve([])
            });
        });
    }

    // 搜索相关函数
    // 搜索结果缓存
    const searchCache = new Map();
    const CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存

    // 全局搜索状态变量
    let lastSearchResults = [];
    let lastSearchQuery = '';

    // 统一的层级管理常量
    const Z_INDEX_LAYERS = {
        SEARCH_RESULTS: 2147483647,    // 搜索结果框 - 最高层级
        SEARCH_CONTAINER: 2147483646,  // 搜索容器
        SEARCH_LOADING: 2147483645     // 搜索中指示器 - 在搜索框内显示
    };

    // 优化的搜索中指示器控制函数
    function setSearchLoading(show) {
        const loadingIndicator = document.getElementById('search-loading');
        if (loadingIndicator) {
            if (show) {
                // 记录显示时间
                loadingIndicator.dataset.showTime = Date.now().toString();

                // 立即显示并设置正确的层级
                loadingIndicator.style.setProperty('display', 'block', 'important');
                loadingIndicator.style.setProperty('visibility', 'visible', 'important');
                loadingIndicator.style.setProperty('opacity', '1', 'important');
                loadingIndicator.style.setProperty('z-index', Z_INDEX_LAYERS.SEARCH_LOADING, 'important');

                // 立即校准位置,确保显示在搜索框内
                resetSearchLoadingPosition();

                // 搜索中指示器已显示
            } else {
                // 清除显示时间记录
                delete loadingIndicator.dataset.showTime;
                loadingIndicator.style.setProperty('display', 'none', 'important');
                // 搜索中指示器已隐藏
            }
        } else {
            console.warn('搜索中指示器元素未找到');
        }
    }

    // 统一的搜索结果框显示控制函数 - 优化版,确保输入框水平对齐
    function showSearchResults() {
        const resultsContainer = document.getElementById('search-results');
        const controlPanel = document.getElementById('douban-tmdb-panel');
        const inputContainer = document.getElementById('input-container');

        if (resultsContainer && lastSearchResults.length > 0) {
            // 只有在内容已准备好时才显示
            if (resultsContainer.innerHTML.trim() !== '') {
                // 优化控制面板展开机制 - 确保输入框保持水平对齐
                if (controlPanel) {
                    // 添加展开状态的视觉指示
                    controlPanel.classList.add('expanded');

                    // 确保控制面板有足够的内部空间显示搜索结果
                    controlPanel.style.setProperty('overflow', 'visible', 'important');
                    controlPanel.style.setProperty('transition', 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)', 'important');
                }

                // 确保输入框容器保持水平对齐
                if (inputContainer) {
                    inputContainer.style.setProperty('align-items', 'flex-start', 'important');
                    inputContainer.style.setProperty('display', 'flex', 'important');
                }

                // 设置显示状态:通过类控制展开,避免display切换导致空白
                resultsContainer.style.setProperty('display', 'block', 'important');
                resultsContainer.style.setProperty('visibility', 'visible', 'important');
                resultsContainer.style.setProperty('opacity', '1', 'important');
                resultsContainer.style.setProperty('position', 'relative', 'important');
                resultsContainer.style.setProperty('z-index', '1', 'important');
                resultsContainer.style.setProperty('margin-top', '8px', 'important');

                // 添加显示动画
                resultsContainer.classList.add('show');
                return true;
            }
        }
        return false;
    }

    // 简化的显示动画函数
    function animateShow(element, className = 'show') {
        if (element && !element.classList.contains(className)) {
            element.classList.add(className);
        }
    }

    // 将搜索结果容器的可视高度限制为约6条影片的高度,更多通过滚动查看
    function adjustSearchResultsHeightToSix(container) {
        try {
            if (!container) return;
            const items = container.querySelectorAll('.search-item');
            if (!items || items.length === 0) return;

            if (items.length <= 6) {
                // 少于等于6条不限制高度
                container.style.removeProperty('max-height');
                return;
            }

            // 计算前6条底部相对容器的像素高度
            const sixth = items[5];
            const targetBottom = sixth.offsetTop + sixth.offsetHeight + 6; // 6px缓冲
            container.style.setProperty('max-height', targetBottom + 'px', 'important');
            container.style.setProperty('overflow-y', 'auto', 'important');
            container.style.setProperty('overscroll-behavior', 'contain', 'important');
        } catch (_) {}
    }

    // 轻量隐藏:只做淡出与关闭交互,避免 display 切换引发布局重排
    function fadeOutSearchResultsNoLayout() {
        const resultsContainer = document.getElementById('search-results');
        const controlPanel = document.getElementById('douban-tmdb-panel');
        const inputContainer = document.getElementById('input-container');

        if (resultsContainer) {
            // 先移除动画类,触发隐藏动画
            resultsContainer.classList.remove('show');
            resultsContainer.style.willChange = 'opacity, transform, max-height';
            resultsContainer.style.visibility = 'hidden';
            resultsContainer.style.opacity = '0';
            resultsContainer.style.pointerEvents = 'none';
            resultsContainer.style.maxHeight = '0';
            resultsContainer.style.marginTop = '0';

            // 过渡结束后彻底移除占位,避免窄屏不回弹
            const endHide = () => {
                resultsContainer.style.setProperty('display', 'none', 'important');
                resultsContainer.removeEventListener('transitionend', endHide);
            };
            resultsContainer.addEventListener('transitionend', endHide);
            setTimeout(endHide, 250);

            // 恢复控制面板的原始状态
            if (controlPanel) {
                // 移除展开状态的视觉指示
                controlPanel.classList.remove('expanded');

                // 恢复控制面板的原始样式
                controlPanel.style.setProperty('overflow', 'visible', 'important');
                controlPanel.style.setProperty('transition', 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)', 'important');
            }

            // 确保输入框容器保持水平对齐
            if (inputContainer) {
                inputContainer.style.setProperty('align-items', 'flex-start', 'important');
                inputContainer.style.setProperty('display', 'flex', 'important');
            }
        }

        // 隐藏搜索中指示器
        setSearchLoading(false);
    }

    // 兼容旧调用名
    function hideSearchResults() { fadeOutSearchResultsNoLayout(); }

    // 检测当前布局状态
    function detectLayoutState() {
        const searchInput = document.getElementById('search-movie');
        const mediaUrlLabel = document.querySelector('label[for="media-url"], label[style*="width:70px"]');

        if (!searchInput || !mediaUrlLabel) return 'horizontal';

        const inputRect = searchInput.getBoundingClientRect();
        const labelRect = mediaUrlLabel.getBoundingClientRect();

        // 如果标签在搜索框下方,说明是垂直布局
        const isVertical = labelRect.top > inputRect.bottom + 10; // 10px容差

        return isVertical ? 'vertical' : 'horizontal';
    }

    // 动态调整输入框对齐
    function adjustInputAlignment() {
        const inputContainer = document.getElementById('input-container');
        const searchContainer = document.querySelector('div[style*="flex: 1 1 250px"][style*="min-width: 200px"][style*="position: relative"]');
        const linkContainer = document.getElementById('media-url-container');

        if (!inputContainer || !searchContainer || !linkContainer) return;

        const windowWidth = window.innerWidth;
        const isMobile = windowWidth < 800;

        if (isMobile) {
            // 移动端:垂直布局
            inputContainer.style.setProperty('flex-direction', 'column', 'important');
            inputContainer.style.setProperty('align-items', 'stretch', 'important');
            inputContainer.style.setProperty('gap', '12px', 'important');

            // 竖排时子块恢复自适应,避免横排规则残留
            try {
                searchContainer.style.removeProperty('display');
                searchContainer.style.removeProperty('align-items');
                searchContainer.style.removeProperty('min-height');
                linkContainer.style.removeProperty('display');
                linkContainer.style.removeProperty('align-items');
                linkContainer.style.removeProperty('min-height');
            } catch (e) {}
        } else {
            // 桌面端:水平布局
            inputContainer.style.setProperty('flex-direction', 'row', 'important');
            inputContainer.style.setProperty('align-items', 'flex-start', 'important');
            inputContainer.style.setProperty('gap', '15px', 'important');

            // 两个子容器统一为顶部对齐,避免切换瞬间出现"先居中"的视觉跳动
            try {
                searchContainer.style.setProperty('display', 'flex', 'important');
                searchContainer.style.setProperty('align-items', 'flex-start', 'important');
                searchContainer.style.setProperty('min-width', '200px', 'important');
                linkContainer.style.setProperty('display', 'flex', 'important');
                linkContainer.style.setProperty('align-items', 'flex-start', 'important');
                linkContainer.style.setProperty('min-width', '200px', 'important');
            } catch (e) {}
        }

        // 确保两个输入框容器高度一致
        const searchRect = searchContainer.getBoundingClientRect();
        const linkRect = linkContainer.getBoundingClientRect();

        if (!isMobile && Math.abs(searchRect.height - linkRect.height) > 5) {
            const maxHeight = Math.max(searchRect.height, linkRect.height);
            searchContainer.style.setProperty('min-height', maxHeight + 'px', 'important');
            linkContainer.style.setProperty('min-height', maxHeight + 'px', 'important');
        }
    }
    // 优化的位置校准函数
    function resetSearchLoadingPosition() {
        const loadingIndicator = document.getElementById('search-loading');
        const searchInput = document.getElementById('search-movie');
        if (!loadingIndicator || !searchInput) return;

        const windowWidth = window.innerWidth;
        const isVerticalLayout = windowWidth < 800;

        // 简化的位置计算
        const rightOffset = windowWidth > 900 ? 8 :
                           windowWidth > 650 ? 6 :
                           windowWidth > 400 ? 4 :
                           windowWidth > 300 ? 2 : 1;

        const topPosition = isVerticalLayout
            ? `calc(45% + ${windowWidth > 650 ? 2 : 1}px)`
            : '50%';

        // 强制设置所有样式,确保在缩放时完全不会消失
        loadingIndicator.style.setProperty('position', 'absolute', 'important');
        loadingIndicator.style.setProperty('right', `${rightOffset}px`, 'important');
        loadingIndicator.style.setProperty('top', topPosition, 'important');
        loadingIndicator.style.setProperty('transform', 'translateY(-50%)', 'important');
        loadingIndicator.style.setProperty('display', 'block', 'important');
        loadingIndicator.style.setProperty('visibility', 'visible', 'important');
        loadingIndicator.style.setProperty('opacity', '1', 'important');
        loadingIndicator.style.setProperty('z-index', Z_INDEX_LAYERS.SEARCH_LOADING, 'important');
        loadingIndicator.style.setProperty('color', '#6b7280', 'important');
        loadingIndicator.style.setProperty('font-size', '11px', 'important');
        loadingIndicator.style.setProperty('font-weight', '500', 'important');
        loadingIndicator.style.setProperty('background', 'rgba(255, 255, 255, 0.9)', 'important');
        loadingIndicator.style.setProperty('padding', '2px 6px', 'important');
        loadingIndicator.style.setProperty('border-radius', '4px', 'important');
    }

    // 强制注入CSS确保搜索结果框显示(优化版 - 内嵌到控制面板中)
    function injectSearchResultsCSS() {
        // 避免重复注入CSS
        if (document.getElementById('search-results-force-style')) {
            return;
        }

        const style = document.createElement('style');
        style.id = 'search-results-force-style';
        style.textContent = `
            /* 强制降低遮挡元素的层级 */
            div.tox-editor-header {
                z-index: 1 !important;
            }

            /* 独立容器的搜索结果框样式 - 确保输入框水平对齐 */
            #search-results {
                position: relative !important;
                top: 0 !important;
                left: 0 !important;
                right: 0 !important;
                z-index: 1 !important;
                background: #fff !important;
                border: 1px solid #f3d5d9 !important;
                border-radius: 6px !important;
                margin-top: 8px !important;
                margin-left: 0 !important;
                margin-right: 0 !important;
                box-shadow: 0 4px 12px rgba(0,0,0,0.15) !important;
                width: 100% !important;
                max-height: 400px !important;
                overflow-y: auto !important;
                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
                transform: none !important;
            }

            /* 搜索结果容器优化样式 - 已内嵌到控制面板中,无需绝对定位 */

            /* 搜索中指示器基础样式 - 默认隐藏,由JavaScript控制显示 */
            #search-loading {
                position: absolute !important;
                right: 10px !important;
                top: 35% !important;
                transform: translateY(-50%) !important;
                color: #6b7280 !important;
                font-size: 11px !important;
                font-weight: 500 !important;
                background: rgba(255, 255, 255, 0.9) !important;
                padding: 2px 6px !important;
                border-radius: 4px !important;
                z-index: 1001 !important; /* 搜索中指示器 - 最高层级 */
                pointer-events: none !important;
                white-space: nowrap !important;
                overflow: hidden !important;
                text-overflow: ellipsis !important;
                max-width: 60px !important;
                box-sizing: border-box !important;
                display: none !important; /* 默认隐藏,由JavaScript控制 */
                visibility: visible !important; /* 确保可见性 */
                opacity: 1 !important; /* 确保透明度 */
            }

            #search-results * {
                pointer-events: auto !important;
            }

            /* 确保搜索结果框的父容器也有足够高的z-index */
            div[style*="position: relative"]:has(#search-results) {
                z-index: 999999 !important;
            }

            /* 搜索中指示器保护样式已在上方统一定义 */


            /* 重复的媒体查询已在上方统一定义 */

            /* 在垂直布局时调整搜索中指示器位置 */
            @media screen and (max-width: 800px) {
                /* 确保在垂直布局时,指示器相对于输入框而不是标签定位 */
                div[style*="position: relative"]:has(#search-movie) {
                    position: relative !important;
                }

                /* 当标签和输入框变为上下布局时,调整搜索中指示器位置 */
                #search-loading {
                    position: absolute !important;
                    right: 10px !important;
                    /* 在垂直布局时,现在相对于搜索框容器定位,不需要额外偏移 */
                    top: 35% !important;
                    transform: translateY(-50%) !important;
                    color: #6b7280 !important;
                    font-size: 11px !important;
                    font-weight: 500 !important;
                    background: rgba(255, 255, 255, 0.9) !important;
                    padding: 2px 6px !important;
                    border-radius: 4px !important;
                    z-index: 1001 !important; /* 搜索中指示器 - 最高层级 */
                    pointer-events: none !important;
                    /* 强制重置其他可能影响的属性 */
                    left: auto !important;
                    bottom: auto !important;
                    margin: 0 !important;
                    width: auto !important;
                    height: auto !important;
                    max-width: none !important;
                    min-width: 0 !important;
                }
            }

            @media screen and (max-width: 650px) {
                /* 更窄屏幕下的微调 */
                #search-loading {
                    position: absolute !important;
                    right: 3px !important;
                    top: 35% !important;
                    transform: translateY(-50%) !important;
                    font-size: 8px !important;
                    padding: 1px 2px !important;
                    max-width: 35px !important;
                    width: auto !important;
                    height: auto !important;
                    white-space: nowrap !important;
                    overflow: hidden !important;
                    text-overflow: ellipsis !important;
                    box-sizing: border-box !important;
                }
            }

            /* 470像素以下优化 - 防止搜索中指示器超出搜索框 */
            @media screen and (max-width: 470px) {
                #search-loading {
                    position: absolute !important;
                    right: 8px !important;
                    top: 35% !important;
                    transform: translateY(-50%) !important;
                    font-size: 7px !important;
                    padding: 1px 2px !important;
                    max-width: 30px !important;
                    width: auto !important;
                    height: auto !important;
                    white-space: nowrap !important;
                    overflow: hidden !important;
                    text-overflow: ellipsis !important;
                    box-sizing: border-box !important;
                }

                /* 如果空间太小,只显示点号 */
                #search-loading i {
                    font-style: normal !important;
                }
            }

            /* 极限窄屏幕下的搜索中指示器优化 */
            @media screen and (max-width: 400px) {
                #search-loading {
                    position: absolute !important;
                    right: 6px !important;
                    top: 35% !important;
                    transform: translateY(-50%) !important;
                    font-size: 6px !important;
                    padding: 1px !important;
                    max-width: 25px !important;
                    width: auto !important;
                    height: auto !important;
                    white-space: nowrap !important;
                    overflow: hidden !important;
                    text-overflow: ellipsis !important;
                    box-sizing: border-box !important;
                }

                /* 极限窄屏幕下简化文本 */
                #search-loading i::after {
                    content: "..." !important;
                }

                #search-loading i {
                    font-size: 0 !important;
                }
            }
        `;
        document.head.appendChild(style);
    }


    // 显示搜索结果的函数 - 终极版本,彻底解决空白问题
    function displaySearchResults(results, container) {

        // 隐藏搜索中指示器
        setSearchLoading(false);

        // 使用DocumentFragment和createElement优化DOM创建
        const fragment = document.createDocumentFragment();

        // 显示全部结果,滚动在容器内进行
        const doubanResults = results.filter(r => r.source === '豆瓣');
        const tmdbResults = results.filter(r => r.source === 'TMDB');
        const orderedResults = [...doubanResults, ...tmdbResults];
        lastSearchResults = orderedResults;

        if (results.length === 0) {
            const emptyDiv = document.createElement('div');
            emptyDiv.style.cssText = 'padding:12px; color:#6b7280; text-align:center; background:#f9fafb; border-radius:6px; margin:4px;';
            emptyDiv.textContent = '未找到结果,请尝试其他关键词';
            fragment.appendChild(emptyDiv);
        } else {
            const makeGroup = (titleText, list, offsetBase) => {
                const title = document.createElement('div');
                // 简单分组:仅标题 + 细分隔线,不使用背景块
                title.style.cssText = 'margin:8px 4px 4px; padding:0 2px 4px; font-size:12px; color:#6b7280; font-weight:600; border-bottom:1px dashed #e5e7eb;';
                title.textContent = titleText;
                fragment.appendChild(title);
                const box = document.createElement('div');
                box.className = 'results-container';
                list.forEach((item, idx) => {
                    const searchItem = createSearchResultItem(item, offsetBase + idx);
                    box.appendChild(searchItem);
                });
                fragment.appendChild(box);
                return offsetBase + list.length;
            };
            let offset = 0;
            if (doubanResults.length) offset = makeGroup('豆瓣', doubanResults, offset);
            if (tmdbResults.length) offset = makeGroup('TMDB', tmdbResults, offset);
        }

        // 先隐藏容器,避免显示空白
        container.style.display = 'none';
        container.style.visibility = 'hidden';
        container.style.opacity = '0';

        // 一次性设置内容,减少重绘
        container.innerHTML = '';
        container.appendChild(fragment);

        // 设置内嵌显示状态
        container.style.setProperty('display', 'block', 'important');
        container.style.setProperty('visibility', 'visible', 'important');
        container.style.setProperty('opacity', '1', 'important');
        container.style.setProperty('position', 'relative', 'important');
        container.style.setProperty('z-index', '1', 'important');

        // 调用统一的显示函数,确保控制面板自动展开和动画效果
        showSearchResults();

        // 将高度锁定在约6条的高度,可滚动查看更多
        adjustSearchResultsHeightToSix(container);

        // 延迟加载豆瓣图片,避免阻塞显示框动画
        if (orderedResults.length > 0) {
            // 立即设置懒加载(不再延迟与替换容器,避免首屏转圈)
            setupLazyImageLoading(orderedResults, container);
        }
    }

    // 创建单个搜索结果项的优化函数
    function createSearchResultItem(item, index) {
        const resultItem = document.createElement('div');
        resultItem.className = 'search-item';
        resultItem.setAttribute('data-url', item.url || '');
        resultItem.setAttribute('data-type', item.type || '');
        resultItem.setAttribute('data-index', index);

        const isDouban = item.source === '豆瓣';
        const isTMDB = item.source === 'TMDB';
        const bgColor = isDouban ? '#eff6ff' : isTMDB ? '#e0f2fe' : '';

        resultItem.style.cssText = `padding:6px; cursor:pointer; border-bottom:1px solid #e5e7eb; display:flex; align-items:center; gap:6px; background:${bgColor};`;

        // 创建海报占位符
        const posterDiv = document.createElement('div');
        posterDiv.className = 'poster-placeholder';
        posterDiv.style.cssText = 'width:36px; height:54px; background:#f3f4f6; border-radius:3px; display:flex; align-items:center; justify-content:center; color:#9ca3af; transition: all 0.2s ease;';

        // 处理图片
        if (item.poster) {
            let imageUrl = item.poster;
            if (imageUrl.includes('doubanio.com') && !imageUrl.includes('https:')) {
                imageUrl = 'https:' + imageUrl;
            }

            if (imageUrl.includes('doubanio.com')) {
                // 豆瓣图片:显示加载中图标
                const spinner = document.createElement('i');
                spinner.className = 'fa fa-spinner fa-spin';
                spinner.style.cssText = 'font-size:14px; color:#f59e0b;';
                posterDiv.appendChild(spinner);
            } else {
                // 其他图片:直接显示
                const img = document.createElement('img');
                img.src = imageUrl;
                img.alt = item.title;
                img.style.cssText = 'width:36px; height:54px; object-fit:cover; border-radius:3px;';
                img.setAttribute('referrerpolicy', 'no-referrer');
                img.onerror = function() {
                    this.style.display = 'none';
                    const fallback = document.createElement('i');
                    fallback.className = 'fa fa-film';
                    fallback.style.cssText = 'font-size:14px;';
                    posterDiv.appendChild(fallback);
                };
                img.onload = () => {}; // 图片加载成功
                posterDiv.appendChild(img);
            }
        } else {
            const fallback = document.createElement('i');
            fallback.className = 'fa fa-film';
            fallback.style.cssText = 'font-size:14px;';
            posterDiv.appendChild(fallback);
        }

        // 创建内容区域
        const contentDiv = document.createElement('div');

        const title = document.createElement('strong');
        title.textContent = item.title;
        title.style.cssText = 'color:#374151; font-size:12px; line-height:1.3; transition: all 0.2s ease;';

        const meta = document.createElement('div');
        meta.textContent = `${item.type} • ${item.year} • ${item.source}`;
        meta.style.cssText = 'color:#6b7280; font-size:11px; margin-top:2px; transition: all 0.2s ease;';

        contentDiv.appendChild(title);
        contentDiv.appendChild(meta);

        resultItem.appendChild(posterDiv);
        resultItem.appendChild(contentDiv);

        return resultItem;
    }

    // 分批加载豆瓣图片,避免同时发起过多请求
    function loadDoubanImagesBatch(results, container) {
        const doubanItems = results
            .map((item, index) => ({ item, index }))
            .filter(({ item }) => item.poster && item.poster.includes('doubanio.com'));

        if (doubanItems.length === 0) return;

        // 分批加载(每批2个),首屏更快
        const batchSize = 2;
        let currentBatch = 0;

        function loadNextBatch() {
            const startIndex = currentBatch * batchSize;
            const endIndex = Math.min(startIndex + batchSize, doubanItems.length);
            const batch = doubanItems.slice(startIndex, endIndex);

            batch.forEach(({ item, index }) => {
                loadSingleDoubanImage(item, index, container);
            });

            currentBatch++;

            // 如果还有更多批次,延迟加载下一批(加入抖动,避免固定间隔触发风控)
            if (endIndex < doubanItems.length) {
                const jitter = 350 + Math.floor(Math.random()*250);
                setTimeout(loadNextBatch, jitter);
            }
        }

        loadNextBatch();
    }

    // 加载单个豆瓣图片
    function loadSingleDoubanImage(item, index, container) {
        const searchItem = container.querySelector(`[data-index="${index}"]`);
        if (!searchItem) return;

        const placeholder = searchItem.querySelector('.poster-placeholder');
        if (!placeholder) return;

        let imageUrl = item.poster;
        if (!imageUrl.includes('https:')) {
            imageUrl = 'https:' + imageUrl;
        }
        // 先尝试直链缩略图,失败再退到带Referer下载和条目页
        const tryVariants = async () => {
            let thumb = imageUrl;
            try { thumb = toDoubanThumb(imageUrl); } catch(_) {}
            // 先快速插入直链缩略
            try {
                const fastImg = document.createElement('img');
                fastImg.src = thumb;
                fastImg.style.cssText = 'width:36px; height:54px; object-fit:cover; border-radius:3px;';
                fastImg.alt = item.title;
                fastImg.referrerPolicy = 'no-referrer';
                fastImg.onerror = () => fallbackFetch();
                placeholder.innerHTML = '';
                placeholder.appendChild(fastImg);
            } catch(_) {}

            const fallbackFetch = async () => {
                try {
                    const res = await doubanRequest({ method:'GET', url: thumb, headers:{ 'Referer':'https://movie.douban.com/' }, responseType:'blob', timeout: 6500 });
                    const blob = res.response;
                    const hdr = (res.responseHeaders||'').toLowerCase();
                    const invalid = !blob || (blob.size && blob.size < 1500) || hdr.includes('text/html');
                    if (!invalid) {
                        const du = URL.createObjectURL(blob);
                        placeholder.innerHTML = `<img src="${du}" style="width:36px; height:54px; object-fit:cover; border-radius:3px;" alt="${item.title}">`;
                        return;
                    }
                } catch(_) {}
                try {
                    const real = await tryResolvePosterFromSubject(item.url);
                    if (real) {
                        const du = await getFallbackImageDataURL(real);
                        if (du && !/picsum\.photos\/.+error/.test(du)) {
                            placeholder.innerHTML = `<img src="${du}" style="width:36px; height:54px; object-fit:cover; border-radius:3px;" alt="${item.title}">`;
                            return;
                        }
                    }
                } catch(_) {}
                placeholder.innerHTML = '<i class="fa fa-film" style="font-size:14px; color:#9ca3af;"></i>';
            };

            // 保险:2.2s内仍未替换成功,主动触发一次fallback
            setTimeout(()=>{
                const im = placeholder.querySelector('img');
                if (!im || !im.complete) fallbackFetch();
            }, 2200);
        };
        setTimeout(tryVariants, 80 + Math.floor(Math.random()*180));
    }

    // 从豆瓣条目页解析海报URL(用于搜索列表占位图“new.gif”情况)
    function tryResolvePosterFromSubject(subjectUrl) {
        return new Promise((resolve) => {
            if (!subjectUrl) { resolve(''); return; }
            setTimeout(() =>
                doubanRequest({ method: 'GET', url: subjectUrl, headers: { 'Referer': 'https://movie.douban.com/' }, timeout: 5000 })
                    .then((res) => {
                        try {
                            const doc = new DOMParser().parseFromString(res.responseText, 'text/html');
                            const og = doc.querySelector('meta[property="og:image"]');
                            let u = (og && og.content) || '';
                            if (!u) {
                                const img = doc.querySelector('#mainpic img, .subject .pic img');
                                u = img ? (img.getAttribute('src') || '') : '';
                            }
                            if (u && u.startsWith('//')) u = 'https:' + u;
                            resolve(u);
                        } catch (_) { resolve(''); }
                    })
                    .catch(() => resolve('')),
                200 + Math.floor(Math.random() * 300)
            );
        });
    }

    // 设置懒加载图片,只加载可见区域的图片
    function setupLazyImageLoading(results, container) {
        const doubanItems = results
            .map((item, index) => ({ item, index }))
            .filter(({ item }) => item.poster && item.poster.includes('doubanio.com'));

        if (doubanItems.length === 0) return;

        // 创建IntersectionObserver进行懒加载
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const searchItem = entry.target;
                    const index = parseInt(searchItem.getAttribute('data-index'));
                    const item = results[index];

                    if (item && item.poster && item.poster.includes('doubanio.com')) {
                        loadSingleDoubanImage(item, index, container);
                        observer.unobserve(searchItem); // 加载后停止观察
                    }
                }
            });
        }, {
            root: container,
            rootMargin: '80px',
            threshold: 0.01
        });

        // 观察所有搜索结果项;若选不到节点,延迟一帧重试一次,避免组标题插入后索引错位
        const attachObservers = () => {
        doubanItems.forEach(({ index }) => {
            const searchItem = container.querySelector(`[data-index="${index}"]`);
            if (searchItem) {
                observer.observe(searchItem);
            }
        });
        };
        attachObservers();
        if (container.querySelectorAll('.search-item').length < doubanItems.length) {
            requestAnimationFrame(attachObservers);
        }
        // 兜底:立即加载首屏可见项,避免IntersectionObserver在嵌套滚动容器内不触发
        try {
            const rect = container.getBoundingClientRect();
            container.querySelectorAll('.search-item').forEach(item => {
                const r = item.getBoundingClientRect();
                if (r.top < rect.bottom + 40 && r.bottom > rect.top - 40) {
                    const idx = parseInt(item.getAttribute('data-index'));
                    const it = results[idx];
                    if (it && it.poster && it.poster.includes('doubanio.com')) {
                        loadSingleDoubanImage(it, idx, container);
                    }
                }
            });
        } catch (_) {}
    }

    // 图片懒加载设置函数 - 简化版
    function setupImageLazyLoading(results, container) {
        // 创建新的懒加载控制器
        if (window.currentLazyLoadController) {
            window.currentLazyLoadController.abort();
        }
        window.currentLazyLoadController = new AbortController();

        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const item = entry.target;
                    const index = parseInt(item.getAttribute('data-index'));
                    const resultItem = results[index];
                    if (resultItem && resultItem.poster && !window.currentLazyLoadController.signal.aborted) {
                        const placeholder = item.querySelector('.poster-placeholder');
                        if (placeholder) {
                            // 尝试加载图片

                            // 直接使用原始URL,避免复杂的转换
                            let imageUrl = resultItem.poster;

                            // 处理豆瓣图片URL
                            if (imageUrl.includes('doubanio.com') && !imageUrl.includes('https:')) {
                                imageUrl = 'https:' + imageUrl;
                            }

                            // 处理后的图片URL

                            // 立即显示图片,不等待加载完成(TMDB使用小缩略图w92 + 2x)
                            const tmdbThumb = toTMDBThumb(imageUrl);
                            const attr = tmdbThumb ? `src='${tmdbThumb.src}' srcset='${tmdbThumb.srcset}'` : `src='${imageUrl}'`;
                            placeholder.innerHTML = `
                                <img ${attr}
                                     style="width:36px; height:54px; object-fit:cover; border-radius:3px; background:#f3f4f6;"
                                     alt='${resultItem.title}'
                                     loading='lazy'
                                     onerror="this.style.display='none'; this.parentElement.innerHTML='<i class=\\"fa fa-film\\" style=\\"font-size:14px; color:#9ca3af;\\"></i>';"
                                     onload=''>
                            `;
                        }
                    }
                    observer.unobserve(item);
                }
            });
        }, { rootMargin: '0px 0px 100px 0px' });

        // 观察所有搜索项
        container.querySelectorAll('.search-item').forEach(item => {
            observer.observe(item);
        });
    }

    function searchDouban(query) {
        // 检查缓存
        const cacheKey = `douban_${query}`;
        const cached = searchCache.get(cacheKey);
        if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
            // 使用豆瓣搜索缓存
            return Promise.resolve(cached.data);
        }

        return new Promise((resolve) => {
            // 三通道:suggest(快)+ HTML(全)+ Rexxar(稳)并行合并
            const suggestP = searchDoubanSuggest(query).catch(() => []);
            const rexxarP = searchDoubanRexxar(query).catch(() => []);
            const url = `https://search.douban.com/movie/subject_search?search_text=${encodeURIComponent(query)}&cat=1002`;
            doubanRequest({ method: 'GET', url: url, headers: { ...COMMON_HEADERS, 'Host': 'search.douban.com', 'Sec-Fetch-Dest': 'document' }, timeout: 3000 })
                .then((res) => {
                    try {
                        if (res.status !== 200) throw new Error('bad-status');
                        const html = res.responseText;
                        const dataMatch = html.match(/window\.__DATA__\s*=\s*({.*?});/s);
                        if (!dataMatch || !dataMatch[1]) throw new Error('parse-fail');
                        const cleanData = dataMatch[1].replace(/\\x([0-9A-Fa-f]{2})/g, (match, hex) => String.fromCharCode(parseInt(hex, 16)));
                        const doubanData = JSON.parse(cleanData);
                        const items = safeGet(doubanData, 'items', []);
                        let results = items.map(item => ({
                            title: safeGet(item, 'title', '未知作品'),
                            type: safeGet(item, 'labels', []).some(l => l.text === '剧集') ? '电视剧' : '电影',
                            year: safeGet(item, 'title', '').match(/\((\d{4})\)/)?.[1] || '未知',
                            source: '豆瓣',
                            id: safeGet(item, 'id', ''),
                            url: safeGet(item, 'url', ''),
                            poster: safeGet(item, 'cover_url', '')
                        })).filter(item => item.url);
                        if (!results.length) {
                            return Promise.all([suggestP, rexxarP]).then(([sug, rex]) => {
                                const merged = [...(Array.isArray(sug)?sug:[]), ...(Array.isArray(rex)?rex:[])].filter((it,idx,arr)=> idx===arr.findIndex(t=>t.title===it.title && t.year===it.year));
                            searchCache.set(cacheKey, { data: merged, timestamp: Date.now() });
                            resolve(merged);
                            });
                        }
                        return Promise.all([suggestP, rexxarP]).then(([sug, rex]) => {
                        const merged = [...results, ...(Array.isArray(sug)?sug:[]), ...(Array.isArray(rex)?rex:[])].filter((it,idx,arr)=> idx===arr.findIndex(t=> (t.title===it.title || normalizeTextForCompare(t.title)===normalizeTextForCompare(it.title)) && t.year===it.year));
                            searchCache.set(cacheKey, { data: merged, timestamp: Date.now() });
                            resolve(merged);
                        }).catch(() => { searchCache.set(cacheKey, { data: results, timestamp: Date.now() }); resolve(results); });
                    } catch (e) {
                        Promise.all([suggestP, rexxarP]).then(([sug, rex]) => {
                            const merged = [...(Array.isArray(sug)?sug:[]), ...(Array.isArray(rex)?rex:[])].filter((it,idx,arr)=> idx===arr.findIndex(t=> (t.title===it.title || normalizeTextForCompare(t.title)===normalizeTextForCompare(it.title)) && t.year===it.year));
                            searchCache.set(cacheKey, { data: merged, timestamp: Date.now() });
                            resolve(merged);
                        }).catch(() => resolve([]));
                    }
                })
                .catch(() => {
                    Promise.all([suggestP, rexxarP]).then(([sug, rex]) => {
                        const merged = [...(Array.isArray(sug)?sug:[]), ...(Array.isArray(rex)?rex:[])].filter((it,idx,arr)=> idx===arr.findIndex(t=> (t.title===it.title || normalizeTextForCompare(t.title)===normalizeTextForCompare(it.title)) && t.year===it.year));
                        searchCache.set(cacheKey, { data: merged, timestamp: Date.now() });
                        resolve(merged);
                    }).catch(() => resolve([]));
            });
        });
    }

    // Rexxar 移动端搜索作为补充,提升 AI 面板豆瓣覆盖度
    function searchDoubanRexxar(query) {
        return new Promise((resolve) => {
            const url = `https://m.douban.com/rexxar/api/v2/search?q=${encodeURIComponent(query)}&start=0&count=60&cat=1002`;
            doubanRequest({ method: 'GET', url, headers: { ...COMMON_HEADERS, 'Host': 'm.douban.com', 'Referer': `https://m.douban.com/search/?q=${encodeURIComponent(query)}`, 'X-Requested-With': 'XMLHttpRequest' }, timeout: 4000 })
                .then((res) => {
                    try {
                        const data = JSON.parse(res.responseText || '{}');
                        const items = data.subjects || data.items || [];
                        const list = items.map(it => {
                            const id = it.id || (it.target && it.target.id);
                            const title = it.title || (it.target && it.target.title) || (it.display && it.display.split('\n')[0]) || '未知作品';
                            const year = (it.year || (it.card_subtitle && (it.card_subtitle.match(/(\d{4})/)||[])[1])) || '未知';
                            const poster = (it.cover_url || (it.pic && it.pic.normal)) || '';
                            return id ? { title, type: '电影', year, source: '豆瓣', id, url: `https://movie.douban.com/subject/${id}/`, poster } : null;
                        }).filter(Boolean);
                        resolve(list);
                    } catch (_) { resolve([]); }
                })
                .catch(() => resolve([]));
        });
    }

    // 豆瓣搜索回退:使用 subject_suggest 接口(JSON,速度更快,适合首次搜索)
    function searchDoubanSuggest(query) {
        return new Promise((resolve) => {
            const url = `https://movie.douban.com/j/subject_suggest?q=${encodeURIComponent(query)}`;
            doubanRequest({ method: 'GET', url: url, headers: { ...COMMON_HEADERS, 'Host': 'movie.douban.com', 'X-Requested-With': 'XMLHttpRequest' }, timeout: 4000 })
                .then((res) => {
                    try {
                        if (res.status !== 200) { resolve([]); return; }
                        const arr = JSON.parse(res.responseText);
                        const results = (Array.isArray(arr) ? arr : []).map(item => ({
                            title: item.title || item.sub_title || '未知作品',
                            type: item.type === 'movie' ? '电影' : (item.type === 'tv' ? '电视剧' : '电影'),
                            year: item.year || '未知',
                            source: '豆瓣',
                            id: item.id || '',
                            url: item.id ? `https://movie.douban.com/subject/${item.id}/` : (item.url || ''),
                            poster: item.cover_url || ''
                        })).filter(it => it.url);
                        resolve(results);
                    } catch (e) { resolve([]); }
                })
                .catch(() => resolve([]));
        });
    }

    function normalizeTextForCompare(text) {
        try {
            let s = (text || '').toString().toLowerCase();
            // 全角转半角
            s = s.replace(/[\uFF01-\uFF5E]/g, ch => String.fromCharCode(ch.charCodeAt(0) - 0xFEE0));
            // 去除符号与空白
            s = s.replace(/[\p{P}\p{S}\s]+/gu, '');
            return s;
        } catch (_) { return (text || '').toString().toLowerCase(); }
    }

    function parseQueryParts(q) {
        const m = (q || '').match(/(.+?)(?:[\((\[]?(\d{4})[\))\]]?)?$/);
        return { title: (m && m[1] ? m[1] : q).trim(), year: (m && m[2]) ? m[2] : '' };
    }

    function rankAndDedupResults(results, query) {
        const { title, year } = parseQueryParts(query);
        const normQ = normalizeTextForCompare(title);
        const targetYear = parseInt(year || '0', 10);
        const seen = new Set();
        const ranked = (results || []).map(it => {
            const t = (it.title || '').toString();
            const y = parseInt((it.year || '').toString().slice(0,4) || '0', 10);
            const normT = normalizeTextForCompare(t);
            const titleScore = normT.includes(normQ) ? 5 : 0;
            const yearScore = (targetYear && y) ? (5 - Math.min(5, Math.abs(targetYear - y))) : 0;
            const sourceScore = it.source === '豆瓣' ? 2 : 1;
            return { ...it, _score: titleScore + yearScore + sourceScore };
        }).sort((a,b)=> b._score - a._score);
        const dedup = [];
        for (const it of ranked) {
            const key = `${normalizeTextForCompare(it.title)}_${(it.year||'').slice(0,4)}`;
            if (!seen.has(key)) { seen.add(key); dedup.push(it); }
        }
        return dedup;
    }

    function searchTMDB(query) {
        // 检查缓存
        const cacheKey = `tmdb_${query}`;
        const cached = searchCache.get(cacheKey);
        if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
            console.log('使用TMDB搜索缓存');
            return Promise.resolve(cached.data);
        }

        return new Promise((resolve) => {
            const config = getConfig();
            const { title, year } = parseQueryParts(query);
            const langs = ['zh-CN','en-US'];
            const reqs = langs.map(lang => `${config.TMDB.BASE_URL}/search/multi?api_key=${config.TMDB.API_KEY}&query=${encodeURIComponent(title)}&language=${lang}${year?`&year=${year}`:''}`);
            const keywordUrl = `${config.TMDB.BASE_URL}/search/keyword?api_key=${config.TMDB.API_KEY}&query=${encodeURIComponent(title)}`;

            const send = (url) => new Promise(resv => {
            GM_xmlhttpRequest({
                method: 'GET',
                    url,
                headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                    timeout: 5000,
                    onload: r => { try { resv(JSON.parse(r.responseText)); } catch(_) { resv({}); } },
                    onerror: () => resv({}),
                    ontimeout: () => resv({})
                });
            });

            Promise.all([ ...reqs.map(send), send(keywordUrl) ]).then(async (arr) => {
                try {
                    const merge = [];
                    const pushItem = (item) => {
                        if (!item || !item.id) return;
                        const media_type = item.media_type || (item.name ? 'tv' : 'movie');
                        const url = media_type === 'movie' ? `https://www.themoviedb.org/movie/${item.id}` : `https://www.themoviedb.org/tv/${item.id}`;
                        merge.push({
                            title: item.title || item.name || '未知作品',
                            type: media_type === 'movie' ? '电影' : media_type === 'tv' ? '电视剧' : '未知',
                            year: item.release_date?.split('-')[0] || item.first_air_date?.split('-')[0] || '未知',
                            source: 'TMDB',
                            id: item.id,
                            url,
                            poster: item.poster_path ? `${config.TMDB.IMAGE_BASE_URL}${config.TMDB.LIST_POSTER_SIZE}/${item.poster_path}` : ''
                        });
                    };

                    // 多语言 multi 结果
                    for (const a of arr.slice(0, reqs.length)) {
                        const results = safeGet(a, 'results', []);
                        results.forEach(pushItem);
                    }

                    // 关键词 → 再拉一轮 movie/tv 搜索(更全)
                    const kw = safeGet(arr[reqs.length], 'results', []);
                    const kwId = (kw && kw[0] && kw[0].id) ? kw[0].id : null;
                    if (kwId) {
                        const byKw = await Promise.all([
                            send(`${config.TMDB.BASE_URL}/discover/movie?api_key=${config.TMDB.API_KEY}&with_keywords=${kwId}&language=zh-CN`),
                            send(`${config.TMDB.BASE_URL}/discover/tv?api_key=${config.TMDB.API_KEY}&with_keywords=${kwId}&language=zh-CN`)
                        ]);
                        (safeGet(byKw[0],'results',[])||[]).forEach(pushItem);
                        (safeGet(byKw[1],'results',[])||[]).forEach(pushItem);
                    }

                    const ranked = rankAndDedupResults(merge, query).slice(0, 30);
                    searchCache.set(cacheKey, { data: ranked, timestamp: Date.now() });
                    console.log('TMDB合并结果:', ranked.length);
                    resolve(ranked);
                } catch (e) { console.error(e); resolve([]); }
            });
        });
    }
    // 搜索结果交互
    function setupSearchInteractions() {
        const searchInput = document.getElementById('search-movie');
        const resultsContainer = document.getElementById('search-results');
        const loadingIndicator = document.getElementById('search-loading');
        const mediaUrlInput = document.getElementById('media-url');
        let lazyLoadController = new AbortController();

        if (!searchInput || !resultsContainer || !loadingIndicator || !mediaUrlInput) return;

        searchInput.addEventListener('input', debounce(async function () {
            const query = this.value.trim();
            lastSearchQuery = query;

            if (!query) {
                hideSearchResults();
                lastSearchResults = [];
                abortLazyLoad();
                return;
            }

            // 立即显示搜索中指示器
            setSearchLoading(true);
            console.log('开始搜索:', query);

            // 重置搜索结果状态,确保第二次搜索能正常显示
            lastSearchResults = [];
            lastSearchQuery = query;

            // 搜索开始时只淡出,不折叠,待结果到达后再展开
            resultsContainer.classList.remove('show');
            resultsContainer.style.visibility = 'hidden';
            resultsContainer.style.opacity = '0';
            abortLazyLoad();
            lazyLoadController = new AbortController();
            try {
                // 优先搜索豆瓣(通常更快),然后搜索TMDB
                const doubanPromise = searchDouban(query).catch(e => {
                    console.warn('豆瓣搜索失败:', e);
                    return [];
                });

                const tmdbPromise = searchTMDB(query).catch(e => {
                    console.warn('TMDB搜索失败:', e);
                    return [];
                });

                // 等待所有搜索结果完成,避免显示旧内容
                const [doubanResult, tmdbResult] = await Promise.all([
                    doubanPromise,
                    tmdbPromise
                ]);

                setSearchLoading(false);

                // 合并、排序、去重,并扩大上限到60条
                const uniqueResults = rankAndDedupResults([...(doubanResult||[]), ...(tmdbResult||[])], query).slice(0, 60);

                // 确保显示最新搜索结果
                displaySearchResults(uniqueResults, resultsContainer);
            } catch (e) {
                console.error('搜索出错:', e);
                setSearchLoading(false);
                resultsContainer.innerHTML = '<div style="padding:12px; color:#ef4444; text-align:center; background:#fef2f2; border-radius:6px; margin:4px; border:1px solid #fecaca;">搜索出错,请检查网络连接后重试</div>';
                // 使用统一的动画函数
                animateShow(resultsContainer);
            }
        }, 500));

        function abortLazyLoad() {
            if (lazyLoadController) {
                lazyLoadController.abort();
            }
        }

        // 不再因输入框失焦自动隐藏结果,交由外部点击空白处或主动选择项来隐藏

        searchInput.addEventListener('focus', function () {
            const query = this.value.trim();
            if (query && lastSearchResults.length > 0) {
                // 如果有搜索结果,使用统一的显示函数
                showSearchResults();
            } else if (query && (lastSearchResults.length === 0 || lastSearchQuery !== query)) {
                // 如果有查询但没有结果或查询不同,触发搜索
                const inputEvent = new Event('input', { bubbles: true });
                this.dispatchEvent(inputEvent);
            }
        });

        resultsContainer.addEventListener('click', async function (event) {
            // 确保容器有内容且可见时才响应点击
            if (resultsContainer.innerHTML.trim() === '' ||
                resultsContainer.style.display === 'none' ||
                resultsContainer.style.visibility === 'hidden') {
                return;
            }

            const targetItem = event.target.closest('.search-item');
            if (targetItem) {
                const url = targetItem.getAttribute('data-url');
                const type = targetItem.getAttribute('data-type');
                const title = targetItem.querySelector('strong').textContent;
                if (url) {
                    // 添加加载状态
                    targetItem.classList.add('loading');

                    mediaUrlInput.value = url;
                    hideSearchResults();
                    searchInput.blur();
                    const fetchBtn = document.getElementById('fetch-btn');
                    if (fetchBtn) fetchBtn.classList.remove('active'); // 使用active类而不是display属性
                    showStatus(`正在加载【${type}】${title}的信息...`, false);
                    try {
                        currentMovieInfo = await getBasicInfo(url);
                        currentComments = await getHotComments(url);
                        showStatus('信息加载完成,请选择海报和剧照', false);
                        await showImageSelection(currentMovieInfo);
                    } catch (err) {
                        showStatus(`加载失败:${err.message}`, true);
                        if (mediaUrlInput.value.trim() && fetchBtn) {
                            fetchBtn.classList.add('active'); // 使用active类而不是display属性
                        }
                    }
                }
            }
        });

        // 点击面板外部区域才隐藏;点击面板内部的其它控件不自动隐藏
        document.addEventListener('click', function (event) {
            const panel = document.getElementById('douban-tmdb-panel');
            if (panel && panel.contains(event.target)) return; // 面板内部不隐藏
            if (!searchInput.contains(event.target) && !resultsContainer.contains(event.target)) {
                        hideSearchResults();
            }
        });

        // 智能保持搜索结果框显示的函数
        function forceKeepSearchResultsVisible() {
            const query = searchInput.value.trim();
            // 只有在有查询内容、有搜索结果、且搜索框有焦点时才显示
            if (query && lastSearchResults.length > 0 &&
                (document.activeElement === searchInput || resultsContainer.style.display === 'block')) {
                showSearchResults();

                // 搜索结果已内嵌到控制面板中,无需位置调整
            }
        }

        // 专门处理窗口缩放时的显示逻辑 - 只在搜索框有焦点时保持显示
        function handleResizeDisplay() {
            const query = searchInput.value.trim();
            const resultsContainer = document.getElementById('search-results');
            const loadingIndicator = document.getElementById('search-loading');

            // 强制保持搜索中指示器显示
            if (loadingIndicator && (loadingIndicator.style.display === 'block' || loadingIndicator.style.display === '')) {
                resetSearchLoadingPosition();
            }

            // 只在搜索框有焦点时保持搜索结果框显示
            if (query && lastSearchResults.length > 0 && resultsContainer && document.activeElement === searchInput) {
                // 使用强制样式设置,确保不会消失
                resultsContainer.style.setProperty('display', 'block', 'important');
                resultsContainer.style.setProperty('visibility', 'visible', 'important');
                resultsContainer.style.setProperty('opacity', '1', 'important');
                resultsContainer.style.setProperty('z-index', '800', 'important');
                resultsContainer.classList.add('show');

                // 搜索结果已内嵌到控制面板中,无需位置调整
            }
        }

        // 强制保持搜索结果框显示的函数 - 修复版本
        function forceKeepSearchResultsVisible() {
            const query = searchInput.value.trim();
            const resultsContainer = document.getElementById('search-results');

            // 只有在有查询内容、有搜索结果、且搜索框有焦点时才保持显示
            if (query && lastSearchResults.length > 0 && resultsContainer &&
                (document.activeElement === searchInput || resultsContainer.style.display === 'block')) {
                // 强制保持显示状态
                if (resultsContainer.style.display !== 'block') {
                    resultsContainer.style.setProperty('display', 'block', 'important');
                }
                if (resultsContainer.style.visibility !== 'visible') {
                    resultsContainer.style.setProperty('visibility', 'visible', 'important');
                }
                if (resultsContainer.style.opacity !== '1') {
                    resultsContainer.style.setProperty('opacity', '1', 'important');
                }
            } else if (!query || lastSearchResults.length === 0) {
                // 如果没有查询内容或没有搜索结果,确保隐藏
                if (resultsContainer && resultsContainer.style.display !== 'none') {
                    resultsContainer.style.setProperty('display', 'none', 'important');
                    resultsContainer.style.setProperty('visibility', 'hidden', 'important');
                    resultsContainer.style.setProperty('opacity', '0', 'important');
                }
            }
        }

        // 移除定期检查,避免阻止正常的失焦隐藏
        // setInterval(forceKeepSearchResultsVisible, 1000);

        // 智能检查机制:只在窗口大小变化时触发,避免阻止失焦隐藏
        let lastWindowSize = { width: window.innerWidth, height: window.innerHeight };
        let resizeCheckInterval = setInterval(() => {
            const currentSize = { width: window.innerWidth, height: window.innerHeight };
            // 只有在窗口大小真正发生变化时才检查显示
            if (currentSize.width !== lastWindowSize.width || currentSize.height !== lastWindowSize.height) {
                lastWindowSize = currentSize;
                handleResizeDisplay();
            }
        }, 500); // 每500ms检查一次窗口大小变化,减少性能影响

        // 超级窄窗口过渡效果增强
        let resizeTimeout;
        let isUltraNarrow = false;

        function handleUltraNarrowTransition() {
            const panel = document.getElementById('douban-tmdb-panel');
            if (!panel) return;

            const windowWidth = window.innerWidth;
            const wasUltraNarrow = isUltraNarrow;
            isUltraNarrow = windowWidth <= 10;

            if (isUltraNarrow && !wasUltraNarrow) {
                // 进入超级窄模式
                panel.style.transition = 'all 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
                panel.style.transform = 'scale(0.1)';
                panel.style.transformOrigin = 'top left';
                panel.style.overflow = 'hidden';

                // 添加特殊类名用于CSS选择器
                panel.classList.add('ultra-narrow');

                // 显示极简指示器
                const indicator = document.createElement('div');
                indicator.id = 'ultra-narrow-indicator';
                indicator.style.cssText = `
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 10px;
                    height: 10px;
                    background: linear-gradient(135deg, #ec4899 0%, #be185d 100%);
                    color: white;
                    font-size: 8px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border-radius: 2px;
                    z-index: 1001; /* 搜索中指示器 - 最高层级 */
                    transition: all 0.3s ease;
                `;
                indicator.textContent = '🎬';
                document.body.appendChild(indicator);

            } else if (!isUltraNarrow && wasUltraNarrow) {
                // 退出超级窄模式
                panel.style.transition = 'all 0.5s cubic-bezier(0.4, 0, 0.2, 1)';
                panel.style.transform = 'scale(1)';
                panel.style.transformOrigin = 'top left';
                panel.style.overflow = 'visible';

                // 移除特殊类名
                panel.classList.remove('ultra-narrow');

                // 移除极简指示器
                const indicator = document.getElementById('ultra-narrow-indicator');
                if (indicator) {
                    indicator.remove();
                }
            }
        }

        // 监听窗口大小变化,同时处理搜索结果框和超级窄窗口过渡
        window.addEventListener('resize', function() {
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(() => {
                // 处理搜索结果框位置 - 只在有焦点时保持显示
                const searchInput = document.getElementById('search-movie');
                const resultsContainer = document.getElementById('search-results');
                if (searchInput && resultsContainer && document.activeElement === searchInput) {
                    const query = searchInput.value.trim();
                    if (query && lastSearchResults.length > 0) {
                        showSearchResults();
                    }
                }
                // 处理窗口缩放时的显示
                handleResizeDisplay();
                // 处理超级窄窗口过渡
                handleUltraNarrowTransition();
                // 搜索中提示位置已在setSearchLoading中处理
            }, 50); // 统一延迟时间
        });

        // 初始化检查
        handleUltraNarrowTransition();

        // 初始化时搜索中提示位置将在需要时自动校准
    }

    // 影视信息提取(增强版)
    function getBasicInfo(url) {
        return new Promise((resolve, reject) => {
            // Douban API 回退:使用移动端 rexxar 接口规避“请证明你是人类”
            async function fetchDoubanDetailViaApi(id, isTv) {
                try {
                    const apiUrl = `https://m.douban.com/rexxar/api/v2/${isTv ? 'tv' : 'movie'}/${id}?for_mobile=1`;
                    const json = await new Promise((resv, rej)=>{
                        GM_xmlhttpRequest({
                            method: 'GET',
                            url: apiUrl,
                            headers: {
                                ...COMMON_HEADERS,
                                'Accept': 'application/json',
                                'X-Requested-With': 'XMLHttpRequest',
                                'Referer': `https://m.douban.com/${isTv ? 'tv' : 'movie'}/subject/${id}/`
                            },
                            timeout: 8000,
                            onload: (r)=>{ try { resv(JSON.parse(r.responseText)); } catch(e){ rej(e);} },
                            onerror: ()=>rej(new Error('豆瓣API请求失败')),
                            ontimeout: ()=>rej(new Error('豆瓣API请求超时'))
                        });
                    });
                    // 字段映射
                    const title = json.title || '';
                    const originalTitle = json.original_title || '';
                    const genreTags = (json.genres || []).slice(0, 8);
                    const year = (json.year || '').toString() || '未知';
                    const alsoKnown = (json.aka || []).join(' / ');
                    const director = (json.directors || []).map(d=>d.name).join(' / ') || '未知';
                    const writer = (json.writers || []).map(w=>w.name).join(' / ') || '未知';
                    const actor = (json.actors || []).map(a=>a.name).join(',') || '未知';
                    const region = (json.countries || []).join('、') || '未知';
                    const lang = (json.languages || []).join('、') || '未知';
                    const release = (json.pubdate || json.release_date || '') || (isTv ? '未知首播时间' : '未知上映时间');
                    const rating = (json.rating && (json.rating.value || json.rating.average)) ? (json.rating.value || json.rating.average).toFixed ? (json.rating.value || json.rating.average).toFixed(1) : (json.rating.value || json.rating.average) : '暂无';
                    const voteCount = (json.rating && (json.rating.count || json.rating.votes)) || '0';
                    const doubanId = id;
                    const imdbId = (json.imdb || (json.extra && json.extra.imdb)) || '暂无';
                    const runtime = (json.durations && json.durations[0]) || (json.duration ? `${json.duration}分钟` : (isTv ? '未知集数' : '未知片长'));
                    const intro = json.intro || json.card_subtitle || '';
                    return {
                        mediaType: isTv ? 'tv' : 'movie',
                        source: '豆瓣',
                        title, originalTitle, genreTags, year, alsoKnown, director, writer, actor,
                        region, release, lang, rating, voteCount, doubanId, imdbId, runtime,
                        intro, awards: [], posterUrls: [], stillUrls: [], url
                    };
                } catch (e) {
                    throw e;
                }
            }
            // 重试函数,带指数退避
            const retryRequest = async (requestFn, maxRetries = 2, delay = 1000) => {
                let lastError;
                for (let attempt = 0; attempt <= maxRetries; attempt++) {
                    try {
                        if (attempt > 0) {
                            await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, attempt - 1)));
                        }
                        return await requestFn();
                    } catch (error) {
                        lastError = error;
                        console.warn(`请求失败,尝试 ${attempt + 1}/${maxRetries + 1}:`, error);
                    }
                }
                throw lastError || new Error('所有重试均失败');
            };

            const urlObj = new URL(url);
            if (url.includes('douban.com')) {
                let isTv = url.includes('tv.douban.com');
                const headers = {
                    ...COMMON_HEADERS,
                    'Referer': 'https://movie.douban.com/',
                    'Host': urlObj.hostname,
                    'Sec-Fetch-Dest': 'document'
                };

                retryRequest(() => {
                    return new Promise((innerResolve, innerReject) => {
                        doubanRequest({
                            method: 'GET',
                            url: url,
                            headers: headers,
                            timeout: 10000
                        }).then(async (res) => {
                                try {
                                    // 若被重定向到登录(不可用)/检测页,或页面出现“请证明你是人类/嗯...”,则回退API
                                    if ((res.finalUrl && /\/accounts\.|\/j\/app\/user\/check/.test(res.finalUrl)) ||
                                        /请证明你是人类|你的访问豆瓣的方式有点像机器人|嗯\s*\.\.\./.test(res.responseText)) {
                                        const fallback = await (async ()=>{
                                            try {
                                                const list = await searchDoubanSuggest((currentMovieInfo && currentMovieInfo.title) || '')
                                                    .catch(()=>[]);
                                                return Array.isArray(list) && list.length ? list[0] : null;
                                            } catch(e){ return null; }
                                        })();
                                        if (fallback && (fallback.id || fallback.url)) {
                                            const id = fallback.id || (fallback.url.match(/subject\/(\d+)/)||[])[1];
                                            if (id) {
                                                try { const viaApi = await fetchDoubanDetailViaApi(id, isTv); innerResolve(viaApi); return; } catch(_){}
                                            }
                                            innerResolve({ mediaType: isTv ? 'tv' : 'movie', source: '豆瓣', title: fallback.title, originalTitle: '', genreTags: [], year: fallback.year || '未知', alsoKnown: '', director: '未知', writer: '未知', actor: '未知', region: '未知', release: '未知', lang: '', rating: '暂无', voteCount: '0', doubanId: id || '', imdbId: '暂无', runtime: isTv ? '未知集数' : '未知片长', intro: '', awards: [], posterUrls: [], stillUrls: [], url });
                                        } else {
                                            throw new Error('豆瓣需要登录(不可用),且回退失败');
                                        }
                                        return;
                                    }
                                    const doc = new DOMParser().parseFromString(res.responseText, 'text/html');
                                    const titleElem = doc.querySelector('h1 span[property="v:itemreviewed"], h1 span[itemprop="name"]');
                                    const title = titleElem ? titleElem.textContent.trim() : (isTv ? '未知电视剧' : '未知电影');
                                    const originalTitle = doc.querySelector('h1 .year')?.previousSibling?.textContent?.trim()?.replace(/\s+/g, ' ') || '';
                                    const genreTags = Array.from(doc.querySelectorAll('span[property="v:genre"]')).map(g => g.textContent.trim()).filter(Boolean);
                                    let year = '未知';
                                    const yearElem = doc.querySelector('span[property="v:initialReleaseDate"]');
                                    if (yearElem) {
                                        const yearMatch = yearElem.textContent.trim().match(/\d{4}/);
                                        year = yearMatch ? yearMatch[0] : '未知';
                                    }

                                    // 提取更多信息的函数
                                    const extractInfo = (label) => {
                                        const infoText = Array.from(doc.querySelectorAll('#info')).find(info =>
                                            info.textContent.includes(label)
                                        )?.textContent || '';
                                        const match = infoText.match(new RegExp(`${label}[::]\s*(.+?)\n`));
                                        return match ? match[1].replace(/\s+/g, ' ').trim() : '未知';
                                    };

                                    const alsoKnown = doc.querySelector('span[property="v:alternative"]')?.textContent.trim() || '';
                                    const director = Array.from(doc.querySelectorAll('a[rel="v:directedBy"]')).map(d => d.textContent.trim()).join(' / ') || '未知';
                                    const writer = extractInfo('编剧');
                                    const actor = Array.from(doc.querySelectorAll('a[rel="v:starring"]')).map(a => a.textContent.trim()).join(',') || '未知';
                                    const region = extractInfo('制片国家/地区');
                                    const lang = extractInfo('语言');
                                    const release = yearElem?.textContent.trim() || (isTv ? '未知首播时间' : '未知上映时间');
                                    const rating = doc.querySelector('strong[property="v:average"]')?.textContent || '暂无';
                                    const voteCount = doc.querySelector('span[property="v:votes"]')?.textContent || '0';
                                    const doubanId = url.match(/subject\/(\d+)/)?.[1] || '未知';
                                    const imdbId = doc.querySelector('a[href*="imdb.com/title/"]')?.href?.match(/tt\d+/)?.[0] || '暂无';
                                    const runtime = isTv
                                        ? doc.querySelector('span[property="v:episodeCount"]')
                                            ? `共${doc.querySelector('span[property="v:episodeCount"]').textContent}集`
                                            : '未知集数'
                                        : doc.querySelector('span[property="v:runtime"]')?.textContent.trim() || '未知片长';

                                    // 提取更完整的简介
                                    let intro = '';
                                    const summaryElem = doc.querySelector('span[property="v:summary"]');
                                    if (summaryElem) {
                                        intro = summaryElem.textContent.trim().replace(/\s+/g, ' ');
                                    }
                                    if (!intro) {
                                        // 尝试其他可能的简介位置
                                        const otherIntroElem = doc.querySelector('.all.hidden');
                                        if (otherIntroElem) {
                                            intro = otherIntroElem.textContent.trim().replace(/\s+/g, ' ');
                                        }
                                    }
                                    if (!intro) {
                                        intro = isTv ? '暂无电视剧简介' : '暂无电影简介';
                                    }

                                    // 尝试提取奖项信息
                                    let awards = [];
                                    const awardsElem = doc.querySelector('#celebrities');
                                    if (awardsElem && awardsElem.textContent.includes('获奖')) {
                                        const awardTexts = Array.from(awardsElem.querySelectorAll('.award')).map(a => a.textContent.trim());
                                        if (awardTexts.length > 0) {
                                            awards = awardTexts.slice(0, 3); // 最多取3个主要奖项
                                        }
                                    }

                                    innerResolve({
                                        mediaType: isTv ? 'tv' : 'movie',
                                        source: '豆瓣',
                                        title,
                                        originalTitle: originalTitle || '',
                                        genreTags,
                                        year,
                                        alsoKnown,
                                        director,
                                        writer,
                                        actor,
                                        region,
                                        release,
                                        lang,
                                        rating,
                                        voteCount,
                                        doubanId,
                                        imdbId,
                                        runtime,
                                        intro,
                                        awards,
                                        // 延迟加载:图片在选择面板内部异步加载,提升首屏弹出速度
                                        posterUrls: [],
                                        stillUrls: [],
                                        url // 保存原始URL用于后续加载更多
                                    });
                                } catch (e) {
                                    innerReject(new Error(`豆瓣解析失败:${e.message}`));
                                }
                        }).catch(() => innerReject(new Error('豆瓣请求失败')));
                    });
                }).then(result => resolve(result)).catch(error => reject(error));
            } else if (url.includes('themoviedb.org')) {
                const isMovie = url.includes('/movie/');
                const isTv = url.includes('/tv/');
                let mediaType = isMovie ? 'movie' : (isTv ? 'tv' : 'movie');
                const idMatch = url.match(/\/(movie|tv)\/(\d+)/);
                if (!idMatch) {
                    reject(new Error('TMDB链接格式错误(需包含/movie/或/tv/及数字ID)'));
                    return;
                }
                const [, type, id] = idMatch;
                mediaType = type;

                // 请求更多信息,包含额外数据
                const config = getConfig();
                const tmdbDetailUrl = `${config.TMDB.BASE_URL}/${mediaType}/${id}?api_key=${config.TMDB.API_KEY}&language=zh-CN&append_to_response=credits,keywords,release_dates,external_ids`;

                retryRequest(() => {
                    return new Promise((innerResolve, innerReject) => {
                        GM_xmlhttpRequest({
                            method: 'GET',
                            url: tmdbDetailUrl,
                            headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                            onload: async (res) => {
                                try {
                                    const data = JSON.parse(res.responseText);
                                    const title = mediaType === 'movie' ? data.title : data.name;
                                    const originalTitle = mediaType === 'movie' ? data.original_title : data.original_name;
                                    const genreTags = data.genres.map(g => g.name);
                                    const year = mediaType === 'movie'
                                        ? data.release_date?.split('-')[0]
                                        : data.first_air_date?.split('-')[0];
                                    const alsoKnown = data.also_known_as?.join(' / ') || '';
                                    const director = mediaType === 'movie'
                                        ? (data.credits?.crew?.filter(c => c.job === 'Director').map(d => d.name).join(' / ') || '未知')
                                        : (data.credits?.crew?.filter(c => c.job === 'Director' || c.job === 'Executive Producer').map(d => d.name).join(' / ') || '未知');
                                    const writer = data.credits?.crew?.filter(c => c.job === 'Writer' || c.job === 'Screenplay').map(w => w.name).join(' / ') || '未知';
                                    const actor = (data.credits?.cast || []).map(a => a.name).join(',') || '未知';
                                    const region = (data.production_countries || []).map(c => c.name).join('、') || '未知';
                                    const release = mediaType === 'movie' ? data.release_date : data.first_air_date;
                                    const lang = (data.spoken_languages || []).map(l => l.name).join('、') || '未知';
                                    const rating = data.vote_average ? data.vote_average.toFixed(1) : '暂无';
                                    const voteCount = data.vote_count || 0;
                                    const tmdbId = id;
                                    const imdbId = data.imdb_id || '暂无';
                                    const runtime = mediaType === 'movie'
                                        ? `${data.runtime}分钟`
                                        : `${data.number_of_episodes || '未知'}集(共${data.number_of_seasons || '未知'}季)`;
                                    const intro = data.overview || (mediaType === 'tv' ? '暂无电视剧简介' : '暂无电影简介');

                                    // 获取关键字
                                    const keywords = data.keywords?.keywords?.map(k => k.name).join('、') || '';

                                    // 获取预算和票房(电影)
                                    let budget = '未知';
                                    let revenue = '未知';
                                    if (mediaType === 'movie') {
                                        budget = data.budget > 0 ? `$${(data.budget / 1000000).toFixed(1)}M` : '未知';
                                        revenue = data.revenue > 0 ? `$${(data.revenue / 1000000).toFixed(1)}M` : '未知';
                                    }

                                    // 获取流媒体平台信息
                                    let streamingPlatforms = [];
                                    const watchProvidersUrl = `${config.TMDB.BASE_URL}/${mediaType}/${id}/watch/providers?api_key=${config.TMDB.API_KEY}`;
                                    try {
                                        const providersData = await new Promise(resolve => {
                                            GM_xmlhttpRequest({
                                                method: 'GET',
                                                url: watchProvidersUrl,
                                                headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                                                onload: (res) => resolve(JSON.parse(res.responseText)),
                                                onerror: () => resolve({}),
                                                ontimeout: () => resolve({})
                                            });
                                        });
                                        // 获取中国或美国的流媒体平台
                                        const watchProviders = providersData.results?.CN || providersData.results?.US || {};
                                        streamingPlatforms = [
                                            ...(watchProviders.flatrate || []).map(p => p.provider_name),
                                            ...(watchProviders.buy || []).map(p => p.provider_name)
                                        ].slice(0, 5); // 最多取5个平台
                                    } catch (e) {
                                        console.log('获取流媒体平台失败:', e);
                                    }

                                    // 初始加载海报和剧照
                                    posterPage = 1;
                                    let posterUrls = [];
                                    if (data.poster_path) {
                                        const postersUrl = `${config.TMDB.BASE_URL}/${mediaType}/${id}/images?api_key=${config.TMDB.API_KEY}&include_image_language=zh,en&image_type=poster&sort_by=primary`;
                                        try {
                                            const posterData = await new Promise(resolve => {
                                                GM_xmlhttpRequest({
                                                    method: 'GET',
                                                    url: postersUrl,
                                                    headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                                                    onload: (res) => resolve(JSON.parse(res.responseText)),
                                                    onerror: () => resolve({}),
                                                    ontimeout: () => resolve({})
                                                });
                                            });
                                            // 按第1页截取(5张)
                                            const pagePosters = safeGet(posterData, 'posters', [])
                                                .slice((posterPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, posterPage * config.TMDB.IMAGE_CANDIDATES_COUNT)
                                                .map(img => `${config.TMDB.IMAGE_BASE_URL}${config.TMDB.LIST_POSTER_SIZE}/${img.file_path}`)
                                                .filter(Boolean);
                                            posterUrls = pagePosters;
                                        } catch (e) {
                                            console.log('获取更多海报失败:', e);
                                        }
                                    }

                                    // 【统一逻辑】初始加载第1页剧照(5张)
                                    stillPage = 1;
                                    const stillUrls = await retryRequest(() => getTMDBStillsList(mediaType, id));

                                    innerResolve({
                                        mediaType,
                                        source: 'TMDB',
                                        title,
                                        originalTitle,
                                        genreTags,
                                        year,
                                        alsoKnown,
                                        director,
                                        writer,
                                        actor,
                                        region,
                                        release,
                                        lang,
                                        rating,
                                        voteCount,
                                        tmdbId,
                                        imdbId,
                                        runtime,
                                        intro,
                                        keywords,
                                        budget,
                                        revenue,
                                        streamingPlatforms,
                                        posterUrls: posterUrls.length > 0 ? posterUrls : [],
                                        stillUrls: stillUrls.length > 0 ? stillUrls : [],
                                        url // 保存原始URL用于后续加载更多
                                    });
                                } catch (e) {
                                    innerReject(new Error(`TMDB解析失败:${e.message}`));
                                }
                            },
                            onerror: () => innerReject(new Error('TMDB请求失败')),
                            ontimeout: () => innerReject(new Error('TMDB请求超时'))
                        });
                    });
                }).then(result => resolve(result)).catch(error => reject(error));
            } else {
                reject(new Error('不支持的链接类型(仅支持豆瓣、TMDB)'));
            }
        });
    }

    function getHotComments(url) {
        return new Promise(async resolve => {
            // TMDB来源:改为走豆瓣短评页
            if (url.includes('themoviedb.org')) {
                try {
                    // 从currentMovieInfo获取豆瓣subject链接;若无,则以片名搜索豆瓣匹配
                    const info = currentMovieInfo || {};
                    let doubanId = info.doubanId;
                    if (!doubanId) {
                        try {
                            const title = info.title || info.originalTitle || '';
                            if (title) {
                                const list = await searchDouban(title).catch(() => []);
                                if (Array.isArray(list) && list.length) {
                                    // 按年份或相似度粗匹配
                                    const year = (info.release || '').slice(0,4);
                                    const picked = list.find(r => (r.year && year && String(r.year) === String(year))) || list[0];
                                    const idMatch = picked && picked.url ? picked.url.match(/subject\/(\d+)/) : null;
                                    if (idMatch) doubanId = idMatch[1];
                                }
                            }
                        } catch (e) {}
                    }
                    const doubanLink = doubanId ? `https://movie.douban.com/subject/${doubanId}/comments?sort=new_score&status=P` : '';
                    if (!doubanLink) { resolve([]); return; }
                    doubanRequest({
                        method: 'GET', url: doubanLink,
                        headers: { ...COMMON_HEADERS, 'Referer': `https://movie.douban.com/subject/${doubanId}/`, 'Host': 'movie.douban.com' },
                        timeout: 8000
                    }).then((res)=>{
                            try {
                                const doc = new DOMParser().parseFromString(res.responseText, 'text/html');
                                const items = Array.from(doc.querySelectorAll('.comment-item')).slice(0, 5);
                                const comments = items.map(node => {
                                    const short = node.querySelector('span.short');
                                    const infoA = node.querySelector('.comment-info a');
                                    const content = short ? short.textContent.trim() : '';
                                    const author = infoA ? infoA.textContent.trim() : '';
                                    return content ? { content, author } : null;
                                }).filter(Boolean).slice(0, 3);
                                resolve(comments.length ? comments : []);
                            } catch (e) { resolve([]); }
                    }).catch(()=>resolve([]));
                } catch (e) { resolve([]); }
                return;
            }
            // 优先“热门短评”页,其次默认短评页
            const base = url.replace(/\/$/, '');
            const commentUrl = `${base}/comments?sort=new_score&status=P`;
            doubanRequest({
                method: 'GET',
                url: commentUrl,
                headers: { ...COMMON_HEADERS, 'Referer': url, 'Host': new URL(url).hostname },
                timeout: 8000
            }).then((res)=>{
                    try {
                        const doc = new DOMParser().parseFromString(res.responseText, 'text/html');
                        // 兼容新旧结构:.comment-item > .comment/.comment-info + span.short
                        const items = Array.from(doc.querySelectorAll('.comment-item')).slice(0, 5);
                        const comments = items.map(node => {
                            const short = node.querySelector('span.short');
                            const info = node.querySelector('.comment-info a');
                            const content = short ? short.textContent.trim() : '';
                            const author = info ? info.textContent.trim() : '';
                            return content ? { content, author } : null;
                        }).filter(Boolean).slice(0, 3);
                        resolve(comments.length ? comments : []);
                    } catch (e) {
                        resolve([]);
                    }
            }).catch(()=>resolve([]));
        });
    }

    // 加载更多海报功能(修复点击无反应+统一分页逻辑)
    // 存储已加载的海报和剧照的唯一标识符,用于去重
    const loadedPosterIds = new Set();
    const loadedStillIds = new Set();

    // 获取图片的唯一标识符(基于URL的哈希值)
    function getImageUniqueId(url) {
        try {
            // 从URL中提取有辨识度的部分用于生成唯一ID
            let id = url;
            // 移除查询参数
            const urlObj = new URL(url);
            id = urlObj.origin + urlObj.pathname;
            // 移除可能变化的尺寸部分(针对TMDB和豆瓣)
            id = id.replace(/w\d+/g, '').replace(/h\d+/g, '').replace(/\/m\//g, '/').replace(/\/l\//g, '/').replace(/\/s\//g, '/');

            // 使用简单的哈希算法生成短ID
            let hash = 0;
            for (let i = 0; i < id.length; i++) {
                const char = id.charCodeAt(i);
                hash = ((hash << 5) - hash) + char;
                hash = hash & hash; // 转换为32位整数
            }
            return Math.abs(hash).toString(36);
        } catch (e) {
            console.warn('生成图片唯一ID失败:', e);
            // 回退方案:返回URL的基本部分
            return url.split('?')[0].split('#')[0];
        }
    }
    async function loadMorePosters() {
        if (isLoadingPosters) {
            showStatus('正在加载海报,请稍候...', false);
            return;
        }

        if (!currentMovieInfo) {
            showStatus('未找到影视信息,请重新加载', true);
            return;
        }

        isLoadingPosters = true;
        const loadMoreBtn = document.getElementById('load-more-posters');
        if (loadMoreBtn) {
            loadMoreBtn.textContent = '加载中...';
            loadMoreBtn.disabled = true;
        }

        try {
            const prevPage = posterPage;
            posterPage++; // 页码递增(加载下一页)
            let morePosters = [];

            if (currentMovieInfo.source === '豆瓣') {
                morePosters = await getDoubanOfficialPosters(currentMovieInfo.url, posterPage);
            } else if (currentMovieInfo.source === 'TMDB' && currentMovieInfo.tmdbId) {
                const config = getConfig();
                const postersUrl = `${config.TMDB.BASE_URL}/${currentMovieInfo.mediaType}/${currentMovieInfo.tmdbId}/images?api_key=${config.TMDB.API_KEY}&include_image_language=zh,en&image_type=poster&sort_by=primary`;
                await new Promise(resolvePosters => {
                    GM_xmlhttpRequest({
                        method: 'GET',
                        url: postersUrl,
                        headers: { 'Authorization': `Bearer ${config.TMDB.ACCESS_TOKEN}`, 'Content-Type': 'application/json' },
                        onload: (res) => {
                            try {
                                const posterData = JSON.parse(res.responseText);
                                // 按当前页截取(5张),避免重复
                                morePosters = safeGet(posterData, 'posters', [])
                                    .slice((posterPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT, posterPage * config.TMDB.IMAGE_CANDIDATES_COUNT)
                                    .map(img => `${config.TMDB.IMAGE_BASE_URL}${config.TMDB.LIST_POSTER_SIZE}/${img.file_path}`)
                                    .filter(Boolean);
                            } catch (e) {
                                console.log('获取更多海报失败:', e);
                            }
                            resolvePosters();
                        },
                        onerror: () => resolvePosters(),
                        ontimeout: () => resolvePosters()
                    });
                });
            }

            // 验证是否加载到新数据(避免重复加载空数据)
            if (morePosters.length > 0) {
                posterContainer.style.display = 'grid';

                // 过滤掉已加载的海报
                const uniquePosters = morePosters.filter(posterUrl => {
                    const posterId = getImageUniqueId(posterUrl);
                    if (loadedPosterIds.has(posterId)) {
                        console.log('跳过重复海报:', posterUrl);
                        return false;
                    }
                    return true;
                });

                if (uniquePosters.length === 0) {
                    // 没有新的唯一海报
                    posterPage = prevPage;
                    showStatus('没有更多新的海报了', false);
                    if (loadMoreBtn) {
                        loadMoreBtn.textContent = '没有更多海报了';
                        loadMoreBtn.disabled = true;
                        loadMoreBtn.style.opacity = '0.6';
                    }
                    return;
                }

                let addedCount = 0;
                for (let i = 0; i < uniquePosters.length; i++) {
                    try {
                        const dataUrl = await getImageDataURLWithQuality(uniquePosters[i]);
                        const posterImg = document.createElement('div');
                        // 统一海报样式:适应grid布局,避免超出,添加hover效果
                        posterImg.style.cssText = `
                            width: 100%; height: 200px; object-fit: contain;
                            border: 1px solid #f3d5d9;
                            border-radius: 8px; cursor: pointer; overflow: hidden;
                            background: #fff5f7; display: flex; align-items: center; justify-content: center;
                            transition: all 0.3s ease;
                            position: relative;
                        `;
                        // 添加hover效果的样式
                        posterImg.onmouseenter = function() {
                            this.style.transform = 'scale(1.02)';
                            this.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                        };
                        posterImg.onmouseleave = function() {
                            this.style.transform = 'scale(1)';
                            this.style.boxShadow = 'none';
                        };
                        const config = getConfig();
                        posterImg.innerHTML = `<img src="${dataUrl}" style="max-width:100%; max-height:100%; object-fit: contain;" alt="海报 ${i + 1 + (posterPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT}">`;
                        posterImg.dataset.url = dataUrl;

                        // 标记此海报已加载
                        const posterId = getImageUniqueId(uniquePosters[i]);
                        loadedPosterIds.add(posterId);
                        posterImg.dataset.posterId = posterId;

                        posterContainer.appendChild(posterImg);
                        addedCount++;
                    } catch (e) {
                        console.log(`加载海报 ${i + 1} 失败:`, e);
                    }
                }

                if (addedCount === 0) {
                    // 虽然有唯一海报,但加载全部失败
                    posterPage = prevPage;
                    showStatus('加载海报失败,请稍后重试', true);
                } else {
                    // 滚动到底部,显示新加载的海报
                    if (posterContainer) {
                        posterContainer.scrollTop = posterContainer.scrollHeight;
                    }
                    showStatus(`已加载第${posterPage}页海报(新增${addedCount}张)`, false);
                    if (loadMoreBtn) {
                        loadMoreBtn.textContent = '加载更多海报';
                        loadMoreBtn.disabled = false;
                    }
                }
            } else {
                // 无新数据,恢复页码并禁用按钮
                posterPage = prevPage;
                posterContainer.style.display = 'grid';
                if (loadMoreBtn) {
                    loadMoreBtn.textContent = '没有更多海报了';
                    loadMoreBtn.disabled = true;
                    loadMoreBtn.style.opacity = '0.6';
                }
                showStatus('已加载全部海报', false);
            }
        } catch (e) {
            // 加载失败,恢复页码
            posterPage--;
            console.error('加载更多海报出错:', e);
            showStatus('加载更多海报失败,请稍后重试', true);
            if (loadMoreBtn) {
                loadMoreBtn.textContent = '加载失败,重试';
                loadMoreBtn.disabled = false;
            }
        } finally {
            isLoadingPosters = false;
        }
    }

    // 加载更多剧照功能(修复点击无反应+统一分页逻辑+样式适配)
    async function loadMoreStills() {
        if (isLoadingStills) {
            showStatus('正在加载剧照,请稍候...', false);
            return;
        }

        if (!currentMovieInfo) {
            showStatus('未找到影视信息,请重新加载', true);
            return;
        }

        isLoadingStills = true;
        const loadMoreBtn = document.getElementById('load-more-stills');
        if (loadMoreBtn) {
            loadMoreBtn.textContent = '加载中...';
            loadMoreBtn.disabled = true;
        }

        try {
            const prevPage = stillPage;
            stillPage++; // 页码递增(加载下一页)
            let moreStills = [];

            if (currentMovieInfo.source === '豆瓣') {
                moreStills = await getDoubanStillsList(currentMovieInfo.url, stillPage);
            } else if (currentMovieInfo.source === 'TMDB' && currentMovieInfo.tmdbId) {
                moreStills = await getTMDBStillsList(currentMovieInfo.mediaType, currentMovieInfo.tmdbId, stillPage);
            }

            // 验证是否加载到新数据(避免重复加载空数据)
            if (moreStills.length > 0) {
                stillContainer.style.display = 'grid';

                // 过滤掉已加载的剧照
                const uniqueStills = moreStills.filter(stillUrl => {
                    const stillId = getImageUniqueId(stillUrl);
                    if (loadedStillIds.has(stillId)) {
                        console.log('跳过重复剧照:', stillUrl);
                        return false;
                    }
                    return true;
                });

                if (uniqueStills.length === 0) {
                    // 没有新的唯一剧照
                    stillPage = prevPage;
                    showStatus('没有更多新的剧照了', false);
                    if (loadMoreBtn) {
                        loadMoreBtn.textContent = '没有更多剧照了';
                        loadMoreBtn.disabled = true;
                        loadMoreBtn.style.opacity = '0.6';
                    }
                    return;
                }

                let addedCount = 0;
                for (let i = 0; i < uniqueStills.length; i++) {
                    try {
                        const dataUrl = await getImageDataURLWithQuality(uniqueStills[i]);
                        const stillImg = document.createElement('div');
                        // 【修复剧照超出】统一剧照样式:适应grid布局,宽高比例协调,添加hover效果
                        stillImg.style.cssText = `
                            width: 100%; height: 120px; object-fit: contain;
                            border: 1px solid #f3d5d9;
                            border-radius: 8px; cursor: pointer; overflow: hidden;
                            background: #fff5f7; display: flex; align-items: center; justify-content: center;
                            transition: all 0.3s ease;
                            position: relative;
                        `;
                        // 添加hover效果的样式
                        stillImg.onmouseenter = function() {
                            this.style.transform = 'scale(1.02)';
                            this.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                        };
                        stillImg.onmouseleave = function() {
                            this.style.transform = 'scale(1)';
                            this.style.boxShadow = 'none';
                        };
                        const config = getConfig();
                        stillImg.innerHTML = `<img src="${dataUrl}" style="max-width:100%; max-height:100%; object-fit: contain;" alt="剧照 ${i + 1 + (stillPage - 1) * config.TMDB.IMAGE_CANDIDATES_COUNT}">`;
                        stillImg.dataset.url = dataUrl;

                        // 标记此剧照已加载
                        const stillId = getImageUniqueId(uniqueStills[i]);
                        loadedStillIds.add(stillId);
                        stillImg.dataset.stillId = stillId;

                        stillContainer.appendChild(stillImg);
                        addedCount++;
                    } catch (e) {
                        console.log(`加载剧照 ${i + 1} 失败:`, e);
                    }
                }

                if (addedCount === 0) {
                    // 虽然有唯一剧照,但加载全部失败
                    stillPage = prevPage;
                    showStatus('加载剧照失败,请稍后重试', true);
                } else {
                    // 滚动到底部,显示新加载的剧照
                    if (stillContainer) {
                        stillContainer.scrollTop = stillContainer.scrollHeight;
                    }
                    showStatus(`已加载第${stillPage}页剧照(新增${addedCount}张)`, false);
                    if (loadMoreBtn) {
                        loadMoreBtn.textContent = '加载更多剧照';
                        loadMoreBtn.disabled = false;
                    }
                }
            } else {
                // 无新数据,恢复页码并禁用按钮
                stillPage = prevPage;
                stillContainer.style.display = 'grid';
                if (loadMoreBtn) {
                    loadMoreBtn.textContent = '没有更多剧照了';
                    loadMoreBtn.disabled = true;
                    loadMoreBtn.style.opacity = '0.6';
                }
                showStatus('已加载全部剧照', false);
            }
        } catch (e) {
            // 加载失败,恢复页码
            stillPage--;
            console.error('加载更多剧照出错:', e);
            showStatus('加载更多剧照失败,请稍后重试', true);
            if (loadMoreBtn) {
                loadMoreBtn.textContent = '加载失败,重试';
                loadMoreBtn.disabled = false;
            }
        } finally {
            isLoadingStills = false;
        }
    }

    async function showImageSelection(movieInfo) {
        return new Promise(async (resolve) => {
            console.log('showImageSelection 被调用,movieInfo:', movieInfo);
            console.log('posterUrls:', movieInfo.posterUrls);
            console.log('stillUrls:', movieInfo.stillUrls);

            if (!posterContainer || !stillContainer) {
                posterContainer = document.getElementById('poster-candidates');
                stillContainer = document.getElementById('still-candidates');
            }
            setupImageSelectionDelegates();
            const imageSelection = document.getElementById('image-selection');
            const loadMorePostersBtn = document.getElementById('load-more-posters');
            const loadMoreStillsBtn = document.getElementById('load-more-stills');

            if (!posterContainer || !stillContainer || !imageSelection) {
                resolve();
                return;
            }

            // 重置去重集合
            loadedPosterIds.clear();
            loadedStillIds.clear();

            // 初始加载时显示"加载中"
            posterContainer.style.display = 'grid';
            posterContainer.innerHTML = '<div style="color:#6b7280; grid-column: 1 / -1; text-align:center; padding:20px;">加载海报中...</div>';
            // 确保剧照容器首屏可见(修复首次不显示)
            stillContainer.style.display = 'grid';
            stillContainer.innerHTML = '<div style="color:#6b7280; grid-column: 1 / -1; text-align:center; padding:20px;">加载剧照中...</div>';
            imageSelection.style.display = 'block';
            loadMorePostersBtn.style.display = 'none';
            loadMoreStillsBtn.style.display = 'none';

            // 重建观察器,避免旧实例导致乱加载
            disconnectCandidateObservers();
            initCandidateObservers();

            // 处理海报(统一样式+初始第1页)
            if (movieInfo.posterUrls && movieInfo.posterUrls.length > 0) {
                stillContainer.style.display = 'grid';
                posterContainer.innerHTML = '';
                // 首张不等待转码,先用直链,极大缩短首屏时间
                selectedPosterUrl = normalizeImageUrl(movieInfo.posterUrls[0]);

                // 批量创建DOM,减少重排
                const posterFrag = document.createDocumentFragment();
                for (let i = 0; i < movieInfo.posterUrls.length; i++) {
                    try {
                        // 异步并发处理:先创建卡片,图片加载完成后替换src,避免阻塞渲染
                        const rawUrl = normalizeImageUrl(movieInfo.posterUrls[i]);
                        const posterImg = document.createElement('div');
                        // 统一海报样式:适应grid布局,添加hover效果
                        posterImg.style.cssText = `
                            width: 100%; height: 200px; object-fit: contain;
                            border: ${i === 0 ? '3px solid #ec4899' : '1px solid #f3d5d9'};
                            border-radius: 8px; cursor: pointer; overflow: hidden;
                            background: #fff5f7; display: flex; align-items: center; justify-content: center;
                            transition: all 0.3s ease;
                            position: relative;
                        `;
                        // 添加hover效果的样式
                        posterImg.onmouseenter = function() {
                            this.style.transform = 'scale(1.02)';
                            this.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                        };
                        posterImg.onmouseleave = function() {
                            this.style.transform = 'scale(1)';
                            this.style.boxShadow = 'none';
                        };
                        // 创建图片元素(先用缩略图展示,提升首屏速度)
                        const img = document.createElement('img');
                        img.style.cssText = 'max-width:100%; max-height:100%; object-fit: contain;';
                        img.alt = `海报 ${i + 1}`;
                        try {
                            getThumbnailForDisplay(rawUrl).then((thumb)=>{ const im = posterImg.querySelector('img'); if (im) im.src = thumb; });
                        } catch(e) { img.src = LAZY_PLACEHOLDER; }

                        posterImg.appendChild(img);
                        posterImg.dataset.rawUrl = rawUrl;
                        posterImg.dataset.url = rawUrl;
                        // 设置点击选中行为(同步变量与高亮)
                        posterImg.addEventListener('click', function() {
                            try {
                                selectedPosterUrl = this.dataset.url || rawUrl;
                                selectedPosterEl = this;
                                document.querySelectorAll('#poster-candidates > div').forEach(el => {
                                    el.style.border = el === this ? '3px solid #ec4899' : '1px solid #f3d5d9';
                                });
                            } catch (e) {}
                        });

                        // 标记此海报已加载
                        const posterId = getImageUniqueId(movieInfo.posterUrls[i]);
                        loadedPosterIds.add(posterId);
                        posterImg.dataset.posterId = posterId;

                        if (i === 0) {
                            selectedPosterEl = posterImg;
                        }

                        posterFrag.appendChild(posterImg);
                        // 懒加载观察
                        observeCandidateCard(posterImg, 'poster');
                    } catch (e) {
                        console.log(`加载海报 ${i + 1} 失败:`, e);
                    }
                }
                posterContainer.appendChild(posterFrag);

                loadMorePostersBtn.style.display = 'inline-block';
                loadMorePostersBtn.disabled = false;
            } else {
                // 海报保底机制:如果有剧照,使用第一张剧照作为海报
                if (movieInfo.source === '豆瓣' && movieInfo.url) {
                    // 异步抓取首批海报,不阻塞面板弹出
                    posterContainer.innerHTML = '<div style="color:#9ca3af; grid-column: 1 / -1; text-align:center; padding:12px;">加载海报中…</div>';
                    (async () => {
                        try {
                            posterPage = 1;
                            const urls = await getDoubanOfficialPosters(movieInfo.url, 1);
                            if (Array.isArray(urls) && urls.length) {
                                movieInfo.posterUrls = urls;
                                posterContainer.innerHTML = '';
                                const frag = document.createDocumentFragment();
                                for (let i = 0; i < urls.length; i++) {
                                    const rawUrl = normalizeImageUrl(urls[i]);
                                    const card = document.createElement('div');
                                    card.style.cssText = 'width: 100%; height: 200px; object-fit: contain; border: '+(i===0?'3px solid #ec4899':'1px solid #f3d5d9')+'; border-radius: 8px; cursor: pointer; overflow: hidden; background: #fff5f7; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; position: relative;';
                                    const img = document.createElement('img');
                                    img.style.cssText = 'max-width:100%; max-height:100%; object-fit: contain;';
                                    img.alt = `海报 ${i + 1}`;
                                    img.src = LAZY_PLACEHOLDER;
                                    card.appendChild(img);
                                    card.dataset.rawUrl = rawUrl;
                                    card.dataset.url = rawUrl;
                                    if (i === 0) { selectedPosterEl = card; selectedPosterUrl = rawUrl; }
                                    card.addEventListener('click', function(){
                                        try {
                                            selectedPosterUrl = this.dataset.url || rawUrl;
                                            selectedPosterEl = this;
                                            document.querySelectorAll('#poster-candidates > div').forEach(el => { el.style.border = el === this ? '3px solid #ec4899' : '1px solid #f3d5d9'; });
                                        } catch(e) {}
                                    });
                                    frag.appendChild(card);
                                    observeCandidateCard(card, 'poster');
                                }
                                posterContainer.appendChild(frag);
                                loadMorePostersBtn.style.display = 'inline-block';
                                loadMorePostersBtn.disabled = false;
                                primeFirstCandidates();
                            } else {
                                posterContainer.innerHTML = '<div style="color:#6b7280; grid-column: 1 / -1; text-align:center; padding:20px;">未找到海报</div>';
                            }
                        } catch (e) {
                            posterContainer.innerHTML = '<div style="color:#ef4444; grid-column: 1 / -1; text-align:center; padding:20px;">海报加载失败</div>';
                        }
                    })();
                } else if (movieInfo.stillUrls && movieInfo.stillUrls.length > 0) {
                    console.log('未找到海报,使用第一张剧照作为保底海报');
                    stillContainer.style.display = 'grid';
                    posterContainer.innerHTML = '';

                    const fallbackUrl = normalizeImageUrl(movieInfo.stillUrls[0]);
                    selectedPosterUrl = fallbackUrl;

                    // 创建保底海报显示
                    const fallbackPosterImg = document.createElement('div');
                    fallbackPosterImg.style.cssText = `
                        width: 100%; height: 200px;
                        border: 2px solid #f59e0b;
                        border-radius: 8px; cursor: pointer; overflow: hidden;
                        background: #fffbeb; display: flex; align-items: center; justify-content: center;
                        transition: all 0.3s ease; position: relative;
                    `;

                    // 添加保底标识
                    const badge = document.createElement('div');
                    badge.style.cssText = `
                        position: absolute; top: 5px; right: 5px;
                        background: #f59e0b; color: white; font-size: 10px;
                        padding: 2px 6px; border-radius: 4px; z-index: 1; font-weight: 500;
                    `;
                    badge.textContent = '首图';

                    const img = document.createElement('img');
                    img.src = fallbackUrl;
                    img.style.cssText = 'max-width:100%; max-height:100%; object-fit: contain;';
                    img.alt = '保底海报';
                    img.onerror = function() {
                        this.src = 'https://picsum.photos/200/300?default-poster';
                    };

                    fallbackPosterImg.appendChild(img);
                    fallbackPosterImg.appendChild(badge);
                    fallbackPosterImg.dataset.url = fallbackUrl;

                    // 添加点击选中效果
                    fallbackPosterImg.addEventListener('click', function() {
                        selectedPosterUrl = fallbackUrl;
                        document.querySelectorAll('#poster-candidates > div').forEach(el => {
                            el.style.border = el === this ? '3px solid #f59e0b' : '1px solid #f3d5d9';
                        });
                    });

                    posterContainer.appendChild(fallbackPosterImg);
                    loadMorePostersBtn.style.display = 'none';
                } else {
                    posterContainer.innerHTML = '<div style="color:#6b7280; grid-column: 1 / -1; text-align:center; padding:20px;">未找到海报</div>';
                    selectedPosterUrl = 'https://picsum.photos/200/300?default-poster';
                }
            }

            // 处理剧照(统一样式+初始第1页+修复超出)
            if (movieInfo.stillUrls && movieInfo.stillUrls.length > 0) {
                stillContainer.innerHTML = '';
                selectedStillUrl = normalizeImageUrl(movieInfo.stillUrls[0]);

                const stillFrag = document.createDocumentFragment();
                for (let i = 0; i < movieInfo.stillUrls.length; i++) {
                    try {
                        const rawUrl = normalizeImageUrl(movieInfo.stillUrls[i]);
                        const stillImg = document.createElement('div');
                        // 【修复剧照超出】统一剧照样式:适应grid布局,宽高比例协调,添加hover效果
                        stillImg.style.cssText = `
                            width: 100%; height: 120px; object-fit: contain;
                            border: ${i === 0 ? '3px solid #ec4899' : '1px solid #f3d5d9'};
                            border-radius: 8px; cursor: pointer; overflow: hidden;
                            background: #fff5f7; display: flex; align-items: center; justify-content: center;
                            transition: all 0.3s ease;
                            position: relative;
                        `;
                        // 添加hover效果的样式
                        stillImg.onmouseenter = function() {
                            this.style.transform = 'scale(1.02)';
                            this.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                        };
                        stillImg.onmouseleave = function() {
                            this.style.transform = 'scale(1)';
                            this.style.boxShadow = 'none';
                        };
                        // 创建图片元素(先用缩略图展示,提升首屏速度)
                        const img = document.createElement('img');
                        img.style.cssText = 'max-width:100%; max-height:100%; object-fit: contain;';
                        img.alt = `剧照 ${i + 1}`;
                        try {
                            getThumbnailForDisplay(rawUrl).then((thumb)=>{ const im = stillImg.querySelector('img'); if (im) im.src = thumb; });
                        } catch(e) { img.src = LAZY_PLACEHOLDER; }

                        stillImg.appendChild(img);
                        stillImg.dataset.rawUrl = rawUrl;
                        stillImg.dataset.url = rawUrl;
                        // 设置点击选中行为(同步变量与高亮)
                        stillImg.addEventListener('click', function() {
                            try {
                                selectedStillUrl = this.dataset.url || rawUrl;
                                selectedStillEl = this;
                                document.querySelectorAll('#still-candidates > div').forEach(el => {
                                    el.style.border = el === this ? '3px solid #ec4899' : '1px solid #f3d5d9';
                                });
                            } catch (e) {}
                        });

                        // 标记此剧照已加载
                        const stillId = getImageUniqueId(movieInfo.stillUrls[i]);
                        loadedStillIds.add(stillId);
                        stillImg.dataset.stillId = stillId;

                        if (i === 0) {
                            selectedStillEl = stillImg;
                        }

                        stillFrag.appendChild(stillImg);
                        // 懒加载观察
                        observeCandidateCard(stillImg, 'still');
                        // 保障首图立刻显示:若是首图则立即触发加载
                        if (i === 0) {
                            try {
                                const raw = stillImg.dataset.rawUrl || rawUrl;
                                // 先展示缩略图,后台升级为原图dataURL
                                getThumbnailForDisplay(raw).then((thumb)=>{ const im = stillImg.querySelector('img'); if (im) im.src = thumb; });
                                const upgrade = shouldConvertToDataURL(raw)
                                    ? getImageDataURLWithQuality(raw)
                                    : Promise.resolve(raw.replace(`/${getConfig().TMDB.LIST_STILL_SIZE}/`, `/${getConfig().TMDB.SELECTED_STILL_SIZE}/`));
                                upgrade.then((du)=>{
                                    const im = stillImg.querySelector('img');
                                    if (im) im.src = du;
                                    stillImg.dataset.url = du;
                                    stillImg.dataset.loaded = '1';
                                    if (selectedStillUrl === raw) selectedStillUrl = du;
                                });
                            } catch (e) {}
                        }
                    } catch (e) {
                        console.log(`加载剧照 ${i + 1} 失败:`, e);
                    }
                }
                stillContainer.appendChild(stillFrag);

                loadMoreStillsBtn.style.display = 'inline-block';
                loadMoreStillsBtn.disabled = false;
            } else {
                if (movieInfo.source === '豆瓣' && movieInfo.url) {
                    stillContainer.innerHTML = '<div style="color:#9ca3af; grid-column: 1 / -1; text-align:center; padding:12px;">加载剧照中…</div>';
                    (async () => {
                        try {
                            stillPage = 1;
                            const urls = await getDoubanStillsList(movieInfo.url, 1);
                            if (Array.isArray(urls) && urls.length) {
                                movieInfo.stillUrls = urls;
                                stillContainer.innerHTML = '';
                                const frag = document.createDocumentFragment();
                                for (let i = 0; i < urls.length; i++) {
                                    const rawUrl = normalizeImageUrl(urls[i]);
                                    const card = document.createElement('div');
                                    card.style.cssText = 'width: 100%; height: 120px; object-fit: contain; border: '+(i===0?'3px solid #ec4899':'1px solid #f3d5d9')+'; border-radius: 8px; cursor: pointer; overflow: hidden; background: #fff5f7; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; position: relative;';
                                    const img = document.createElement('img');
                                    img.style.cssText = 'max-width:100%; max-height:100%; object-fit: contain;';
                                    img.alt = `剧照 ${i + 1}`;
                                    img.src = LAZY_PLACEHOLDER;
                                    card.appendChild(img);
                                    card.dataset.rawUrl = rawUrl;
                                    card.dataset.url = rawUrl;
                                    if (i === 0) { selectedStillEl = card; selectedStillUrl = rawUrl; }
                                    card.addEventListener('click', function(){
                                        try {
                                            selectedStillUrl = this.dataset.url || rawUrl;
                                            selectedStillEl = this;
                                            document.querySelectorAll('#still-candidates > div').forEach(el => { el.style.border = el === this ? '3px solid #ec4899' : '1px solid #f3d5d9'; });
                                        } catch(e) {}
                                    });
                                    frag.appendChild(card);
                                    observeCandidateCard(card, 'still');
                                    // 保障首图立刻显示
                                    if (i === 0) {
                                        try {
                                            if (shouldConvertToDataURL(rawUrl)) {
                                                getImageDataURLWithQuality(rawUrl).then((du)=>{
                                                    const im = card.querySelector('img');
                                                    if (im) im.src = du;
                                                    card.dataset.url = du;
                                                    card.dataset.loaded = '1';
                                                    if (selectedStillUrl === rawUrl) selectedStillUrl = du;
                                                });
                                            } else {
                                                const im = card.querySelector('img');
                                                if (im) im.src = rawUrl;
                                                card.dataset.url = rawUrl;
                                                card.dataset.loaded = '1';
                                            }
                                        } catch (e) {}
                                    }
                                }
                                stillContainer.appendChild(frag);
                                loadMoreStillsBtn.style.display = 'inline-block';
                                loadMoreStillsBtn.disabled = false;
                                primeFirstCandidates();
                            } else {
                                stillContainer.style.display = 'grid';
                                stillContainer.innerHTML = '<div style="color:#6b7280; grid-column: 1 / -1; text-align:center; padding:20px;">未找到剧照</div>';
                                selectedStillUrl = 'https://picsum.photos/300/180?default-still';
                                loadMoreStillsBtn.style.display = 'none';
                            }
                        } catch (e) {
                            stillContainer.innerHTML = '<div style="color:#ef4444; grid-column: 1 / -1; text-align:center; padding:20px;">剧照加载失败</div>';
                        }
                    })();
                } else {
                    stillContainer.style.display = 'grid';
                    stillContainer.innerHTML = '<div style="color:#6b7280; grid-column: 1 / -1; text-align:center; padding:20px;">未找到剧照</div>';
                    selectedStillUrl = 'https://picsum.photos/300/180?default-still';
                    loadMoreStillsBtn.style.display = 'none';
                }
            }

            // 图片区域已完成:预热首图并延迟初始化模板工具栏,避免首屏阻塞
            try {
                primeFirstCandidates();
                setTimeout(() => { try { initTemplateToolbar(); } catch (e) {} }, 300);
            } catch (e) {}

            resolve();
        });
    }

    // 初始化美化工具
    function initFormatTools() {
        const buttonContainer = document.getElementById('format-buttons');
        const categoryContainer = document.getElementById('format-categories');
        const previewContainer = document.getElementById('format-preview');
        const previewToggle = document.getElementById('format-preview-toggle');

        if (!buttonContainer || !categoryContainer || !previewContainer || !previewToggle) return;
        // 默认隐藏预览,避免初始化时渲染预览造成卡顿
        try {
            previewContainer.style.display = 'none';
            previewToggle.textContent = '显示预览';
            previewContainer.innerHTML = '<div style="text-align:center; color:#6b7280; font-size:12px;">预览已关闭,点击“显示预览”后再加载</div>';
        } catch (e) {}

        // 清空容器
        buttonContainer.innerHTML = '';
        categoryContainer.innerHTML = '';

        // 获取所有唯一分类(稳定排序,避免reflow震荡)
        const categories = [...new Set(FORMAT_STYLES.map(style => style.category))];

        // 创建分类标签(但不触发样式渲染)
        categories.forEach(category => {
            const catBtn = document.createElement('div');
            catBtn.textContent = category;
            catBtn.style.cssText = `
                padding:4px 10px; background:#fce7f3; color:#be185d; border-radius:6px;
                font-size:12px; cursor:pointer; white-space:nowrap; transition: all 0.3s ease;
            `;

            // 添加hover效果
            catBtn.addEventListener('mouseenter', () => {
                if (catBtn.style.background !== 'rgb(236, 72, 153)') {
                    catBtn.style.background = '#fbcfe8';
                    catBtn.style.transform = 'translateY(-1px)';
                }
            });
            catBtn.addEventListener('mouseleave', () => {
                if (catBtn.style.background !== 'rgb(236, 72, 153)') {
                    catBtn.style.background = '#fce7f3';
                    catBtn.style.transform = 'translateY(0)';
                }
            });

            // 默认选中第一个分类
            if (category === categories[0]) {
                catBtn.style.background = '#ec4899';
                catBtn.style.color = 'white';
                catBtn.style.fontWeight = '500';
            }

            // 点击分类标签过滤样式(若尚未渲染按钮,则延迟到下一帧再过滤)
            catBtn.addEventListener('click', () => {
                // 更新分类按钮样式
                document.querySelectorAll('#format-categories > div').forEach(btn => {
                    btn.style.background = '#fce7f3';
                    btn.style.color = '#be185d';
                    btn.style.fontWeight = 'normal';
                });
                catBtn.style.background = '#ec4899';
                catBtn.style.color = 'white';
                catBtn.style.fontWeight = '500';

                // 显示选中分类的样式按钮
                const filterButtons = () => {
                    document.querySelectorAll('#format-buttons > button').forEach(btn => {
                        const btnCategory = btn.getAttribute('data-category');
                        btn.style.display = btnCategory === category ? 'inline-flex' : 'none';
                    });
                };
                if (buttonContainer.children.length === 0) {
                    setTimeout(filterButtons, 0);
                } else {
                    filterButtons();
                }

                // 清空预览
                previewContainer.innerHTML = '<div style="text-align:center; color:#6b7280; font-size:13px;">选择样式查看预览效果</div>';
            });

            categoryContainer.appendChild(catBtn);
        });

        // 创建样式按钮(极限斩断:初始不渲染任何按钮,首次点击分类时才懒加载)
        const CHUNK = 25;
        let index = 0;
        function renderChunk() {
            const end = Math.min(index + CHUNK, FORMAT_STYLES.length);
            for (let i = index; i < end; i++) {
                const style = FORMAT_STYLES[i];
            const btn = document.createElement('button');
            const iconHtml = style.icon ? `<i class="fa ${style.icon}" style="margin-right:4px;"></i>` : '';
            btn.innerHTML = `${iconHtml}${style.name}`;
            btn.setAttribute('data-category', style.category);
            btn.style.cssText = `
                background: #f472b6; color: white; border: none;
                padding: 6px 12px; border-radius: 6px; cursor: pointer;
                font-size: 12px; margin: 2px; display: ${style.category === categories[0] ? 'inline-flex' : 'none'};
                align-items: center; transition: all 0.3s ease; box-shadow: 0 1px 3px rgba(244, 114, 182, 0.2);
            `;

            // 样式预览功能
            if (style.preview) {
                btn.addEventListener('mouseenter', () => {
                    // 仅在“显示预览”开启后,才按需渲染预览内容
                    if (previewContainer.style.display === 'block') {
                        previewContainer.innerHTML = `
                            <div style="margin-bottom:5px; font-size:13px; color:#4b5563; font-weight:500;">
                                ${style.name} 预览:
                            </div>
                            <div class="style-preview-content">
                                ${style.apply()}
                            </div>
                        `;
                    }
                });
            }

            // 样式应用功能
            btn.addEventListener('click', async (e) => {
                e.stopPropagation();
                e.preventDefault();

                // 添加点击动画反馈
                btn.style.background = '#db2777';
                btn.style.transform = 'scale(0.98)';
                setTimeout(() => {
                    btn.style.background = '#f472b6';
                    btn.style.transform = 'scale(1)';
                }, 200);

                await autoClickSourceBtn();

                const editor = getCurrentEditor();
                if (!editor) {
                    showStatus('未找到编辑框,请先切换到源代码模式', true);
                    return;
                }

                let selectedText = '';
                if (editor.type === 'codemirror') {
                    selectedText = editor.instance.getSelection();
                } else {
                    selectedText = editor.instance.value.substring(
                        editor.instance.selectionStart,
                        editor.instance.selectionEnd
                    );
                }

                let styledHtml = style.apply(selectedText);

                // 如果选择了模板,使用模板替换编辑器内容
                try {
                    const REG = window.__TEMPLATE__;
                    if (REG && REG.CURRENT_ID) {
                        const chosen = REG.REGISTRY.find(t => t.id === REG.CURRENT_ID);
                        if (chosen) {
                            const html = compileTemplate(chosen.content, buildTemplateVars());
                            // 阀门:选择模板时,直接用模板替换编辑器全文
                            styledHtml = html;
                            // 清除按钮选中高亮
                            document.querySelectorAll('#template-toolbar button[data-tpl-id]').forEach(b => {
                                b.style.background = '#f472b6';
                                b.style.color = '#fff';
                                b.style.border = '1px solid transparent';
                                b.style.boxShadow = '0 1px 3px rgba(244,114,182,.2)';
                            });
                            REG.CURRENT_ID = null;
                        }
                    }
                } catch (e) {}

                if (editor.type === 'codemirror') {
                    editor.instance.replaceSelection(styledHtml);
                } else {
                    const start = editor.instance.selectionStart;
                    const end = editor.instance.selectionEnd;
                    editor.instance.value = editor.instance.value.substring(0, start) + styledHtml + editor.instance.value.substring(end);
                    editor.instance.dispatchEvent(new Event('input', { bubbles: true }));
                    editor.instance.focus();
                    editor.instance.setSelectionRange(start + styledHtml.length, start + styledHtml.length);
                }

                const saved = await autoClickSaveBtn();
                if (saved) {
                    showStatus(`已应用"${style.name}"并自动保存`, false);
                } else {
                    showStatus(`已应用"${style.name}",请手动保存`, false);
                }
            });

                buttonContainer.appendChild(btn);
            }
            index = end;
            if (index < FORMAT_STYLES.length) {
                const schedule = (cb) => {
                    try {
                        if (typeof window.requestIdleCallback === 'function') return window.requestIdleCallback(cb);
                        if (typeof window.requestAnimationFrame === 'function') return window.requestAnimationFrame(() => cb());
                    } catch (e) {}
                    return setTimeout(cb, 0);
                };
                schedule(renderChunk);
            }
        }
        let stylesRendered = false;
        const ensureRender = () => { if (!stylesRendered) { stylesRendered = true; renderChunk(); } };

        // 首次用户与工具交互时再开始渲染,避免初始化阻塞
        buttonContainer.addEventListener('pointerover', ensureRender, { once: true });
        categoryContainer.addEventListener('click', ensureRender, { once: true });
        previewToggle.addEventListener('click', ensureRender, { once: true });

        // 预览区域切换功能(持久化开关到localStorage,避免每次初始化造成抖动)
        previewToggle.addEventListener('click', () => {
            if (previewContainer.style.display === 'none') {
                // 打开预览时仅显示占位,不立即渲染,等待用户悬停某个样式按钮
                previewContainer.style.display = 'block';
                previewToggle.textContent = '隐藏预览';
                previewContainer.innerHTML = '<div style="text-align:center; color:#6b7280; font-size:13px;">选择样式查看预览效果</div>';
                try { localStorage.setItem('format_preview_open', '1'); } catch (e) {}
            } else {
                // 关闭预览并清空内容,释放DOM,阻止后续渲染
                previewContainer.style.display = 'none';
                previewToggle.textContent = '显示预览';
                previewContainer.innerHTML = '<div style="text-align:center; color:#6b7280; font-size:12px;">预览已关闭,点击“显示预览”后再加载</div>';
                try { localStorage.setItem('format_preview_open', '0'); } catch (e) {}
            }
        });

        // 根据本地记忆恢复预览开关
        try {
            const open = localStorage.getItem('format_preview_open') === '1';
            if (open) {
                previewContainer.style.display = 'block';
                previewToggle.textContent = '隐藏预览';
                previewContainer.innerHTML = '<div style="text-align:center; color:#6b7280; font-size:13px;">选择样式查看预览效果</div>';
            }
        } catch (e) {}

        // 为所有按钮添加悬停效果
        setTimeout(() => {
            document.querySelectorAll('#format-buttons button').forEach(btn => {
                btn.addEventListener('mouseenter', () => {
                    btn.style.transform = 'translateY(-1px)';
                    btn.style.boxShadow = '0 2px 6px rgba(244, 114, 182, 0.3)';
                });
                btn.addEventListener('mouseleave', () => {
                    btn.style.transform = 'translateY(0)';
                    btn.style.boxShadow = '0 1px 3px rgba(244, 114, 182, 0.2)';
                });
            });
        }, 100);

        // ===== 模板工具条(延迟到图片区域渲染后再初始化,避免首屏阻塞) =====
        // 移至 showImageSelection 完成后触发
    }

    // 模板系统:注册(不可用)/预览/选择
    function initTemplateToolbar() {
        try {
            const hostCard = document.querySelector('#format-buttons')?.parentElement;
            if (!hostCard) return;

            // 创建独立的模板选择界面
            let tplToolbar = document.getElementById('template-toolbar');
            if (!tplToolbar) {
                tplToolbar = document.createElement('div');
                tplToolbar.id = 'template-toolbar';
                tplToolbar.style.cssText = `
                    margin: 20px 0;
                    padding: 15px;
                    background: #ffffff;
                    border: 1px solid #e5e7eb;
                    border-radius: 8px;
                    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
                    width: 100%;
                    box-sizing: border-box;
                `;

                // 创建标题
                const titleDiv = document.createElement('div');
                titleDiv.style.cssText = 'text-align: center; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #f3f4f6;';

                const title = document.createElement('h3');
                title.textContent = '📋 模板选择器';
                title.style.cssText = 'margin: 0; font-size: 16px; font-weight: 600; color: #1f2937;';

                const subtitle = document.createElement('p');
                subtitle.textContent = '选择您喜欢的排版风格';
                subtitle.style.cssText = 'margin: 4px 0 0 0; font-size: 12px; color: #6b7280;';

                titleDiv.appendChild(title);
                titleDiv.appendChild(subtitle);
                tplToolbar.appendChild(titleDiv);

                // 创建按钮容器
                const buttonContainer = document.createElement('div');
                buttonContainer.id = 'template-button-container';
                buttonContainer.style.cssText = 'display: grid; grid-template-columns: repeat(auto-fit, minmax(85px, 1fr)); gap: 8px; justify-items: center;';
                tplToolbar.appendChild(buttonContainer);

                // 插入到合适位置(在输入区域下方,格式按钮上方)
                const formatSection = document.querySelector('#format-buttons')?.parentElement;

                if (formatSection && formatSection.parentElement) {
                    // 插在格式按钮区域上方
                    formatSection.parentElement.insertBefore(tplToolbar, formatSection);
                } else {
                    // 备用方案:插在输入区域下方
                    const inputSection = document.querySelector('div[style*="margin-bottom:20px"][style*="padding:15px"][style*="background:#fff"]');
                    if (inputSection && inputSection.parentElement) {
                        inputSection.parentElement.insertBefore(tplToolbar, inputSection.nextSibling);
                    } else {
                        hostCard.appendChild(tplToolbar);
                    }
                }
            }

            // 初始化模板注册(不可用)中心
            if (!window.__TEMPLATE__) window.__TEMPLATE__ = { REGISTRY: [], CURRENT_ID: null };
            const REG = window.__TEMPLATE__;

            // 读取外部模板(以常量内嵌,避免运行时IO)
            const TPL1 = `<div class="editor-wrap" style="max-width: 880px; margin: 40px auto; font-family: 'Helvetica Neue', 'Noto Sans SC', sans-serif; color: #1f2937; background: #ffffff; padding: 0 30px;"><!-- 主标题:玫瑰红渐变双线+对称符号,视觉焦点完全创新 -->
<h2 style="text-align: center; font-size: 31px; color: #e11d48; border-bottom: 2px double; border-image: linear-gradient(to right, transparent, #e11d48, transparent) 1; padding: 22px 0; margin: 0 0 40px 0; letter-spacing: 1.5px; text-shadow: 0 1px 4px rgba(225,29,72,0.15);">✦ {{title}} ✦</h2>
<!-- 新增:视觉主题解析(优先拆解核心立意,区别原帖模块顺序) -->
<div style="background: #f0fdf4; border-radius: 14px; padding: 24px; margin: 0 0 40px 0; border-left: 5px solid #34d399;">
<h4 style="color: #166534; font-size: 20px; margin-top: 0; margin-bottom: 18px; font-weight: 600;">◇ 视觉主题:魔法与反战的双向奔赴</h4>
<ul style="margin: 0; padding-left: 30px; line-height: 2.1; font-size: 17px;">
<li>❶ 移动城堡:钢铁与草木交织的造型,隐喻“战争机器”与“自然生机”的对抗</li>
<li>❷ 苏菲的魔法:从白发老妪到少女的转变,不是“变美”,而是“接纳自我”——真正的魔法是内心的勇敢</li>
<li>❸ 哈尔的头发:金色→黑色→红色,对应他从“伪装完美”到“直面真实”再到“为守护而战”的成长</li>
<li>❹ 反战内核:硝烟弥漫的天空与鲜花盛开的山谷对比,宫崎骏用魔法故事呐喊“战争会吞噬一切美好”</li>
</ul>
</div>
<!-- 海报+基础信息:海报hover效果创新,信息符号差异化 -->
<div style="border: 2px solid #fecdd3; border-radius: 14px; padding: 28px; margin: 0 0 40px 0; background: #fffafb;">
<div style="text-align: center; margin-bottom: 28px;"><img style="max-width: 100%; border-radius: 8px; box-shadow: 0 5px 15px rgba(225,29,72,0.12), 0 8px 20px rgba(225,29,72,0.08); transition: all 0.4s ease;" src="{{posterUrl}}" alt="主海报">
<p style="color: #e11d48; font-size: 18px; font-weight: 600; margin-top: 20px;">主视觉海报(苏菲与哈尔站在移动城堡前,天空泛着反战的硝烟蓝)</p>
</div>
<!-- 基础信息:符号位置调整,新增“原著”项,区别原帖 -->
<div class="grid-layout" style="grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); margin-top: 15px;">
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">🎬 影片名称:</strong>{{title}}</p>
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">🈶️ 原名:</strong>{{originalTitle}}</p>
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">🎬 导演:</strong>{{director}}</p>
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">📚 原著:</strong>{{originalAuthor}}</p>
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">✨ 类型:</strong>{{genres}}</p>
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">📅 上映时间:</strong>{{release}}</p>
<p style="margin: 0; font-size: 17px;"><strong style="color: #be123c;">⭐ 豆瓣评分:</strong><span style="color: #fff; background: #e11d48; padding: 3px 12px; border-radius: 15px; font-weight: 500;">{{rating}}</span></p>
</div>
</div>
<!-- 角色羁绊:上下渐变边框+错位排列,保留原模板内容(可手动编辑) -->
<h3 style="font-size: 22px; color: #e11d48; font-weight: 600; text-decoration: underline solid #fecdd3; margin: 0 0 26px 0;">▹ 魔法羁绊双人组</h3>
<div style="display: flex; flex-wrap: wrap; gap: 25px; margin: 0 0 40px 0;"><div class="role-card" style="flex: 1; min-width: 300px; background: #ffffff; padding: 24px; border-radius: 12px; border-top: 3px solid; border-image: linear-gradient(to right, #e11d48, #fecdd3) 1; box-shadow: 0 6px 16px rgba(225,29,72,0.09); transition: box-shadow 0.3s ease;"><p style="margin: 0 0 18px 0; font-size: 19px;"><strong style="color: #be123c;">● 苏菲</strong>(帽子店少女)</p><p style="margin: 0; font-size: 17px; line-height: 2;">被荒野女巫施咒变成老妪,却因祸得福逃离平庸生活。她用温柔与勇敢治愈哈尔的“逃避症”,从“自卑少女”到“城堡守护者”,最终明白:“年龄和外貌都不重要,内心的强大才是真正的魔法”。</p></div><div class="role-card" style="flex: 1; min-width: 300px; background: #ffffff; padding: 24px; border-radius: 12px; border-top: 3px solid; border-image: linear-gradient(to right, #34d399, #bbf7d0) 1; box-shadow: 0 6px 16px rgba(52,211,153,0.09); transition: box-shadow 0.3s ease;"><p style="margin: 0 0 18px 0; font-size: 19px;"><strong style="color: #166534;">● 哈尔</strong>(魔法少年)</p><p style="margin: 0; font-size: 17px; line-height: 2;">拥有强大魔法却害怕承担责任的“完美主义者”,为逃避国王的征兵而四处躲藏。遇到苏菲后,他逐渐学会直面内心:“我终于找到想守护的东西了”——这份守护让他从“华丽的逃兵”变成“勇敢的战士”。</p></div></div>
<!-- 关键场景解析:使用可变量剧照 -->
<h3 style="font-size: 22px; color: #e11d48; font-weight: 600; text-decoration: underline solid #fecdd3; margin: 0 0 26px 0;">▹ 魔法场景隐喻</h3>
<div style="margin: 0 0 40px 0; text-align: center;"><div style="display: inline-block; position: relative; max-width: 100%;"><img style="max-width: 100%; border-radius: 8px; border: 2px solid #fecdd3; box-shadow: 0 6px 16px rgba(225,29,72,0.1);" src="{{sceneUrl}}" alt="苏菲与哈尔的魔法场景"><div class="scene-desc" style="position: absolute; bottom: -45px; left: 50%; transform: translateX(-50%); background: #fffafb; padding: 8px 16px; border-radius: 8px; border: 1px solid #fecdd3; font-size: 15px; color: #be123c; width: 92%; line-height: 1.8;">场景说明</div></div></div>
<!-- 剧情脉络/热评/观影提示:保留原模板的详细写作,用户可手动修订 -->
<h3 style="font-size: 22px; color: #e11d48; font-weight: 600; text-decoration: underline solid #fecdd3; margin: 0 0 26px 0;">▹ 剧情脉络</h3>
<div style="background: #fffafb; border-left: 5px solid #e11d48; padding: 28px; border-radius: 12px; margin: 0 0 40px 0; line-height: 2.1; font-size: 17px;">
<p>1. ……(保持模板原文,便于“一比一”呈现,可手动修改)</p>
</div>
</div>`;
            const TPL2 = `<!-- 3. 标题区(后置,用分割线强化区分) -->
<div style="margin: 0 0 30px 0; padding: 10px 0; border-top: 1px dashed #f5e0c8; border-bottom: 1px dashed #f5e0c8;">
  <h2 style="text-align: center; font-size: 22px; color: #cd7f32; margin: 0; letter-spacing: 2px; font-weight: 600;">◇ {{title}} ◇</h2>
</div>
<div style="max-width: 880px; margin: 25px auto; font-family: 'Heiti SC', 'Microsoft Yahei', sans-serif; color: #332718; background: #fffbf5; padding: 22px; border-radius: 10px; box-shadow: 0 3px 10px rgba(205, 127, 50, 0.09);"><!-- 1. 核心信息卡(置顶,打破“标题→海报”的常规顺序) -->
  <div style="background: #fff; border-radius: 8px; padding: 18px; margin: 0 0 28px 0; border-top: 4px solid #cd7f32; box-shadow: 0 2px 6px rgba(205, 127, 50, 0.06);">
    <div style="display: grid; grid-template-columns: auto 1fr; gap: 15px; align-items: center; margin-bottom: 15px;">
      <!-- 左侧:评分醒目展示 -->
      <div style="text-align: center; padding: 10px 15px; background: #fff8f0; border-radius: 6px; border: 1px solid #f5e0c8;">
        <span style="font-size: 28px; color: #cd7f32; font-weight: bold;">{{rating}}</span>
        <p style="margin: 5px 0 0; font-size: 12px; color: #8b5a2b;">{{ratingSource}}</p>
      </div>
      <!-- 右侧:关键标识+基础信息 -->
      <div style="display: flex; justify-content: space-between; align-items: center;">
        <div>
          <p style="margin: 0; font-size: 14px; color: #665233;"><strong>● 标识:</strong>{{markerType}} <a style="color: #cd7f32; text-decoration: none; border-bottom: 1px dotted #f5e0c8;" href="{{markerLink}}" target="_blank" rel="noopener">{{markerId}}</a></p>
          <p style="margin: 8px 0 0; font-size: 14px; color: #665233;"><strong>● 上线:</strong>{{release}}</p>
        </div>
        <p style="margin: 0; font-size: 14px; color: #665233;"><strong>● 片长:</strong>{{runtime}}</p>
      </div>
    </div>
    <!-- 下方:多列信息网格(拆分为三列,区别于之前的两列) -->
    <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; font-size: 14px; line-height: 1.6;">
      <p><strong style="color: #cd7f32;">▶ 片名:</strong>{{title}}</p>
      <p><strong style="color: #cd7f32;">▶ 导演:</strong>{{directorDisplay}}</p>
      <p><strong style="color: #cd7f32;">▶ 编剧:</strong>{{writerDisplay}}</p>
      <p><strong style="color: #cd7f32;">▶ 类型:</strong>{{genresDisplay}}</p>
      <p><strong style="color: #cd7f32;">▶ 地区:</strong>{{regionDisplay}}</p>
      <p><strong style="color: #cd7f32;">▶ 语言:</strong>{{filmLanguageDisplay}}</p>
      <p style="grid-column: 1 / -1;"><strong style="color: #cd7f32;">▶ 主演:</strong><span style="display: inline-block; max-width: calc(100% - 60px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" title="{{actor}}">{{actorDisplay}}</span></p>
    </div>
  </div>
  <!-- 2. 海报区(放在信息卡之后,视觉重心后移) -->
  <div style="margin: 0 0 32px 0; border: 1px solid #f5e0c8; border-radius: 8px; padding: 12px; background: #fff;">
    <img style="max-width: 100%; border-radius: 6px; display: block; margin: 0 auto;" src="{{posterUrl}}" alt="{{title}}海报">
    <p style="text-align: center; color: #8b5a2b; font-size: 13px; font-weight: 500; margin: 12px 0 0; letter-spacing: 0.5px;">{{title}} · 官方海报</p>
  </div>
  <!-- 4. 剧情区(用色块+图标引导,区别于竖线) -->
  <div style="margin: 0 0 30px 0;">
    <div style="display: flex; align-items: center; margin-bottom: 10px;"><span style="display: inline-block; width: 20px; height: 20px; background: #cd7f32; color: #fff; border-radius: 50%; text-align: center; line-height: 20px; font-size: 12px; margin-right: 8px;">●</span>
      <h3 style="font-size: 17px; color: #8b5a2b; font-weight: 600; margin: 0;">剧情简介</h3>
    </div>
    <div style="background: #fff; padding: 18px; border-radius: 8px; border: 1px solid #f5e0c8; line-height: 1.7; font-size: 15px; color: #332718;">{{introAuto}}</div>
  </div>
  <!-- 5. 热评区(左对齐来源,区别于右对齐;加边框装饰) -->
  <div style="margin: 0 0 30px 0;">
    <div style="display: flex; align-items: center; margin-bottom: 10px;"><span style="display: inline-block; width: 20px; height: 20px; background: #cd7f32; color: #fff; border-radius: 50%; text-align: center; line-height: 20px; font-size: 12px; margin-right: 8px;">●</span>
      <h3 style="font-size: 17px; color: #8b5a2b; font-weight: 600; margin: 0;">观众热评</h3>
    </div>
    <div style="border: 1px dashed #f5e0c8; border-radius: 8px; padding: 18px; background: #fff8f0; line-height: 1.7; font-size: 15px;">
      {{commentsAuto}}
    </div>
  </div>
  <!-- 6. 观影贴士(用序号+图标,区别于列表) -->
  <div style="background: #fff; border-radius: 8px; padding: 20px; border: 1px solid #f5e0c8; margin: 0 0 5px 0;">
    <h3 style="font-size: 16px; color: #cd7f32; font-weight: 600; margin: 0 0 15px 0; display: flex; align-items: center;"><span style="display: inline-block; width: 18px; height: 18px; background: #cd7f32; color: #fff; border-radius: 3px; text-align: center; line-height: 18px; font-size: 12px; margin-right: 8px;">◆</span> 观影小贴士</h3>
    <div style="font-size: 15px; line-height: 2; color: #332718;">
      <p style="margin: 0;"><strong>1. </strong>推荐在{{watchScene}}观看,减少外界干扰</p>
      <p style="margin: 0;"><strong>2. </strong>二刷可留意{{detailTip}},会有新发现</p>
      <p style="margin: 0;"><strong>3. </strong>适合和{{watchWith}}一起看,看完可交流不同视角</p>
    </div>
  </div>
</div>`;
            const TPL3 = `<div style="max-width: 860px; margin: 25px auto; font-family: 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif; color: #2e7d32; background: #f9fdf9; padding: 26px; border-radius: 16px; box-shadow: 0 3px 12px rgba(46, 125, 50, 0.06);"><!-- 1. 标题区(樱花符号+居中柔和排版) -->
<h2 style="text-align: center; font-size: 22px; color: #f48fb1; margin: 0 0 35px 0; font-weight: 500; letter-spacing: 1.2px;">⭐{{title}} ⭐</h2>
<!-- 2. 海报区(纸质感边框+充足留白) -->
<div style="text-align: center; margin: 0 0 35px 0; padding: 12px; background: #fff; border-radius: 12px; border: 1px solid #e0e0e0; box-shadow: 0 2px 8px rgba(46, 125, 50, 0.04);"><img style="max-width: 75%; border-radius: 8px; border: 1px solid #f0f0f0;" src="{{posterUrl}}" alt="{{title}}海报">
<p style="color: #66bb6a; font-size: 13px; margin: 14px 0 0; line-height: 1.4;">{{title}} · 官方海报</p>
</div>
<!-- 3. 核心信息区(纵向列表+图标引导) -->
<div style="background: #fff; padding: 22px; border-radius: 12px; margin: 0 0 35px 0; border: 1px solid #e8f5e9;">
<ul style="margin: 0; padding: 0; list-style: none;">
<li style="display: flex; align-items: center; margin-bottom: 12px; font-size: 15px;">
<div>
<p style="margin: 0 0 4px; font-size: 12px; color: #81c784;">作品名</p>
<p style="margin: 0; font-weight: 500;">{{title}}</p>
</div>
</li>
<li style="display: flex; align-items: center; margin-bottom: 12px; font-size: 15px;">
<div>
<p style="margin: 0 0 4px; font-size: 12px; color: #81c784;">主创团队</p>
<p style="margin: 0;">导演:{{directorDisplay}} / 编剧:{{writerDisplay}}</p>
</div>
</li>
<li style="display: flex; align-items: center; margin-bottom: 12px; font-size: 15px;">
<div>
<p style="margin: 0 0 4px; font-size: 12px; color: #81c784;">主演</p>
<p style="margin: 0; max-width: 100%;"><span style="display: inline-block; max-width: calc(100% - 40px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" title="{{actor}}">{{actorDisplay}}</span></p>
</div>
</li>
<li style="display: flex; align-items: center; margin: 0 0 16px 0; font-size: 15px;">
<div>
<p style="margin: 0 0 4px; font-size: 12px; color: #81c784;">基础信息</p>
<p style="margin: 0;">类型:{{genresDisplay}} / 地区:{{regionDisplay}} / 语言:{{filmLanguageDisplay}}</p>
</div>
</li>
<li style="display: flex; align-items: center; margin: 0; font-size: 15px;">
<div>
<p style="margin: 0 0 4px; font-size: 12px; color: #81c784;">评分&时长</p>
<p style="margin: 0;">评分:<span style="color: #fff; background: #66bb6a; padding: 2px 8px; border-radius: 12px; font-weight: 500; font-size: 14px;">{{rating}}</span> / 片长:{{runtimeDisplay}} / 上线:{{releaseDisplay}}</p>
<p style="margin: 8px 0 0; font-size: 14px;">标识:<a style="color: #66bb6a; text-decoration: none; border-bottom: 1px dashed #e8f5e9;" href="{{markerLink}}" target="_blank" rel="noopener">{{markerType}} {{markerId}}</a></p>
</div>
</li>
</ul>
</div>
<!-- 4. 剧情简介区(樱花分割线+柔和背景) -->
<div style="margin: 0 0 35px 0;">
<div style="text-align: center; margin-bottom: 15px;"><span style="color: #f48fb1; font-size: 16px;">⭐ 剧情简介 ⭐</span>
<div style="height: 1px; background: linear-gradient(to right, transparent, #e8f5e9, transparent); margin-top: 8px;">&nbsp;</div>
</div>
<div style="background: #fff; padding: 22px; border-radius: 12px; line-height: 1.8; font-size: 15px; color: #2e7d32; border: 1px solid #e8f5e9;">{{introAuto}}</div>
</div>
<!-- 5. 观众热评区(手写感引用框) -->
<div style="margin: 0 0 35px 0;">
<div style="text-align: center; margin-bottom: 15px;"><span style="color: #f48fb1; font-size: 16px;">✍️ 观众热评 ✍️</span>
<div style="height: 1px; background: linear-gradient(to right, transparent, #e8f5e9, transparent); margin-top: 8px;">&nbsp;</div>
</div>
<div style="background: #fff; padding: 20px; border-radius: 12px; border: 1px solid #fce4ec; box-shadow: 0 2px 6px rgba(244, 143, 177, 0.05);">
<div style="font-size: 24px; color: #f48fb1; margin: -10px 0 0 -10px; opacity: 0.3;">"</div>
{{commentsAuto}}
</div>
</div>
<!-- 6. 观影贴士(植物符号+纵向卡片) -->
<div style="margin: 0 0 10px 0;">
<div style="text-align: center; margin-bottom: 15px;"><span style="color: #f48fb1; font-size: 16px;">✨ 观影贴士 ✨</span><br>
<div style="height: 1px; background: linear-gradient(to right, transparent, #e8f5e9, transparent); margin-top: 8px;">&nbsp;</div>
</div>
<div style="display: grid; grid-template-columns: 1fr; gap: 12px;">
<div style="background: #fff; padding: 18px; border-radius: 10px; border-left: 4px solid #66bb6a; font-size: 15px; color: #2e7d32;">
<p style="margin: 0;">① 推荐在{{watchScene}}观看,搭配热茶更有氛围~</p>
</div>
<div style="background: #fff; padding: 18px; border-radius: 10px; border-left: 4px solid #66bb6a; font-size: 15px; color: #2e7d32;">
<p style="margin: 0;">② 二刷可留意{{detailTip}},细节里藏着小温柔</p>
</div>
<div style="background: #fff; padding: 18px; border-radius: 10px; border-left: 4px solid #66bb6a; font-size: 15px; color: #2e7d32;">
<p style="margin: 0;">③ 适合和{{watchWith}}一起看,看完可以聊聊剧中的温暖瞬间</p>
</div>
</div>
</div>`;
            const TPL4 = `<div style="max-width: 880px; margin: 30px auto; font-family: 'SimHei', 'Microsoft Yahei', sans-serif; color: #fff; background: #1a140f; padding: 28px; border-radius: 8px; border: 1px solid #8b4513; box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);"><!-- 1. 海报+核心信息 左右分栏(港风不对称排版) -->
<div style="display: grid; grid-template-columns: 1fr 1.2fr; gap: 18px 25px; align-items: start; margin: 0 0 28px 0;"><!-- 左侧:海报区(做旧胶片边框) -->
<div style="position: relative; align-self: start; border: 8px solid #fff; border-radius: 2px; box-shadow: 0 0 0 2px #8b4513;"><img style="width: 100%; display: block; border: 1px solid #333;" src="{{posterUrl}}" alt="{{title}}海报">
<div style="position: absolute; bottom: -8px; left: 0; width: 100%; text-align: center; font-size: 12px; color: #f0c892; letter-spacing: 2px;">{{title}} · 原版海报</div>
</div>
<!-- 右侧:核心信息(港风粗体+红棕对比) -->
<div style="background: #2d2013; padding: 20px; border-radius: 4px; border-left: 4px solid #cd5c5c;">
<h3 style="font-size: 18px; color: #f0c892; margin: 0 0 20px 0; font-weight: bold; border-bottom: 1px dashed #8b4513; padding-bottom: 10px;">&diams; 影片信息 &diams;</h3>
<div style="display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; font-size: 14px; line-height: 1.65;">
<p style="margin: 0; color: #f0c892; font-weight: bold;">片名:</p>
<p style="margin: 0; font-size: 16px;">{{title}}</p>
<p style="margin: 0; color: #f0c892; font-weight: bold;">导演:</p>
<p style="margin: 0;">{{directorDisplay}}</p>
<p style="margin: 0; color: #f0c892; font-weight: bold;">主演:</p>
<p style="margin: 0; max-width: 100%;"><span style="display: inline-block; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" title="{{actor}}">{{actorDisplay}}</span></p>
<p style="margin: 0; color: #f0c892; font-weight: bold;">类型:</p>
<p style="margin: 0;">{{genresDisplay}}</p>
<p style="margin: 0; color: #f0c892; font-weight: bold;">评分:</p>
<p style="margin: 0; color: #ffd700; font-weight: bold;">{{rating}}({{ratingSource}})</p>
<p style="margin: 0; color: #f0c892; font-weight: bold;">上线:</p>
<p style="margin: 0;">{{releaseDisplay}} / {{runtimeDisplay}}</p>
<p style="margin: 0; color: #f0c892; font-weight: bold;">标识:</p>
<p style="margin: 0;"><a style="color: #f0c892; text-decoration: none; border-bottom: 1px solid #cd5c5c;" href="{{markerLink}}" target="_blank" rel="noopener"> {{markerType}} {{markerId}} </a></p>
</div>
</div>
</div>
<!-- 2. 标题区(港风大标题+复古分割) -->
<div style="margin: 0 0 28px 0; text-align: center;">
<div style="display: flex; align-items: center; justify-content: center; gap: 15px;">
<div style="height: 1px; flex: 1; background: linear-gradient(to right, transparent, #8b4513, transparent);">&nbsp;</div>
<h2 style="font-size: 26px; color: #f0c892; margin: 0; font-weight: bold; letter-spacing: 3px;">{{title}}</h2>
<div style="height: 1px; flex: 1; background: linear-gradient(to right, transparent, #8b4513, transparent);">&nbsp;</div>
</div>
<p style="margin: 10px 0 0; color: #cd5c5c; font-size: 13px; letter-spacing: 1px;">{{regionDisplay}} &middot; {{filmLanguageDisplay}} &middot; {{genresDisplay}}</p>
</div>
<!-- 3. 剧情简介区(港风报纸栏样式) -->
<div style="margin: 0 0 28px 0;">
<h3 style="font-size: 17px; color: #f0c892; margin: 0 0 15px 0; font-weight: bold; display: inline-block; background: #cd5c5c; padding: 3px 12px; border-radius: 3px;">▶ 剧情简介</h3>
<div style="background: #2d2013; padding: 22px; border-radius: 4px; line-height: 1.8; font-size: 15px; border: 1px solid #8b4513;">{{introAuto}}</div>
</div>
<!-- 4. 观众热评区(港风胶片框+手写感) -->
<div style="margin: 0 0 28px 0;">
<h3 style="font-size: 17px; color: #f0c892; margin: 0 0 15px 0; font-weight: bold; display: inline-block; background: #cd5c5c; padding: 3px 12px; border-radius: 3px;">▶ 观众热评</h3>
<div style="position: relative; background: #2d2013; padding: 25px 20px; border-radius: 4px; border: 1px solid #8b4513; box-shadow: 0 2px 8px rgba(139, 69, 19, 0.2);"><!-- 胶片装饰角 -->
<!-- 角饰移除 -->
{{commentsAuto}}
</div>
</div>
<!-- 5. 观影贴士(港风标签式) -->
<div style="margin: 0 0 10px 0;">
<h3 style="font-size: 17px; color: #f0c892; margin: 0 0 15px 0; font-weight: bold; display: inline-block; background: #cd5c5c; padding: 3px 12px; border-radius: 3px;">▶ 观影贴士</h3>
<div style="display: grid; grid-template-columns: 1fr; gap: 12px;">
<div style="background: #2d2013; padding: 15px 20px; border-radius: 4px; border-left: 3px solid #ffd700; font-size: 15px; line-height: 1.6;"><span style="color: #ffd700; font-weight: bold;">★ </span>推荐在{{watchScene}}观看,搭配汽水或啤酒更有港味~</div>
<div style="background: #2d2013; padding: 15px 20px; border-radius: 4px; border-left: 3px solid #ffd700; font-size: 15px; line-height: 1.6;"><span style="color: #ffd700; font-weight: bold;">★ </span>二刷可重点关注{{detailTip}},港片的细节藏着江湖气</div>
<div style="background: #2d2013; padding: 15px 20px; border-radius: 4px; border-left: 3px solid #ffd700; font-size: 15px; line-height: 1.6;"><span style="color: #ffd700; font-weight: bold;">★ </span>适合和{{watchWith}}一起看,看完能聊透片中的“江湖道义”</div>
</div>
</div>
</div>`;
            const TPL5 = `<div style="max-width: 800px; margin: 25px auto; font-family: 'SimSun', 'Microsoft Yahei', serif; color: #232323; background: #F5F0E1; padding: 24px; border: 1px solid #D4C8B8;">
  <div style="margin: 0 0 20px 0; text-align: center; padding: 10px 0;">
    <h1 style="font-size: 26px; color: #8B0000; margin: 0; font-weight: bold; letter-spacing: 3px;">「{{title}}」</h1>
    <p style="margin: 12px 0 0; font-size: 14px; color: #666; letter-spacing: 1px;">{{genres}} · {{release}} · {{region}}</p>
  </div>

  <div style="text-align: center; margin: 0 0 20px 0; padding: 12px; background: #fff; border: 1px solid #D4C8B8;">
    <img src="{{posterUrl}}" alt="{{title}}海报" style="max-width: 70%; border: 1px solid #D4C8B8;">
    <p style="margin: 12px 0 0; font-size: 13px; color: #8B0000; font-weight: bold;">{{title}} · 官方海报</p>
  </div>

  <div style="display: flex; flex-direction: column; gap: 10px; margin: 0 0 20px 0;">
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">影片名称:</span>{{title}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">导演:</span>{{directorDisplay}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">编剧:</span>{{writerDisplay}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">主演:</span><span style="display: inline-block; max-width: calc(100% - 60px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;" title="{{actor}}">{{actorDisplay}}</span></div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">影片类型:</span>{{genres}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">制片地区:</span>{{regionDisplay}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">语言:</span>{{filmLanguageDisplay}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">片长:</span>{{runtimeDisplay}}</div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">评分:</span><span style="background: #8B0000; color: #fff; padding: 2px 10px; font-size: 14px;">{{rating}}</span></div>
    <div style="background: #fff; padding: 10px; border-left: 3px solid #8B0000; line-height: 2; font-size: 15px;"><span style="color: #8B0000; font-weight: bold;">标识:</span><a href="{{markerLink}}" target="_blank" style="color: #8B0000; text-decoration: none; border-bottom: 1px dashed #D4C8B8;">{{markerType}} {{markerId}}</a></div>
  </div>

  <div style="margin: 0 0 20px 0;">
    <div style="background: #8B0000; color: #fff; padding: 5px 15px; font-size: 16px; font-weight: bold;">【剧情简介】</div>
    <div style="background: #fff; padding: 15px; border: 1px solid #D4C8B8; line-height: 1.8; font-size: 15px;">{{introAuto}}</div>
  </div>

  <div style="margin: 0 0 20px 0;">
    <div style="background: #8B0000; color: #fff; padding: 5px 15px; font-size: 16px; font-weight: bold;">【观众热评】</div>
    <div style="background: #fff; padding: 15px; border: 1px solid #D4C8B8; line-height: 1.8; font-size: 15px;">{{commentsAuto}}</div>
  </div>

  <div style="background: #fff; padding: 15px; border: 1px solid #D4C8B8; margin: 0 0 10px 0;">
    <div style="color: #8B0000; font-size: 16px; font-weight: bold; margin: 0 0 15px 0; border-bottom: 1px solid #D4C8B8; padding-bottom: 5px;">【观影贴士】</div>
    <ul style="margin: 0; padding-left: 20px; line-height: 2; font-size: 15px;">
      <li>推荐于{{watchScene}}观看,更能品悟影片韵味</li>
      <li>二刷可着重留意{{detailTip}},藏有中式巧思</li>
      <li>适合与{{watchWith}}共赏,观后可交流中式意趣</li>
    </ul>
  </div>
</div>`;
            const TPL6 = `<div style="max-width: 760px; margin: 30px auto; font-family: '微软雅黑', '宋体', serif; color: #2d2d2d; background: #ffffff; padding: 24px; border-radius: 8px; box-shadow: 0 2px 8px rgba(26,54,93,0.04);">
    <div style="margin-bottom: 26px; padding: 14px 18px; background: #1a365d; color: #fff; border-radius: 6px;">
        <h1 style="font-size: 24px; margin: 0; letter-spacing: 1px;">{{title}}</h1>
        <p style="font-size: 14px; margin: 8px 0 0; opacity: 0.9; line-height: 1.6;">● {{genres}} | {{releaseDisplay}} | {{regionDisplay}}</p>
    </div>

    <div style="margin-bottom: 26px; display: flex; flex-direction: column; gap: 12px;">
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px;"><span style="color: #1a365d; font-weight: bold;">● 导演:</span>{{directorDisplay}}</div>
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px;"><span style="color: #1a365d; font-weight: bold;">● 编剧:</span>{{writerDisplay}}</div>
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"><span style="color: #1a365d; font-weight: bold;">● 主演:</span><span title="{{actor}}">{{actorDisplay}}</span></div>
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px;"><span style="color: #1a365d; font-weight: bold;">● 语言:</span>{{filmLanguageDisplay}}</div>
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px;"><span style="color: #1a365d; font-weight: bold;">● 片长:</span>{{runtimeDisplay}}</div>
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px;"><span style="color: #1a365d; font-weight: bold;">● 评分:</span><span style="background: #1a365d; color: #fff; padding: 2px 8px; border-radius: 12px; font-size: 14px;">{{rating}}</span></div>
        <div style="padding: 12px 16px; background: #f5f5f5; border-radius: 6px; line-height: 1.8; font-size: 15px;"><span style="color: #1a365d; font-weight: bold;">● 官方标识:</span><a href="{{markerLink}}" target="_blank" style="color: #1a365d; text-decoration: none; border-bottom: 1px dashed #c4c9d0;">{{markerType}} {{markerId}}</a></div>
    </div>

    <div style="text-align: center; margin-bottom: 26px; padding: 14px; border: 1px solid #e5e7eb; border-radius: 6px;">
        <img src="{{posterUrl}}" alt="{{title}}官方海报" style="max-width: 70%; border-radius: 4px; border: 1px solid #e5e7eb;">
        <p style="font-size: 14px; color: #1a365d; font-weight: 600; margin-top: 12px;">{{title}} · 官方海报</p>
    </div>

    <div style="margin-bottom: 26px; padding: 16px; border-radius: 6px; border-top: 2px solid #1a365d;">
        <h3 style="font-size: 16px; color: #1a365d; margin: 0 0 12px; font-weight: bold;">● 剧情简介</h3>
        <div style="font-size: 15px; line-height: 1.8; color: #2d2d2d; margin: 0; text-indent: 2em;">{{introAuto}}</div>
    </div>

    <div style="margin-bottom: 26px; padding: 16px; background: #f9f9f9; border-radius: 6px; border-left: 3px solid #1a365d;">
        <h3 style="font-size: 16px; color: #1a365d; margin: 0 0 12px; font-weight: bold;">● 观众热评</h3>
        <div style="font-size: 15px; line-height: 1.8; color: #2d2d2d; margin: 0; padding: 10px; background: #fff; border-radius: 4px;">{{commentsAuto}}</div>
    </div>

    <div style="padding: 16px; background: #f9f9f9; border-radius: 6px;">
        <h3 style="font-size: 16px; color: #1a365d; margin: 0 0 12px; font-weight: bold;">● 观影贴士</h3>
        <ul style="margin: 0; padding-left: 24px; font-size: 15px; line-height: 2; color: #2d2d2d;">
            <li style="margin-bottom: 10px; list-style-type: disc;">推荐于{{watchScene}}观看,更能体会影片情感内核</li>
            <li style="margin-bottom: 10px; list-style-type: disc;">适合与{{watchWith}}共赏,观后可深入交流角色塑造与剧情逻辑</li>
            <li style="list-style-type: disc;">二刷可重点留意{{detailTip}},能挖掘更多创作巧思</li>
        </ul>
    </div>
</div>`;
            const TPL7 = `<div class="post-wrap"><!-- 1. 主标题区(固定框架:★装饰+渐变边框) -->
<h2 style="text-align: center; font-size: 26px; color: #22c55e; border-bottom: 2px solid; border-image: linear-gradient(to right, #f0fdf4, #22c55e, #f0fdf4) 1; padding: 15px 0; margin: 0 0 28px 0; letter-spacing: 0.5px;">★ {{title}}{{originalTitleParen}} ★</h2>
<!-- 2. 核心基础信息(固定框架:网格布局+▷符号) -->
<div style="background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 20px; margin: 0 0 28px 0;">
<h3 style="color: #166534; font-size: 19px; margin: 0 0 16px 0; font-weight: 600;">▷ 影片基础信息</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px 20px; font-size: 16px; line-height: 1.6;">
<p style="margin: 0;"><strong style="color: #22c55e;">▷ 导演:</strong>{{director}}</p>
<p style="margin: 0;"><strong style="color: #22c55e;">▷ 类型:</strong>{{genres}}</p>
<p style="margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"><strong style="color: #22c55e;">▷ 主演:</strong><span title="{{actor}}">{{actorDisplay}}</span></p>
<p style="margin: 0;"><strong style="color: #22c55e;">▷ 编剧:</strong>{{writer}}</p>
<p style="margin: 0;"><strong style="color: #22c55e;">▷ 上映:</strong>{{release}}</p>
<p style="margin: 0;"><strong style="color: #22c55e;">▷ 地区:</strong>{{region}}</p>
<p style="margin: 0;"><strong style="color: #22c55e;">▷ 片长:</strong>{{runtime}}</p>
<p style="margin: 0;"><strong style="color: #22c55e;">▷ {{ratingSource}}评分:</strong><span style="color: #fff; background: #22c55e; padding: 2px 10px; border-radius: 12px; font-weight: 500;">{{rating}}</span></p>
<p style="margin: 0; grid-column: 1 / -1;"><strong style="color: #22c55e;">▷ 标识:</strong>{{idLineHtml}}</p>
</div>
</div>
<!-- 3. 海报展示区(固定框架:居中+hover阴影) -->
<div style="text-align: center; margin: 0 0 28px 0;">
<div style="display: inline-block; max-width: 100%;"><img style="max-width: 100%; border-radius: 10px; box-shadow: 0 4px 10px rgba(34, 197, 94, 0.1); transition: box-shadow 0.3s ease;" src="{{posterUrl}}" alt="{{title}}主海报"></div>
<p style="color: #166534; font-size: 16px; font-weight: 500; margin-top: 12px;">{{title}}主视觉海报</p>
</div>
<!-- 4. 剧情简介(固定框架:左侧绿边框+浅绿背景)→ 提前至剧照前 -->
<h3 style="color: #22c55e; font-size: 19px; font-weight: 600; margin: 0 0 14px 0; text-decoration: underline dotted #bbf7d0;">▷ 影视简介</h3>
<div style="background: #f0fdf4; border-left: 4px solid #22c55e; padding: 18px; border-radius: 0 8px 8px 0; margin: 0 0 28px 0; line-height: 1.8; font-size: 16px; color: #1f2937;">{{introAuto}}</div>
<!-- 5. 影片剧照(固定框架:单张居中+hover阴影,后置到剧情简介后) -->
<h3 style="color: #22c55e; font-size: 19px; font-weight: 600; margin: 0 0 14px 0; text-decoration: underline dotted #bbf7d0;">▷ 影片剧照</h3>
<div style="text-align: center; margin: 0 0 28px 0;">
<div style="display: inline-block; max-width: 100%;"><img style="max-width: 100%; border-radius: 8px; box-shadow: 0 3px 8px rgba(139, 92, 246, 0.08); transition: box-shadow 0.3s ease;" src="{{sceneUrl}}" alt="{{title}}核心剧照">
<p style="color: #6b21a8; font-size: 15px; margin: 10px 0 0 0; line-height: 1.5;">{{title}}经典镜头</p>
</div>
</div>
<!-- 6. 观众热评(固定框架:双视角区分+顶部色边框) -->
<h3 style="color: #22c55e; font-size: 19px; font-weight: 600; margin: 0 0 14px 0; text-decoration: underline dotted #bbf7d0;">▷ 观众热评</h3>
<div style="background: #fff; padding: 20px; border-radius: 8px; margin: 0 0 28px 0; border: 1px solid #bbf7d0; border-top: 3px solid #22c55e;">
{{commentsAuto}}
</div>
<!-- 7. 观影小贴士(固定框架:◆符号+浅紫背景) -->
<p style="font-size: 16px; color: #1f2937; background: #f5f3ff; padding: 18px 18px 18px 32px; border-radius: 8px; margin: 0; line-height: 1.8; border-left: 4px solid #8b5cf6; position: relative;"><span style="position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #8b5cf6; font-size: 20px;">◆</span> 【观影小贴士】① 结合剧情简介看剧照,更易理解情感张力;② 二刷可留意剧照中的细节,与剧情伏笔呼应;③ 适合朋友/家人共同观看,看完可结合剧照讨论场景氛围的营造~</p>
</div>`;

            // 覆盖模板(1):采用用户提供的橙红风格一比一排版(变量占位已简化为可替换形式)
            const TPL1_ORANGE = `<div style="max-width: 820px; margin: 30px auto; font-family: 'Noto Sans SC', 'Microsoft Yahei', sans-serif; color: #333; background: #fff; padding: 0 20px;">
  <h2 style="text-align: center; font-size: 27px; color: #e64a19; border-bottom: 2px double; border-image: linear-gradient(to right, transparent, #e64a19, transparent) 1; padding: 15px 0; margin: 0 0 25px 0; letter-spacing: 0.8px;">★ {{title}}{{originalTitleParen}} ★</h2>

  <div style="text-align: center; margin: 0 0 25px 0; padding: 12px; border: 2px solid #ffccbc; border-radius: 10px;">
    <img src="{{posterUrl}}" alt="{{title}}海报" style="max-width: 100%; border-radius: 8px; box-shadow: 0 3px 8px rgba(230,74,25,0.15);">
    <p style="color: #e64a19; font-size: 15px; font-weight: 600; margin-top: 10px;">{{title}}主视觉海报</p>
  </div>

  <div style="background: #fff8f5; border-radius: 10px; padding: 18px 20px; margin: 0 0 16px 0; border: 1px solid #ffccbc;">
    <h4 style="color: #c2185b; font-size: 18px; margin-top: 0; margin-bottom: 12px; font-weight: 600;">▷ 基础信息</h4>
    <div style="display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 8px 16px; align-items: start; font-size: 15px; line-height: 1.6;">
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 导演:</strong>{{director}}</p>
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 类型:</strong>{{genres}}</p>
      <p style="margin: 0; min-width: 0;"><strong style="color: #e64a19;">▷ 主演:</strong><span style="display:inline-block; max-width: calc(100% - 70px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: top;" title="{{actor}}">{{actorShort}}</span></p>
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 编剧:</strong>{{writer}}</p>
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 上映:</strong>{{release}}</p>
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 地区:</strong>{{region}}</p>
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 片长:</strong>{{runtime}}</p>
      <p style="margin: 0;"><strong style="color: #e64a19;">▷ 评分:</strong><span style="color: #fff; background: #e64a19; padding: 2px 8px; border-radius: 15px; font-weight: 500;">{{rating}}</span></p>
      <p style="margin: 0; grid-column: 1 / -1;"><strong style="color: #e64a19;">▷ 标识:</strong>{{idLineHtml}}</p>
    </div>
  </div>

  <h3 style="font-size: 19px; color: #e64a19; font-weight: 600; text-decoration: underline solid #ffccbc; margin: 0 0 10px 0;">▷ 剧情简介</h3>
  <div style="background: #fff; border-left: 4px solid #e64a19; padding: 14px; border-radius: 8px; margin: 0 0 18px 0; line-height: 1.7; font-size: 15px;">{{introAuto}}</div>

  <h3 style="font-size: 19px; color: #e64a19; font-weight: 600; text-decoration: underline solid #ffccbc; margin: 0 0 10px 0;">▷ 观众热评</h3>
  <div style="background: #fff; padding: 14px; border-radius: 8px; margin: 0 0 18px 0; border: 1px solid #ffccbc; border-top: 3px solid #e64a19;">
    {{commentsAuto}}
  </div>

  <p style="font-size: 16px; color: #333; background: #fff8f5; padding: 12px 14px 12px 26px; border-radius: 8px; margin: 0 0 12px 0; line-height: 1.7; border-left: 4px solid #e64a19; position: relative;">
    <span style="position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #e64a19; font-size: 18px;">◆</span>
    【观影提示】① 建议优先查看长评,深度解析更易理解剧情;② 二刷可关注{{detailTip}},可能发现隐藏伏笔;③ 适合{{watchWith}}共同观看,看完可交流观点~
  </p>
</div>`;

            function safePush(id, name, raw) {
                if (!raw) return;
                if (REG.REGISTRY.some(t => t.id === id)) return;
                REG.REGISTRY.push({ id, name, content: templatizeHtml(raw) });
            }

            // 为每个模板赋予风格化名称(纯名字,不带备注)
            safePush('tpl1', '玫瑰幻境', TPL1_ORANGE);
            safePush('tpl2', '琥珀复古', TPL2);
            safePush('tpl3', '樱雾清新', TPL3);
            safePush('tpl4', '港风胶片', TPL4);
            safePush('tpl5', '国韵典藏', TPL5);
            safePush('tpl6', '理性简约', TPL6);
            safePush('tpl7', '森系活力', TPL7);

            // 渲染模板按钮
            const buttonContainer = document.getElementById('template-button-container') || tplToolbar;
            buttonContainer.querySelectorAll('button[data-tpl-id]').forEach(b => b.remove());
            const previewContainer = document.getElementById('format-preview');
            const previewToggle = document.getElementById('format-preview-toggle');

            REG.REGISTRY.forEach(tpl => {
                const btn = document.createElement('button');
                btn.textContent = tpl.name;
                btn.setAttribute('data-tpl-id', tpl.id);
                btn.style.cssText = `
                    background: linear-gradient(135deg, #f472b6, #ec4899);
                    color: #fff;
                    border: 1px solid transparent;
                    padding: 8px 12px;
                    border-radius: 6px;
                    font-size: 12px;
                    font-weight: 500;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    text-align: center;
                    min-width: 70px;
                    box-shadow: 0 1px 3px rgba(244, 114, 182, 0.3);
                `;

                btn.addEventListener('mouseenter', () => {
                    if (REG.CURRENT_ID !== tpl.id) {
                        btn.style.transform = 'translateY(-1px)';
                        btn.style.boxShadow = '0 2px 6px rgba(244,114,182,.35)';
                    }
                });
                btn.addEventListener('mouseleave', () => {
                    if (REG.CURRENT_ID !== tpl.id) {
                        btn.style.transform = 'translateY(0)';
                        btn.style.boxShadow = '0 1px 3px rgba(244,114,182,.2)';
                    }
                });

            btn.addEventListener('click', () => {
                    // 选中动画
                    btn.style.transform = 'scale(0.98)';
                    setTimeout(() => { btn.style.transform = 'scale(1)'; }, 120);

                // 若再次点击同一个按钮,则视为取消选择
                if (REG.CURRENT_ID === tpl.id) {
                    REG.CURRENT_ID = null;
                    btn.style.background = '#f472b6';
                    btn.style.color = '#fff';
                    btn.style.border = '1px solid transparent';
                    btn.style.boxShadow = '0 1px 3px rgba(244,114,182,.2)';
                    // 不强制关闭预览,保留上一次内容;如需关闭可开启:
                    // previewContainer.style.display = 'none'; previewToggle.textContent = '显示预览';
                    return;
                }

                // 取消其他按钮的选中样式
                tplToolbar.querySelectorAll('button[data-tpl-id]').forEach(b => {
                    b.style.background = '#f472b6';
                    b.style.color = '#fff';
                    b.style.border = '1px solid transparent';
                    b.style.boxShadow = '0 1px 3px rgba(244,114,182,.2)';
                });

                // 设置当前为选中(白色高亮)
                REG.CURRENT_ID = tpl.id;
                btn.style.background = '#fff';
                btn.style.color = '#db2777';
                btn.style.border = '1px solid #f472b6';
                btn.style.boxShadow = '0 2px 8px rgba(236,72,153,.25)';

                // 预览模板
                const demoHtml = compileTemplate(tpl.content, buildTemplateVars());
                previewContainer.style.display = 'block';
                previewToggle.textContent = '隐藏预览';
                previewContainer.innerHTML = `<div style="font-size:12px;color:#6b7280;margin-bottom:6px;">当前模板:${tpl.name}</div>` + demoHtml;
                });
                buttonContainer.appendChild(btn);
            });
        } catch (e) { /* 忽略模板初始化异常,避免影响主流程 */ }
    }

    // 将外部模板自动打上占位符,便于替换
    function templatizeHtml(html) {
        try {
            let h = String(html || '');
            if (!/\{\{title\}\}/.test(h)) h = h.replace(/(<h[12][^>]*>)([\s\S]*?)(<\/h[12]>)/i, '$1{{title}}$3');
            let imgIdx = 0;
            h = h.replace(/(<img[^>]*?src=")([^"]+)("[^>]*>)/ig, (m, p1, p2, p3) => {
                imgIdx += 1;
                if (imgIdx === 1) return `${p1}{{posterUrl}}${p3}`;
                if (imgIdx === 2) return `${p1}{{sceneUrl}}${p3}`;
                return m;
            });
            h = h.replace(/(豆瓣评分[^<]*?<span[^>]*>)[^<]+(<\/span>)/i, '$1{{rating}}$2');
            return h;
        } catch { return html; }
    }

    function compileTemplate(raw, vars) {
        return String(raw || '').replace(/\{\{(\w+)\}\}/g, (m, k) => (vars && (k in vars) ? (vars[k] ?? '') : ''));
    }

    function buildTemplateVars() {
        const info = currentMovieInfo || {};
        const src = (info && info.source) || '';
        const url = (info && info.url) || '';
        const isDouban = src === '豆瓣' || (url && url.includes('douban.com'));
        const isTmdb = src === 'TMDB' || (url && url.includes('themoviedb.org'));
        const isImdb = src === 'IMDB' || (url && url.includes('imdb.com'));
        const idLineHtml = (function(){
            if (isDouban) {
                const id = info.doubanId || '—';
                const link = url || (info.doubanId ? `https://movie.douban.com/subject/${info.doubanId}/` : '');
                return link ? `豆瓣 <a href="${link}" target="_blank" rel="noopener">${id}</a>` : `豆瓣 ${id}`;
            }
            if (isTmdb) {
                const id = info.tmdbId || '—';
                const link = info.tmdbId ? `https://www.themoviedb.org/${info.mediaType || 'movie'}/${info.tmdbId}` : (url || '');
                return link ? `TMDB <a href="${link}" target="_blank" rel="noopener">${id}</a>` : `TMDB ${id}`;
            }
            if (info.imdbId) {
                const link = `https://www.imdb.com/title/${info.imdbId}/`;
                return `IMDB <a href="${link}" target="_blank" rel="noopener">${info.imdbId}</a>`;
            }
            return '—';
        })();

        // 评分来源标签与标识三元组
        const ratingSource = isDouban ? '豆瓣' : (isTmdb ? 'TMDB' : (isImdb ? 'IMDB' : '评分'));
        let markerType = '—', markerLink = '', markerId = '—';
        if (isDouban && (info.doubanId || url)) {
            markerType = '豆瓣';
            markerId = info.doubanId || '—';
            markerLink = url || (info.doubanId ? `https://movie.douban.com/subject/${info.doubanId}/` : '');
        } else if (isTmdb && info.tmdbId) {
            markerType = 'TMDB';
            markerId = info.tmdbId;
            markerLink = `https://www.themoviedb.org/${info.mediaType || 'movie'}/${info.tmdbId}`;
        } else if (isImdb && info.imdbId) {
            markerType = 'IMDB';
            markerId = info.imdbId;
            markerLink = `https://www.imdb.com/title/${info.imdbId}/`;
        }

        // 自动简介:优先 info.intro,否则简短占位
        const introAuto = (info.intro && String(info.intro).trim())
            ? info.intro
            : '暂无剧情简介,欢迎补充你的观影理解~';

        // 自动热评:从 currentComments 取首条
        let commentsAuto = '<p style="margin:0;color:#666;font-size:15px;">暂无热评,分享你的观影感受吧~</p>';
        try {
            if (Array.isArray(currentComments) && currentComments.length > 0) {
                const first = currentComments[0];
                const quote = (first && (first.content || first.text || first.comment || '')).toString().trim();
                const author = (first && (first.author || first.user || first.nickname || '匿名'));
                if (quote) {
                    commentsAuto = `<p style=\"margin:0 0 8px 0;font-size:16px;color:#c2185b;line-height:1.7;\">\"${quote}\"</p><p style=\"margin:0;text-align:right;color:#e64a19;font-style:italic;font-size:14px;\">—— ${isDouban ? '豆瓣用户' : '用户'} @${author}</p>`;
                }
            } else if (isTmdb) {
                // TMDB无热评:用剧情/标语摘录 + TMDB更多评价链接
                const raw = (info.intro || info.tagline || '').toString().trim();
                const snippet = raw ? (raw.length > 80 ? raw.slice(0, 78) + '…' : raw) : `类型:${(Array.isArray(info.genreTags) ? info.genreTags.join(' / ') : (info.genres || '影片'))}`;
                const rvLink = info.tmdbId ? `https://www.themoviedb.org/${info.mediaType || 'movie'}/${info.tmdbId}/reviews` : '';
                const linkHtml = rvLink ? ` <a href=\"${rvLink}\" target=\"_blank\" rel=\"noopener\" style=\"color:#e64a19;text-decoration:none;border-bottom:1px dashed #ffccbc;\">更多评价</a>` : '';
                commentsAuto = `<p style=\"margin:0 0 8px 0;font-size:16px;color:#c2185b;line-height:1.7;\">\"${snippet}\"</p><p style=\"margin:0;text-align:right;color:#e64a19;font-style:italic;font-size:14px;\">—— 看点摘录${linkHtml}</p>`;
            }
        } catch (e) {}

        // 热评首条提供给模板2的精简占位
        let commentQuote = '';
        let commentAuthor = '';
        let commentSourceLabel = isDouban ? '豆瓣用户' : (isTmdb ? 'TMDB用户' : '用户');
        try {
            if (Array.isArray(currentComments) && currentComments.length > 0) {
                const first = currentComments[0];
                commentQuote = (first && (first.content || first.text || first.comment || '')).toString().trim() || '';
                commentAuthor = (first && (first.author || first.user || first.nickname || '匿名')) || '';
            }
        } catch (e) {}
        if (!commentQuote) {
            commentQuote = '暂无热评,分享你的观影感受吧~';
            commentAuthor = '匿名';
        }

        // 演员截断:避免撑开导致中间空隙,保留前若干字符与人名数量
        const actorShort = (function(){
            const raw = info.actor || '';
            if (!raw) return '未知';
            // 先按顿号/逗号/空格拆分,最多取前6个;若依旧很长,再做总长度截断
            const names = String(raw).split(/[、,,\s]+/).filter(Boolean).slice(0, 6);
            let txt = names.join('、');
            if (txt.length > 38) txt = txt.slice(0, 36) + '…';
            return txt;
        })();

        // 展示用兜底字段,避免模板出现未替换占位
        const directorDisplay = info.director || '未知';
        const writerDisplay = info.writer || '未知';
        const genresDisplay = (Array.isArray(info.genreTags) ? info.genreTags.filter(Boolean).join(' / ') : (info.genres || '')) || '未知';
        const regionDisplay = info.region || '未知';
        const filmLanguage = info.language || info.lang || '';
        const filmLanguageDisplay = filmLanguage || '未知';
        const runtimeDisplay = info.runtime || '未知';
        const releaseDisplay = (info.release || info.releaseDate || '') || '未知';
        const actorDisplay = (actorShort || info.actor || '').trim() || '未知';

        return {
            title: info.title || info.originalTitle || '标题',
            originalTitle: info.originalTitle || '',
            originalTitleSafe: info.originalTitle || '无原名',
            originalTitleParen: (info.originalTitle && info.originalTitle !== (info.title || '')) ? `(${info.originalTitle})` : '',
            director: info.director || '',
            writer: info.writer || '',
            actor: info.actor || '',
            actorShort,
            originalAuthor: info.originalAuthor || info.writer || '',
            genres: Array.isArray(info.genreTags) ? info.genreTags.join(' / ') : (info.genres || ''),
            genreTags: Array.isArray(info.genreTags) ? info.genreTags : [],
            release: info.release || info.releaseDate || '',
            region: info.region || '',
            runtime: info.runtime || '',
            filmLanguage,
            doubanId: info.doubanId || '',
            imdbId: info.imdbId || '',
            idLineHtml,
            posterUrl: selectedPosterUrl || 'https://via.placeholder.com/680x480/ff69b4/FFF?text=Poster',
            sceneUrl: selectedStillUrl || 'https://via.placeholder.com/640x340/ff69b4/FFF?text=Scene',
            rating: info.rating || '—',
            introAuto,
            commentsAuto,
            ratingSource,
            markerType,
            markerLink,
            markerId,
            commentQuote,
            commentAuthor,
            commentSourceLabel,
            detailTip: info.detailTip || '镜头语言设计',
            watchWith: info.watchWith || '家人/朋友',
            watchScene: info.watchScene || '周末午后',

            // 展示用(模板2使用)
            directorDisplay,
            writerDisplay,
            genresDisplay,
            regionDisplay,
            filmLanguageDisplay,
            runtimeDisplay,
            releaseDisplay,
            actorDisplay
        };
    }

    function getCurrentEditor() {
        // 先检查已经缓存的sourceCodeElement
        if (sourceCodeElement && sourceCodeElement.offsetParent !== null) {
            console.log('Found cached sourceCodeElement:', sourceCodeElement);
            return { type: 'textarea', instance: sourceCodeElement };
        }

        // 检查CodeMirror编辑器
        const codeMirror = document.querySelector('.CodeMirror');
        if (codeMirror && codeMirror.CodeMirror) {
            console.log('Found CodeMirror editor');
            return { type: 'codemirror', instance: codeMirror.CodeMirror };
        }

        // 扩展的编辑器选择器列表,覆盖更多可能的编辑器类型
        const editorSelectors = [
            '#myModal-code textarea',
            'textarea.tox-textarea',
            'textarea.mce-textbox',
            'textarea.cke_source',
            'textarea[name="message"]',
            '#editor_content',
            'textarea[name="content"]', // 常见的内容输入框
            '#post_content', // 论坛常见的内容输入框
            'textarea#content', // ID为content的textarea
            '.editor-content textarea', // 带有editor-content类的容器内的textarea
            '#post_message', // 论坛发帖编辑器
            '.article-editor textarea', // 文章编辑器
            'div[contenteditable="true"]', // 富文本编辑区
            '.prose-editor', // 专业编辑器
            'textarea[id^="editor_"]', // ID以editor_开头的textarea
            'textarea[id$="_editor"]', // ID以_editor结尾的textarea
            'textarea.editor'
        ];

        for (const selector of editorSelectors) {
            const elem = document.querySelector(selector);
            if (elem && elem.style.display !== 'none' && elem.offsetParent !== null) {
                console.log('Found editor with selector:', selector);
                sourceCodeElement = elem;
                return { type: 'textarea', instance: elem };
            }
        }

        // 最后的尝试:查找页面上所有可见的textarea
        const allTextareas = document.querySelectorAll('textarea');
        for (let i = 0; i < allTextareas.length; i++) {
            const textarea = allTextareas[i];
            if (textarea && textarea.style.display !== 'none' && textarea.offsetParent !== null &&
                textarea.offsetWidth > 100 && textarea.offsetHeight > 100) {
                console.log('Found visible textarea as fallback');
                sourceCodeElement = textarea;
                return { type: 'textarea', instance: textarea };
            }
        }

        if (!editorNotFoundLogged) {
        console.log('No editor found');
            editorNotFoundLogged = true;
        }
        return null;
    }
    // 修改绑定按钮事件(确保加载更多功能正常)
    function bindEventListeners() {
        // 绑定AI相关事件监听器
        bindAIEventListeners();
        let fetchBtn = document.getElementById('fetch-btn');
        const mediaUrlInput = document.getElementById('media-url');
        const pasteBtn = document.getElementById('paste-btn');
        const clearBtn = document.getElementById('clear-btn');
        const confirmImagesBtn = document.getElementById('confirm-images-btn');
        const loadMorePostersBtn = document.getElementById('load-more-posters');
        const loadMoreStillsBtn = document.getElementById('load-more-stills');

        // 调试代码:检查按钮状态
        if (fetchBtn) {
            console.log('提取按钮已找到,初始状态:', {
                classList: fetchBtn.classList.toString(),
                style: {
                    pointerEvents: fetchBtn.style.pointerEvents,
                    cursor: fetchBtn.style.cursor,
                    opacity: fetchBtn.style.opacity
                }
            });

            // 添加状态变化监听
            const observer = new MutationObserver((mutations) => {
                mutations.forEach(mutation => {
                    if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                        console.log('按钮class变化:', fetchBtn.classList.toString());
                    }
                });
            });
            observer.observe(fetchBtn, { attributes: true });
        }

        // 输入URL时激活提取按钮 - 已移至按钮初始化中,避免重复监听

        // 提取影视信息按钮
        if (fetchBtn) {
            // 移除所有可能的现有事件监听器
            const newFetchBtn = fetchBtn.cloneNode(true);
            fetchBtn.parentNode.replaceChild(newFetchBtn, fetchBtn);

            // 重新获取按钮引用
            const updatedFetchBtn = document.getElementById('fetch-btn');

            // 根据输入框内容决定按钮状态
            if (mediaUrlInput && mediaUrlInput.value.trim()) {
                updatedFetchBtn.classList.add('active');
                updatedFetchBtn.style.pointerEvents = 'auto';
                updatedFetchBtn.style.cursor = 'pointer';
                updatedFetchBtn.style.opacity = '1';
                updatedFetchBtn.style.display = 'block';
            } else {
                updatedFetchBtn.classList.remove('active');
                updatedFetchBtn.style.pointerEvents = 'none';
                updatedFetchBtn.style.cursor = 'not-allowed';
                updatedFetchBtn.style.opacity = '0.6';
                updatedFetchBtn.style.display = 'none';
            }

            // 确保按钮在页面加载时根据当前输入框内容正确激活
            if (mediaUrlInput) {
                const checkButtonState = () => {
                    if (mediaUrlInput.value.trim()) {
                        updatedFetchBtn.classList.add('active');
                        updatedFetchBtn.style.pointerEvents = 'auto';
                        updatedFetchBtn.style.cursor = 'pointer';
                        updatedFetchBtn.style.opacity = '1';
                        updatedFetchBtn.style.display = 'block';
                    } else {
                        updatedFetchBtn.classList.remove('active');
                        updatedFetchBtn.style.pointerEvents = 'none';
                        updatedFetchBtn.style.cursor = 'not-allowed';
                        updatedFetchBtn.style.opacity = '0.6';
                        updatedFetchBtn.style.display = 'none';
                    }
                };

                // 立即检查一次
                checkButtonState();

                // 监听输入变化
                mediaUrlInput.addEventListener('input', checkButtonState);
            }

            // 绑定新的点击事件处理函数
            updatedFetchBtn.addEventListener('click', async function (e) {
                console.log('提取按钮被点击');
                // 触发阻断:阻止事件冒泡,防止触发表单验证
                e.stopPropagation();
                e.preventDefault();

                const url = document.getElementById('media-url')?.value.trim();
                if (!url) {
                    showStatus('请输入影视链接', true);
                    return;
                }

                showStatus('正在提取影视信息...', false);
                try {
                    currentMovieInfo = await getBasicInfo(url);
                    currentComments = await getHotComments(url);
                    showStatus('信息提取完成,请选择海报和剧照', false);
                    await showImageSelection(currentMovieInfo);
                } catch (err) {
                    showStatus(`提取失败:${err.message || '未知错误'}`, true);
                    console.error('提取错误:', err);
                }
            });

            // 更新引用
            fetchBtn = updatedFetchBtn;

            // 确保按钮状态与输入框内容同步
            if (mediaUrlInput && mediaUrlInput.value.trim()) {
                updatedFetchBtn.classList.add('active');
                updatedFetchBtn.style.pointerEvents = 'auto';
                updatedFetchBtn.style.cursor = 'pointer';
                updatedFetchBtn.style.opacity = '1';
                updatedFetchBtn.style.display = 'block';
            } else {
                updatedFetchBtn.classList.remove('active');
                updatedFetchBtn.style.pointerEvents = 'none';
                updatedFetchBtn.style.cursor = 'not-allowed';
                updatedFetchBtn.style.opacity = '0.6';
                updatedFetchBtn.style.display = 'none';
            }
        }

        // 手动粘贴内容按钮
        if (pasteBtn) {
            pasteBtn.addEventListener('click', async function (e) {
                // 触发阻断:阻止事件冒泡,防止触发表单验证
                e.stopPropagation();
                e.preventDefault();
                const backupHtml = document.getElementById('backup-html').value;
                if (backupHtml) {
                    await autoClickSourceBtn();
                    const filled = await autoFillSourceBox(backupHtml);
                    if (filled) {
                        showStatus('内容已粘贴到编辑框', false);
                    } else {
                        showStatus('内容粘贴失败,请手动粘贴剪贴板内容', true);
                    }
                }
            });
        }

        // 清除所有内容按钮
        if (clearBtn) {
            clearBtn.addEventListener('click', function (e) {
                // 触发阻断:阻止事件冒泡,防止触发表单验证
                e.stopPropagation();
                e.preventDefault();
                if (mediaUrlInput) mediaUrlInput.value = '';
                const searchInput = document.getElementById('search-movie');
                if (searchInput) searchInput.value = '';
                const searchResults = document.getElementById('search-results');
                if (searchResults) { searchResults.classList.remove('show'); searchResults.style.visibility='hidden'; searchResults.style.opacity='0'; searchResults.style.pointerEvents='none'; }
                const imageSelection = document.getElementById('image-selection');
                if (imageSelection) imageSelection.style.display = 'none';
                if (posterContainer) posterContainer.innerHTML = '';
                if (stillContainer) stillContainer.innerHTML = '';
                if (fetchBtn) {
                    fetchBtn.classList.remove('active');
                    fetchBtn.style.display = 'none';
                    fetchBtn.style.pointerEvents = 'none';
                    fetchBtn.style.cursor = 'not-allowed';
                    fetchBtn.style.opacity = '0.6';
                }
                selectedPosterUrl = '';
                selectedStillUrl = '';
                currentMovieInfo = null;
                currentComments = [];
                // 重置页码
                posterPage = 1;
                stillPage = 1;
                showStatus('已清除所有内容', false);
            });
        }

        // 确认选择并填充按钮
        if (confirmImagesBtn) {
            confirmImagesBtn.addEventListener('click', async function (e) {
                // 触发阻断:阻止事件冒泡,防止触发表单验证
                e.stopPropagation();
                e.preventDefault();

                if (!currentMovieInfo) {
                    showStatus('未找到影视信息,请重新加载', true);
                    return;
                }

                // 兜底:优先读取已选元素的dataset.url,保证首次不点击也能拿到生效后的dataURL
                try {
                    if ((!selectedPosterUrl || /doubanio\.com/.test(selectedPosterUrl)) && selectedPosterEl && selectedPosterEl.dataset && selectedPosterEl.dataset.url) {
                        selectedPosterUrl = selectedPosterEl.dataset.url;
                    }
                } catch (e) {}
                try {
                    if ((!selectedStillUrl || /doubanio\.com/.test(selectedStillUrl)) && selectedStillEl && selectedStillEl.dataset && selectedStillEl.dataset.url) {
                        selectedStillUrl = selectedStillEl.dataset.url;
                    }
                } catch (e) {}

                // 保障:控件里可显示缩略,进入排版确保原图
                try {
                    // Douban:若仍是直链且疑似 m/s 尺寸,则拉取 raw/l 为 DataURL
                    if (/^https?:\/\/.*doubanio\.com\//.test(selectedPosterUrl)) {
                        const rawBase = selectedPosterEl && selectedPosterEl.dataset && selectedPosterEl.dataset.rawUrl
                            ? selectedPosterEl.dataset.rawUrl
                            : selectedPosterUrl;
                        selectedPosterUrl = await getImageDataURLWithQuality(rawBase);
                    }
                } catch(_) {}
                try {
                    if (/^https?:\/\/.*doubanio\.com\//.test(selectedStillUrl)) {
                        const rawBase = selectedStillEl && selectedStillEl.dataset && selectedStillEl.dataset.rawUrl
                            ? selectedStillEl.dataset.rawUrl
                            : selectedStillUrl;
                        selectedStillUrl = await getImageDataURLWithQuality(rawBase);
                    }
                } catch(_) {}

                const finalPosterUrl = toTMDBOriginal(selectedPosterUrl || '') || 'https://picsum.photos/200/300?default-poster';
                const finalStillUrl = toTMDBOriginal(selectedStillUrl || '') || 'https://picsum.photos/300/180?default-still';

                // 模板阀门:优先使用已选模板
                let useTemplate = false;
                let html;
                try {
                    const REG = window.__TEMPLATE__;
                    if (REG && REG.CURRENT_ID) {
                        const chosen = REG.REGISTRY.find(t => t.id === REG.CURRENT_ID);
                        if (chosen) {
                            useTemplate = true;
                            html = compileTemplate(chosen.content, buildTemplateVars());
                            // 应用后清空选中与高亮
                            document.querySelectorAll('#template-toolbar button[data-tpl-id]').forEach(b => {
                                b.style.background = '#f472b6';
                                b.style.color = '#fff';
                                b.style.border = '1px solid transparent';
                                b.style.boxShadow = '0 1px 3px rgba(244,114,182,.2)';
                            });
                            REG.CURRENT_ID = null;
                        }
                    }
                } catch (e) { /* 忽略模板异常,回退到原排版 */ }

                if (!useTemplate) {
                    showStatus('正在生成HTML内容...', false);
                    html = generateHTML(currentMovieInfo, currentComments, finalPosterUrl, finalStillUrl);
                } else {
                    showStatus('正在应用模板并生成内容...', false);
                }

                // 异常兜底:本地存储备份,防止填充失败
                try {
                    localStorage.setItem('backup-movie-html', html);
                } catch (localStorageError) {
                    console.log('localStorage备份失败:', localStorageError);
                }

                const backupHtml = document.getElementById('backup-html');
                if (backupHtml) backupHtml.value = html;

                // 统一逻辑:直接写入并自动保存
                const success = await writeHtmlToAnyEditor(html);
                try { await autoClickSaveBtn(); } catch(_) {}
                showStatus(success ? (useTemplate ? '模板已写入并自动保存' : '内容已写入并自动保存') : '写入失败,已提供剪贴板备份', !success);
            });
        }

        // 绑定加载更多海报按钮(确保点击有效)
        if (loadMorePostersBtn) {
            // 先移除旧事件(避免重复绑定)
            loadMorePostersBtn.removeEventListener('click', loadMorePosters);
            // 创建新的包装函数以添加事件阻止
            const wrappedLoadMorePosters = function(e) {
                // 触发阻断:阻止事件冒泡,防止触发表单验证
                e.stopPropagation();
                e.preventDefault();
                loadMorePosters();
            };
            loadMorePostersBtn.addEventListener('click', wrappedLoadMorePosters);
        }

        // 绑定加载更多剧照按钮(确保点击有效)
        if (loadMoreStillsBtn) {
            // 先移除旧事件(避免重复绑定)
            loadMoreStillsBtn.removeEventListener('click', loadMoreStills);
            // 创建新的包装函数以添加事件阻止
            const wrappedLoadMoreStills = function(e) {
                // 触发阻断:阻止事件冒泡,防止触发表单验证
                e.stopPropagation();
                e.preventDefault();
                loadMoreStills();
            };
            loadMoreStillsBtn.addEventListener('click', wrappedLoadMoreStills);
        }

        // 初始化搜索交互
        setupSearchInteractions();

        // 设置海报/剧照容器的事件委托(避免为每个item单独绑定)
        setupImageSelectionDelegates();

        // 确保移动端适配在绑定事件后应用
        applyMobileStyles();
    }

    function setupImageSelectionDelegates() {
        if (!posterContainer) posterContainer = document.getElementById('poster-candidates');
        if (!stillContainer) stillContainer = document.getElementById('still-candidates');
        // 保证默认选中元素引用与dataset同步(首次渲染后立即记录)
        try {
            const firstPoster = posterContainer && posterContainer.firstElementChild;
            if (firstPoster && !selectedPosterEl) selectedPosterEl = firstPoster;
            const firstStill = stillContainer && stillContainer.firstElementChild;
            if (firstStill && !selectedStillEl) selectedStillEl = firstStill;
        } catch (e) {}
        if (posterContainer && !posterContainer.dataset.delegateBound) {
            posterContainer.addEventListener('click', function (e) {
                const item = e.target.closest('div');
                if (!item || !posterContainer.contains(item) || !item.dataset || !item.dataset.url) return;
                const url = item.dataset.url;
                selectedPosterUrl = url;
                if (selectedPosterEl && selectedPosterEl !== item) {
                    selectedPosterEl.style.border = '1px solid #f3d5d9';
                    selectedPosterEl.style.boxShadow = 'none';
                    selectedPosterEl.style.padding = '0px';
                }
                // 使用粉色外框+偏移留白作为选中状态
                item.style.border = '3px solid #ec4899';
                item.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                item.style.padding = '2px';
                selectedPosterEl = item;
            });
            posterContainer.dataset.delegateBound = '1';
        }
        if (stillContainer && !stillContainer.dataset.delegateBound) {
            stillContainer.addEventListener('click', function (e) {
                const item = e.target.closest('div');
                if (!item || !stillContainer.contains(item) || !item.dataset || !item.dataset.url) return;
                const url = item.dataset.url;
                selectedStillUrl = url;
                if (selectedStillEl && selectedStillEl !== item) {
                    selectedStillEl.style.border = '1px solid #f3d5d9';
                    selectedStillEl.style.boxShadow = 'none';
                    selectedStillEl.style.padding = '0px';
                }
                // 使用粉色外框+偏移留白作为选中状态
                item.style.border = '3px solid #ec4899';
                item.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                item.style.padding = '2px';
                selectedStillEl = item;
            });
            stillContainer.dataset.delegateBound = '1';
        }
    }

    // 绑定AI相关事件监听器
    function bindAIEventListeners() {
        if (aiEventsBound) return; // 避免重复绑定导致多次请求
        // 先确保AI面板内容已正确生成并插入
        const aiPanelContainer = document.getElementById('ai-panel-container');
        if (aiPanelContainer && aiPanelContainer.innerHTML.trim() === '') {
            // 使用传统的DOM操作方式插入AI面板内容
            aiPanelContainer.innerHTML = createAIPanelContent();
        }
        // 重新排序:将“AI检索与图片选择”整体移动到“生成提示”上方
        try {
            const promptDiv = document.getElementById('ai-prompt-input')?.parentElement;
            const searchWrap = document.getElementById('ai-search-input')?.closest('div[style*="border:1px solid"]');
            if (promptDiv && searchWrap && promptDiv.previousSibling !== searchWrap) {
                promptDiv.parentElement.insertBefore(searchWrap, promptDiv);
            }
        } catch (_) {}

        // 获取所有需要的元素
        const aiFunctionSelect = document.getElementById('ai-function-select');
        const aiPromptInput = document.getElementById('ai-prompt-input');
        const generateAiTextBtn = document.getElementById('generate-ai-text');
        const abortAiBtn = document.getElementById('abort-ai-generate');
        const aiResultArea = document.getElementById('ai-result-area');
        const aiResultContent = document.getElementById('ai-result-content');
        // 选择结果忙碌锁,防止重复点击
        let aiResultsBusy = false;
        // 新增:AI 检索与图片区域元素
        const aiSearchInput = document.getElementById('ai-search-input');
        const aiSearchStatus = document.getElementById('ai-search-status');
        const aiSearchResults = document.getElementById('ai-search-results');
        const aiImageSelection = document.getElementById('ai-image-selection');
        const aiPosterContainer = document.getElementById('ai-poster-candidates');
        const aiStillContainer = document.getElementById('ai-still-candidates');
        const aiLoadMorePosters = document.getElementById('ai-load-more-posters');
        const aiLoadMoreStills = document.getElementById('ai-load-more-stills');
        const aiAutoTitle = document.getElementById('ai-auto-title');
        const aiDeepThink = document.getElementById('ai-deep-think');
        const aiWebBrowse = document.getElementById('ai-web-browse');
        const aiFeatureTip = document.getElementById('ai-feature-tip');

        // 根据模型能力开启/禁用“深度思考/联网补充”
        (function initFeatureToggles(){
            const cfg = getConfig();
            const model = (cfg.AI.DEFAULT_MODEL||'').toLowerCase();
            const provider = (cfg.AI.PROVIDER||'').toLowerCase();
            let supportsDeep = /gpt-4|gpt-4o|gpt-4\.1|claude-3|sonnet|gemini|glm|qwen|deepseek|mixtral/.test(model) || /openai|anthropic|gemini|bigmodel|aliyuncs|ark|together/.test(provider);
            let supportsWeb = /gpt-4o|gpt-4\.1|gemini|qwen|glm|deepseek/.test(model) || /gemini|aliyuncs|bigmodel/.test(provider);
            if (aiDeepThink) {
                aiDeepThink.disabled = !supportsDeep;
                const wrap = document.getElementById('ai-deep-wrap');
                if (wrap) wrap.style.opacity = supportsDeep? '1' : '0.5';
            }
            if (aiWebBrowse) {
                aiWebBrowse.disabled = !supportsWeb;
                const wrap = document.getElementById('ai-web-wrap');
                if (wrap) wrap.style.opacity = supportsWeb? '1' : '0.5';
            }
            if (aiFeatureTip) {
                aiFeatureTip.textContent = (!supportsDeep || !supportsWeb) ? '当前模型部分功能不可用' : '';
            }
        })();
        // 已移除AI“搜索”按钮,以下为通用的状态展示工具
        function setAiSearchLoading(show, text = '正在加载...') {
            if (!aiSearchStatus) return;
            if (show) {
                    aiSearchStatus.style.display = 'block';
                aiSearchStatus.textContent = text;
                    } else {
                            aiSearchStatus.style.display = 'none';
            }
        }

        async function renderAiImageSelection(info){
            aiImageSelection.style.display = 'block';
            aiPosterContainer.innerHTML = '';
            aiStillContainer.innerHTML = '';
            // 切换影片时清空AI区域多选集合
            try { aiSelectedPosterUrls.clear(); aiSelectedStillUrls.clear(); } catch (e) {}
            // 记录AI侧影片信息
            aiCurrentMovieInfo = info || null;
            const posters = info.posterUrls || [];
            const stills = info.stillUrls || [];
            const buildCard = (rawUrl, type) => {
                const card = document.createElement('div');
                card.style.cssText = 'width:100%;height:'+(type==='poster'?'180px':'120px')+';border:1px solid #f3d5d9;border-radius:6px;cursor:pointer;overflow:hidden;display:flex;align-items:center;justify-content:center;background:#fff5f7;';
                const img = document.createElement('img');
                img.style.cssText = 'max-width:100%;max-height:100%;object-fit:contain;';
                img.src = LAZY_PLACEHOLDER;
                card.appendChild(img);
                card.dataset.url = rawUrl;
                card.onclick = function(){ try {
                    const chosen = this.dataset.url;
                    const isSelected = this.style.border && this.style.border.indexOf('3px solid')!==-1;
                    if (isSelected) {
                        this.style.border = '1px solid #f3d5d9';
                        this.style.boxShadow = 'none';
                        this.style.padding = '0px';
                        if (type==='poster') { aiSelectedPosterUrls.delete(chosen); } else { aiSelectedStillUrls.delete(chosen); }
                    } else {
                    this.style.border = '3px solid #ec4899';
                        this.style.boxShadow = '0 4px 12px rgba(236, 72, 153, 0.3)';
                        this.style.padding = '2px';
                        if (type==='poster') { aiSelectedPosterUrls.add(chosen); } else { aiSelectedStillUrls.add(chosen); }
                    }
                } catch(e){} };
                // 懒加载真实缩略图
                getThumbnailForDisplay(rawUrl).then(src=>{ img.src = src; });
                // 预升级为更高清尺寸或DataURL
                const upgrade = shouldConvertToDataURL(rawUrl)
                    ? getImageDataURLWithQuality(rawUrl)
                    : Promise.resolve(
                        type === 'poster'
                            ? rawUrl.replace(`/${getConfig().TMDB.LIST_POSTER_SIZE}/`, `/${getConfig().TMDB.SELECTED_POSTER_SIZE}/`)
                            : rawUrl.replace(`/${getConfig().TMDB.LIST_STILL_SIZE}/`, `/${getConfig().TMDB.SELECTED_STILL_SIZE}/`)
                      );
                upgrade.then(du=>{ card.dataset.url = du; if (type==='poster') { if (aiSelectedPosterUrls.has(rawUrl)) { aiSelectedPosterUrls.delete(rawUrl); aiSelectedPosterUrls.add(du); } } else { if (aiSelectedStillUrls.has(rawUrl)) { aiSelectedStillUrls.delete(rawUrl); aiSelectedStillUrls.add(du); } } });
                return card;
            };
            // 如果接口暂时未返回图片,主动拉取首批
            let posterList = posters;
            let stillList = stills;
            if ((!posterList || posterList.length===0) && info.url) { try { posterList = await getDoubanOfficialPosters(info.url, 1); } catch(e) {} }
            if ((!stillList || stillList.length===0) && info.url) { try { stillList = await getDoubanStillsList(info.url, 1); } catch(e) {} }
            // 批量DOM插入,降低重排
            const pFrag = document.createDocumentFragment();
            (posterList||[]).forEach(u=>{ pFrag.appendChild(buildCard(u, 'poster')); });
            aiPosterContainer.appendChild(pFrag);
            const sFrag = document.createDocumentFragment();
            (stillList||[]).forEach(u=>{ sFrag.appendChild(buildCard(u, 'still')); });
            aiStillContainer.appendChild(sFrag);
            // 当列表条数>=首批数时显示“加载更多”
            const pageSize = getConfig().TMDB.IMAGE_CANDIDATES_COUNT || 5;
            const hasMorePosters = (posterList && posterList.length >= pageSize);
            const hasMoreStills = (stillList && stillList.length >= pageSize);
            if (aiLoadMorePosters) { aiLoadMorePosters.style.display = hasMorePosters ? 'inline-block' : 'none'; }
            if (aiLoadMoreStills) { aiLoadMoreStills.style.display = hasMoreStills ? 'inline-block' : 'none'; }
        }

        // 输入时自动弹出搜索结果列表(500ms防抖)
        if (aiSearchInput) {
            let debounceTimer;
            aiSearchInput.addEventListener('input', function(){
                clearTimeout(debounceTimer);
                const v = this.value.trim();
                if (!v) { if (aiSearchResults) aiSearchResults.style.display = 'none'; return; }
                debounceTimer = setTimeout(async ()=>{
                    if (isMainFlowActive) return; // 主流程激活时隔离AI检索
                    setAiSearchLoading(true, '搜索中...');
                    const [d, t] = await Promise.all([searchDouban(v).catch(()=>[]), searchTMDB(v).catch(()=>[])]);
                    const unique = rankAndDedupResults([...(d||[]), ...(t||[])], v).slice(0,60);
                    aiSearchResults.style.display = 'block';
                    aiSearchResults.innerHTML = '';
                    displaySearchResults(unique, aiSearchResults);
                    // 重新绑定点击(避免多次搜索后因旧监听失效而无反应)
                    aiSearchResults.onclick = null;
                    aiResultsBusy = false;
                    aiSearchResults.addEventListener('click', async (ev)=>{
                        const itemEl = ev.target.closest('.search-item');
                        if (!itemEl) return;
                        const url = itemEl.getAttribute('data-url');
                        if (!url) return;
                        if (aiResultsBusy) return;
                        aiResultsBusy = true;
                        setAiSearchLoading(true, '正在加载图片...');
                        const detail = await getBasicInfo(url);
                        await renderAiImageSelection(detail);
                        // 自动把选中的片名写入提示词(可开关,且会替换旧的“目标影视:”行)
                        try {
                            if (aiAutoTitle && aiAutoTitle.checked) {
                                const p = document.getElementById('ai-prompt-input');
                                if (p) {
                                    const title = (detail && detail.title) || (itemEl.querySelector('strong')?.textContent)||'';
                                    if (title) {
                                        // 移除旧的“目标影视:xxx”行
                                        let cleaned = (p.value || '').replace(/^\s*目标影视:.*$/gm, '').trim();
                                        p.value = (cleaned ? cleaned + '\n' : '') + `目标影视:${title}`;
                                    }
                                }
                            }
                            // 若关掉开关,则清理已有的“目标影视:”行
                            else {
                                const p = document.getElementById('ai-prompt-input');
                                if (p) p.value = (p.value || '').replace(/^\s*目标影视:.*$/gm, '').trim();
                            }
                        } catch(_) {}
                        setAiSearchLoading(false);
                        aiResultsBusy = false;
                    });
                    setAiSearchLoading(false);
                }, 500);
            });
        }
        const copyAiResultBtn = document.getElementById('copy-ai-result');
        const insertAiResultBtn = document.getElementById('insert-ai-result');



        // 绑定AI角色设置按钮点击事件 - 已移除入口,保留空函数避免引用错误
        function setupAIRoleSettingsBtn() { return; }

        // 立即执行一次
        setupAIRoleSettingsBtn();

        // 已移除轮询与降级逻辑,避免无意义的DOM操作

        // 切换AI功能类型时更新提示框占位符
        if (aiFunctionSelect && aiPromptInput) {
            aiFunctionSelect.addEventListener('change', function() {
                const selectedId = this.value;
                const config = getConfig();
                const selectedFeature = config.AI.FEATURES.find(f => f.id === selectedId);
                if (selectedFeature && selectedFeature.placeholder) {
                    aiPromptInput.placeholder = selectedFeature.placeholder;
                }
            });
        }

        // 生成AI文本
        if (generateAiTextBtn) {
            // 防抖:避免重复触发导致多次请求
            let isGenerating = false;
            generateAiTextBtn.addEventListener('click', async function(e) {
                e.stopPropagation();
                e.preventDefault();
                if (isGenerating) return;
                isGenerating = true;
                if (abortAiBtn) abortAiBtn.style.display = 'inline-block';
                const functionType = aiFunctionSelect.value;
                const promptText = aiPromptInput.value.trim();
                const styleSelectionEl = document.getElementById('ai-style-select');
                const styleChoice = styleSelectionEl ? (styleSelectionEl.value || '') : '';
                const config = getConfig();
                const apiEndpoint = config.AI.API_ENDPOINT;
                const apiKey = config.AI.API_KEY;

                if (!promptText) {
                    showStatus('请输入生成提示', true, 'ai');
                    return;
                }

                if (!apiEndpoint) {
                    showStatus('请配置AI API端点', true, 'ai');
                    return;
                }

                // 显示加载状态
                generateAiTextBtn.disabled = true;
                generateAiTextBtn.innerHTML = '<i class="fa fa-spinner fa-spin" style="margin-right:5px;"></i>生成中...';
                aiResultArea.style.display = 'none';
                aiResultContent.textContent = '';

                try {
                    // 获取AI侧影片信息(与主流程隔离)
                    let movieContext = '';
                    const refInfo = aiCurrentMovieInfo || currentMovieInfo;
                    if (refInfo) {
                        movieContext = `\n\n参考影视信息:\n名称:${refInfo.title}\n类型:${refInfo.genreTags?.join('、') || '未知'}\n简介:${refInfo.intro?.substring(0, 300) || '暂无简介'}`;
                    }

                    // 获取编辑框内容作为上下文
                    let editorContext = '';
                    const editor = getCurrentEditor();
                    if (editor) {
                        let editorContent = '';
                        if (editor.type === 'codemirror') {
                            editorContent = editor.instance.getValue();
                        } else if (editor.instance) {
                            // 处理普通textarea
                            if (editor.instance.value) {
                                editorContent = editor.instance.value;
                            }
                            // 处理contenteditable元素
                            else if (editor.instance.getAttribute('contenteditable') === 'true') {
                                editorContent = editor.instance.textContent || editor.instance.innerText;
                            }
                        }

                        if (editorContent && editorContent.trim()) {
                            console.log('Successfully got editor content, length:', editorContent.length);
                            // 只取前1000个字符,避免上下文过长
                            const trimmedContent = editorContent.substring(0, 1000);
                            editorContext = `\n\n编辑框内容(作为参考):\n${trimmedContent}`;
                        } else {
                            console.log('Editor found but content is empty');
                        }
                    } else {
                        if (!editorNotFoundLogged) {
                        console.log('No editor found');
                            editorNotFoundLogged = true;
                        }
                    }

                    // 生成完整的提示词(附加固定框架提示+预设模板+已选图片URL)
                    // 去掉“让AI学习排版文件”的旧提示拼接
                    const presetHead = '';
                    const presetText = '';
                    // 收集多选图片
                    // 仅使用AI面板选择的图片,绝不读取主工具选择
                    const posterListForAI = Array.from(aiSelectedPosterUrls || []);
                    const stillListForAI = Array.from(aiSelectedStillUrls || []);
                    // 向后兼容:若无多选,则回退到单选值
                    // 不回退到主工具选择:无选择则按“无图”策略
                    // 控制上下文体积,避免超长
                    const maxImagesForPrompt = 6;
                    const posterForPrompt = posterListForAI.slice(0, maxImagesForPrompt);
                    const stillForPrompt = stillListForAI.slice(0, maxImagesForPrompt);
                    // 将长链接压缩为可识别的短标识(避免占用大量token)
                    const toShortRef = (u)=>{
                        try {
                            const s = String(u);
                            if (/doubanio\.com/.test(s)) {
                                const m = s.match(/\/p(\d+)/); // 取图片ID
                                return m ? `db:p${m[1]}` : 'db:img';
                            }
                            if (/image\.tmdb\.org\/t\/p\//.test(s)) {
                                const m = s.match(/t\/p\/[^/]+\/([^/?#]+)/);
                                return m ? `tmdb:${m[1].slice(0,16)}` : 'tmdb:img';
                            }
                            // 其他来源:仅保留文件名
                            const tail = s.split('/')[(s.split('/').length-1)] || '';
                            return tail ? tail.slice(0,18) : 'img';
                        } catch(_) { return 'img'; }
                    };
                    const posterRefs = posterForPrompt.map(toShortRef);
                    const stillRefs = stillForPrompt.map(toShortRef);
                    const imageContext = `${posterRefs.length ? `\n\n[海报参考ID] ${posterRefs.length} 张\n${posterRefs.join(' ')}` : '\n\n[海报参考ID] 0 张'}${stillRefs.length ? `\n\n[剧照参考ID] ${stillRefs.length} 张\n${stillRefs.join(' ')}` : '\n\n[剧照参考ID] 0 张'}`;
                    // 影片基础信息上下文(确保标题/导演/主演/评分/海报/简介/热评)
                    const base = aiCurrentMovieInfo || currentMovieInfo || {};
                    const safeIntro = (base.intro||'').replace(/\s+/g,' ').slice(0,800);
                    const safeComments = (base.comments && base.comments.length)?`\n观众热评:${base.comments.slice(0,3).map(c=>c.content.slice(0,140)).join(' / ')}`:'';
                    const baseInfo = `\n\n[影片信息]\n标题:${base.title||''}\n原名:${base.originalTitle||''}\n又名:${base.alsoKnown||''}\n类型:${(base.genreTags||[]).join('、')}\n地区:${base.region||''}\n语言:${base.lang||''}\n上映:${base.release||''}\n片长:${base.runtime||''}\n导演:${base.director||''}\n编剧:${base.writer||''}\n主演:${base.actor||''}\nIMDb:${base.imdbId||''}\n评分:${base.rating||''}\n关键词:${(base.keywords||'').toString().slice(0,120)}\n平台:${(base.streamingPlatforms||[]).join('、').slice(0,60)}\n获奖:${(base.awards||[]).join('、').slice(0,120)}\n海报参考:${posterRefs[0]||''}\n剧情简介:${safeIntro}${safeComments}`;
                    const styleHint = styleChoice ? (
                        styleChoice === '万象合流'
                            ? `\n\n[风格要求]\n采用“万象合流”混合风格:可跨文化、跨体裁自适应(专业严谨/简洁实用/活泼有趣/学术/幽默/文艺/复古/赛博/国潮等),按影片题材与情绪在段落级别灵活切换,但整体语气与视觉层级保持一致、自然、可读。`
                            : `\n\n[风格要求]\n请以“${styleChoice}”风格组织语言与排版。`
                    ) : '';
                    // 标题锁定,避免串片
                    const refTitle = (base && base.title) ? String(base.title) : '';
                    const lockTitle = refTitle ? `\n\n[标题锁定]\n仅针对《${refTitle}》生成内容,禁止替换为其他影片。若无足够信息请明确标注“未知”。` : '';
                    // 无图策略:明确指令不生成任何图片容器
                    const noImageRule = (!posterRefs.length && !stillRefs.length) ? '\n\n[无图模式]\n禁止输出任何与图片相关的标题、容器或占位(包括海报、剧照、图集等),按纯文本/信息卡排版。' : '';
                    const combinedPrompt = `${presetHead}\n\n${presetText}\n\n${promptText}${styleHint}${lockTitle}${imageContext}${noImageRule}${baseInfo}`;
                    // 组合并裁剪提示,避免超长
                    const merged = getAIPromptByType(functionType, combinedPrompt, movieContext + editorContext);
                    const MAX_PROMPT_CHARS = 60000; // 兼容多数提供商
                    const fullPrompt = merged.length > MAX_PROMPT_CHARS ? merged.slice(0, MAX_PROMPT_CHARS) : merged;

                    // 调用AI API生成文本
                    const aiResult = await generateAIText(apiEndpoint, apiKey, fullPrompt);

                    // 显示结果
                    aiResultContent.textContent = aiResult;
                    aiResultArea.style.display = 'block';
                    showStatus('AI文本生成成功', false, 'ai');

                    // 确保搜索相关元素状态正常恢复
                    setTimeout(() => {
                        const searchInput = document.getElementById('search-movie');
                        const fetchBtn = document.getElementById('fetch-btn');
                        const mediaUrlInput = document.getElementById('media-url');

                        if (mediaUrlInput && fetchBtn) {
                            // 确保获取按钮状态正常
                            if (mediaUrlInput.value.trim()) {
                                fetchBtn.classList.add('active'); // 使用active类而不是display属性
                                fetchBtn.style.display = 'block';
                            } else {
                                fetchBtn.classList.remove('active');
                                fetchBtn.style.display = 'none';
                            }
                        }

                        // 重置搜索结果状态,确保搜索功能可以正常使用
                        if (mediaUrlInput) {
                            // 不清除用户已经输入的URL,但确保交互功能可用
                            setupSearchInteractions();
                        }
                    }, 500);
                } catch (error) {
                    console.error('AI生成失败:', error);
                    showStatus(`AI生成失败:${error.message || '未知错误'}`, true, 'ai');
                } finally {
                    // 恢复按钮状态
                    generateAiTextBtn.disabled = false;
                    generateAiTextBtn.innerHTML = '<i class="fa fa-magic" style="margin-right:5px;"></i>生成AI文本';
                    isGenerating = false;
                    if (abortAiBtn) abortAiBtn.style.display = 'none';
                }
            });
            aiEventsBound = true;
        }

        // 终止按钮
        if (abortAiBtn) {
            abortAiBtn.addEventListener('click', function(e){
                e.stopPropagation();
                e.preventDefault();
                if (aiCurrentRequest && typeof aiCurrentRequest.abort === 'function') {
                    try { aiCurrentRequest.abort(); } catch (_) {}
                }
                if (typeof aiAbortReject === 'function') {
                    try { aiAbortReject(new Error('已终止')); } catch (_) {}
                }
                abortAiBtn.style.display = 'none';
                showStatus('已终止AI生成', true, 'ai');
            });
        }

        // 清理按钮:重置AI结果、候选与搜索状态
        const aiClearBtn = document.getElementById('ai-clear');
        if (aiClearBtn) {
            aiClearBtn.addEventListener('click', function(e){
                e.stopPropagation();
                e.preventDefault();
                try {
                    if (aiResultArea) { aiResultArea.style.display = 'none'; }
                    if (aiResultContent) { aiResultContent.textContent = ''; }
                    const poster = document.getElementById('ai-poster-candidates');
                    const still = document.getElementById('ai-still-candidates');
                    if (poster) poster.innerHTML = '';
                    if (still) still.innerHTML = '';
                    aiSelectedPosterUrls.clear();
                    aiSelectedStillUrls.clear();
                    const aiSearchInputEl = document.getElementById('ai-search-input');
                    const aiSearchResultsEl = document.getElementById('ai-search-results');
                    if (aiSearchInputEl) aiSearchInputEl.value = '';
                    if (aiSearchResultsEl) { aiSearchResultsEl.innerHTML=''; aiSearchResultsEl.style.display='none'; }
                    selectedPosterUrl = '';
                    selectedStillUrl = '';
                    showStatus('已清理AI结果与候选区', false, 'ai');
                } catch (_) {}
            });
        }

        // 复制AI结果
        if (copyAiResultBtn) {
            copyAiResultBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                e.preventDefault();
                const resultText = aiResultContent.textContent;
                if (resultText) {
                    GM_setClipboard(resultText);
                    showStatus('AI生成结果已复制到剪贴板', false, 'ai');
                }
            });
        }

        // 插入AI结果到编辑框
        if (insertAiResultBtn) {
            insertAiResultBtn.addEventListener('click', async function(e) {
                e.stopPropagation();
                e.preventDefault();
                const resultText = aiResultContent.textContent;
                if (!resultText) {
                    showStatus('没有可插入的AI生成结果', true, 'ai');
                    return;
                }
                const ok = await writeHtmlToAnyEditor(resultText);
                try { await autoClickSaveBtn(); } catch(_) {}
                showStatus(ok ? 'AI生成结果已插入并保存' : '插入失败,已提供剪贴板备份', !ok, 'ai');
            });
        }
        }

        // 用户AI预设模板(内置)
        try {
            if (!window.AI_PRESET_TEMPLATE) {
                window.AI_PRESET_TEMPLATE = `<div style="max-width: 820px; margin: 28px auto; font-family: 'Noto Sans SC', sans-serif; color: #1e293b; background: #ffffff; padding: 0 20px;">
  <!-- 主标题:深松绿主色+双线边框,区别用户的单虚线/纯色边框 -->
  <h2 style="
    text-align: center;
    font-size: 27px;
    color: #2c5f2d;
    border-bottom: 2px double #97bc62;
    padding: 14px 0;
    margin: 0 0 28px 0;
    letter-spacing: 1px;
  ">【新海诚治愈神作】你的名字。(君の名は。)</h2>

  <!-- 海报+信息卡容器:浅灰蓝背景+深松绿边框,质感柔和且无重复色 -->
  <div style="
    border: 2px solid #2c5f2d;
    border-radius: 12px;
    padding: 18px;
    margin: 0 0 28px 0;
    background: #e6f4ea;
  ">
    <!-- 主海报:深松绿边框+轻微阴影,贴合电影自然氛围 -->
    <div style="text-align: center; margin-bottom: 18px;">
      <img
        src="https://via.placeholder.com/620x420/2c5f2d/FFF?text=Your+Name"
        alt="你的名字。电影海报"
        style="max-width: 100%; border-radius: 8px; border: 2px solid #2c5f2d; box-shadow: 0 4px 10px rgba(44,95,45,0.15);"
      >
      <p style="color: #2c5f2d; font-size: 15px; font-weight: 600; margin-top: 10px; margin-bottom: 0;">你的名字。主视觉海报(彗星与系守镇)</p>
    </div>

    <!-- 信息卡:纯白底+浅松绿边框,信息层级清晰,文字色无重复 -->
    <div style="background: #ffffff; padding: 18px; border-radius: 10px; border: 1px solid #97bc62;">
      <p style="font-size: 17px; color: #1e293b; margin: 10px 0;"><strong>电影名称:</strong>你的名字。(君の名は。)</p>
      <p style="font-size: 17px; color: #1e293b; margin: 10px 0;"><strong>导演:</strong>新海诚</p>
      <p style="font-size: 17px; color: #1e293b; margin: 10px 0;"><strong>类型:</strong>动画 &middot; 爱情 &middot; 奇幻</p>
      <p style="font-size: 17px; color: #1e293b; margin: 10px 0;"><strong>上映时间:</strong>2016-08-26(日本) / 2016-12-02(中国大陆)</p>
      <p style="font-size: 17px; color: #1e293b; margin: 10px 0;"><strong>豆瓣评分:</strong> <span style="color: #fff; background: #2c5f2d; padding: 3px 10px; border-radius: 16px; font-weight: 600;">8.5</span></p>
      <p style="font-size: 17px; color: #1e293b; margin: 10px 0;"><strong>核心元素:</strong>身体互换 &middot; 时空交错 &middot; 结绳传说</p>
    </div>
  </div>

  <!-- 电影剧情:浅灰蓝背景+深松绿左粗边,突出治愈感,标题下划线创新 -->
  <h3 style="
    font-size: 19px;
    color: #2c5f2d;
    font-weight: 600;
    text-decoration: underline wavy #97bc62;
    margin: 28px 0 18px 0;
  ">【电影剧情】</h3>
  <div style="
    background: #e6f4ea;
    border-left: 4px solid #2c5f2d;
    padding: 18px;
    border-radius: 8px;
    margin: 0 0 28px 0;
  ">
    <p style="margin: 12px 0; line-height: 1.8;">住在东京的少年泷,某天醒来发现自己变成了陌生少女的身体——她是住在深山小镇“系守镇”的三叶。与此同时,三叶也在泷的身体里醒来,面对繁华的东京街头手足无措。两人开始通过日记、便签交流,在彼此的生活里“扮演”对方:泷帮三叶拯救濒临废弃的神社,三叶帮泷赢得暗恋前辈的好感。</p>
    <p style="margin: 12px 0; line-height: 1.8;">随着了解加深,情愫渐生,可他们从未见过面。直到某天,身体互换突然停止,泷发现三叶所在的系守镇,竟在三年前的彗星撞击中消失。为了拯救三叶和小镇,他带着仅存的记忆踏上寻找之旅,在神社的“御神体”前,通过结绳的力量穿越时空,与三叶在黄昏之时(たそがれ)相遇——那是“非日非夜,非人非鬼”的特殊时刻,也是他们跨越时空的唯一交集。</p>
  </div>

  <!-- 经典画面:深松绿边框+圆角,图片加阴影更显质感,说明文字更细腻 -->
  <h3 style="
    font-size: 19px;
    color: #2c5f2d;
    font-weight: 600;
    text-decoration: underline wavy #97bc62;
    margin: 28px 0 18px 0;
  ">【经典画面】</h3>
  <div style="
    border: 2px solid #2c5f2d;
    border-radius: 12px;
    padding: 18px;
    margin: 0 0 28px 0;
    text-align: center;
  ">
    <img
      src="https://via.placeholder.com/620x320/2c5f2d/FFF?text=Kimi+no+Na+wa+Twilight"
      alt="黄昏之时相遇场景"
      style="max-width: 100%; border-radius: 8px; display: inline-block; box-shadow: 0 4px 10px rgba(44,95,45,0.15);"
    >
    <p style="color: #2c5f2d; font-size: 15px; font-weight: 600; margin-top: 10px;">“黄昏之时”——泷与三叶跨越时空触碰的瞬间(结绳缠绕的手是关键伏笔)</p>
  </div>

  <!-- 观众热评:纯白底+浅松绿边框,评论文字带情绪感,作者信息更有设计感 -->
  <h3 style="
    font-size: 19px;
    color: #2c5f2d;
    font-weight: 600;
    text-decoration: underline wavy #97bc62;
    margin: 28px 0 18px 0;
  ">【观众热评】</h3>
  <div style="
    background: #ffffff;
    padding: 18px;
    border-radius: 10px;
    border: 1px solid #97bc62;
    margin: 0 0 28px 0;
  ">
    <p style="margin: 0 0 18px 0; font-weight: 500; color: #2c5f2d; font-size: 17px; line-height: 1.6;">“第一次看时没懂结绳的意义,二刷才发现:它是时间的象征,是三叶和泷的羁绊,也是拯救小镇的关键。新海诚太会把细腻的情感藏在画面里了——最后两人在街头问‘你的名字是?’时,我哭了半小时。”</p>
    <p style="margin: 0; text-align: right; color: #0f5132; font-style: italic; font-size: 16px; border-top: 1px dashed #97bc62; padding-top: 10px;">—— 豆瓣用户 @星尘收集者</p>
  </div>

  <!-- 观影提示:浅灰蓝背景+居中排版,增加独家细节建议,提升实用性 -->
  <p style="
    font-size: 17px;
    color: #1e293b;
    text-align: center;
    margin: 32px 0;
    padding: 14px;
    background-color: #e6f4ea;
    border-radius: 8px;
    line-height: 1.8;
  ">
    【观影提示】① 建议留意“结绳”“口嚼酒”“黄昏之时”三个关键元素,它们是串联时空的伏笔;② 搭配RADWIMPS的原声《前前前世》观看,音乐响起时会更沉浸;③ 结尾的“名字”梗适合二刷回味——你会发现,两人的羁绊早有伏笔。
  </p>
</div>`;
            }
        } catch (e) {}

        // 根据类型获取AI提示词
    function getAIPromptByType(type, userPrompt, movieContext) {
        // 获取详细排版指南
        const { POST_FORMAT_GUIDELINES } = DEFAULT_CONFIG.AI;

        const prompts = {
            summary: `请根据用户需求和提供的影视信息,生成一个高质量的剧情简介。\n用户需求:${userPrompt}${movieContext}`,
            comment: `请根据用户需求和提供的影视信息,生成一个专业、有深度的评论摘要。\n用户需求:${userPrompt}${movieContext}`,
            tagline: `请根据用户需求和提供的影视信息,生成几个吸引人的宣传标语。\n用户需求:${userPrompt}${movieContext}`,
            analysis: `请根据用户需求和提供的影视信息,生成一个深入的分析。\n用户需求:${userPrompt}${movieContext}`,

            // 影视资源帖排版美化智能体框架功能提示词 - 增强版
            post_format: `作为专业的影视资源帖排版美化智能体,你需要基于编辑器提供的源代码内容,结合用户需求和影视信息,生成一个高度精美的HTML排版方案。\n\n用户需求:${userPrompt}\n\n【强制要求】\n请严格按照以下要求输出:\n1. 只返回完整的HTML代码,不要包含任何额外的文字说明、解释或注释\n2. 确保HTML代码是格式正确、可直接使用的,不要返回源代码形式的HTML\n3. 所有样式必须使用内联CSS,不要使用外部样式表\n4. 生成的HTML代码应直接展示为格式化的内容,而不是显示HTML标签\n\n【内容处理优先级】\n1. 优先使用编辑器内容作为基础进行美化排版\n2. 当编辑器内容不足时,结合影视信息进行补充\n3. 最后根据用户需求进行调整\n\n【核心样式和结构要求】\n请确保最终生成的HTML代码包含以下关键设计元素:\n1. **整体容器**:使用max-width: 800px; margin: 25px auto;的居中容器\n2. **主题配色**:根据影片类型选择主题色(动画用活泼色如#a2d2ff、电影用质感色如#2a9d8f、剧集用柔和色)\n3. **标题样式**:使用大号字体、主色、下边框装饰,如:text-align: center; font-size: 26px; color: #2a9d8f; border-bottom: 2px dashed #e9c46a;\n4. **海报区域**:使用带边框的居中海报,如:border: 2px solid #e9c46a; border-radius: 10px; text-align: center;\n5. **信息卡**:使用白色背景、圆角边框的信息卡,如:background: #fff; padding: 15px; border-radius: 8px; border: 1px solid #e2e8f0;\n6. **评分样式**:使用主色背景的标签式评分,如:color: #fff; background: #2a9d8f; padding: 2px 8px; border-radius: 15px;\n7. **内容分区**:使用下划线虚线的子标题区分不同内容模块,如:text-decoration: underline dotted #e9c46a;\n8. **影评区域**:官方影评使用主色左侧边框,用户评论使用次要色左侧边框,如:border-left: 4px solid #2a9d8f;\n9. **合规提示**:使用浅色背景的合规提示框,如:background-color: #f8f9fa; border-radius: 5px;\n\n【内容模块要求】\n请包含以下完整模块结构:\n1. **标题区**:精美装饰的主标题,包含影片名称和类型标签\n2. **海报展示**:高清海报展示,包含来源标注\n3. **信息卡**:完整的影视参数,包括导演、主演、类型、上映日期、评分等\n4. **剧情简介**:清晰的剧情描述,可选择性使用折叠面板\n5. **经典场景**:剧照展示区域\n6. **观众热评**:官方推荐和用户评论区,区分不同评论类型\n7. **观影提示**:观影建议和注意事项\n8. **合规声明**:支持正版影视的声明\n\n【技术实现要求】\n- 所有样式使用内联CSS,确保兼容性\n- 使用Microsoft Yahei等中文字体,保证可读性\n- 确保文本内容完整、准确、流畅\n- 使用适当的间距和留白,避免内容拥挤\n- 确保所有模块都有明确的视觉边界和层次感${movieContext}`,

            content_optimize: `作为专业的内容优化助手,你需要根据用户需求和影视信息,提供详细的内容优化建议。\n\n用户需求:${userPrompt}\n\n优化方向:\n1. **SEO优化**:合理融入影片关键词、类型词、导演演员名称等\n2. **流量优化**:\n   - 标题使用吸引人的表述,包含影片亮点\n   - 开头段落简明扼要,突出核心吸引力\n   - 使用emoji或特殊标记提升内容可辨识度(如适用)\n3. **合规优化**:\n   - 替换敏感表述:将"百度云"替换为"合规平台","免费观看"改为"正版渠道观看"\n   - 检查影评内容,确保无侵权引用,保留必要的作者署名\n4. **结构优化**:\n   - 调整信息呈现顺序,重要内容前置\n   - 使用合适的标题层级和排版元素划分内容\n   - 增加可读性:剧情文本行高设为1.7倍,段落间距20px\n\n多平台适配建议:\n- 掘金:保留代码高亮,优化图片懒加载\n- 微信公众号:简化样式,优化防盗链格式\n- 知乎:优化首图尺寸,调整段落间距${movieContext}`,

            format_check: `作为专业的排版合规检查工具,你需要根据用户需求和影视信息,对内容进行全面的合规性检查。\n\n用户需求:${userPrompt}\n\n检查重点:\n1. **版权检查**:\n   - 海报是否为官方发布的宣传海报,避免使用影院偷拍的正片截图\n   - 是否在图片说明中注明"用于影视推荐合理使用"\n   - 用户影评是否注明来源,专业影评引用是否保留作者署名且不超过原文1/3\n   - 资源链接是否仅推荐正规视频平台(如腾讯视频、爱奇艺等)\n2. **敏感词检查**:\n   - 扫描是否包含"盗版"、"枪版"、"百度云"、"网盘"等风险词汇\n   - 检查影评中是否有过激表述或不当言论\n3. **排版结构检查**:\n   - 模块顺序是否合理,是否包含完整的头图、信息卡、剧情、影评等核心模块\n   - 样式是否统一,间距、字体、颜色等是否符合规范\n   - 响应式设计是否完善,在375px、768px、1200px断点下是否正常显示\n4. **平台规则检查**:\n   - 是否避免使用特殊符号(如★、→等)\n   - 评分是否使用文本或CSS实现而非emoji\n   - 是否包含"支持正版影视"的合规声明\n\n请生成详细的检查报告,指出问题并提供修改建议${movieContext}`,

            modular_design: `作为专业的模块化排版设计师,你需要根据用户需求和影视信息,设计一个完整的模块化排版方案。\n\n用户需求:${userPrompt}\n\n设计原则:\n1. **分章节展示**:\n   - 头图区:自适应海报容器,16:9比例,包含来源标注\n   - 信息卡区:网格布局,展示导演、类型、上映日期、评分等核心参数\n   - 剧情简介区:防剧透折叠面板,分安全版和完整版\n   - 影评区:区分官方推荐和用户评论,使用不同样式标识\n   - 资源提示区:合规声明和正规平台链接推荐\n2. **醒目重点**:\n   - 使用主题色突出标题和重要信息\n   - 关键内容使用加粗或背景高亮(background:#fff380;padding:0 3px;border-radius:2px)\n   - 评分使用主题色背景的标签样式\n3. **便于阅读**:\n   - 统一使用"Microsoft Yahei, sans-serif"字体\n   - 正文行高1.7倍,段落间距20px\n   - 使用列表和分隔线组织内容,提升可读性\n4. **视觉层次**:\n   - 建立清晰的标题层级(h1>h2>h3)\n   - 使用不同的边框、背景色区分不同类型的内容模块\n   - 合理使用空白区域,避免内容过于拥挤\n\n请提供详细的HTML和CSS代码示例,包括各模块的具体实现${movieContext}`,
            free_text: `${userPrompt}${movieContext}`
        };

        let base = prompts[type] || `请根据用户需求生成内容。\n用户需求:${userPrompt}${movieContext}`;
        // 统一追加图片占位说明,避免AI输出真实图片链接(支持精确放置)
        base += `\n\n[排版占位规则]\n请勿在内容中粘贴任何图片URL。可用占位符:\n- {#POSTER#}: 主海报(可选,仅1次)\n- {#IMG1#}..{#IMGN#}: 我会按你给出的编号依次替换为已选剧照(逐一放置,适合自定义布局)\n- {#STILLS#}: 若未使用逐一占位,使用此占位一次性放入所有剧照(我会做自适应流式布局)。`;
        return base;
    }
    // 调用AI API生成文本
    async function generateAIText(apiEndpoint, apiKey, prompt) {
        return new Promise((resolve, reject) => {
            // 获取配置的模型名称和提供商
            const config = getConfig();
            const modelName = config.AI.DEFAULT_MODEL;
            const provider = config.AI.PROVIDER;

            // 判断是否为排版美化相关功能
            const isFormatRelated = prompt.includes('排版美化') || prompt.includes('内容优化') || prompt.includes('排版合规') || prompt.includes('模块化排版');

            // 根据功能类型设置不同的系统提示
            const roleConfig = getAIRoleConfig();
            let systemPrompt = generateSystemPrompt(roleConfig, isFormatRelated);
            // 深度思考/联网补充(仅在支持时生效)
            try {
                const deep = document.getElementById('ai-deep-think');
                const web = document.getElementById('ai-web-browse');
                if (deep && !deep.disabled && deep.checked) {
                    systemPrompt += '\n请在生成前进行结构化深度思考与多步推理,先在脑内列出要点再输出结果。';
                }
                if (web && !web.disabled && web.checked) {
                    systemPrompt += '\n如信息明显缺失或不确定,可模拟联网补充(无需真实请求),在结果中补全缺失信息并标注来源类型。';
                }
            } catch(_) {}
            let max_tokens = 1000;

            if (isFormatRelated) {
                // 排版相关功能通常需要更长的输出内容
                max_tokens = 2000;
            }

            // 根据不同的AI提供商构建适当的请求体
            let requestBody = {};

            // 检查AI提供商类型,使用不同的请求格式
            if (provider === 'gemini' || apiEndpoint.includes('gemini')) {
                // Gemini API格式
                requestBody = {
                    contents: [{
                        parts: [{
                            text: prompt
                        }]
                    }],
                    generationConfig: {
                        maxOutputTokens: max_tokens,
                        temperature: 0.7
                    }
                };
            } else if (provider === 'claude' || apiEndpoint.includes('claude')) {
                // Claude API格式
                requestBody = {
                    model: modelName,
                    messages: [
                        { role: 'system', content: systemPrompt },
                        { role: 'user', content: prompt }
                    ],
                    max_tokens_to_sample: max_tokens,
                    temperature: 0.7
                };
            } else if (provider === 'glm4' || apiEndpoint.includes('bigmodel')) {
                // 智谱AI API格式
                requestBody = {
                    model: modelName,
                    prompt: {
                        text: prompt
                    },
                    parameters: {
                        max_tokens: max_tokens,
                        temperature: 0.7
                    }
                };
            } else if (provider === 'qwen' || apiEndpoint.includes('aliyuncs')) {
                // 通义千问API格式
                requestBody = {
                    model: modelName,
                    messages: [
                        { role: 'system', content: systemPrompt },
                        { role: 'user', content: prompt }
                    ],
                    max_tokens: max_tokens,
                    temperature: 0.7
                };
            } else if (provider === 'xunfei' || apiEndpoint.includes('xf-yun')) {
                // 讯飞星火API格式
                requestBody = {
                    header: {
                        app_id: apiKey.split('.')[0], // 假设app_id在apiKey的第一部分
                        uid: 'user'
                    },
                    parameter: {
                        chat: {
                            domain: 'general',
                            temperature: 0.7,
                            max_tokens: max_tokens
                        }
                    },
                    payload: {
                        message: {
                            text: [
                                { role: 'system', content: systemPrompt },
                                { role: 'user', content: prompt }
                            ]
                        }
                    }
                };
            } else if (provider === 'ark' || apiEndpoint.includes('doubao')) {
                // 豆包API格式
                requestBody = {
                    model: modelName,
                    messages: [
                        { role: 'system', content: systemPrompt },
                        { role: 'user', content: prompt }
                    ],
                    max_tokens: max_tokens,
                    temperature: 0.7
                };
            } else if (provider === 'together' || apiEndpoint.includes('together')) {
                // Together AI格式
                requestBody = {
                    model: modelName,
                    messages: [
                        { role: 'system', content: systemPrompt },
                        { role: 'user', content: prompt }
                    ],
                    max_tokens: max_tokens,
                    temperature: 0.7
                };
            } else {
                // 默认使用OpenAI API格式
                requestBody = {
                    model: modelName,
                    messages: [
                        { role: 'system', content: systemPrompt },
                        { role: 'user', content: prompt }
                    ],
                    max_tokens: max_tokens,
                    temperature: 0.7
                };
            }

            // 构建请求头 - 根据不同提供商处理认证
            const headers = {
                'Content-Type': 'application/json'
            };

            // 根据AI提供商设置正确的认证方式
            if (apiKey) {
                // 提供商特定的认证方式
                if (provider === 'ark' || apiEndpoint.includes('doubao')) {
                    // 豆包API使用的认证方式
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'claude' || apiEndpoint.includes('claude')) {
                    // Claude API认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'gemini' || apiEndpoint.includes('gemini')) {
                    // Gemini API认证
                    headers['x-goog-api-key'] = apiKey;
                } else if (provider === 'github' || apiEndpoint.includes('github')) {
                    // GitHub模型市场认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'xunfei' || apiEndpoint.includes('xf-yun')) {
                    // 讯飞星火认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'qwen' || apiEndpoint.includes('aliyuncs')) {
                    // 通义千问认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'glm4' || provider === 'legalglm' || apiEndpoint.includes('bigmodel')) {
                    // 智谱AI认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'huggingface' || apiEndpoint.includes('huggingface')) {
                    // Hugging Face认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'together' || apiEndpoint.includes('together')) {
                    // Together AI认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'baishan' || apiEndpoint.includes('baishanai')) {
                    // 白山云认证
                    headers['Authorization'] = `Bearer ${apiKey}`;
                } else if (provider === 'gpt4free' || apiEndpoint.includes('gpt4free')) {
                    // 一些免费API可能不需要标准Bearer格式
                    headers['Authorization'] = apiKey;
                } else {
                    // 默认认证方式(OpenAI兼容)
                    headers['Authorization'] = `Bearer ${apiKey}`;
                }
            }

            // 发送请求
            console.log(`AI API请求 - 端点: ${apiEndpoint}, 提供商: ${provider}, 模型: ${modelName}`);
            console.log(`请求头:`, headers);
            console.log(`请求体结构:`, JSON.stringify(requestBody).substring(0, 500) + (JSON.stringify(requestBody).length > 500 ? '...' : ''));

            // 验证API端点格式
            try {
                new URL(apiEndpoint);
            } catch (e) {
                throw new Error(`API端点格式无效:${apiEndpoint}\n请检查配置的API端点是否为有效的URL格式`);
            }

            // 发起请求并保存控制句柄
            aiAbortReject = reject;
            const req = GM_xmlhttpRequest({
                method: 'POST',
                url: apiEndpoint,
                headers: headers,
                data: JSON.stringify(requestBody),
                onload: (response) => {
                    try {
                        console.log(`API响应状态码: ${response.status}`);
                        console.log(`API响应头:`, response.responseHeaders);

                        // 检查响应状态
                        if (response.status < 200 || response.status >= 400) {
                            let errorMsg = `请求失败:HTTP ${response.status}`;

                            // 特殊处理404错误
                            if (response.status === 404) {
                                errorMsg = `请求失败:HTTP 404\nAPI端点不存在或无效: ${apiEndpoint}\n请检查配置的API端点是否正确,不同AI提供商的API端点格式可能不同`;

                                // 根据提供商类型提供更具体的建议
                                if (provider === 'openai') {
                                    errorMsg += '\nOpenAI API端点格式应为: https://api.openai.com/v1/chat/completions';
                                } else if (provider === 'claude') {
                                    errorMsg += '\nClaude API端点格式应为: https://api.anthropic.com/v1/messages';
                                } else if (provider === 'gemini') {
                                    errorMsg += '\nGemini API端点格式应为: https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent';
                                }
                            }

                            try {
                                const errorData = JSON.parse(response.responseText);
                                if (errorData.error && errorData.error.message) {
                                    errorMsg = errorData.error.message;
                                    // 特殊处理模型访问错误
                                    if (errorMsg.includes('model does not exist') || errorMsg.includes('not have access')) {
                                        errorMsg = `模型访问失败:${errorMsg}\n请在AI配置中更换为您有权限访问的模型`;
                                    }
                                    // 特殊处理认证错误
                                    if (errorMsg.includes('Invalid bearer token') ||
                                        errorMsg.includes('API key format is incorrect') ||
                                        errorMsg.includes('authentication')) {
                                        errorMsg = `认证失败:${errorMsg}\n请检查API密钥格式是否正确,不同AI提供商可能有不同的密钥格式要求`;
                                    }
                                }
                            } catch (e) {
                                // 如果解析错误信息失败,使用原始错误
                                console.error('解析错误响应失败:', e);
                            }
                            throw new Error(errorMsg);
                        }

                        const data = JSON.parse(response.responseText);

                        // 处理不同API的响应格式
                        let resultText = '';
                        if (data.choices && data.choices.length > 0) {
                            // OpenAI、通义千问、讯飞星火等API格式
                            resultText = data.choices[0].message?.content || data.choices[0].text || '';
                        } else if (data.result) {
                            // GLM-4、豆包等API格式
                            resultText = data.result;
                        } else if (data.text) {
                            // Together AI等API格式
                            resultText = data.text;
                        } else if (data.candidates && data.candidates.length > 0) {
                            // Gemini API格式
                            resultText = data.candidates[0].content?.parts?.[0]?.text || '';
                        } else if (Array.isArray(data) && data.length > 0 && data[0].generated_text) {
                            // Hugging Face API格式
                            resultText = data[0].generated_text || '';
                        } else if (data.output?.choices && data.output.choices.length > 0) {
                            // 其他API格式
                            resultText = data.output.choices[0].text || '';
                        } else {
                            throw new Error('未找到有效结果');
                        }

                        if (!resultText.trim()) {
                            throw new Error('AI返回了空结果');
                        }

                        // 去除三引号围栏 ```xxx 开头/结尾
                        let cleaned = resultText.trim();
                        cleaned = cleaned.replace(/^```[a-zA-Z]*\n/, '').replace(/\n```$/, '');
                        // 将占位符替换为真实图片HTML
                        const pickPoster = () => {
                            try {
                                const list = Array.from(aiSelectedPosterUrls || []);
                                let url = list[0] || '';
                                try { url = toTMDBOriginal(url); } catch(_) {}
                                return url || '';
                            } catch(_) { return ''; }
                        };
                        const pickStills = () => {
                            try {
                                const list = Array.from(aiSelectedStillUrls || []);
                                return (list && list.length? list : []).slice(0,6);
                            } catch(_) { return []; }
                        };
                        if (cleaned.includes('{#POSTER#}')) {
                            const p = pickPoster();
                            const posterHtml = p ? `<div style="text-align:center;margin:12px 0;"><img data-ai-img="1" src="${p}" alt="海报" style="max-width:100%;height:auto;border-radius:10px;box-shadow:0 2px 10px rgba(0,0,0,.08);display:block;"/></div>` : '';
                            // 只替换第一次,其他占位清空,避免重复
                            cleaned = cleaned.replace('{#POSTER#}', posterHtml);
                            cleaned = cleaned.replace(/\{#POSTER#\}/g, '');
                        }
                         if (cleaned.includes('{#STILLS#}') || /\{#IMG\d+#\}/.test(cleaned)) {
                            const arr = pickStills();
                            let html = '';
                            const n = Array.isArray(arr) ? arr.length : 0;
                            const toImg = (u, radius='10px') => {
                                const src = toTMDBOriginal ? toTMDBOriginal(u) : u;
                                return `<img data-ai-img="1" src="${src}" alt="剧照" style="width:100%;height:auto;border-radius:${radius};object-fit:cover;display:block;"/>`;
                            };
                             // 若AI使用精确占位 {#IMGn#},则按编号逐张替换,给足自由编排空间
                             if (/\{#IMG\d+#\}/.test(cleaned) && n > 0) {
                                 let placed = cleaned;
                                 for (let i = 0; i < n; i++) {
                                     const tag = new RegExp(`\\{#IMG${i+1}#\\}`,'g');
                                     placed = placed.replace(tag, toImg(arr[i]));
                                 }
                                 // 清理未用完的编号占位
                                 placed = placed.replace(/\{#IMG\d+#\}/g, '');
                                 cleaned = placed;
                             }
                            if (n === 1) {
                                html = arr[0] ? `<div style="text-align:center;margin:16px 0;">${toImg(arr[0],'12px')}</div>` : '';
                            } else if (n === 2) {
                                html = `<div style="display:grid;width:100%;grid-template-columns:repeat(2,1fr);gap:16px;margin:16px 0;">${toImg(arr[0])}${toImg(arr[1])}</div>`;
                            } else if (n === 3) {
                                // 上1下2,避免右侧空白
                                const top = arr[0] ? `<div style=\"margin:0 0 14px 0;\">${toImg(arr[0],'12px')}</div>` : '';
                                const bottom = `<div style=\"display:grid;width:100%;grid-template-columns:repeat(2,1fr);gap:16px;\">${toImg(arr[1])}${toImg(arr[2])}</div>`;
                                html = `<div style="width:100%;margin:16px 0;">${top}${bottom}</div>`;
                            } else if (n === 4) {
                                html = `<div style="display:grid;width:100%;grid-template-columns:repeat(2,1fr);gap:16px;margin:16px 0;">${arr.map(u=>toImg(u)).join('')}</div>`;
                            } else if (n === 5) {
                                // 上1(大图)+ 下4(2列)
                                const top = `<div style=\"margin:0 0 14px 0;\">${toImg(arr[0],'12px')}</div>`;
                                const rest = `<div style=\"display:grid;width:100%;grid-template-columns:repeat(2,1fr);gap:16px;\">${arr.slice(1).map(u=>toImg(u)).join('')}</div>`;
                                html = `<div style="width:100%;margin:16px 0;">${top}${rest}</div>`;
                            } else if (n >= 6) {
                                html = `<div style="display:grid;width:100%;grid-template-columns:repeat(3,1fr);gap:16px;margin:16px 0;">${arr.map(u=>toImg(u)).join('')}</div>`;
                            }
                             // 若未使用{#IMGn#},再处理{#STILLS#} 的一次性替换
                             if (cleaned.includes('{#STILLS#}')) {
                                 cleaned = cleaned.replace('{#STILLS#}', html);
                                 cleaned = cleaned.replace(/\{#STILLS#\}/g, '');
                             }
                        }
                        // 清理非占位符产生的多余<img>与孤立属性片段
                        try {
                            cleaned = cleaned.replace(/<img(?![^>]*data-ai-img=\"1\")[^>]*>/gi, '');
                            cleaned = cleaned.replace(/\salt=\"[^\"]*\"[^>]*>/gi, '>');
                        } catch(_) {}
                        resolve(cleaned.trim());
                    } catch (error) {
                        console.error('解析AI响应失败:', error, response.responseText);
                        reject(new Error(`解析响应失败:${error.message}`));
                    }
                },
                onerror: (error) => {
                    console.error('AI API请求失败:', error);
                    reject(new Error(`网络请求失败:${error.message || '未知错误'}`));
                },
                ontimeout: () => {
                    reject(new Error('AI API请求超时'));
                }
            });
            aiCurrentRequest = req;
        });
    }

    // 初始化页面
    function init() {
        // 立即禁用所有表单验证
        disableAllFormValidation();

        // 加载Font Awesome图标(确保美化工具图标正常显示)
        const faLink = document.createElement('link');
        faLink.rel = 'stylesheet';
        faLink.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css';
        faLink.crossOrigin = 'anonymous'; // 解决跨域加载问题

        // 确保head存在才添加
        if (document.head) {
            document.head.appendChild(faLink);
        } else {
            // 如果head还没加载,延迟添加
            setTimeout(() => {
                if (document.head) {
                    document.head.appendChild(faLink);
                }
            }, 100);
        }

        // 插入控制面板(精准位置+空值修复)
        insertPanelInMarkedPosition();

        // 检查是否有默认URL(从URL参数中获取)
        const urlParams = new URLSearchParams(window.location.search);
        const mediaUrl = urlParams.get('mediaUrl');
        if (mediaUrl && document.getElementById('media-url')) {
            document.getElementById('media-url').value = mediaUrl;
            const fetchBtn = document.getElementById('fetch-btn');
            // 根据输入框内容设置提取按钮状态
            if (fetchBtn) {
                const mediaUrlInput = document.getElementById('media-url');
                if (mediaUrlInput && mediaUrlInput.value.trim()) {
                    fetchBtn.classList.add('active');
                } else {
                    fetchBtn.classList.remove('active');
                }
            }
        }
    }

    // 启动脚本
    init();

    // 额外的安全检查 - 确保switchTab函数在全局作用域可访问
    setTimeout(function() {
        if (typeof window.switchTab !== 'function') {
            // 如果window上没有switchTab函数,尝试重新暴露
            if (typeof unsafeWindow !== 'undefined') {
                window.switchTab = unsafeWindow.switchTab || switchTab;
            } else {
                window.switchTab = switchTab;
            }
        }

        // 修复HTML中的onclick属性调用
        const tabButtons = document.querySelectorAll('[onclick^="switchTab("]');
        tabButtons.forEach(button => {
            const originalOnclick = button.getAttribute('onclick');
            if (originalOnclick) {
                // 提取tabId参数
                const match = originalOnclick.match(/switchTab\('([^']+)'\)/);
                if (match && match[1]) {
                    const tabId = match[1];
                    // 移除原始的onclick属性
                    button.removeAttribute('onclick');
                    // 使用addEventListener添加点击事件
                    button.addEventListener('click', function(e) {
                        e.stopPropagation();
                        e.preventDefault();
                        if (typeof window.switchTab === 'function') {
                            window.switchTab(tabId);
                        } else if (typeof document.switchTab === 'function') {
                            document.switchTab(tabId);
                        }
                    });
                }
            }
        });
    }, 100);

    // ========== AI角色配置系统(保留内部使用,移除UI入口) ==========
    // 影视类型色彩配置
    const MOVIE_GENRE_COLORS = {
        horror: { name: '恐怖', primary: '#2d3142', secondary: '#ef8354', lightBg: '#f5f5f5', text: '#333333' },
        romance: { name: '爱情', primary: '#f8b195', secondary: '#f8e1d1', lightBg: '#fff8f5', text: '#8b4513' },
        action: { name: '动作', primary: '#335c67', secondary: '#e09f3e', lightBg: '#f9f7f1', text: '#3a3a3a' },
        drama: { name: '剧情', primary: '#3a0ca3', secondary: '#4361ee', lightBg: '#f8f9ff', text: '#333333' },
        comedy: { name: '喜剧', primary: '#ffb347', secondary: '#fdfd96', lightBg: '#fffef0', text: '#5d4037' },
        sciFi: { name: '科幻', primary: '#4169e1', secondary: '#87cefa', lightBg: '#f0f8ff', text: '#333333' },
        fantasy: { name: '奇幻', primary: '#9370db', secondary: '#e6e6fa', lightBg: '#f8f5ff', text: '#4a4a4a' },
        anime: { name: '动漫', primary: '#ff69b4', secondary: '#ffb6c1', lightBg: '#fff0f5', text: '#8b4513' },
        documentary: { name: '纪录片', primary: '#708090', secondary: '#d3d3d3', lightBg: '#f5f5f5', text: '#333333' },
        thriller: { name: '惊悚', primary: '#264653', secondary: '#2a9d8f', lightBg: '#f1faee', text: '#333333' },
        adventure: { name: '冒险', primary: '#e9c46a', secondary: '#f4a261', lightBg: '#fffbeb', text: '#5d4037' },
        musical: { name: '歌舞', primary: '#e76f51', secondary: '#f4a261', lightBg: '#fff5f5', text: '#5d4037' }
    };

    // AI角色配置默认值
    const AI_ROLE_DEFAULTS = {
        role: '专注影视资源帖排版美化的创意助手',
        personality: '审美敏锐(懂排版视觉逻辑)、严谨合规(熟平台过滤规则)、高效实用(模块化出稿)、富有创意(适配不同影视风格)',
        style: '简洁直白,用“设计师视角”讲排版思路;重点突出,同时说明“美化效果+合规技巧”;专业术语+通俗表达结合',
        tone: '友好、专业、鼓励性',
        specialRequirements: '1.输出用基础HTML+内联CSS(无复杂框架,多平台可复制);\n2.自动规避特殊符号(如emoji→【】)、敏感词(如“网盘”→“合规路径”);\n3.固定模块:标题区→核心信息卡→影视简介→剧照展示→热评模块→合规提示,每个模块带视觉分层(边框/背景/间距);\n4.配色贴合类型:动画活泼、电影质感、剧集柔和,单帖主色≤3种。',
        // 影视类型偏好配置
        preferredGenre: '',
        autoApplyColors: true,
        // 色彩主题配置
        primaryColor: '#ff69b4',
        secondaryColor: '#ffb6c1',
        lightBgColor: '#fff0f5',
        textColor: '#8b4513',
        // 排版配置
        titleFontSize: 26,
        bodyFontSize: 16,
        lineHeight: 1.8,
        paragraphMargin: 15
    };

    // AI角色模板系统
    const AI_ROLE_TEMPLATES = {
        professional: {
            name: '专业影评人',
            role: '专业的影视内容创作助手和影评人',
            personality: '知识渊博、专业严谨、见解独到',
            style: '深入分析、逻辑清晰、细节丰富、引用专业术语',
            tone: '专业、客观、学术性',
            specialRequirements: '请结合影视理论进行分析,适当引用经典电影案例'
        },
        casual: {
            name: '影视爱好者',
            role: '热情的影视爱好者和推荐人',
            personality: '活泼开朗、热情洋溢、善于表达',
            style: '口语化、亲切自然、情感丰富',
            tone: '友好、热情、有感染力',
            specialRequirements: '请使用轻松愉快的语言,避免过于专业的术语'
        },
        humorous: {
            name: '幽默评论员',
            role: '幽默风趣的影视评论员',
            personality: '幽默风趣、机智活泼、善于调侃',
            style: '诙谐幽默、语言生动、比喻巧妙',
            tone: '轻松、搞笑、充满活力',
            specialRequirements: '请适当加入幽默元素,使用生动有趣的表达方式'
        },
        academic: {
            name: '影视学者',
            role: '严谨的影视研究者和教育者',
            personality: '严谨治学、逻辑严密、学识渊博',
            style: '学术化、系统化、理论深厚',
            tone: '庄重、学术、教导性',
            specialRequirements: '请从学术角度分析,结合相关理论和研究成果'
        },
        postFormatter: {
            name: '影视资源帖排版美化师',
            role: '专注影视资源帖排版美化的创意助手',
            personality: '审美敏锐(懂排版视觉逻辑)、严谨合规(熟悉平台过滤规则)、高效实用(模块化出稿)、富有创意(适配不同影视风格)',
            style: '简洁直白,用"设计师视角"讲排版思路;重点突出,同时说明"美化效果+合规技巧";专业术语+通俗表达结合',
            tone: '友好耐心,像专业排版师一样提供step-by-step指导;鼓励性强,降低用户操作压力',
            specialRequirements: '1.输出用基础HTML+内联CSS(无复杂框架,多平台可复制);\n2.自动规避特殊符号(如emoji→【】)、敏感词(如"网盘"→合规平台);\n3.固定模块:标题区→核心信息→影视简介→剧照展示→热评模块→合规提示,每个模块带视觉分层(边框/背景/间距);\n4.配色贴合类型:动画用活泼色、电影用质感色、剧集用柔和色,单帖主色≤3种。'
        }
    };

    // 生成AI系统提示
    function generateSystemPrompt(roleConfig, isFormatRelated = false) {
        const { role, personality, style, tone, specialRequirements } = roleConfig;

        let basePrompt = `你是${role}。`;
        basePrompt += `你的性格特点是:${personality}。`;
        basePrompt += `你的语言风格是:${style}。`;
        basePrompt += `你的语气是:${tone}。`;

        if (specialRequirements) {
            basePrompt += `特别要求:${specialRequirements}。`;
        }

        if (isFormatRelated) {
            // 平台过滤认知与排版原则(精简版,低Token)
            basePrompt += `\n\n平台过滤:强标准化+安全管控+样式阉割。仅保留基础原子样式;复杂布局/渐变/阴影/圆角/媒体查询等多会失效。结构以table/tr/td与简单div为白名单;外链资源受限,内联style优先。`;
            basePrompt += `\n\n排版原则(6步):\n1) 布局:优先表格;多列用内层table,两列50%均分。\n2) 色彩:单色系三层次(主色10-20%,辅助30-40%,正文#444)。\n3) 分层:统一符号+加粗+字号;正文行高1.8,必要处首行缩进。\n4) 图片:按平台规则统一尺寸,max-width:100%; height:auto。\n5) 间距:统一padding/margin;模块用浅色边框分隔。\n6) 细节:仅用基础元素做精致感(边框/前缀符号/按钮浅底主色字)。`;
        }

        return basePrompt;
    }

    // 获取保存的AI角色配置
    function getAIRoleConfig() {
        try {
            const saved = GM_getValue('ai_role_config', null);
            return saved ? JSON.parse(saved) : { ...AI_ROLE_DEFAULTS };
        } catch (e) {
            console.error('读取AI角色配置失败:', e);
            return { ...AI_ROLE_DEFAULTS };
        }
    }

    // 保存AI角色配置
    function saveAIRoleConfig(config) {
        try {
            GM_setValue('ai_role_config', JSON.stringify(config));
            return true;
        } catch (e) {
            console.error('保存AI角色配置失败:', e);
            return false;
        }
    }

    // 打开AI角色配置界面(开发预览下可用)
    function openAIRoleConfigUI() {
        const config = getAIRoleConfig();

        // 创建配置界面HTML
        const dialogHTML = `
        <div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 50;">
            <div style="background-color: white; border-radius: 8px; padding: 20px; width: 90%; max-width: 700px; max-height: 90vh; overflow-y: auto;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
                    <h2 style="margin: 0;">设置智能体与影视配置</h2>
                    <button id="close-dialog" style="background: none; border: none; font-size: 24px; cursor: pointer;">×</button>
                </div>

                <div style="margin-bottom: 20px;">
                    <label style="display: block; margin-bottom: 10px;">选择智能体模板:</label>
                    <select id="template-select" style="width: 100%; padding: 8px; margin-bottom: 15px;">
                        <option value="custom">自定义</option>
                        <option value="professional">专业影评人</option>
                        <option value="casual">影视爱好者</option>
                        <option value="humorous">幽默评论员</option>
                        <option value="academic">影视学者</option>
                        <option value="postFormatter">影视资源帖排版美化师</option>
                    </select>
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px;">角色定位:</label>
                    <input type="text" id="role-input" value="${config.role}" style="width: 100%; padding: 8px; box-sizing: border-box;">
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px;">性格特点:</label>
                    <input type="text" id="personality-input" value="${config.personality}" style="width: 100%; padding: 8px; box-sizing: border-box;">
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px;">语言风格:</label>
                    <input type="text" id="style-input" value="${config.style}" style="width: 100%; padding: 8px; box-sizing: border-box;">
                </div>

                <div style="margin-bottom: 15px;">
                    <label style="display: block; margin-bottom: 5px;">语气特点:</label>
                    <input type="text" id="tone-input" value="${config.tone}" style="width: 100%; padding: 8px; box-sizing: border-box;">
                </div>

                <div style="margin-bottom: 20px;">
                    <label style="display: block; margin-bottom: 5px;">特别要求(可选):</label>
                    <textarea id="requirements-input" rows="3" style="width: 100%; padding: 8px; box-sizing: border-box;">${config.specialRequirements}</textarea>
                </div>

                <hr style="border: none; border-top: 1px solid #e0e0e0; margin: 25px 0;">

                <!-- 影视类型偏好配置 -->
                <div style="margin-bottom: 20px;">
                    <h3 style="margin: 0 0 15px 0; color: #333;">影视类型偏好设置</h3>

                    <div style="margin-bottom: 15px;">
                        <label style="display: block; margin-bottom: 8px;">首选影视类型:</label>
                        <select id="preferred-genre" style="width: 100%; padding: 8px; box-sizing: border-box;">
                            <option value="">不指定</option>
                            ${Object.entries(MOVIE_GENRE_COLORS).map(([key, value]) =>
                                `<option value="${key}" ${config.preferredGenre === key ? 'selected' : ''}>${value.name}</option>`
                            ).join('')}
                        </select>
                    </div>

                    <div style="margin-bottom: 15px;">
                        <label style="display: block; margin-bottom: 8px;">自动应用类型主题色彩:</label>
                        <label style="display: inline-block; margin-right: 20px;">
                            <input type="radio" name="auto-apply-colors" value="yes" ${config.autoApplyColors !== false ? 'checked' : ''}> 开启
                        </label>
                        <label style="display: inline-block;">
                            <input type="radio" name="auto-apply-colors" value="no" ${config.autoApplyColors === false ? 'checked' : ''}> 关闭
                        </label>
                    </div>
                </div>

                <!-- 色彩主题配置 -->
                <div style="margin-bottom: 20px;">
                    <h3 style="margin: 0 0 15px 0; color: #333;">色彩主题配置</h3>

                    <div style="grid-template-columns: 1fr 1fr; gap: 15px; display: grid;">
                        <div>
                            <label style="display: block; margin-bottom: 5px;">主色调:</label>
                            <input type="color" id="primary-color" value="${config.primaryColor || '#ff69b4'}" style="width: 100%; height: 35px; padding: 0; cursor: pointer;">
                        </div>
                        <div>
                            <label style="display: block; margin-bottom: 5px;">辅助色:</label>
                            <input type="color" id="secondary-color" value="${config.secondaryColor || '#ffb6c1'}" style="width: 100%; height: 35px; padding: 0; cursor: pointer;">
                        </div>
                        <div>
                            <label style="display: block; margin-bottom: 5px;">浅背景色:</label>
                            <input type="color" id="light-bg-color" value="${config.lightBgColor || '#fff0f5'}" style="width: 100%; height: 35px; padding: 0; cursor: pointer;">
                        </div>
                        <div>
                            <label style="display: block; margin-bottom: 5px;">文本主色:</label>
                            <input type="color" id="text-color" value="${config.textColor || '#8b4513'}" style="width: 100%; height: 35px; padding: 0; cursor: pointer;">
                        </div>
                    </div>

                    <div style="margin-top: 15px;">
                        <button id="apply-genre-colors" style="background-color: #2196F3; color: white; border: none; padding: 8px 15px; cursor: pointer; border-radius: 4px;">应用选中类型的配色</button>
                    </div>
                </div>

                <!-- 排版配置 -->
                <div style="margin-bottom: 20px;">
                    <h3 style="margin: 0 0 15px 0; color: #333;">排版配置</h3>

                    <div style="grid-template-columns: 1fr 1fr; gap: 15px; display: grid;">
                        <div>
                            <label style="display: block; margin-bottom: 5px;">标题字号:</label>
                            <input type="number" id="title-font-size" value="${config.titleFontSize || 26}" min="16" max="48" style="width: 100%; padding: 8px; box-sizing: border-box;">
                        </div>
                        <div>
                            <label style="display: block; margin-bottom: 5px;">正文字号:</label>
                            <input type="number" id="body-font-size" value="${config.bodyFontSize || 16}" min="12" max="24" style="width: 100%; padding: 8px; box-sizing: border-box;">
                        </div>
                        <div>
                            <label style="display: block; margin-bottom: 5px;">行高:</label>
                            <input type="number" step="0.1" id="line-height" value="${config.lineHeight || 1.8}" min="1.0" max="3.0" style="width: 100%; padding: 8px; box-sizing: border-box;">
                        </div>
                        <div>
                            <label style="display: block; margin-bottom: 5px;">段落间距:</label>
                            <input type="number" id="paragraph-margin" value="${config.paragraphMargin || 15}" min="0" max="50" style="width: 100%; padding: 8px; box-sizing: border-box;">
                        </div>
                    </div>
                </div>

                <div style="display: flex; justify-content: flex-end; margin-top: 30px;">
                    <button id="save-config" style="background-color: #4CAF50; color: white; border: none; padding: 10px 20px; margin-left: 10px; cursor: pointer; border-radius: 4px;">保存配置</button>
                    <button id="reset-config" style="background-color: #f44336; color: white; border: none; padding: 10px 20px; cursor: pointer; border-radius: 4px;">重置为默认值</button>
                </div>
            </div>
        </div>`;

        // 关闭对话框 - 安全版本
        function closeDialog() {
            try {
                const dialog = document.querySelector('div[style*="position: fixed"]');
                if (dialog && document.body.contains(dialog)) {
                    document.body.removeChild(dialog);
                } else if (dialog) {
                    // 如果dialog不是body的直接子元素,尝试找到其实际的父元素
                    const parent = dialog.parentNode;
                    if (parent) {
                        parent.removeChild(dialog);
                    }
                }
            } catch (e) {
                console.warn('关闭对话框时出现错误:', e);
                // 作为最后手段,尝试隐藏元素
                const dialog = document.querySelector('div[style*="position: fixed"]');
                if (dialog) {
                    dialog.style.display = 'none';
                }
            }
        }

        // 添加到页面 - 包含安全检查
        const tempContainer = document.createElement('div');
        tempContainer.innerHTML = dialogHTML;
        const dialogElement = tempContainer.firstElementChild;

        // 确保body存在才添加
        if (document.body) {
            document.body.appendChild(dialogElement);
        } else {
            // 如果body还没加载,延迟添加
            setTimeout(() => {
                if (document.body) {
                    document.body.appendChild(dialogElement);
                }
            }, 100);
        }

        // 获取元素并添加事件监听
        const dialog = dialogElement;
        const closeBtn = dialog.querySelector('#close-dialog');
        const saveBtn = dialog.querySelector('#save-config');
        const resetBtn = dialog.querySelector('#reset-config');
        const templateSelect = dialog.querySelector('#template-select');

        // 确保closeBtn存在再绑定事件
        if (closeBtn) {
            closeBtn.addEventListener('click', closeDialog);
        } else {
            console.error('未找到关闭按钮');
        }

        // 点击对话框外部(遮罩层)不关闭 - 根据用户需求修改
        dialog.addEventListener('click', function(e) {
            // 空函数,不执行任何关闭操作
        });

        // 确保点击内容区域也不关闭对话框
        const dialogContent = dialog.querySelector('div[style*="background-color: white"]');
        if (dialogContent) {
            dialogContent.addEventListener('click', function(e) {
                e.stopPropagation(); // 阻止事件冒泡到遮罩层
            });
        }

        // 模板选择事件
        templateSelect.addEventListener('change', function() {
            const templateId = this.value;
            if (templateId !== 'custom' && AI_ROLE_TEMPLATES[templateId]) {
                const template = AI_ROLE_TEMPLATES[templateId];
                document.getElementById('role-input').value = template.role;
                document.getElementById('personality-input').value = template.personality;
                document.getElementById('style-input').value = template.style;
                document.getElementById('tone-input').value = template.tone;
                document.getElementById('requirements-input').value = template.specialRequirements;
            }
        });

        // 应用选中类型的配色
        const applyGenreColorsBtn = dialog.querySelector('#apply-genre-colors');
        if (applyGenreColorsBtn) {
            applyGenreColorsBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                e.preventDefault();
                const selectedGenre = document.getElementById('preferred-genre').value;
                if (selectedGenre && MOVIE_GENRE_COLORS[selectedGenre]) {
                    const colors = MOVIE_GENRE_COLORS[selectedGenre];
                    document.getElementById('primary-color').value = colors.primary;
                    document.getElementById('secondary-color').value = colors.secondary;
                    document.getElementById('light-bg-color').value = colors.lightBg;
                    document.getElementById('text-color').value = colors.text;
                    showStatus('已应用' + colors.name + '类型的配色方案', false, 'ai');
                } else {
                    showStatus('请先选择一个影视类型', true, 'ai');
                }
            });
        }

        // 保存配置
        saveBtn.addEventListener('click', function(e) {
            e.stopPropagation();
            e.preventDefault();

            const autoApplyColorsValue = document.querySelector('input[name="auto-apply-colors"][type="radio"]:checked').value;

            const newConfig = {
                role: document.getElementById('role-input').value,
                personality: document.getElementById('personality-input').value,
                style: document.getElementById('style-input').value,
                tone: document.getElementById('tone-input').value,
                specialRequirements: document.getElementById('requirements-input').value,
                // 影视类型偏好配置
                preferredGenre: document.getElementById('preferred-genre').value,
                autoApplyColors: autoApplyColorsValue === 'yes',
                // 色彩主题配置
                primaryColor: document.getElementById('primary-color').value,
                secondaryColor: document.getElementById('secondary-color').value,
                lightBgColor: document.getElementById('light-bg-color').value,
                textColor: document.getElementById('text-color').value,
                // 排版配置
                titleFontSize: parseInt(document.getElementById('title-font-size').value),
                bodyFontSize: parseInt(document.getElementById('body-font-size').value),
                lineHeight: parseFloat(document.getElementById('line-height').value),
                paragraphMargin: parseInt(document.getElementById('paragraph-margin').value)
            };

            if (saveAIRoleConfig(newConfig)) {
                alert('配置已保存!');
                closeDialog();
            } else {
                alert('保存失败,请重试!');
            }
        });

        // 重置配置
        resetBtn.addEventListener('click', function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (confirm('确定要重置为默认配置吗?')) {
                // 重置AI角色配置
                document.getElementById('role-input').value = AI_ROLE_DEFAULTS.role;
                document.getElementById('personality-input').value = AI_ROLE_DEFAULTS.personality;
                document.getElementById('style-input').value = AI_ROLE_DEFAULTS.style;
                document.getElementById('tone-input').value = AI_ROLE_DEFAULTS.tone;
                document.getElementById('requirements-input').value = AI_ROLE_DEFAULTS.specialRequirements;
                templateSelect.value = 'custom';

                // 重置影视类型配置
                document.getElementById('preferred-genre').value = '';
                document.querySelector('input[name="auto-apply-colors"][value="yes"]').checked = true;

                // 重置色彩配置(默认粉黛仙境主题)
                document.getElementById('primary-color').value = '#ff69b4';
                document.getElementById('secondary-color').value = '#ffb6c1';
                document.getElementById('light-bg-color').value = '#fff0f5';
                document.getElementById('text-color').value = '#8b4513';

                // 重置排版配置
                document.getElementById('title-font-size').value = 26;
                document.getElementById('body-font-size').value = 16;
                document.getElementById('line-height').value = 1.8;
                document.getElementById('paragraph-margin').value = 15;
            }
        });
    }
    // 粉黛仙境主题式提取影片信息功能 - 专门用于提取豆瓣和TMDB影片资源并以特定排版粘贴到编辑框
    const emeraldButton = document.getElementById('emerald-city-format');
    if (emeraldButton) {
        emeraldButton.addEventListener('click', function(e) {
            e.stopPropagation();
            e.preventDefault();
            try {
                // 直接写入编辑器,无需切换源代码对话框

                // 轻微延迟,确保编辑器可用
                setTimeout(async function() {
                    showStatus('开始应用粉黛仙境主题式影片资源提取...', false);

                    // 使用全局变量中已从豆瓣和TMDB获取的电影信息
                    if (!currentMovieInfo) {
                        showStatus('请先搜索影片并选择海报和剧照', true);
                        return;
                    }

                    // 从currentMovieInfo中获取完整的影片信息
                    const title = currentMovieInfo.title || '电影名称';
                    const director = currentMovieInfo.director || '未知';
                    const writer = currentMovieInfo.writer || '未知';
                    const actor = currentMovieInfo.actor || '未知';
                    const genreTags = currentMovieInfo.genreTags || [];
                    const type = genreTags.join('、') || '未知';
                    const releaseDate = currentMovieInfo.release || '未知';
                    const rating = currentMovieInfo.rating || '9.0';
                    const mainContent = currentMovieInfo.intro || '暂无剧情简介内容';
                    const originalTitle = currentMovieInfo.originalTitle || '';
                    const alsoKnown = currentMovieInfo.alsoKnown || '';
                    const region = currentMovieInfo.region || '未知';
                    const lang = currentMovieInfo.lang || '未知';
                    const runtime = currentMovieInfo.runtime || '未知';
                    const imdbId = currentMovieInfo.imdbId || '暂无';
                    const keywords = currentMovieInfo.keywords || '';
                    const budget = currentMovieInfo.budget || '未知';
                    const revenue = currentMovieInfo.revenue || '未知';
                    const streamingPlatforms = currentMovieInfo.streamingPlatforms || [];
                    const awards = currentMovieInfo.awards || [];

                    // 智能识别内容类型(电影、动漫、电视剧)
                    let contentType = '电影';
                    const animeKeywords = ['动漫', '动画', '番剧', '卡通', '二次元'];
                    const tvKeywords = ['电视剧', '剧集', '网剧', '韩剧', '日剧', '美剧', '英剧', '国产剧', '集数'];

                    if (currentMovieInfo.genreTags && currentMovieInfo.genreTags.some(tag => animeKeywords.some(keyword => tag.includes(keyword)))) {
                        contentType = '动漫';
                    } else if (currentMovieInfo.genreTags && currentMovieInfo.genreTags.some(tag => tvKeywords.some(keyword => tag.includes(keyword)))) {
                        contentType = '电视剧';
                    } else if (currentMovieInfo.mediaType === 'tv') {
                        contentType = '电视剧';
                    } else if (mainContent && animeKeywords.some(keyword => mainContent.includes(keyword))) {
                        contentType = '动漫';
                    } else if (mainContent && tvKeywords.some(keyword => mainContent.includes(keyword))) {
                        contentType = '电视剧';
                    }

                    // 获取已选择的海报和剧照URL
                    const posterUrl = selectedPosterUrl || `https://via.placeholder.com/600x400/ff69b4/FFF?text=${encodeURIComponent(title)}`;
                    const stillUrl = selectedStillUrl || `https://via.placeholder.com/600x300/ff69b4/FFF?text=${encodeURIComponent(title)+'经典场景'}`;

                    // 创建粉黛仙境风格排版,用于展示从豆瓣和TMDB提取的完整影片资源
                    // 根据内容类型自动适配色彩
                    let primaryColor = '#ff69b4'; // 默认主色调:粉色
                    let secondaryColor = '#ffb6c1'; // 默认辅助色:浅粉色
                    let lightBgColor = '#fff0f5'; // 默认浅背景色:淡粉色
                    let lightBorderColor = '#ffcce7'; // 默认浅边框色:超浅粉色
                    let accentColor = '#db7093'; // 默认强调色:深粉色
                    let textColor = '#8b4513'; // 默认文本主色

                    // 根据类型标签识别并应用对应的色彩系统
                    const config = getConfig();
                    if (config.AI && config.AI.POST_FORMAT_GUIDELINES && config.AI.POST_FORMAT_GUIDELINES.VISUAL_ENHANCEMENT && config.AI.POST_FORMAT_GUIDELINES.VISUAL_ENHANCEMENT.COLOR_SYSTEM && genreTags && genreTags.length > 0) {
                        // 类型关键词映射
                        const typeKeywords = {
                            'horror': ['恐怖', '惊悚', '悬疑'],
                            'romance': ['爱情', '浪漫', '恋爱'],
                            'action': ['动作', '冒险', '武侠'],
                            'drama': ['剧情', '文艺', '传记'],
                            'comedy': ['喜剧', '搞笑', '幽默'],
                            'sciFi': ['科幻', '未来', '太空'],
                            'fantasy': ['奇幻', '魔幻', '玄幻'],
                            'anime': ['动漫', '动画', '番剧'],
                            'documentary': ['纪录片', '纪录']
                        };

                        // 查找匹配的类型
                        for (const [type, keywords] of Object.entries(typeKeywords)) {
                            if (genreTags.some(tag => keywords.some(keyword => tag.includes(keyword)))) {
                                if (config.AI.POST_FORMAT_GUIDELINES.VISUAL_ENHANCEMENT.COLOR_SYSTEM[type]) {
                                    primaryColor = config.AI.POST_FORMAT_GUIDELINES.VISUAL_ENHANCEMENT.COLOR_SYSTEM[type][0];
                                    secondaryColor = config.AI.POST_FORMAT_GUIDELINES.VISUAL_ENHANCEMENT.COLOR_SYSTEM[type][1];

                                    // 根据主色调生成其他相关色彩
                                    switch(type) {
                                        case 'horror':
                                            lightBgColor = '#2d3142';
                                            lightBorderColor = '#4f5d75';
                                            accentColor = '#ef8354';
                                            textColor = '#f9f7f3';
                                            break;
                                        case 'romance':
                                            lightBgColor = '#fff9f4';
                                            lightBorderColor = '#f8d8c6';
                                            accentColor = '#f8b195';
                                            textColor = '#7b5d4b';
                                            break;
                                        case 'action':
                                            lightBgColor = '#f8f9fa';
                                            lightBorderColor = '#e0e0e0';
                                            accentColor = '#335c67';
                                            textColor = '#333333';
                                            break;
                                        case 'drama':
                                            lightBgColor = '#f9f7fd';
                                            lightBorderColor = '#e8e2f9';
                                            accentColor = '#3a0ca3';
                                            textColor = '#4a4a4a';
                                            break;
                                        case 'comedy':
                                            lightBgColor = '#fffdf5';
                                            lightBorderColor = '#fff1cc';
                                            accentColor = '#ffb347';
                                            textColor = '#8b4513';
                                            break;
                                        case 'sciFi':
                                            lightBgColor = '#f0f7ff';
                                            lightBorderColor = '#c5e0ff';
                                            accentColor = '#4169e1';
                                            textColor = '#2c3e50';
                                            break;
                                        case 'fantasy':
                                            lightBgColor = '#fcfaff';
                                            lightBorderColor = '#e8e4ff';
                                            accentColor = '#9370db';
                                            textColor = '#4a4a4a';
                                            break;
                                        case 'anime':
                                            lightBgColor = '#fff0f5';
                                            lightBorderColor = '#ffcce7';
                                            accentColor = '#ff69b4';
                                            textColor = '#8b4513';
                                            break;
                                        case 'documentary':
                                            lightBgColor = '#f5f5f5';
                                            lightBorderColor = '#e0e0e0';
                                            accentColor = '#708090';
                                            textColor = '#333333';
                                            break;
                                    }
                                    break;
                                }
                            }
                        }
                    }

                    // 处理类型显示格式(用·分隔)
                    let formattedType = type;
                    if (genreTags && genreTags.length > 0) {
                        formattedType = genreTags.join('·');
                    }

                    // 创建新的排版模板
                    const emeraldStyledContent = `
<div style="max-width: 800px; margin: 25px auto; font-family: 'Microsoft Yahei', sans-serif; color: ${textColor}; background: #fff; padding: 0 15px;">

  <!-- 标题区 -->
  <h2 style="text-align: center; font-size: 26px; color: ${primaryColor}; border-bottom: 2px dashed ${secondaryColor}; padding: 15px 0; margin: 0 0 30px 0;">
    【${contentType}】${title}${originalTitle && originalTitle !== title ? `(${originalTitle})` : ''}
  </h2>

  <!-- 核心信息卡 - 粉黛仙境风格 -->
  <div style="border: 2px solid ${primaryColor}; border-radius: 10px; padding: 20px; margin: 0 0 30px 0; background: ${lightBgColor}; box-shadow: 0 4px 12px rgba(255, 105, 180, 0.15);">
    <div style="text-align: center; margin-bottom: 20px;">
      <img
        style="max-width: 100%; border-radius: 8px; border: 2px solid ${secondaryColor}; box-shadow: 0 4px 8px rgba(255, 105, 180, 0.2);"
        src="${posterUrl}"
        alt="${title}海报"
      >
      <p style="color: ${primaryColor}; font-size: 14px; font-weight: bold; margin-top: 10px;">${title}${contentType === '电影' ? '电影' : ''}海报</p>
    </div>
  <div style="background: #ffffff; padding: 20px; border-radius: 8px; border: 1px solid ${lightBorderColor}; color:#1f2937 !important;">
      <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;">
        <div>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">作品名称:</strong> ${title}${originalTitle && originalTitle !== title ? `(${originalTitle})` : ''}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">导演/主创:</strong> ${director || '暂无信息'}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">编剧:</strong> ${writer || '暂无信息'}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">主演:</strong> ${actor.length > 30 ? actor.substring(0, 30) + '...' : actor || '暂无信息'}</p>
        </div>
        <div>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">类型:</strong> ${formattedType || '暂无信息'}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">制片地区:</strong> ${region || '暂无信息'}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">语言:</strong> ${lang || '暂无信息'}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">片长:</strong> ${runtime || '暂无信息'}</p>
          <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">上线时间:</strong> ${releaseDate || '暂无信息'}</p>
        </div>
      </div>
      ${alsoKnown ? `<p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style=\"color:#111827\">又名:</strong> ${alsoKnown}</p>` : ''}
      ${imdbId && imdbId !== '暂无' ? `<p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style=\"color:#111827\">IMDb ID:</strong> ${imdbId}</p>` : ''}
      <p style="font-size: 16px; color: #1f2937; margin: 12px 0; line-height: 1.6;"><strong style="color:#111827">评分:</strong> <span style="color: #fff; background: ${primaryColor}; padding: 3px 10px; border-radius: 15px; font-weight: 700;">${rating || '暂无'}</span></p>
    </div>
  </div>

  <!-- 内容简介区 -->
  <h3 style="font-size: 18px; color: ${primaryColor}; font-weight: bold; text-decoration: underline dotted ${secondaryColor}; margin: 30px 0 20px 0;">
    【${contentType === '电影' ? '电影' : contentType === '动漫' ? '动漫' : '电视剧'}故事】
  </h3>
  <div style="background: ${lightBgColor}; border-left: 4px solid ${primaryColor}; padding: 20px; border-radius: 5px; margin: 0 0 30px 0;">
    ${mainContent ? mainContent.split('。').filter(s => s.trim()).map(paragraph => `
    <p style="margin: 15px 0; line-height: 1.8;">${paragraph.trim()}。</p>`).join('') : `
    <p style="margin: 15px 0; line-height: 1.8;">暂无剧情简介内容。</p>`}
  </div>



  <!-- 精彩画面区 -->
  <h3 style="font-size: 18px; color: ${primaryColor}; font-weight: bold; text-decoration: underline dotted ${secondaryColor}; margin: 30px 0 20px 0;">
    【精彩画面】
  </h3>
  <div style="border: 2px solid ${primaryColor}; border-radius: 10px; padding: 20px; margin: 0 0 30px 0; text-align: center; box-shadow: 0 4px 12px rgba(255, 105, 180, 0.15);">
    <img
      style="max-width: 100%; border-radius: 8px; display: inline-block; box-shadow: 0 4px 8px rgba(255, 105, 180, 0.2);"
      src="${stillUrl}"
      alt="${title}经典画面"
    >
    <p style="color: ${primaryColor}; font-size: 14px; font-weight: bold; margin-top: 12px;">${title}经典场景</p>
  </div>

  <!-- 热评区 -->
  <h3 style="font-size: 18px; color: ${primaryColor}; font-weight: bold; text-decoration: underline dotted ${secondaryColor}; margin: 30px 0 20px 0;">
    【观众热评】
  </h3>
  <div style="background: #fff; padding: 20px; border-radius: 8px; border: 1px solid ${lightBorderColor}; margin: 0 0 30px 0; line-height: 1.7;">
    <p style="margin: 0 0 15px 0; font-weight: 500; color: ${primaryColor}; font-size: 16px;">&ldquo;每次看${title}都会有不同的感受,故事情节引人入胜,人物形象鲜明,是一部值得反复观看的经典作品。&rdquo;</p>
    <p style="margin: 0; text-align: right; color: ${textColor}; font-style: italic;">—— 豆瓣用户 @影视爱好者</p>
  </div>

  <!-- 提示区 -->
  <p style="font-size: 16px; color: ${textColor}; text-align: center; margin: 40px 0; padding: 15px; background-color: ${lightBgColor}; border-radius: 5px; line-height: 1.7;">
    【${contentType === '电影' ? '观影' : '追剧'}提示】${title}值得反复看,每次都有新感悟。推荐找个安静下午,沉浸式感受这部作品的魅力。
  </p>

</div>`;

                    // 预览与归档
                    try { updateLivePreview(emeraldStyledContent, { step: '粉黛仙境预览' }); } catch(_) {}

                    // 直接写入编辑器(统一助手,覆盖TinyMCE/CodeMirror/textarea/iframe/contenteditable)
                    const ok = await writeHtmlToAnyEditor(emeraldStyledContent);
                    // 保存(按钮自动点击,失败不抛错)
                    try { await autoClickSaveBtn(); } catch(_) {}
                    if (ok) {
                        showStatus('粉黛仙境内容已直接写入编辑器并保存', false);
                        try { logPreviewStep('写入编辑器并保存', true); } catch(_) {}
                    } else {
                        showStatus('写入失败,已提供剪贴板备份', true);
                        try { logPreviewStep('写入失败,已回退到剪贴板', false); } catch(_) {}
                    }
                }, 1000); // 1秒延迟
            } catch (error) {
                showStatus('绿野仙踪主题式影片资源提取失败,请检查是否已选择影片', true);
                console.error('绿野仙踪主题式影片资源提取错误:', error);
            }
        });
    }

    // 注册(不可用)油猴菜单项
    try {
        GM_registerMenuCommand('🔧 脚本配置', createConfigDialog);
        // 移除外部菜单入口:仅在预览模式下保留,避免打扰实际使用
        try {
            const isPreview = /[?&]preview=1\b/.test(location.search) || localStorage.getItem('script_preview') === '1';
            if (isPreview) GM_registerMenuCommand('设置AI角色', openAIRoleConfigUI);
        } catch (e) {}
    } catch (e) {
        console.error('注册(不可用)菜单项失败:', e);
        // 降级方案:在控制台提供信息
        console.log('=== 油猴菜单注册(不可用)失败,您可以通过控制台执行 createConfigDialog() 打开配置界面 ===');
    }

    // 修改generateAIText函数以使用用户配置的角色信息
    // 由于无法直接修改已定义的函数,我们需要在脚本中找到该函数并修改
    // 以下是修改后的函数核心部分,用户可以手动替换原函数
    /* 修改建议:在generateAIText函数中,将设置systemPrompt的部分替换为:
    const roleConfig = getAIRoleConfig();
    let systemPrompt = generateSystemPrompt(roleConfig, isFormatRelated);
    */

    // 豆瓣模拟登录(不可用)函数
    function performDoubanLogin(username, password, statusElement) {
        // 模拟登录(不可用)成功
        setTimeout(() => {
            if (statusElement && statusElement.parentNode) {
                statusElement.textContent = '✅ 模拟登录(不可用)成功!';
                statusElement.style.color = '#065f46';
                statusElement.style.backgroundColor = '#d1fae5';

                // 保存登录(不可用)信息
                try {
                    const savedConfig = localStorage.getItem('apiConfig');
                    const config = savedConfig ? JSON.parse(savedConfig) : {};
                    config.doubanUsername = username;
                    config.doubanLoginTime = new Date().toISOString();
                    config.doubanLoginStatus = 'simulated';
                    localStorage.setItem('apiConfig', JSON.stringify(config));
                    console.log('豆瓣模拟登录(不可用)信息已保存');
                } catch (storageError) {
                    console.error('保存模拟登录(不可用)信息失败:', storageError);
                }

                // 显示成功通知
                try {
                    showNotification('豆瓣模拟登录(不可用)成功!', 'success');
                } catch (notifyError) {
                    console.warn('显示通知失败:', notifyError);
                }

                // 更新编辑器内容
                ensureEditorHasContent();
            }
        }, 1000);
    }

    // 豆瓣登录(不可用)函数
    function isolatedDoubanLogin() {
        // 获取用户名和密码输入框
        const usernameInput = document.querySelector('input[name="username"], input[type="text"]');
        const passwordInput = document.querySelector('input[name="password"], input[type="password"]');

        if (!usernameInput || !passwordInput) {
            console.error('未找到用户名或密码输入框');
            return;
        }

        const username = usernameInput.value.trim();
        const password = passwordInput.value.trim();

        if (!username || !password) {
            console.error('用户名或密码不能为空');
            return;
        }

        // 创建状态显示元素
        let statusElement = document.getElementById('login-status');
        if (!statusElement) {
            statusElement = document.createElement('div');
            statusElement.id = 'login-status';
            statusElement.style.cssText = 'position:fixed;top:20px;right:20px;padding:10px;border-radius:5px;z-index:50;font-size:14px;';
            document.body.appendChild(statusElement);
        }

        statusElement.textContent = '🔄 正在登录(不可用)...';
        statusElement.style.color = '#1e40af';
        statusElement.style.backgroundColor = '#dbeafe';

        // 由于跨域限制,直接使用模拟登录(不可用)
        console.log('由于浏览器安全限制,使用模拟登录(不可用)模式');

        // 显示回退通知
        try {
            showNotification('由于浏览器安全限制,正在使用模拟登录(不可用)模式...', 'info');
        } catch (notifyError) {
            console.warn('显示通知失败:', notifyError);
        }

        // 延迟后执行模拟登录(不可用)
        setTimeout(() => {
            if (statusElement && statusElement.parentNode) {
                performDoubanLogin(username, password, statusElement);
            }
        }, 1000);
    }

    // 确保编辑器有完整内容
    function ensureEditorHasContent() {
        try {
            // 首先调用确保标题非空的函数
            ensureTitleIsNotEmpty();

            const editor = window.editor || { instance: { value: '' } };

            // 确保editor.instance存在
            if (!editor.instance) {
                console.warn('编辑器实例不存在,无法确保内容');
                return;
            }

            let currentContent = '';

            // 安全获取当前编辑器内容
            try {
                if (editor.type === 'codemirror' && typeof editor.instance.getValue === 'function') {
                    currentContent = editor.instance.getValue() || '';
                } else if (typeof editor.instance.value !== 'undefined') {
                    currentContent = editor.instance.value || '';
                }
            } catch (contentError) {
                console.warn('获取编辑器内容失败:', contentError);
                currentContent = '';
            }

            // 如果编辑器内容仍然为空,尝试恢复备份
            if (!currentContent.trim()) {
                const restored = restoreBackupHtml();

                // 如果没有备份或恢复失败,创建更完整的默认内容
                if (!restored) {
                    try {
                        // 创建安全的默认HTML内容
                        const defaultContent = `<h1 style="color:#1e40af;font-size:24px;font-weight:bold;margin:20px 0 15px 0;padding-bottom:8px;border-bottom:2px solid #dbeafe;">【豆瓣影视资源】</h1>\n<p style="color:#333;font-size:14px;line-height:1.8;margin:8px 0;text-indent:2em;">已完成豆瓣账号登录(不可用),您可以开始搜索和提取影视信息。</p>\n<p style="color:#333;font-size:14px;line-height:1.8;margin:8px 0;text-indent:2em;">使用提示:搜索影片名称,选择合适的海报和剧照,然后点击确认填充按钮。</p>\n<p style="color:#6b7280;font-size:12px;line-height:1.6;margin:20px 0 10px 0;">提示:如需手动复制内容,可使用页面中的复制功能按钮。</p>`;

                        // 保存备份
                        saveBackupHtml(defaultContent);

                        // 安全填充内容到编辑器
                        if (editor.type === 'codemirror' && typeof editor.instance.setValue === 'function') {
                            editor.instance.setValue(defaultContent);
                        } else if (typeof editor.instance.value !== 'undefined') {
                            editor.instance.value = defaultContent;
                        }
                    } catch (defaultContentError) {
                        console.error('创建和设置默认内容失败:', defaultContentError);
                    }
                }
            }
        } catch (error) {
            console.error('确保编辑器有内容失败:', error);
        }
    }

    // 从Cookie字符串中提取重要的豆瓣Cookie
    function extractImportantCookies(cookiesStr) {
        const importantCookies = ['dbcl2', 'bid', 'ck', 'll'];
        const cookies = cookiesStr.split('; ');
        const result = [];

        for (const cookie of cookies) {
            const [name, value] = cookie.split('=', 2);
            if (importantCookies.includes(name)) {
                result.push(`${name}=${value}`);
            }
        }

        return result.join('; ');
    }

    // 获取TMDB API配置
    function getTmdbConfig() {
        try {
            const savedConfig = localStorage.getItem('apiConfig');
            return savedConfig ? JSON.parse(savedConfig) : {};
        } catch (error) {
            console.error('获取TMDB配置失败:', error);
            return {};
        }
    }

    // 获取豆瓣Cookie配置
    function getDoubanCookie() {
        try {
            const savedConfig = localStorage.getItem('apiConfig');
            return savedConfig ? JSON.parse(savedConfig).doubanCookie || '' : '';
        } catch (error) {
            console.error('获取豆瓣Cookie失败:', error);
            return '';
        }
    }

    // 加载已保存的账号信息(只加载用户名,不加载密码以保证安全)
    function loadSavedAccountInfo() {
        try {
            const savedConfig = localStorage.getItem('apiConfig');
            if (savedConfig) {
                const config = JSON.parse(savedConfig);
                // 如果之前保存过用户名,则填充用户名输入框
                if (config.doubanUsername) {
                    document.getElementById('douban-username').value = config.doubanUsername;
                }
            }

            // 页面加载时确保编辑器有内容
            setTimeout(() => {
                ensureEditorHasContent();
            }, 500); // 延迟500ms,确保编辑器已经初始化
        } catch (error) {
            console.error('加载账号信息失败:', error);

            // 即使加载失败,也要确保编辑器有内容
            ensureEditorHasContent();
        }
    }

    // 复制内容到剪贴板功能
    function copyEditorContent() {
        try {
            const editor = window.editor || { instance: { value: '' } };
            let content = '';

            // 获取编辑器内容
            if (editor.type === 'codemirror') {
                content = editor.instance.getValue();
            } else if (editor.instance) {
                content = editor.instance.value || '';
            }

            // 如果编辑器内容为空,尝试获取备份
            if (!content.trim()) {
                content = localStorage.getItem('editorBackupHtml') || '';
            }

            if (content.trim()) {
                // 使用Clipboard API复制内容
                if (navigator.clipboard && window.isSecureContext) {
                    navigator.clipboard.writeText(content).then(() => {
                        showNotification('✅ 内容已复制到剪贴板!', 'success');
                    }).catch(err => {
                        console.error('复制失败:', err);
                        showNotification('❌ 复制失败,请手动选择复制', 'error');
                    });
                } else {
                    // 降级方案:创建临时textarea元素
                    const textArea = document.createElement('textarea');
                    textArea.value = content;
                    textArea.style.position = 'fixed';
                    textArea.style.left = '-999999px';
                    textArea.style.top = '-999999px';

                    // 确保body存在才添加
                    if (document.body) {
                        document.body.appendChild(textArea);
                    } else {
                        // 如果body还没加载,延迟添加
                        setTimeout(() => {
                            if (document.body) {
                                document.body.appendChild(textArea);
                            }
                        }, 100);
                    }
                    textArea.focus();
                    textArea.select();

                    try {
                        const successful = document.execCommand('copy');
                        if (successful) {
                            showNotification('✅ 内容已复制到剪贴板!', 'success');
                        } else {
                            showNotification('❌ 复制失败,请手动选择复制', 'error');
                        }
                    } catch (err) {
                        console.error('复制失败:', err);
                        showNotification('❌ 复制失败,请手动选择复制', 'error');
                    }

                    document.body.removeChild(textArea);
                }
            } else {
                showNotification('⚠️ 没有可复制的内容', 'warning');
            }
        } catch (error) {
            console.error('复制功能异常:', error);
            showNotification('❌ 复制功能异常', 'error');
        }
    }

    // 显示通知消息
    function showNotification(message, type = 'info', duration = 3000) {
        try {
            // 确保message是字符串类型
            const safeMessage = String(message || '未知消息');

            // 检查是否已存在通知元素
            try {
                let notification = document.getElementById('copy-notification');
                if (notification) {
                    notification.remove();
                }
            } catch (removeError) {
                console.warn('移除现有通知失败:', removeError);
            }

            // 创建新的通知元素
            const notification = document.createElement('div');
            notification.id = 'copy-notification';
            notification.textContent = safeMessage; // 使用安全的消息内容

            // 增强可访问性
            notification.setAttribute('role', 'alert');
            notification.setAttribute('aria-live', 'assertive');

            // 设置样式
            notification.style.position = 'fixed';
            notification.style.top = '20px';
            notification.style.right = '20px';
            notification.style.padding = '12px 20px';
            notification.style.borderRadius = '8px';
            notification.style.fontSize = '14px';
            notification.style.fontWeight = '500';
            notification.style.zIndex = '99999'; // 增加z-index确保在最上层
            notification.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
            notification.style.transition = 'opacity 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease';
            notification.style.pointerEvents = 'auto';
            notification.style.cursor = 'pointer'; // 提示用户可以点击关闭
            notification.style.minWidth = '250px';
            notification.style.maxWidth = '400px';
            notification.style.wordWrap = 'break-word';

            // 初始状态(用于动画效果)
            notification.style.opacity = '0';
            notification.style.transform = 'translateX(100%) translateY(-20px)';

            // 根据类型设置不同颜色
            if (type === 'success') {
                notification.style.backgroundColor = '#d1fae5';
                notification.style.color = '#065f46';
                notification.style.border = '1px solid #a7f3d0';
            } else if (type === 'error') {
                notification.style.backgroundColor = '#fee2e2';
                notification.style.color = '#991b1b';
                notification.style.border = '1px solid #fecaca';
            } else if (type === 'warning') {
                notification.style.backgroundColor = '#fef3c7';
                notification.style.color = '#92400e';
                notification.style.border = '1px solid #fde68a';
            } else {
                notification.style.backgroundColor = '#dbeafe';
                notification.style.color = '#1e40af';
                notification.style.border = '1px solid #bfdbfe';
            }

            // 添加点击关闭功能
            notification.addEventListener('click', function() {
                try {
                    if (notification && notification.parentNode) {
                        notification.style.opacity = '0';
                        notification.style.transform = 'translateX(100%) translateY(-20px)';
                        setTimeout(() => {
                            try {
                                if (notification && notification.parentNode) {
                                    notification.parentNode.removeChild(notification);
                                }
                            } catch (removeError) {
                                console.warn('移除通知失败:', removeError);
                            }
                        }, 300);
                    }
                } catch (clickError) {
                    console.warn('关闭通知失败:', clickError);
                }
            });

            // 安全添加到文档中
            function addNotificationToBody() {
                if (document.body && !document.getElementById('copy-notification')) {
                    document.body.appendChild(notification);

                    // 强制重排以确保动画效果正常
                    setTimeout(() => {
                        try {
                            if (notification) {
                                notification.style.opacity = '1';
                                notification.style.transform = 'translateX(0) translateY(0)';
                                // 添加微妙的悬停效果
                                notification.addEventListener('mouseenter', function() {
                                    try {
                                        notification.style.transform = 'translateX(0) translateY(-2px)';
                                        notification.style.boxShadow = '0 6px 16px rgba(0, 0, 0, 0.2)';
                                    } catch (hoverError) {
                                        console.warn('悬停效果设置失败:', hoverError);
                                    }
                                });
                                notification.addEventListener('mouseleave', function() {
                                    try {
                                        notification.style.transform = 'translateX(0) translateY(0)';
                                        notification.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.15)';
                                    } catch (leaveError) {
                                        console.warn('离开效果设置失败:', leaveError);
                                    }
                                });
                            }
                        } catch (animationError) {
                            console.warn('通知动画设置失败:', animationError);
                        }
                    }, 10);
                }
            }

            if (document.body) {
                addNotificationToBody();
            } else {
                // 如果body还没加载,延迟添加,最多尝试3次
                let attempts = 0;
                const maxAttempts = 3;
                const interval = setInterval(() => {
                    attempts++;
                    if (attempts >= maxAttempts) {
                        clearInterval(interval);
                        // 如果多次尝试仍失败,使用alert作为最后的备选
                        console.warn('多次尝试添加通知失败,使用alert');
                        alert(safeMessage);
                        return;
                    }

                    if (document.body) {
                        clearInterval(interval);
                        addNotificationToBody();
                    }
                }, 100);
            }

            // 定时自动消失
            setTimeout(() => {
                try {
                    if (notification && notification.parentNode) {
                        notification.style.opacity = '0';
                        notification.style.transform = 'translateX(100%) translateY(-20px)';
                        setTimeout(() => {
                            try {
                                if (notification && notification.parentNode) {
                                    notification.parentNode.removeChild(notification);
                                }
                            } catch (removeError) {
                                console.warn('移除通知失败:', removeError);
                            }
                        }, 300);
                    }
                } catch (timeoutError) {
                    console.warn('通知超时处理失败:', timeoutError);
                }
            }, duration);
        } catch (error) {
            console.error('显示通知失败:', error);
            // 如果所有显示方式都失败,使用alert作为最后的备选
            try {
                alert(String(message || '操作已完成'));
            } catch (alertError) {
                console.error('显示alert也失败:', alertError);
            }
        }
    }

    // 禁用所有表单验证,防止浏览器原生验证触发
    function disableAllFormValidation() {
        try {
            // 查找所有表单
            const forms = document.querySelectorAll('form');
            forms.forEach(form => {
                form.setAttribute('novalidate', 'true');
                form.addEventListener('submit', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    return false;
                }, true);
            });

            // 查找所有required字段并移除required属性
            const requiredFields = document.querySelectorAll('input[required], textarea[required], select[required]');
            requiredFields.forEach(field => {
                field.removeAttribute('required');
                field.setAttribute('data-was-required', 'true');
            });

            console.log('已禁用所有表单验证');
        } catch (error) {
            console.error('禁用表单验证失败:', error);
        }
    }
    // 注册(不可用)事件监听器
    document.addEventListener('DOMContentLoaded', function() {
        // 立即禁用所有表单验证
        disableAllFormValidation();

        // 立即测试豆瓣登录(不可用)按钮
        setTimeout(() => {
            const testBtn = document.getElementById('test-douban-login');
            // 静默检查按钮状态
            if (testBtn) {
                // 静默添加测试功能
                testBtn.onclick = function() {
                    alert('按钮点击测试成功!');
                };
            }
        }, 1000);

        // 页面完全加载后再次尝试
        window.addEventListener('load', function() {
            // 静默尝试绑定按钮事件
            const loadButton = document.getElementById('test-douban-login');
            if (loadButton) {
                // 静默找到按钮
                loadButton.onclick = function() {
                    alert('页面加载后绑定测试成功!');
                    // 静默处理点击事件
                    return false;
                };
            } else {
                // 静默处理按钮未找到的情况
            }
        });

        // 静默检查按钮状态

        // 使用MutationObserver监听按钮变化
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.type === 'childList') {
                    const addedNodes = Array.from(mutation.addedNodes);
                    addedNodes.forEach(function(node) {
                        if (node.nodeType === 1) { // Element node
                            if (node.id === 'test-douban-login' ||
                                (node.querySelector && node.querySelector('#test-douban-login'))) {
                                console.log('发现豆瓣登录(不可用)按钮被添加:', node);
                                const button = node.id === 'test-douban-login' ? node : node.querySelector('#test-douban-login');
                                if (button) {
                                    button.onclick = function() {
                                        alert('MutationObserver捕获到按钮!');
                                        return false;
                                    };
                                    button.style.border = '2px solid blue';
                                }
                            }
                        }
                    });
                }
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // 移除了全局点击事件监听器,因为它会中断所有按钮的正常点击流程
        // 仅保留必要的按钮特定事件监听器

        // 立即尝试绑定事件,不等待
        const immediateButton = document.getElementById('test-douban-login');
        if (immediateButton) {
            console.log('立即找到按钮,直接绑定事件');
            console.log('按钮HTML:', immediateButton.outerHTML);

            // 添加最简单的测试
            immediateButton.onclick = function() {
                alert('立即绑定测试成功!');
                console.log('立即绑定onclick被触发');
                return false;
            };

            // 也尝试添加内联onclick
            immediateButton.setAttribute('onclick', 'alert("内联onclick测试成功!"); return false;');

            // 添加测试属性
            immediateButton.setAttribute('data-test', 'true');
            immediateButton.style.border = '2px solid red'; // 添加红色边框来确认按钮

            // 添加一个简单的测试函数
            window.testButton = function() {
                alert('测试函数被调用!');
            };

            // 尝试直接调用测试函数
            setTimeout(() => {
                console.log('尝试直接调用测试函数');
                window.testButton();
            }, 2000);

        } else {
            console.log('立即未找到按钮,等待DOM加载');
        }

        // 立即绑定手动配置按钮事件
        bindManualConfigButtons();

        // 添加全局点击事件监听器
        document.addEventListener('click', function(event) {
            console.log('全局点击事件被触发:', event.target);
            console.log('点击元素ID:', event.target.id);
            console.log('点击元素文本:', event.target.textContent);

            if (event.target.id === 'test-douban-login') {
                console.log('全局监听器捕获到豆瓣登录(不可用)按钮点击');
                event.preventDefault();
                event.stopPropagation();
                alert('全局监听器:豆瓣登录(不可用)按钮被点击了!');
                isolatedDoubanLogin();
                return false;
            }
        }, true); // 使用捕获阶段

        // 等待DOM加载完成后再绑定事件
        setTimeout(() => {
            // 添加更灵活的按钮查找逻辑
            const findAndBindButton = function(textPattern, callback) {
                const allButtons = document.querySelectorAll('button, input[type="button"], input[type="submit"]');
                for (let button of allButtons) {
                    const buttonText = button.textContent || button.value || '';
                    if (buttonText.includes(textPattern)) {
                        button.addEventListener('click', callback);
                        console.log(`已绑定包含"${textPattern}"的按钮点击事件`);
                        return button;
                    }
                }
                return null;
            };

            // 尝试通过文本内容绑定按钮
            findAndBindButton('登录(不可用)', function() {
                fillAllRequiredFields();
                isolatedDoubanLogin();
            });

            // 测试豆瓣登录(不可用)按钮点击事件 - 完全隔离版本
            const testButton = document.getElementById('test-douban-login');
            console.log('查找豆瓣登录(不可用)按钮:', testButton);
            console.log('所有按钮元素:', document.querySelectorAll('button'));
            console.log('所有ID包含douban的元素:', document.querySelectorAll('[id*="douban"]'));

            if (testButton) {
                console.log('找到豆瓣登录(不可用)按钮,开始绑定事件');

                // 移除旧的事件监听器,确保只使用新的增强版
                const newTestButton = testButton.cloneNode(true);
                testButton.parentNode.replaceChild(newTestButton, testButton);

                // 重新获取引用并绑定增强版事件监听器
                const enhancedTestButton = document.getElementById('test-douban-login');
                console.log('重新获取按钮引用:', enhancedTestButton);

                enhancedTestButton.addEventListener('click', function(event) {
                    console.log('豆瓣登录(不可用)按钮被点击!');

                    // 多重阻断:确保事件完全被阻止,不触发任何表单验证
                    event.stopPropagation();
                    event.preventDefault();

                    if (event.stopImmediatePropagation) {
                        event.stopImmediatePropagation();
                    }

                    // 立即填充所有required字段,防止浏览器验证触发
                    fillAllRequiredFields();

                    // 完全隔离的豆瓣登录(不可用)处理,不触发任何编辑器验证
                    isolatedDoubanLogin();

                    return false;
                }, true);

                // 添加CSS类以明确标识这是一个填充按钮而非提交按钮
                enhancedTestButton.classList.add('fill-only-button');

                // 设置类型为button,确保不是submit类型
                enhancedTestButton.type = 'button';

                // 移除所有可能的旧的onclick属性
                enhancedTestButton.removeAttribute('onclick');

                // 确保事件处理器正确绑定
                enhancedTestButton.onclick = function() {
                    console.log('豆瓣登录(不可用)按钮被点击,执行登录(不可用)逻辑');

                    // 立即填充所有required字段,防止浏览器验证触发
                    fillAllRequiredFields();

                    // 执行实际的豆瓣登录(不可用)逻辑
                    isolatedDoubanLogin();

                    return false;
                };

                console.log('豆瓣登录(不可用)按钮事件绑定完成,已确保正确执行登录(不可用)逻辑');

            } else {
                console.error('未找到豆瓣登录(不可用)按钮元素');

                // 如果找不到按钮,尝试通过其他方式查找
                const allButtons = document.querySelectorAll('button');
                console.log('页面中所有按钮:', allButtons);

                // 查找包含"豆瓣"或"登录(不可用)"文字的按钮
                const doubanButtons = Array.from(allButtons).filter(btn =>
                    btn.textContent.includes('豆瓣') ||
                    btn.textContent.includes('登录(不可用)') ||
                    btn.id.includes('douban') ||
                    btn.id.includes('login')
                );
                console.log('找到的相关按钮:', doubanButtons);
            }

            // 绑定手动复制内容按钮事件
            const copyBtn = document.getElementById('copy-content-btn');
            if (copyBtn) {
                // 移除旧的事件监听器,确保只使用新的增强版
                const newCopyBtn = copyBtn.cloneNode(true);
                copyBtn.parentNode.replaceChild(newCopyBtn, copyBtn);

                // 重新获取引用并绑定增强版事件监听器
                const enhancedCopyBtn = document.getElementById('copy-content-btn');
                enhancedCopyBtn.addEventListener('click', function(event) {
                    // 多重阻断:确保事件完全被阻止,不触发任何表单验证
                    event.stopPropagation();
                    event.preventDefault();

                    if (event.stopImmediatePropagation) {
                        event.stopImmediatePropagation();
                    }

                    // 执行复制功能
                    copyEditorContent();

                    return false;
                }, true);

                // 添加CSS类以明确标识这是一个填充按钮而非提交按钮
                enhancedCopyBtn.classList.add('fill-only-button');

                // 设置类型为button,确保不是submit类型
                enhancedCopyBtn.type = 'button';
            }

            // 加载已保存的配置
            loadManualConfig();

            // 加载已保存的账号信息
            loadSavedAccountInfo();
        }, 100); // 稍等一下确保DOM完全加载
    });

    // 立即填充所有required字段,防止浏览器表单验证触发
    function fillAllRequiredFields() {
        try {
            // 查找所有带required属性的输入框
            const requiredFields = document.querySelectorAll('input[required], textarea[required], select[required]');

            requiredFields.forEach(field => {
                // 强制填充,不管当前是否有值
                if (field.id === 'title' || field.name === 'title' || field.placeholder === '标题') {
                    field.value = '【豆瓣影视资源】自动生成内容';
                } else if (field.type === 'textarea' || field.tagName.toLowerCase() === 'textarea') {
                    field.value = '正在通过豆瓣账号获取影视信息...';
                } else if (field.type === 'text' || field.type === 'email' || field.type === 'tel') {
                    field.value = '自动填充';
                } else if (field.type === 'number') {
                    field.value = '1';
                } else if (field.tagName.toLowerCase() === 'select') {
                    // 选择第一个非空选项
                    const options = field.querySelectorAll('option');
                    for (let option of options) {
                        if (option.value && option.value.trim() !== '') {
                            field.value = option.value;
                            break;
                        }
                    }
                }

                // 触发所有相关事件,确保验证状态更新
                field.dispatchEvent(new Event('input', { bubbles: true }));
                field.dispatchEvent(new Event('change', { bubbles: true }));
                field.dispatchEvent(new Event('blur', { bubbles: true }));
            });

            console.log('已填充所有required字段,防止表单验证触发');
        } catch (error) {
            console.error('填充required字段失败:', error);
        }
    }

    // 确保所有required字段都不为空,防止浏览器表单验证触发
    function ensureRequiredFieldsNotEmpty() {
        try {
            // 查找所有带required属性的输入框
            const requiredFields = document.querySelectorAll('input[required], textarea[required], select[required]');

            requiredFields.forEach(field => {
                if (!field.value || field.value.trim() === '') {
                    // 根据字段类型设置默认值
                    if (field.id === 'title' || field.name === 'title' || field.placeholder === '标题') {
                        field.value = '【豆瓣影视资源】自动生成内容';
                    } else if (field.type === 'textarea' || field.tagName.toLowerCase() === 'textarea') {
                        field.value = '正在通过豆瓣账号获取影视信息...';
                    } else {
                        field.value = '自动填充';
                    }

                    // 触发input和change事件,确保验证状态更新
                    field.dispatchEvent(new Event('input', { bubbles: true }));
                    field.dispatchEvent(new Event('change', { bubbles: true }));
                }
            });
        } catch (error) {
            console.error('确保required字段非空失败:', error);
        }
    }

    // 确保标题字段非空
    function ensureTitleIsNotEmpty() {
        try {
            const editor = window.editor || { instance: { value: '' } };
            let currentContent = '';

            // 获取当前编辑器内容
            if (editor.type === 'codemirror') {
                currentContent = editor.instance.getValue();
            } else if (editor.instance) {
                currentContent = editor.instance.value || '';
            }

            // 检查标题是否为空,如为空则注入默认标题
            if (!currentContent.trim() || !hasValidTitle(currentContent)) {
                const defaultTitle = '【豆瓣影视资源】自动生成内容';
                const defaultHtml = `<h1 style="color:#1e40af;font-size:24px;font-weight:bold;margin:20px 0 15px 0;padding-bottom:8px;border-bottom:2px solid #dbeafe;">${defaultTitle}</h1>\n<p style="color:#333;font-size:14px;line-height:1.8;margin:8px 0;text-indent:2em;">正在通过豆瓣账号获取影视信息...</p>`;

                // 保存备份内容
                saveBackupHtml(defaultHtml);

                // 填充内容到编辑器
                if (editor.type === 'codemirror') {
                    editor.instance.setValue(defaultHtml);
                } else if (editor.instance) {
                    editor.instance.value = defaultHtml;
                }
            }
        } catch (error) {
            console.error('确保标题非空失败:', error);
        }
    }

    // 检查内容是否包含有效的标题
    function hasValidTitle(content) {
        // 检查是否包含h1-h6标签或明显的标题结构
        return /<h[1-6][^>]*>.*?<\/h[1-6]>/.test(content) ||
               /^#\s+.*$/m.test(content) ||
               /^【.*?】$/.test(content);
    }

    // 保存HTML备份
    function saveBackupHtml(html) {
        try {
            // 确保html是字符串类型
            const safeHtml = String(html || '');

            // 创建或更新备份元素
            let backupElement = document.getElementById('backup-html');
            if (!backupElement) {
                backupElement = document.createElement('input');
                backupElement.type = 'hidden';
                backupElement.id = 'backup-html';

                // 确保在尝试appendChild前body已加载
                if (document.body) {
                    document.body.appendChild(backupElement);
                } else {
                    // 如果body还没加载,延迟添加
                    setTimeout(() => {
                        if (document.body && !document.getElementById('backup-html')) {
                            document.body.appendChild(backupElement);
                            backupElement.value = safeHtml;
                        }
                    }, 100);
                }
            }

            // 安全地设置值
            if (backupElement) {
                backupElement.value = safeHtml;
            }

            // 同时保存到localStorage作为额外备份
            try {
                localStorage.setItem('lastBackupHtml', safeHtml);
            } catch (storageError) {
                console.warn('无法保存到localStorage:', storageError);
            }
        } catch (error) {
            console.error('保存HTML备份失败:', error);
        }
    }

    // 恢复HTML备份
    function restoreBackupHtml() {
        try {
            const editor = window.editor || { instance: { value: '' } };
            let backupHtml = '';

            // 优先从页面元素中获取
            try {
                const backupElement = document.getElementById('backup-html');
                if (backupElement && backupElement.value) {
                    backupHtml = String(backupElement.value || '');
                }
            } catch (elemError) {
                console.warn('从页面元素获取备份失败:', elemError);
            }

            // 如果没有从页面元素获取到,尝试从localStorage获取
            if (!backupHtml.trim()) {
                try {
                    const storedHtml = localStorage.getItem('lastBackupHtml');
                    backupHtml = String(storedHtml || '');
                } catch (storageError) {
                    console.warn('从localStorage获取备份失败:', storageError);
                }
            }

            // 安全验证和清理HTML内容
            if (backupHtml && backupHtml.trim() && (!editor.instance.value || !editor.instance.value.trim())) {
                // 简单的HTML验证,确保内容包含有效标签
                if (/<[a-z][\s\S]*>/i.test(backupHtml)) {
                    // 只有当编辑器内容为空时才恢复
                    try {
                        if (editor.type === 'codemirror' && editor.instance && typeof editor.instance.setValue === 'function') {
                            editor.instance.setValue(backupHtml);
                        } else if (editor.instance) {
                            editor.instance.value = backupHtml;
                        }
                        return true;
                    } catch (editorError) {
                        console.error('设置编辑器内容失败:', editorError);
                    }
                } else {
                    console.warn('备份内容不包含有效的HTML标签');
                }
            }

            return false;
        } catch (error) {
            console.error('恢复HTML备份失败:', error);
            return false;
        }
    }

    // 设置面板功能 - 加载配置到设置面板
    function loadConfigToSettingsPanel() {
        const config = getConfig();

        // 加载TMDB配置
        const tmdbApiKeyInput = document.getElementById('tmdb-api-key');
        const tmdbAccessTokenInput = document.getElementById('tmdb-access-token');
        if (tmdbApiKeyInput) tmdbApiKeyInput.value = config.TMDB.API_KEY || '';
        if (tmdbAccessTokenInput) tmdbAccessTokenInput.value = config.TMDB.ACCESS_TOKEN || '';

        // 加载AI配置
        const aiApiKeyInput = document.getElementById('ai-api-key');
        const aiApiEndpointInput = document.getElementById('ai-api-endpoint');
        const aiProviderSelect = document.getElementById('ai-provider');
        const aiModelInput = document.getElementById('ai-model');
        if (aiApiKeyInput) aiApiKeyInput.value = config.AI.API_KEY || '';
        if (aiApiEndpointInput) aiApiEndpointInput.value = config.AI.API_ENDPOINT || DEFAULT_CONFIG.AI.API_ENDPOINT;
        if (aiProviderSelect) aiProviderSelect.value = config.AI.PROVIDER || DEFAULT_CONFIG.AI.PROVIDER;
        if (aiModelInput) aiModelInput.value = config.AI.DEFAULT_MODEL || DEFAULT_CONFIG.AI.DEFAULT_MODEL;

        // 绑定AI提供商变更事件
        if (aiProviderSelect) {
            aiProviderSelect.addEventListener('change', function() {
                if (this.value !== 'custom') {
                    let endpoint = DEFAULT_CONFIG.AI.API_ENDPOINT;
                    let model = DEFAULT_CONFIG.AI.DEFAULT_MODEL;

                    switch (this.value) {
                        case 'openai':
                            endpoint = 'https://api.openai.com/v1/chat/completions';
                            model = 'gpt-3.5-turbo';
                            break;
                        case 'anthropic':
                            endpoint = 'https://api.anthropic.com/v1/messages';
                            model = 'claude-3-opus-20240229';
                            break;
                        case 'google':
                            endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent';
                            model = 'gemini-pro';
                            break;
                    }

                    if (aiApiEndpointInput && !aiApiEndpointInput.dataset.userModified) {
                        aiApiEndpointInput.value = endpoint;
                    }
                    if (aiModelInput && !aiModelInput.dataset.userModified) {
                        aiModelInput.value = model;
                    }
                }
            });
        }

        // 标记输入框为用户修改过的
        const inputsToWatch = [tmdbApiKeyInput, tmdbAccessTokenInput, aiApiKeyInput, aiApiEndpointInput, aiModelInput];
        inputsToWatch.forEach(input => {
            if (input) {
                input.addEventListener('input', function() {
                    this.dataset.userModified = 'true';
                });
            }
        });
    }

    // 设置面板功能 - 保存配置
    function saveSettingsFromPanel() {
        const config = getConfig();

        // 获取TMDB配置
        const tmdbApiKeyInput = document.getElementById('tmdb-api-key');
        const tmdbAccessTokenInput = document.getElementById('tmdb-access-token');
        if (tmdbApiKeyInput) config.TMDB.API_KEY = tmdbApiKeyInput.value.trim();
        if (tmdbAccessTokenInput) config.TMDB.ACCESS_TOKEN = tmdbAccessTokenInput.value.trim();
        // 保持基础URL使用默认值
        config.TMDB.BASE_URL = DEFAULT_CONFIG.TMDB.BASE_URL;

        // 获取AI配置
        const aiApiKeyInput = document.getElementById('ai-api-key');
        const aiApiEndpointInput = document.getElementById('ai-api-endpoint');
        const aiProviderSelect = document.getElementById('ai-provider');
        const aiModelInput = document.getElementById('ai-model');
        if (aiApiKeyInput) config.AI.API_KEY = aiApiKeyInput.value.trim();
        if (aiApiEndpointInput) config.AI.API_ENDPOINT = aiApiEndpointInput.value.trim() || DEFAULT_CONFIG.AI.API_ENDPOINT;
        if (aiProviderSelect) config.AI.PROVIDER = aiProviderSelect.value;
        if (aiModelInput) config.AI.DEFAULT_MODEL = aiModelInput.value.trim() || DEFAULT_CONFIG.AI.DEFAULT_MODEL;

        // 保存配置
        try {
            saveConfig(config);
            showStatus('设置已保存', false, 'settings');
            return true;
        } catch (error) {
            showStatus('保存设置失败: ' + error.message, true, 'settings');
            console.error('保存配置失败:', error);
            return false;
        }
    }

    // 设置面板功能 - 重置为默认配置
    function resetSettingsToDefault() {
        if (confirm('确定要将所有设置重置为默认值吗?这将清除您的API密钥等配置。')) {
            // 重置TMDB配置
            const tmdbApiKeyInput = document.getElementById('tmdb-api-key');
            const tmdbAccessTokenInput = document.getElementById('tmdb-access-token');
            if (tmdbApiKeyInput) {
                tmdbApiKeyInput.value = '';
                delete tmdbApiKeyInput.dataset.userModified;
            }
            if (tmdbAccessTokenInput) {
                tmdbAccessTokenInput.value = '';
                delete tmdbAccessTokenInput.dataset.userModified;
            }

            // 重置AI配置
            const aiApiKeyInput = document.getElementById('ai-api-key');
            const aiApiEndpointInput = document.getElementById('ai-api-endpoint');
            const aiProviderSelect = document.getElementById('ai-provider');
            const aiModelInput = document.getElementById('ai-model');
            if (aiApiKeyInput) {
                aiApiKeyInput.value = '';
                delete aiApiKeyInput.dataset.userModified;
            }
            if (aiApiEndpointInput) {
                aiApiEndpointInput.value = DEFAULT_CONFIG.AI.API_ENDPOINT;
                delete aiApiEndpointInput.dataset.userModified;
            }
            if (aiProviderSelect) aiProviderSelect.value = DEFAULT_CONFIG.AI.PROVIDER;
            if (aiModelInput) {
                aiModelInput.value = DEFAULT_CONFIG.AI.DEFAULT_MODEL;
                delete aiModelInput.dataset.userModified;
            }

            // 保存默认配置
            const defaultConfig = {
                TMDB: {
                    ...DEFAULT_CONFIG.TMDB,
                    API_KEY: '',
                    ACCESS_TOKEN: ''
                },
                AI: {
                    ...DEFAULT_CONFIG.AI,
                    API_KEY: ''
                }
            };

            try {
                saveConfig(defaultConfig);
                showStatus('已重置为默认设置', false, 'settings');
            } catch (error) {
                showStatus('重置设置失败: ' + error.message, true, 'settings');
                console.error('重置配置失败:', error);
            }
        }
    }

    // 确保在切换到设置标签页时加载配置
    const originalSwitchTab = document.switchTab;
    document.switchTab = function(tabId) {
        originalSwitchTab(tabId);

        // 当切换到设置标签页时,加载配置
        if (tabId === 'settings') {
            loadConfigToSettingsPanel();
        }
    };

    // 同步更新到window和unsafeWindow
    if (typeof unsafeWindow !== 'undefined') {
        unsafeWindow.switchTab = document.switchTab;
    }
    window.switchTab = document.switchTab;

    // 绑定设置面板的事件监听器
    function bindSettingsEventListeners() {
        // 保存设置按钮
        const saveConfigBtn = document.getElementById('save-config-btn');
        if (saveConfigBtn) {
            saveConfigBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                e.preventDefault();
                saveSettingsFromPanel();
            });
        }

        // 重置设置按钮
        const resetConfigBtn = document.getElementById('reset-config-btn');
        if (resetConfigBtn) {
            resetConfigBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                e.preventDefault();
                resetSettingsToDefault();
            });
        }
    }

    // 修改bindEventListeners函数,添加设置面板的事件监听器绑定
    (function() {
        const originalBindEventListeners = bindEventListeners;
        const enhancedBindEventListeners = function() {
            originalBindEventListeners();
            bindSettingsEventListeners();
        };

        // 替换全局bindEventListeners函数
        window.bindEventListeners = enhancedBindEventListeners;

        // 确保内部调用也使用增强版本
        Object.defineProperty(window, 'bindEventListeners', {
            value: enhancedBindEventListeners,
            writable: true,
            configurable: true
        });
    })();

    // 修改insertPanelInMarkedPosition函数,确保设置面板的事件监听器被正确绑定
    (function() {
        const originalInsertPanelInMarkedPosition = insertPanelInMarkedPosition;
        const enhancedInsertPanelInMarkedPosition = function() {
            const result = originalInsertPanelInMarkedPosition();
            bindSettingsEventListeners();
            return result;
        };

        // 替换全局insertPanelInMarkedPosition函数
        window.insertPanelInMarkedPosition = enhancedInsertPanelInMarkedPosition;

        // 确保内部调用也使用增强版本
        Object.defineProperty(window, 'insertPanelInMarkedPosition', {
            value: enhancedInsertPanelInMarkedPosition,
            writable: true,
            configurable: true
        });
    })();

    // ==================== 豆瓣登录(不可用)检测功能 ====================

    // 豆瓣登录(不可用)检测相关变量
    let isCheckingDoubanLogin = false;

    // 通用请求头配置(确保请求不被豆瓣拦截)
    const DOUBAN_COMMON_HEADERS = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Cache-Control': 'no-cache'
    };

    /**
     * 安全获取DOM元素:多次重试直到元素存在或超时
     */
    function safeGetDoubanElement(id, maxRetries = 10, retryDelay = 100) {
        return new Promise((resolve) => {
            let retries = 0;
            const checkElement = () => {
                const element = document.getElementById(id);
                if (element) resolve(element);
                else if (retries < maxRetries) {
                    retries++;
                    setTimeout(checkElement, retryDelay);
                } else {
                    GM_log(`[豆瓣检测] 未找到元素: ${id}`);
                    resolve(null);
                }
            };
            checkElement();
        });
    }

    /**
     * 安全绑定事件:确保元素存在后再绑定
     */
    function safeBindDoubanEvent(elementId, eventType, handler, maxRetries = 10) {
        return safeGetDoubanElement(elementId, maxRetries).then(element => {
            if (element) {
                element.addEventListener(eventType, handler);
                return true;
            }
            return false;
        });
    }
    /**
     * 豆瓣登录(不可用)状态检测(主函数)
     * @returns {Promise} { isLoggedIn: 布尔值, error: 错误信息, details: 检测详情 }
     */
    function checkDoubanLoginStatus() {
        return new Promise((resolve) => {
            // 1. 防抖保护:若检测已在进行,直接返回
            if (isCheckingDoubanLogin) {
                GM_log('[豆瓣检测] 检测已在进行中,跳过重复请求');
                resolve({ isLoggedIn: false, error: '检测正在进行中', details: {} });
                return;
            }

            isCheckingDoubanLogin = true;
            GM_log('[豆瓣检测] 开始跨域检测...');

            // 2. 总超时保护(12秒,避免无限等待)
            const totalTimeoutId = setTimeout(() => {
                isCheckingDoubanLogin = false;
                GM_log('[豆瓣检测] 总超时(12秒)');
                resolve({ isLoggedIn: false, error: '检测超时(12秒)', details: { method: '总超时保护' } });
            }, 12000);

            // --------------------------
            // 主方法:调用豆瓣官方用户状态接口
            // --------------------------
            GM_xmlhttpRequest({
                method: 'GET',
                url: 'https://www.douban.com/j/app/user/check', // 豆瓣官方状态接口
                headers: {
                    ...DOUBAN_COMMON_HEADERS,
                    'Referer': 'https://www.douban.com/', // 模拟从豆瓣主页发起请求
                    'X-Requested-With': 'XMLHttpRequest'
                },
                timeout: 8000, // 主方法单独超时(8秒)
                withCredentials: true, // 关键:携带浏览器中存储的豆瓣Cookie
                onload: (res) => {
                    clearTimeout(totalTimeoutId);
                    isCheckingDoubanLogin = false;
                    GM_log(`[豆瓣检测] 主方法响应:状态码=${res.status}, 最终URL=${res.finalUrl}`);

                    // 主方法成功(200状态码):解析返回数据判断登录(不可用)状态
                    if (res.status === 200) {
                        try {
                            const data = JSON.parse(res.responseText);
                            // 多字段判断登录(不可用)(豆瓣接口可能返回不同字段,需兼容)
                            const isLoggedIn = data && (
                                data.user_id || data.uid || data.logged_in === true ||
                                (data.user && (data.user.id || data.user.uid))
                            );

                            if (isLoggedIn) {
                                resolve({
                                    isLoggedIn: true,
                                    error: '',
                                    details: {
                                        method: '主方法(豆瓣官方接口)',
                                        status: res.status,
                                        userData: { uid: data.user_id || data.uid } // 脱敏返回用户ID
                                    }
                                });
                            } else {
                                GM_log('[豆瓣检测] 主方法返回未登录(不可用),切换到备用方法');
                                tryBackupMethod(); // 主方法未登录(不可用),用备用方法确认
                            }
                        } catch (e) {
                            GM_log(`[豆瓣检测] 主方法JSON解析失败:${e.message}`);
                            tryBackupMethod(); // 解析失败,切换备用方法
                        }
                    } else {
                        GM_log(`[豆瓣检测] 主方法状态码异常(${res.status}),切换备用方法`);
                        tryBackupMethod(); // 状态码非200,切换备用方法
                    }
                },
                onerror: (err) => {
                    clearTimeout(totalTimeoutId);
                    isCheckingDoubanLogin = false;
                    GM_log(`[豆瓣检测] 主方法请求失败:${err.message}`);
                    tryBackupMethod(); // 请求失败,切换备用方法
                },
                ontimeout: () => {
                    clearTimeout(totalTimeoutId);
                    isCheckingDoubanLogin = false;
                    GM_log('[豆瓣检测] 主方法超时(8秒)');
                    tryBackupMethod(); // 超时,切换备用方法
                }
            });

            // --------------------------
            // 备用方法:访问豆瓣个人主页,判断是否重定向到登录(不可用)页
            // --------------------------
            function tryBackupMethod() {
                GM_log('[豆瓣检测] 启动备用方法(访问个人主页)');
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: 'https://www.douban.com/mine/', // 豆瓣个人主页
                    headers: { ...DOUBAN_COMMON_HEADERS, 'Referer': 'https://www.douban.com/' },
                    timeout: 6000, // 备用方法超时(6秒)
                    withCredentials: true,
                    onload: (res) => {
                        clearTimeout(totalTimeoutId);
                        isCheckingDoubanLogin = false;
                        // 判断逻辑:200状态码 + 未重定向到登录(不可用)页 → 已登录(不可用)
                        const isLoggedIn = res.status === 200 &&
                                          !res.finalUrl?.includes('/login') &&
                                          !res.finalUrl?.includes('/passport');
                        const reason = isLoggedIn ? '个人主页访问成功' :
                                      (res.finalUrl?.includes('/login') ? '重定向到登录(不可用)页' : `状态码=${res.status}`);

                        resolve({
                            isLoggedIn: isLoggedIn,
                            error: isLoggedIn ? '' : reason,
                            details: {
                                method: '备用方法(个人主页)',
                                status: res.status,
                                finalUrl: res.finalUrl
                            }
                        });
                    },
                    onerror: (err) => {
                        clearTimeout(totalTimeoutId);
                        isCheckingDoubanLogin = false;
                        resolve({
                            isLoggedIn: false,
                            error: '网络连接失败',
                            details: { method: '备用方法(请求失败)', error: err.message }
                        });
                    },
                    ontimeout: () => {
                        clearTimeout(totalTimeoutId);
                        isCheckingDoubanLogin = false;
                        resolve({
                            isLoggedIn: false,
                            error: '备用方法超时(6秒)',
                            details: { method: '备用方法(超时)' }
                        });
                    }
                });
            }
        });
    }

    /**
     * 打开豆瓣登录(不可用)页面(处理弹窗拦截)
     */
    function openDoubanLoginPage() {
        const doubanHomeUrl = 'https://www.douban.com/'; // 豆瓣主页(自动判断是否需要登录(不可用))
        try {
            // 尝试打开新标签页
            const newWindow = window.open(doubanHomeUrl, '_blank', 'noopener,noreferrer');
            if (newWindow && !newWindow.closed) {
                showStatus('已在新标签页打开豆瓣主页,请登录(不可用)后返回重试检测', false, 'settings');
                return;
            }
            // 弹窗被拦截,处理备用方案
            GM_log('[豆瓣登录(不可用)] 弹窗被拦截,尝试复制链接');
            handleDoubanPopupBlocked(doubanHomeUrl);
        } catch (e) {
            GM_log(`[豆瓣登录(不可用)] 打开页面失败:${e.message}`);
            handleDoubanPopupBlocked(doubanHomeUrl);
        }
    }

    /**
     * 处理弹窗被拦截:复制链接到剪贴板+显示手动链接
     */
    function handleDoubanPopupBlocked(url) {
        // 尝试复制链接到剪贴板
        if (navigator.clipboard?.writeText) {
            navigator.clipboard.writeText(url).then(() => {
                showStatus('豆瓣链接已复制到剪贴板,请粘贴到新标签页登录(不可用)', false, 'settings');
                displayDoubanManualLink(url); // 显示手动点击链接
            }).catch(() => displayDoubanManualLink(url));
        } else {
            displayDoubanManualLink(url); // 不支持剪贴板API,直接显示链接
        }
    }

    /**
     * 显示手动登录(不可用)链接(弹窗拦截时兜底)
     */
    function displayDoubanManualLink(url) {
        safeGetDoubanElement('douban-login-status').then(container => {
            if (!container) return;
            const manualLink = document.createElement('div');
            manualLink.style.cssText = 'margin-top:8px; padding:8px; background:#f5f7fa; border-radius:4px; border:1px solid #e4e7ed;';
            manualLink.innerHTML = `
                <div style="font-size:12px; color:#606266;">🔗 手动登录(不可用)链接:</div>
                <a href="${url}" target="_blank" style="color:#409eff; text-decoration:underline; font-size:11px;">点击访问豆瓣主页 →</a>
            `;
            container.appendChild(manualLink);
        });
    }

    /**
     * 显示内嵌诊断面板(分析Cookie、DOM、环境)
     */
    function showDoubanDiagnosticPanel(details = {}) {
        // 移除已存在的面板(避免重复创建)
        const existingPanel = document.getElementById('douban-diagnostic-panel');
        if (existingPanel) existingPanel.remove();

        // 创建诊断面板
        const panel = document.createElement('div');
        panel.id = 'douban-diagnostic-panel';
        panel.style.cssText = `
            position:fixed; top:50px; right:20px; width:500px; max-height:600px;
            overflow-y:auto; background:white; border:1px solid #e4e7ed; border-radius:4px;
            padding:15px; z-index:50; font-family:Arial,sans-serif; font-size:12px;
            box-shadow:0 2px 12px 0 rgba(0,0,0,0.1);
        `;
        panel.innerHTML = `
            <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid #e4e7ed; padding-bottom:8px; margin-bottom:10px;">
                <h3 style="margin:0; color:#303133; font-size:14px;">🔍 豆瓣登录(不可用)诊断报告</h3>
                <button id="close-douban-diagnostic" style="background:transparent; border:none; font-size:16px; cursor:pointer; color:#c0c4cc;">×</button>
            </div>
            <div id="douban-diagnostic-results">正在生成诊断报告...</div>
            <div style="text-align:center; margin-top:15px;">
                <button id="copy-douban-diagnostic" style="background:#409eff; color:white; border:none; padding:6px 12px; border-radius:4px; cursor:pointer;">复制报告</button>
            </div>
        `;
        document.body.appendChild(panel);

        // 绑定"关闭"按钮
        safeBindDoubanEvent('close-douban-diagnostic', 'click', () => panel.remove());
        // 绑定"复制报告"按钮
        safeBindDoubanEvent('copy-douban-diagnostic', 'click', () => {
            safeGetDoubanElement('douban-diagnostic-results').then(resultsDiv => {
                navigator.clipboard.writeText(resultsDiv.innerText).then(() => {
                    showStatus('诊断报告已复制到剪贴板', false, 'settings');
                }).catch(() => alert('诊断报告:\n' + resultsDiv.innerText));
            });
        });

        // 生成诊断报告
        generateDoubanDiagnosticReport();

        /**
         * 生成详细诊断报告(Cookie+DOM+环境)
         */
        function generateDoubanDiagnosticReport() {
            safeGetDoubanElement('douban-diagnostic-results').then(resultsDiv => {
                if (!resultsDiv) return;

                // 1. 环境信息
                const envInfo = `
                    <div style="border:1px solid #ebeef5; border-radius:4px; padding:10px; margin-bottom:10px; background:#f5f7fa;">
                        <h4 style="margin:0 0 8px 0; color:#303133; font-size:13px;">🌐 环境信息</h4>
                        <p><strong>当前域名:</strong>${window.location.hostname}</p>
                        <p><strong>当前URL:</strong>${window.location.href}</p>
                        <p><strong>GM_API支持:</strong>${typeof GM_xmlhttpRequest !== 'undefined' ? '✅ 支持' : '❌ 不支持'}</p>
                        <p><strong>检测时间:</strong>${new Date().toLocaleString()}</p>
                    </div>
                `;

                // 2. Cookie分析(关键登录(不可用)Cookie:dbcl2/bid/ll)
                const allCookies = document.cookie.split(';').filter(c => c.trim());
                const doubanCookies = allCookies.filter(c => c.includes('douban') || c.startsWith('dbcl') || c.startsWith('bid'));
                const keyCookies = ['dbcl2', 'bid', 'll'].map(name => {
                    const cookie = allCookies.find(c => c.trim().startsWith(`${name}=`));
                    return { name, exists: !!cookie, value: cookie ? cookie.trim().slice(0, 50) + '...' : '无' };
                });
                const cookieInfo = `
                    <div style="border:1px solid #ebeef5; border-radius:4px; padding:10px; margin-bottom:10px; background:#f5f7fa;">
                        <h4 style="margin:0 0 8px 0; color:#303133; font-size:13px;">🍪 Cookie分析</h4>
                        <p><strong>总Cookie数:</strong>${allCookies.length} | <strong>豆瓣Cookie数:</strong>${doubanCookies.length}</p>
                        <h5 style="margin:8px 0 5px 0; color:#303133; font-size:12px;">关键登录(不可用)Cookie:</h5>
                        ${keyCookies.map(c => `
                            <div style="margin:3px 0; padding:3px; background:${c.exists ? '#f0f9eb' : '#fef0f0'}; border-radius:3px;">
                                <strong>${c.name}:</strong>${c.exists ? '✅ 存在' : '❌ 不存在'}
                                ${c.exists ? `(值:${c.value})` : ''}
                            </div>
                        `).join('')}
                    </div>
                `;

                // 3. 检测详情(来自之前的检测结果)
                const checkDetails = `
                    <div style="border:1px solid #ebeef5; border-radius:4px; padding:10px; margin-bottom:10px; background:#f5f7fa;">
                        <h4 style="margin:0 0 8px 0; color:#303133; font-size:13px;">🔍 检测详情</h4>
                        <div style="margin-top:10px; padding:10px; background:#f9fafb; border-radius:6px; border-left:3px solid #f59e0b;">
                            <p style="margin:0; font-size:12px; color:#6b7280;">
                                <strong>检测说明:</strong><br>
                                未登录(不可用)豆瓣账号时,页面将提示“检测失败:状态码=403”。请点击页面中的“去豆瓣登录(不可用)”按钮,完成豆瓣账号登录(不可用)流程后返回当前网页。若网页显示“豆瓣已登录(不可用)”,即表示系统已成功检测到您的豆瓣登录(不可用)状态,此后豆瓣源可正常使用。
                            </p>
                        </div>
                        <p><strong>HTTP状态码:</strong>${details.status || '未知'}</p>
                        <p><strong>最终URL:</strong>${details.finalUrl || '未知'}</p>
                        <p><strong>错误信息:</strong>${details.error || '无'}</p>
                    </div>
                `;

                // 4. 建议操作
                const suggestions = keyCookies.some(c => c.name === 'dbcl2' && c.exists)
                    ? '1. Cookie存在但未登录(不可用):可能是Cookie过期,建议重新登录(不可用)豆瓣<br>2. 清除浏览器缓存后重试'
                    : '1. 未检测到关键Cookie:请先访问豆瓣并完成登录(不可用)<br>2. 检查浏览器是否禁用Cookie<br>3. 尝试无痕模式登录(不可用)(排除缓存干扰)';
                const suggestionInfo = `
                    <div style="border:1px solid #ebeef5; border-radius:4px; padding:10px; background:#f5f7fa;">
                        <h4 style="margin:0 0 8px 0; color:#303133; font-size:13px;">💡 建议操作</h4>
                        <p>${suggestions}</p>
                    </div>
                `;

                // 拼接报告并渲染
                resultsDiv.innerHTML = envInfo + cookieInfo + checkDetails + suggestionInfo;
            });
        }
    }

    /**
     * 渲染豆瓣登录(不可用)状态到UI
     * @param {boolean} isLoggedIn - 是否已登录(不可用)
     * @param {string} error - 错误信息(空表示无错误)
     * @param {object} details - 检测详情
     */
    function renderDoubanLoginStatus(isLoggedIn, error = '', details = {}) {
        safeGetDoubanElement('douban-login-status').then(statusContainer => {
            if (!statusContainer) return;

            // 1. 处理"检测错误"状态(如超时、网络失败)
            if (error) {
                statusContainer.innerHTML = `
                    <div style="display: flex; align-items: center; margin-bottom: 12px;">
                        <span style="color:#e91e63; font-size: 14px; margin-right: 8px;">❌</span>
                        <span style="color:#e91e63; font-weight: 500;">检测失败:${error}</span>
                    </div>
                    <div style="display:flex; gap:8px; flex-wrap:wrap;">
                        <button id="go-douban-login" style="background: #4caf50; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(76, 175, 80, 0.2);">去豆瓣登录(不可用)</button>
                        <button id="retry-douban-check" style="background: #ff9800; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(255, 152, 0, 0.2);">重试检测</button>
                        <button id="douban-diagnose" style="background: #409eff; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(64, 158, 255, 0.2);">详细诊断</button>
                    </div>
                `;
                // 绑定"去登录(不可用)"按钮事件
                safeBindDoubanEvent('go-douban-login', 'click', openDoubanLoginPage);
                // 绑定"重试检测"按钮事件(防重复点击)
                safeBindDoubanEvent('retry-douban-check', 'click', async () => {
                    if (isCheckingDoubanLogin) {
                        showStatus('检测正在进行中,请稍候...', true, 'settings');
                        return;
                    }
                    const retryBtn = await safeGetDoubanElement('retry-douban-check');
                    if (retryBtn) {
                        retryBtn.textContent = '检测中...';
                        retryBtn.disabled = true;
                        retryBtn.style.background = '#ccc';
                    }
                    showStatus('正在重新检测豆瓣登录(不可用)状态...', false, 'settings');
                    const result = await checkDoubanLoginStatus();
                    renderDoubanLoginStatus(result.isLoggedIn, result.error, result.details);
                });
                // 绑定"详细诊断"按钮事件
                safeBindDoubanEvent('douban-diagnose', 'click', () => showDoubanDiagnosticPanel(details));
                return;
            }

            // 2. 处理"已登录(不可用)"状态
            if (isLoggedIn) {
                statusContainer.innerHTML = `
                    <div style="display: flex; align-items: center; margin-bottom: 12px;">
                        <span style="color:#4caf50; font-size: 14px; margin-right: 8px;">✅</span>
                        <span style="color:#4caf50; font-weight: 500;">豆瓣已登录(不可用)</span>
                    </div>
                    <div style="display:flex; gap:8px; margin-bottom: 8px;">
                        <button id="refresh-douban-status" style="background: #4caf50; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(76, 175, 80, 0.2);">刷新状态</button>
                        <button id="go-douban-home" style="background: #409eff; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(64, 158, 255, 0.2);">访问豆瓣</button>
                    </div>
                    <div style="margin-top:10px; padding:10px; background:#f9fafb; border-radius:6px; border-left:3px solid #f59e0b;">
                        <p style="margin:0; font-size:12px; color:#6b7280;">
                            <strong>检测说明:</strong><br>
                            未登录(不可用)豆瓣账号时,页面将提示“检测失败:状态码=403”。请点击页面中的“去豆瓣登录(不可用)”按钮,完成豆瓣账号登录(不可用)流程后返回当前网页。若网页显示“豆瓣已登录(不可用)”,即表示系统已成功检测到您的豆瓣登录(不可用)状态,此后豆瓣源可正常使用。
                        </p>
                    </div>
                `;
                // 绑定"访问豆瓣"按钮
                safeBindDoubanEvent('go-douban-home', 'click', () => window.open('https://www.douban.com/', '_blank'));
                // 绑定"刷新状态"按钮
                safeBindDoubanEvent('refresh-douban-status', 'click', async () => {
                    if (isCheckingDoubanLogin) {
                        showStatus('检测正在进行中,请稍候...', true, 'settings');
                        return;
                    }
                    const refreshBtn = await safeGetDoubanElement('refresh-douban-status');
                    if (refreshBtn) {
                        refreshBtn.textContent = '刷新中...';
                        refreshBtn.disabled = true;
                        refreshBtn.style.background = '#ccc';
                    }
                    showStatus('正在刷新豆瓣登录(不可用)状态...', false, 'settings');
                    const result = await checkDoubanLoginStatus();
                    renderDoubanLoginStatus(result.isLoggedIn, result.error, result.details);
                });
                return;
            }

            // 3. 处理"未登录(不可用)(无错误)"状态
            statusContainer.innerHTML = `
                <div style="display: flex; align-items: center; margin-bottom: 12px;">
                    <span style="color:#ff9800; font-size: 14px; margin-right: 8px;">⚠️</span>
                    <span style="color:#ff9800; font-weight: 500;">豆瓣未登录(不可用)</span>
                </div>
                <div style="display:flex; gap:8px; flex-wrap:wrap; margin-bottom: 8px;">
                    <button id="go-douban-login" style="background: #4caf50; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(76, 175, 80, 0.2);">去豆瓣登录(不可用)</button>
                    <button id="retry-douban-check" style="background: #ff9800; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(255, 152, 0, 0.2);">重试检测</button>
                    <button id="douban-diagnose" style="background: #409eff; color:white; border:none; padding:8px 16px; border-radius:4px; cursor:pointer; font-size:12px; font-weight:500; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(64, 158, 255, 0.2);">详细诊断</button>
                </div>
                <div style="font-size:11px; color:#606266; background:#f5f7fa; padding:6px 8px; border-radius:4px; border-left:3px solid #ff9800;">请先在豆瓣登录(不可用),登录(不可用)后点击"重试检测"</div>
            `;
            // 绑定按钮事件(同"检测错误"状态)
            safeBindDoubanEvent('go-douban-login', 'click', openDoubanLoginPage);
            safeBindDoubanEvent('retry-douban-check', 'click', async () => {
                if (isCheckingDoubanLogin) {
                    showStatus('检测正在进行中,请稍候...', true, 'settings');
                    return;
                }
                const retryBtn = await safeGetDoubanElement('retry-douban-check');
                if (retryBtn) {
                    retryBtn.textContent = '检测中...';
                    retryBtn.disabled = true;
                    retryBtn.style.background = '#ccc';
                }
                showStatus('正在重新检测豆瓣登录(不可用)状态...', false, 'settings');
                const result = await checkDoubanLoginStatus();
                renderDoubanLoginStatus(result.isLoggedIn, result.error, result.details);
            });
            safeBindDoubanEvent('douban-diagnose', 'click', () => showDoubanDiagnosticPanel(details));
        });
    }

    /**
     * 创建豆瓣登录(不可用)检测UI容器
     */
    function createDoubanLoginContainer() {
        const container = document.createElement('div');
        container.id = 'douban-login-container';
        container.style.cssText = `
            background: #fff; border: 1px solid #e4e7ed; border-radius: 8px;
            padding: 15px; margin: 15px 0; box-shadow: 0 2px 12px 0 rgba(0,0,0,0.05);
            position: relative;
        `;
        container.innerHTML = `
            <div style="display: flex; align-items: center; margin-bottom: 12px;">
                <span style="font-size: 16px; margin-right: 8px;">🔐</span>
                <h4 style="margin: 0; color: #8b5cf6; font-size: 14px; font-weight: 600;">豆瓣登录(不可用)状态</h4>
            </div>
            <div id="douban-login-status" style="font-size: 13px; margin-bottom: 10px;"></div>
            <div id="douban-status-container"></div>
            <style>
                #douban-login-container button {
                        transition: border-color 0.2s ease, box-shadow 0.2s ease;
                }
                #douban-login-container button:hover {
                    transform: translateY(-1px);
                    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1) !important;
                }
                #douban-login-container button:active {
                    transform: translateY(0);
                }
                #douban-login-container button:disabled {
                    opacity: 0.6;
                    cursor: not-allowed;
                    transform: none !important;
                }
            </style>
        `;
        return container;
    }

    /**
     * 初始化豆瓣登录(不可用)检测功能
     */
    function initDoubanLoginCheck() {
        // 1. 创建UI容器并插入到设置面板中的指定位置(AI API配置区域下方)
        const settingsContentArea = document.querySelector('#settings-content-area');
        if (settingsContentArea) {
            const doubanContainer = createDoubanLoginContainer();

            // 查找AI API配置区域,将豆瓣检测UI插入到其下方
            const aiApiConfigSection = settingsContentArea.querySelector('div:nth-of-type(2)'); // AI API配置区域
            if (aiApiConfigSection) {
                settingsContentArea.insertBefore(doubanContainer, aiApiConfigSection.nextSibling);
            } else {
                // 备用方案:如果找不到特定位置,仍插入到设置内容区域的顶部
                settingsContentArea.insertBefore(doubanContainer, settingsContentArea.firstChild);
            }
        }

        // 2. 页面加载完成后执行首次检测
        setTimeout(async () => {
            showStatus('正在初始化豆瓣登录(不可用)检测...', false, 'settings');
            const result = await checkDoubanLoginStatus();
            renderDoubanLoginStatus(result.isLoggedIn, result.error, result.details);

            // 3. 监听页面可见性变化(用户从登录(不可用)页返回后自动重新检测)
            document.addEventListener('visibilitychange', async () => {
                if (!document.hidden && !isCheckingDoubanLogin) {
                    showStatus('页面重新可见,正在更新豆瓣登录(不可用)状态...', false, 'settings');
                    const result = await checkDoubanLoginStatus();
                    renderDoubanLoginStatus(result.isLoggedIn, result.error, result.details);
                }
            });
        }, 500); // 延迟500ms确保DOM加载完成
    }

    // 在脚本初始化时启动豆瓣登录(不可用)检测
    setTimeout(() => {
        initDoubanLoginCheck();
        // 自动应用移动端适配
        applyMobileStyles();
        // 预览模式:?preview=1 或 localStorage.preview=1
        try {
            const urlHasPreview = /[?&]preview=1\b/.test(location.search);
            const lsPreview = (localStorage.getItem('script_preview') === '1');
            if (urlHasPreview || lsPreview) {
                localStorage.setItem('script_preview', '1');
                const badge = document.createElement('div');
                badge.textContent = '预览模式';
                badge.style.cssText = 'position:fixed;right:10px;bottom:10px;background:#ec4899;color:#fff;padding:6px 10px;border-radius:8px;font-size:12px;z-index:2147483647;box-shadow:0 2px 8px rgba(0,0,0,0.15);';
                document.body.appendChild(badge);
            }
        } catch (e) { /* 忽略预览装饰失败 */ }
    }, 1000); // 延迟1秒确保主面板已创建

    // 移动端适配工具函数
    function isMobileDevice() {
        return window.innerWidth <= 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    }
    // 应用移动端样式
    function applyMobileStyles() {
        if (!isMobileDevice()) return;

        // 先移除已存在的移动端样式,避免样式重复
        const existingStyle = document.getElementById('mobile-adaptation-styles');
        if (existingStyle) existingStyle.remove();

        // 添加全局响应式样式
        const style = document.createElement('style');
        style.id = 'mobile-adaptation-styles';
        style.textContent = `
            /* 全局搜索结果框保护规则 - 保持样式一致性 */
            #search-results {
                /* 确保搜索结果框样式一致,但允许JavaScript控制显示状态 */
                /* visibility: visible !important; - 移除强制可见 */
                /* opacity: 1 !important; - 移除强制不透明 */
                position: relative !important;
                z-index: 999999 !important;
            }

            /* 确保tox-editor-header不会遮挡搜索结果 */
            div.tox-editor-header {
                z-index: 1 !important;
            }

            /* 确保只在移动设备上应用这些样式 */
            @media screen and (min-width: 769px) {
                /* 电脑端样式保护 - 确保原有布局不受影响 */
                div[style*="display:flex"][style*="gap:20px"] {
                    display: flex !important;
                    flex-direction: row !important;
                    gap: 20px !important;
                }

                #search-results {
                    position: absolute !important;
                    z-index: 999999 !important;
                    /* 移除强制显示,让JavaScript控制显示/隐藏 */
                    background: #fff !important;
                    border: 1px solid #f3d5d9 !important;
                    border-radius: 8px !important;
                    max-height: 300px !important;
                    overflow-y: auto !important;
                    width: calc(100% - 85px) !important;
                    left: 75px !important;
                    top: 32px !important;
                    display: none !important;
                }

                /* 在电脑端也强制降低编辑器头部层级 */
                div.tox-editor-header {
                    z-index: 1 !important;
                }

                label[style*="display:inline-block"][style*="width:75px"] {
                    display: inline-block !important;
                    width: 75px !important;
                    vertical-align: middle !important;
                }

                input[style*="width: calc(100% - 85px)"] {
                    width: calc(100% - 85px) !important;
                    vertical-align: middle !important;
                }

                /* 电脑端提取按钮 - 默认隐藏,由JavaScript控制显示 */
                #fetch-btn {
                    display: none !important; /* 默认隐藏 */
                    opacity: 0.6 !important;
                    pointer-events: none !important;
                    background: #ec4899 !important;
                    color: white !important;
                    border: none !important;
                    padding: 8px 16px !important;
                    border-radius: 0 8px 8px 0 !important;
                    cursor: not-allowed !important;
                    font-size: 13px !important;
                    transition: all 0.3s ease !important;
                }

                #fetch-btn.active {
                    opacity: 1 !important;
                    pointer-events: auto !important;
                    cursor: pointer !important;
                    background: #db2777 !important;
                }

                /* 电脑端控制面板响应式优化 */
                #douban-tmdb-panel {
                    min-width: 320px !important;
                    max-width: 1400px !important; /* 扩大宽屏最大宽度限制,让搜索结果框能更好铺满 */
                    width: 100% !important;
                    overflow-x: auto !important;
                }

                /* 电脑端搜索区域响应式优化 */
                #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"] {
                    flex-wrap: wrap !important;
                    min-width: 0 !important;
                    align-items: flex-start !important;
                }

                /* 宽窗口优化 (宽度 < 800px) - 提前处理 */
                @media screen and (max-width: 800px) {
                    #douban-tmdb-panel {
                        min-width: 400px !important;
                    }

                    #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                        flex: 1 1 48% !important;
                        min-width: 200px !important;
                    }
                }


                /* 较宽窄窗口优化 (宽度 < 700px) - 提前处理 */
                @media screen and (max-width: 700px) {
                    #douban-tmdb-panel {
                        min-width: 350px !important;
                    }

                    #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                        flex: 1 1 45% !important;
                        min-width: 180px !important;
                    }

                    #search-movie, #media-url {
                        min-width: 100px !important;
                    }
                }

                /* 中等窄窗口优化 (宽度 < 650px) - 开始垂直布局 */
                @media screen and (max-width: 650px) {
                    #douban-tmdb-panel {
                        min-width: 340px !important;
                    }

                    /* 强制搜索区域垂直布局 - 使用更高优先级的选择器 */
                    #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                        flex-direction: column !important;
                        gap: 12px !important;
                        align-items: stretch !important;
                    }

                    /* 搜索和链接输入容器全宽显示 */
                    #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                        flex: none !important;
                        width: 100% !important;
                        min-width: auto !important;
                        display: flex !important;
                        flex-direction: row !important;
                        align-items: center !important;
                    }

                    /* 搜索输入框优化 */
                    #search-movie {
                        width: calc(100% - 75px) !important;
                        min-width: 150px !important;
                        font-size: 12px !important;
                        padding: 6px 10px !important;
                    }

                    /* 影视链接输入框优化 */
                    #media-url {
                        width: calc(100% - 75px) !important;
                        min-width: 150px !important;
                        font-size: 12px !important;
                        padding: 6px 10px !important;
                    }

                    /* 搜索结果框位置调整 */
                    #search-results {
                        position: relative !important;
                        width: 100% !important;
                        left: 0 !important;
                        top: 0 !important;
                        margin-top: 4px !important;
                        z-index: 1 !important;
                    }

                    /* 标签页按钮优化 */
                    #main-tab, #ai-tab, #settings-tab {
                        font-size: 11px !important;
                        padding: 6px 12px !important;
                        min-width: 70px !important;
                    }

                    /* 标签文字优化 */
                    label[style*="width:70px"] {
                        width: 65px !important;
                        font-size: 11px !important;
                    }

                    /* 修复链接框显示问题 */
                    .link-container {
                        display: flex;
                        flex-direction: column;
                        gap: 10px;
                    }

                    .link-item {
                        width: 100%;
                        word-break: break-all;
                    }
                }

                /* 中等窄窗口优化 (宽度 < 600px) - 强制垂直布局 */
                @media screen and (max-width: 600px) {
                    #douban-tmdb-panel {
                        min-width: 320px !important;
                    }

                    /* 强制搜索区域垂直布局 - 使用更高优先级的选择器 */
                    #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                        flex-direction: column !important;
                        gap: 12px !important;
                        align-items: stretch !important;
                    }

                    /* 搜索和链接输入容器全宽显示 */
                    #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                        flex: none !important;
                        width: 100% !important;
                        min-width: auto !important;
                        display: flex !important;
                        flex-direction: row !important;
                        align-items: center !important;
                    }

                    /* 搜索输入框优化 */
                    #search-movie {
                        width: calc(100% - 75px) !important;
                        min-width: 150px !important;
                        font-size: 12px !important;
                        padding: 6px 10px !important;
                    }

                    /* 影视链接输入框优化 */
                    #media-url {
                        width: calc(100% - 75px) !important;
                        min-width: 150px !important;
                        font-size: 12px !important;
                        padding: 6px 10px !important;
                    }

                    /* 搜索结果框位置调整 */
                    #search-results {
                        position: relative !important;
                        width: 100% !important;
                        left: 0 !important;
                        top: 0 !important;
                        margin-top: 4px !important;
                        z-index: 1 !important;
                    }

                    /* 标签页按钮优化 */
                    #main-tab, #ai-tab, #settings-tab {
                        font-size: 11px !important;
                        padding: 6px 12px !important;
                        min-width: 70px !important;
                    }

                    /* 标签文字优化 */
                    label[style*="width:70px"] {
                        width: 65px !important;
                        font-size: 11px !important;
                    }
                }

                /* 较窄窗口优化 (宽度 < 500px) - 强制换行 */
                @media screen and (max-width: 500px) {
                    #douban-tmdb-panel {
                        min-width: 300px !important;
                        padding: 12px !important;
                    }

                    /* 强制搜索区域垂直布局 */
                    #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"] {
                        flex-direction: column !important;
                        gap: 12px !important;
                    }

                    /* 搜索和链接输入容器全宽显示 */
                    #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                        flex: none !important;
                        width: 100% !important;
                        min-width: auto !important;
                    }

                    /* 搜索输入框优化 */
                    #search-movie {
                        width: calc(100% - 75px) !important;
                        min-width: 150px !important;
                        font-size: 12px !important;
                        padding: 6px 10px !important;
                    }

                    /* 影视链接输入框优化 */
                    #media-url {
                        width: calc(100% - 75px) !important;
                        min-width: 150px !important;
                        font-size: 12px !important;
                        padding: 6px 10px !important;
                    }

                    /* 搜索结果框位置调整 */
                    #search-results {
                        position: relative !important;
                        width: 100% !important;
                        left: 0 !important;
                        top: 0 !important;
                        margin-top: 4px !important;
                        z-index: 1 !important;
                    }

                    /* 标签页按钮优化 */
                    #main-tab, #ai-tab, #settings-tab {
                        font-size: 11px !important;
                        padding: 6px 12px !important;
                        min-width: 70px !important;
                    }

                    /* 标签文字优化 */
                    label[style*="width:70px"] {
                        width: 65px !important;
                        font-size: 11px !important;
                    }
                }

                /* 电脑端输入框响应式优化 */
                #search-movie, #media-url {
                    min-width: 100px !important;
                }

                /* 电脑端标签响应式优化 */
                label[style*="width:70px"] {
                    flex-shrink: 0 !important;
                }

                /* 电脑端标签页按钮响应式优化 */
                #main-tab, #ai-tab, #settings-tab {
                    flex: 1 1 auto !important;
                    min-width: 80px !important;
                    white-space: nowrap !important;
                    overflow: hidden !important;
                    text-overflow: ellipsis !important;
                }


                /* 极窄窗口优化 (宽度 < 400px) - 强制搜索区域垂直布局 */
                @media screen and (max-width: 400px) {
                    #douban-tmdb-panel {
                        min-width: 280px !important;
                        padding: 10px !important;
                    }

                    /* 强制搜索区域垂直布局 */
                    #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"] {
                        flex-direction: column !important;
                        gap: 10px !important;
                    }

                    /* 搜索和链接输入容器全宽显示 */
                    #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                        flex: none !important;
                        width: 100% !important;
                        min-width: auto !important;
                    }

                    /* 搜索输入框优化 */
                    #search-movie {
                        width: calc(100% - 65px) !important;
                        min-width: 120px !important;
                        font-size: 11px !important;
                        padding: 5px 8px !important;
                    }

                    /* 影视链接输入框优化 */
                    #media-url {
                        width: calc(100% - 65px) !important;
                        min-width: 120px !important;
                        font-size: 11px !important;
                        padding: 5px 8px !important;
                    }

                    /* 搜索结果框位置调整 */
                    #search-results {
                        position: relative !important;
                        width: 100% !important;
                        left: 0 !important;
                        top: 0 !important;
                        margin-top: 4px !important;
                        z-index: 1 !important;
                    }

                    /* 标签页按钮优化 */
                    #main-tab, #ai-tab, #settings-tab {
                        font-size: 11px !important;
                        padding: 6px 12px !important;
                        min-width: 70px !important;
                    }

                    /* 标签文字优化 */
                    label[style*="width:70px"] {
                        width: 65px !important;
                        font-size: 11px !important;
                    }
                }
            }

            /* 移动端专用样式 - 只在移动设备上生效 */
            @media screen and (max-width: 768px) {
                /* 全局移动端适配 */
                * {
                    box-sizing: border-box;
                    -webkit-tap-highlight-color: transparent;
                }

                /* 主要容器适配 */
                #douban-tmdb-panel {
                    width: 100% !important;
                    margin: 0 !important;
                    padding: 8px !important;
                    font-size: 14px !important;
                    overflow-x: hidden !important;
                    min-width: auto !important;
                    max-width: none !important;
                }

                /* 标题和文本适配 */
                h2, h3, h4 {
                    font-size: 18px !important;
                    margin: 8px 0 !important;
                }

                p, span {
                    font-size: 14px !important;
                    line-height: 1.5 !important;
                }

                /* 海报和剧照容器响应式布局 */
                #poster-candidates, #still-candidates {
                    grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)) !important;
                    gap: 4px !important;
                    padding: 6px !important;
                    max-height: 280px !important;
                    overflow-y: auto !important;
                }

                /* 图片尺寸控制 */
                #poster-candidates img, #still-candidates img {
                    max-width: 100% !important;
                    height: auto !important;
                    object-fit: cover !important;
                    border-radius: 4px !important;
                }

                /* 按钮适配 */
                button {
                    font-size: 13px !important;
                    padding: 8px 12px !important;
                    margin: 3px !important;
                    border-radius: 4px !important;
                    min-height: 36px !important;
                    touch-action: manipulation;
                }

                /* 选择图片弹窗适配 */
                #image-selection {
                    width: 98% !important;
                    max-height: none !important; /* 避免与内部候选区形成双重高度上限 */
                    margin: 2.5vh auto !important;
                    padding: 10px !important;
                    border-radius: 8px !important;
                }

                /* 输入框适配 */
                input, select, textarea {
                    width: 100% !important;
                    margin-bottom: 8px !important;
                    padding: 10px !important;
                    font-size: 14px !important;
                    border-radius: 4px !important;
                    height: auto !important;
                }

                /* 搜索结果影视框适配 */
                .movie-item, .search-result-item {
                    width: 100% !important;
                    padding: 8px !important;
                    margin-bottom: 10px !important;
                    border-radius: 6px !important;
                    overflow: hidden !important;
                    box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
                }

                .movie-item img, .search-result-item img {
                    max-width: 40% !important;
                    height: auto !important;
                    float: left !important;
                    margin-right: 10px !important;
                    border-radius: 4px !important;
                }

                .movie-info, .search-result-info {
                    display: block !important;
                    overflow: hidden !important;
                    white-space: normal !important;
                    font-size: 13px !important;
                    line-height: 1.4 !important;
                }

                .movie-title, .search-result-title {
                    font-size: 16px !important;
                    font-weight: bold !important;
                    margin-bottom: 5px !important;
                    white-space: normal !important;
                    word-wrap: break-word !important;
                }

                /* 标签和评分适配 */
                .movie-tags, .movie-rating {
                    font-size: 12px !important;
                    margin: 3px 0 !important;
                }

                /* 分页控制适配 */
                .pagination {
                    display: flex !important;
                    justify-content: center !important;
                    flex-wrap: wrap !important;
                    padding: 10px 0 !important;
                }

                .pagination button {
                    min-width: 30px !important;
                    height: 30px !important;
                    line-height: 30px !important;
                    padding: 0 8px !important;
                    font-size: 12px !important;
                }

                /* 滚动条美化 */
                ::-webkit-scrollbar {
                    width: 6px !important;
                    height: 6px !important;
                }

                ::-webkit-scrollbar-track {
                    background: #f1f1f1 !important;
                    border-radius: 3px !important;
                }

                ::-webkit-scrollbar-thumb {
                    background: #888 !important;
                    border-radius: 3px !important;
                }

                ::-webkit-scrollbar-thumb:hover {
                    background: #555 !important;
                }

                /* 表单布局适配 */
                form {
                    display: flex !important;
                    flex-direction: column !important;
                    gap: 8px !important;
                }

                /* 网格布局适配 */
                .grid-container {
                    grid-template-columns: 1fr !important;
                    gap: 10px !important;
                }

                /* 加载更多按钮 */
                #load-more-posters, #load-more-stills {
                    width: 100% !important;
                    margin: 10px 0 !important;
                    padding: 10px !important;
                    font-size: 14px !important;
                }

                /* 搜索结果弹窗优化 - 移动设备专用 */
                #search-results {
                    position: relative !important;
                    z-index: 1000 !important;
                    background: #fff !important;
                    border: 1px solid #ddd !important;
                    border-radius: 8px !important;
                    max-height: 50vh !important;
                    overflow-y: auto !important;
                    width: 100% !important;
                    left: 0 !important;
                    right: 0 !important;
                    top: auto !important;
                    bottom: auto !important;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.15) !important;
                    transform: none !important;
                    transition: none !important;
                    margin-top: 2px !important;
                }

                /* 移动端搜索区域整体布局 - 垂直排列 */
                div[style*="display:flex"][style*="gap:20px"] {
                    display: flex !important;
                    flex-direction: column !important;
                    gap: 10px !important;
                }

                /* 搜索框和提取按钮布局优化 */
                #search-movie {
                    width: 100% !important;
                    margin-bottom: 8px !important;
                    padding: 10px !important;
                    font-size: 14px !important;
                }

                #fetch-btn {
                    width: 100% !important;
                    margin-top: 5px !important;
                    padding: 10px !important;
                    font-size: 14px !important;
                    min-height: 40px !important;
                    display: none !important; /* 移动端默认隐藏 */
                }

                /* 移动端:移除CSS强制显示规则,完全由JavaScript控制按钮显示 */
                /* #media-url:not(:placeholder-shown) + #fetch-btn,
                #media-url[value]:not([value=""]) + #fetch-btn {
                    display: block;
                } */

                /* 搜索输入框的父容器布局优化 */
                div[id^="search-section"], div[id*="search-section"] {
                    position: relative !important;
                    width: 100% !important;
                    margin-bottom: 10px !important;
                }

                /* 移动端影视链接容器 - 确保垂直布局 */
                div[style*="flex:1"][style*="display:flex"][style*="align-items:center"] {
                    flex: none !important;
                    width: 100% !important;
                    display: flex !important;
                    flex-direction: column !important;
                    align-items: stretch !important;
                }

                /* 搜索加载指示器优化 */
                #search-loading {
                    position: absolute !important;
                    right: 15px !important;
                    top: 35% !important;
                    transform: translateY(-50%) !important;
                    color: #999 !important;
                    font-size: 12px !important;
                }

                /* 影视链接输入框优化 */
                #media-url {
                    width: 100% !important;
                    padding: 10px !important;
                    font-size: 14px !important;
                    margin-bottom: 10px !important;
                }

                /* 修复标签和输入框之间的布局问题 */
                label[for="search-movie"], label[for="media-url"], label[style*="width:80px"], label[style*="width:70px"] {
                    display: block !important;
                    width: 100% !important;
                    margin-bottom: 4px !important;
                    font-size: 13px !important;
                }

                /* 移动端标签布局优化 - 确保标签在输入框上方 */
                label[style*="display:inline-block"][style*="width:75px"] {
                    display: block !important;
                    width: 100% !important;
                    margin-bottom: 6px !important;
                    font-size: 14px !important;
                    font-weight: 500 !important;
                    color: #6b7280 !important;
                }

                /* 移动端输入框布局优化 */
                input[style*="width: calc(100% - 85px)"] {
                    width: 100% !important;
                    margin-left: 0 !important;
                    vertical-align: top !important;
                }

                /* 修复搜索结果项的样式 */
                .search-item {
                    padding: 10px !important;
                    border-bottom: 1px solid #eee !important;
                    display: flex !important;
                    align-items: center !important;
                    gap: 8px !important;
                    font-size: 13px !important;
                }

                .search-item .poster-placeholder {
                    width: 36px !important;
                    height: 54px !important;
                    background: #f5f5f5 !important;
                    border-radius: 4px !important;
                }

                /* 修复AI功能面板样式 */
                #ai-function-select, #ai-prompt-input {
                    width: 100% !important;
                    padding: 8px !important;
                    font-size: 13px !important;
                }

                /* 确保按钮在移动设备上更易于点击 */
                button, input[type="button"], input[type="submit"] {
                    touch-action: manipulation;
                    cursor: pointer;
                    -webkit-appearance: none;
                    border-radius: 4px;
                }

                /* 避免键盘弹出时布局错乱 */
                body {
                    overflow-x: hidden;
                }

                /* 修复链接框显示问题 */
                .link-container {
                    display: flex;
                    flex-direction: column;
                    gap: 10px;
                }

                .link-item {
                    width: 100%;
                    word-break: break-all;
                }
            } /* 闭合移动端媒体查询 */

             /* 针对极窄屏幕的额外优化 */
             @media screen and (max-width: 480px) {
                 #douban-tmdb-panel {
                     padding: 10px 8px !important;
                 }

                 /* 强制搜索区域垂直布局 */
                 #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                     flex-direction: column !important;
                     gap: 10px !important;
                     align-items: stretch !important;
                 }

                 /* 搜索和链接输入容器全宽显示 */
                 #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                     flex: none !important;
                     width: 100% !important;
                     min-width: auto !important;
                 }

                 /* 影视链接容器优化 */
                 #media-url-container {
                     width: 100% !important;
                     flex: none !important;
                     min-width: auto !important;
                 }

                 /* 影视链接包装器优化 - 强制垂直布局 */
                 #media-url-wrapper {
                     flex-direction: column !important;
                     align-items: stretch !important;
                     gap: 6px !important;
                     width: 100% !important;
                 }

                 #search-movie {
                     width: 100% !important;
                     font-size: 11px !important;
                     padding: 5px 8px !important;
                     min-width: 120px !important;
                 }

                 #media-url {
                     width: 100% !important;
                     font-size: 11px !important;
                     padding: 5px 8px !important;
                     min-width: 120px !important;
                     border-radius: 6px !important;
                 }

                 #fetch-btn {
                     width: 100% !important;
                     padding: 5px 8px !important;
                     font-size: 11px !important;
                     margin-left: 0 !important;
                     border-radius: 6px !important;
                     flex-shrink: 0 !important;
                 }

                 label[style*="width:70px"] {
                     font-size: 10px !important;
                     width: 60px !important;
                 }

                 #search-results {
                     width: calc(100% - 70px) !important;
                     left: 60px !important;
                     max-height: 200px !important;
                 }

                 /* 确保标签在极窄屏幕上不被挤压 */
                 .search-item {
                     flex-wrap: wrap !important;
                 }

                 .search-item .poster-placeholder {
                     width: 30px !important;
                     height: 45px !important;
                 }

                 /* 修复链接框显示问题 */
                 .link-container {
                     gap: 5px;
                 }
             }

            /* 针对超窄屏幕的优化 */
            @media screen and (max-width: 360px) {
                #douban-tmdb-panel {
                    padding: 8px 6px !important;
                }

                /* 强制搜索区域垂直布局 */
                #douban-tmdb-panel div[style*="display:flex"][style*="gap:15px"][style*="margin-bottom:12px"][style*="align-items:center"] {
                    flex-direction: column !important;
                    gap: 8px !important;
                    align-items: stretch !important;
                }

                /* 搜索和链接输入容器全宽显示 */
                #douban-tmdb-panel div[style*="flex: 1 1 250px"][style*="min-width: 200px"] {
                    flex: none !important;
                    width: 100% !important;
                    min-width: auto !important;
                }

                 /* 影视链接容器优化 */
                 #media-url-container {
                     width: 100% !important;
                     flex: none !important;
                     min-width: auto !important;
                 }

                 /* 影视链接包装器优化 - 强制垂直布局 */
                 #media-url-wrapper {
                     flex-direction: column !important;
                     align-items: stretch !important;
                     gap: 4px !important;
                     width: 100% !important;
                 }

                 #search-movie {
                     width: 100% !important;
                     font-size: 10px !important;
                     padding: 4px 6px !important;
                     min-width: 100px !important;
                 }

                 #media-url {
                     width: 100% !important;
                     font-size: 10px !important;
                     padding: 4px 6px !important;
                     min-width: 100px !important;
                     border-radius: 6px !important;
                 }

                 #fetch-btn {
                     width: 100% !important;
                     padding: 4px 6px !important;
                     font-size: 10px !important;
                     margin-left: 0 !important;
                     border-radius: 6px !important;
                     flex-shrink: 0 !important;
                 }

                label[style*="width:70px"] {
                    font-size: 9px !important;
                    width: 50px !important;
                }

                #search-results {
                    position: relative !important;
                    width: 100% !important;
                    left: 0 !important;
                    top: 0 !important;
                    max-height: 150px !important;
                    margin-top: 4px !important;
                    z-index: 1 !important;
                }

                /* 搜索结果项进一步压缩 */
                .search-item {
                    padding: 6px !important;
                    gap: 5px !important;
                }

                .search-item .poster-placeholder {
                    width: 25px !important;
                    height: 38px !important;
                }

                /* 修复链接框显示问题 */
                .link-container {
                    gap: 3px;
                }
            }
        `;
        document.head.appendChild(style);

        // 提取按钮初始化 - 默认隐藏(所有设备)
        const fetchBtn = document.getElementById('fetch-btn');
        if (fetchBtn) {
            fetchBtn.style.display = 'none';
        }

        // 添加动态调整搜索结果位置的逻辑
        const searchInput = document.getElementById('search-movie');
        const resultsContainer = document.getElementById('search-results');

        if (searchInput && resultsContainer) {
            // 调整搜索结果位置的函数 - 简化版本,因为显示框现在在控制面板内部
            function adjustResultsPosition() {
                if (!searchInput || !resultsContainer) return;

                // 尝试查找并降低div.tox-editor-header的z-index
                const editorHeader = document.querySelector('div.tox-editor-header');
                if (editorHeader) {
                    editorHeader.style.zIndex = '1'; // 临时降低编辑器头部的z-index
                }

                // 显示框现在在控制面板内部,不需要复杂的位置计算
                // 只需要确保显示框正确显示
                if (resultsContainer.style.display === 'block') {
                    resultsContainer.style.setProperty('position', 'relative', 'important');
                    resultsContainer.style.setProperty('top', '0', 'important');
                    resultsContainer.style.setProperty('left', '0', 'important');
                    resultsContainer.style.setProperty('right', '0', 'important');
                    resultsContainer.style.setProperty('z-index', '1000', 'important');
                }
            }

            // 防抖函数,避免频繁调用
            let positionTimeout;
            const debouncedAdjustPosition = () => {
                clearTimeout(positionTimeout);
                positionTimeout = setTimeout(adjustResultsPosition, 50);
            };

            // 立即调整位置
            setTimeout(adjustResultsPosition, 100);

            // 监听输入框聚焦事件
            searchInput.addEventListener('focus', debouncedAdjustPosition);

            // 监听窗口大小变化
            window.addEventListener('resize', debouncedAdjustPosition);

            // 监听页面滚动
            window.addEventListener('scroll', debouncedAdjustPosition);

            // 监听搜索结果显示/隐藏状态变化
            const observer = new MutationObserver((mutations) => {
                mutations.forEach(mutation => {
                    if (mutation.attributeName === 'style') {
                        if (resultsContainer.style.display !== 'none') {
                            debouncedAdjustPosition();
                        }
                    }
                });
            });

            observer.observe(resultsContainer, { attributes: true });
        }
    }

    try {
        // 注册(不可用)油猴菜单项
        GM_registerMenuCommand('📱 移动端适配', () => {
            applyMobileStyles();
            showStatus('移动端适配样式已应用', false);
        });
    } catch (e) {
        console.error('注册(不可用)移动端适配菜单项失败:', e);
    }

    // 立即注入搜索结果框CSS确保显示
    setTimeout(() => {
        if (typeof injectSearchResultsCSS === 'function') {
            injectSearchResultsCSS();
            console.log('已注入搜索结果框强制CSS样式');
        }

        // 确保搜索中指示器初始状态为隐藏
        setSearchLoading(false);

        // 定期检查并隐藏搜索中指示器(防止意外显示)
        setInterval(() => {
            const searchInput = document.getElementById('search-movie');
            const resultsContainer = document.getElementById('search-results');
            const loadingIndicator = document.getElementById('search-loading');

            // 只有在搜索框为空、没有搜索结果、且搜索中指示器已经显示超过5秒时才隐藏
            if (searchInput && !searchInput.value.trim() &&
                resultsContainer && resultsContainer.style.display === 'none' &&
                loadingIndicator && loadingIndicator.style.display === 'block') {
                // 检查指示器是否已经显示超过5秒
                const now = Date.now();
                if (!loadingIndicator.dataset.showTime) {
                    loadingIndicator.dataset.showTime = now.toString();
                } else {
                    const showTime = parseInt(loadingIndicator.dataset.showTime);
                    if (now - showTime > 5000) {
                        setSearchLoading(false);
                        // 静默隐藏超时的搜索中指示器
                    }
                }
            }
        }, 3000);
    }, 100);

    // 脚本功能检查机制 - 静默运行,不显示UI
    function initScriptChecks() {
        console.log('🎬 豆瓣+TMDB影视工具脚本已启动');

        // 核心功能检查(静默运行)
        const coreChecks = {
            // 检查控制面板是否正确创建
            checkPanelCreation: () => {
                const panel = document.getElementById('douban-tmdb-panel');
                return panel ? true : false;
            },

            // 检查搜索功能
            checkSearchFunction: () => {
                const searchInput = document.getElementById('search-movie');
                const results = document.getElementById('search-results');
                return !!(searchInput && results);
            },

            // 检查输入框水平对齐(更稳健:直接比较元素本身位置,移动端跳过)
            checkInputAlignment: () => {
                try {
                    // 移动端/窄屏为垂直布局,不做水平对齐校验
                    if (window.innerWidth <= 800) return true;

                    const searchEl = document.getElementById('search-movie');
                    const linkContainer = document.getElementById('media-url-container');
                    if (!searchEl || !linkContainer) return true; // 缺少元素时不报错

                    const searchRect = searchEl.getBoundingClientRect();
                    const linkRect = linkContainer.getBoundingClientRect();
                    const heightDiff = Math.abs(searchRect.top - linkRect.top);
                    return heightDiff < 8; // 适度放宽容差,避免偶发1-2px误差
                } catch (e) { return true; }
            }
        };

        // 静默运行功能检查,不显示UI

        // 静默运行核心功能检查
        setTimeout(() => {
            // 只检查关键功能,只在出错时输出警告
            Object.entries(coreChecks).forEach(([key, check]) => {
                if (!check()) {
                    console.warn('脚本功能检查失败:', key);
                }
            });
        }, 2000);

        // 监听搜索功能(静默)
        const searchInput = document.getElementById('search-movie');
        if (searchInput) {
            searchInput.addEventListener('input', (e) => {
                // 静默监听,不输出日志
            });
        }

        // 监听控制面板展开状态(静默)
        const panel = document.getElementById('douban-tmdb-panel');
        if (panel) {
            const observer = new MutationObserver((mutations) => {
                // 静默监听,不输出日志
            });
            observer.observe(panel, { attributes: true });
        }

        // 监听窗口大小变化,动态调整输入框对齐(横排即时,竖排轻微防抖)
        let resizeTimeout;
        window.addEventListener('resize', () => {
            const w = window.innerWidth;
            // 竖→横:立即执行,配合no-transition实现闪切
            if (w > 800) {
                adjustInputAlignment();
                return;
            }
            // 横→竖:仅做极短防抖,减小抖动
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(() => {
                adjustInputAlignment();
            }, 50);
        });

        // 初始化时调整对齐(缩短延迟,加快就绪速度)
        setTimeout(() => {
            adjustInputAlignment();
        }, 120);
    }

    // 初始化脚本检查机制
    setTimeout(initScriptChecks, 1000);

})();

QingJ © 2025

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