Greasy Fork

来自缓存

Greasy Fork is available in English.

【对不起,Discord!】 DC Orbs 任务视频跳过按钮 (Beta)

🔒 99% 安全且不会封禁账号的脚本 — 可拖拽的悬浮按钮,用于跳过 Discord Orbs 任务视频

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name                【Sorry,Discord!】 DC Orbs Quests Video Skip Button (Beta)
// @name:zh-TW          【對不起,Discord!】 DC Orbs 任務影片跳過按鈕 (Beta)
// @name:zh-CN          【对不起,Discord!】 DC Orbs 任务视频跳过按钮 (Beta)
// @name:ja             【すみません,Discord!】 DC Orbs クエスト動画スキップボタン (Beta)
// @name:ko             【죄송합니다,Discord!】 DC Orbs 퀘스트 동영상 건너뛰기 버튼 (Beta)
// @namespace           https://github.com/NiktoBlox/Tampermonkey-Scripts/tree/60ae32ddf7b8d2e6cfdae065bf1ce5f702550180/%F0%9F%9F%A2%E2%94%82Deploy%20Scripts/Discord%20Orbs%20Quests%20Video%20Skip%20Button
// @version             1.51-Beta
// @description         🔒 99% Safe & Account Ban-Free Script — Floating draggable skip button for Discord Orbs Quests Videos
// @description:zh-TW   🔒 99% 安全且不會封禁帳號的腳本 — 可拖曳的懸浮按鈕,用於跳過 Discord Orbs 任務影片
// @description:zh-CN   🔒 99% 安全且不会封禁账号的脚本 — 可拖拽的悬浮按钮,用于跳过 Discord Orbs 任务视频
// @description:ja      🔒 99% 安全・アカウントBANリスクなしスクリプト — Discord Orbs クエスト動画をスキップするためのドラッグ可能なフローティングボタン
// @description:ko      🔒 99% 안전 & 계정 차단 없는 스크립트 — Discord Orbs 퀘스트 동영상을 건너뛰기 위한 드래그 가능한 플로팅 버튼
// @author              NiktoBlox
// @license             MIT
// @match               https://discord.com/quest-home
// @match               https://discord.com/quests/*
// @match               https://discord.com/channels/*
// @match               https://discord.com/*
// @icon                https://files.catbox.moe/kdzneo.png
// @grant               GM_getValue
// @grant               GM_setValue
// ==/UserScript==

(function () {
    'use strict';

    // ── 多國語系 ──
    const I18N = {
        en: {
            skip: '⏭️ Skip', skipped: '✅ Skipped!', notFound: '❌ Not Found',
            settings: '⚙️ Settings', theme: '🎨 Theme', customColor: '🖌️ Custom Color',
            btnColor: 'Button', textColor: 'Text', borderRadius: '⬜ Border Radius',
            opacity: '👁️ Opacity', autoHide: '🔁 Auto-hide', autoHideDesc: 'Fade button when inactive',
            language: '🌐 Language', about: 'ℹ️ About', version: 'Version',
            author: 'Author', license: 'License', github: 'GitHub ↗',
            autoSkip: '🤖 Auto Skip', autoSkipDesc: 'Auto skip when video detected',
            autoSkipDelay: '⏱️ Auto Skip Delay', seconds: 's',
            notifyDuration: '🔔 Notify Duration',
            btnSize: '📐 Button Size', small: 'S', medium: 'M', large: 'L',
            btnPosition: '📌 Quick Position',
            customText: '✏️ Custom Button Text',
            resetAll: '🔄 Reset All Settings',
            resetConfirm: 'Reset all settings?',
            exportSettings: '📤 Export', importSettings: '📥 Import',
            importSuccess: '✅ Imported!', importFail: '❌ Import Failed',
            guiTheme: '🖥️ Panel Theme', guiLight: 'Light', guiDark: 'Dark', guiBlack: 'Pure Black',
            corners: ['↖ Top Left', '↗ Top Right', '↙ Bottom Left', '↘ Bottom Right'],
            dragDelay: '🖱️ Long-press Drag Delay', ms: 'ms',
            tabPanel: 'Panel', tabBtn: 'Button Style', tabOther: 'Other',
            aboutSection: 'ℹ️ About',
            aboutAuthor: '👨‍💻 Author',
            aboutVersion: '🏷️ Version',
            aboutBug: '🐛 Report a Bug',
            aboutBugLink: 'Click here to report →',
            aboutLang: '🌐 Add a Language',
            aboutLangLink: 'Request a new language →',
        },
        'zh-TW': {
            skip: '⏭️ 跳過', skipped: '✅ 已跳過!', notFound: '❌ 找不到',
            settings: '⚙️ 設定', theme: '🎨 主題', customColor: '🖌️ 自訂顏色',
            btnColor: '按鈕', textColor: '文字', borderRadius: '⬜ 圓角大小',
            opacity: '👁️ 透明度', autoHide: '🔁 自動隱藏', autoHideDesc: '閒置時淡化按鈕',
            language: '🌐 語言', about: 'ℹ️ 關於', version: '版本',
            author: '作者', license: '授權', github: 'GitHub ↗',
            autoSkip: '🤖 自動跳過', autoSkipDesc: '偵測到影片時自動跳過',
            autoSkipDelay: '⏱️ 自動跳過延遲', seconds: '秒',
            notifyDuration: '🔔 通知顯示時間',
            btnSize: '📐 按鈕大小', small: '小', medium: '中', large: '大',
            btnPosition: '📌 快速定位',
            customText: '✏️ 自訂按鈕文字',
            resetAll: '🔄 重設所有設定',
            resetConfirm: '確定重設所有設定?',
            exportSettings: '📤 匯出', importSettings: '📥 匯入',
            importSuccess: '✅ 匯入成功!', importFail: '❌ 匯入失敗',
            guiTheme: '🖥️ 面板主題', guiLight: '淺色', guiDark: '深色', guiBlack: '極黑',
            corners: ['↖ 左上', '↗ 右上', '↙ 左下', '↘ 右下'],
            dragDelay: '🖱️ 長按拖曳延遲', ms: '毫秒',
            tabPanel: '面板外觀', tabBtn: '按鈕外觀', tabOther: '其他',
            aboutSection: 'ℹ️ 關於',
            aboutAuthor: '👨‍💻 製作者',
            aboutVersion: '🏷️ 版本',
            aboutBug: '🐛 回報 Bug',
            aboutBugLink: '點此回報問題 →',
            aboutLang: '🌐 新增語言',
            aboutLangLink: '申請新增語言 →',
        },
        'zh-CN': {
            skip: '⏭️ 跳过', skipped: '✅ 已跳过!', notFound: '❌ 未找到',
            settings: '⚙️ 设置', theme: '🎨 主题', customColor: '🖌️ 自定义颜色',
            btnColor: '按钮', textColor: '文字', borderRadius: '⬜ 圆角大小',
            opacity: '👁️ 透明度', autoHide: '🔁 自动隐藏', autoHideDesc: '闲置时淡化按钮',
            language: '🌐 语言', about: 'ℹ️ 关于', version: '版本',
            author: '作者', license: '许可证', github: 'GitHub ↗',
            autoSkip: '🤖 自动跳过', autoSkipDesc: '检测到视频时自动跳过',
            autoSkipDelay: '⏱️ 自动跳过延迟', seconds: '秒',
            notifyDuration: '🔔 通知显示时间',
            btnSize: '📐 按钮大小', small: '小', medium: '中', large: '大',
            btnPosition: '📌 快速定位',
            customText: '✏️ 自定义按钮文字',
            resetAll: '🔄 重置所有设置',
            resetConfirm: '确定重置所有设置?',
            exportSettings: '📤 导出', importSettings: '📥 导入',
            importSuccess: '✅ 导入成功!', importFail: '❌ 导入失败',
            guiTheme: '🖥️ 面板主题', guiLight: '浅色', guiDark: '深色', guiBlack: '极黑',
            corners: ['↖ 左上', '↗ 右上', '↙ 左下', '↘ 右下'],
            dragDelay: '🖱️ 长按拖拽延迟', ms: '毫秒',
            tabPanel: '面板外观', tabBtn: '按钮外观', tabOther: '其他',
            aboutSection: 'ℹ️ 关于',
            aboutAuthor: '👨‍💻 制作者',
            aboutVersion: '🏷️ 版本',
            aboutBug: '🐛 反馈 Bug',
            aboutBugLink: '点此反馈问题 →',
            aboutLang: '🌐 新增语言',
            aboutLangLink: '申请新增语言 →',
        },
        ja: {
            skip: '⏭️ スキップ', skipped: '✅ スキップ完了!', notFound: '❌ 見つかりません',
            settings: '⚙️ 設定', theme: '🎨 テーマ', customColor: '🖌️ カスタムカラー',
            btnColor: 'ボタン', textColor: 'テキスト', borderRadius: '⬜ 角丸サイズ',
            opacity: '👁️ 透明度', autoHide: '🔁 自動非表示', autoHideDesc: '非アクティブ時にフェード',
            language: '🌐 言語', about: 'ℹ️ このスクリプトについて', version: 'バージョン',
            author: '作者', license: 'ライセンス', github: 'GitHub ↗',
            autoSkip: '🤖 自動スキップ', autoSkipDesc: '動画検出時に自動スキップ',
            autoSkipDelay: '⏱️ 自動スキップ遅延', seconds: '秒',
            notifyDuration: '🔔 通知表示時間',
            btnSize: '📐 ボタンサイズ', small: '小', medium: '中', large: '大',
            btnPosition: '📌 クイック配置',
            customText: '✏️ カスタムボタンテキスト',
            resetAll: '🔄 設定をリセット',
            resetConfirm: '全ての設定をリセットしますか?',
            exportSettings: '📤 エクスポート', importSettings: '📥 インポート',
            importSuccess: '✅ インポート完了!', importFail: '❌ インポート失敗',
            guiTheme: '🖥️ パネルテーマ', guiLight: 'ライト', guiDark: 'ダーク', guiBlack: '漆黒',
            corners: ['↖ 左上', '↗ 右上', '↙ 左下', '↘ 右下'],
            dragDelay: '🖱️ 長押しドラッグ遅延', ms: 'ms',
            tabPanel: 'パネル外観', tabBtn: 'ボタン外観', tabOther: 'その他',
            aboutSection: 'ℹ️ このスクリプトについて',
            aboutAuthor: '👨‍💻 作者',
            aboutVersion: '🏷️ バージョン',
            aboutBug: '🐛 バグを報告',
            aboutBugLink: 'こちらから報告 →',
            aboutLang: '🌐 言語を追加',
            aboutLangLink: '新しい言語をリクエスト →',
        },
        ko: {
            skip: '⏭️ 건너뛰기', skipped: '✅ 건너뛰기 완료!', notFound: '❌ 찾을 수 없음',
            设置: '⚙️ 설정', theme: '🎨 테마', customColor: '🖌️ 커스텀 색상',
            btnColor: '버튼', textColor: '텍스트', borderRadius: '⬜ 테두리 반경',
            opacity: '👁️ 투명도', autoHide: '🔁 자동 숨김', autoHideDesc: '비활성 시 페이드 처리',
            language: '🌐 언어', about: 'ℹ️ 정보', version: '버전',
            author: '작성자', license: '라이선스', github: 'GitHub ↗',
            autoSkip: '🤖 자동 건너뛰기', autoSkipDesc: '영상 감지 시 자동 건너뛰기',
            autoSkipDelay: '⏱️ 자동 건너뛰기 지연', seconds: '초',
            notifyDuration: '🔔 알림 표시 시간',
            btnSize: '📐 버튼 크기', small: '소', medium: '중', large: '대',
            btnPosition: '📌 빠른 위치',
            customText: '✏️ 버튼 텍스트 커스텀',
            resetAll: '🔄 모든 설정 초기화',
            resetConfirm: '모든 설정을 초기화할까요?',
            exportSettings: '📤 내보내기', importSettings: '📥 가져오기',
            importSuccess: '✅ 가져오기 완료!', importFail: '❌ 가져오기 실패',
            guiTheme: '🖥️ 패널 테마', guiLight: '라이트', guiDark: '다크', guiBlack: '순수 블랙',
            corners: ['↖ 왼쪽 위', '↗ 오른쪽 위', '↙ 왼쪽 아래', '↘ 오른쪽 아래'],
            dragDelay: '🖱️ 길게 누르기 지연', ms: 'ms',
            tabPanel: '패널 외관', tabBtn: '버튼 스타일', tabOther: '기타',
            aboutSection: 'ℹ️ 정보',
            aboutAuthor: '👨‍💻 제작자',
            aboutVersion: '🏷️ 버전',
            aboutBug: '🐛 버그 신고',
            aboutBugLink: '여기서 신고하기 →',
            aboutLang: '🌐 언어 추가',
            aboutLangLink: '새 언어 요청하기 →',
        },
    };

    const LANG_NAMES = { en: 'English', 'zh-TW': '繁體中文', 'zh-CN': '简体中文', ja: '日本語', ko: '한국어' };

    const detectLang = () => {
        const nav = (navigator.languages?.[0] || navigator.language || 'en').toLowerCase();
        if (nav.startsWith('zh-tw') || nav.startsWith('zh-hk')) return 'zh-TW';
        if (nav.startsWith('zh')) return 'zh-CN';
        if (nav.startsWith('ja')) return 'ja';
        if (nav.startsWith('ko')) return 'ko';
        return 'en';
    };

    const DEFAULTS = {
        theme: 'discord', btnColor: '#5865F2', btnTextColor: '#ffffff',
        btnRadius: '20', btnOpacity: '100', autoHide: false,
        lang: 'en', autoSkip: false, autoSkipDelay: '3',
        notifyDuration: '2', btnSize: 'M', customText: '',
        dragDelay: '200',
        guiTheme: 'dark',
    };

    const load = (key) => { try { return GM_getValue(key, DEFAULTS[key]); } catch { return DEFAULTS[key]; } };
    const save = (key, val) => { try { GM_setValue(key, val); } catch {} };

    let cfg = Object.fromEntries(Object.keys(DEFAULTS).map(k => [k, load(k)]));
    const t = () => I18N[cfg.lang] || I18N.en;

    const THEMES = {
        discord: { bg: '#5865F2', text: '#ffffff' }, dark: { bg: '#1e1e1e', text: '#ffffff' },
        light: { bg: '#e0e0e0', text: '#000000' }, green: { bg: '#43a047', text: '#ffffff' },
        red: { bg: '#e53935', text: '#ffffff' }, purple: { bg: '#8e24aa', text: '#ffffff' },
    };

    const BTN_SIZES = { S: '8px 14px', M: '10px 20px', L: '14px 28px' };
    const BTN_FONT = { S: '12px', M: '14px', L: '16px' };

    // ── 面板主題定義 ──
    const PANEL_THEMES = {
        light: {
            panel: '#f2f3f5', header: '#e3e5e8', text: '#060607',
            subtext: '#747f8d', input: '#e3e5e8', inputText: '#060607',
            border: '#d4d7dc', divider: '#d4d7dc', accent: '#5865F2',
            btnBg: '#e3e5e8', btnText: '#060607', btnActiveText: '#ffffff',
            resetBg: '#fde8e8', resetText: '#d32f2f',
        },
        dark: {
            panel: '#2b2d31', header: '#1e1f22', text: '#dbdee1',
            subtext: '#80848e', input: '#1e1f22', inputText: '#dbdee1',
            border: '#1e1f22', divider: '#3f4147', accent: '#ebebeb',
            btnBg: '#1e1f22', btnText: '#b0b3b8', btnActiveText: '#111111',
            resetBg: '#3a1e1e', resetText: '#e53935',
        },
        black: {
            panel: '#0d0d0d', header: '#000000', text: '#e0e0e0',
            subtext: '#666666', input: '#1a1a1a', inputText: '#e0e0e0',
            border: '#000000', divider: '#222222', accent: '#ffffff',
            btnBg: '#1a1a1a', btnText: '#cccccc', btnActiveText: '#000000',
            resetBg: '#2a0a0a', resetText: '#ff5252',
        },
    };
    const pt = () => PANEL_THEMES[cfg.guiTheme] || PANEL_THEMES.dark;

    // ── 主按鈕 【修復】──
    const btn = document.createElement('button');
    const getBtnText = () => cfg.customText.trim() || t().skip;
    btn.innerText = getBtnText();
    btn.id = 'sq-skip-btn';

    const applyBtn = () => {
        btn.style.cssText = `
            position: fixed !important; 
            bottom: 30px !important; 
            right: 30px !important; 
            z-index: 9999999 !important;
            background: ${cfg.btnColor} !important; 
            color: ${cfg.btnTextColor} !important;
            border: none !important; 
            border-radius: ${cfg.btnRadius}px !important;
            padding: ${BTN_SIZES[cfg.btnSize] || BTN_SIZES.M} !important;
            font-size: ${BTN_FONT[cfg.btnSize] || BTN_FONT.M} !important;
            font-weight: bold !important; 
            cursor: grab !important;
            box-shadow: 0 4px 12px rgba(0,0,0,0.3) !important; 
            user-select: none !important;
            transition: background 0.2s, opacity 0.2s !important;
            opacity: ${cfg.autoHide ? '0.2' : Number(cfg.btnOpacity) / 100} !important;
            visibility: visible !important;
            display: block !important;
            pointer-events: auto !important;
        `;
    };
    applyBtn();

    // ── 跳過核心 ──
    const doSkip = () => {
        const i = t();
        let found = false;
        document.querySelectorAll('video').forEach(el => { el.currentTime = el.duration; found = true; });
        ['[class*="skip"]', '[class*="close"]', '[class*="dismiss"]'].forEach(sel => {
            document.querySelectorAll(sel).forEach(el => {
                if (el.offsetParent !== null) { el.click(); found = true; }
            });
        });
        btn.innerText = found ? i.skipped : i.notFound;
        setTimeout(() => { btn.innerText = getBtnText(); }, Number(cfg.notifyDuration) * 1000);
    };

    // ── 自動跳過 ──
    let autoSkipTimer = null;
    const setupAutoSkip = () => {
        if (autoSkipTimer) clearInterval(autoSkipTimer);
        if (!cfg.autoSkip) return;
        autoSkipTimer = setInterval(() => {
            const videos = document.querySelectorAll('video');
            videos.forEach(v => {
                if (!v.paused && !v.ended && v.duration && v.currentTime < v.duration) {
                    setTimeout(() => { v.currentTime = v.duration; }, Number(cfg.autoSkipDelay) * 1000);
                }
            });
        }, 2000);
    };
    setupAutoSkip();

    // ── 設定面板 ──
    const panel = document.createElement('div');
    const applyPanelTheme = () => {
        const p = pt();
        const wasVisible = panel.style.display === 'block';
        const savedLeft = panel.style.left;
        const savedTop = panel.style.top;
        panel.style.cssText = `
            display:${wasVisible ? 'block' : 'none'} !important; 
            position:fixed !important; 
            z-index:9999999 !important; 
            width:310px !important;
            background:${p.panel} !important; 
            color:${p.text} !important; 
            border-radius:12px !important;
            box-shadow:0 8px 32px rgba(0,0,0,0.6) !important;
            font-family:'gg sans',sans-serif !important; 
            font-size:14px !important;
            overflow:hidden !important; 
            border:1px solid ${p.border} !important;
            max-height:85vh !important; 
            overflow-y:auto !important;
        `;
        if (savedLeft) panel.style.left = savedLeft;
        if (savedTop) panel.style.top = savedTop;
    };
    applyPanelTheme();

    const row = (label, content) => `
        <div style="margin-bottom:14px;">
            <div style="font-size:11px;font-weight:700;text-transform:uppercase;color:${pt().subtext};margin-bottom:6px;">${label}</div>
            ${content}
        </div>`;

    const toggle = (id, checked, label, desc = '') => `
        <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px;">
            <div><div style="font-weight:600;">${label}</div>${desc ? `<div style="font-size:11px;color:${pt().subtext};">${desc}</div>` : ''}</div>
            <label style="position:relative;display:inline-block;width:44px;height:24px;flex-shrink:0;">
                <input type="checkbox" id="${id}" ${checked ? 'checked' : ''} style="opacity:0;width:0;height:0;">
                <span style="position:absolute;top:0;left:0;right:0;bottom:0;background:${checked ? '#5865F2' : '#4e5058'};border-radius:24px;cursor:pointer;transition:0.2s;"></span>
                <span style="position:absolute;height:18px;width:18px;left:${checked ? '23px' : '3px'};bottom:3px;background:white;border-radius:50%;transition:0.2s;pointer-events:none;"></span>
            </label>
        </div>`;

    const buildPanel = () => {
        const i = t();

        panel.innerHTML = `
            <div style="background:${pt().header};padding:12px 16px;font-size:15px;font-weight:700;display:flex;align-items:center;gap:8px;position:sticky;top:0;z-index:1;border-bottom:1px solid ${pt().divider};">
                ${i.settings}
                <span id="sq-close" style="margin-left:auto;cursor:pointer;font-size:18px;color:${pt().subtext};">✕</span>
            </div>
            <div style="padding:0 16px 16px;">

                
            <div style="display:flex;align-items:center;gap:8px;margin:16px 0 10px;padding-bottom:6px;border-bottom:2px solid ${pt().accent}22;">
                
                <span style="font-size:13px;font-weight:700;color:${pt().accent};text-transform:uppercase;letter-spacing:0.5px;">${i.tabPanel}</span>
            </div>

                ${row(i.language, `
                    <select id="sq-lang" style="width:100%;padding:7px 10px;border-radius:6px;border:none;background:${pt().input};color:${pt().inputText};cursor:pointer;font-size:13px;">
                        ${Object.entries(LANG_NAMES).map(([k,v]) => `<option value="${k}" ${cfg.lang===k?'selected':''}>${v}</option>`).join('')}
                    </select>`)}

                ${row(i.guiTheme, `
                    <div style="display:flex;gap:6px;">
                        ${[['light', i.guiLight], ['dark', i.guiDark], ['black', i.guiBlack]].map(([k, lbl]) => `
                            <button data-guitheme="${k}" style="flex:1;padding:7px;border-radius:6px;border:none;cursor:pointer;font-size:12px;font-weight:600;
                                background:${cfg.guiTheme===k ? pt().accent : pt().btnBg};
                                color:${cfg.guiTheme===k ? pt().btnActiveText : pt().btnText};">
                                ${lbl}
                            </button>
                        `).join('')}
                    </div>`)}

                
            <div style="display:flex;align-items:center;gap:8px;margin:16px 0 10px;padding-bottom:6px;border-bottom:2px solid ${pt().accent}22;">
                
                <span style="font-size:13px;font-weight:700;color:${pt().accent};text-transform:uppercase;letter-spacing:0.5px;">${i.tabBtn}</span>
            </div>

                ${row(i.theme, `
                    <div style="display:flex;flex-wrap:wrap;gap:6px;" id="sq-themes">
                        ${Object.entries(THEMES).map(([k,v]) => `
                            <div data-theme="${k}" title="${k}" style="width:32px;height:32px;border-radius:50%;background:${v.bg};cursor:pointer;
                                border:${cfg.theme===k?'3px solid #fff':'3px solid transparent'};box-shadow:0 2px 6px rgba(0,0,0,0.4);transition:border 0.2s;"></div>
                        `).join('')}
                    </div>`)}

                ${row(i.customColor, `
                    <div style="display:flex;gap:8px;align-items:center;">
                        <input type="color" id="sq-btncolor" value="${cfg.btnColor}" style="width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;">
                        <input type="color" id="sq-txtcolor" value="${cfg.btnTextColor}" style="width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;">
                        <span style="font-size:12px;color:${pt().subtext};">${i.btnColor} / ${i.textColor}</span>
                    </div>`)}

                ${row(i.btnSize, `
                    <div style="display:flex;gap:6px;">
                        ${['S','M','L'].map(s => `
                            <button data-size="${s}" style="flex:1;padding:6px;border-radius:6px;border:none;cursor:pointer;font-weight:bold;font-size:13px;
                                background:${cfg.btnSize===s?pt().accent:pt().btnBg};color:${cfg.btnSize===s?pt().btnActiveText:pt().btnText};">
                                ${i[s === 'S' ? 'small' : s === 'M' ? 'medium' : 'large']}
                            </button>`).join('')}
                    </div>`)}

                ${row(i.btnPosition, `
                    <div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;">
                        ${[['TL','top:10px;left:10px'],['TR','top:10px;right:10px'],['BL','bottom:10px;left:10px'],['BR','bottom:10px;right:10px']].map(([pos, s], idx) => `
                            <button data-pos="${s}" style="padding:6px;border-radius:6px;border:none;cursor:pointer;background:${pt().btnBg};color:${pt().text};font-size:12px;">
                                ${i.corners[idx]}
                            </button>`).join('')}
                    </div>`)}

                ${row(`${i.borderRadius}: <span id="sq-radius-val">${cfg.btnRadius}</span>px`, `
                    <input type="range" id="sq-radius" min="0" max="50" value="${cfg.btnRadius}" style="width:100%;accent-color:${pt().accent};">`)}

                ${row(`${i.opacity}: <span id="sq-opacity-val">${cfg.btnOpacity}</span>%`, `
                    <input type="range" id="sq-opacity" min="10" max="100" value="${cfg.btnOpacity}" style="width:100%;accent-color:${pt().accent};">`)}

                ${toggle('sq-autohide', cfg.autoHide, i.autoHide, i.autoHideDesc)}

                ${row(i.customText, `
                    <input type="text" id="sq-customtext" value="${cfg.customText}" placeholder="${t().skip}" maxlength="20"
                        style="width:100%;padding:7px 10px;border-radius:6px;border:none;background:${pt().input};color:${pt().inputText};font-size:13px;box-sizing:border-box;">`)}

                
            <div style="display:flex;align-items:center;gap:8px;margin:16px 0 10px;padding-bottom:6px;border-bottom:2px solid ${pt().accent}22;">
                
                <span style="font-size:13px;font-weight:700;color:${pt().accent};text-transform:uppercase;letter-spacing:0.5px;">${i.tabOther}</span>
            </div>

                ${toggle('sq-autoskip', cfg.autoSkip, i.autoSkip, i.autoSkipDesc)}

                ${row(`${i.autoSkipDelay}: <span id="sq-delay-val">${cfg.autoSkipDelay}</span>${i.seconds}`, `
                    <input type="range" id="sq-delay" min="1" max="10" value="${cfg.autoSkipDelay}" style="width:100%;accent-color:${pt().accent};">`)}

                ${row(`${i.notifyDuration}: <span id="sq-notify-val">${cfg.notifyDuration}</span>${i.seconds}`, `
                    <input type="range" id="sq-notify" min="1" max="10" value="${cfg.notifyDuration}" style="width:100%;accent-color:${pt().accent};">`)}

                ${row(`${i.dragDelay}: <span id="sq-dragdelay-val">${cfg.dragDelay}</span>${i.ms}`, `
                    <input type="range" id="sq-dragdelay" min="0" max="1000" step="100" value="${cfg.dragDelay}" style="width:100%;accent-color:${pt().accent};">
                    <div style="display:flex;justify-content:space-between;font-size:11px;color:${pt().subtext};margin-top:3px;">
                        <span>0${i.ms}</span><span>500${i.ms}</span><span>1000${i.ms}</span>
                    </div>`)}

                <div style="border-top:1px solid ${pt().divider};margin:4px 0 14px;"></div>

                <div style="display:flex;gap:6px;margin-bottom:14px;">
                    <button id="sq-export" style="flex:1;padding:7px;border-radius:6px;border:none;cursor:pointer;background:${pt().btnBg};color:${pt().text};font-size:12px;">${i.exportSettings}</button>
                    <button id="sq-import" style="flex:1;padding:7px;border-radius:6px;border:none;cursor:pointer;background:${pt().btnBg};color:${pt().text};font-size:12px;">${i.importSettings}</button>
                    <button id="sq-reset" style="flex:1;padding:7px;border-radius:6px;border:none;cursor:pointer;background:${pt().resetBg};color:${pt().resetText};font-size:12px;">${i.resetAll}</button>
                </div>

                <div style="border-top:1px solid ${pt().divider};margin:4px 0 14px;"></div>

                <div style="display:flex;align-items:center;gap:8px;margin:0 0 10px;padding-bottom:6px;border-bottom:2px solid ${pt().accent}22;">
                    <span style="font-size:13px;font-weight:700;color:${pt().accent};text-transform:uppercase;letter-spacing:0.5px;">${i.aboutSection}</span>
                </div>

                <div style="
                    background:${pt().input};
                    border-radius:10px;
                    padding:12px 14px;
                    margin-bottom:10px;
                    border:1px solid ${pt().divider};
                    font-size:13px;
                    line-height:1.8;
                ">
                    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;">
                        <span style="color:${pt().subtext};font-size:11px;font-weight:700;text-transform:uppercase;">${i.aboutAuthor}</span>
                        <span style="font-weight:700;color:${pt().text};">NiktoBlox</span>
                    </div>
                    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;">
                        <span style="color:${pt().subtext};font-size:11px;font-weight:700;text-transform:uppercase;">${i.aboutVersion}</span>
                        <span style="
                            font-weight:700;
                            color:${pt().accent};
                            background:${pt().accent}18;
                            padding:2px 8px;
                            border-radius:20px;
                            font-size:11px;
                        ">v1.0-Beta</span>
                    </div>
                    <div style="border-top:1px solid ${pt().divider};margin:8px 0;"></div>
                    <div style="margin-bottom:4px;">
                        <span style="color:${pt().subtext};font-size:11px;font-weight:700;text-transform:uppercase;">${i.aboutBug}</span>
                    </div>
                    <a href="https://github.com/NiktoBlox/Tampermonkey-Scripts/issues" target="_blank" rel="noopener noreferrer" style="
                        display:block;
                        text-align:center;
                        padding:7px 10px;
                        border-radius:6px;
                        background:#e53935;
                        color:#ffffff;
                        font-size:12px;
                        font-weight:700;
                        text-decoration:none;
                        transition:opacity 0.2s;
                        margin-bottom:8px;
                    " onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
                        ${i.aboutBugLink}
                    </a>
                    <div style="margin-bottom:4px;">
                        <span style="color:${pt().subtext};font-size:11px;font-weight:700;text-transform:uppercase;">${i.aboutLang}</span>
                    </div>
                    <a href="https://github.com/NiktoBlox/Tampermonkey-Scripts/issues" target="_blank" rel="noopener noreferrer" style="
                        display:block;
                        text-align:center;
                        padding:7px 10px;
                        border-radius:6px;
                        background:#5865F2;
                        color:#ffffff;
                        font-size:12px;
                        font-weight:700;
                        text-decoration:none;
                        transition:opacity 0.2s;
                    " onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
                        ${i.aboutLangLink}
                    </a>
                </div>

            </div>
        `;

        // 關閉
        panel.querySelector('#sq-close').onclick = () => panel.style.display = 'none';

        // 語言
        panel.querySelector('#sq-lang').onchange = (e) => {
            cfg.lang = e.target.value;
            save('lang', cfg.lang);
            buildPanel();
            // 同步更新主按鈕文字跟隨語言
            if (!cfg.customText.trim()) {
                btn.innerText = getBtnText();
            }
        };

        // GUI主題
        panel.querySelectorAll('[data-guitheme]').forEach(guiBtn => {
            guiBtn.onclick = (e) => {
                e.stopPropagation();
                cfg.guiTheme = guiBtn.dataset.guitheme;
                save('guiTheme', cfg.guiTheme);
                applyPanelTheme();
                buildPanel();
            };
        });

        // 主題色
        panel.querySelectorAll('[data-theme]').forEach(div => {
            div.onclick = (e) => {
                e.stopPropagation();
                cfg.theme = div.dataset.theme;
                cfg.btnColor = THEMES[cfg.theme].bg;
                cfg.btnTextColor = THEMES[cfg.theme].text;
                save('theme', cfg.theme);
                save('btnColor', cfg.btnColor);
                save('btnTextColor', cfg.btnTextColor);
                applyBtn();
                buildPanel();
            };
        });

        // 自訂顏色
        const btnColor = panel.querySelector('#sq-btncolor');
        const txtColor = panel.querySelector('#sq-txtcolor');
        btnColor.onchange = (e) => {
            cfg.btnColor = e.target.value;
            save('btnColor', cfg.btnColor);
            applyBtn();
        };
        txtColor.onchange = (e) => {
            cfg.btnTextColor = e.target.value;
            save('btnTextColor', cfg.btnTextColor);
            applyBtn();
        };

        // 按鈕大小
        panel.querySelectorAll('[data-size]').forEach(sizeBtn => {
            sizeBtn.onclick = (e) => {
                e.stopPropagation();
                cfg.btnSize = sizeBtn.dataset.size;
                save('btnSize', cfg.btnSize);
                applyBtn();
                buildPanel();
            };
        });

        // 快速定位
        panel.querySelectorAll('[data-pos]').forEach(posBtn => {
            posBtn.onclick = (e) => {
                e.stopPropagation();
                posBtn.dataset.pos.split(';').forEach(p => {
                    const [k, v] = p.split(':');
                    if (k && v) { btn.style[k] = v; }
                });
                btn.style.right = 'auto';
                btn.style.bottom = 'auto';
            };
        });

        // 圓角
        panel.querySelector('#sq-radius').oninput = (e) => {
            cfg.btnRadius = e.target.value;
            panel.querySelector('#sq-radius-val').innerText = e.target.value;
            applyBtn();
        };
        panel.querySelector('#sq-radius').onchange = (e) => {
            cfg.btnRadius = e.target.value;
            save('btnRadius', cfg.btnRadius);
        };

        // 透明度
        panel.querySelector('#sq-opacity').oninput = (e) => {
            cfg.btnOpacity = e.target.value;
            panel.querySelector('#sq-opacity-val').innerText = e.target.value;
            applyBtn();
        };
        panel.querySelector('#sq-opacity').onchange = (e) => {
            cfg.btnOpacity = e.target.value;
            save('btnOpacity', cfg.btnOpacity);
        };

        // 自動隱藏
        panel.querySelector('#sq-autohide').onchange = (e) => {
            cfg.autoHide = e.target.checked;
            save('autoHide', cfg.autoHide);
            applyBtn();
        };

        // 自訂文字
        panel.querySelector('#sq-customtext').onchange = (e) => {
            cfg.customText = e.target.value;
            save('customText', cfg.customText);
            btn.innerText = getBtnText();
        };

        // 自動跳過
        panel.querySelector('#sq-autoskip').onchange = (e) => {
            cfg.autoSkip = e.target.checked;
            save('autoSkip', cfg.autoSkip);
            setupAutoSkip();
        };

        // 自動跳過延遲
        panel.querySelector('#sq-delay').oninput = (e) => {
            panel.querySelector('#sq-delay-val').innerText = e.target.value;
        };
        panel.querySelector('#sq-delay').onchange = (e) => {
            cfg.autoSkipDelay = e.target.value;
            save('autoSkipDelay', cfg.autoSkipDelay);
        };

        // 通知時間
        panel.querySelector('#sq-notify').oninput = (e) => {
            panel.querySelector('#sq-notify-val').innerText = e.target.value;
        };
        panel.querySelector('#sq-notify').onchange = (e) => {
            cfg.notifyDuration = e.target.value;
            save('notifyDuration', cfg.notifyDuration);
        };

        // 拖曳延遲
        panel.querySelector('#sq-dragdelay').oninput = (e) => {
            panel.querySelector('#sq-dragdelay-val').innerText = e.target.value;
        };
        panel.querySelector('#sq-dragdelay').onchange = (e) => {
            cfg.dragDelay = e.target.value;
            save('dragDelay', cfg.dragDelay);
        };

        // 匯出
        panel.querySelector('#sq-export').onclick = () => {
            const data = JSON.stringify(cfg);
            const blob = new Blob([data], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `discord-orbs-skip-settings-${Date.now()}.json`;
            a.click();
        };

        // 匯入
        panel.querySelector('#sq-import').onclick = () => {
            const input = document.createElement('input');
            input.type = 'file';
            input.accept = '.json';
            input.onchange = (evFile) => {
                const file = evFile.target.files[0];
                const reader = new FileReader();
                reader.onload = (evRead) => {
                    try {
                        const imported = JSON.parse(evRead.target.result);
                        Object.keys(DEFAULTS).forEach(k => { if (k in imported) { cfg[k] = imported[k]; save(k, cfg[k]); } });
                        applyBtn(); applyPanelTheme(); buildPanel();
                        panel.style.display = 'block';
                        btn.innerText = t().importSuccess;
                        setTimeout(() => { btn.innerText = getBtnText(); }, 2000);
                    } catch {
                        btn.innerText = t().importFail;
                        setTimeout(() => { btn.innerText = getBtnText(); }, 2000);
                    }
                };
                reader.readAsText(file);
            };
            input.click();
        };

        // 重設
        panel.querySelector('#sq-reset').onclick = () => {
            if (!confirm(t().resetConfirm)) return;
            Object.keys(DEFAULTS).forEach(k => { cfg[k] = DEFAULTS[k]; save(k, DEFAULTS[k]); });
            applyBtn(); applyPanelTheme(); buildPanel();
            panel.style.display = 'block';
            btn.innerText = getBtnText();
        };
    };
    buildPanel();

    // ── 面板定位 ──
    const positionPanel = () => {
        panel.style.display = 'block';
        const rect = btn.getBoundingClientRect();
        const pw = Math.min(310, window.innerWidth - 20);
        const ph = Math.min(panel.scrollHeight || 500, window.innerHeight * 0.85);
        panel.style.width = pw + 'px';
        let left = rect.left - pw + btn.offsetWidth;
        let top = rect.top - ph - 10;
        if (left < 10) left = 10;
        if (top < 10) top = rect.bottom + 10;
        if (left + pw > window.innerWidth - 10) left = window.innerWidth - pw - 10;
        if (top + ph > window.innerHeight - 10) top = window.innerHeight - ph - 10;
        panel.style.left = left + 'px';
        panel.style.top = top + 'px';
    };

    // ── 長按拖曳模式 ──
    let isDragging = false;
    let dragReady = false;
    let longPressTimer = null;
    let startX, startY, startLeft, startTop;

    const ring = document.createElement('div');
    ring.style.cssText = `
        position: fixed; z-index: 9999998; pointer-events: none;
        width: 0; height: 0; border-radius: 50%;
        border: 3px solid transparent;
        transition: none; display: none;
    `;
    document.body.appendChild(ring);

    const showRing = (x, y) => {
        const size = 54;
        ring.style.display = 'block';
        ring.style.left = (x - size / 2) + 'px';
        ring.style.top = (y - size / 2) + 'px';
        ring.style.width = size + 'px';
        ring.style.height = size + 'px';
        ring.style.border = `3px solid ${cfg.btnColor}`;
        ring.style.boxShadow = `0 0 0 0 ${cfg.btnColor}44`;
        ring.style.animation = 'sq-ring-spin 1s linear forwards';
    };
    const hideRing = () => {
        ring.style.display = 'none';
        ring.style.animation = 'none';
    };

    const styleEl = document.createElement('style');
    styleEl.textContent = `
        @keyframes sq-ring-spin {
            0% { clip-path: inset(0 100% 0 0); opacity: 1; }
            100% { clip-path: inset(0 0% 0 0);   opacity: 1; }
        }
        @keyframes sq-ring-pulse {
            0% { box-shadow: 0 0 0 0px rgba(88,101,242,0.5); }
            100% { box-shadow: 0 0 0 10px rgba(88,101,242,0); }
        }
    `;
    document.head.appendChild(styleEl);

    btn.addEventListener('mousedown', (e) => {
        if (e.button !== 0) return;
        isDragging = false;
        dragReady = false;

        const rect = btn.getBoundingClientRect();
        startX = e.clientX; startY = e.clientY;
        startLeft = rect.left; startTop = rect.top;

        showRing(e.clientX, e.clientY);
        btn.style.transition = 'transform 0.1s';
        btn.style.transform = 'scale(0.92)';

        longPressTimer = setTimeout(() => {
            dragReady = true;
            hideRing();
            btn.style.transform = 'scale(1.1)';
            btn.style.cursor = 'grabbing';
            btn.style.boxShadow = `0 0 0 4px ${cfg.btnColor}66, 0 6px 20px rgba(0,0,0,0.4)`;
            btn.style.right = 'auto'; btn.style.bottom = 'auto';
            btn.style.left = startLeft + 'px'; btn.style.top = startTop + 'px';
        }, Number(cfg.dragDelay));

        const onMouseMove = (e) => {
            if (!dragReady) return;
            isDragging = true;
            const dx = e.clientX - startX, dy = e.clientY - startY;
            btn.style.left = Math.max(10, Math.min(startLeft + dx, window.innerWidth - btn.offsetWidth - 10)) + 'px';
            btn.style.top = Math.max(10, Math.min(startTop + dy, window.innerHeight - btn.offsetHeight - 10)) + 'px';
        };

        const onMouseUp = () => {
            clearTimeout(longPressTimer);
            hideRing();
            btn.style.cursor = 'grab';
            btn.style.transform = 'scale(1)';
            btn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.3)';
            dragReady = false;
            document.removeEventListener('mousemove', onMouseMove);
            document.removeEventListener('mouseup', onMouseUp);
        };

        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
        e.preventDefault();
    });

    btn.addEventListener('click', () => {
        if (isDragging) { isDragging = false; return; }
        doSkip();
    });

    btn.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        if (panel.style.display === 'block') { panel.style.display = 'none'; } else { buildPanel(); positionPanel(); }
    });

    btn.addEventListener('mouseenter', () => {
        btn.style.opacity = '1'; btn.style.background = adjustColor(cfg.btnColor, -20);
    });
    btn.addEventListener('mouseleave', () => {
        btn.style.background = cfg.btnColor;
        btn.style.opacity = cfg.autoHide ? '0.2' : String(Number(cfg.btnOpacity) / 100);
    });

    document.addEventListener('click', (e) => {
        if (!panel.contains(e.target) && e.target !== btn) panel.style.display = 'none';
    });

    function adjustColor(hex, amount) {
        try {
            const n = parseInt(hex.slice(1), 16);
            const r = Math.max(0, Math.min(255, (n >> 16) + amount));
            const g = Math.max(0, Math.min(255, ((n >> 8) & 0xff) + amount));
            const b = Math.max(0, Math.min(255, (n & 0xff) + amount));
            return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        } catch { return hex; }
    }

    document.body.appendChild(btn);
    document.body.appendChild(panel);
    
    // 【修復】最後確認一次按鈕可見
    setTimeout(() => {
        btn.style.cssText += 'z-index: 9999999 !important; visibility: visible !important; display: block !important;';
        console.log('✅ Skip Button Initialized Successfully!');
    }, 500);
})();