ChatGPT Tools

ChatGPT 工具箱 - Token 获取、Plus 支付链接、全自动注册、账号管理与对话导出

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         ChatGPT Tools
// @namespace    https://linux.do/u/npc1
// @version      10.7
// @description  ChatGPT 工具箱 - Token 获取、Plus 支付链接、全自动注册、账号管理与对话导出
// @author       npc1
// @match        https://chatgpt.com/*
// @match        https://*.chatgpt.com/*
// @match        https://chat.openai.com/*
// @match        https://auth.openai.com/*
// @match        https://auth0.openai.com/*
// @match        https://pay.openai.com/*
// @icon         data:image/png;base64,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
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @grant        GM_addStyle
// @grant        GM_addElement
// @grant        GM_cookie
// @grant        unsafeWindow
// @connect      dash.xphdfs.me
// @connect      tempmail.plus
// @connect      mail.chatgpt.org.uk
// @connect      *
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';
    const _0xb = s => atob(s);
    const _0x8d = ['tm-app-root', 'tm_npcmail_apikey', 'registered_accounts', 'auto_reg_data', 'auto_reg_step', 'tm_auto_redirect_team'];
    const _0xg = i => _0x8d[i];
    const _0x3c = _0xb('aHR0cHM6Ly9kYXNoLnhwaGRmcy5tZQ==');
    const _0x4e = { API_KEY: _0xg(0x1), ACCOUNTS: _0xg(0x2), AUTO_REG: _0xg(0x3), AUTO_REG_STEP: _0xg(0x4), AUTO_REDIRECT_TEAM: _0xg(0x5) };
    const _0x_TM_API = 'https://tempmail.plus/api';
    const _0x_TM_DOMAINS = ['mailto.plus', 'fexpost.com', 'fexbox.org', 'mailbox.in.ua', 'rover.info', 'chitthi.in', 'fextemp.com', 'any.pink', 'merepost.com'];
    const _0x5f = { IDLE: 'idle', GOTO_SIGNUP: 'goto_signup', FILL_EMAIL: 'fill_email', FILL_PASSWORD: 'fill_password', WAIT_CODE: 'wait_code', FILL_CODE: 'fill_code', FILL_PROFILE: 'fill_profile', COMPLETE: 'complete' };

    /* ═══════════════ 对话导出 - 页面上下文执行(绕过沙箱 Promise 互操作问题) ═══════════════ */
    const _EXP = (function () {
        const W = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
        let _jsZipReady = false;

        // 通过 GM_addElement 在页面上下文加载 JSZip(绕过 CSP)
        function _loadJSZip() {
            return new Promise((resolve) => {
                if (W.JSZip) { _jsZipReady = true; resolve(); return; }
                try {
                    GM_addElement('script', {
                        src: 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js',
                        type: 'text/javascript'
                    });
                } catch (e) {
                    console.warn('[Exporter] GM_addElement failed, trying direct injection:', e);
                    const s = document.createElement('script');
                    s.src = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js';
                    document.head.appendChild(s);
                }
                // 轮询等待 JSZip 在页面上下文中可用
                const t = setInterval(() => {
                    if (W.JSZip) { clearInterval(t); _jsZipReady = true; resolve(); }
                }, 100);
                setTimeout(() => { clearInterval(t); resolve(); }, 15000); // 15s 超时
            });
        }

        // 预加载 JSZip
        _loadJSZip();

        // 在页面上下文注入导出核心逻辑
        // 这样所有 fetch、Promise、JSZip 都在同一个原生上下文中运行,不会有互操作问题
        function _injectPageExporter() {
            if (W.__expPageReady) return;
            W.__expPageReady = true;

            // 网络拦截:捕获 Token 和 Workspace ID(在页面上下文中运行)
            W.__expAccessToken = null;
            W.__expCapturedWsIds = W.__expCapturedWsIds || new Set();

            const rawFetch = W.fetch;
            W.fetch = function (resource, options) {
                try {
                    const headers = options && options.headers;
                    if (headers) {
                        // 捕获 Token
                        let auth = null;
                        if (typeof headers === 'object' && !(headers instanceof W.Headers)) {
                            auth = headers.Authorization || headers.authorization;
                        } else if (headers instanceof W.Headers) {
                            auth = headers.get('Authorization');
                        }
                        if (auth && typeof auth === 'string' && auth.startsWith('Bearer ')) {
                            const tk = auth.slice(7);
                            if (tk && tk.toLowerCase() !== 'dummy') W.__expAccessToken = tk;
                        }
                        // 捕获 Workspace ID
                        var wsId = (typeof headers === 'object' && !(headers instanceof W.Headers)) ? headers['ChatGPT-Account-Id'] : null;
                        if (wsId) W.__expCapturedWsIds.add(wsId);
                    }
                } catch (_) { }
                return rawFetch.apply(this, arguments);
            };

            const rawXhrOpen = W.XMLHttpRequest.prototype.open;
            W.XMLHttpRequest.prototype.open = function () {
                this.addEventListener('readystatechange', function () {
                    if (this.readyState === 4) {
                        try {
                            var a = this.getRequestHeader('Authorization');
                            if (a && a.startsWith('Bearer ')) {
                                var tk = a.slice(7);
                                if (tk && tk.toLowerCase() !== 'dummy') W.__expAccessToken = tk;
                            }
                            var wid = this.getRequestHeader('ChatGPT-Account-Id');
                            if (wid) W.__expCapturedWsIds.add(wid);
                        } catch (_) { }
                    }
                });
                return rawXhrOpen.apply(this, arguments);
            };
        }

        _injectPageExporter();

        // === 以下辅助函数在沙箱中运行,但最终的 ZIP 生成在页面上下文 ===
        const BASE_DELAY = 600, JITTER_RANGE = 400, PAGE_LIMIT = 100;

        function _getToken() { return W.__expAccessToken; }

        async function ensureAccessToken() {
            if (_getToken()) return _getToken();
            try {
                const r = await W.fetch('/api/auth/session?unstable_client=true');
                const session = await r.json();
                if (session.accessToken) { W.__expAccessToken = session.accessToken; return session.accessToken; }
            } catch (_) { }
            return null;
        }

        const sleep = ms => new Promise(r => setTimeout(r, ms));
        const jitter = () => BASE_DELAY + Math.random() * JITTER_RANGE;
        const sanitize = name => name.replace(/[\/\\?%*:|"|<>]/g, '-').trim();

        function getOaiDeviceId() {
            const m = document.cookie.match(/oai-did=([^;]+)/);
            return m ? m[1] : null;
        }

        function genFilename(convData) {
            const shortId = convData.conversation_id.split('-').pop();
            let baseName = convData.title;
            if (!baseName || baseName.trim().toLowerCase() === 'new chat') baseName = 'Untitled';
            return sanitize(baseName) + '_' + shortId + '.json';
        }

        function downloadFile(blob, filename) {
            const a = document.createElement('a');
            a.href = URL.createObjectURL(blob);
            a.download = filename;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(a.href);
        }

        async function _apiFetch(url, workspaceId) {
            const token = _getToken();
            const deviceId = getOaiDeviceId();
            if (!deviceId) throw new Error('无法获取 oai-device-id');
            const headers = { 'Authorization': 'Bearer ' + token, 'oai-device-id': deviceId };
            if (workspaceId) headers['ChatGPT-Account-Id'] = workspaceId;
            const r = await W.fetch(url, { headers });
            if (!r.ok) throw new Error('API 请求失败 (' + r.status + '): ' + url);
            return r.json();
        }

        async function getProjects(workspaceId) {
            if (!workspaceId) return [];
            try {
                const data = await _apiFetch('/backend-api/gizmos/snorlax/sidebar', workspaceId);
                const projects = [];
                if (data.items) data.items.forEach(function (item) {
                    if (item && item.gizmo && item.gizmo.id && item.gizmo.display && item.gizmo.display.name)
                        projects.push({ id: item.gizmo.id, title: item.gizmo.display.name });
                });
                return projects;
            } catch (_) { return []; }
        }

        async function collectIds(onStatus, workspaceId, gizmoId) {
            const all = new Set();
            if (gizmoId) {
                let cursor = '0';
                do {
                    const j = await _apiFetch('/backend-api/gizmos/' + gizmoId + '/conversations?cursor=' + cursor, workspaceId);
                    if (j.items) j.items.forEach(function (it) { all.add(it.id); });
                    cursor = j.cursor;
                    await sleep(jitter());
                } while (cursor);
            } else {
                for (const is_archived of [false, true]) {
                    let offset = 0, has_more = true, page = 0;
                    do {
                        if (onStatus) onStatus('📂 ' + (is_archived ? 'Archived' : 'Active') + ' p' + (++page));
                        const j = await _apiFetch('/backend-api/conversations?offset=' + offset + '&limit=' + PAGE_LIMIT + '&order=updated' + (is_archived ? '&is_archived=true' : ''), workspaceId);
                        if (j.items && j.items.length > 0) {
                            j.items.forEach(function (it) { all.add(it.id); });
                            has_more = j.items.length === PAGE_LIMIT;
                            offset += j.items.length;
                        } else has_more = false;
                        await sleep(jitter());
                    } while (has_more);
                }
            }
            return Array.from(all);
        }

        async function getConversation(id, workspaceId) {
            const j = await _apiFetch('/backend-api/conversation/' + id, workspaceId);
            j.__fetched_at = new Date().toISOString();
            return j;
        }

        function detectAllWorkspaceIds() {
            const foundIds = new Set(W.__expCapturedWsIds || []);
            try {
                const el = document.getElementById('__NEXT_DATA__');
                if (el) {
                    const data = JSON.parse(el.textContent);
                    const accounts = data && data.props && data.props.pageProps && data.props.pageProps.user && data.props.pageProps.user.accounts;
                    if (accounts) Object.values(accounts).forEach(function (acc) { if (acc && acc.account && acc.account.id) foundIds.add(acc.account.id); });
                }
            } catch (_) { }
            try {
                for (let i = 0; i < W.localStorage.length; i++) {
                    const key = W.localStorage.key(i);
                    if (key && (key.includes('account') || key.includes('workspace'))) {
                        const value = W.localStorage.getItem(key);
                        if (value) {
                            const m = value.match(/ws-[a-f0-9-]{36}/i);
                            if (m) foundIds.add(m[0]);
                            else if (/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value.replace(/"/g, '')))
                                foundIds.add(value.replace(/"/g, ''));
                        }
                    }
                }
            } catch (_) { }
            return Array.from(foundIds);
        }

        // 导出主流程 — ZIP 生成在页面上下文中执行
        async function startExport(mode, workspaceId, onStatus) {
            if (!onStatus) onStatus = function () { };
            onStatus('🔑 验证身份...');
            if (!await ensureAccessToken()) { onStatus('❌ 无法获取 Token'); return false; }

            // 确保 JSZip 已加载到页面上下文
            if (!W.JSZip) {
                onStatus('📦 正在加载 JSZip...');
                await _loadJSZip();
                if (!W.JSZip) { onStatus('❌ JSZip 加载失败,请刷新页面重试'); return false; }
            }

            try {
                // 收集所有对话数据
                onStatus('📂 获取对话列表…');
                const allFiles = []; // { path, content }
                const orphanIds = await collectIds(onStatus, workspaceId, null);
                for (let i = 0; i < orphanIds.length; i++) {
                    onStatus('📥 根目录 (' + (i + 1) + '/' + orphanIds.length + ')');
                    const c = await getConversation(orphanIds[i], workspaceId);
                    allFiles.push({ path: genFilename(c), content: JSON.stringify(c, null, 2) });
                    await sleep(jitter());
                }
                onStatus('🔍 获取项目列表…');
                const projects = await getProjects(workspaceId);
                for (const project of projects) {
                    const folderName = sanitize(project.title);
                    onStatus('📂 项目: ' + project.title);
                    const pIds = await collectIds(onStatus, workspaceId, project.id);
                    for (let i = 0; i < pIds.length; i++) {
                        onStatus('📥 ' + project.title.substring(0, 10) + '... (' + (i + 1) + '/' + pIds.length + ')');
                        const c = await getConversation(pIds[i], workspaceId);
                        allFiles.push({ path: folderName + '/' + genFilename(c), content: JSON.stringify(c, null, 2) });
                        await sleep(jitter());
                    }
                }

                onStatus('📦 生成 ZIP…');
                // 在页面上下文中执行 JSZip 操作,彻底避免沙箱 Promise 问题
                const date = new Date().toISOString().slice(0, 10);
                const fname = mode === 'team' ? 'chatgpt_team_' + workspaceId + '_' + date + '.zip' : 'chatgpt_personal_' + date + '.zip';

                // 将文件列表传递给页面上下文,在那里创建 ZIP
                W.__expFilesToZip = allFiles;
                W.__expZipFilename = fname;
                W.__expZipDone = null; // null=pending, true=success, string=error

                // 在页面上下文中运行 ZIP 生成(用 Function 构造器绕过 CSP inline 限制)
                // 由于 CSP 可能阻止 eval/Function,我们直接在沙箱中通过 unsafeWindow 调用页面的 JSZip
                try {
                    const PageJSZip = W.JSZip;
                    const zip = new PageJSZip();
                    for (let i = 0; i < allFiles.length; i++) {
                        zip.file(allFiles[i].path, allFiles[i].content);
                    }
                    // generateAsync 返回的是页面上下文的原生 Promise
                    const pagePromise = zip.generateAsync({ type: 'blob', compression: 'DEFLATE' });
                    // 使用回调方式处理,完全不依赖 await 与跨上下文 Promise 互操作
                    const blob = await new Promise(function (resolve, reject) {
                        pagePromise.then(
                            function (result) { resolve(result); },
                            function (err) { reject(err); }
                        );
                        // 安全超时
                        setTimeout(function () { reject(new Error('ZIP 生成超时')); }, 120000);
                    });
                    downloadFile(blob, fname);
                    return true;
                } catch (zipErr) {
                    console.error('[Exporter] ZIP generation error:', zipErr);
                    onStatus('❌ ZIP 生成失败: ' + zipErr.message);
                    return false;
                }
            } catch (e) {
                console.error('导出错误:', e);
                onStatus('❌ ' + e.message);
                return false;
            }
        }

        return { startExport, detectAllWorkspaceIds };
    })();

    /* ═══════════════ 对话导出 - 导出对话框 UI ═══════════════ */
    function _expShowExportDialog() {
        if (document.getElementById('tm-export-overlay')) return;

        const overlay = document.createElement('div');
        overlay.id = 'tm-export-overlay';
        overlay.className = 'tm-ov show';
        const dialog = document.createElement('div');
        dialog.className = 'tm-md';
        dialog.style.maxWidth = '450px';
        const closeDialog = () => { overlay.classList.remove('show'); setTimeout(() => { if (overlay.parentNode) document.body.removeChild(overlay); }, 300); };

        function doExport(mode, workspaceId) {
            closeDialog();
            const _st = (msg) => _tmToast(msg, 'loading');
            _EXP.startExport(mode, workspaceId, _st).then(ok => {
                if (ok) _tmToast('✅ 对话导出完成!', 'success', 4000);
            });
        }

        const renderStep = (step) => {
            let html = '';
            switch (step) {
                case 'team':
                    const detectedIds = _EXP.detectAllWorkspaceIds();
                    html = `<div class="tm-md-h"><div class="tm-md-t">🏢 导出团队空间</div><button class="tm-md-x" data-exp-close>✕</button></div><div class="tm-md-b">`;
                    if (detectedIds.length > 1) {
                        html += `<div class="tm-alert tm-alert-s">🔎 检测到多个 Workspace,请选择一个:</div><div class="tm-fld">`;
                        detectedIds.forEach((id, index) => {
                            html += `<label class="tm-chk" style="margin-bottom:6px;padding:8px;border-radius:8px;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.04)"><input type="radio" name="exp_workspace_id" value="${id}" ${index === 0 ? 'checked' : ''}><code style="font-family:monospace;font-size:11px;color:rgba(255,255,255,.7)">${id}</code></label>`;
                        });
                        html += `</div>`;
                    } else if (detectedIds.length === 1) {
                        html += `<div class="tm-alert tm-alert-s">✅ 已自动检测到 Workspace ID:</div><div class="tm-code" id="exp-workspace-id-code" style="margin-bottom:12px">${detectedIds[0]}</div>`;
                    } else {
                        html += `<div class="tm-alert tm-alert-w">⚠️ 未能自动检测到 Workspace ID。请尝试刷新页面或打开一个团队对话,或在下方手动输入。</div><div class="tm-fld"><label class="tm-lbl">手动输入 Team Workspace ID</label><input type="text" class="tm-inp" id="exp-team-id-input" placeholder="粘贴您的 Workspace ID (ws-...)"></div>`;
                    }
                    html += `</div><div class="tm-md-f"><button class="tm-btn tm-btn-s" id="exp-back-btn">← 返回</button><button class="tm-btn tm-btn-p" id="exp-start-team-btn">📦 开始导出 (ZIP)</button></div>`;
                    break;
                case 'initial': default:
                    html = `<div class="tm-md-h"><div class="tm-md-t">📦 导出对话</div><button class="tm-md-x" data-exp-close>✕</button></div><div class="tm-md-b"><div class="tm-fld" style="margin-bottom:16px"><button class="tm-btn" id="exp-select-personal" style="width:100%;padding:16px;text-align:left;background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.08);display:block"><strong style="font-size:14px;color:rgba(255,255,255,.95);display:block;margin-bottom:4px">👤 个人空间</strong><span style="font-size:11px;color:rgba(255,255,255,.5)">导出您个人账户下的所有对话</span></button></div><div class="tm-fld"><button class="tm-btn" id="exp-select-team" style="width:100%;padding:16px;text-align:left;background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.08);display:block"><strong style="font-size:14px;color:rgba(255,255,255,.95);display:block;margin-bottom:4px">🏢 团队空间</strong><span style="font-size:11px;color:rgba(255,255,255,.5)">导出团队空间下的对话,将自动检测 Workspace ID</span></button></div></div><div class="tm-md-f"><button class="tm-btn tm-btn-s" data-exp-close>取消</button></div>`;
                    break;
            }
            dialog.innerHTML = html;
            dialog.querySelectorAll('[data-exp-close]').forEach(b => b.onclick = closeDialog);
            if (step === 'initial') {
                document.getElementById('exp-select-personal').onclick = () => doExport('personal', null);
                document.getElementById('exp-select-team').onclick = () => renderStep('team');
            } else if (step === 'team') {
                document.getElementById('exp-back-btn').onclick = () => renderStep('initial');
                document.getElementById('exp-start-team-btn').onclick = () => {
                    let wid = '';
                    const rc = dialog.querySelector('input[name="exp_workspace_id"]:checked');
                    const ce = document.getElementById('exp-workspace-id-code');
                    const ie = document.getElementById('exp-team-id-input');
                    if (rc) wid = rc.value; else if (ce) wid = ce.textContent; else if (ie) wid = ie.value.trim();
                    if (!wid) { alert('请选择或输入一个有效的 Team Workspace ID!'); return; }
                    doExport('team', wid);
                };
            }
        };

        overlay.appendChild(dialog);
        document.body.appendChild(overlay);
        overlay.onclick = (e) => { if (e.target === overlay) closeDialog(); };
        renderStep('initial');
    }


    /* ═══════════════ CSS ═══════════════ */
    GM_addStyle(`
@keyframes tm-spin{to{transform:rotate(360deg)}}
@keyframes tm-in{from{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:none}}
@keyframes tm-pop{0%{transform:scale(0);opacity:0}60%{transform:scale(1.08)}100%{transform:scale(1);opacity:1}}
@keyframes tm-bar{from{width:100%}to{width:0}}
@keyframes tm-pulse{0%,100%{box-shadow:0 4px 20px rgba(16,163,127,.5),0 0 0 0 rgba(16,163,127,.3)}50%{box-shadow:0 4px 20px rgba(16,163,127,.5),0 0 0 8px rgba(16,163,127,0)}}
@keyframes tm-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}
@keyframes tm-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
@keyframes tm-glow{0%,100%{opacity:.5}50%{opacity:1}}
@keyframes tm-slideUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes tm-aurora{0%{background-position:0% 50%}25%{background-position:100% 0%}50%{background-position:100% 100%}75%{background-position:0% 100%}100%{background-position:0% 50%}}
@keyframes tm-lightsweep{0%{transform:translateX(-200%) skewX(-18deg);opacity:0}15%{opacity:1}85%{opacity:1}100%{transform:translateX(700%) skewX(-18deg);opacity:0}}
@keyframes tm-borderShift{0%,100%{border-color:rgba(16,163,127,.22)}33%{border-color:rgba(99,102,241,.18)}66%{border-color:rgba(236,72,153,.16)}}
@keyframes tm-breathe{0%,100%{box-shadow:0 0 0 2px rgba(16,163,127,.12),inset 0 0 8px rgba(16,163,127,.02)}50%{box-shadow:0 0 0 3px rgba(16,163,127,.35),inset 0 0 20px rgba(16,163,127,.07)}}
@keyframes tm-stagger{from{opacity:0;transform:translateY(16px) scale(.97)}to{opacity:1;transform:none}}
@keyframes tm-rippleOut{0%{transform:scale(0);opacity:.4}100%{transform:scale(1);opacity:0}}
@keyframes tm-cardShine{from{transform:translateX(-250%) skewX(-18deg)}to{transform:translateX(500%) skewX(-18deg)}}
@keyframes tm-iconPop{0%{transform:scale(1)}40%{transform:scale(.8) rotate(-8deg)}70%{transform:scale(1.18) rotate(4deg)}100%{transform:scale(1) rotate(0)}}
@keyframes tm-fabMorph{0%,100%{box-shadow:0 4px 20px rgba(16,163,127,.5),0 0 0 0 rgba(16,163,127,.25),0 0 30px rgba(16,163,127,.15)}33%{box-shadow:0 4px 20px rgba(99,102,241,.5),0 0 0 0 rgba(99,102,241,.25),0 0 30px rgba(99,102,241,.15)}66%{box-shadow:0 4px 20px rgba(236,72,153,.5),0 0 0 0 rgba(236,72,153,.25),0 0 30px rgba(236,72,153,.15)}}
@keyframes tm-toastSlide{from{transform:translateX(-50%) translateY(-30px) scale(.85);opacity:0}to{transform:translateX(-50%) translateY(0) scale(1);opacity:1}}
@keyframes tm-successPulse{0%{box-shadow:0 0 0 0 rgba(16,163,127,.45)}70%{box-shadow:0 0 0 22px rgba(16,163,127,0)}100%{box-shadow:0 0 0 0 rgba(16,163,127,0)}}
@keyframes tm-titleGradient{0%{background-position:0% center}100%{background-position:200% center}}
@keyframes tm-glassRefract{0%,100%{background-position:0% 0%}50%{background-position:100% 100%}}
@keyframes tm-dotFloat{0%{transform:translateY(0) scale(1);opacity:.4}50%{transform:translateY(-12px) scale(1.3);opacity:.8}100%{transform:translateY(0) scale(1);opacity:.4}}
#tm-app-root{font-family:'Segoe UI',Inter,-apple-system,BlinkMacSystemFont,Roboto,sans-serif;position:fixed;bottom:24px;right:24px;z-index:2147483647;display:flex;flex-direction:column-reverse;align-items:flex-end;gap:12px;pointer-events:none}
#tm-app-root *{box-sizing:border-box}
.tm-fab{width:50px;height:50px;border-radius:50%;background:linear-gradient(135deg,#10a37f 0%,#0d8a6a 100%);box-shadow:0 4px 20px rgba(16,163,127,.5),0 0 0 0 rgba(16,163,127,.3);border:none;cursor:grab;display:flex;align-items:center;justify-content:center;transition:.3s cubic-bezier(.34,1.56,.64,1);color:#fff;pointer-events:auto;touch-action:none;user-select:none;position:relative;overflow:hidden;animation:tm-pulse 3s ease-in-out infinite}
.tm-fab::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at 30% 30%,rgba(255,255,255,.2),transparent 60%);pointer-events:none}
.tm-fab:hover{transform:scale(1.08);box-shadow:0 6px 24px rgba(16,163,127,.6),0 0 0 4px rgba(16,163,127,.15)}
.tm-fab:active{cursor:grabbing}
.tm-fab.open{background:linear-gradient(135deg,#1a1a2e,#16213e);box-shadow:0 4px 20px rgba(0,0,0,.4);animation:none}
.tm-fab.open svg{transform:rotate(45deg)}
.tm-fab.dragging{cursor:grabbing!important;transform:scale(1.12);box-shadow:0 8px 32px rgba(16,163,127,.65)}
#tm-app-root.dragging .tm-panel{opacity:0!important;pointer-events:none!important;transform:translateY(12px) scale(.92)!important}
.tm-fab svg{width:22px;height:22px;transition:transform .35s cubic-bezier(.4,0,.2,1);filter:drop-shadow(0 1px 2px rgba(0,0,0,.2))}
.tm-panel{width:300px;background:rgba(15,15,25,.88);backdrop-filter:blur(20px) saturate(1.4);-webkit-backdrop-filter:blur(20px) saturate(1.4);border:1px solid rgba(255,255,255,.08);border-radius:20px;box-shadow:0 16px 48px rgba(0,0,0,.35),0 0 0 1px rgba(255,255,255,.05) inset;overflow:hidden;opacity:0;transform:translateY(14px) scale(.92);pointer-events:none;transform-origin:bottom right;transition:.32s cubic-bezier(.34,1.56,.64,1)}
.tm-panel.show{opacity:1;transform:none;pointer-events:auto}
.tm-p-head{padding:18px 18px 6px;display:flex;justify-content:space-between;align-items:center}
.tm-p-title{font-size:16px;font-weight:700;color:#fff;letter-spacing:-.3px}
.tm-p-ver{font-size:9px;color:rgba(255,255,255,.45);background:rgba(255,255,255,.08);padding:3px 8px;border-radius:6px;font-weight:600;letter-spacing:.3px}
.tm-p-body{padding:8px 10px 12px}
.tm-g{display:grid;grid-template-columns:1fr 1fr 1fr;gap:5px;margin-bottom:8px}
.tm-gi{display:flex;flex-direction:column;align-items:center;gap:6px;padding:12px 6px;border-radius:14px;border:1px solid transparent;background:rgba(255,255,255,.04);cursor:pointer;transition:.2s;color:rgba(255,255,255,.8);opacity:0;animation:tm-slideUp .35s ease forwards}
.tm-panel.show .tm-gi:nth-child(1){animation-delay:.05s}
.tm-panel.show .tm-gi:nth-child(2){animation-delay:.08s}
.tm-panel.show .tm-gi:nth-child(3){animation-delay:.11s}
.tm-panel.show .tm-gi:nth-child(4){animation-delay:.14s}
.tm-panel.show .tm-gi:nth-child(5){animation-delay:.17s}
.tm-panel.show .tm-gi:nth-child(6){animation-delay:.2s}
.tm-panel.show .tm-gi:nth-child(7){animation-delay:.23s}
.tm-gi:hover{background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.08);transform:translateY(-1px)}
.tm-gi:active{transform:scale(.95);background:rgba(255,255,255,.06)}
.tm-gi-ic{width:36px;height:36px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:17px;box-shadow:0 2px 8px rgba(0,0,0,.2);transition:.3s cubic-bezier(.34,1.56,.64,1)}
.tm-gi:hover .tm-gi-ic{transform:scale(1.12) translateY(-2px);box-shadow:0 4px 14px rgba(0,0,0,.3)}
.tm-gi-lb{font-size:10px;font-weight:600;line-height:1.2;text-align:center;opacity:.85}
.tm-sep{height:1px;background:rgba(255,255,255,.06);margin:4px 10px}
.tm-li{display:flex;align-items:center;gap:8px;padding:9px 12px;border-radius:10px;border:none;background:transparent;cursor:pointer;transition:.2s;color:rgba(255,255,255,.5);width:100%;text-align:left;font-size:12px;font-weight:500;opacity:0;animation:tm-slideUp .3s ease forwards;animation-delay:.25s}
.tm-li+.tm-li{animation-delay:.3s}
.tm-li:hover{background:rgba(255,255,255,.07);color:rgba(255,255,255,.8);padding-left:16px}
.tm-li svg{width:15px;height:15px;opacity:.4;flex-shrink:0}
/* Modal - Liquid Glass */
.tm-ov{position:fixed;inset:0;background:rgba(0,0,0,.4);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);z-index:2147483648;display:flex;justify-content:center;align-items:center;opacity:0;visibility:hidden;transition:.3s}
.tm-ov.show{opacity:1;visibility:visible}
.tm-md{background:rgba(255,255,255,.06);backdrop-filter:blur(20px) saturate(1.4);-webkit-backdrop-filter:blur(20px) saturate(1.4);width:420px;max-width:92vw;max-height:85vh;border-radius:24px;overflow:hidden;transform:translateY(24px) scale(.92) rotateX(2deg);transition:.4s cubic-bezier(.34,1.56,.64,1);display:flex;flex-direction:column;box-shadow:0 24px 80px rgba(0,0,0,.35),inset 0 1px 0 rgba(255,255,255,.2),inset 0 -1px 0 rgba(255,255,255,.05),inset 0 0 30px rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.12)}
.tm-ov.show .tm-md{transform:none}
.tm-md-h{padding:14px 18px;border-bottom:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:space-between;background:rgba(255,255,255,.03)}
.tm-md-t{font-size:15px;font-weight:700;color:rgba(255,255,255,.95);display:flex;align-items:center;gap:6px;text-shadow:0 1px 2px rgba(0,0,0,.2)}
.tm-md-x{width:28px;height:28px;border-radius:8px;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.06);color:rgba(255,255,255,.5);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:.2s}
.tm-md-x:hover{background:rgba(239,68,68,.65);color:#fff;border-color:rgba(239,68,68,.3)}
.tm-md-b{padding:16px 18px;overflow-y:auto;flex:1}
.tm-md-b::-webkit-scrollbar{width:5px}.tm-md-b::-webkit-scrollbar-track{background:transparent}.tm-md-b::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:4px}.tm-md-b::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.2)}
.tm-md-f{padding:12px 18px;border-top:1px solid rgba(255,255,255,.08);display:flex;justify-content:flex-end;gap:6px;background:rgba(255,255,255,.02)}
/* Form - Liquid Glass */
.tm-inp{width:100%;padding:9px 12px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:10px;font-size:13px;color:#fff!important;outline:none;transition:.25s}
.tm-inp:focus{border-color:rgba(16,163,127,.5);box-shadow:0 0 0 2px rgba(16,163,127,.15),inset 0 0 10px rgba(16,163,127,.05);background:rgba(255,255,255,.1)}
.tm-inp::placeholder{color:rgba(255,255,255,.3)}
.tm-sel{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' fill='%23aaa' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;padding-right:28px;}
.tm-sel option{background:#1a1a2e;color:rgba(255,255,255,1);}
.tm-lbl{display:block;margin-bottom:4px;font-size:11px;font-weight:600;color:rgba(255,255,255,.55);text-transform:uppercase;letter-spacing:.3px}
.tm-fld{margin-bottom:14px}
.tm-fld:last-child{margin-bottom:0}
.tm-chk{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:12px;color:rgba(255,255,255,.75)}
.tm-chk input{width:16px;height:16px;accent-color:#10a37f}
/* Buttons - Liquid Glass */
.tm-btn{border:1px solid rgba(255,255,255,.08);padding:8px 14px;border-radius:10px;font-size:12px;font-weight:600;cursor:pointer;transition:.25s cubic-bezier(.4,0,.2,1);display:inline-flex;align-items:center;gap:4px;position:relative;overflow:hidden}
.tm-btn:hover{filter:brightness(1.15);transform:translateY(-1px);box-shadow:0 4px 16px rgba(0,0,0,.15)}
.tm-btn:active{transform:scale(.95) translateY(0);box-shadow:none}
.tm-btn-p{background:rgba(16,163,127,.6);color:#fff;border-color:rgba(16,163,127,.25);box-shadow:0 2px 10px rgba(16,163,127,.2)}
.tm-btn-s{background:rgba(255,255,255,.08);color:rgba(255,255,255,.7);border-color:rgba(255,255,255,.1)}
.tm-btn-d{background:rgba(239,68,68,.12);color:rgba(239,68,68,.9);border-color:rgba(239,68,68,.12)}
.tm-btn-sm{padding:4px 10px;font-size:11px;border-radius:8px}
/* Cards - Liquid Glass */
.tm-card{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:12px;margin-bottom:8px;transition:.25s}
.tm-card:hover{border-color:rgba(16,163,127,.35);box-shadow:0 4px 16px rgba(16,163,127,.1),inset 0 0 15px rgba(16,163,127,.03);transform:translateY(-1px)}
.tm-card-t{font-size:12px;font-weight:600;color:rgba(255,255,255,.92);word-break:break-all}
.tm-card-sub{font-size:11px;color:rgba(255,255,255,.5);font-family:monospace;margin-top:2px}
.tm-card-meta{font-size:10px;color:rgba(255,255,255,.35);margin-top:4px}
.tm-card-acts{display:flex;gap:4px;margin-top:8px;flex-wrap:wrap}
.tm-empty{text-align:center;padding:32px 16px;color:rgba(255,255,255,.4);font-size:13px}
/* Code - Liquid Glass */
.tm-code{background:rgba(0,0,0,.2);border:1px solid rgba(255,255,255,.08);border-radius:10px;padding:10px 12px;font-family:'SF Mono',Menlo,monospace;font-size:11px;color:rgba(255,255,255,.8);word-break:break-all;max-height:100px;overflow-y:auto}
/* Alert - Liquid Glass */
.tm-alert{padding:10px 12px;border-radius:10px;font-size:11px;display:flex;align-items:flex-start;gap:6px;margin-bottom:12px}
.tm-alert-w{background:rgba(251,191,36,.1);border:1px solid rgba(251,191,36,.2);color:rgba(251,191,36,.9)}
.tm-alert-s{background:rgba(16,185,129,.1);border:1px solid rgba(16,185,129,.2);color:rgba(16,185,129,.9)}
.tm-alert-e{background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.2);color:rgba(239,68,68,.9)}
/* Status bar */
/* Toast */
.tm-toast{position:fixed;top:16px;left:50%;transform:translateX(-50%) translateY(-20px);z-index:2147483650;display:flex;align-items:center;gap:8px;padding:10px 18px;border-radius:12px;font-size:13px;font-weight:600;box-shadow:0 8px 32px rgba(0,0,0,.2);opacity:0;visibility:hidden;transition:.35s cubic-bezier(.34,1.56,.64,1);pointer-events:none}
.tm-toast.show{opacity:1;visibility:visible;pointer-events:auto;transform:translateX(-50%) translateY(0)}
.tm-toast.loading{background:linear-gradient(135deg,#10a37f,#0e8c6b);color:#fff}
.tm-toast.success{background:linear-gradient(135deg,#059669,#047857);color:#fff}
.tm-toast.error{background:linear-gradient(135deg,#dc2626,#b91c1c);color:#fff}
.tm-toast .sp{width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:tm-spin .7s linear infinite}
.tm-sbar{position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:2147483650;display:flex;align-items:center;gap:8px;padding:10px 18px;border-radius:10px;font-size:13px;font-weight:600;box-shadow:0 6px 24px rgba(0,0,0,.15);background:linear-gradient(135deg,#10a37f,#0e8c6b);color:#fff;display:none}
.tm-sbar.show{display:flex}
.tm-sbar .sp{width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:tm-spin .7s linear infinite}
.tm-sbar .x{background:rgba(255,255,255,.2);border:none;color:#fff;padding:3px 10px;border-radius:5px;font-size:11px;font-weight:600;cursor:pointer;margin-left:10px}
.tm-sbar .x:hover{background:rgba(255,255,255,.3)}
/* Success - Liquid Glass */
.tm-suc-ic{width:64px;height:64px;margin:0 auto 12px;background:rgba(16,163,127,.15);border:1px solid rgba(16,163,127,.2);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:30px;animation:tm-pop .5s ease-out;box-shadow:0 4px 16px rgba(16,163,127,.15)}
.tm-suc-t{font-size:18px;font-weight:700;color:rgba(16,185,129,.95);margin-bottom:4px;text-shadow:0 1px 3px rgba(0,0,0,.15)}
.tm-suc-sub{font-size:12px;color:rgba(255,255,255,.5);margin-bottom:16px}
.tm-suc-info{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:12px;margin-bottom:12px}
.tm-suc-row{display:flex;justify-content:space-between;align-items:center;padding:6px 0}
.tm-suc-row+.tm-suc-row{border-top:1px solid rgba(255,255,255,.06)}
.tm-suc-lb{font-size:11px;color:rgba(255,255,255,.4);font-weight:500}
.tm-suc-val{font-size:12px;color:rgba(255,255,255,.9);font-weight:600;font-family:monospace;word-break:break-all;max-width:200px;text-align:right}
.tm-suc-redir{background:rgba(16,185,129,.08);border:1px solid rgba(16,185,129,.15);border-radius:10px;padding:10px 12px;margin-bottom:12px}
.tm-suc-redir-txt{font-size:12px;color:rgba(16,185,129,.9);font-weight:500;margin-bottom:8px}
.tm-suc-prog{height:3px;background:rgba(16,185,129,.1);border-radius:2px;overflow:hidden}
.tm-suc-prog-bar{height:100%;background:linear-gradient(90deg,rgba(16,185,129,.8),rgba(5,150,105,.8));border-radius:2px;width:100%}
/* ═══════════════ Liquid Glass Animations ═══════════════ */
/* Modal aurora background + light sweep */
.tm-md{position:relative;animation:tm-borderShift 8s ease infinite}
.tm-md::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(16,163,127,.06),rgba(99,102,241,.04),rgba(236,72,153,.03),rgba(59,130,246,.04),rgba(16,163,127,.06));background-size:300% 300%;animation:tm-aurora 15s ease infinite;pointer-events:none;z-index:0;border-radius:24px}
.tm-md::after{content:'';position:absolute;top:0;left:0;width:22%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.08),rgba(255,255,255,.03),transparent);pointer-events:none;z-index:1;animation:tm-lightsweep 8s ease-in-out 2s infinite;will-change:transform,opacity}
.tm-md-h,.tm-md-b,.tm-md-f{position:relative;z-index:2}
/* Staggered entrance for form fields */
.tm-ov.show .tm-fld{opacity:0;animation:tm-stagger .5s cubic-bezier(.16,1,.3,1) forwards}
.tm-ov.show .tm-fld:nth-child(1){animation-delay:.04s}
.tm-ov.show .tm-fld:nth-child(2){animation-delay:.08s}
.tm-ov.show .tm-fld:nth-child(3){animation-delay:.12s}
.tm-ov.show .tm-fld:nth-child(4){animation-delay:.16s}
.tm-ov.show .tm-fld:nth-child(5){animation-delay:.2s}
.tm-ov.show .tm-fld:nth-child(6){animation-delay:.24s}
.tm-ov.show .tm-fld:nth-child(7){animation-delay:.28s}
.tm-ov.show .tm-fld:nth-child(8){animation-delay:.32s}
.tm-ov.show .tm-alert{opacity:0;animation:tm-stagger .5s cubic-bezier(.16,1,.3,1) .02s forwards}
.tm-ov.show .tm-chk{opacity:0;animation:tm-stagger .45s cubic-bezier(.16,1,.3,1) .2s forwards}
/* Input breathing glow on focus */
.tm-inp:focus{animation:tm-breathe 2.5s ease-in-out infinite}
/* Card hover shine sweep */
.tm-card{position:relative;overflow:hidden}
.tm-card::after{content:'';position:absolute;top:0;left:0;width:40%;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.07),rgba(255,255,255,.02),transparent);pointer-events:none;z-index:1;will-change:transform}
.tm-card:hover::after{animation:tm-cardShine .7s ease}
/* Grid icon bounce on click */
.tm-gi:active .tm-gi-ic{animation:tm-iconPop .45s cubic-bezier(.34,1.56,.64,1)}
.tm-gi:hover .tm-gi-ic{transform:scale(1.15) translateY(-3px) rotate(3deg);box-shadow:0 8px 24px rgba(0,0,0,.35),0 0 15px rgba(255,255,255,.08)}
.tm-gi{transition:.25s cubic-bezier(.34,1.56,.64,1)}
.tm-gi:hover{transform:translateY(-2px)}
/* FAB rainbow morph glow */
.tm-fab{animation:tm-fabMorph 6s ease infinite}
.tm-fab.open{animation:none}
.tm-fab:hover{animation:none;box-shadow:0 6px 28px rgba(16,163,127,.6),0 0 0 5px rgba(16,163,127,.12)}
/* Glass toast notifications */
.tm-toast{backdrop-filter:blur(10px) saturate(1.3);-webkit-backdrop-filter:blur(10px) saturate(1.3);border:1px solid rgba(255,255,255,.15)}
.tm-toast.show{animation:tm-toastSlide .45s cubic-bezier(.34,1.56,.64,1)}
.tm-toast.loading{background:linear-gradient(135deg,rgba(16,163,127,.85),rgba(14,140,107,.85))}
.tm-toast.success{background:linear-gradient(135deg,rgba(5,150,105,.85),rgba(4,120,87,.85))}
.tm-toast.error{background:linear-gradient(135deg,rgba(220,38,38,.85),rgba(185,28,28,.85))}
/* Success icon pulse ring */
.tm-suc-ic{animation:tm-pop .5s ease-out,tm-successPulse 1.5s ease .5s}
/* Panel aurora + floating dots */
.tm-panel{position:relative;overflow:hidden}
.tm-panel::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(16,163,127,.05),rgba(99,102,241,.04),transparent,rgba(236,72,153,.03));background-size:300% 300%;animation:tm-aurora 12s ease infinite;pointer-events:none;border-radius:20px;z-index:0}
.tm-panel>*{position:relative;z-index:1}
/* Panel title shimmer gradient */
.tm-p-title{background:linear-gradient(90deg,#fff 0%,rgba(16,163,127,.8) 45%,rgba(99,102,241,.8) 55%,#fff 100%);background-size:200% 100%;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;animation:tm-titleGradient 4s ease infinite}
/* Version badge float */
.tm-p-ver{animation:tm-float 3s ease-in-out infinite}
/* Close button spin on hover */
.tm-md-x{transition:.25s cubic-bezier(.34,1.56,.64,1)}
.tm-md-x:hover{transform:scale(1.1) rotate(90deg)}
/* Separator glass refraction */
.tm-sep{background:linear-gradient(90deg,transparent,rgba(255,255,255,.08),transparent);transition:.3s}
/* Status bar glass */
.tm-sbar{backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);background:linear-gradient(135deg,rgba(16,163,127,.85),rgba(14,140,107,.85));border:1px solid rgba(255,255,255,.12)}
/* Button hover glass highlight */
.tm-btn-p:hover{box-shadow:0 4px 20px rgba(16,163,127,.35),inset 0 1px 0 rgba(255,255,255,.15)}
.tm-btn-s:hover{box-shadow:0 4px 16px rgba(0,0,0,.12),inset 0 1px 0 rgba(255,255,255,.08)}
/* Card stagger entrance in accounts */
.tm-ov.show .tm-card{opacity:0;animation:tm-stagger .45s cubic-bezier(.16,1,.3,1) forwards}
.tm-ov.show .tm-card:nth-child(1){animation-delay:.03s}
.tm-ov.show .tm-card:nth-child(2){animation-delay:.06s}
.tm-ov.show .tm-card:nth-child(3){animation-delay:.09s}
.tm-ov.show .tm-card:nth-child(4){animation-delay:.12s}
.tm-ov.show .tm-card:nth-child(5){animation-delay:.15s}
.tm-ov.show .tm-card:nth-child(6){animation-delay:.18s}
.tm-ov.show .tm-card:nth-child(7){animation-delay:.21s}
.tm-ov.show .tm-card:nth-child(8){animation-delay:.24s}
.tm-ov.show .tm-card:nth-child(9){animation-delay:.27s}
.tm-ov.show .tm-card:nth-child(10){animation-delay:.3s}

/* ═══════════════ 移动端适配 ═══════════════ */
@media screen and (max-width:768px){
/* 主容器 - 移动端底部固定(不加!important,允许JS拖动覆盖) */
#tm-app-root{gap:10px}

/* FAB 按钮 - 移动端稍小一点 */
.tm-fab{width:46px;height:46px}
.tm-fab svg{width:20px;height:20px}

/* 面板 - 移动端底部固定弹出 */
.tm-panel{position:fixed!important;bottom:0!important;left:0!important;right:0!important;width:100%!important;max-width:100%!important;border-radius:20px 20px 0 0!important;transform:translateY(100%)!important;transform-origin:bottom center!important;z-index:2147483647}
.tm-panel.show{transform:translateY(0)!important}
.tm-panel::after{content:'';position:absolute;top:8px;left:50%;transform:translateX(-50%);width:36px;height:4px;border-radius:2px;background:rgba(255,255,255,.2);z-index:10}
.tm-p-head{padding:20px 16px 6px}
.tm-p-title{font-size:16px}
.tm-p-body{padding:8px 12px calc(12px + env(safe-area-inset-bottom,0px))}

/* 面板打开时的遮罩 */
.tm-panel-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);z-index:2147483646;opacity:0;transition:opacity .3s}
.tm-panel-backdrop.show{display:block;opacity:1}

/* 网格 - 移动端保持3列但缩小间距 */
.tm-g{gap:4px;margin-bottom:6px}
.tm-gi{padding:10px 4px;border-radius:12px;gap:5px}
.tm-gi-ic{width:32px;height:32px;border-radius:8px;font-size:15px}
.tm-gi-lb{font-size:9px}

/* 底部列表项 */
.tm-li{padding:8px 10px;font-size:11px;gap:6px}
.tm-li svg{width:14px;height:14px}

/* 分隔线 */
.tm-sep{margin:3px 8px}

/* 弹窗 overlay */
.tm-ov{align-items:flex-end;padding:0}

/* 弹窗 modal - 移动端底部弹出式 */
.tm-md{width:100%!important;max-width:100vw!important;max-height:92vh!important;border-radius:20px 20px 0 0!important;margin:0!important;transform:translateY(100%) scale(1)!important}
.tm-ov.show .tm-md{transform:translateY(0) scale(1)!important}
.tm-md::before{border-radius:20px 20px 0 0}

/* 弹窗顶部拖拽指示条 */
.tm-md::after{content:'';position:absolute;top:8px;left:50%;transform:translateX(-50%);width:36px;height:4px;border-radius:2px;background:rgba(255,255,255,.2);z-index:10;animation:none!important}

/* 弹窗头部 */
.tm-md-h{padding:18px 16px 10px}
.tm-md-t{font-size:14px}
.tm-md-x{width:32px;height:32px;border-radius:10px;font-size:16px}

/* 弹窗内容区 */
.tm-md-b{padding:12px 14px;max-height:calc(92vh - 120px)!important;-webkit-overflow-scrolling:touch}

/* 弹窗底部 */
.tm-md-f{padding:10px 14px calc(10px + env(safe-area-inset-bottom,0px));gap:6px;flex-wrap:wrap}

/* 表单元素 - 移动端更大的触摸区域 */
.tm-inp{padding:11px 14px;font-size:14px;border-radius:12px}
.tm-lbl{font-size:11px;margin-bottom:5px}
.tm-fld{margin-bottom:12px}
.tm-chk{font-size:13px;gap:10px;padding:4px 0}
.tm-chk input{width:20px;height:20px}

/* 按钮 - 移动端更大触摸区域 */
.tm-btn{padding:10px 16px;font-size:13px;border-radius:12px;min-height:40px}
.tm-btn-sm{padding:8px 12px;font-size:12px;border-radius:10px;min-height:36px}

/* 卡片 - 移动端适配 */
.tm-card{padding:12px;border-radius:14px;margin-bottom:8px}
.tm-card-t{font-size:13px}
.tm-card-sub{font-size:12px}
.tm-card-meta{font-size:11px}
.tm-card-acts{gap:6px;margin-top:10px}
.tm-card-acts .tm-btn{flex:1;justify-content:center;min-width:0;text-align:center;padding:8px 6px}

/* 代码块 */
.tm-code{font-size:11px;padding:10px;border-radius:10px;max-height:120px;word-break:break-all}

/* 提示框 */
.tm-alert{padding:10px;font-size:12px;border-radius:10px}

/* Toast 通知 - 移动端更宽 */
.tm-toast{left:12px!important;right:12px!important;transform:translateX(0) translateY(-20px)!important;max-width:none;border-radius:14px;padding:12px 16px;font-size:13px}
.tm-toast.show{transform:translateX(0) translateY(0)!important}

/* 状态栏 - 移动端更宽 */
.tm-sbar{left:12px!important;right:12px!important;transform:translateX(0)!important;max-width:none;border-radius:12px;padding:10px 14px;font-size:12px}

/* 成功图标 */
.tm-suc-ic{width:56px;height:56px;font-size:26px}
.tm-suc-t{font-size:16px}
.tm-suc-sub{font-size:12px}
.tm-suc-val{max-width:180px;font-size:11px}

/* 空状态 */
.tm-empty{padding:24px 14px;font-size:13px}

/* 收件箱邮件内容 */
#tm-mail-content{max-height:280px!important;padding:12px;font-size:13px}

/* 分页按钮 */
#tm-pg-first,#tm-pg-prev,#tm-pg-next,#tm-pg-last{min-height:34px;padding:6px 10px}

/* 设置页 - 移动端底部按钮区域 */
.tm-md-f .tm-btn{flex:none}

/* 关于页 */
.tm-md[style*="max-width:360px"] .tm-md-b{padding:16px 14px}

/* 账号弹窗底部按钮 - 移动端自动换行 */

/* 设置弹窗底部按钮 */
#tm-modal-settings .tm-md-f{flex-wrap:wrap;gap:6px}
#tm-modal-settings .tm-md-f .tm-btn{flex:1 1 auto;min-width:0;justify-content:center;text-align:center}

/* 收件箱 - 移动端适配 */
}

/* 更小屏幕适配 (iPhone SE 等) */
@media screen and (max-width:375px){
.tm-fab{width:42px;height:42px}
.tm-fab svg{width:18px;height:18px}
.tm-panel{width:calc(100vw - 16px);max-width:100%}
.tm-g{grid-template-columns:1fr 1fr 1fr;gap:3px}
.tm-gi{padding:8px 3px;gap:4px}
.tm-gi-ic{width:28px;height:28px;font-size:13px;border-radius:7px}
.tm-gi-lb{font-size:8px}
.tm-md-h{padding:16px 12px 8px}
.tm-md-b{padding:10px 12px}
.tm-md-f{padding:8px 12px calc(8px + env(safe-area-inset-bottom,0px));gap:4px}
.tm-inp{padding:10px 12px;font-size:14px}
.tm-btn{padding:9px 12px;font-size:12px;min-height:38px}
.tm-btn-sm{padding:7px 10px;font-size:11px;min-height:34px}
.tm-card-acts{flex-wrap:wrap}
.tm-card-acts .tm-btn{flex:1 1 calc(50% - 3px);min-width:0}
.tm-toast{left:8px!important;right:8px!important;padding:10px 14px;font-size:12px}
.tm-sbar{left:8px!important;right:8px!important;padding:8px 12px;font-size:11px}
}

/* 横屏模式适配 */
@media screen and (max-height:500px) and (orientation:landscape){
.tm-md{max-height:96vh!important}
.tm-md-b{max-height:calc(96vh - 110px)!important}
.tm-fab{width:40px;height:40px}
.tm-fab svg{width:18px;height:18px}
.tm-suc-ic{width:40px;height:40px;font-size:20px;margin-bottom:6px}
.tm-suc-t{font-size:14px}
}

/* 安全区域适配 (刘海屏/底部横条) */
@supports(padding-bottom:env(safe-area-inset-bottom)){
@media screen and (max-width:768px){
.tm-md-f{padding-bottom:calc(10px + env(safe-area-inset-bottom,0px))}
.tm-toast{top:calc(16px + env(safe-area-inset-top,0px))!important}
.tm-sbar{top:calc(16px + env(safe-area-inset-top,0px))!important}
}
}

/* 触摸设备优化 */
@media(hover:none) and (pointer:coarse){
.tm-gi{-webkit-tap-highlight-color:transparent}
.tm-btn{-webkit-tap-highlight-color:transparent}
.tm-card{-webkit-tap-highlight-color:transparent}
.tm-li{-webkit-tap-highlight-color:transparent}
.tm-md-x{-webkit-tap-highlight-color:transparent}
.tm-gi:hover{transform:none;background:rgba(255,255,255,.04);border-color:transparent}
.tm-gi:hover .tm-gi-ic{transform:none;box-shadow:0 2px 8px rgba(0,0,0,.2)}
.tm-gi:active{transform:scale(.95);background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.08)}
.tm-gi:active .tm-gi-ic{transform:scale(1.08)}
.tm-card:hover{border-color:rgba(255,255,255,.08);box-shadow:none;transform:none}
.tm-card:active{border-color:rgba(16,163,127,.35);transform:scale(.98)}
.tm-btn:hover{filter:none;transform:none;box-shadow:none}
.tm-btn:active{transform:scale(.95);filter:brightness(1.1)}
.tm-li:hover{background:transparent;color:rgba(255,255,255,.5);padding-left:12px}
.tm-li:active{background:rgba(255,255,255,.07);color:rgba(255,255,255,.8)}
}
`);

    /* ═══════════════ 工具函数 ═══════════════ */
    function _0x7b(t) { GM_setClipboard(t, 'text'); return !0; }
    const _0x8c = ['James', 'John', 'Robert', 'Michael', 'William', 'David', 'Richard', 'Joseph', 'Thomas', 'Charles', 'Mary', 'Patricia', 'Jennifer', 'Linda', 'Barbara', 'Elizabeth', 'Susan', 'Jessica', 'Sarah', 'Karen', 'Emma', 'Olivia', 'Ava', 'Sophia', 'Isabella', 'Liam', 'Noah', 'Oliver', 'Elijah', 'Lucas'];
    const _0x9d = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis', 'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson', 'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin', 'Lee', 'Thompson', 'White', 'Harris', 'Clark'];
    function _0xae(l = 0x10) { const c = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%'; let p = ''; p += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[Math.floor(Math.random() * 0x1a)]; p += 'abcdefghijklmnopqrstuvwxyz'[Math.floor(Math.random() * 0x1a)]; p += '0123456789'[Math.floor(Math.random() * 0xa)]; p += '!@#$%'[Math.floor(Math.random() * 0x5)]; for (let i = 0x4; i < l; i++) { p += c[Math.floor(Math.random() * c.length)]; } return p.split('').sort(() => Math.random() - 0.5).join(''); }
    function _0xbf() { return { firstName: _0x8c[Math.floor(Math.random() * _0x8c.length)], lastName: _0x9d[Math.floor(Math.random() * _0x9d.length)] }; }
    function _0xc0() { const y = new Date().getFullYear(); const yr = y - 0x12 - Math.floor(Math.random() * 0x1e); const m = Math.floor(Math.random() * 0xc) + 0x1; const d = Math.floor(Math.random() * 0x1c) + 0x1; return { year: yr, month: m, day: d }; }

    /* ═══════════════ NPCmail API ═══════════════ */
    function _0xd1(e, o = {}) { const k = GM_getValue(_0x4e.API_KEY, ''); if (!k) { return Promise.reject(new Error('请先配置 NPCmail 密钥')); } return new Promise((r, j) => { GM_xmlhttpRequest({ method: o.method || 'GET', url: _0x3c + e, headers: { 'X-API-Key': k, 'Content-Type': _0xb('YXBwbGljYXRpb24vanNvbg==') }, data: o.body ? JSON.stringify(o.body) : undefined, onload: function (rs) { try { const d = JSON.parse(rs.responseText); if (rs.status >= 0xc8 && rs.status < 0x12c) { r(d); } else { j(new Error(d.error || d.message || 'HTTP ' + rs.status)); } } catch (x) { j(new Error('JSON 解析失败')); } }, onerror: function (x) { j(new Error('网络请求失败')); } }); }); }
    async function _0xe2() { return await _0xd1(_0xb('L2FwaS9wdWJsaWMvYXBpLWtleS9pbmZv')); }
    async function _0xf3(d = null, p = null) { const b = { count: 0x1, expiryDays: 0x1e }; d && (b.domain = d); p && (b.prefix = p); const r = await _0xd1(_0xb('L2FwaS9wdWJsaWMvYmF0Y2gtY3JlYXRlLWVtYWlscw=='), { method: 'POST', body: b }); if (r.emails && r.emails.length > 0x0) return r.emails[0x0]; throw new Error('创建邮箱失败'); }
    async function _0x115(a) { try { const r = await _0xd1(_0xb('L2FwaS9wdWJsaWMvZXh0cmFjdC1jb2Rlcw=='), { method: 'POST', body: { addresses: [a] } }); console.log('[_0x115] response:', JSON.stringify(r)); if (r && r.length > 0x0 && r[0x0].code) return r[0x0].code; if (r && r.codes && r.codes.length > 0 && r.codes[0].code) return r.codes[0].code; if (r && r.data && r.data.length > 0 && r.data[0].code) return r.data[0].code; return null; } catch (e) { console.error('[_0x115] error:', e); return null; } }
    async function _0x_npcMails(a) { return await _0xd1('/api/public/emails/' + encodeURIComponent(a) + '/messages'); }
    /* ═══════════════ GPTMail API ═══════════════ */
    function _gptReq(ep, k) {
        return new Promise((r, j) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: 'https://mail.chatgpt.org.uk/api' + ep,
                headers: { 'X-API-Key': k || 'gpt-test', 'Content-Type': 'application/json' },
                timeout: 15000,
                onload: function (rs) {
                    try {
                        const d = JSON.parse(rs.responseText);
                        if (d.success) r(d.data);
                        else j(new Error(d.error || 'GPTMail: false'));
                    } catch (x) { j(new Error('GPTMail: parse fail')); }
                },
                onerror: function () { j(new Error('GPTMail: network err')); },
                ontimeout: function () { j(new Error('GPTMail: timeout')); }
            });
        });
    }
    function _gptReqPost(ep, b, k) {
        return new Promise((r, j) => {
            GM_xmlhttpRequest({
                method: 'POST',
                url: 'https://mail.chatgpt.org.uk/api' + ep,
                headers: { 'X-API-Key': k || 'gpt-test', 'Content-Type': 'application/json' },
                data: JSON.stringify(b),
                timeout: 15000,
                onload: function (rs) {
                    try {
                        const d = JSON.parse(rs.responseText);
                        if (d.success) r(d.data);
                        else j(new Error(d.error || 'GPTMail: false'));
                    } catch (x) { j(new Error('GPTMail: parse fail')); }
                },
                onerror: function () { j(new Error('GPTMail: network err')); },
                ontimeout: function () { j(new Error('GPTMail: timeout')); }
            });
        });
    }

    /* ═══════════════ TempMail API ═══════════════ */
    function _0x_tmReq(ep) { return new Promise((r, j) => { GM_xmlhttpRequest({ method: 'GET', url: _0x_TM_API + ep, headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }, timeout: 15000, onload: function (rs) { try { const d = JSON.parse(rs.responseText); if (rs.status >= 200 && rs.status < 300) { r(d); } else { j(new Error('临时邮箱服务请求失败 ' + rs.status)); } } catch (x) { j(new Error('临时邮箱响应解析失败')); } }, onerror: function () { j(new Error('临时邮箱网络错误')); }, ontimeout: function () { j(new Error('临时邮箱请求超时')); } }); }); }
    async function _0x_tmInbox(email, epin) { return await _0x_tmReq('/mails?email=' + encodeURIComponent(email) + '&epin=' + (epin || '')); }
    async function _0x_tmMail(id, email, epin) { return await _0x_tmReq('/mails/' + id + '?email=' + encodeURIComponent(email) + '&epin=' + (epin || '')); }
    async function _0x_tmCode(email, epin) { try { const inbox = await _0x_tmInbox(email, epin); if (!inbox.mail_list || inbox.mail_list.length === 0) return null; const m = inbox.mail_list[0]; const lastId = GM_getValue('tm_last_mail_id', ''); if (lastId === m.mail_id) return null; const det = await _0x_tmMail(m.mail_id, email, epin); const all = (det.text || '') + ' ' + (det.html || '') + ' ' + (det.subject || m.subject || ''); let code = null; const mt = all.match(/\b(\d{6})\b/); if (mt) code = mt[1]; else { const mt2 = all.match(/\b(\d{4,8})\b/); if (mt2) code = mt2[1]; } if (code) { GM_setValue('tm_last_mail_id', m.mail_id); return code; } return null; } catch (e) { console.warn('[TempMail]', e); return null; } }

    /* ═══════════════ Team 后台 API ═══════════════ */
    function _0x_teamReq(baseUrl, method, path, apiKey, body) { return new Promise((r, j) => { const url = baseUrl.replace(/\/+$/, '') + path; GM_xmlhttpRequest({ method: method, url: url, headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' }, data: body ? JSON.stringify(body) : undefined, timeout: 120000, onload: function (rs) { try { const d = JSON.parse(rs.responseText); if (rs.status >= 200 && rs.status < 300) { r(d); } else { j(new Error(d.detail || d.message || d.error || 'HTTP ' + rs.status)); } } catch (x) { j(new Error('响应解析失败 (HTTP ' + rs.status + ')')); } }, onerror: function () { j(new Error('网络请求失败,请检查地址')); }, ontimeout: function () { j(new Error('请求超时')); } }); }); }
    async function _0x_pushToTeam() {
        const url = (GM_getValue('tm_team_url', '') || '')
            .trim()
            .replace(/\/+$/, '')
            .replace(/\/external\/push$/i, '')
            .replace(/\/external$/i, '');
        const key = (GM_getValue('tm_team_key', '') || '').trim().replace(/^Bearer\s+/i, '');
        if (!url || !key) throw new Error('请先在设置中配置 Team 后台地址和密钥');

        let token = null;
        try {
            const sr = await fetch(_0xb('L2FwaS9hdXRoL3Nlc3Npb24='));
            const ct = sr.headers.get('content-type');
            if (ct && ct.includes('application/json')) {
                const tk = await sr.json();
                if (tk.accessToken) token = tk.accessToken;
            }
        } catch (e) { }
        if (!token) throw new Error('请先登录 ChatGPT');
        return await _0x_teamReq(url, 'POST', '/external/push', key, { access_token: token });
    }

    async function _0x_doPush() {
        _tmToast('正在推送当前账号...', 'loading');
        try {
            const res = await _0x_pushToTeam();
            if (res && res.success === false) {
                _tmToast(res.message || res.error || '导入失败', 'error', 4500);
            } else {
                const msg = (res && res.message) ? res.message : '导入成功';
                _tmToast(msg, 'success', 3500);
            }
        } catch (e) {
            _tmToast((e && e.message) ? e.message : '推送失败', 'error', 4500);
        }
    }

    /* ═══════════════ 自定义域名 ═══════════════ */
    function _0x_getCDs() { return GM_getValue('tm_custom_domains', []); }
    function _0x_setCDs(d) { GM_setValue('tm_custom_domains', d); }
    function _0x_addCD(d) { d = d.trim().toLowerCase().replace(/^@/, ''); if (!d || !/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/.test(d)) return false; const ds = _0x_getCDs(); if (ds.includes(d)) return false; ds.push(d); _0x_setCDs(ds); return true; }
    function _0x_rmCD(d) { _0x_setCDs(_0x_getCDs().filter(x => x !== d)); }
    function _0x_randPfx(n = 12) { const c = 'abcdefghijklmnopqrstuvwxyz0123456789'; let r = c[Math.floor(Math.random() * 26)]; for (let i = 1; i < n; i++)r += c[Math.floor(Math.random() * c.length)]; return r; }
    function _0x_renderCDs() { const el = document.getElementById('tm-cd-list'); if (!el) return; const ds = _0x_getCDs(); if (ds.length === 0) { el.innerHTML = '<div style="font-size:11px;color:#aaa;padding:6px;text-align:center">暂未添加域名</div>'; return; } el.innerHTML = ds.map(d => '<div style="display:flex;align-items:center;justify-content:space-between;padding:5px 8px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:8px;margin-bottom:3px"><span style="font-size:11px;font-family:monospace;color:rgba(255,255,255,.8)">' + d + '</span><button class="tm-btn tm-btn-d tm-btn-sm" data-rmcd="' + d + '" style="padding:2px 6px;font-size:10px">✕</button></div>').join(''); el.querySelectorAll('[data-rmcd]').forEach(b => { b.onclick = function () { _0x_rmCD(this.dataset.rmcd); _0x_renderCDs(); }; }); }

    /* ═══════════════ 数据存取 ═══════════════ */
    function _0x126() { return GM_getValue(_0x4e.ACCOUNTS, []); }
    function _0x137(a) { const ac = _0x126(); const i = ac.findIndex(x => x.email === a.email); i >= 0x0 ? ac[i] = { ...ac[i], ...a } : ac.unshift(a); GM_setValue(_0x4e.ACCOUNTS, ac); const _v = GM_getValue(_0x4e.ACCOUNTS, []); if (!_v.find(x => x.email === a.email)) { console.error('[SaveGuard] 保存验证失败,正在重试...'); GM_setValue(_0x4e.ACCOUNTS, ac); const _v2 = GM_getValue(_0x4e.ACCOUNTS, []); if (!_v2.find(x => x.email === a.email)) { try { const bk = JSON.parse(localStorage.getItem('tm_accounts_backup') || '[]'); if (!bk.find(x => x.email === a.email)) bk.unshift(a); localStorage.setItem('tm_accounts_backup', JSON.stringify(bk)); } catch (e) { } console.error('[SaveGuard] 二次保存仍失败,已写入 localStorage 备份'); } } try { localStorage.setItem('tm_accounts_backup', JSON.stringify(GM_getValue(_0x4e.ACCOUNTS, []))); } catch (e) { } _syncPush(a); }

    /* ═══════════════ Workers 云同步 ═══════════════ */
    function _workerReq(method, path, body) { const url = GM_getValue('tm_sync_url', ''); const key = GM_getValue('tm_sync_apikey', ''); if (!url || !key) return Promise.resolve(null); return new Promise((r, j) => { GM_xmlhttpRequest({ method: method, url: url.replace(/\/+$/, '') + path, headers: { 'X-Sync-Key': key, 'Content-Type': 'application/json' }, data: body ? JSON.stringify(body) : undefined, timeout: 15000, onload: function (rs) { try { const d = JSON.parse(rs.responseText); if (rs.status >= 200 && rs.status < 300) { r(d); } else { j(new Error(d.error || 'HTTP ' + rs.status)); } } catch (x) { j(new Error('响应解析失败')); } }, onerror: function () { j(new Error('网络请求失败')); }, ontimeout: function () { j(new Error('请求超时')); } }); }); }
    async function _syncPush(account) { const _su = GM_getValue('tm_sync_url', ''); const _sk = GM_getValue('tm_sync_apikey', ''); if (!_su || !_sk) return; try { await _workerReq('POST', '/api/accounts', { account: account }); console.log('[CloudSync] 已上传:', account.email); } catch (e) { console.warn('[CloudSync] 上传失败:', e.message); } }
    async function _syncPushAll() { const url = GM_getValue('tm_sync_url', ''); const key = GM_getValue('tm_sync_apikey', ''); if (!url || !key) throw new Error('请先在设置中配置云同步地址和密钥'); const ac = _0x126(); if (!ac.length) throw new Error('本地暂无账号'); return await _workerReq('POST', '/api/accounts', { accounts: ac }); }
    async function _syncPull() { const _su = GM_getValue('tm_sync_url', ''); const _sk = GM_getValue('tm_sync_apikey', ''); if (!_su || !_sk) return; try { const r = await _workerReq('GET', '/api/accounts'); if (!r || !r.accounts || !r.accounts.length) return; const remote = r.accounts; const local = _0x126(); let added = 0; const localEmails = new Set(local.map(a => a.email)); for (const ra of remote) { if (!ra.email) continue; if (!localEmails.has(ra.email)) { local.unshift(ra); added++; } else { const li = local.findIndex(x => x.email === ra.email); if (li >= 0) { const la = local[li]; if (ra.status === '注册完成' && la.status !== '注册完成') { local[li] = { ...la, ...ra }; } else if (ra.createdAt && la.createdAt && ra.createdAt > la.createdAt) { local[li] = { ...la, ...ra }; } } } } if (added > 0) { GM_setValue(_0x4e.ACCOUNTS, local); try { localStorage.setItem('tm_accounts_backup', JSON.stringify(local)); } catch (e) { } console.log('[CloudSync] 从云端同步了 ' + added + ' 个新账号'); setTimeout(() => _tmToast('云同步: 恢复了 ' + added + ' 个账号', 'success', 3000), 2500); } else { console.log('[CloudSync] 云端无新账号'); } } catch (e) { console.warn('[CloudSync] 拉取失败:', e.message); } }

    /* ═══════════════ 兜底 & 导入导出 ═══════════════ */
    let _backupChecked = false;
    function _0x_restoreFromBackup() { if (_backupChecked) return; _backupChecked = true; try { const bk = JSON.parse(localStorage.getItem('tm_accounts_backup') || '[]'); if (!bk.length) return; const cur = _0x126(); let count = 0; for (const b of bk) { if (b.email && !cur.find(x => x.email === b.email)) { cur.unshift(b); count++; } } if (count > 0) { GM_setValue(_0x4e.ACCOUNTS, cur); console.log('[SaveGuard] 从备份恢复了 ' + count + ' 个账号'); setTimeout(() => _tmToast('从备份恢复了 ' + count + ' 个丢失账号', 'success', 4000), 2000); } } catch (e) { console.warn('[SaveGuard]', e); } }
    function _0x_exportAccounts() { const ac = _0x126(); if (!ac.length) { alert('暂无账号可导出'); return; } const data = JSON.stringify(ac, null, 2); const blob = new Blob([data], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'chatgpt-accounts-' + new Date().toISOString().slice(0, 10) + '.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); _tmToast('已导出 ' + ac.length + ' 个账号', 'success', 2000); }
    function _0x_importAccounts() { const inp = document.createElement('input'); inp.type = 'file'; inp.accept = '.json,.txt,.csv'; inp.onchange = function (e) { const f = e.target.files[0]; if (!f) return; const rd = new FileReader(); rd.onload = function (ev) { try { let arr = []; const txt = ev.target.result.trim(); try { const j = JSON.parse(txt); arr = Array.isArray(j) ? j : [j]; } catch (_) { arr = txt.split('\n').map(l => l.trim()).filter(l => l).map(l => { const p = l.split(/[,\t|;]/); return { email: (p[0] || '').trim(), password: (p[1] || '').trim() }; }); } let added = 0, skipped = 0; const cur = _0x126(); for (const item of arr) { if (!item.email || !item.email.includes('@')) { skipped++; continue; } if (cur.find(x => x.email === item.email)) { skipped++; continue; } _0x137({ email: item.email, password: item.password || '', status: item.status || '导入', createdAt: item.createdAt || new Date().toISOString(), ...item }); added++; } const msg = '导入完成: ' + added + ' 个账号' + (skipped ? ' (跳过' + skipped + '个)' : ''); _tmToast(msg, 'success', 3000); } catch (ex) { alert('导入失败: ' + ex.message); } }; rd.readAsText(f); }; inp.click(); }
    function _0x_importEmails() { const inp = document.createElement('input'); inp.type = 'file'; inp.accept = '.json,.txt,.csv'; inp.onchange = function (e) { const f = e.target.files[0]; if (!f) return; const rd = new FileReader(); rd.onload = function (ev) { try { let emails = []; const txt = ev.target.result.trim(); try { const j = JSON.parse(txt); if (Array.isArray(j)) emails = j.map(x => typeof x === 'string' ? { email: x } : x); else if (j.email) emails = [j]; else if (j.emails) emails = j.emails.map(x => typeof x === 'string' ? { email: x } : x); } catch (_) { emails = txt.split(/[\n,;]/).map(l => l.trim()).filter(l => l.includes('@')).map(e => ({ email: e })); } let added = 0, skipped = 0; const cur = _0x126(); for (const item of emails) { if (!item.email || !item.email.includes('@')) { skipped++; continue; } if (cur.find(x => x.email === item.email)) { skipped++; continue; } _0x137({ email: item.email, password: item.password || '', status: '邮箱导入', createdAt: new Date().toISOString(), isEmailImport: true, ...item }); added++; } const msg = '导入完成: ' + added + ' 个邮箱' + (skipped ? ' (跳过' + skipped + '个)' : ''); _tmToast(msg, 'success', 3000); } catch (ex) { alert('导入失败: ' + ex.message); } }; rd.readAsText(f); }; inp.click(); }
    function _0x_exportEmails() { const ac = _0x126(); if (!ac.length) { alert('暂无邮箱可导出'); return; } const emails = ac.map(a => a.email); const blob = new Blob([emails.join('\n')], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'chatgpt-emails-' + new Date().toISOString().slice(0, 10) + '.txt'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); _tmToast('已导出 ' + emails.length + ' 个邮箱', 'success', 2000); }
    function _0x_fullBackup() { const data = { _meta: { version: '9.1', exportedAt: new Date().toISOString(), type: 'chatgpt-tools-full-backup' }, accounts: _0x126(), settings: { apiKey: GM_getValue(_0x4e.API_KEY, ''), regPrefix: GM_getValue('tm_reg_prefix', ''), regDomain: GM_getValue('tm_reg_domain', ''), useCd: GM_getValue('tm_use_cd', false), customDomains: _0x_getCDs(), tmAddr: GM_getValue('tm_tm_addr', ''), tmEpin: GM_getValue('tm_tm_epin', ''), teamUrl: GM_getValue('tm_team_url', ''), teamKey: GM_getValue('tm_team_key', ''), autoRedirectTeam: GM_getValue(_0x4e.AUTO_REDIRECT_TEAM, false), fabPos: GM_getValue('tm_fab_pos', null) } }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'chatgpt-tools-backup-' + new Date().toISOString().slice(0, 10) + '.json'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); _tmToast('已备份全部数据 (' + data.accounts.length + ' 个账号 + 全部设置)', 'success', 2500); }
    function _0x_fullRestore() { const inp = document.createElement('input'); inp.type = 'file'; inp.accept = '.json'; inp.onchange = function (e) { const f = e.target.files[0]; if (!f) return; const rd = new FileReader(); rd.onload = function (ev) { try { const data = JSON.parse(ev.target.result); if (!data._meta || data._meta.type !== 'chatgpt-tools-full-backup') { if (Array.isArray(data) && data.length > 0 && data[0].email) { if (!confirm('检测到这是账号列表文件,包含 ' + data.length + ' 个账号。\n\n是否导入到账号列表?')) return; let added = 0; const cur = _0x126(); for (const item of data) { if (item.email && !cur.find(x => x.email === item.email)) { _0x137(item); added++; } } _tmToast('已导入 ' + added + ' 个账号', 'success', 2500); return; } alert('无效的备份文件格式。\n请选择由「备份全部数据」导出的 .json 文件'); return; } const acCount = data.accounts ? data.accounts.length : 0; const hasSettings = !!data.settings; const info = '备份时间: ' + (data._meta.exportedAt ? new Date(data._meta.exportedAt).toLocaleString() : '未知') + '\n账号数量: ' + acCount + '\n包含设置: ' + (hasSettings ? '是' : '否') + '\n\n⚠️ 恢复将覆盖当前所有数据!确定继续?'; if (!confirm(info)) return; if (data.accounts && Array.isArray(data.accounts)) { GM_setValue(_0x4e.ACCOUNTS, data.accounts); try { localStorage.setItem('tm_accounts_backup', JSON.stringify(data.accounts)); } catch (e) { } } if (data.settings) { const s = data.settings; if (s.apiKey !== undefined) GM_setValue(_0x4e.API_KEY, s.apiKey); if (s.regPrefix !== undefined) GM_setValue('tm_reg_prefix', s.regPrefix); if (s.regDomain !== undefined) GM_setValue('tm_reg_domain', s.regDomain); if (s.useCd !== undefined) GM_setValue('tm_use_cd', s.useCd); if (s.customDomains !== undefined) _0x_setCDs(s.customDomains); if (s.tmAddr !== undefined) GM_setValue('tm_tm_addr', s.tmAddr); if (s.tmEpin !== undefined) GM_setValue('tm_tm_epin', s.tmEpin); if (s.teamUrl !== undefined) GM_setValue('tm_team_url', s.teamUrl); if (s.teamKey !== undefined) GM_setValue('tm_team_key', s.teamKey); if (s.autoRedirectTeam !== undefined) GM_setValue(_0x4e.AUTO_REDIRECT_TEAM, s.autoRedirectTeam); if (s.fabPos !== undefined && s.fabPos) GM_setValue('tm_fab_pos', s.fabPos); } _tmToast('数据恢复成功!' + acCount + ' 个账号 + 全部设置', 'success', 3000); const sm = document.getElementById('tm-modal-settings'); if (sm && sm.classList.contains('show')) { sm.classList.remove('show'); setTimeout(() => _0x76a(), 300); } } catch (ex) { alert('恢复失败: ' + ex.message); } }; rd.readAsText(f); }; inp.click(); }

    /* ═══════════════ DOM 工具 ═══════════════ */
    function _0x1ae(m) { return new Promise(r => setTimeout(r, m)); }
    function _0x1bf(s, t = 0x2710) { return new Promise((r, j) => { const e = document.querySelector(s); if (e) { r(e); return; } const o = new MutationObserver(() => { const el = document.querySelector(s); if (el) { o.disconnect(); r(el); } }); o.observe(document.body, { childList: !0, subtree: !0 }); setTimeout(() => { o.disconnect(); j(new Error('元素未找到: ' + s)); }, t); }); }
    function _0x1c0(i, v) { i.focus(); const n = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; n.call(i, v); i.dispatchEvent(new Event('input', { bubbles: !0, composed: !0 })); i.dispatchEvent(new Event('change', { bubbles: !0, composed: !0 })); for (const c of v) { i.dispatchEvent(new KeyboardEvent('keydown', { key: c, bubbles: !0 })); i.dispatchEvent(new KeyboardEvent('keypress', { key: c, bubbles: !0 })); i.dispatchEvent(new KeyboardEvent('keyup', { key: c, bubbles: !0 })); } i.dispatchEvent(new Event('blur', { bubbles: !0 })); i.focus(); }
    async function _0x1d1(e, v) { console.log('[AutoReg] Setting spinbutton:', v); e.focus(); e.click(); await _0x1ae(0xc8); if (!e.textContent.match(/\d/)) { e.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: !0 })); await _0x1ae(0x64); } let m = 0x64; while (m-- > 0x0) { let t = e.textContent || e.getAttribute('aria-valuenow') || ''; let c = parseInt(t.replace(/\D/g, '')); if (isNaN(c)) { e.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: !0 })); await _0x1ae(0x64); continue; } let d = v - c; if (d === 0x0) break; const k = d > 0x0 ? 'ArrowUp' : 'ArrowDown'; e.dispatchEvent(new KeyboardEvent('keydown', { key: k, bubbles: !0 })); await _0x1ae(0x50); } e.setAttribute('aria-valuenow', v); e.dispatchEvent(new Event('change', { bubbles: !0 })); e.dispatchEvent(new Event('blur', { bubbles: !0 })); await _0x1ae(0x64); }
    function _0x1e2(e) { e.click(); e.dispatchEvent(new MouseEvent('click', { bubbles: !0, cancelable: !0 })); }
    function _0x1f3(s, ts) { const es = document.querySelectorAll(s); for (const e of es) { const t = e.textContent.toLowerCase(); for (const x of ts) { if (t.includes(x.toLowerCase())) return e; } } return null; }

    /* ═══════════════ Toast 通知 ═══════════════ */
    let _toastTimer = null;
    function _tmToast(msg, type = 'loading', duration = 0) { let t = document.getElementById('tm-toast'); if (!t) { t = document.createElement('div'); t.id = 'tm-toast'; t.className = 'tm-toast'; document.body.appendChild(t); } if (_toastTimer) { clearTimeout(_toastTimer); _toastTimer = null; } t.className = 'tm-toast ' + type + ' show'; t.innerHTML = (type === 'loading' ? '<div class="sp"></div>' : type === 'success' ? '<span>✅</span>' : '<span>❌</span>') + '<span>' + msg + '</span>'; if (duration > 0) { _toastTimer = setTimeout(() => { t.classList.remove('show'); _toastTimer = null; }, duration); } }
    function _tmToastHide() { const t = document.getElementById('tm-toast'); if (t) t.classList.remove('show'); if (_toastTimer) { clearTimeout(_toastTimer); _toastTimer = null; } }

    /* ═══════════════ 移动端弹窗滚动锁定 ═══════════════ */
    function _tmModalScrollLock() { const check = () => { const anyOpen = document.querySelector('.tm-ov.show'); document.body.style.overflow = anyOpen ? 'hidden' : ''; }; const obs = new MutationObserver(check); setTimeout(() => { document.querySelectorAll('.tm-ov').forEach(ov => { obs.observe(ov, { attributes: true, attributeFilter: ['class'] }); }); }, 2000); }

    /* ═══════════════ 初始化入口 ═══════════════ */
    function _0x204() { if (document.getElementById(_0xg(0x0))) return; _0x_restoreFromBackup(); _syncPull(); _0x215(); _0x326(); _tmModalScrollLock(); }

    /* ═══════════════ 主面板 ═══════════════ */
    function _0x215() {
        const r = document.createElement('div'); r.id = _0xg(0x0);
        const p = document.createElement('div'); p.className = 'tm-panel';
        p.innerHTML = `
<div class="tm-p-head"><div class="tm-p-title">ChatGPT Tools</div><div class="tm-p-ver">v9.4</div></div>
<div class="tm-p-body">
<div class="tm-g">
<button class="tm-gi" data-act="token"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#059669,#047857)">🔑</div><div class="tm-gi-lb">复制 Token</div></button>
<button class="tm-gi" data-act="pay"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#3b82f6,#2563eb)">💳</div><div class="tm-gi-lb">Plus 支付</div></button>
<button class="tm-gi" data-act="team"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#f59e0b,#d97706)">🔗</div><div class="tm-gi-lb">Team 链接</div></button>
<button class="tm-gi" data-act="paypal"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#2563eb,#1d4ed8)">🅿️</div><div class="tm-gi-lb">PayPal支付</div></button>
<button class="tm-gi" data-act="vcc"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#14b8a6,#0f766e)">💠</div><div class="tm-gi-lb">获取虚拟卡</div></button>
<button class="tm-gi" data-act="export"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#f97316,#ea580c)">📦</div><div class="tm-gi-lb">导出对话</div></button>
<button class="tm-gi" data-act="settings"><div class="tm-gi-ic" style="background:linear-gradient(135deg,#6b7280,#4b5563)">⚙️</div><div class="tm-gi-lb">设置</div></button>
</div>
<div class="tm-sep"></div>
<button class="tm-li" data-act="push"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg>推送当前账号到 Team</button>
<button class="tm-li" data-act="about"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>关于</button>
<button class="tm-li" data-act="logout" style="color:rgba(239,68,68,.9)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>退出登录</button>
</div>`;
        const fab = document.createElement('button'); fab.className = 'tm-fab'; fab.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>';
        /* 拖动逻辑 */
        let _drag = false, _moved = false, _sx, _sy, _sl, _st, _isTouch = false;
        function _onStart(e) { if (p.classList.contains('show')) return; _drag = true; _moved = false; _isTouch = !!e.touches; const ev = e.touches ? e.touches[0] : e; const rc = r.getBoundingClientRect(); _sx = ev.clientX; _sy = ev.clientY; _sl = rc.left; _st = rc.top; r.classList.add('dragging'); fab.classList.add('dragging'); if (!_isTouch) e.preventDefault(); }
        function _onMove(e) { if (!_drag) return; const ev = e.touches ? e.touches[0] : e; const dx = ev.clientX - _sx, dy = ev.clientY - _sy; if (Math.abs(dx) > 3 || Math.abs(dy) > 3) { _moved = true; e.preventDefault(); } if (!_moved) return; let nl = _sl + dx, nt = _st + dy; nl = Math.max(0, Math.min(nl, window.innerWidth - 52)); nt = Math.max(0, Math.min(nt, window.innerHeight - 52)); r.style.right = 'auto'; r.style.bottom = 'auto'; r.style.left = nl + 'px'; r.style.top = nt + 'px'; }
        function _onEnd(e) { if (!_drag) return; _drag = false; r.classList.remove('dragging'); fab.classList.remove('dragging'); if (_moved) { const rc = r.getBoundingClientRect(); GM_setValue('tm_fab_pos', JSON.stringify({ x: rc.left, y: rc.top })); if (_isTouch) { _moved = false; } else { e.preventDefault(); e.stopPropagation(); } } else if (_isTouch) { _togglePanel(); } }
        fab.addEventListener('mousedown', _onStart); fab.addEventListener('touchstart', _onStart, { passive: true });
        document.addEventListener('mousemove', _onMove); document.addEventListener('touchmove', _onMove, { passive: false });
        document.addEventListener('mouseup', _onEnd); document.addEventListener('touchend', _onEnd);
        /* 移动端遮罩 */
        const _isMobile = () => window.innerWidth <= 768;
        const backdrop = document.createElement('div'); backdrop.className = 'tm-panel-backdrop'; document.body.appendChild(backdrop);
        function _togglePanel(show) { const s = typeof show === 'boolean' ? show : !p.classList.contains('show'); if (s) { p.classList.add('show'); fab.classList.add('open'); if (_isMobile()) { backdrop.classList.add('show'); document.body.style.overflow = 'hidden'; } } else { p.classList.remove('show'); fab.classList.remove('open'); backdrop.classList.remove('show'); document.body.style.overflow = ''; } }
        fab.addEventListener('click', (e) => { e.stopPropagation(); if (_isTouch) return; if (_moved) { _moved = false; return; } _togglePanel(); });
        backdrop.addEventListener('click', () => _togglePanel(false));
        document.addEventListener('click', (e) => { if (!r.contains(e.target) && !backdrop.contains(e.target) && p.classList.contains('show')) _togglePanel(false); });
        r.appendChild(p); r.appendChild(fab); document.body.appendChild(r);
        /* 恢复保存的位置 */
        try { const sp = GM_getValue('tm_fab_pos'); if (sp) { const pos = JSON.parse(sp); r.style.right = 'auto'; r.style.bottom = 'auto'; r.style.left = Math.min(Math.max(0, pos.x), window.innerWidth - 52) + 'px'; r.style.top = Math.min(Math.max(0, pos.y), window.innerHeight - 52) + 'px'; } } catch (e) { }
        p.addEventListener('click', async (e) => { e.stopPropagation(); const item = e.target.closest('[data-act]'); if (!item) return; const act = item.dataset.act; _togglePanel(false); switch (act) { case 'token': _0xcbf(); break; case 'pay': _0xdd0(); break; case 'team': _0xee1(); break; case 'paypal': _0xpp0(); break; case 'vcc': window.open('https://779.chat', '_blank'); break; case 'export': _expShowExportDialog(); break; case 'push': _0x_doPush(); break; case 'settings': _0x76a(); break; case 'about': _0x103(); break; case 'logout': _0xLogout(); break; } });
    }

    /* ═══════════════ Modal 创建 ═══════════════ */
    function _0x326() {
        // Pay Modal
        if (!document.getElementById('tm-modal-pay')) {
            const m = document.createElement('div'); m.id = 'tm-modal-pay'; m.className = 'tm-ov'; m.innerHTML = `
<div class="tm-md" style="max-width:400px">
<div class="tm-md-h"><div class="tm-md-t">✅ 生成成功</div><button class="tm-md-x" data-close>✕</button></div>
<div class="tm-md-b">
<div class="tm-alert tm-alert-w">⚠️ 请在无痕模式 + 全局节点下打开</div>
<div class="tm-lbl">支付链接</div>
<div class="tm-code" id="tm-modal-pay-code"></div>
</div>
<div class="tm-md-f"><button class="tm-btn tm-btn-s" data-close>关闭</button><button class="tm-btn tm-btn-p" id="tm-modal-pay-copy">📋 复制</button><button class="tm-btn tm-btn-sm" style="background:rgba(59,130,246,.15);color:rgba(96,165,250,.9);border-color:rgba(59,130,246,.2)" id="tm-modal-pay-open">🔗 打开</button></div>
</div>`; document.body.appendChild(m);
            m.querySelectorAll('[data-close]').forEach(b => b.onclick = () => m.classList.remove('show'));
            document.getElementById('tm-modal-pay-copy').onclick = function () { _0x7b(document.getElementById('tm-modal-pay-code').innerText); this.innerText = '✅ 已复制'; setTimeout(() => this.innerText = '📋 复制', 1200); };
            document.getElementById('tm-modal-pay-open').onclick = function () { window.open(document.getElementById('tm-modal-pay-code').innerText, '_blank'); };
        }

        // Settings Modal
        if (!document.getElementById('tm-modal-settings')) {
            const m = document.createElement('div'); m.id = 'tm-modal-settings'; m.className = 'tm-ov'; m.innerHTML = `
<div class="tm-md" style="max-width:440px">
<div class="tm-md-h"><div class="tm-md-t">⚙️ 设置</div><button class="tm-md-x" data-close>✕</button></div>
<div class="tm-md-b" style="max-height:480px">
<div class="tm-fld">
<label class="tm-lbl">邮箱服务提供商</label>
<select class="tm-inp tm-sel" id="tm-settings-email-provider" style="margin-bottom:6px">
<option value="npcmail">NPCmail</option>
<option value="gptmail" selected>GPTMail</option>
</select>
<div id="tm-npcmail-setting" style="display:none">
<label class="tm-lbl">NPCmail 密钥</label><input type="text" class="tm-inp" id="tm-settings-apikey" placeholder="输入 NPCmail API 密钥"><div style="font-size:10px;color:rgba(255,255,255,.45);margin-top:4px">API: ${_0x3c}</div>
</div>
<div id="tm-gptmail-setting">
<label class="tm-lbl">GPTMail 密钥</label><input type="text" class="tm-inp" id="tm-settings-gptmail-key" placeholder="输入 GPTMail API 密钥 (默认: gpt-test)"><div style="font-size:10px;color:rgba(255,255,255,.45);margin-top:4px">API: https://mail.chatgpt.org.uk</div>
</div>
</div>
<div style="height:1px;background:rgba(255,255,255,.08);margin:14px 0"></div>
<div class="tm-fld"><label class="tm-lbl">邮箱配置 (可选)</label><input type="text" class="tm-inp" id="tm-settings-reg-prefix" placeholder="邮箱前缀 (留空随机)" style="margin-bottom:6px"><select class="tm-inp tm-sel" id="tm-settings-reg-domain"><option value="">随机域名</option><option value="" disabled>加载中...</option></select></div>
<div style="height:1px;background:rgba(255,255,255,.08);margin:14px 0"></div>
<div class="tm-fld">
<label class="tm-lbl">🌐 自定义域名 + TempMail</label>
<div style="font-size:10px;color:rgba(255,255,255,.45);margin-bottom:6px">CF 邮件路由转发到临时邮箱,无需密钥</div>
<label class="tm-chk" style="margin-bottom:8px"><input type="checkbox" id="tm-settings-use-cd">启用自定义域名注册</label>
<div id="tm-cd-section" style="display:none">
<div style="display:flex;gap:4px;margin-bottom:6px"><input type="text" class="tm-inp" id="tm-cd-input" placeholder="域名 (如 example.com)" style="flex:1"><button class="tm-btn tm-btn-p tm-btn-sm" id="tm-cd-add">添加</button></div>
<div id="tm-cd-list" style="margin-bottom:8px"></div>
<div class="tm-lbl" style="margin-top:8px">📬 TempMail 取件</div>
<input type="text" class="tm-inp" id="tm-settings-tm-addr" placeholder="邮箱 (如 [email protected])" style="margin-bottom:4px">
<input type="text" class="tm-inp" id="tm-settings-tm-epin" placeholder="PIN 码 (没有可留空)">
<div style="font-size:9px;color:rgba(255,255,255,.4);margin-top:3px">支持: ${_0x_TM_DOMAINS.join(', ')}</div>
</div></div>
<div style="height:1px;background:rgba(255,255,255,.08);margin:14px 0"></div>
<div class="tm-fld">
<label class="tm-lbl">🔗 Team 管理后台</label>
<div style="font-size:10px;color:rgba(255,255,255,.45);margin-bottom:6px">配置后可在账号列表中一键推送账号到管理系统</div>
<input type="text" class="tm-inp" id="tm-settings-team-url" placeholder="后台地址 (如 http://127.0.0.1:8008)" style="margin-bottom:4px">
<input type="password" class="tm-inp" id="tm-settings-team-key" placeholder="后台密钥">
</div>
<div style="height:1px;background:rgba(255,255,255,.08);margin:14px 0"></div>
<div class="tm-fld"><label class="tm-chk"><input type="checkbox" id="tm-settings-auto-redirect">注册后自动跳转 Team 短链接</label></div>
<div style="height:1px;background:rgba(255,255,255,.08);margin:14px 0"></div>
<div class="tm-fld">
<label class="tm-lbl">☁️ 云同步 (自动)</label>
<div style="font-size:10px;color:rgba(255,255,255,.45);margin-bottom:6px">输入管理员生成的 API 密钥,账号将自动上传到云端</div>
<input type="text" class="tm-inp" id="tm-settings-sync-url" placeholder="云同步地址 (如 https://xxx.workers.dev)" style="margin-bottom:4px">
<input type="text" class="tm-inp" id="tm-settings-sync-apikey" placeholder="同步密钥 (管理员后台生成)">
<div style="display:flex;gap:4px;margin-top:6px"><button class="tm-btn tm-btn-sm" id="tm-sync-test" style="background:rgba(6,182,212,.15);color:rgba(34,211,238,.9);border-color:rgba(6,182,212,.2);flex:1">🔗 测试连接</button><button class="tm-btn tm-btn-sm" id="tm-sync-push-all" style="background:rgba(168,85,247,.15);color:rgba(192,132,252,.9);border-color:rgba(168,85,247,.2);flex:1">📤 全量上传</button><button class="tm-btn tm-btn-sm" id="tm-sync-pull" style="background:rgba(16,185,129,.15);color:rgba(16,185,129,.9);border-color:rgba(16,185,129,.2);flex:1">📥 拉取</button></div>
</div>
<div style="height:1px;background:rgba(255,255,255,.08);margin:14px 0"></div>
<div class="tm-fld">
<label class="tm-lbl">💾 数据备份与恢复</label>
<div style="font-size:10px;color:rgba(255,255,255,.45);margin-bottom:8px">一键备份所有账号、设置和自定义域名到文件,换浏览器或重装时可恢复</div>
<div style="display:flex;gap:6px"><button class="tm-btn tm-btn-sm" id="tm-backup-export" style="background:rgba(59,130,246,.15);color:rgba(96,165,250,.9);border-color:rgba(59,130,246,.2);flex:1;padding:10px 8px">📦 备份全部数据</button><button class="tm-btn tm-btn-sm" id="tm-backup-import" style="background:rgba(245,158,11,.12);color:rgba(251,191,36,.9);border-color:rgba(245,158,11,.2);flex:1;padding:10px 8px">📂 导入备份</button></div>
</div>
<div id="tm-settings-status" style="display:none;padding:8px 10px;border-radius:6px;font-size:12px;margin-top:12px"></div>
</div>
<div class="tm-md-f"><button class="tm-btn tm-btn-s" data-close>关闭</button><button class="tm-btn tm-btn-s" id="tm-settings-test" style="background:rgba(59,130,246,.15);color:rgba(96,165,250,.9);border-color:rgba(59,130,246,.2)">测试邮箱连接</button><button class="tm-btn tm-btn-s" id="tm-settings-test-team" style="background:rgba(245,158,11,.12);color:rgba(251,191,36,.9);border-color:rgba(245,158,11,.2)">测试 Team</button><button class="tm-btn tm-btn-p" id="tm-settings-save">💾 保存</button></div>
</div>`; document.body.appendChild(m);
            m.querySelectorAll('[data-close]').forEach(b => b.onclick = () => m.classList.remove('show'));
            document.getElementById('tm-settings-test').onclick = async function () { const st = document.getElementById('tm-settings-status'); const prv = document.getElementById('tm-settings-email-provider').value; if (prv === 'npcmail') { const k = document.getElementById('tm-settings-apikey').value.trim(); if (!k) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ 请输入 NPCmail 密钥'; return; } GM_setValue(_0x4e.API_KEY, k); this.innerText = '测试中...'; try { const i = await _0xe2(); st.style.display = 'block'; st.style.background = 'rgba(16,185,129,.12)'; st.style.color = 'rgba(16,185,129,.9)'; st.innerText = '✅ NPCmail 连接成功!剩余调用: ' + i.remaining_calls; } catch (e) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ ' + e.message; } } else if (prv === 'gptmail') { const k = document.getElementById('tm-settings-gptmail-key').value.trim(); if (!k) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ 请输入 GPTMail 密钥'; return; } GM_setValue('gptmail_api_key', k); this.innerText = '测试中...'; try { const i = await _gptReq('/stats', k); st.style.display = 'block'; st.style.background = 'rgba(16,185,129,.12)'; st.style.color = 'rgba(16,185,129,.9)'; st.innerText = '✅ GPTMail 连接成功!系统收件数: ' + (i.total_emails || 0); } catch (e) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ ' + e.message; } } this.innerText = '测试邮箱连接'; };
            document.getElementById('tm-settings-use-cd').onchange = function () { document.getElementById('tm-cd-section').style.display = this.checked ? 'block' : 'none'; };
            document.getElementById('tm-cd-add').onclick = function () { const v = document.getElementById('tm-cd-input').value; if (_0x_addCD(v)) { document.getElementById('tm-cd-input').value = ''; _0x_renderCDs(); } else { alert('域名格式不正确或已存在'); } };
            document.getElementById('tm-settings-test-team').onclick = async function () { const st = document.getElementById('tm-settings-status'); const url = document.getElementById('tm-settings-team-url').value.trim(); const key = document.getElementById('tm-settings-team-key').value.trim(); if (!url || !key) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ 请输入 Team 后台地址和密钥'; return; } this.innerText = '测试中...'; try { const r = await _0x_teamReq(url, 'GET', '/external/health', key); st.style.display = 'block'; st.style.background = 'rgba(16,185,129,.12)'; st.style.color = 'rgba(16,185,129,.9)'; st.innerText = '✅ Team 后台连接成功!'; } catch (e) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ ' + e.message; } this.innerText = '测试 Team'; };
            document.getElementById('tm-sync-test').onclick = async function () { const st = document.getElementById('tm-settings-status'); const url = document.getElementById('tm-settings-sync-url').value.trim(); const key = document.getElementById('tm-settings-sync-apikey').value.trim(); if (!url || !key) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ 请输入云同步地址和密钥'; return; } this.innerText = '测试中...'; GM_setValue('tm_sync_url', url); GM_setValue('tm_sync_apikey', key); try { const r = await _workerReq('GET', '/health'); if (!r) { throw new Error('无响应,请检查地址是否正确'); } if (r.keyValid === false) { st.style.display = 'block'; st.style.background = 'rgba(251,191,36,.12)'; st.style.color = 'rgba(251,191,36,.9)'; st.innerText = '⚠️ 云端已连接,但密钥无效,请检查'; } else { st.style.display = 'block'; st.style.background = 'rgba(16,185,129,.12)'; st.style.color = 'rgba(16,185,129,.9)'; st.innerText = '✅ 云端连接成功,密钥有效!'; } } catch (e) { st.style.display = 'block'; st.style.background = 'rgba(239,68,68,.12)'; st.style.color = 'rgba(239,68,68,.9)'; st.innerText = '❌ ' + e.message; } this.innerText = '🔗 测试连接'; };
            document.getElementById('tm-sync-push-all').onclick = async function () { const url = document.getElementById('tm-settings-sync-url').value.trim(); const key = document.getElementById('tm-settings-sync-apikey').value.trim(); if (!url || !key) { alert('请先填写云同步地址和密钥'); return; } GM_setValue('tm_sync_url', url); GM_setValue('tm_sync_apikey', key); this.innerText = '上传中...'; try { const r = await _syncPushAll(); const st = document.getElementById('tm-settings-status'); st.style.display = 'block'; st.style.background = 'rgba(16,185,129,.12)'; st.style.color = 'rgba(16,185,129,.9)'; st.innerText = '✅ 全量上传成功!共 ' + r.count + ' 个账号'; _tmToast('全量上传成功!共 ' + r.count + ' 个账号', 'success', 3000); } catch (e) { alert('上传失败: ' + e.message); } this.innerText = '📤 全量上传'; };
            document.getElementById('tm-sync-pull').onclick = async function () { const url = document.getElementById('tm-settings-sync-url').value.trim(); const key = document.getElementById('tm-settings-sync-apikey').value.trim(); if (!url || !key) { alert('请先填写云同步地址和密钥'); return; } GM_setValue('tm_sync_url', url); GM_setValue('tm_sync_apikey', key); this.innerText = '拉取中...'; try { await _syncPull(); const st = document.getElementById('tm-settings-status'); st.style.display = 'block'; st.style.background = 'rgba(16,185,129,.12)'; st.style.color = 'rgba(16,185,129,.9)'; st.innerText = '✅ 拉取完成!'; } catch (e) { alert('拉取失败: ' + e.message); } this.innerText = '📥 拉取'; };
            document.getElementById('tm-settings-save').onclick = function () { const prEl = document.getElementById('tm-settings-email-provider'); if (prEl) { GM_setValue('tm_email_provider', prEl.value); console.log('[Settings] 邮箱提供商已保存:', prEl.value); } const gk = document.getElementById('tm-settings-gptmail-key'); if (gk) GM_setValue('gptmail_api_key', gk.value.trim()); GM_setValue(_0x4e.API_KEY, document.getElementById('tm-settings-apikey').value.trim()); GM_setValue(_0x4e.AUTO_REDIRECT_TEAM, document.getElementById('tm-settings-auto-redirect').checked); GM_setValue('tm_reg_prefix', document.getElementById('tm-settings-reg-prefix').value.trim()); GM_setValue('tm_reg_domain', document.getElementById('tm-settings-reg-domain').value); GM_setValue('tm_use_cd', document.getElementById('tm-settings-use-cd').checked); GM_setValue('tm_tm_addr', document.getElementById('tm-settings-tm-addr').value.trim()); GM_setValue('tm_tm_epin', document.getElementById('tm-settings-tm-epin').value.trim()); GM_setValue('tm_team_url', document.getElementById('tm-settings-team-url').value.trim()); GM_setValue('tm_team_key', document.getElementById('tm-settings-team-key').value.trim()); const _oldSyncKey = GM_getValue('tm_sync_apikey', ''); const _newSyncUrl = document.getElementById('tm-settings-sync-url').value.trim(); const _newSyncKey = document.getElementById('tm-settings-sync-apikey').value.trim(); GM_setValue('tm_sync_url', _newSyncUrl); GM_setValue('tm_sync_apikey', _newSyncKey); if (_newSyncKey && _newSyncUrl && _newSyncKey !== _oldSyncKey) { setTimeout(async () => { try { const r = await _syncPushAll(); _tmToast('API密钥已设置,自动上传了 ' + r.count + ' 个账号', 'success', 3000); console.log('[CloudSync] 首次设置密钥,自动全量上传完成'); } catch (e) { console.warn('[CloudSync] 首次全量上传失败:', e.message); } }, 500); } m.classList.remove('show'); };
            document.getElementById('tm-backup-export').onclick = _0x_fullBackup;
            document.getElementById('tm-backup-import').onclick = _0x_fullRestore;
        }

        // About Modal
        if (!document.getElementById('tm-modal-about')) {
            const m = document.createElement('div'); m.id = 'tm-modal-about'; m.className = 'tm-ov'; m.innerHTML = `
<div class="tm-md" style="max-width:360px">
<div class="tm-md-h"><div class="tm-md-t">ℹ️ 关于</div><button class="tm-md-x" data-close>✕</button></div>
<div class="tm-md-b" style="text-align:center">
<div style="width:56px;height:56px;margin:0 auto 12px;border-radius:14px;background:linear-gradient(135deg,#10a37f,#0e8c6b);display:flex;align-items:center;justify-content:center;font-size:24px;box-shadow:0 6px 16px rgba(16,163,127,.3)">⚡</div>
<div style="font-size:18px;font-weight:700;color:rgba(255,255,255,.95);margin-bottom:2px;text-shadow:0 1px 2px rgba(0,0,0,.15)">ChatGPT Tools</div>
<div style="font-size:11px;color:rgba(255,255,255,.45);margin-bottom:16px">v9.4</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:16px;text-align:center">
<div style="padding:8px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:10px;font-size:11px;color:rgba(255,255,255,.6)">🔑 Token</div>
<div style="padding:8px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:10px;font-size:11px;color:rgba(255,255,255,.6)">💳 Plus</div>
<div style="padding:8px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:10px;font-size:11px;color:rgba(255,255,255,.6)">🚀 注册</div>
<div style="padding:8px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:10px;font-size:11px;color:rgba(255,255,255,.6)">📦 导出对话</div>
</div>
<a href="https://linux.do/u/npc1/summary" target="_blank" style="display:flex;align-items:center;justify-content:center;gap:6px;padding:10px;background:rgba(16,185,129,.1);border:1px solid rgba(16,185,129,.2);border-radius:10px;color:rgba(16,185,129,.9);text-decoration:none;font-size:12px;font-weight:500;transition:.2s">
👨‍💻 开发者: NPC →</a>
</div>
<div class="tm-md-f"><button class="tm-btn tm-btn-s" data-close>关闭</button></div>
</div>`; document.body.appendChild(m);
            m.querySelectorAll('[data-close]').forEach(b => b.onclick = () => m.classList.remove('show'));
        }

        // Success Modal
        if (!document.getElementById('tm-modal-success')) {
            const m = document.createElement('div'); m.id = 'tm-modal-success'; m.className = 'tm-ov'; m.innerHTML = `
<div class="tm-md" style="max-width:360px;text-align:center">
<div class="tm-md-b" style="padding:24px">
<div class="tm-suc-ic">🎉</div>
<div class="tm-suc-t">注册成功!</div>
<div class="tm-suc-sub">账号已保存到列表</div>
<div class="tm-suc-info">
<div class="tm-suc-row"><span class="tm-suc-lb">邮箱</span><span class="tm-suc-val" id="tm-success-email"></span></div>
<div class="tm-suc-row"><span class="tm-suc-lb">密码</span><span class="tm-suc-val" id="tm-success-password"></span></div>
</div>
<div class="tm-suc-redir" id="tm-suc-redir-wrap">
<div class="tm-suc-redir-txt"><span id="tm-success-countdown">3</span>s 后跳转...</div>
<div class="tm-suc-prog"><div class="tm-suc-prog-bar" id="tm-success-progress-bar"></div></div>
</div>
<div style="display:flex;gap:6px;justify-content:center;margin-top:12px">
<button class="tm-btn tm-btn-d" id="tm-success-cancel">取消</button>
<button class="tm-btn tm-btn-p" id="tm-success-copy">📋 复制</button>
</div>
</div>
</div>`; document.body.appendChild(m);
        }
    }

    /* ═══════════════ 注册成功弹窗逻辑 ═══════════════ */
    function _0x214(e, pw, oc, cn) { document.getElementById('tm-success-email').innerText = e; document.getElementById('tm-success-password').innerText = pw; const rs = document.getElementById('tm-suc-redir-wrap'); const cb = document.getElementById('tm-success-cancel'); const ce = document.getElementById('tm-success-countdown'); const pb = document.getElementById('tm-success-progress-bar'); const wr = typeof oc === 'function'; rs.style.display = wr ? 'block' : 'none'; cb.innerText = wr ? '取消' : '关闭'; document.getElementById('tm-modal-success').classList.add('show'); let cd = 0x3; let cl = !1; let tm = null; if (wr) { ce.innerText = cd; pb.style.width = '100%'; pb.style.transition = 'none'; setTimeout(() => { pb.style.transition = 'width 3s linear'; pb.style.width = '0%'; }, 0x32); tm = setInterval(() => { if (cl) { clearInterval(tm); return; } cd--; ce.innerText = cd; if (cd <= 0x0) { clearInterval(tm); document.getElementById('tm-modal-success').classList.remove('show'); oc(); } }, 0x3e8); } cb.onclick = function () { cl = !0; if (tm) clearInterval(tm); document.getElementById('tm-modal-success').classList.remove('show'); if (cn) cn(); }; document.getElementById('tm-success-copy').onclick = function () { _0x7b('邮箱: ' + e + '\n密码: ' + pw); this.innerText = '✅ 已复制'; setTimeout(() => this.innerText = '📋 复制', 800); }; }

    /* ═══════════════ Token / Pay / Team ═══════════════ */
    async function _0x325() { const r = await fetch(_0xb('L2FwaS9hdXRoL3Nlc3Npb24=')); if (r.status === 0x193) throw new Error('访问被拒绝 (403)'); const d = await r.json(); if (!d.accessToken) throw new Error('未登录 ChatGPT'); return d.accessToken; }
    async function _0xcbf() { _tmToast('获取 Token...', 'loading'); try { _0x7b(await _0x325()); _tmToast('Token 已复制到剪贴板', 'success', 2000); } catch (e) { _tmToast(e.message, 'error', 3000); } }
    async function _0xdd0() { _tmToast('生成 Plus 支付链接...', 'loading'); try { const tk = await _0x325(); const p = { plan_type: 'plus', promo_campaign: { promo_campaign_id: 'plus-1-month-free', is_coupon_from_query_param: !0 }, checkout_ui_mode: 'custom' }; const r = await fetch(_0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9iYWNrZW5kLWFwaS9wYXltZW50cy9jaGVja291dA=='), { method: 'POST', headers: { 'Authorization': 'Bearer ' + tk, 'Content-Type': _0xb('YXBwbGljYXRpb24vanNvbg==') }, body: JSON.stringify(p) }); const d = await r.json(); if (d.checkout_session_id) { const su = _0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9jaGVja291dC9vcGVuYWlfbGxjLw==') + d.checkout_session_id; _0x7b(su); document.getElementById('tm-modal-pay-code').innerText = su; _tmToastHide(); document.getElementById('tm-modal-pay').classList.add('show'); } else throw new Error(d.detail || 'API 错误'); } catch (e) { _tmToast('' + e, 'error', 3000); } }
    async function _0xpp0() { _tmToast('生成 PayPal 支付链接...', 'loading'); try { const tk = await _0x325(); const p = { plan_name: 'chatgptteamplan', team_plan_data: { workspace_name: 'Team-' + Math.floor(Math.random() * 99999), price_interval: 'month', seat_quantity: 0x5 }, promo_campaign: { promo_campaign_id: 'team-1-month-free', is_coupon_from_query_param: !0 }, billing_details: { country: 'DE', currency: 'EUR' }, checkout_ui_mode: 'hosted' }; const r = await fetch(_0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9iYWNrZW5kLWFwaS9wYXltZW50cy9jaGVja291dA=='), { method: 'POST', headers: { 'Authorization': 'Bearer ' + tk, 'Content-Type': _0xb('YXBwbGljYXRpb24vanNvbg==') }, body: JSON.stringify(p) }); const d = await r.json(); if (d.url) { _0x7b(d.url); document.getElementById('tm-modal-pay-code').innerText = d.url; _tmToastHide(); document.getElementById('tm-modal-pay').classList.add('show'); } else throw new Error(d.detail || 'API 错误'); } catch (e) { _tmToast('' + e, 'error', 3000); } }
    async function _0xee1() { _tmToast('生成 Team 链接...', 'loading'); try { const sr = await fetch(_0xb('L2FwaS9hdXRoL3Nlc3Npb24=')); const ct = sr.headers.get('content-type'); if (!ct || !ct.includes(_0xb('YXBwbGljYXRpb24vanNvbg=='))) { _tmToast('请先登录 ChatGPT', 'error', 3000); return; } const tk = await sr.json(); if (!tk.accessToken) { _tmToast('请先登录 ChatGPT', 'error', 3000); return; } const p = { plan_name: 'chatgptteamplan', team_plan_data: { workspace_name: 'Team-' + Math.floor(Math.random() * 99999), price_interval: 'month', seat_quantity: 0x5 }, promo_campaign: { promo_campaign_id: 'team-1-month-free', is_coupon_from_query_param: !0 }, checkout_ui_mode: 'custom' }; const r = await fetch(_0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9iYWNrZW5kLWFwaS9wYXltZW50cy9jaGVja291dA=='), { method: 'POST', headers: { Authorization: 'Bearer ' + tk.accessToken, 'Content-Type': _0xb('YXBwbGljYXRpb24vanNvbg==') }, body: JSON.stringify(p) }); const d = await r.json(); if (d.checkout_session_id) { const su = _0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9jaGVja291dC9vcGVuYWlfbGxjLw==') + d.checkout_session_id; _0x7b(su); document.getElementById('tm-modal-pay-code').innerText = su; _tmToastHide(); document.getElementById('tm-modal-pay').classList.add('show'); } else { _tmToast('生成失败:' + (d.detail || '未知错误'), 'error', 3000); } } catch (e) { _tmToast('' + e, 'error', 3000); } }
    async function _0x436(e, pw) { try { const sr = await fetch(_0xb('L2FwaS9hdXRoL3Nlc3Npb24=')); const ct = sr.headers.get('content-type'); if (!ct || !ct.includes(_0xb('YXBwbGljYXRpb24vanNvbg=='))) { _0xa9d(); alert('获取会话失败'); return; } const tk = await sr.json(); if (!tk.accessToken) { _0xa9d(); alert('获取 Token 失败'); return; } _0xbae('生成 Team 短链接...'); const p = { plan_name: 'chatgptteamplan', team_plan_data: { workspace_name: 'MyTeam', price_interval: 'month', seat_quantity: 0x5 }, promo_campaign: { promo_campaign_id: 'team-1-month-free', is_coupon_from_query_param: !0 }, billing_details: { country: 'DE', currency: 'EUR' }, checkout_ui_mode: 'custom' }; const r = await fetch(_0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9iYWNrZW5kLWFwaS9wYXltZW50cy9jaGVja291dA=='), { method: 'POST', headers: { Authorization: 'Bearer ' + tk.accessToken, 'Content-Type': _0xb('YXBwbGljYXRpb24vanNvbg==') }, body: JSON.stringify(p) }); const d = await r.json(); if (d.checkout_session_id) { const su = _0xb('aHR0cHM6Ly9jaGF0Z3B0LmNvbS9jaGVja291dC9vcGVuYWlfbGxjLw==') + d.checkout_session_id; _0xa9d(); _0x214(e, pw, () => { window.location.href = su; }, () => { }); } else { _0xa9d(); alert('生成失败'); } } catch (ex) { _0xa9d(); alert('出错:' + ex); } }

    /* ═══════════════ 域名加载 / 设置 ═══════════════ */
    async function _0x547() { const dd = ['git-hub.email', 'hccc.edu.kg', 'xphdfs.me', 'kiroxubei.tech', 'xpzsd.codes', 'zhurunqi.love', 'geminikey.app', 'geminikey.email', '880070.xyz', '880333.xyz', 'ghukr.cn', '292998.xyz']; let ad = []; try { const d = await _0xd1(_0xb('L2FwaS9wdWJsaWMvZG9tYWlucw==')); if (Array.isArray(d)) ad = d; else if (d && d.domains) ad = d.domains; } catch (e) { console.warn('获取域名失败:', e); } return [...new Set([...ad, ...dd])]; }
    async function _0x76a() { let defPrv = GM_getValue('tm_email_provider', 'gptmail'); console.log('[Settings] GM_getValue tm_email_provider =', defPrv); if (defPrv !== 'npcmail' && defPrv !== 'gptmail') defPrv = 'gptmail'; const prEl = document.getElementById('tm-settings-email-provider'); if (prEl) { for (let i = 0; i < prEl.options.length; i++) { prEl.options[i].selected = (prEl.options[i].value === defPrv); } prEl.value = defPrv; console.log('[Settings] 下拉框设置为:', prEl.value); } const nt = document.getElementById('tm-npcmail-setting'); const gt = document.getElementById('tm-gptmail-setting'); if (nt) nt.style.display = defPrv === 'npcmail' ? 'block' : 'none'; if (gt) gt.style.display = defPrv === 'npcmail' ? 'none' : 'block'; if (prEl) { prEl.onchange = function () { const isN = this.value === 'npcmail'; if (nt) nt.style.display = isN ? 'block' : 'none'; if (gt) gt.style.display = !isN ? 'block' : 'none'; }; } document.getElementById('tm-settings-apikey').value = GM_getValue(_0x4e.API_KEY, ''); const gkp = document.getElementById('tm-settings-gptmail-key'); if (gkp) gkp.value = GM_getValue('gptmail_api_key', 'gpt-test'); document.getElementById('tm-settings-auto-redirect').checked = GM_getValue(_0x4e.AUTO_REDIRECT_TEAM, !1); document.getElementById('tm-settings-reg-prefix').value = GM_getValue('tm_reg_prefix', ''); document.getElementById('tm-settings-team-url').value = GM_getValue('tm_team_url', ''); document.getElementById('tm-settings-team-key').value = GM_getValue('tm_team_key', ''); const ucd = GM_getValue('tm_use_cd', false); document.getElementById('tm-settings-use-cd').checked = ucd; document.getElementById('tm-cd-section').style.display = ucd ? 'block' : 'none'; document.getElementById('tm-settings-tm-addr').value = GM_getValue('tm_tm_addr', ''); document.getElementById('tm-settings-tm-epin').value = GM_getValue('tm_tm_epin', ''); _0x_renderCDs(); document.getElementById('tm-settings-sync-url').value = GM_getValue('tm_sync_url', ''); document.getElementById('tm-settings-sync-apikey').value = GM_getValue('tm_sync_apikey', ''); const sd = GM_getValue('tm_reg_domain', ''); const ds = document.getElementById('tm-settings-reg-domain'); if (ds.options.length <= 0x2) { const dm = await _0x547(); const lo = ds.querySelector('option[value=""]'); if (lo && lo.disabled) lo.remove(); dm.forEach(d => { const dn = typeof d === 'string' ? d : d.domain; if (!ds.querySelector('option[value="' + dn + '"]')) { const o = document.createElement('option'); o.value = dn; o.innerText = dn; ds.appendChild(o); } }); } ds.value = sd || ''; document.getElementById('tm-settings-status').style.display = 'none'; document.getElementById('tm-modal-settings').classList.add('show'); }
    function _0x103() { document.getElementById('tm-modal-about').classList.add('show'); }
    function _0xLogout() { if (!confirm('确定要退出登录吗?')) return; const names = ['__Secure-next-auth.session-token', '__Secure-next-auth.session-token.0', '__Secure-next-auth.session-token.1', '__Secure-next-auth.session-token.2']; let pending = 0, done = 0; function tryReload() { done++; if (done >= pending) location.reload(); } for (const n of names) { pending++; GM_cookie.delete({ name: n, url: 'https://chatgpt.com/' }, tryReload); } if (pending === 0) location.reload(); }

    /* ═══════════════ 点击涟漪效果 ═══════════════ */
    document.addEventListener('click', function (e) { const b = e.target.closest('.tm-btn,.tm-gi'); if (!b) return; const rc = b.getBoundingClientRect(); const sz = Math.max(rc.width, rc.height) * 2.5; const x = e.clientX - rc.left - sz / 2; const y = e.clientY - rc.top - sz / 2; const rp = document.createElement('span'); rp.style.cssText = 'position:absolute;border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.3) 0%,rgba(255,255,255,.1) 40%,transparent 70%);pointer-events:none;width:' + sz + 'px;height:' + sz + 'px;left:' + x + 'px;top:' + y + 'px;transform:scale(0);opacity:1;animation:tm-rippleOut .65s cubic-bezier(0,.4,.2,1) forwards;z-index:10'; b.style.position || (b.style.position = 'relative'); b.style.overflow = 'hidden'; b.appendChild(rp); setTimeout(() => rp.remove(), 700); });

    setInterval(_0x204, 0x5dc);
    setTimeout(_0x204, 0x3e8);
})();