ChatGPT, GROK, and DEEPSEEK AI WEB Chat Scroll Navigator Tool(AI网页聊天智能滚动导航工具)

A unified interface for scrolling, navigation in ChatGPT, GROK, and DEEPSEEK AI chats with multiple themes. 为ChatGPT、GROK和DEEPSEEK AI聊天提供统一的滚动导航界面,支持多种主题风格和自定义设置。

// ==UserScript==
// @name         ChatGPT, GROK, and DEEPSEEK AI WEB Chat Scroll Navigator Tool(AI网页聊天智能滚动导航工具)
// @namespace    http://tampermonkey.net/
// @version      0.24
// @description  A unified interface for scrolling, navigation in ChatGPT, GROK, and DEEPSEEK AI chats with multiple themes. 为ChatGPT、GROK和DEEPSEEK AI聊天提供统一的滚动导航界面,支持多种主题风格和自定义设置。
// @author       Lepturus
// @match        *://chatgpt.com/*
// @match        *://chat.deepseek.com/*
// @match        *://grok.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // --- 1. CONFIGURATION & STATE --- //

    const CONFIG = {
        platforms: {
            chatgpt: { container: '.flex.basis-auto.flex-col.grow.overflow-hidden div.relative.h-full div.overflow-y-auto' },
            grok: { container: '.scrollbar-gutter-stable' },
            deepseek: { container: '.scrollable' },
            generic: { container: 'html, body' }
        },
        defaults: {
            showAutoScrollBtn: true,
            showSectionNavBtn: true,
            language: 'en',
            themeColor: '#007AFF',
            themeStyle: 'minimal',
            scrollSpeed: 5,
            showProgressIndicator: true,
            alwaysShowButtons: true,
            iconSet: 'minimal',
            buttonPosition: 'bottom-right'
        },
        iconSets: {
            minimal: {
                settings: '⚙️',      // 齿轮
                section: '📄',       // 文档
                autoscroll: '⏯️',    // 播放/暂停
                scrollTop: '⬆️',     // 向上箭头
                scrollBottom: '⬇️'   // 向下箭头
            },
            colorful: {
                settings: '🎨',      // 调色板
                section: '📖',       // 书本
                autoscroll: '🚀',    // 火箭
                scrollTop: '👆',     // 向上手指
                scrollBottom: '👇'   // 向下手指
            },
            tech: {
                settings: '🔧',      // 扳手
                section: '📊',       // 图表
                autoscroll: '⚡',    // 闪电
                scrollTop: '🔼',     // 三角形上
                scrollBottom: '🔽'   // 三角形下
            },
            forest: {
                settings: '🌿',      // 叶子
                section: '🌳',       // 树
                autoscroll: '🌊',    // 波浪
                scrollTop: '⛰️',     // 山峰
                scrollBottom: '🌱'   // 幼苗
            },
            anime: {
                settings: '✨',      // 星星
                section: '📑',       // 书签
                autoscroll: '🎵',    // 音乐
                scrollTop: '↑',      // 简洁向上箭头
                scrollBottom: '↓'    // 简洁向下箭头
            }
        },
        themes: {
            minimal: {
                name: { en: 'Minimal', zh: '简约风格' },
                bgColor: '#2c2c2e',
                hoverColor: '#444',
                activeColor: 'var(--enh-nav-theme)',
                textColor: 'white',
                shadow: '0 4px 12px rgba(0,0,0,0.3)',
                panelBg: '#1e1e1e',
                panelBorder: '1px solid #e0e0e0',
                selectColor: 'black',
            },
            colorful: {
                name: { en: 'Colorful', zh: '多彩风格' },
                bgColor: 'linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%)',
                hoverColor: 'linear-gradient(135deg, #ff6a6e 0%, #f8c0b4 100%)',
                activeColor: 'linear-gradient(135deg, #ff4b50 0%, #f6b0a0 100%)',
                textColor: '#7c4dff',
                shadow: '0 8px 16px rgba(124, 77, 255, 0.4)',
                panelBg: 'linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)',
                panelBorder: '1px solid rgba(124, 77, 255, 0.3)',
                selectColor: 'rgba(255,255,255,0.2)',
            },
            tech: {
                name: { en: 'Tech', zh: '科技风格' },
                bgColor: 'rgba(0, 20, 40, 0.8)',
                hoverColor: 'rgba(0, 100, 200, 0.8)',
                activeColor: 'var(--enh-nav-theme)',
                textColor: '#00e5ff',
                shadow: '0 0 15px rgba(0, 229, 255, 0.7)',
                panelBg: 'rgba(0, 30, 60, 0.95)',
                panelBorder: '1px solid rgba(0, 229, 255, 0.5)',
                selectColor: 'rgba(255,255,255,0.2)',
            },
            forest: {
                name: { en: 'Forest', zh: '森林风格' },
                bgColor: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
                hoverColor: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
                activeColor: 'linear-gradient(135deg, #2ed573 0%, #1ed6c8 100%)',
                textColor: '#004d40',
                shadow: '0 6px 14px rgba(0, 77, 64, 0.4)',
                panelBg: 'linear-gradient(135deg, #7bc6cc 0%, #be93c5 100%)',
                panelBorder: '1px solid rgba(0, 77, 64, 0.3)',
                selectColor: 'rgba(255,255,255,0.2)',
            },
            anime: {
                name: { en: 'Cute', zh: '可爱风格' },
                bgColor: 'linear-gradient(135deg, #ffcbf2 0%, #e0c3fc 100%)',
                hoverColor: 'linear-gradient(135deg, #ffafcc 0%, #cdb4db 100%)',
                activeColor: 'linear-gradient(135deg, #ff85a1 0%, #b8a1d9 100%)',
                textColor: '#ff006e',
                shadow: '0 8px 20px rgba(255, 0, 110, 0.4)',
                panelBg: 'linear-gradient(135deg, #f6d5f7 0%, #fbe9d7 100%)',
                panelBorder: '1px solid rgba(255, 0, 110, 0.3)',
                selectColor: 'rgba(255,255,255,0.2)',
            }
        },
        i18n: {
            zh: {
                // Main Titles & Tooltips
                mainTitle: '导航',
                autoScroll: '自动滚动',
                pauseAutoScroll: '暂停滚动',
                sectionNav: '章节导航',
                settings: '设置',
                scrollToTop: '滚动到顶部',
                scrollToBottom: '滚动到底部',
                // Settings Panel
                settingsTitle: '脚本设置',
                showHideButtons: '显示/隐藏功能按钮',
                showReadingButton: '阅读模式',
                showAutoScrollButton: '自动滚动',
                showSectionNavButton: '章节导航',
                showProgressIndicator: '显示进度指示器',
                alwaysShowButtons: '常驻显示按钮',
                language: '语言',
                themeColor: '主题颜色',
                themeStyle: '主题风格',
                scrollSpeed: '自动滚动速度',
                speedValue: (val) => ({ 1: '很慢', 3: '慢', 5: '中等', 8: '快', 10: '很快' })[val] || '自定义',
                // Section Nav Panel
                navTitle: '页面导航',
                noHeadings: '未找到章节标题。',
                iconSet: '图标风格',
                iconSetMinimal: '简约',
                iconSetColorful: '多彩',
                iconSetTech: '科技',
                iconSetForest: '森林',
                iconSetAnime: '可爱',
                buttonPosition: '按钮位置',
                positionBottomRight: '右下',
                positionTopRight: '右上',
                positionMiddleRight: '右中'
            },
            en: {
                // Main Titles & Tooltips
                mainTitle: 'Navigate',
                autoScroll: 'Auto-Scroll',
                pauseAutoScroll: 'Pause Auto-Scroll',
                sectionNav: 'Section Nav',
                settings: 'Settings',
                scrollToTop: 'Scroll to Top',
                scrollToBottom: 'Scroll to Bottom',
                // Settings Panel
                settingsTitle: 'Script Settings',
                showHideButtons: 'Show/Hide Feature Buttons',
                showReadingButton: 'Reading Mode',
                showAutoScrollButton: 'Auto-Scroll',
                showSectionNavButton: 'Section Nav',
                showProgressIndicator: 'Show Progress Indicator',
                alwaysShowButtons: 'Always Show Buttons',
                language: 'Language',
                themeColor: 'Theme Color',
                themeStyle: 'Theme Style',
                scrollSpeed: 'Auto-Scroll Speed',
                speedValue: (val) => ({ 1: 'Very Slow', 3: 'Slow', 5: 'Medium', 8: 'Fast', 10: 'Very Fast' })[val] || 'Custom',
                // Section Nav Panel
                navTitle: 'Section Navigation',
                noHeadings: 'No section headings found.',
                iconSet: 'Icon Style',
                iconSetMinimal: 'Minimal',
                iconSetColorful: 'Colorful',
                iconSetTech: 'Tech',
                iconSetForest: 'Forest',
                iconSetAnime: 'Cute',
                buttonPosition: 'Button Position',
                positionBottomRight: 'Bottom Right',
                positionTopRight: 'Top Right',
                positionMiddleRight: 'Middle Right'
            }
        }
    };

    let STATE = {
        isInitialized: false,
        isAutoScrolling: false,
        autoScrollInterval: null,
        scrollContainer: null,
        settings: {},
        currentPlatform: 'generic',
    };

    // --- 2. CORE LOGIC --- //

    /** Gets a setting value, falling back to default */
    function getSetting(key) {
        return GM_getValue(key, CONFIG.defaults[key]);
    }

    /** Loads all settings into the STATE object */
    function loadSettings() {
        STATE.settings = {
            showAutoScrollBtn: getSetting('showAutoScrollBtn'),
            showSectionNavBtn: getSetting('showSectionNavBtn'),
            language: getSetting('language'),
            themeColor: getSetting('themeColor'),
            iconSet: getSetting('iconSet'),
            themeStyle: getSetting('themeStyle'),
            scrollSpeed: getSetting('scrollSpeed'),
            showProgressIndicator: getSetting('showProgressIndicator'),
            alwaysShowButtons: getSetting('alwaysShowButtons'),
            buttonPosition: getSetting('buttonPosition')
        };
    }

    /** Finds the correct scrollable element on the page */
    function findScrollContainer() {
        const { host } = window.location;
        let platform = 'generic';
        if (host.includes('chatgpt.com')) platform = 'chatgpt';
        else if (host.includes('grok.com')) platform = 'grok';
        else if (host.includes('deepseek.com')) platform = 'deepseek';
        STATE.currentPlatform = platform;

        const selector = CONFIG.platforms[platform].container;
        if (platform === 'deepseek') {
            const containers = document.querySelectorAll(selector);
            return containers.length > 1 ? containers[1] : containers[0];
        }
        return platform === 'generic' ? (document.scrollingElement || document.documentElement) : document.querySelector(selector);
    }

    /** Handles the main scroll button click */
    function handleScrollClick() {
        if (!STATE.scrollContainer) return;
        const isNearTop = STATE.scrollContainer.scrollTop < 100;
        STATE.scrollContainer.scrollTo({
            top: isNearTop ? STATE.scrollContainer.scrollHeight : 0,
            behavior: 'smooth'
        });
    }

    function updateIcons() {
        const iconSet = CONFIG.iconSets[STATE.settings.iconSet] || CONFIG.iconSets.minimal;

        const settingsBtn = document.getElementById('enh-nav-settings-btn');
        if (settingsBtn) settingsBtn.textContent = iconSet.settings;

        const sectionBtn = document.getElementById('enh-nav-section-btn');
        if (sectionBtn) sectionBtn.textContent = iconSet.section;

        const autoscrollBtn = document.getElementById('enh-nav-autoscroll-btn');
        if (autoscrollBtn) autoscrollBtn.textContent = iconSet.autoscroll;

        updateScrollArrow();
    }


    function updateScrollArrow() {
        if (!STATE.scrollContainer) return;

        const arrowEl = document.getElementById('enh-nav-scroll-arrow');
        const iconSet = CONFIG.iconSets[STATE.settings.iconSet] || CONFIG.iconSets.minimal;

        const isNearTop = STATE.scrollContainer.scrollTop < 100;
        if (arrowEl) arrowEl.textContent = isNearTop ? iconSet.scrollBottom : iconSet.scrollTop;
    }


    /** Toggles Auto-Scroll */
    function toggleAutoScroll() {
        STATE.isAutoScrolling = !STATE.isAutoScrolling;
        const btn = document.getElementById('enh-nav-autoscroll-btn');
        if (btn) btn.classList.toggle('active', STATE.isAutoScrolling);

        if (STATE.isAutoScrolling) {
            STATE.autoScrollInterval = setInterval(() => {
                if (!STATE.scrollContainer) return;
                const atBottom = STATE.scrollContainer.scrollTop + STATE.scrollContainer.clientHeight >= STATE.scrollContainer.scrollHeight - 2;
                if (atBottom) {
                    toggleAutoScroll(); // Stop scrolling
                } else {
                    const scrollAmount = Math.max(1, STATE.settings.scrollSpeed / 5);
                    STATE.scrollContainer.scrollBy(0, scrollAmount);
                }
            }, 20);
        } else {
            clearInterval(STATE.autoScrollInterval);
        }
        updateUIText(); // Update title
    }

    /** Applies the selected button position */
    function applyButtonPosition(position) {
        const container = document.getElementById('enh-nav-container');
        const hoverArea = document.getElementById('enh-nav-hover-area');

        if (!container || !hoverArea) return;

        container.classList.remove(
            'enh-nav-pos-bottom-right',
            'enh-nav-pos-top-right',
            'enh-nav-pos-middle-right'
        );

        hoverArea.classList.remove(
            'enh-nav-pos-bottom-right',
            'enh-nav-pos-top-right',
            'enh-nav-pos-middle-right'
        );

        container.classList.add(`enh-nav-pos-${position}`);
        hoverArea.classList.add(`enh-nav-pos-${position}`);

        updatePanelPositions(position);
    }

    /** Updates panel positions based on button position */
    function updatePanelPositions(position) {
        const panels = document.querySelectorAll('.enh-nav-panel');

        panels.forEach(panel => {
            panel.classList.remove(
                'enh-nav-pos-bottom-right',
                'enh-nav-pos-top-right',
                'enh-nav-pos-middle-right'
            );

            panel.classList.add(`enh-nav-pos-${position}`);
        });
    }

    /** Updates the UI text based on the current language without reloading */
    function updateUIText() {
        const lang = STATE.settings.language;
        const translations = CONFIG.i18n[lang];

        document.querySelectorAll('[data-i18n-key]').forEach(el => {
            const key = el.dataset.i18nKey;
            const prop = el.dataset.i18nProp || 'textContent';
            if (translations[key]) el[prop] = translations[key];
        });

        // fix theme style lang not change
        const themeSelect = document.getElementById('enh-nav-theme-style');
        if (themeSelect) {
            Array.from(themeSelect.options).forEach(option => {
                const themeId = option.value;
                const theme = CONFIG.themes[themeId];
                if (theme) {
                    option.textContent = theme.name[lang] || theme.name.en;
                }
            });
        }

        const autoScrollBtn = document.getElementById('enh-nav-autoscroll-btn');
        if (autoScrollBtn) autoScrollBtn.title = STATE.isAutoScrolling ? translations.pauseAutoScroll : translations.autoScroll;

        const mainBtn = document.getElementById('enh-nav-main-btn');
        if (mainBtn && STATE.scrollContainer) {
            const isNearTop = STATE.scrollContainer.scrollTop < 100;
            mainBtn.title = isNearTop ? translations.scrollToBottom : translations.scrollToTop;
        }

        // Update speed value text
        const speedValueEl = document.getElementById('enh-nav-speed-value');
        if (speedValueEl) {
            speedValueEl.textContent = translations.speedValue(STATE.settings.scrollSpeed);
        }
    }


    // --- 3. UI CREATION & UPDATES --- //

    /** Injects all CSS into the page */
    function injectStyles() {
        const theme = CONFIG.themes[STATE.settings.themeStyle] || CONFIG.themes.minimal;

        GM_addStyle(`
        :root {
    --enh-nav-theme: ${STATE.settings.themeColor};
    --enh-nav-bg: ${theme.bgColor};
    --enh-nav-hover: ${theme.hoverColor};
    --enh-nav-active: ${theme.activeColor};
    --enh-nav-text: ${theme.textColor};
    --enh-nav-shadow: ${theme.shadow};
    --enh-nav-panel-bg: ${theme.panelBg};
    --enh-nav-panel-border: ${theme.panelBorder};
    --enh-nav-select: ${theme.selectColor};
}

#enh-nav-container {
    position: fixed;
    right: 15px;
    bottom: 15px;
    z-index: 99999;
    display: flex !important;
    flex-direction: column;
    align-items: center;
    transition: opacity 0.3s ease;
}

#enh-nav-container.hidden {
    opacity: 0;
    pointer-events: none;
}

#enh-nav-container:hover,
#enh-nav-container.always-visible {
    opacity: 1;
    pointer-events: auto;
}

#enh-nav-hover-area {
    position: fixed;
    right: 0;
    bottom: 0;
    width: 60px;
    height: 60px;
    z-index: 99998;
}

.enh-nav-btn {
    background: var(--enh-nav-bg);
    color: var(--enh-nav-text);
    border-radius: 50%;
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    cursor: pointer;
    border: none;
    box-shadow: var(--enh-nav-shadow);
    transition: all 0.3s ease;
    user-select: none;
}

.enh-nav-btn:hover {
    transform: scale(1.1);
    background: var(--enh-nav-hover);
}

.enh-nav-btn.active {
    background: var(--enh-nav-active);
}

#enh-nav-main-btn {
    position: relative;
    font-weight: bold;
}

#enh-nav-progress-circle {
    position: absolute;
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
}

#enh-nav-progress-circle-bar {
    stroke: var(--enh-nav-theme);
    stroke-width: 4;
    fill: transparent;
    transition: stroke-dashoffset 0.1s linear;
}

#enh-nav-progress-text {
    font-size: 12px;
    font-weight: bold;
    color: var(--enh-nav-text);
}

#enh-nav-menu {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 10px;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    transform-origin: bottom center;
    transform: scale(0.8) translateY(20px);
    opacity: 0;
    pointer-events: none;
}

#enh-nav-container:hover #enh-nav-menu {
    transform: scale(1) translateY(0);
    opacity: 1;
    pointer-events: auto;
}

.enh-nav-menu-btn {
    width: 40px;
    height: 40px;
    font-size: 16px;
    margin-top: 10px;
}

.enh-nav-panel {
    position: fixed;
    right: 80px;
    bottom: 15px;
    width: 210px;
    background: var(--enh-nav-panel-bg);
    color: var(--enh-nav-text);
    border-radius: 16px;
    padding: 11px;
    box-shadow: var(--enh-nav-shadow);
    border: var(--enh-nav-panel-border);
    opacity: 0;
    transform: translateX(20px);
    transition: all 0.3s ease;
    pointer-events: none;
    z-index: 99998;
    backdrop-filter: blur(10px);
}

.enh-nav-panel.visible {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}

.enh-nav-panel h3 {
    margin: 0 0 11px;
    font-size: 15px;
    border-bottom: 1px solid rgba(255,255,255,0.2);
    padding-bottom: 10px;
    text-align: center;
}

.enh-nav-panel .close-btn {
    position: absolute;
    top: 15px;
    right: 15px;
    cursor: pointer;
    font-size: 16px;
    opacity: 0.7;
    transition: all 0.2s;
}

.enh-nav-panel .close-btn:hover {
    opacity: 1;
    transform: scale(1.1);
}

.enh-nav-setting-row {
    margin-bottom: 9px;
    padding: 6px 0;
    border-bottom: 1px solid rgba(255,255,255,0.1);
}

.enh-nav-setting-row label {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 14px;
    width: 100%;
}

.enh-nav-panel input[type=checkbox] {
    transform: scale(1.2);
    accent-color: var(--enh-nav-theme);
}

.enh-nav-panel input[type=color] {
    width: 40px;
    height: 25px;
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
}

.enh-nav-panel input[type=range] {
    width: 100%;
    margin-top: 5px;
    accent-color: var(--enh-nav-theme);
}

.enh-nav-panel select {
    background: var(--enh-nav-select);
    color: var(--enh-nav-text);
    border: 1px solid rgba(255,255,255,0.2);
    border-radius: 8px;
    padding: 5px 10px;
    cursor: pointer;
}

#enh-nav-section-panel {
    width: 350px;
    height: 500px;
    max-height: 70vh;
    right: 90px;
    transform: translateX(30px) scale(0.95);
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

#enh-nav-section-panel.visible {
    transform: translateX(0) scale(1);
}

#enh-nav-section-panel ul {
    list-style: none;
    padding: 0;
    margin: 0;
    max-height: calc(100% - 60px);
    overflow-x: hidden;
    overflow-y: auto;
}

#enh-nav-section-panel ul::-webkit-scrollbar {
    width: 8px;
}

#enh-nav-section-panel ul::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.1);
    border-radius: 4px;
}

#enh-nav-section-panel ul::-webkit-scrollbar-thumb {
    background: var(--enh-nav-theme);
    border-radius: 4px;
}

#enh-nav-section-panel ul::-webkit-scrollbar-thumb:hover {
    background: var(--enh-nav-active);
}

#enh-nav-section-panel li {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 12px 15px;
    cursor: pointer;
    border-radius: 10px;
    font-size: 14px;
    margin-bottom: 8px;
    transition: all 0.3s ease;
    background: rgba(255,255,255,0.05);
    opacity: 0;
    transform: translateY(10px);
    transition-delay: calc(var(--index, 0) * 0.05s);
}

#enh-nav-section-panel.visible li {
    opacity: 1;
    transform: translateY(0);
}

#enh-nav-section-panel li:hover {
    background-color: var(--enh-nav-theme);
    color: white;
    transform: translateX(5px) translateY(0);
}

#enh-nav-section-panel li[data-i18n-key="noHeadings"] {
    text-align: center;
    padding: 30px;
    font-size: 16px;
    opacity: 0.7;
    white-space: normal;
    transform: none;
}

.theme-preview {
    display: inline-block;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    margin-right: 8px;
    vertical-align: middle;
}

.speed-container {
    display: flex;
    flex-direction: column;
    margin-top: 5px;
}

/* 位置样式 */
#enh-nav-container.enh-nav-pos-bottom-right {
    right: 15px;
    bottom: 15px;
    top: auto;
    transform: none;
}

#enh-nav-container.enh-nav-pos-top-right {
    right: 15px;
    top: 15px;
    bottom: auto;
    transform: none;
}

#enh-nav-container.enh-nav-pos-middle-right {
    right: 15px;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
}

/* 菜单方向 */
#enh-nav-container.enh-nav-pos-bottom-right #enh-nav-menu {
    flex-direction: column;
    margin-bottom: 10px;
    margin-top: 0;
}

#enh-nav-container.enh-nav-pos-top-right #enh-nav-menu,
#enh-nav-container.enh-nav-pos-middle-right #enh-nav-menu {
    flex-direction: column-reverse;
    margin-bottom: 0;
    margin-top: 10px;
}

#enh-nav-container.enh-nav-pos-top-right:hover #enh-nav-menu,
#enh-nav-container.enh-nav-pos-middle-right:hover #enh-nav-menu {
    transform: scale(1) translateY(0);
}

/* 面板位置 */
#enh-nav-container.enh-nav-pos-bottom-right .enh-nav-panel {
    bottom: 15px;
    top: auto;
}

#enh-nav-container.enh-nav-pos-top-right .enh-nav-panel {
    top: 15px;
    bottom: auto;
}

#enh-nav-container.enh-nav-pos-middle-right .enh-nav-panel {
    top: 50%;
    bottom: auto;
    transform: translateX(20px) translateY(-50%);
}

#enh-nav-container.enh-nav-pos-middle-right .enh-nav-panel.visible {
    transform: translateX(0) translateY(-50%);
}

/* 悬停区域位置 */
#enh-nav-hover-area.enh-nav-pos-bottom-right {
    right: 0;
    bottom: 0;
    top: auto;
}

#enh-nav-hover-area.enh-nav-pos-top-right {
    right: 0;
    top: 0;
    bottom: auto;
}

#enh-nav-hover-area.enh-nav-pos-middle-right {
    right: 0;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
}
/* 按钮位置样式*/
#enh-nav-container.enh-nav-pos-bottom-right {
    right: 15px;
    bottom: 15px;
    top: auto;
    transform: none;
}

#enh-nav-container.enh-nav-pos-top-right {
    right: 15px;
    top: 15px;
    bottom: auto;
    transform: none;
}

#enh-nav-container.enh-nav-pos-middle-right {
    right: 15px;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
}

/* 调整菜单方向 */
#enh-nav-container.enh-nav-pos-bottom-right #enh-nav-menu {
    flex-direction: column;
    margin-bottom: 10px;
    margin-top: 0;
}

#enh-nav-container.enh-nav-pos-top-right #enh-nav-menu {
    flex-direction: column;
    margin-bottom: 10px;
    margin-top: 0;
}

#enh-nav-container.enh-nav-pos-middle-right #enh-nav-menu {
    flex-direction: column;
    margin-bottom: 10px;
    margin-top: 0;
}

/* 调整面板位置 */
#enh-nav-container.enh-nav-pos-bottom-right .enh-nav-panel {
    right: 80px;
    bottom: 15px;
    top: auto;
}

#enh-nav-container.enh-nav-pos-top-right .enh-nav-panel {
    right: 80px;
    top: 80px; /* 在按钮下方 */
    bottom: auto;
}

#enh-nav-container.enh-nav-pos-middle-right .enh-nav-panel {
    right: 80px;
    top: calc(50% + 40px); /* 在按钮下方 */
    bottom: auto;
    transform: translateX(20px) translateY(-50%);
}

#enh-nav-container.enh-nav-pos-middle-right .enh-nav-panel.visible {
    transform: translateX(0) translateY(-50%);
}

/* 确保面板在正确位置 */
.enh-nav-panel {
    transform: translateX(20px);
}

.enh-nav-panel.visible {
    transform: translateX(0);
}

/* 调整悬停区域位置 */
#enh-nav-hover-area.enh-nav-pos-bottom-right {
    right: 0;
    bottom: 0;
    top: auto;
    width: 80px;
    height: 80px;
}

#enh-nav-hover-area.enh-nav-pos-top-right {
    right: 0;
    top: 0;
    bottom: auto;
    width: 80px;
    height: 80px;
}

#enh-nav-hover-area.enh-nav-pos-middle-right {
    right: 0;
    top: 50%;
    bottom: auto;
    transform: translateY(-50%);
    width: 80px;
    height: 80px;
}

        `);
    }

    /** Creates the main UI elements */
    function createUI() {
        const container = document.createElement('div');
        container.id = 'enh-nav-container';

        if (!STATE.settings.alwaysShowButtons) {
            container.classList.add('hidden');
        } else {
            container.classList.add('always-visible');
        }

        const hoverArea = document.createElement('div');
        hoverArea.id = 'enh-nav-hover-area';
        hoverArea.classList.add(`enh-nav-pos-${STATE.settings.buttonPosition || 'bottom-right'}`);
        document.body.appendChild(hoverArea);

        const progressRadius = 22;
        const progressCircumference = 2 * Math.PI * progressRadius;

        container.innerHTML = `
            <!-- Menu Buttons (appear on hover) -->
            <div id="enh-nav-menu">
                <button id="enh-nav-settings-btn" class="enh-nav-btn enh-nav-menu-btn" title="Settings" data-i18n-prop="title" data-i18n-key="settings">⚙️</button>
                <button id="enh-nav-section-btn" class="enh-nav-btn enh-nav-menu-btn" title="Section Nav" data-i18n-prop="title" data-i18n-key="sectionNav">📄</button>
                <button id="enh-nav-autoscroll-btn" class="enh-nav-btn enh-nav-menu-btn" title="Auto-Scroll" data-i18n-prop="title" data-i18n-key="autoScroll">⏯️</button>
            </div>

            <!-- Main Scroll Button -->
            <button id="enh-nav-main-btn" class="enh-nav-btn" title="Scroll to Bottom">
                <span id="enh-nav-scroll-arrow">⬇️</span>
                <span id="enh-nav-progress-text">0%</span>
                <svg id="enh-nav-progress-circle" width="48" height="48">
                    <circle id="enh-nav-progress-circle-bar" r="${progressRadius}" cx="24" cy="24" stroke-dasharray="${progressCircumference}" stroke-dashoffset="${progressCircumference}"></circle>
                </svg>
            </button>

            <!-- Settings Panel -->
            <div id="enh-nav-settings-panel" class="enh-nav-panel" enh-nav-pos-${STATE.settings.buttonPosition || 'bottom-right'}">
                <span class="close-btn">✖️</span>
                <h3 data-i18n-key="settingsTitle">Script Settings</h3>
                <div class="enh-nav-setting-row">
                    <strong data-i18n-key="showHideButtons">Show/Hide Buttons</strong>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="showAutoScrollButton">Auto-Scroll</span><input type="checkbox" id="enh-nav-toggle-autoscroll"></label>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="showSectionNavButton">Section Nav</span><input type="checkbox" id="enh-nav-toggle-section"></label>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="showProgressIndicator">Show Progress Indicator</span><input type="checkbox" id="enh-nav-toggle-progress"></label>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="alwaysShowButtons">Always Show Buttons</span><input type="checkbox" id="enh-nav-toggle-always-show"></label>
                </div>
                <div class="enh-nav-setting-row">
                <label><span data-i18n-key="buttonPosition">Button Position</span>
                    <select id="enh-nav-button-position">
                        <option value="bottom-right" data-i18n-key="positionBottomRight">Bottom Right</option>
                        <option value="top-right" data-i18n-key="positionTopRight">Top Right</option>
                        <option value="middle-right" data-i18n-key="positionMiddleRight">Middle Right</option>
                    </select>
                </label>
                </div>
                <hr style="border-color: rgba(255,255,255,0.2); margin: 15px 0;">
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="language">Language</span>
                        <select id="enh-nav-lang-select">
                            <option value="en">English</option>
                            <option value="zh">中文</option>
                        </select>
                    </label>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="themeStyle">Theme Style</span>
                    <select id="enh-nav-theme-style">
                    ${Object.entries(CONFIG.themes).map(([id, theme]) =>
            `<option value="${id}">${theme.name[STATE.settings.language] || theme.name.en}</option>`
        ).join('')}
                    </select>
                    </label>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="iconSet">Icon Style</span>
                        <select id="enh-nav-icon-set">
                            <option value="minimal" data-i18n-key="iconSetMinimal">Minimal</option>
                            <option value="colorful" data-i18n-key="iconSetColorful">Colorful</option>
                            <option value="tech" data-i18n-key="iconSetTech">Tech</option>
                            <option value="forest" data-i18n-key="iconSetForest">Forest</option>
                            <option value="anime" data-i18n-key="iconSetAnime">Anime</option>
                        </select>
                    </label>
                </div>
                <div class="enh-nav-setting-row">
                    <label><span data-i18n-key="themeColor">Theme Color</span><input type="color" id="enh-nav-theme-color"></label>
                </div>
                <div class="enh-nav-setting-row">
                     <label><span data-i18n-key="scrollSpeed">Scroll Speed</span> <span id="enh-nav-speed-value"></span></label>
                     <div class="speed-container">
                         <input type="range" id="enh-nav-scroll-speed" min="1" max="10" step="1">
                     </div>
                </div>
            </div>

            <!-- Section Nav Panel -->
            <div id="enh-nav-section-panel" class="enh-nav-panel" enh-nav-pos-${STATE.settings.buttonPosition || 'bottom-right'}">
                 <span class="close-btn">✖️</span>
                 <h3 data-i18n-key="navTitle">Page Navigation</h3>
                 <ul id="enh-nav-section-list"></ul>
            </div>
        `;
        document.body.appendChild(container);

        // Apply initial visibility from settings
        document.getElementById('enh-nav-autoscroll-btn').style.display = STATE.settings.showAutoScrollBtn ? 'flex' : 'none';
        document.getElementById('enh-nav-section-btn').style.display = STATE.settings.showSectionNavBtn ? 'flex' : 'none';

        // Apply initial progress indicator setting
        updateProgressIndicatorVisibility();
    }

    /** Updates the circular progress bar and scroll direction arrow */
    function updateScrollState() {
        if (!STATE.scrollContainer) return;
        const { scrollTop, scrollHeight, clientHeight } = STATE.scrollContainer;
        const scrollableHeight = scrollHeight - clientHeight;

        const arrowEl = document.getElementById('enh-nav-scroll-arrow');
        const textEl = document.getElementById('enh-nav-progress-text');
        const circleBar = document.getElementById('enh-nav-progress-circle-bar');

        if (scrollableHeight <= 0) {
            if (arrowEl) arrowEl.style.display = 'block';
            if (textEl) textEl.style.display = 'none';
            if (arrowEl) arrowEl.textContent = '↕️';
            return;
        }

        const percent = Math.min(Math.round((scrollTop / scrollableHeight) * 100), 100);
        const isNearTop = scrollTop < 100;
        const isNearBottom = scrollTop > scrollableHeight - 100;

        // Show arrow or percentage based on settings
        const showProgress = STATE.settings.showProgressIndicator;

        if (isNearTop || isNearBottom || !showProgress) {
            if (arrowEl) arrowEl.style.display = 'block';
            if (textEl) textEl.style.display = 'none';
            if (arrowEl) arrowEl.textContent = isNearTop ? '⬇️' : '⬆️';
        } else {
            if (arrowEl) arrowEl.style.display = 'none';
            if (textEl) textEl.style.display = 'block';
            if (textEl) textEl.textContent = `${percent}%`;
        }

        // Update progress circle
        if (circleBar) {
            const radius = circleBar.r.baseVal.value;
            const circumference = 2 * Math.PI * radius;
            const offset = circumference - (percent / 100) * circumference;
            circleBar.style.strokeDashoffset = offset;
        }

        // Update main button title for accessibility
        updateScrollArrow();
        updateUIText();
    }

    /** Updates progress indicator visibility based on setting */
    function updateProgressIndicatorVisibility() {
        const textEl = document.getElementById('enh-nav-progress-text');
        const circleBar = document.getElementById('enh-nav-progress-circle-bar');
        const showProgress = STATE.settings.showProgressIndicator;

        if (textEl && circleBar) {
            textEl.style.display = showProgress ? 'block' : 'none';
            circleBar.style.display = showProgress ? 'block' : 'none';
        }
        updateScrollState(); // Refresh the display
    }

    /** Populates the section navigation panel */
    function updateSectionNav() {
        const list = document.getElementById('enh-nav-section-list');
        const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6'); // 包含所有标题级别

        list.innerHTML = '';

        const unwantedTexts = [
            '脚本设置', 'Script Settings',
            '页面导航', 'Section Navigation',
            'Upgrade to SuperGrok',
            'Chat history', 'Chats', 'You said:', 'ChatGPT said:',
            '导航', 'Navigate',
            '设置', 'Settings'
        ];

        if (headings.length === 0) {
            list.innerHTML = `<li data-i18n-key="noHeadings" style="opacity: 0.6; text-align: center; padding: 30px;">
            ${CONFIG.i18n[STATE.settings.language].noHeadings}
        </li>`;
            return;
        }

        let hasValidHeadings = false;
        let index = 0;
        headings.forEach(h => {
            const text = h.textContent.trim();
            const id = h.id || h.textContent.toLowerCase().replace(/\s+/g, '-');

            if (text === '' || unwantedTexts.includes(text)) return;

            hasValidHeadings = true;

            const item = document.createElement('li');
            item.textContent = text;

            const level = parseInt(h.tagName.substring(1));
            item.style.paddingLeft = `${(level - 1) * 15 + 15}px`;
            item.style.fontSize = `${18 - level * 2}px`;
            item.style.fontWeight = level <= 2 ? 'bold' : 'normal';

            item.style.setProperty('--index', index);
            index++;
            item.addEventListener('mouseenter', () => {
                h.style.transition = 'background-color 0.2s';
                h.style.backgroundColor = 'var(--enh-nav-theme)';
            });

            item.addEventListener('mouseleave', () => {
                setTimeout(() => {
                    h.style.backgroundColor = '';
                }, 200);
            });

            item.onclick = () => {
                const element = document.getElementById(id) || h;
                element.scrollIntoView({
                    behavior: 'smooth',
                    block: 'start'
                });

                const originalBg = element.style.backgroundColor;
                element.style.backgroundColor = 'var(--enh-nav-theme)';
                element.style.transition = 'background-color 0.3s';
            };

            list.appendChild(item);
        });

        if (!hasValidHeadings) {
            list.innerHTML = `<li data-i18n-key="noHeadings" style="opacity: 0.6; text-align: center; padding: 30px;">
            ${CONFIG.i18n[STATE.settings.language].noHeadings}
        </li>`;
        }
    }
    /** Toggles the visibility of a panel */
    function togglePanel(panelId, forceState) {
        const panel = document.getElementById(panelId);
        if (!panel) return;
        // Hide other panels
        // document.querySelectorAll('.enh-nav-panel').forEach(p => {
        //     if (p.id !== panelId) p.classList.remove('visible');
        // });
        const isVisible = panel.classList.toggle('visible', forceState);
        // Toggle current panel
        // If we are opening the section nav, refresh its content
        if (isVisible && panelId === 'enh-nav-section-panel') {
            updateSectionNav();
        }
    }

    /** Applies the selected theme style */
    function applyThemeStyle(themeId) {
        STATE.settings.themeStyle = themeId;
        GM_setValue('themeStyle', themeId);
        injectStyles(); // Re-inject styles with the new theme
    }


    // --- 4. EVENT LISTENERS --- //

    /** Binds all event listeners to the UI */
    function attachEventListeners() {
        // Main Actions
        document.getElementById('enh-nav-main-btn').addEventListener('click', handleScrollClick);
        document.getElementById('enh-nav-autoscroll-btn').addEventListener('click', toggleAutoScroll);

        // Panel Toggles
        document.getElementById('enh-nav-settings-btn').addEventListener('click', () => togglePanel('enh-nav-settings-panel'));
        document.getElementById('enh-nav-section-btn').addEventListener('click', () => togglePanel('enh-nav-section-panel'));

        // Close Panel Buttons
        document.querySelectorAll('.enh-nav-panel .close-btn').forEach(btn => {
            btn.addEventListener('click', (e) => e.currentTarget.parentElement.classList.remove('visible'));
        });

        // Settings Controls
        const settingsMap = {
            'enh-nav-toggle-autoscroll': { key: 'showAutoScrollBtn', target: '#enh-nav-autoscroll-btn', type: 'toggle' },
            'enh-nav-toggle-section': { key: 'showSectionNavBtn', target: '#enh-nav-section-btn', type: 'toggle' },
            'enh-nav-toggle-progress': { key: 'showProgressIndicator', type: 'value', callback: updateProgressIndicatorVisibility },
            'enh-nav-icon-set': {
                key: 'iconSet',
                type: 'value',
                callback: updateIcons
            },
            'enh-nav-button-position': {
                key: 'buttonPosition',
                type: 'value',
                callback: (value) => {
                    applyButtonPosition(value);
                    setTimeout(() => {
                        updatePanelPositions(value);
                    }, 100);
                }
            },
            'enh-nav-toggle-always-show': {
                key: 'alwaysShowButtons',
                type: 'toggle',
                callback: (value) => {
                    const container = document.getElementById('enh-nav-container');
                    const hoverArea = document.getElementById('enh-nav-hover-area');

                    if (value) {
                        container.classList.add('always-visible');
                        container.classList.remove('hidden');
                        if (hoverArea) hoverArea.style.display = 'none';
                    } else {
                        container.classList.remove('always-visible');
                        container.classList.add('hidden');
                        if (hoverArea) hoverArea.style.display = 'block';
                    }
                }
            },
            'enh-nav-lang-select': { key: 'language', type: 'value', callback: updateUIText },
            'enh-nav-theme-style': { key: 'themeStyle', type: 'value', callback: applyThemeStyle },
            'enh-nav-theme-color': {
                key: 'themeColor', type: 'value', callback: (value) => {
                    document.documentElement.style.setProperty('--enh-nav-theme', value);
                    updateUIText();
                }
            },
            'enh-nav-scroll-speed': { key: 'scrollSpeed', type: 'value', callback: updateUIText },
        };

        for (const [id, config] of Object.entries(settingsMap)) {
            const el = document.getElementById(id);
            if (!el) continue;

            const eventType = (el.type === 'checkbox' || el.tagName === 'SELECT') ? 'change' : 'input';

            // Set initial value
            if (el.type === 'checkbox') el.checked = STATE.settings[config.key];
            else el.value = STATE.settings[config.key];

            // Add listener
            el.addEventListener(eventType, (e) => {
                const value = (e.target.type === 'checkbox') ? e.target.checked : e.target.value;
                GM_setValue(config.key, value);
                STATE.settings[config.key] = value;

                // Apply change instantly
                if (config.type === 'toggle' && config.target) {
                    document.querySelector(config.target).style.display = value ? 'flex' : 'none';
                }
                if (config.callback) {
                    config.callback(value);
                }
            });
        }

        const hoverArea = document.getElementById('enh-nav-hover-area');
        const container = document.getElementById('enh-nav-container');

        if (hoverArea && container) {
            hoverArea.addEventListener('mouseenter', () => {
                if (!STATE.settings.alwaysShowButtons) {
                    container.classList.remove('hidden');
                }
            });

            container.addEventListener('mouseleave', () => {
                if (!STATE.settings.alwaysShowButtons) {
                    container.classList.add('hidden');
                }
            });
        }
    }


    // --- 5. INITIALIZATION --- //

    /** Main function to start the script */
    function init() {
        if (document.getElementById('enh-nav-container')) return;

        STATE.scrollContainer = findScrollContainer();
        if (!STATE.scrollContainer) {
            setTimeout(init, 1000); // Retry if container not found yet
            return;
        }

        loadSettings();
        injectStyles();
        updateIcons();
        createUI();
        attachEventListeners();
        updateUIText();
        updateScrollState();
        applyButtonPosition(STATE.settings.buttonPosition);

        const scrollTarget = (STATE.currentPlatform === 'generic') ? window : STATE.scrollContainer;
        scrollTarget.addEventListener('scroll', updateScrollState, { passive: true });

        const observer = new MutationObserver(() => {
            const currentContainer = findScrollContainer();
            if (STATE.scrollContainer !== currentContainer) {
                STATE.scrollContainer = currentContainer;
                const newTarget = (STATE.currentPlatform === 'generic') ? window : STATE.scrollContainer;
                newTarget.addEventListener('scroll', updateScrollState, { passive: true });
                updateScrollState();
            }
        });
        observer.observe(document.body, { childList: true, subtree: true });

        console.log("Enhanced AI Chat Scroll Navigator initialized.");
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }

})();