QuickNav for Google AI Studio

Restores classic chat navigation in Google AI Studio, adding essential UI controls for precise, message-by-message browsing, and a powerful message index menu for efficient conversation navigation. This script operates entirely locally in your browser, does not collect any personal data, and makes no requests to external servers.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         QuickNav for Google AI Studio
// @namespace    http://tampermonkey.net/
// @version      20.4
// @description  Restores classic chat navigation in Google AI Studio, adding essential UI controls for precise, message-by-message browsing, and a powerful message index menu for efficient conversation navigation. This script operates entirely locally in your browser, does not collect any personal data, and makes no requests to external servers.
// @author       Axl_script
// @homepageURL  https://greasyfork.org/en/scripts/548346-quicknav-for-google-ai-studio
// @contributionURL https://nowpayments.io/donation/axl_script
// @match        https://aistudio.google.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

// Manages chat state, scrolling, observers, and turn indexing.
    const ChatController = {
        allTurns: [],
        currentIndex: -1,
        menuFocusedIndex: -1,
        isDownButtonAtEndToggle: false,
        JUMP_DISTANCE: 5,
        isScrollingProgrammatically: false,
        isQueueProcessing: false,
        isUnstickingFromBottom: false,
        originalScrollTop: 0,
        originalCurrentIndex: -1,
        loadingQueue: [],
        totalToLoad: 0,
        chatObserver: null,
        visibilityObserver: null,
        scrollObserver: null,
        chatContainerElement: null,
        currentScrollContainer: null,
        holdTimeout: null,
        holdInterval: null,
        isBottomHoldActive: false,
        bottomHoldTimeout: null,
        bottomHoldInterval: null,
        debouncedBuildTurnIndex: null,
        visibleTurnContainers: new Set(),
        isScrollUpdateQueued: false,
        boundHandlePageScroll: null,
        boundHandleRealtimeScrollSync: null,
        isScrollLocked: false,
        scrollLockInterval: null,
        scrollLockTimeout: null,

        init(chatContainer) {
            this.chatContainerElement = chatContainer;
            this.debouncedBuildTurnIndex = this.debounce(this.buildTurnIndex.bind(this), 750);
            
            this.boundHandlePageScroll = UIManager.handlePageScroll.bind(UIManager);
            this.boundHandleRealtimeScrollSync = this.handleRealtimeScrollSync.bind(this);

            this.initializeChatObserver(this.chatContainerElement);
            this.attachScrollListeners();
            this.buildTurnIndex();

            document.addEventListener('mousedown', this.stopBottomHold.bind(this), true);
            document.addEventListener('wheel', this.stopBottomHold.bind(this), true);
            document.addEventListener('click', this.handleEditClick.bind(this), true);
        },

        attachScrollListeners() {
            const newScrollContainer = this.chatContainerElement?.querySelector('ms-autoscroll-container');
            
            if (this.currentScrollContainer === newScrollContainer && newScrollContainer?.isConnected) {
                return;
            }

            if (this.currentScrollContainer) {
                this.currentScrollContainer.removeEventListener('scroll', this.boundHandlePageScroll);
                this.currentScrollContainer.removeEventListener('scroll', this.boundHandleRealtimeScrollSync);
            }

            if (newScrollContainer) {
                this.currentScrollContainer = newScrollContainer;
                this.currentScrollContainer.addEventListener('scroll', this.boundHandlePageScroll);
                this.currentScrollContainer.addEventListener('scroll', this.boundHandleRealtimeScrollSync);
                this.handleRealtimeScrollSync();
            } else {
                this.currentScrollContainer = null;
            }
        },

        destroy() {
            if (this.chatObserver) this.chatObserver.disconnect();
            if (this.visibilityObserver) this.visibilityObserver.disconnect();
            if (this.scrollObserver) this.scrollObserver.disconnect();
            this.chatObserver = null;
            this.visibilityObserver = null;
            this.scrollObserver = null;
            this.clearScrollLock();

            if (this.currentScrollContainer) {
                this.currentScrollContainer.removeEventListener('scroll', this.boundHandlePageScroll);
                this.currentScrollContainer.removeEventListener('scroll', this.boundHandleRealtimeScrollSync);
            }
            this.currentScrollContainer = null;

            this.chatContainerElement = null;
            this.allTurns = [];
            this.currentIndex = -1;
            this.menuFocusedIndex = -1;
            document.removeEventListener('mousedown', this.stopBottomHold.bind(this), true);
            document.removeEventListener('wheel', this.stopBottomHold.bind(this), true);
            document.removeEventListener('click', this.handleEditClick.bind(this), true);
        },

        clearScrollLock() {
            clearInterval(this.scrollLockInterval);
            clearTimeout(this.scrollLockTimeout);
            this.scrollLockInterval = null;
            this.scrollLockTimeout = null;
            this.isScrollLocked = false;
        },

        handleEditClick(event) {
            const editButton = event.target.closest('ms-chat-turn .toggle-edit-button');
            if (!editButton || this.isScrollLocked) return;

            const turnElement = event.target.closest('ms-chat-turn');
            const scrollContainer = this.currentScrollContainer;
            if (!turnElement || !scrollContainer) return;

            const buttonIcon = editButton.querySelector('.ms-button-icon-symbol');
            const isEnteringEditMode = buttonIcon && buttonIcon.textContent.trim() !== 'done_all';
            if (!isEnteringEditMode) return;

            const savedScrollTop = scrollContainer.scrollTop;
            this.isScrollLocked = true;

            const immediateClearLock = () => {
                this.clearScrollLock();
                scrollContainer.removeEventListener('wheel', immediateClearLock, { once: true });
                scrollContainer.removeEventListener('mousedown', immediateClearLock, { once: true });
            };

            scrollContainer.addEventListener('wheel', immediateClearLock, { once: true });
            scrollContainer.addEventListener('mousedown', immediateClearLock, { once: true });

            this.scrollLockInterval = setInterval(() => {
                if (scrollContainer.scrollTop !== savedScrollTop) {
                    scrollContainer.scrollTop = savedScrollTop;
                }
            }, 15);

            this.scrollLockTimeout = setTimeout(() => {
                immediateClearLock();
            }, 5000);
        },

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

        // Sets up the MutationObserver to track chat additions and removals.
        initializeChatObserver(container) {
            const observerCallback = (mutationsList) => {
                this.attachScrollListeners();

                let shouldRebuildIndex = false;

                for (const mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        if (mutation.addedNodes.length > 0) {
                            for (const node of mutation.addedNodes) {
                                if (node.nodeType === 1) {
                                    if (node.matches('ms-chat-turn') || node.querySelector('ms-chat-turn')) {
                                        shouldRebuildIndex = true;
                                    }
                                    const codeBlock = node.matches('ms-code-block') ? node : node.querySelector('ms-code-block');
                                    if (codeBlock) {
                                        const parentTurn = codeBlock.closest('ms-chat-turn');
                                        if (parentTurn) CodeBlockNavigator.processTurns([parentTurn]);
                                    }
                                }
                            }
                        }

                        if (mutation.removedNodes.length > 0) {
                            const turnRemoved = Array.from(mutation.removedNodes).some(node => 
                                node.nodeType === 1 && (
                                    node.matches('ms-chat-turn') || 
                                    node.querySelector?.('ms-chat-turn')
                                )
                            );
                            if (turnRemoved) {
                                shouldRebuildIndex = true;
                            }
                        }
                    }
                }

                if (shouldRebuildIndex) {
                    this.debouncedBuildTurnIndex();
                }
            };

            this.chatObserver = new MutationObserver(observerCallback);
            this.chatObserver.observe(container, { childList: true, subtree: true });
        },

        setupVisibilityObserver() {
            if (this.visibilityObserver) {
                this.visibilityObserver.disconnect();
            }
            const scrollContainer = this.currentScrollContainer || document.querySelector('ms-autoscroll-container');
            if (!scrollContainer || this.allTurns.length === 0) {
                return;
            }

            const observerCallback = (entries) => {
                for (const entry of entries) {
                    if (entry.isIntersecting) {
                        const visibleTurnElement = entry.target;
                        const turnIndex = this.allTurns.findIndex(t => t === visibleTurnElement);
                        if (turnIndex === -1) continue;

                        CodeBlockNavigator.processTurns([visibleTurnElement]);

                        const turnObject = this.allTurns[turnIndex];
                        const newContent = UIManager.getTextFromTurn(visibleTurnElement, true);

                        if (newContent.source === 'fallback') {
                            continue;
                        }

                        const hasValidCache = turnObject.cachedContent && !turnObject.isFallbackContent;
                        const isAnUpgrade = hasValidCache && turnObject.cachedContent.source === 'scrollbar' && newContent.source === 'dom';
                        const contentContainer = turnObject.querySelector('.turn-content');
                        const contentHasChanged = hasValidCache && Math.abs(turnObject.cachedContent.full.length - newContent.full.length) > 5;

                        if (!hasValidCache || isAnUpgrade || contentHasChanged) {
                            turnObject.cachedContent = newContent;
                            turnObject.isFallbackContent = false;
                            UIManager.updateMenuItemContent(turnIndex);
                        }
                    }
                }
            };

            this.visibilityObserver = new IntersectionObserver(observerCallback, {
                root: scrollContainer,
                rootMargin: "0px",
            });

            this.allTurns.forEach(turn => this.visibilityObserver.observe(turn));
        },

        setupScrollObserver() {
            if (this.scrollObserver) this.scrollObserver.disconnect();
            const scrollContainer = this.currentScrollContainer || document.querySelector('ms-autoscroll-container');
            if (!scrollContainer || this.allTurns.length === 0) return;

            const observerCallback = (entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        this.visibleTurnContainers.add(entry.target);
                    } else {
                        this.visibleTurnContainers.delete(entry.target);
                    }
                });
            };

            this.scrollObserver = new IntersectionObserver(observerCallback, {
                root: scrollContainer,
                rootMargin: "0px",
                threshold: 0
            });

            this.allTurns.forEach(turn => {
                const container = turn.querySelector('.chat-turn-container');
                if (container) {
                    this.scrollObserver.observe(container);
                }
            });
        },

        handleRealtimeScrollSync() {
            if (this.isScrollUpdateQueued) {
                return;
            }
            this.isScrollUpdateQueued = true;

            requestAnimationFrame(() => {
                if (this.isScrollingProgrammatically || this.isQueueProcessing || this.isUnstickingFromBottom || this.isScrollLocked) {
                    this.isScrollUpdateQueued = false;
                    return;
                }

                if (!this.currentScrollContainer || !this.currentScrollContainer.isConnected) {
                    this.attachScrollListeners();
                }

                const scrollContainer = this.currentScrollContainer;
                if (!scrollContainer) {
                    this.isScrollUpdateQueued = false;
                    return;
                }

                const activationLine = scrollContainer.clientHeight * 0.3;
                let bestMatch = { element: null, minDistance: Infinity };
                
                const containersToCheck = this.visibleTurnContainers.size > 0 
                    ? this.visibleTurnContainers 
                    : this.allTurns.map(t => t.querySelector('.chat-turn-container')).filter(Boolean);

                containersToCheck.forEach(containerElement => {
                    const rect = containerElement.getBoundingClientRect();
                    const distance = Math.abs(rect.top - activationLine);

                    if (distance < bestMatch.minDistance) {
                        bestMatch = { element: containerElement, minDistance: distance };
                    }
                });

                if (bestMatch.element) {
                    const parentTurn = bestMatch.element.closest('ms-chat-turn');
                    if (parentTurn) {
                        const bestMatchIndex = this.allTurns.indexOf(parentTurn);
                        if (bestMatchIndex !== -1 && this.currentIndex !== bestMatchIndex) {
                            UIManager.updateHighlight(this.currentIndex, bestMatchIndex);
                            this.currentIndex = bestMatchIndex;

                            const currentTurn = this.allTurns[bestMatchIndex];
                            if (currentTurn && (!currentTurn.cachedContent || currentTurn.isFallbackContent)) {
                                const newContent = UIManager.getTextFromTurn(currentTurn, true);
                                if (newContent.source !== 'fallback') {
                                    currentTurn.cachedContent = newContent;
                                    currentTurn.isFallbackContent = false;
                                }
                            }
                            UIManager.updateMenuItemContent(bestMatchIndex);

                            UIManager.updateCounterDisplay();
                            UIManager.showBadge();
                            UIManager.updateScrollPercentage();
                            UIManager.hideBadge();
                        }
                    }
                }
                this.isScrollUpdateQueued = false;
            });
        },

        isUserPrompt(turnElement) {
            return !!turnElement.querySelector('.chat-turn-container.user');
        },

        // Scans the DOM to build the index of chat turns.
        buildTurnIndex() {
            const freshTurns = Array.from(document.querySelectorAll('ms-chat-turn')).filter(turn => {
                const isUser = !!turn.querySelector('.chat-turn-container.user');
                if (isUser) return true;

                const isModel = !!turn.querySelector('.chat-turn-container.model');
                if (isModel) {
                    const isThought = !!turn.querySelector('ms-thought-chunk');
                    const hasEditButton = !!turn.querySelector('.toggle-edit-button');
                    const contentContainer = turn.querySelector('.turn-content');
                    const hasRenderedContent = !!(contentContainer && contentContainer.querySelector('ms-prompt-chunk, ms-code-block'));


                    return !isThought && (hasEditButton || hasRenderedContent);
                }
                return false;
            });

            if (freshTurns.length !== this.allTurns.length || !this.arraysEqual(this.allTurns, freshTurns)) {
                const oldIndex = this.currentIndex;
                
                const freshTurnsSet = new Set(freshTurns);
                this.allTurns.forEach(oldTurn => {
                    if (!freshTurnsSet.has(oldTurn)) {
                        const container = oldTurn.querySelector('.chat-turn-container');
                        if (container) {
                            container.classList.remove('prompt-turn-highlight', 'response-turn-highlight');
                        }
                    }
                });

                const contentCache = new Map();
                this.allTurns.forEach(turn => {
                    if (turn.id && turn.cachedContent) {
                        contentCache.set(turn.id, { content: turn.cachedContent, isFallback: turn.isFallbackContent });
                    }
                });

                this.allTurns = freshTurns;

                this.allTurns.forEach(turn => {
                    if (turn.id && contentCache.has(turn.id)) {
                        const cachedData = contentCache.get(turn.id);
                        turn.cachedContent = cachedData.content;
                        turn.isFallbackContent = cachedData.isFallback;
                    } else {
                        turn.cachedContent = null;
                        turn.isFallbackContent = false;
                    }
                });

                if (this.allTurns.length === 0) {
                    this.currentIndex = -1;
                } else if (this.currentIndex >= this.allTurns.length) {
                    this.currentIndex = this.allTurns.length - 1;
                    UIManager.updateHighlight(-1, this.currentIndex);
                } else {
                    UIManager.updateHighlight(-1, this.currentIndex);
                }

                this.setupScrollObserver();
                this.setupVisibilityObserver();

                const menuContainer = document.getElementById('chat-nav-menu-container');
                if (menuContainer && menuContainer.classList.contains('visible')) {
                    UIManager.populateNavMenu();
                    const menuList = document.getElementById('chat-nav-menu');
                    const items = menuList ? menuList.querySelectorAll('.chat-nav-menu-item') : [];
                    if (items.length > 0) {
                         const safeFocusIndex = Math.min(this.menuFocusedIndex, items.length - 1);
                         UIManager.updateMenuFocus(items, Math.max(0, safeFocusIndex), false);
                    }
                }

                if (this.allTurns.length > 0 && this.currentIndex === -1) {
                    setTimeout(() => this.handleRealtimeScrollSync(), 150);
                }
            }

            CodeBlockNavigator.processTurns(this.allTurns);
            UIManager.updateCounterDisplay();
        },

        arraysEqual(a, b) {
            if (a.length !== b.length) return false;
            for (let i = 0; i < a.length; i++) {
                if (a[i] !== b[i]) return false;
            }
            return true;
        },

        setupHoldableButton(button, action) {
            const HOLD_DELAY = 300;
            const HOLD_INTERVAL = 100;
            let isHolding = false;
            const stopHold = () => {
                clearTimeout(this.holdTimeout);
                clearInterval(this.holdInterval);
                this.holdInterval = null;
                isHolding = false;
            };
            button.addEventListener('click', (e) => {
                if (!isHolding) {
                    action();
                }
                stopHold();
            });
            button.addEventListener('mousedown', (e) => {
                if (e.button !== 0) return;
                isHolding = true;
                this.holdTimeout = setTimeout(() => {
                    if (isHolding) {
                        this.holdInterval = setInterval(action, HOLD_INTERVAL);
                    }
                }, HOLD_DELAY);
            });
            button.addEventListener('mouseup', stopHold);
            button.addEventListener('mouseleave', stopHold);
        },

        scrollToAbsoluteTop() {
            const scrollContainer = this.currentScrollContainer;
            if (!scrollContainer) return;
            UIManager.hideBadge(0, true);
            this.isScrollingProgrammatically = true;
            scrollContainer.scrollTo({
                top: 0,
                behavior: this.holdInterval ? 'auto' : 'smooth'
            });
            if (this.allTurns.length > 0 && this.currentIndex !== 0) {
                UIManager.updateHighlight(this.currentIndex, 0);
                this.currentIndex = 0;
                UIManager.updateCounterDisplay();
            }
            setTimeout(() => {
                this.isScrollingProgrammatically = false;
                UIManager.showBadge();
                UIManager.updateScrollPercentage();
                UIManager.hideBadge(2000);
                this.focusChatContainer();
            }, this.holdInterval ? 50 : 800);
        },

        waitForTurnToStabilize(turnElement, timeout = 1000) {
            return new Promise((resolve, reject) => {
                let lastRect = turnElement.getBoundingClientRect();
                let stableChecks = 0;
                const STABLE_CHECKS_REQUIRED = 3;
                const CHECK_INTERVAL = 100;
                const intervalId = setInterval(() => {
                    if (!turnElement || !turnElement.isConnected) {
                        clearInterval(intervalId);
                        clearTimeout(timeoutId);
                        return reject(new Error('Target element was removed from DOM.'));
                    }
                    const currentRect = turnElement.getBoundingClientRect();
                    if (currentRect.top !== lastRect.top || currentRect.height !== lastRect.height) {
                        lastRect = currentRect;
                        stableChecks = 0;
                    } else {
                        stableChecks++;
                    }
                    if (stableChecks >= STABLE_CHECKS_REQUIRED) {
                        clearInterval(intervalId);
                        clearTimeout(timeoutId);
                        resolve();
                    }
                }, CHECK_INTERVAL);
                const timeoutId = setTimeout(() => {
                    clearInterval(intervalId);
                    reject(new Error(`Element stabilization timed out.`));
                }, timeout);
            });
        },

        async scrollToTurn(index, blockPosition = 'center') {
            const targetTurn = this.allTurns[index];
            if (!targetTurn) {
                this.isScrollingProgrammatically = false;
                return;
            }
            this.isScrollingProgrammatically = true;
            const isSmooth = !this.isQueueProcessing && !this.holdInterval;
            const scrollContainer = this.currentScrollContainer;
            if (!scrollContainer) {
                this.isScrollingProgrammatically = false;
                return;
            }
            try {
                const verticalOffset = scrollContainer.clientHeight * 0.35;

                let initialTargetScrollTop;
                if (blockPosition === 'end') {
                    initialTargetScrollTop = targetTurn.offsetTop - (scrollContainer.clientHeight - targetTurn.offsetHeight);
                } else {
                    initialTargetScrollTop = targetTurn.offsetTop - verticalOffset;
                }

                scrollContainer.scrollTop = Math.max(0, Math.min(initialTargetScrollTop, scrollContainer.scrollHeight - scrollContainer.clientHeight));
                await this.waitForTurnToStabilize(targetTurn, 4000);

                let finalTargetScrollTop;
                if (blockPosition === 'end') {
                    finalTargetScrollTop = targetTurn.offsetTop - (scrollContainer.clientHeight - targetTurn.offsetHeight);
                } else {
                    finalTargetScrollTop = targetTurn.offsetTop - verticalOffset;
                }

                finalTargetScrollTop = Math.max(0, finalTargetScrollTop);
                finalTargetScrollTop = Math.min(finalTargetScrollTop, scrollContainer.scrollHeight - scrollContainer.clientHeight);
                scrollContainer.scrollTo({
                    top: finalTargetScrollTop,
                    behavior: isSmooth ? 'smooth' : 'auto'
                });
                const timeoutDuration = isSmooth ? 800 : 50;
                await new Promise(resolve => setTimeout(resolve, timeoutDuration));
            } catch (error) {} finally {
                this.isScrollingProgrammatically = false;
                UIManager.showBadge();
                UIManager.updateScrollPercentage();
                UIManager.hideBadge(2000);
            }
        },

        async navigateToIndex(newIndex, blockPosition = 'center') {
            if (newIndex < 0 || newIndex >= this.allTurns.length) return;
            UIManager.hideBadge(0, true);
            const oldIndex = this.currentIndex;
            if (newIndex < this.allTurns.length - 1) this.isDownButtonAtEndToggle = false;
            this.currentIndex = newIndex;

            UIManager.updateHighlight(oldIndex, newIndex);
            UIManager.updateCounterDisplay();
            await this.scrollToTurn(newIndex, blockPosition);

            const targetTurn = this.allTurns[newIndex];
            if (targetTurn) {
                const newContent = UIManager.getTextFromTurn(targetTurn, true);
                if (newContent.source !== 'fallback') {
                    targetTurn.cachedContent = newContent;
                    targetTurn.isFallbackContent = false;
                    UIManager.updateMenuItemContent(newIndex);
                }
            }

            UIManager.updateScrollPercentage();
            this.focusChatContainer();
        },

        async forceScrollToTop(scrollContainer) {
            return new Promise(resolve => {
                this.isScrollingProgrammatically = true;
                const firstTurn = this.allTurns[0];
                if (!firstTurn) {
                    this.isScrollingProgrammatically = false;
                    return resolve();
                }
                let attempts = 0;
                const maxAttempts = 15;
                const attemptScroll = () => {
                    attempts++;
                    scrollContainer.scrollTop = 0;
                    setTimeout(() => {
                        if (scrollContainer.scrollTop < 50 || attempts >= maxAttempts) {
                            firstTurn.scrollIntoView({ behavior: 'auto', block: 'start' });
                            setTimeout(() => { this.isScrollingProgrammatically = false; resolve(); }, 100);
                        } else {
                            attemptScroll();
                        }
                    }, 150);
                };
                attemptScroll();
            });
        },

        async startDynamicMenuLoading() {
            if (this.isQueueProcessing) return;
            const loadButton = document.getElementById('chat-nav-load-button');
            const scrollContainer = this.currentScrollContainer;
            if (!scrollContainer || !loadButton) return;
            const menuList = document.getElementById('chat-nav-menu');
            const menuItems = menuList ? menuList.querySelectorAll('.chat-nav-menu-item') : [];
            if (menuList && menuItems.length > 0) {
                const targetIndex = this.currentIndex > -1 ? this.currentIndex : 0;
                UIManager.updateMenuFocus(menuItems, targetIndex, true);
                menuList.focus({ preventScroll: true });
            }
            this.originalCurrentIndex = this.currentIndex;
            this.originalScrollTop = scrollContainer.scrollTop;
            this.loadingQueue = this.allTurns
                .map((turn, index) => ({ turn, index, menuItem: menuItems[index] }))
                .filter(item => {
                    const text = item.menuItem.dataset.tooltip;
                    return text.endsWith('...') || text === 'Could not extract content.' || !item.turn.cachedContent || item.turn.isFallbackContent;
                });
            if (this.loadingQueue.length > 0) {
                this.totalToLoad = this.loadingQueue.length;
                loadButton.disabled = true;
                loadButton.classList.add('loading-active');
                this.isQueueProcessing = true;

                const isAtBottom = scrollContainer.scrollTop >= scrollContainer.scrollHeight - scrollContainer.clientHeight - 5;
                if (isAtBottom) {
                    this.isUnstickingFromBottom = true;
                    scrollContainer.scrollTop -= 10;
                    await new Promise(resolve => setTimeout(resolve, 50));
                    this.isUnstickingFromBottom = false;
                }

                await this.forceScrollToTop(scrollContainer);
                this.processLoadingQueue();
            } else {
                const statusIndicator = document.getElementById('chat-nav-loader-status');
                if (statusIndicator) {
                    statusIndicator.textContent = 'All loaded.';
                    statusIndicator.classList.add('google-text-flash');
                    statusIndicator.addEventListener('animationend', () => {
                        statusIndicator.classList.remove('google-text-flash');
                    }, { once: true });
                }
            }
        },

        pollForContent(turn) {
            return new Promise((resolve, reject) => {
                const maxAttempts = 50;
                let attempts = 0;
                const interval = setInterval(() => {
                    if (!this.isQueueProcessing) {
                        clearInterval(interval);
                        return reject(new Error('Loading stopped by user.'));
                    }
                    const content = UIManager.getTextFromTurn(turn, true);
                    if (content.source === 'dom') {
                        clearInterval(interval);
                        resolve(content);
                    } else if (++attempts >= maxAttempts) {
                        clearInterval(interval);
                        reject(new Error('Content polling timed out.'));
                    }
                }, 100);
            });
        },

        async processLoadingQueue() {
            const statusIndicator = document.getElementById('chat-nav-loader-status');
            const menuItems = document.querySelectorAll('#chat-nav-menu .chat-nav-menu-item');
            while (this.loadingQueue.length > 0 && this.isQueueProcessing) {
                const itemsProcessed = this.totalToLoad - this.loadingQueue.length;
                if (statusIndicator) {
                    statusIndicator.textContent = `Loading ${itemsProcessed + 1} of ${this.totalToLoad}...`;
                    statusIndicator.classList.remove('google-text-flash');
                }
                const itemToLoad = this.loadingQueue.shift();
                const { turn, index, menuItem } = itemToLoad;
                const textSpan = menuItem.querySelector('.menu-item-text');
                if (!turn || !textSpan) continue;
                menuItem.classList.add('loading-in-progress');
                UIManager.updateMenuFocus(menuItems, index, true);
                try {
                    await this.scrollToTurn(index, 'center');
                    const newContent = await this.pollForContent(turn);
                    turn.cachedContent = newContent;
                    turn.isFallbackContent = false;
                    const truncatedText = (newContent.display.length > 200) ? newContent.display.substring(0, 197) + '...' : newContent.display;
                    textSpan.textContent = truncatedText;
                    menuItem.dataset.tooltip = newContent.full.replace(/\s+/g, ' ');
                } catch (error) {
                    console.error(`Failed to load item ${index + 1}:`, error.message);
                    textSpan.textContent = '[Error]';
                } finally {
                    menuItem.classList.remove('loading-in-progress');
                }
            }
            this.isQueueProcessing = false;
            const scrollContainer = this.currentScrollContainer;
            if (this.originalCurrentIndex > -1 && this.originalCurrentIndex < this.allTurns.length) {
                await this.navigateToIndex(this.originalCurrentIndex, 'center');
            } else if (scrollContainer) {
                this.isScrollingProgrammatically = true;
                scrollContainer.scrollTo({ top: this.originalScrollTop, behavior: 'smooth' });
                await new Promise(resolve => setTimeout(() => {
                    this.isScrollingProgrammatically = false;
                    resolve();
                }, 800));
            }
            const menuContainer = document.getElementById('chat-nav-menu-container');
            const loadButton = document.getElementById('chat-nav-load-button');
            if (loadButton) {
                loadButton.disabled = false;
                loadButton.classList.remove('loading-active');
            }
            if (statusIndicator) {
                if (this.loadingQueue.length > 0) {
                    statusIndicator.textContent = 'Stopped.';
                    statusIndicator.classList.remove('google-text-flash');
                } else {
                    statusIndicator.textContent = 'Done.';
                    statusIndicator.classList.add('google-text-flash');
                    statusIndicator.addEventListener('animationend', () => {
                        statusIndicator.classList.remove('google-text-flash');
                    }, { once: true });
                }
            }

            if (menuContainer && menuContainer.classList.contains('visible')) {
                const items = menuContainer.querySelectorAll('.chat-nav-menu-item');
                UIManager.updateMenuFocus(items, this.currentIndex, true);
                const menuList = document.getElementById('chat-nav-menu');
                if (menuList) {
                    menuList.focus({ preventScroll: true });
                }
            } else {
                this.focusChatContainer();
            }
        },

        stopDynamicMenuLoading() {
            if (!this.isQueueProcessing) return;
            this.isQueueProcessing = false;
            const loadButton = document.getElementById('chat-nav-load-button');
            if (loadButton) {
                loadButton.disabled = false;
                loadButton.classList.remove('loading-active');
            }
            const statusIndicator = document.getElementById('chat-nav-loader-status');
            if (statusIndicator) {
                statusIndicator.textContent = 'Stopped.';
                statusIndicator.classList.remove('google-text-animated');
            }
        },

        stopBottomHold() {
            if (!this.isBottomHoldActive) return;
            this.isBottomHoldActive = false;
            clearInterval(this.bottomHoldInterval);
            this.bottomHoldInterval = null;
            const btnBottom = document.getElementById('nav-bottom');
            if (btnBottom) {
                btnBottom.classList.remove('auto-click-active');
            }
        },

        focusChatContainer() {
            const scrollContainer = this.currentScrollContainer;
            if (scrollContainer) {
                scrollContainer.tabIndex = -1;
                scrollContainer.focus({ preventScroll: true });
            }
        },

// Focuses the main chat input field with visual feedback.
        focusPromptInput() {
            const targetElement = document.querySelector('ms-prompt-box textarea') || document.querySelector('textarea[placeholder="Start typing a prompt"]');
            
            if (!targetElement) {
                console.error("QuickNav: Prompt input textarea not found.");
                return;
            }

            const originalTransition = targetElement.style.transition;
            const originalShadow = targetElement.style.boxShadow;
            
            targetElement.style.transition = 'box-shadow 0.2s ease-out';
            targetElement.style.boxShadow = '0 0 0 2px var(--ms-primary, #8ab4f8)';
            
            setTimeout(() => {
                targetElement.style.boxShadow = originalShadow;
                setTimeout(() => {
                    targetElement.style.transition = originalTransition;
                }, 200);
            }, 400);

            const mouseDownEvent = new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window });
            const mouseUpEvent = new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window });
            const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: window });
            
            targetElement.dispatchEvent(mouseDownEvent);
            targetElement.dispatchEvent(mouseUpEvent);
            targetElement.dispatchEvent(clickEvent);
            targetElement.focus();
        }
    };

// Manages global visual settings: Font Size, Chat Width, and Hover Delay.
    const StyleManager = {
        FONT: {
            DEFAULT: 14,
            MIN: 10,
            MAX: 32,
            STEP: 1,
            current: 14,
            enabled: true,
            storageKey: 'quicknav_font_size',
            enableKey: 'quicknav_font_enabled'
        },
        WIDTH: {
            DEFAULT: 1000,
            MIN: 600,
            MAX: 8000,
            STEP: 10,
            current: 1000,
            enabled: false,
            storageKey: 'quicknav_chat_width',
            enableKey: 'quicknav_width_enabled'
        },
        HOVER_MENU: {
            enabled: false,
            storageKey: 'quicknav_hover_menu_enabled',
            enableKey: 'quicknav_hover_menu_enabled'
        },
        HOVER_DELAY: {
            DEFAULT: 250,
            MIN: 0,
            MAX: 5000,
            STEP: 50,
            current: 250,
            enabled: true,
            storageKey: 'quicknav_hover_delay'
        },

        styleElement: null,
        widthResizeObserver: null,
        observedElement: null,
        
        ui: {
            fontIndicator: null,
            fontControls: null,
            fontBtnMinus: null,
            fontBtnPlus: null,
            fontCheckbox: null, 
            widthIndicator: null,
            widthControls: null,
            widthBtnMinus: null,
            widthBtnPlus: null,
            widthCheckbox: null,
            hoverCheckbox: null,
            hoverControls: null,
            hoverIndicator: null,
            hoverBtnMinus: null,
            hoverBtnPlus: null
        },

// Init method with Smart Resize Listener.
        init() {
            this.loadSettings();
            this.injectStaticBaseStyles();
            
            setTimeout(() => {
                this.setupWidthObserver();
                this.applyVariableUpdates(); 
            }, 500);
            
            let resizeTimeout;
            window.addEventListener('resize', () => {
                const dropdown = document.getElementById('quicknav-settings-dropdown');
                if (!dropdown || !dropdown.classList.contains('visible')) return;
                if (!resizeTimeout) {
                    resizeTimeout = setTimeout(() => {
                        resizeTimeout = null;
                        this.updateUIDisplay();
                    }, 150);
                }
            });
        },

        setupWidthObserver() {
            const target = document.querySelector('.chat-session-content') || document.querySelector('ms-chunk-editor');
            
            if (target && target !== this.observedElement) {
                if (this.widthResizeObserver) this.widthResizeObserver.disconnect();
                
                this.observedElement = target;
                
                this.widthResizeObserver = new ResizeObserver((entries) => {
                    if (!this.WIDTH.enabled) {
                        for (const entry of entries) {
                            if (entry.contentBoxSize) {
                                const width = entry.contentRect.width;
                                document.documentElement.style.setProperty('--quicknav-chat-width', `${width}px`);
                            }
                        }
                    }
                });
                
                this.widthResizeObserver.observe(target);
            }
        },

        measureAndSyncWidth() {
            if (this.observedElement) {
                const rect = this.observedElement.getBoundingClientRect();
                document.documentElement.style.setProperty('--quicknav-chat-width', `${rect.width}px`);
            }
        },

// --- ROBUST STORAGE SYSTEM ---
        _read(key, defaultValue) {
            let value;
            try {
                if (typeof GM_getValue === 'function') {
                    value = GM_getValue(key);
                }
            } catch (e) {
                console.warn(`[QuickNav] GM_getValue failed for ${key}, trying localStorage.`);
            }

            if (value === undefined) {
                try {
                    const local = localStorage.getItem(key);
                    if (local !== null) {
                        if (local === 'true') value = true;
                        else if (local === 'false') value = false;
                        else if (!isNaN(Number(local))) value = Number(local);
                        else value = local;
                    }
                } catch (e) {
                    console.error(`[QuickNav] localStorage failed for ${key}:`, e);
                }
            }

            return value !== undefined ? value : defaultValue;
        },

        _write(key, value) {
            try {
                if (typeof GM_setValue === 'function') {
                    GM_setValue(key, value);
                }
            } catch (e) {
                console.warn(`[QuickNav] GM_setValue failed for ${key}, falling back.`);
            }

            try {
                localStorage.setItem(key, String(value));
            } catch (e) {
                console.error(`[QuickNav] localStorage write failed:`, e);
            }
        },

// Loads settings from storage.
        loadSettings() {
            const savedFont = this._read(this.FONT.storageKey, this.FONT.DEFAULT);
            this.FONT.current = parseInt(savedFont, 10) || this.FONT.DEFAULT;
            
            const savedFontEnabled = this._read(this.FONT.enableKey, true);
            this.FONT.enabled = !!savedFontEnabled;

            const savedWidth = this._read(this.WIDTH.storageKey, this.WIDTH.DEFAULT);
            this.WIDTH.current = parseInt(savedWidth, 10) || this.WIDTH.DEFAULT;

            const savedWidthEnabled = this._read(this.WIDTH.enableKey, false);
            this.WIDTH.enabled = !!savedWidthEnabled;

            const savedHover = this._read(this.HOVER_MENU.storageKey, false);
            this.HOVER_MENU.enabled = !!savedHover;

            const savedHoverDelay = this._read(this.HOVER_DELAY.storageKey, this.HOVER_DELAY.DEFAULT);
            this.HOVER_DELAY.current = parseInt(savedHoverDelay, 10);
            if (isNaN(this.HOVER_DELAY.current)) this.HOVER_DELAY.current = this.HOVER_DELAY.DEFAULT;
        },

// Injects static CSS rules utilizing CSS Variables.
        injectStaticBaseStyles() {
            if (document.getElementById('quicknav-font-styles')) return;
            
            this.styleElement = document.createElement('style');
            this.styleElement.id = 'quicknav-font-styles';
            
            this.styleElement.textContent = `
                :root {
                    --quicknav-font-size: ${this.FONT.DEFAULT}px;
                    --quicknav-chat-width: ${this.WIDTH.DEFAULT}px;
                }

                /* Apply font size to chat content and prompt box */
                html.quicknav-font-active .turn-content, 
                html.quicknav-font-active .turn-content p, 
                html.quicknav-font-active .turn-content li, 
                html.quicknav-font-active .turn-content span,
                html.quicknav-font-active .turn-content .cmark-node, 
                html.quicknav-font-active .turn-content pre, 
                html.quicknav-font-active .turn-content code,
                html.quicknav-font-active .turn-content textarea,
                html.quicknav-font-active .prompt-box-container textarea,
                html.quicknav-font-active .prompt-input-wrapper-container textarea,
                html.quicknav-font-active ms-prompt-input-wrapper textarea { 
                    font-size: var(--quicknav-font-size) !important; 
                    line-height: 1.6 !important;
                }

                /* Apply font size to Navigation Menu and Tooltips */
                html.quicknav-font-active .chat-nav-menu-item,
                html.quicknav-font-active #quicknav-custom-tooltip {
                    font-size: var(--quicknav-font-size) !important;
                }

                html.quicknav-width-active .chat-session-content,
                html.quicknav-width-active .prompt-box-container,
                html.quicknav-width-active ms-prompt-box,
                html.quicknav-width-active .prompt-input-wrapper-container {
                    max-width: var(--quicknav-chat-width) !important;
                }
            `;
            document.head.appendChild(this.styleElement);
        },

        applyVariableUpdates() {
            const root = document.documentElement;

            if (this.FONT.enabled) {
                root.style.setProperty('--quicknav-font-size', `${this.FONT.current}px`);
                root.classList.add('quicknav-font-active');
            } else {
                root.classList.remove('quicknav-font-active');
            }

            if (this.WIDTH.enabled) {
                root.style.setProperty('--quicknav-chat-width', `${this.WIDTH.current}px`);
                root.classList.add('quicknav-width-active');
            } else {
                root.classList.remove('quicknav-width-active');
                this.measureAndSyncWidth();
            }

            this.updateUIDisplay();
        },

        applyStyles() {
            this.applyVariableUpdates();
        },

        getSafeWidthMax() {
            const scrollContainer = document.querySelector('ms-autoscroll-container') || document.body;
            return Math.floor(scrollContainer.clientWidth - 24);
        },

        updateUIDisplay() {
            if (this.ui.fontIndicator) {
                this.ui.fontIndicator.textContent = `${this.FONT.current}`;
                this.updateIndicatorStyle(this.ui.fontIndicator, this.FONT);
            }
            if (this.ui.fontCheckbox) {
                this.ui.fontCheckbox.checked = this.FONT.enabled;
            }
            if (this.ui.fontControls) {
                if (this.FONT.enabled) {
                    this.ui.fontControls.classList.remove('disabled');
                    if (this.ui.fontBtnMinus) this.ui.fontBtnMinus.disabled = (this.FONT.current <= this.FONT.MIN);
                    if (this.ui.fontBtnPlus) this.ui.fontBtnPlus.disabled = (this.FONT.current >= this.FONT.MAX);
                    const btnReset = this.ui.fontControls.querySelector('.quicknav-tool-indicator');
                    if (btnReset) btnReset.disabled = false;
                } else {
                    this.ui.fontControls.classList.add('disabled');
                    this.ui.fontControls.querySelectorAll('button').forEach(btn => btn.disabled = true);
                }
            }

            if (this.ui.widthIndicator) {
                this.ui.widthIndicator.textContent = `${this.WIDTH.current}`;
                this.updateIndicatorStyle(this.ui.widthIndicator, this.WIDTH);
            }
            if (this.ui.widthCheckbox) {
                this.ui.widthCheckbox.checked = this.WIDTH.enabled;
            }
            if (this.ui.widthControls) {
                if (this.WIDTH.enabled) {
                    this.ui.widthControls.classList.remove('disabled');
                    const safeMax = this.getSafeWidthMax();
                    if (this.ui.widthBtnMinus) this.ui.widthBtnMinus.disabled = (this.WIDTH.current <= this.WIDTH.MIN);
                    if (this.ui.widthBtnPlus) {
                        this.ui.widthBtnPlus.disabled = (this.WIDTH.current >= this.WIDTH.MAX || this.WIDTH.current >= safeMax);
                    }
                    const btnReset = this.ui.widthControls.querySelector('.quicknav-tool-indicator');
                    if (btnReset) btnReset.disabled = false;
                } else {
                    this.ui.widthControls.classList.add('disabled');
                    this.ui.widthControls.querySelectorAll('button').forEach(btn => btn.disabled = true);
                }
            }

            if (this.ui.hoverCheckbox) {
                this.ui.hoverCheckbox.checked = this.HOVER_MENU.enabled;
            }
            if (this.ui.hoverIndicator) {
                this.ui.hoverIndicator.textContent = `${this.HOVER_DELAY.current}`;
                this.ui.hoverIndicator.title = `Reset delay to ${this.HOVER_DELAY.DEFAULT}ms`;
                
                const proxyConfig = {
                    current: this.HOVER_DELAY.current,
                    DEFAULT: this.HOVER_DELAY.DEFAULT,
                    enabled: this.HOVER_MENU.enabled
                };
                this.updateIndicatorStyle(this.ui.hoverIndicator, proxyConfig);
            }
            if (this.ui.hoverControls) {
                if (this.HOVER_MENU.enabled) {
                    this.ui.hoverControls.classList.remove('disabled');
                    if (this.ui.hoverBtnMinus) this.ui.hoverBtnMinus.disabled = (this.HOVER_DELAY.current <= this.HOVER_DELAY.MIN);
                    if (this.ui.hoverBtnPlus) this.ui.hoverBtnPlus.disabled = (this.HOVER_DELAY.current >= this.HOVER_DELAY.MAX);
                    const btnReset = this.ui.hoverControls.querySelector('.quicknav-tool-indicator');
                    if (btnReset) btnReset.disabled = false;
                } else {
                    this.ui.hoverControls.classList.add('disabled');
                    this.ui.hoverControls.querySelectorAll('button').forEach(btn => btn.disabled = true);
                }
            }
        },

        updateIndicatorStyle(element, config) {
            if (config.current !== config.DEFAULT && config.enabled) {
                element.style.fontWeight = '500';
                element.style.backgroundColor = 'rgba(138, 180, 248, 0.1)';
            } else {
                element.style.fontWeight = '500';
                element.style.backgroundColor = 'transparent';
            }
        },

        toggleSetting(type, state) {
            if (type === 'HOVER_MENU') {
                this.HOVER_MENU.enabled = state;
                this._write(this.HOVER_MENU.enableKey, state);
                this.updateUIDisplay();
                return;
            }

            this[type].enabled = state;
            this._write(this[type].enableKey, state);
            this.applyVariableUpdates();
        },

        changeValue(type, delta) {
            if (type === 'HOVER_DELAY') {
                 if (!this.HOVER_MENU.enabled) return;
                 const config = this.HOVER_DELAY;
                 let newValue = config.current + delta;
                 if (newValue >= config.MIN && newValue <= config.MAX) {
                     config.current = newValue;
                     this._write(config.storageKey, config.current);
                     this.updateUIDisplay();
                 }
                 return;
            }

            const config = this[type];
            if (!config.enabled) return;

            let newValue = config.current + delta;

            if (type === 'WIDTH') {
                const safeVisibleWidth = this.getSafeWidthMax();
                
                if (delta > 0) {
                    if (config.current >= safeVisibleWidth) return; 
                    if (newValue > safeVisibleWidth) newValue = safeVisibleWidth;
                }
                
                if (delta < 0 && config.current > safeVisibleWidth) {
                    newValue = safeVisibleWidth - config.STEP; 
                }
            }

            if (newValue >= config.MIN && newValue <= config.MAX) {
                const action = () => {
                    config.current = newValue;
                    this._write(config.storageKey, config.current);
                    this.applyVariableUpdates();
                };

                if (type === 'FONT') {
                    this.preserveScrollPosition(action);
                } else {
                    action();
                }
            }
        },

        resetValue(type) {
            if (type === 'HOVER_DELAY') {
                if (!this.HOVER_MENU.enabled) return;
                this.HOVER_DELAY.current = this.HOVER_DELAY.DEFAULT;
                this._write(this.HOVER_DELAY.storageKey, this.HOVER_DELAY.DEFAULT);
                this.updateUIDisplay();
                return;
            }

            const config = this[type];
            if (!config.enabled) return;
            
            const action = () => {
                config.current = config.DEFAULT;
                this._write(config.storageKey, config.current);
                this.applyVariableUpdates();
            };

            if (type === 'FONT') {
                this.preserveScrollPosition(action);
            } else {
                action();
            }
        },

        preserveScrollPosition(actionCallback) {
            const scrollContainer = document.querySelector('ms-autoscroll-container');
            if (!scrollContainer) {
                actionCallback();
                return;
            }

            const originalOverflowAnchor = scrollContainer.style.overflowAnchor;
            scrollContainer.style.overflowAnchor = 'none';
            const containerRect = scrollContainer.getBoundingClientRect();
            const readingLine = containerRect.top + (containerRect.height * 0.5); 
            
            const turns = document.querySelectorAll('ms-chat-turn');
            let anchor = null;
            let closestDist = Infinity;

            for (const turn of turns) {
                const rect = turn.getBoundingClientRect();
                
                if (rect.top > containerRect.bottom + 500) break;
                if (rect.bottom < containerRect.top - 500) continue;

                if (rect.top <= readingLine && rect.bottom > readingLine) {
                    anchor = turn;
                    break;
                }

                const distTop = Math.abs(rect.top - readingLine);
                const distBottom = Math.abs(rect.bottom - readingLine);
                const distance = Math.min(distTop, distBottom);
                
                if (distance < closestDist) {
                    closestDist = distance;
                    anchor = turn;
                }
            }

            if (!anchor) {
                actionCallback();
                scrollContainer.style.overflowAnchor = originalOverflowAnchor;
                return;
            }

            const oldRect = anchor.getBoundingClientRect();
            const offsetInElement = readingLine - oldRect.top;
            const ratio = oldRect.height > 0 ? offsetInElement / oldRect.height : 0;

            actionCallback();

            const _ = scrollContainer.scrollHeight; 
            
            const newRect = anchor.getBoundingClientRect();
            const newOffsetInElement = newRect.height * ratio;
            const desiredTop = readingLine - newOffsetInElement;
            
            const diff = newRect.top - desiredTop;

            if (Math.abs(diff) > 1) {
                scrollContainer.scrollTop += diff;
            }

            scrollContainer.style.overflowAnchor = originalOverflowAnchor;
        },

        setupAutoRepeat(button, action) {
            let timeout, interval;
            const REPEAT_DELAY = 400; 
            const REPEAT_RATE = 50;   

            const start = (e) => {
                if (e.button !== 0) return;
                e.preventDefault();
                e.stopPropagation();

                if (button.disabled) return;
                
                action();

                timeout = setTimeout(() => {
                    interval = setInterval(() => {
                        if (button.disabled) {
                            stop();
                        } else {
                            action();
                        }
                    }, REPEAT_RATE);
                }, REPEAT_DELAY);
            };

            const stop = () => {
                clearTimeout(timeout);
                clearInterval(interval);
            };

            button.addEventListener('mousedown', start);
            button.addEventListener('mouseup', stop);
            button.addEventListener('mouseleave', stop);
            button.addEventListener('click', (e) => e.stopPropagation());
        },

        createSvgIcon(pathData) {
            const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svg.setAttribute("viewBox", "0 0 24 24");
            svg.setAttribute("width", "18");
            svg.setAttribute("height", "18");
            svg.setAttribute("fill", "currentColor");
            const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
            path.setAttribute("d", pathData);
            svg.appendChild(path);
            return svg;
        },

        createRow(type, iconPath, minusPath, plusPath, titleGroup, titleMinus, titlePlus, titleReset) {
            const rowWrapper = document.createElement('div');
            rowWrapper.className = 'quicknav-control-row';

            const leftGroup = document.createElement('div');
            leftGroup.className = 'quicknav-row-label';
            leftGroup.title = titleGroup; 

            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.className = 'quicknav-checkbox';
            checkbox.checked = this[type].enabled;
            checkbox.addEventListener('click', (e) => e.stopPropagation());
            checkbox.addEventListener('change', (e) => this.toggleSetting(type, e.target.checked));
            
            if (type === 'FONT') this.ui.fontCheckbox = checkbox;
            if (type === 'WIDTH') this.ui.widthCheckbox = checkbox;

            const labelIcon = this.createSvgIcon(iconPath);
            labelIcon.classList.add('quicknav-icon-label');
            
            leftGroup.append(checkbox, labelIcon);

            const container = document.createElement('div');
            container.className = 'quicknav-toolbar-group';
            if (type === 'FONT') this.ui.fontControls = container;
            if (type === 'WIDTH') this.ui.widthControls = container;

            const btnMinus = document.createElement('button');
            btnMinus.className = 'quicknav-tool-btn';
            btnMinus.title = titleMinus;
            btnMinus.appendChild(this.createSvgIcon(minusPath));
            this.setupAutoRepeat(btnMinus, () => this.changeValue(type, -this[type].STEP));
            
            if (type === 'FONT') this.ui.fontBtnMinus = btnMinus;
            if (type === 'WIDTH') this.ui.widthBtnMinus = btnMinus;

            const btnReset = document.createElement('button');
            btnReset.className = 'quicknav-tool-btn quicknav-tool-indicator';
            btnReset.title = titleReset;
            btnReset.textContent = `${this[type].current}`;
            btnReset.addEventListener('click', (e) => { e.stopPropagation(); this.resetValue(type); });
            
            if (type === 'FONT') this.ui.fontIndicator = btnReset;
            if (type === 'WIDTH') this.ui.widthIndicator = btnReset;

            const btnPlus = document.createElement('button');
            btnPlus.className = 'quicknav-tool-btn';
            btnPlus.title = titlePlus;
            btnPlus.appendChild(this.createSvgIcon(plusPath));
            this.setupAutoRepeat(btnPlus, () => this.changeValue(type, this[type].STEP));

            if (type === 'FONT') this.ui.fontBtnPlus = btnPlus;
            if (type === 'WIDTH') this.ui.widthBtnPlus = btnPlus;

            container.append(btnMinus, btnReset, btnPlus);
            
            rowWrapper.append(leftGroup, container);
            return rowWrapper;
        },

// Generates the settings dropdown UI with Font, Width, and Hover options.
        createControls() {
            const container = document.createElement('div');
            container.style.display = 'flex';
            container.style.flexDirection = 'column';
            container.style.gap = '8px';
            
            const fontIcon = 'M5 4v3h5.5v12h3V7H19V4z'; 
            const fontMinus = 'M19 13H5v-2h14v2z';
            const fontPlus = 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z';
            const fontRow = this.createRow('FONT', fontIcon, fontMinus, fontPlus, 
                'Enable custom font size', 'Decrease font size (Alt + -)', 'Increase font size (Alt + +)', 'Reset font size (Alt + 0)');
            
            const widthIconSimple = 'M21 5H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H3V7h18v10z'; 
            const widthMinus = 'M19 13H5v-2h14v2z';
            const widthPlus = 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z';
            const widthRow = this.createRow('WIDTH', widthIconSimple, widthMinus, widthPlus, 
                'Enable custom chat width', 'Decrease chat width (Shift + Alt + -)', 'Increase chat width (Shift + Alt + +)', 'Reset chat width (Shift + Alt + 0)');
            
            const hoverRow = document.createElement('div');
            hoverRow.className = 'quicknav-control-row';
            
            const hoverLeft = document.createElement('div');
            hoverLeft.className = 'quicknav-row-label';
            hoverLeft.title = 'Open navigation menu on hover';
            
            const hoverCheckbox = document.createElement('input');
            hoverCheckbox.type = 'checkbox';
            hoverCheckbox.className = 'quicknav-checkbox';
            hoverCheckbox.checked = this.HOVER_MENU.enabled;
            hoverCheckbox.addEventListener('click', (e) => e.stopPropagation());
            hoverCheckbox.addEventListener('change', (e) => this.toggleSetting('HOVER_MENU', e.target.checked));
            this.ui.hoverCheckbox = hoverCheckbox;
            
            const hoverIconPath = 'M9 11.24V7.5C9 6.12 10.12 5 11.5 5S14 6.12 14 7.5v3.74c1.21-.81 2-2.18 2-3.74C16 5.01 13.99 3 11.5 3S7 5.01 7 7.5c0 1.56.79 2.93 2 3.74z m9.84 4.63l-4.54-2.26c-.17-.07-.35-.11-.54-.11H13v-6c0-.83-.67-1.5-1.5-1.5S10 6.67 10 7.5v10.74l-3.43-.72c-.08-.01-.15-.03-.24-.03-.31 0-.59.13-.79.33l-.79.8 4.94 4.94c.27.27.65.44 1.06.44h6.79c.75 0 1.33-.55 1.44-1.28l.75-5.27c.01-.07.02-.14.02-.2 0-.62-.38-1.16-.91-1.38z';
            const hoverIcon = this.createSvgIcon(hoverIconPath);
            hoverIcon.classList.add('quicknav-icon-label');
            
            hoverLeft.append(hoverCheckbox, hoverIcon);

            const hoverControls = document.createElement('div');
            hoverControls.className = 'quicknav-toolbar-group';
            this.ui.hoverControls = hoverControls;

            const delayMinus = 'M19 13H5v-2h14v2z';
            const delayPlus = 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z';

            const btnMinus = document.createElement('button');
            btnMinus.className = 'quicknav-tool-btn';
            btnMinus.title = 'Decrease delay';
            btnMinus.appendChild(this.createSvgIcon(delayMinus));
            this.setupAutoRepeat(btnMinus, () => this.changeValue('HOVER_DELAY', -this.HOVER_DELAY.STEP));
            this.ui.hoverBtnMinus = btnMinus;

            const btnReset = document.createElement('button');
            btnReset.className = 'quicknav-tool-btn quicknav-tool-indicator';
            btnReset.title = `Reset delay to ${this.HOVER_DELAY.DEFAULT}ms`;
            btnReset.textContent = `${this.HOVER_DELAY.current}`;
            btnReset.addEventListener('click', (e) => { e.stopPropagation(); this.resetValue('HOVER_DELAY'); });
            this.ui.hoverIndicator = btnReset;

            const btnPlus = document.createElement('button');
            btnPlus.className = 'quicknav-tool-btn';
            btnPlus.title = 'Increase delay';
            btnPlus.appendChild(this.createSvgIcon(delayPlus));
            this.setupAutoRepeat(btnPlus, () => this.changeValue('HOVER_DELAY', this.HOVER_DELAY.STEP));
            this.ui.hoverBtnPlus = btnPlus;

            hoverControls.append(btnMinus, btnReset, btnPlus);
            hoverRow.append(hoverLeft, hoverControls);
            
            container.append(fontRow, widthRow, hoverRow);
            
            this.updateUIDisplay();
            return container;
        }
    };

// --- MODULE: UI Manager ---
    const UIManager = {
        customTooltip: null,
        tooltipTimeout: null,
        badgeFadeTimeout: null,
        lastScrollTime: 0,
        lastScrollTop: 0,
        isHoveringOnNav: false,
        isThrottled: false,
        footerElement: null,
        toolbarElement: null,
        navContainerElement: null,
        listenedTurnElement: null,
        _handleTurnMouseMove: null,
        _handleTurnMouseLeave: null,
        injectionIntervals: [],

// Initializes the UI Manager, loads styles, and prepares global elements.
        create(targetNode) {
            StyleManager.init();
            this.injectStyles();
            this.createGlobalElements();
            this.createAndInjectUI();
            this.cacheStaticElements();
            this._handleTurnMouseMove = this._handleTurnMouseMove.bind(this);
            this._handleTurnMouseLeave = this._handleTurnMouseLeave.bind(this);
            document.addEventListener('click', this.closeSettingsMenu.bind(this));
            window.addEventListener('resize', this.closeSettingsMenu.bind(this)); 
        },

// Cleans up all injected elements and listeners.
        destroy() {
            this.injectionIntervals.forEach(clearInterval);
            this.injectionIntervals = [];

            const ui = document.getElementById('chat-nav-container');
            if (ui) ui.remove();
            const settingsWrapper = document.querySelector('.quicknav-settings-wrapper');
            if (settingsWrapper) settingsWrapper.remove();
            const dropdown = document.getElementById('quicknav-settings-dropdown');
            if (dropdown) dropdown.remove();
            const menu = document.getElementById('chat-nav-menu-container');
            if (menu) menu.remove();
            const badge = document.getElementById('quicknav-badge-floater');
            if (badge) badge.remove();
            const tooltip = document.getElementById('quicknav-custom-tooltip');
            if (tooltip) tooltip.remove();
            
            this.customTooltip = null;
            this.footerElement = null;
            this.toolbarElement = null;
            this.navContainerElement = null;
            
            if (this.listenedTurnElement) {
                this.listenedTurnElement.removeEventListener('mousemove', this._handleTurnMouseMove);
                this.listenedTurnElement.removeEventListener('mouseleave', this._handleTurnMouseLeave);
                this.listenedTurnElement = null;
            }
            document.removeEventListener('click', this.closeSettingsMenu.bind(this));
            window.removeEventListener('resize', this.closeSettingsMenu.bind(this));
        },

// Caches static references to UI boundaries for the badge positioning.
        cacheStaticElements() {
            this.footerElement = document.querySelector('ms-chunk-editor footer, section.chunk-editor-main > footer');
            this.toolbarElement = document.querySelector('ms-toolbar');
        },

        showBadge() {
            const floater = document.getElementById('quicknav-badge-floater');
            if (!floater) return;
            this.cancelHideBadge();
            floater.style.opacity = '1';
        },

        hideBadge(delay = 1000, force = false) {
            const floater = document.getElementById('quicknav-badge-floater');
            if (!floater || (this.isHoveringOnNav && !force)) return;

            this.cancelHideBadge();

            if (force) {
                floater.classList.add('quicknav-badge-notransition');
                floater.style.opacity = '0';
                requestAnimationFrame(() => {
                    floater.classList.remove('quicknav-badge-notransition');
                });
            } else {
                this.badgeFadeTimeout = setTimeout(() => {
                    floater.style.opacity = '0';
                }, delay);
            }
        },

        cancelHideBadge() {
            clearTimeout(this.badgeFadeTimeout);
        },

        setupMessageObserver() {
            const scrollContainer = document.querySelector('ms-autoscroll-container');
            const messages = document.querySelectorAll('.message-turn');
            if (!scrollContainer || !messages.length) return;

            const observerOptions = { root: scrollContainer, rootMargin: '0px', threshold: 0.1 };
            const observer = new IntersectionObserver(this.handleMessageVisibilityChange.bind(this), observerOptions);
            messages.forEach(msg => observer.observe(msg));
        },

        handleMessageVisibilityChange(entries) {
            const visibleEntries = entries.filter(entry => entry.isIntersecting);
            if (visibleEntries.length === 0) return;
            const bottomMostEntry = visibleEntries.reduce((prev, current) => {
                return prev.boundingClientRect.top > current.boundingClientRect.top ? prev : current;
            });
            if (bottomMostEntry && bottomMostEntry.target !== this.currentVisibleMessage) {
                this.currentVisibleMessage = bottomMostEntry.target;
                this.showBadge();
                this.updateScrollPercentage();
                this.hideBadge();
            }
        },

        handlePageScroll() {
            if (this.isThrottled) return;
            this.isThrottled = true;
            setTimeout(() => { this.isThrottled = false; }, 200);

            const SCROLL_SPEED_THRESHOLD = 500;
            const scrollContainer = document.querySelector('ms-autoscroll-container');
            if (!scrollContainer) return;

            const currentTime = performance.now();
            const currentScrollTop = scrollContainer.scrollTop;
            const deltaTime = currentTime - this.lastScrollTime;

            if (deltaTime > 0) {
                const deltaScroll = currentScrollTop - this.lastScrollTop;
                const scrollSpeed = Math.abs(deltaScroll / deltaTime) * 1000;
                if (scrollSpeed > SCROLL_SPEED_THRESHOLD) {
                    this.showBadge();
                    this.updateScrollPercentage();
                    this.hideBadge(1000);
                }
            }
            this.lastScrollTop = currentScrollTop;
            this.lastScrollTime = currentTime;
        },

        createGlobalElements() {
            if (!document.getElementById('quicknav-badge-floater')) {
                const badgeFloater = document.createElement('div');
                badgeFloater.id = 'quicknav-badge-floater';
                const badgeIndex = document.createElement('div');
                badgeIndex.id = 'quicknav-badge-index';
                const badgePercentage = document.createElement('div');
                badgePercentage.id = 'quicknav-badge-percentage';
                badgeFloater.append(badgeIndex, badgePercentage);
                document.body.appendChild(badgeFloater);
            }
            if (!document.getElementById('quicknav-custom-tooltip')) {
                this.customTooltip = document.createElement('div');
                this.customTooltip.id = 'quicknav-custom-tooltip';
                document.body.appendChild(this.customTooltip);
            }
        },

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

// Injects CSS styles for QuickNav UI, including Font, Layout, and slower Visual Effects.
        injectStyles() {
            if (document.getElementById('chat-nav-styles')) return;
            const styleSheet = document.createElement("style");
            styleSheet.id = 'chat-nav-styles';
            styleSheet.textContent = `
                .chat-turn-container {}

                @keyframes google-text-flow { to { background-position: 200% center; } }
                @keyframes donate-blue-flow { to { background-position: 200% center; } }
                @keyframes load-all-flow { to { background-position: 200% center; } }
                
                /* NEW: Compact High-Intensity Blue Plasma Animation */
                @keyframes quicknav-plasma-blue { 
                    0% { 
                        box-shadow: 0 0 0 0 rgba(66, 133, 244, 0.0); 
                        border-color: #5f6368; 
                        color: #8ab4f8;
                        background-color: transparent;
                    } 
                    50% { 
                        /* Tighter, more concentrated glow */
                        box-shadow: 0 0 10px 2px rgba(66, 133, 244, 0.85), inset 0 0 6px rgba(138, 180, 248, 0.6); 
                        border-color: #aecbfa;
                        color: #ffffff;
                        background-color: rgba(66, 133, 244, 0.3);
                    }
                    100% { 
                        box-shadow: 0 0 0 0 rgba(66, 133, 244, 0.0); 
                        border-color: #5f6368; 
                        color: #8ab4f8; 
                        background-color: transparent;
                    } 
                }

                @keyframes quicknav-loading-flow { to { background-position: -200% center; } }
                .google-text-animated, .google-text-flash { background: linear-gradient(90deg, #8ab4f8, #e67c73, #f7cb73, #57bb8a, #8ab4f8); background-size: 200% auto; -webkit-background-clip: text; background-clip: text; color: transparent !important; }
                .google-text-animated { animation: google-text-flow 10s linear infinite; }
                .google-text-flash { animation: google-text-flow 1.5s ease-in-out 1; }
                .donate-button-animated { background: linear-gradient(90deg, #a8c7fa, #8ab4f8, #669df6, #8ab4f8, #a8c7fa); background-size: 200% auto; -webkit-background-clip: text; background-clip: text; color: transparent !important; animation: donate-blue-flow 8s ease-in-out infinite; }
                ms-autoscroll-container:focus { outline: none; }
                #chat-nav-container { display: flex; justify-content: center; align-items: center; gap: 12px; margin: 2px auto; width: 100%; box-sizing: border-box; position: relative; z-index: 2147483647; }
                .counter-wrapper { position: relative; pointer-events: none; z-index: 9999; }
                
                /* UPDATED: Added hardware acceleration props with vendor prefixes for max compatibility */
                .chat-nav-button, #chat-nav-counter { 
                    background-color: transparent; 
                    border: 1px solid var(--ms-on-surface-variant, #888888); 
                    transition: transform 0.1s ease-out, background-color 0.15s ease-in-out, border-color 0.15s ease, box-shadow 0.2s ease; 
                    pointer-events: auto; 
                    user-select: none; 
                    cursor: pointer;
                    
                    /* Smooth rendering tricks with max compatibility */
                    -webkit-transform: translateZ(0);
                    transform: translateZ(0);
                    -webkit-font-smoothing: antialiased;
                    -webkit-backface-visibility: hidden;
                    backface-visibility: hidden;
                    box-shadow: 0 0 1px rgba(0,0,0,0); 
                }
                
                .chat-nav-button { color: var(--ms-on-surface-variant, #888888); flex-shrink: 0; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 50%; }
                #nav-up, #nav-down { color: #8ab4f8; border-color: #669df6; }
                #nav-top, #nav-bottom, #chat-nav-counter { border-color: #5f6368; }
                #chat-nav-counter { font-family: 'Google Sans', sans-serif; font-size: 14px; padding: 4px 8px; border-radius: 8px; display: inline-flex; align-items: baseline; color: var(--ms-on-surface-variant, #888888); }
                .chat-nav-button:hover, .chat-nav-button:focus { background-color: var(--ms-surface-3, #F1F3F4); outline: none; }
                #nav-top:hover, #nav-bottom:hover, #nav-top:focus, #nav-bottom:focus { background-color: rgba(136, 136, 136, 0.15); }
                #nav-up:hover, #nav-down:hover, #nav-up:focus, #nav-down:focus, #chat-nav-counter:hover, #chat-nav-counter:focus { background-color: rgba(138, 180, 248, 0.15); outline: none; }
                .chat-nav-button:active { -webkit-transform: scale(0.95) translateZ(0); transform: scale(0.95) translateZ(0); }
                
                /* UPDATED: Slower animation (1.8s) */
                #nav-bottom.auto-click-active { animation: quicknav-plasma-blue 2.4s ease-in-out infinite; }
                
                #chat-nav-current-num.chat-nav-current-grey { color: var(--ms-on-surface-variant, #888888); }
                #chat-nav-current-num.chat-nav-current-blue { color: #8ab4f8; font-weight: 500; }
                #chat-nav-total-num { color: #8ab4f8; font-weight: 500; }
                .prompt-turn-highlight { box-shadow: inset 0 0 0 1px var(--ms-on-surface-variant, #9aa0a6) !important; }
                .response-turn-highlight { box-shadow: inset 0 0 0 1px var(--ms-primary, #8ab4f8) !important; }
                .quicknav-title { flex: 2; text-align: center; font-family: 'Google Sans', 'Inter Tight', sans-serif; font-size: 14px; user-select: text; font-weight: 600; }
                
                /* --- SETTINGS DROPDOWN --- */
                .quicknav-settings-wrapper { 
                    margin-left: auto; 
                    margin-right: 12px; 
                    display: flex;
                    align-items: center;
                }
                .quicknav-dropdown-trigger {
                    border: 1px solid transparent; 
                    background: transparent; 
                    color: #8ab4f8; 
                    height: 28px; 
                    min-width: 28px; 
                    display: flex; 
                    align-items: center; 
                    justify-content: center; 
                    cursor: pointer; 
                    border-radius: 4px; 
                    transition: all 0.15s ease-in-out;
                    padding: 0;
                }
                .quicknav-dropdown-trigger:hover, .quicknav-dropdown-trigger.active { 
                    background-color: rgba(138, 180, 248, 0.1); 
                    border-color: rgba(138, 180, 248, 0.5);
                }
                
                .quicknav-dropdown-menu {
                    position: fixed;
                    background-color: #ffffff;
                    border: 1px solid #dadce0;
                    border-radius: 8px;
                    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
                    padding: 8px;
                    z-index: 2147483648; 
                    min-width: 160px;
                    display: none;
                    flex-direction: column;
                    gap: 8px;
                }
                .quicknav-dropdown-menu.visible { display: flex; }
                
                /* Control Row Styling */
                .quicknav-control-row { display: flex; align-items: center; gap: 8px; padding: 0 4px; justify-content: space-between; }
                .quicknav-checkbox { cursor: pointer; width: 16px; height: 16px; accent-color: #8ab4f8; margin: 0; }
                
                .quicknav-toolbar-group { display: flex; align-items: center; gap: 4px; justify-content: center; transition: opacity 0.2s ease, filter 0.2s ease; }
                .quicknav-toolbar-group.disabled { opacity: 0.4; pointer-events: none; filter: grayscale(100%); }

                .quicknav-tool-btn { 
                    border: 1px solid transparent; 
                    background: transparent; 
                    color: #8ab4f8; 
                    height: 28px; 
                    min-width: 28px; 
                    display: flex; 
                    align-items: center; 
                    justify-content: center; 
                    cursor: pointer; 
                    border-radius: 4px; 
                    transition: all 0.15s ease-in-out;
                    padding: 0 4px;
                }
                .quicknav-tool-indicator {
                    font-family: 'Google Sans', sans-serif;
                    font-size: 13px;
                    font-weight: 500;
                    min-width: 40px;
                    text-align: center;
                }
                .quicknav-tool-btn:hover { 
                    background-color: rgba(138, 180, 248, 0.1); 
                    border-color: rgba(138, 180, 248, 0.5); 
                }
                .quicknav-tool-btn:active { background-color: rgba(138, 180, 248, 0.25); }

                /* Disabled state styling for buttons */
                .quicknav-tool-btn:disabled {
                    color: var(--ms-on-surface-variant, #9aa0a6);
                    opacity: 0.5;
                    cursor: default;
                    background-color: transparent;
                    border-color: transparent;
                }
                
                .quicknav-row-label {
                    display: flex;
                    align-items: center;
                    gap: 6px;
                }
                .quicknav-icon-label {
                    width: 18px;
                    height: 18px;
                    color: #5f6368;
                }

                body.dark-theme .quicknav-dropdown-menu {
                    background-color: #202124;
                    border-color: #5f6368;
                    box-shadow: 0 4px 6px rgba(0,0,0,0.3);
                }
                body.dark-theme .quicknav-icon-label { color: #9aa0a6; }

                /* --- MENU & TOOLTIP --- */
                #chat-nav-menu-container { background-color: #f1f3f4; border: 2px solid #1a73e8; }
                #chat-nav-menu { background-color: #f1f3f4; }
                .chat-nav-menu-item { background-color: #ffffff; color: #202124; }
                .chat-nav-menu-item:hover { background-color: #e8eaed; }
                .chat-nav-menu-item.menu-item-focused { background-color: #dfe1e5; }
                .chat-nav-menu-item.loading-in-progress, .chat-nav-menu-item.loading-in-progress:hover, .chat-nav-menu-item.loading-in-progress.menu-item-focused { background: linear-gradient(100deg, #f1f3f4 20%, #d2e3fc 40%, #d2e3fc 60%, #f1f3f4 80%); background-size: 200% 100%; animation: quicknav-loading-flow 1.8s linear infinite; }
                .chat-nav-menu-header { background-color: #f1f3f4; border-bottom: 1px solid #1a73e8; }
                .header-button { font-family: 'Google Sans', sans-serif; text-decoration: none; font-size: 12px; padding: 4px 10px; border-radius: 16px; transition: background-color 0.15s ease-in-out, opacity 0.15s ease-in-out, box-shadow 0.15s ease-in-out; border: 1px solid #669df6; cursor: pointer; font-weight: 500; }
                .header-button:disabled { opacity: 0.5; cursor: not-allowed; }
                .header-button:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--ms-surface-1, #ffffff), 0 0 0 4px var(--ms-primary, #8ab4f8); }
                #chat-nav-load-button { background-color: #e8f0fe; color: #1967d2; }
                #chat-nav-load-button:hover:not(:disabled) { background-color: #d2e3fc; }
                #chat-nav-load-button.loading-active { color: #ffffff; background: linear-gradient(90deg, #1967d2, #4285f4, #1967d2); background-size: 200% auto; animation: load-all-flow 2s linear infinite; }
                #chat-nav-menu::-webkit-scrollbar-track { background: #e8eaed; }
                #chat-nav-menu::-webkit-scrollbar-thumb { background-color: #dfe1e5; }
                #chat-nav-menu::-webkit-scrollbar-thumb:hover { background-color: #9aa0a6; }
                #quicknav-custom-tooltip { background-color: #f1f3f4; color: #202124; border: 1px solid #dadce0; }
                .response-item-bg .menu-item-text { color: #174ea6; }
                body.dark-theme #chat-nav-menu-container { background-color: #191919; border-color: #8ab4f8; }
                body.dark-theme #chat-nav-menu { background-color: #191919; }
                body.dark-theme .chat-nav-menu-item { background-color: #202124; color: #e8eaed; }
                body.dark-theme .chat-nav-menu-item:hover { background-color: #3c4043; }
                body.dark-theme .chat-nav-menu-item.menu-item-focused { background-color: #5f6368; }
                body.dark-theme .chat-nav-menu-item.loading-in-progress, body.dark-theme .chat-nav-menu-item.loading-in-progress:hover, body.dark-theme .chat-nav-menu-item.loading-in-progress.menu-item-focused { background: linear-gradient(100deg, #202124 20%, #3c4043 40%, #3c4043 60%, #202124 80%); background-size: 200% 100%; animation: quicknav-loading-flow 1.8s linear infinite; }
                body.dark-theme .chat-nav-menu-header { background-color: #191919; border-color: #8ab4f8; }
                body.dark-theme .header-button { background-color: #3c4043; color: #e8eaed; border-color: #8ab4f8; }
                body.dark-theme #chat-nav-load-button { background-color: #28354a; color: #a8c7fa; }
                body.dark-theme .header-button:hover:not(:disabled) { background-color: #5f6368; }
                body.dark-theme #chat-nav-load-button:hover:not(:disabled) { background-color: #3c4043; }
                body.dark-theme #chat-nav-load-button.loading-active { color: #202124; background: linear-gradient(90deg, #8ab4f8, #a8c7fa, #8ab4f8); background-size: 200% auto; animation: load-all-flow 2s linear infinite; }
                body.dark-theme #chat-nav-menu::-webkit-scrollbar-track { background: #202124; }
                body.dark-theme #chat-nav-menu::-webkit-scrollbar-thumb { background-color: #5f6368; }
                body.dark-theme #chat-nav-menu::-webkit-scrollbar-thumb:hover { background-color: #9aa0a6; }
                body.dark-theme #quicknav-custom-tooltip { background-color: #2d2d2d; color: #e0e0e0; border: 1px solid #555; }
                body.dark-theme .response-item-bg .menu-item-text { color: var(--ms-primary, #8ab4f8); }
                #quicknav-badge-floater { position: fixed; z-index: 99998; opacity: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; padding: 4px 3px; border-radius: 8px; font-family: 'Google Sans', sans-serif; transition: opacity 0.15s ease-in-out; min-width: 28px; box-sizing: border-box; }
                .quicknav-badge-notransition { transition: none !important; }
                #quicknav-badge-index { font-size: 13px; font-weight: 500; line-height: 1.2; }
                #quicknav-badge-percentage { font-size: 10px; font-weight: 400; line-height: 1.2; border-top: 1px solid rgba(255, 255, 255, 0.3); margin-top: 3px; padding-top: 3px; }
                .prompt-badge-bg { background-color: #5f6368; color: #FFFFFF; }
                .response-badge-bg { background-color: #174ea6; color: #FFFFFF; }
                /* FIXED: Removed max-width: 800px constraint that was blocking resize. Changed to 95vw. */
                #chat-nav-menu-container { display: flex; flex-direction: column; position: fixed; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.25); max-height: 90vh; z-index: 99999; max-width: 95vw; min-width: 300px; box-sizing: border-box; visibility: hidden; opacity: 0; pointer-events: none; transition: opacity 0.15s ease-in-out, visibility 0s linear 0.15s; }
                #chat-nav-menu-container.visible { visibility: visible; opacity: 1; pointer-events: auto; transition: opacity 0.15s ease-in-out, visibility 0s linear 0s; }
                #chat-nav-menu-container:focus { outline: none; }
                #chat-nav-menu { list-style: none; margin: 0; padding: 0 8px 8px 8px; overflow-y: auto; scroll-behavior: smooth; flex-grow: 1; border-radius: 0 0 10px 10px; }
                .chat-nav-menu-item { display: flex; align-items: center; padding: 8px 12px; margin: 2px 0; border-radius: 8px; cursor: pointer; font-size: 13px; font-family: 'Google Sans', sans-serif; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
                .menu-item-number { font-weight: 500; margin-right: 8px; flex-shrink: 0; }
                .prompt-number-color { color: var(--ms-on-surface-variant, #9aa0a6); }
                .response-number-color { color: var(--ms-primary, #8ab4f8); }
                .menu-item-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
                .prompt-item-bg { border-left: 3px solid var(--ms-on-surface-variant, #9aa0a6); margin-left: 32px; }
                .response-item-bg { border-left: 3px solid var(--ms-primary, #8ab4f8); border-bottom: 1px solid var(--ms-primary, #8ab4f8); }
                .chat-nav-menu-header { flex-shrink: 0; z-index: 1; display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; border-radius: 10px 10px 0 0; }
                .header-controls { flex: 1; display: flex; align-items: center; gap: 8px; }
                .header-controls.left { justify-content: flex-start; }
                .header-controls.right { justify-content: flex-end; }
                #chat-nav-menu::-webkit-scrollbar { width: 8px; }
                #chat-nav-loader-status { font-family: 'Google Sans', sans-serif; font-size: 12px; color: var(--ms-on-surface-variant, #9aa0a6); padding: 4px 10px; font-weight: 600; }
                #quicknav-custom-tooltip { position: fixed; z-index: 100000; border-radius: 6px; padding: 6px 10px; font-size: 13px; font-family: 'Google Sans', sans-serif; max-width: 40vw; pointer-events: none; opacity: 0; transition: opacity 0.15s ease-in-out; white-space: normal; }

                /* RESIZERS */
                .quicknav-menu-resizer { position: absolute; top: 0; bottom: 0; width: 20px; cursor: ew-resize; z-index: 2147483647; touch-action: none; background: transparent; transition: background-color 0.15s; }
                .quicknav-menu-resizer:hover { background-color: rgba(138, 180, 248, 0.2); }
                .quicknav-resizer-left { left: -10px; }
                .quicknav-resizer-right { right: -10px; }
                /* GLOBAL RESIZING STATE */
                body.quicknav-resizing { cursor: ew-resize !important; user-select: none !important; }

                /* --- CODE BLOCK NAVIGATION (Google Blue Theme) --- */
                .code-block-nav-container { display: flex; align-items: center; gap: 8px; margin-left: auto; }
                .code-nav-button { background: transparent; border: 1px solid #669df6; color: #8ab4f8; height: 28px; border-radius: 8px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.15s ease, transform 0.1s ease, border-color 0.15s ease, color 0.15s ease; padding: 0 12px; }
                .code-nav-counter { font-family: 'Google Sans', sans-serif; font-size: 12px; font-weight: 500; color: #8ab4f8; user-select: none; }
                .code-nav-button:hover:not(:disabled) { background-color: rgba(138, 180, 248, 0.15); }
                .code-nav-button:active:not(:disabled) { transform: scale(0.95); }
                .code-nav-button:disabled { opacity: 0.5; cursor: not-allowed; color: var(--ms-on-surface-variant, #9aa0a6); border-color: var(--ms-on-surface-variant, #9aa0a6); }
            `;
            document.head.appendChild(styleSheet);
        },

        waitForElement(selector, callback, maxAttempts = 50, intervalMs = 500) {
            let attempts = 0;
            const interval = setInterval(() => {
                const element = document.querySelector(selector);
                if (element) {
                    clearInterval(interval);
                    callback(element);
                    const idx = this.injectionIntervals.indexOf(interval);
                    if (idx > -1) this.injectionIntervals.splice(idx, 1);
                } else {
                    attempts++;
                    if (attempts >= maxAttempts) {
                        clearInterval(interval);
                        console.warn(`[QuickNav] Gave up waiting for ${selector} after ${maxAttempts} attempts.`);
                        const idx = this.injectionIntervals.indexOf(interval);
                        if (idx > -1) this.injectionIntervals.splice(idx, 1);
                    }
                }
            }, intervalMs);
            this.injectionIntervals.push(interval);
        },

// Toggles the dropdown menu, allowing forced state for hover interactions.
        toggleSettingsMenu(e, forceState = null) {
            e.stopPropagation();
            const dropdown = document.getElementById('quicknav-settings-dropdown');
            const trigger = e.currentTarget; 
            
            if (dropdown && trigger) {
                const isVisible = dropdown.classList.contains('visible');
                const shouldOpen = forceState !== null ? forceState : !isVisible;
                
                if (!shouldOpen) {
                    dropdown.classList.remove('visible');
                    trigger.classList.remove('active');
                } else {
                    StyleManager.updateUIDisplay();

                    dropdown.classList.add('visible');
                    trigger.classList.add('active');
                    
                    const rect = trigger.getBoundingClientRect();
                    const menuWidth = dropdown.offsetWidth;
                    const menuHeight = dropdown.offsetHeight;
                    
                    let leftPos = rect.right - menuWidth;
                    
                    if (leftPos < 4) leftPos = 4;

                    dropdown.style.top = `${rect.top - menuHeight - 8}px`;
                    dropdown.style.left = `${leftPos}px`;
                }
            }
        },

// Closes the settings menu if clicked outside.
        closeSettingsMenu(e) {
            const dropdown = document.getElementById('quicknav-settings-dropdown');
            const trigger = document.querySelector('.quicknav-dropdown-trigger');
            
            if (dropdown && dropdown.classList.contains('visible')) {
                if (!dropdown.contains(e.target) && (!trigger || !trigger.contains(e.target))) {
                    dropdown.classList.remove('visible');
                    if (trigger) trigger.classList.remove('active');
                }
            }
        },

// Creates and injects the UI elements into the DOM, adding hover logic for settings.
        createAndInjectUI() {
            const navContainer = document.createElement('div');
            navContainer.id = 'chat-nav-container';
            const pathTop = 'M12 4l-6 6 1.41 1.41L12 6.83l4.59 4.58L18 10z M12 12l-6 6 1.41 1.41L12 14.83l4.59 4.58L18 18z';
            const pathUp = 'M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z';
            const pathDown = 'M12 16l-6-6 1.41-1.41L12 13.17l4.59-4.58L18 10z';
            const pathBottom = 'M12 12l-6-6 1.41-1.41L12 9.17l4.59-4.58L18 6z M12 20l-6-6 1.41-1.41L12 17.17l4.59-4.58L18 14z';
            
            const btnTop = this.createButton('nav-top', 'Go to the first message (Shift + Alt + PgUp)', pathTop);
            const btnUp = this.createButton('nav-up', 'Go to the previous message (Alt + PgUp)', pathUp);
            const counterWrapper = document.createElement('div');
            counterWrapper.className = 'counter-wrapper';
            const counter = document.createElement('span');
            counter.id = 'chat-nav-counter';
            counter.title = 'Open navigation menu (Alt + M)';
            counter.tabIndex = 0;
            counter.setAttribute('role', 'button');
            const currentNumSpan = document.createElement('span');
            currentNumSpan.id = 'chat-nav-current-num';
            counter.appendChild(currentNumSpan);
            const separatorSpan = document.createElement('span');
            separatorSpan.id = 'chat-nav-separator';
            separatorSpan.textContent = ' / ';
            counter.appendChild(separatorSpan);
            const totalNumSpan = document.createElement('span');
            totalNumSpan.id = 'chat-nav-total-num';
            counter.appendChild(totalNumSpan);
            const btnDown = this.createButton('nav-down', 'Go to the next message (Alt + PgDown)', pathDown);
            const btnBottom = this.createButton('nav-bottom', 'Go to the last message (Shift + Alt + PgDown)', pathBottom);
            
            let menuContainer = document.getElementById('chat-nav-menu-container');
            if (!menuContainer) {
                menuContainer = document.createElement('div');
                menuContainer.id = 'chat-nav-menu-container';
                menuContainer.tabIndex = -1;
                menuContainer.setAttribute('role', 'menu');
                
                const resizerLeft = document.createElement('div');
                resizerLeft.className = 'quicknav-menu-resizer quicknav-resizer-left';
                resizerLeft.title = 'Drag to resize';
                
                const resizerRight = document.createElement('div');
                resizerRight.className = 'quicknav-menu-resizer quicknav-resizer-right';
                resizerRight.title = 'Drag to resize';
                
                menuContainer.append(resizerLeft, resizerRight);
                
                this.setupMenuResizer(resizerLeft, -1, menuContainer);
                this.setupMenuResizer(resizerRight, 1, menuContainer);
                
                document.body.appendChild(menuContainer);
            }
            counterWrapper.append(counter);
            
            const settingsWrapper = document.createElement('div');
            settingsWrapper.className = 'quicknav-settings-wrapper';
            settingsWrapper.style.cssText = `
                position: absolute; 
                right: max(10px, calc(((100% - var(--quicknav-chat-width, 1000px)) / 2) + 10px)); 
                top: 50%; 
                transform: translateY(-50%); 
                display: flex; 
                align-items: center; 
                z-index: 10; 
                margin: 0;
            `;

            const triggerBtn = document.createElement('button');
            triggerBtn.className = 'quicknav-dropdown-trigger';
            triggerBtn.title = 'QuickNav Settings';
            const svgDots = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svgDots.setAttribute('height', '24px');
            svgDots.setAttribute('viewBox', '0 0 24 24');
            svgDots.setAttribute('width', '24px');
            svgDots.setAttribute('fill', 'currentColor');
            const pathDots = document.createElementNS("http://www.w3.org/2000/svg", 'path');
            pathDots.setAttribute('d', 'M6 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm12 0c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm-6 0c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z');
            
            svgDots.appendChild(pathDots);
            triggerBtn.appendChild(svgDots);
            triggerBtn.addEventListener('click', this.toggleSettingsMenu.bind(this));

            triggerBtn.addEventListener('mouseenter', (e) => {
                clearTimeout(this.settingsCloseTimeout);
                this.toggleSettingsMenu(e, true);
            });
            
            const closeMenuDelayed = () => {
                this.settingsCloseTimeout = setTimeout(() => {
                    const dropdown = document.getElementById('quicknav-settings-dropdown');
                    const trigger = document.querySelector('.quicknav-dropdown-trigger');
                    if (dropdown) dropdown.classList.remove('visible');
                    if (trigger) trigger.classList.remove('active');
                }, 300);
            };

            triggerBtn.addEventListener('mouseleave', closeMenuDelayed);

            let dropdownMenu = document.getElementById('quicknav-settings-dropdown');
            if (!dropdownMenu) {
                dropdownMenu = document.createElement('div');
                dropdownMenu.id = 'quicknav-settings-dropdown';
                dropdownMenu.className = 'quicknav-dropdown-menu';
                
                const styleControls = StyleManager.createControls();
                dropdownMenu.appendChild(styleControls);
                
                document.body.appendChild(dropdownMenu);
            }

            dropdownMenu.addEventListener('mouseenter', () => clearTimeout(this.settingsCloseTimeout));
            dropdownMenu.addEventListener('mouseleave', closeMenuDelayed);

            settingsWrapper.appendChild(triggerBtn);
            
            navContainer.append(btnTop, btnUp, counterWrapper, btnDown, btnBottom, settingsWrapper);
            this.navContainerElement = navContainer;

            const injectNavBar = (anchor) => {
                if (document.getElementById('chat-nav-container')) return;
                if (anchor && anchor.parentNode) {
                    anchor.parentNode.insertBefore(navContainer, anchor);
                    this.attachNavigationLogic(btnTop, btnUp, btnDown, btnBottom, counter, menuContainer);
                    this.updateCounterDisplay();
                    navContainer.addEventListener('mouseenter', () => {
                        this.isHoveringOnNav = true;
                        this.updateScrollPercentage();
                        this.showBadge();
                    });
                    navContainer.addEventListener('mouseleave', () => {
                        this.isHoveringOnNav = false;
                        this.hideBadge(1000);
                    });
                }
            };

            this.waitForElement('ms-chunk-editor footer, section.chunk-editor-main > footer', injectNavBar);
            
            this.waitForElement('ms-prompt-input-wrapper', (inputWrapper) => {
                if (!document.getElementById('chat-nav-container')) {
                    injectNavBar(inputWrapper);
                }
            });
        },

        createButton(id, title, pathData) {
            const button = document.createElement('button');
            button.id = id;
            button.className = 'chat-nav-button';
            button.title = title;
            button.setAttribute('aria-label', title);
            const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svg.setAttribute('height', '24px');
            svg.setAttribute('viewBox', '0 0 24 24');
            svg.setAttribute('width', '24px');
            svg.setAttribute('fill', 'currentColor');
            const path = document.createElementNS("http://www.w3.org/2000/svg", 'path');
            path.setAttribute('d', pathData);
            svg.appendChild(path);
            button.appendChild(svg);
            return button;
        },

// Attaches event listeners and logic to the navigation UI buttons and menu.
        attachNavigationLogic(btnTop, btnUp, btnDown, btnBottom, counter, menuContainer) {
            const lastIndex = () => ChatController.allTurns.length - 1;

            ChatController.setupHoldableButton(btnTop, () => {
                ChatController.scrollToAbsoluteTop();
            });

            ChatController.setupHoldableButton(btnUp, async () => {
                const last = lastIndex();
                const scrollContainer = document.querySelector('ms-autoscroll-container');

                if (ChatController.currentIndex === last && last > -1 && scrollContainer) {
                    const currentTurn = ChatController.allTurns[last];
                    const isScrolledPastTop = scrollContainer.scrollTop > currentTurn.offsetTop + 10;
                    if (isScrolledPastTop) {
                        await ChatController.navigateToIndex(last, 'center');
                        return;
                    }
                }

                if (ChatController.currentIndex === 0) {
                    ChatController.scrollToAbsoluteTop();
                    return;
                }
                await ChatController.navigateToIndex(ChatController.currentIndex - 1, 'center');
            });

            ChatController.setupHoldableButton(btnDown, async () => {
                const last = lastIndex();
                if (ChatController.currentIndex < last) {
                    await ChatController.navigateToIndex(ChatController.currentIndex + 1, 'center');
                } else {
                    const scrollContainer = document.querySelector('ms-autoscroll-container');
                    if (!scrollContainer) return;
                    if (ChatController.isDownButtonAtEndToggle) {
                        await ChatController.navigateToIndex(last, 'center');
                        ChatController.isDownButtonAtEndToggle = false;
                    } else {
                        UIManager.hideBadge(0, true);
                        ChatController.isScrollingProgrammatically = true;
                        scrollContainer.scrollTo({ top: scrollContainer.scrollHeight, behavior: 'smooth' });
                        setTimeout(() => {
                            ChatController.isScrollingProgrammatically = false;
                            UIManager.showBadge();
                            UIManager.updateScrollPercentage();
                            UIManager.hideBadge(3000);
                            ChatController.focusChatContainer();
                        }, 800);
                        ChatController.isDownButtonAtEndToggle = true;
                    }
                }
            });

            let ignoreNextBottomClick = false;
            const bottomNavAction = async () => {
                UIManager.hideBadge(0, true);
                const last = lastIndex();
                if (ChatController.currentIndex === last) {
                    const scrollContainer = document.querySelector('ms-autoscroll-container');
                    if (scrollContainer) {
                        const isSmooth = !ChatController.isBottomHoldActive;
                        ChatController.isScrollingProgrammatically = true;
                        scrollContainer.scrollTo({ top: scrollContainer.scrollHeight, behavior: isSmooth ? 'smooth' : 'auto' });
                        setTimeout(() => {
                            ChatController.isScrollingProgrammatically = false;
                            UIManager.showBadge();
                            UIManager.updateScrollPercentage();
                            UIManager.hideBadge(3000);
                            ChatController.focusChatContainer();
                        }, isSmooth ? 800 : 50);
                    }
                } else {
                    await ChatController.navigateToIndex(last, 'center');
                }
            };
            btnBottom.addEventListener('mousedown', (e) => {
                if (ChatController.isBottomHoldActive) return;
                ChatController.bottomHoldTimeout = setTimeout(() => {
                    ChatController.isBottomHoldActive = true;
                    btnBottom.classList.add('auto-click-active');
                    ignoreNextBottomClick = true;
                    bottomNavAction();
                    ChatController.bottomHoldInterval = setInterval(bottomNavAction, 150);
                }, 750);
            });
            const stopBottomHoldDetector = () => { clearTimeout(ChatController.bottomHoldTimeout); };
            btnBottom.addEventListener('mouseup', stopBottomHoldDetector);
            btnBottom.addEventListener('mouseleave', stopBottomHoldDetector);
            btnBottom.addEventListener('click', (e) => {
                if (ignoreNextBottomClick) {
                    ignoreNextBottomClick = false;
                    return;
                }
                if (ChatController.isBottomHoldActive) {
                    ChatController.stopBottomHold();
                } else {
                    if (e.target.closest('#nav-bottom')) {
                        bottomNavAction();
                    }
                }
            });

            // --- Toggle Menu Logic (Click + Hover) ---
            counter.addEventListener('click', (e) => { e.stopPropagation(); this.toggleNavMenu(); });
            
            let hoverOpenTimeout = null;

            const handleHoverOpen = () => {
                if (!StyleManager.HOVER_MENU.enabled) return;
                clearTimeout(this.menuCloseTimeout);
                
                if (!menuContainer.classList.contains('visible')) {
                    clearTimeout(hoverOpenTimeout);
                    hoverOpenTimeout = setTimeout(() => {
                        this.toggleNavMenu();
                    }, StyleManager.HOVER_DELAY.current);
                }
            };
            
            const handleHoverClose = () => {
                if (!StyleManager.HOVER_MENU.enabled) return;
                
                clearTimeout(hoverOpenTimeout);

                this.menuCloseTimeout = setTimeout(() => {
                    if (menuContainer.classList.contains('visible')) {
                        this.toggleNavMenu();
                    }
                }, 300);
            };

            counter.addEventListener('mouseenter', handleHoverOpen);
            counter.addEventListener('mouseleave', handleHoverClose);
            
            menuContainer.addEventListener('mouseenter', () => {
                clearTimeout(this.menuCloseTimeout);
                clearTimeout(hoverOpenTimeout);
            });
            menuContainer.addEventListener('mouseleave', handleHoverClose);

            counter.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    this.toggleNavMenu();
                } else if (e.key === 'Tab' && menuContainer.classList.contains('visible')) {
                    e.preventDefault();
                    const menuList = document.getElementById('chat-nav-menu');
                    const donateBtn = document.getElementById('chat-nav-donate-link');
                    if (e.shiftKey) {
                        if (donateBtn) donateBtn.focus();
                    } else {
                        if (menuList) menuList.focus();
                    }
                }
            });

            menuContainer.addEventListener('keydown', (e) => {
                if (e.key === 'Tab') {
                    e.preventDefault();
                    const menuList = document.getElementById('chat-nav-menu');
                    const loadBtn = document.getElementById('chat-nav-load-button');
                    const donateBtn = document.getElementById('chat-nav-donate-link');
                    const activeEl = document.activeElement;

                    if (e.shiftKey) {
                        if (activeEl === menuList) counter.focus();
                        else if (activeEl === loadBtn) menuList.focus();
                        else if (activeEl === donateBtn) loadBtn.focus();
                    } else {
                        if (activeEl === menuList) loadBtn.focus();
                        else if (activeEl === loadBtn) donateBtn.focus();
                        else if (activeEl === donateBtn) counter.focus();
                    }
                    return;
                }

                const items = menuContainer.querySelectorAll('.chat-nav-menu-item');
                let newIndex = ChatController.menuFocusedIndex;
                let shouldUpdateFocus = true;

                switch (e.key) {
                    case 'ArrowDown': e.preventDefault(); if (items.length > 0) newIndex = (ChatController.menuFocusedIndex + 1) % items.length; break;
                    case 'ArrowUp': e.preventDefault(); if (items.length > 0) newIndex = (ChatController.menuFocusedIndex - 1 + items.length) % items.length; break;
                    case 'PageDown': e.preventDefault(); if (items.length > 0) newIndex = Math.min(items.length - 1, ChatController.menuFocusedIndex + ChatController.JUMP_DISTANCE); break;
                    case 'PageUp': e.preventDefault(); if (items.length > 0) newIndex = Math.max(0, ChatController.menuFocusedIndex - ChatController.JUMP_DISTANCE); break;
                    case 'Home': e.preventDefault(); if (items.length > 0) newIndex = 0; break;
                    case 'End': e.preventDefault(); if (items.length > 0) newIndex = items.length - 1; break;
                    case 'Enter':
                        e.preventDefault();
                        const activeEl = document.activeElement;
                        if (activeEl && activeEl.matches('button, a[href]') && menuContainer.contains(activeEl)) {
                            activeEl.click();
                        } else if (ChatController.menuFocusedIndex !== -1 && items[ChatController.menuFocusedIndex]) {
                            items[ChatController.menuFocusedIndex].click();
                        }
                        shouldUpdateFocus = false;
                        break;
                    case 'Escape': e.preventDefault(); this.toggleNavMenu(); shouldUpdateFocus = false; break;
                    default: shouldUpdateFocus = false; break;
                }
                if (shouldUpdateFocus && newIndex !== ChatController.menuFocusedIndex) { this.updateMenuFocus(items, newIndex); }
            });
        },

// Handles mouse movement over the highlighted turn to show/hide the badge.
        _handleTurnMouseMove(e) {
            const hotzoneWidth = 24;
            const rect = this.listenedTurnElement.getBoundingClientRect();
            const cursorX = e.clientX;
            if (cursorX >= rect.left && cursorX <= rect.left + hotzoneWidth ||
                cursorX >= rect.right - hotzoneWidth && cursorX <= rect.right) {
                this.showBadge();
                this.updateScrollPercentage();
            } else {
                this.hideBadge(1000);
            }
        },

        _handleTurnMouseLeave() {
            this.hideBadge(1000);
        },

// Updates the visual highlight, ensuring only one turn is highlighted at a time.
        updateHighlight(oldIndex, newIndex) {
            if (oldIndex > -1 && oldIndex < ChatController.allTurns.length) {
                const oldTurn = ChatController.allTurns[oldIndex];
                const oldTurnContainer = oldTurn.querySelector('.chat-turn-container');
                if (oldTurnContainer) {
                    oldTurnContainer.classList.remove('prompt-turn-highlight', 'response-turn-highlight');
                }
            }

            if (this.listenedTurnElement) {
                this.listenedTurnElement.removeEventListener('mousemove', this._handleTurnMouseMove);
                this.listenedTurnElement.removeEventListener('mouseleave', this._handleTurnMouseLeave);
                this.listenedTurnElement = null;
            }
            const floater = document.getElementById('quicknav-badge-floater');
            if (!floater) return;

            if (newIndex > -1 && newIndex < ChatController.allTurns.length) {
                const newTurn = ChatController.allTurns[newIndex];
                const isPrompt = ChatController.isUserPrompt(newTurn);
                const newContainer = newTurn.querySelector('.chat-turn-container');
                if (newContainer) {
                    newContainer.classList.add(isPrompt ? 'prompt-turn-highlight' : 'response-turn-highlight');
                }
                const badgeIndex = document.getElementById('quicknav-badge-index');
                const badgeClass = isPrompt ? 'prompt-badge-bg' : 'response-badge-bg';
                if (badgeIndex) {
                    badgeIndex.textContent = newIndex + 1;
                }
                floater.className = badgeClass;
                this.listenedTurnElement = newTurn;
                this.listenedTurnElement.addEventListener('mousemove', this._handleTurnMouseMove);
                this.listenedTurnElement.addEventListener('mouseleave', this._handleTurnMouseLeave);
            }
        },

        updateCounterDisplay() {
            let currentNumSpan = document.getElementById('chat-nav-current-num');
            let totalNumSpan = document.getElementById('chat-nav-total-num');
            if (!currentNumSpan || !totalNumSpan) return;
            const current = ChatController.currentIndex > -1 ? ChatController.currentIndex + 1 : '-';
            const total = ChatController.allTurns.length;
            currentNumSpan.textContent = current;
            totalNumSpan.textContent = total;
            currentNumSpan.classList.remove('chat-nav-current-grey', 'chat-nav-current-blue');
            if (ChatController.currentIndex === total - 1 && total > 0) {
                currentNumSpan.classList.add('chat-nav-current-blue');
            } else {
                currentNumSpan.classList.add('chat-nav-current-grey');
            }
        },

// Toggles the visibility and state of the main navigation menu.
        toggleNavMenu() {
            const menuContainer = document.getElementById('chat-nav-menu-container');
            const counter = document.getElementById('chat-nav-counter');
            if (!menuContainer || !counter) return;

            const isVisible = menuContainer.classList.contains('visible');
            if (isVisible) {
                menuContainer.classList.remove('visible');
                const menuList = document.getElementById('chat-nav-menu');
                if (menuList) menuList.tabIndex = -1;
                counter.setAttribute('aria-expanded', 'false');
                document.removeEventListener('click', this.closeNavMenu, true);
                ChatController.stopDynamicMenuLoading();
                ChatController.focusChatContainer();
            } else {
                this.populateNavMenu();
                const newMenuList = document.getElementById('chat-nav-menu');
                if (newMenuList) newMenuList.tabIndex = 0;

                const savedWidth = StyleManager._read('quicknav_menu_custom_width');
                if (savedWidth) {
                    menuContainer.style.width = `${savedWidth}px`;
                } else {
                    const chatContainer = document.querySelector('ms-chunk-editor');
                    if (chatContainer) {
                        const chatWidth = chatContainer.clientWidth;
                        const finalWidth = Math.max(300, Math.min(chatWidth, 800));
                        menuContainer.style.width = `${finalWidth}px`;
                    }
                }

                const counterRect = counter.getBoundingClientRect();
                menuContainer.style.bottom = `${window.innerHeight - counterRect.top + 8}px`;
                menuContainer.style.left = `${counterRect.left + (counterRect.width / 2)}px`;
                menuContainer.style.transform = 'translateX(-50%)';

                const availableSpace = counterRect.top - 18;
                menuContainer.style.maxHeight = `${availableSpace}px`;

                this._proactivelySyncMenuScroll();
                menuContainer.classList.add('visible');
                counter.setAttribute('aria-expanded', 'true');

                const items = newMenuList ? newMenuList.querySelectorAll('.chat-nav-menu-item') : [];
                const initialFocusIndex = ChatController.currentIndex > -1 ? ChatController.currentIndex : 0;
                this.updateMenuFocus(items, initialFocusIndex, false);

                if (newMenuList) {
                    newMenuList.focus();
                } else {
                    menuContainer.focus();
                }

                setTimeout(() => document.addEventListener('click', this.closeNavMenu, true), 0);
            }
        },

// Sets up drag-to-resize logic for the menu handles with improved performance and constraints.
        setupMenuResizer(handle, direction, container) {
            let startX, startWidth, rafId;

            const onMouseMove = (e) => {
                if (rafId) return;

                rafId = requestAnimationFrame(() => {
                    const currentX = e.clientX;
                    const deltaX = (currentX - startX) * direction;
                    
                    let newWidth = startWidth + (deltaX * 2);
                    
                    const maxWidth = window.innerWidth - 32;
                    newWidth = Math.max(300, Math.min(newWidth, maxWidth));
                    
                    container.style.width = `${newWidth}px`;
                    container.style.maxWidth = '100vw'; 
                    
                    rafId = null;
                });
            };

            const onMouseUp = () => {
                if (rafId) cancelAnimationFrame(rafId);
                rafId = null;
                
                document.removeEventListener('mousemove', onMouseMove);
                document.removeEventListener('mouseup', onMouseUp);
                document.body.style.cursor = '';
                document.body.classList.remove('quicknav-resizing');
                
                const currentWidth = parseInt(container.style.width, 10);
                if (currentWidth) {
                    StyleManager._write('quicknav_menu_custom_width', currentWidth);
                }
            };

            handle.addEventListener('mousedown', (e) => {
                if (e.button !== 0) return;
                e.preventDefault();
                e.stopPropagation();
                
                startX = e.clientX;
                startWidth = container.getBoundingClientRect().width;
                
                document.body.style.cursor = 'ew-resize';
                document.body.classList.add('quicknav-resizing');
                
                document.addEventListener('mousemove', onMouseMove);
                document.addEventListener('mouseup', onMouseUp);
            });
        },

// Handles clicks outside the menu to close it.
        closeNavMenu(e) {
            const menuContainer = document.getElementById('chat-nav-menu-container');
            const counter = document.getElementById('chat-nav-counter');
            if (menuContainer && counter && !menuContainer.contains(e.target) && !counter.contains(e.target) && menuContainer.classList.contains('visible')) {
                this.toggleNavMenu();
            }
        },

// Proactively sets the scroll position of the (possibly hidden) nav menu.
        _proactivelySyncMenuScroll() {
            const menuList = document.getElementById('chat-nav-menu');
            if (!menuList) return;

            const items = menuList.querySelectorAll('.chat-nav-menu-item');
            const targetIndex = ChatController.currentIndex;

            if (targetIndex < 0 || targetIndex >= items.length) return;

            const focusedItem = items[targetIndex];
            if (focusedItem) {
                menuList.style.scrollBehavior = 'auto';
                menuList.scrollTop = focusedItem.offsetTop - (menuList.clientHeight / 2) + (focusedItem.clientHeight / 2);
                menuList.style.scrollBehavior = '';
            }
        },

// Updates the text content of a single menu item if the menu is visible.
        updateMenuItemContent(index) {
            const menuContainer = document.getElementById('chat-nav-menu-container');
            if (!menuContainer || !menuContainer.classList.contains('visible')) return;

            const menuList = document.getElementById('chat-nav-menu');
            if (!menuList) return;

            const menuItem = menuList.children[index];
            const turn = ChatController.allTurns[index];
            if (!menuItem || !turn || !turn.cachedContent) return;

            const textSpan = menuItem.querySelector('.menu-item-text');
            if (textSpan) {
                const { display, full } = turn.cachedContent;
                const truncatedText = (display.length > 200) ? display.substring(0, 197) + '...' : display;
                if (textSpan.textContent !== truncatedText) {
                    textSpan.textContent = truncatedText;
                }
                menuItem.dataset.tooltip = full.replace(/\s+/g, ' ');
            }
        },

        updateMenuFocus(items, newIndex, shouldScroll = true) {
            if (!items || items.length === 0 || newIndex < 0 || newIndex >= items.length) return;
            if (ChatController.menuFocusedIndex > -1 && ChatController.menuFocusedIndex < items.length) {
                items[ChatController.menuFocusedIndex].classList.remove('menu-item-focused');
            }
            items[newIndex].classList.add('menu-item-focused');
            if (shouldScroll) {
                const menuList = document.getElementById('chat-nav-menu');
                const focusedItem = items[newIndex];
                if (menuList && focusedItem) {
                    const itemRect = focusedItem.getBoundingClientRect();
                    const menuRect = menuList.getBoundingClientRect();
                    if (itemRect.bottom > menuRect.bottom) {
                        menuList.scrollTop += itemRect.bottom - menuRect.bottom;
                    } else if (itemRect.top < menuRect.top) {
                        menuList.scrollTop -= menuRect.top - itemRect.top;
                    }
                }
            }
            ChatController.menuFocusedIndex = newIndex;
        },

// Extracts text using a hybrid approach: DOM is priority, scrollbar is fallback.
        getTextFromTurn(turn, fromDOMOnly = false) {
            const contentContainer = turn.querySelector('.turn-content');
            if (contentContainer) {
                const clonedContainer = contentContainer.cloneNode(true);
                clonedContainer.querySelectorAll('ms-code-block').forEach(codeBlockElement => {
                    const codeContent = codeBlockElement.querySelector('pre code');
                    if (codeContent) {
                        const pre = document.createElement('pre');
                        pre.textContent = ` [Code Block] `;
                        codeBlockElement.parentNode.replaceChild(pre, codeBlockElement);
                    } else { codeBlockElement.remove(); }
                });
                clonedContainer.querySelectorAll('.author-label, .turn-separator, ms-thought-chunk').forEach(el => el.remove());
                const text = clonedContainer.textContent?.trim().replace(/\s+/g, ' ');

                if (text) {
                    return { display: text, full: text, source: 'dom' };
                }
            }

            if (!fromDOMOnly) {
                const turnId = turn.id;
                if (turnId) {
                    const scrollbarButton = document.getElementById(`scrollbar-item-${turnId.replace('turn-', '')}`);
                    if (scrollbarButton && scrollbarButton.getAttribute('aria-label')) {
                        const labelText = scrollbarButton.getAttribute('aria-label');
                        return { display: labelText, full: labelText, source: 'scrollbar' };
                    }
                }
            }

            return { display: '...', full: 'Could not extract content.', source: 'fallback' };
        },

// Populates the navigation menu, performing an initial cache fill on first run.
        populateNavMenu() {
            const menuContainer = document.getElementById('chat-nav-menu-container');
            if (!menuContainer) return;
            
            Array.from(menuContainer.children).forEach(child => {
                if (!child.classList.contains('quicknav-menu-resizer')) {
                    child.remove();
                }
            });

            const header = document.createElement('div');
            header.className = 'chat-nav-menu-header';
            const menuList = document.createElement('ul');
            menuList.id = 'chat-nav-menu';
            menuList.tabIndex = -1;

            ChatController.allTurns.forEach((turn, index) => {
                let displayContent;
                if (turn.cachedContent && !turn.isFallbackContent) {
                    displayContent = turn.cachedContent;
                } else {
                    displayContent = this.getTextFromTurn(turn);

                    const isStreaming = !!turn.querySelector('loading-indicator');

                    if (isStreaming) {
                        turn.cachedContent = null;
                        turn.isFallbackContent = true;
                    } else {
                        turn.cachedContent = displayContent;
                        turn.isFallbackContent = displayContent.source === 'fallback';
                    }
                }

                const { display, full } = displayContent;
                const truncatedText = (display.length > 200) ? display.substring(0, 197) + '...' : display;
                const item = document.createElement('li');
                item.className = 'chat-nav-menu-item';
                item.setAttribute('role', 'menuitem');
                const isPrompt = ChatController.isUserPrompt(turn);
                item.classList.add(isPrompt ? 'prompt-item-bg' : 'response-item-bg');
                const numberSpan = document.createElement('span');
                numberSpan.className = `menu-item-number ${isPrompt ? 'prompt-number-color' : 'response-number-color'}`;
                numberSpan.textContent = `${index + 1}.`;
                const textSpan = document.createElement('span');
                textSpan.className = 'menu-item-text';
                textSpan.textContent = truncatedText;
                item.append(numberSpan, textSpan);
                item.dataset.tooltip = full.replace(/\s+/g, ' ');

                item.addEventListener('click', () => {
                    this.toggleNavMenu();
                    ChatController.navigateToIndex(index);
                });
                menuList.appendChild(item);
            });

            menuList.addEventListener('wheel', (e) => {
                const list = e.currentTarget;
                const isScrollable = list.scrollHeight > list.clientHeight;
                const isScrollingUp = e.deltaY < 0;
                const isScrollingDown = e.deltaY > 0;

                if (!isScrollable) {
                    e.preventDefault();
                    return;
                }

                const isAtTop = list.scrollTop === 0;
                const isAtBottom = Math.ceil(list.scrollTop + list.clientHeight) >= list.scrollHeight;

                if ((isAtTop && isScrollingUp) || (isAtBottom && isScrollingDown)) {
                    e.preventDefault();
                }
            });

            let tooltipTarget = null;
            menuList.addEventListener('mousemove', e => {
                const currentTarget = e.target.closest('.chat-nav-menu-item');
                if (currentTarget && currentTarget === tooltipTarget && this.customTooltip.style.opacity === '1') {
                    this.positionTooltip(e);
                    return;
                }
                if (currentTarget !== tooltipTarget) {
                    clearTimeout(this.tooltipTimeout);
                    this.customTooltip.style.opacity = '0';
                    tooltipTarget = currentTarget;
                    if (tooltipTarget) {
                        this.tooltipTimeout = setTimeout(() => {
                            if (!tooltipTarget) return;
                            this.customTooltip.textContent = tooltipTarget.dataset.tooltip;
                            if (tooltipTarget.classList.contains('response-item-bg')) {
                                const isDarkMode = document.body.classList.contains('dark-theme');
                                this.customTooltip.style.color = isDarkMode ? 'var(--ms-primary, #8ab4f8)' : '#174ea6';
                            } else {
                                this.customTooltip.style.color = '';
                            }
                            this.customTooltip.style.opacity = '1';
                            requestAnimationFrame(() => this.positionTooltip(e));
                        }, 500);
                    }
                }
            });
            menuList.addEventListener('mouseleave', () => {
                clearTimeout(this.tooltipTimeout);
                this.customTooltip.style.opacity = '0';
                tooltipTarget = null;
            });

            const leftContainer = document.createElement('div');
            leftContainer.className = 'header-controls left';
            const loadButton = document.createElement('button');
            loadButton.id = 'chat-nav-load-button';
            loadButton.className = 'header-button';
            loadButton.textContent = 'Load All';
            loadButton.title = 'Load full text for all messages';
            loadButton.addEventListener('click', (e) => {
                e.stopPropagation();
                ChatController.startDynamicMenuLoading();
            });
            const statusIndicator = document.createElement('span');
            statusIndicator.id = 'chat-nav-loader-status';
            leftContainer.append(loadButton, statusIndicator);
            const titleElement = document.createElement('div');
            titleElement.className = 'quicknav-title google-text-animated';
            titleElement.textContent = 'QuickNav for Google AI Studio';
            const rightContainer = document.createElement('div');
            rightContainer.className = 'header-controls right';
            const donateButton = document.createElement('a');
            donateButton.id = 'chat-nav-donate-link';
            donateButton.href = 'https://nowpayments.io/donation/axl_script';
            donateButton.target = '_blank';
            donateButton.rel = 'noopener noreferrer';
            donateButton.className = 'header-button';
            donateButton.title = 'Support the developer';
            const donateText = document.createElement('span');
            donateText.className = 'donate-button-animated';
            donateText.textContent = 'Donate';
            donateButton.appendChild(donateText);
            donateButton.addEventListener('click', (e) => e.stopPropagation());
            rightContainer.append(donateButton);
            header.append(leftContainer, titleElement, rightContainer);
            menuContainer.appendChild(header);
            menuContainer.appendChild(menuList);
        },

        // Updates the badge's position and content, ensuring it stays within all UI boundaries.
        updateScrollPercentage() {
            const floater = document.getElementById('quicknav-badge-floater');
            const percentageBadge = document.getElementById('quicknav-badge-percentage');
            const scrollContainer = document.querySelector('ms-autoscroll-container');

            if (!floater || !percentageBadge || !scrollContainer || ChatController.currentIndex < 0) {
                if (floater) this.hideBadge(0, true);
                return;
            }

            const currentTurn = ChatController.allTurns[ChatController.currentIndex];
            if (!currentTurn) {
                this.hideBadge(0, true);
                return;
            }

            const rect = currentTurn.getBoundingClientRect();
            const scrollContainerRect = scrollContainer.getBoundingClientRect();
            const turnHeight = rect.height;
            const viewportHeight = window.innerHeight;
            const MIN_VISIBLE_HEIGHT = 40;

            const visibleHeight = Math.max(0, Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0));
            const isElementVisible = visibleHeight >= MIN_VISIBLE_HEIGHT;

            if (floater.style.opacity === '1' && !isElementVisible) {
                this.hideBadge(0, true);
                return;
            }
            if (!isElementVisible || turnHeight <= 0) {
                return;
            }

            const floaterHeight = floater.offsetHeight || 44;

            const visibleTurnTop = Math.max(rect.top, scrollContainerRect.top);
            const visibleTurnBottom = Math.min(rect.bottom, scrollContainerRect.bottom);
            const idealTop = (visibleTurnTop + visibleTurnBottom) / 2 - (floaterHeight / 2);

            const toolbarBottom = this.toolbarElement ? this.toolbarElement.getBoundingClientRect().bottom : 0;
            const footerTop = this.footerElement ? this.footerElement.getBoundingClientRect().top : viewportHeight;
            const navContainerTop = this.navContainerElement ? this.navContainerElement.getBoundingClientRect().top : viewportHeight;

            const upperBound = Math.max(scrollContainerRect.top + 4, rect.top, toolbarBottom + 4);
            const lowerBound = Math.min(scrollContainerRect.bottom, rect.bottom, footerTop, navContainerTop) - floaterHeight - 4;

            let finalTop = Math.max(upperBound, Math.min(idealTop, lowerBound));
            floater.style.top = `${finalTop}px`;
            floater.style.left = `${rect.right - (floater.offsetWidth / 2)}px`;

            const viewportCenterY = viewportHeight / 2;
            const distanceScrolled = viewportCenterY - rect.top;
            const percentage = (distanceScrolled / turnHeight) * 100;
            const clampedPercentage = Math.max(0, Math.min(percentage, 100));
            percentageBadge.textContent = `${Math.round(clampedPercentage)}%`;
        },

        positionTooltip(e) {
            const tooltip = this.customTooltip;
            if (!tooltip) return;
            const winWidth = window.innerWidth;
            const winHeight = window.innerHeight;
            const tipHeight = tooltip.offsetHeight;
            const tipWidth = tooltip.offsetWidth;
            const margin = 10;
            let top;
            if (tipHeight >= winHeight) {
                top = 0;
            } else {
                top = e.clientY + 15;
                if (top + tipHeight + margin > winHeight) {
                    top = winHeight - tipHeight - margin;
                }
            }
            let left = e.clientX + 100;
            if (left + tipWidth + margin > winWidth) {
                left = winWidth - tipWidth - margin;
            }
            left = Math.max(margin, left);
            tooltip.style.top = `${top}px`;
            tooltip.style.left = `${left}px`;
        }
    };

    UIManager.closeNavMenu = UIManager.closeNavMenu.bind(UIManager);

    // --- MODULE: Code Block Navigator ---
    // Finds code blocks and injects or updates intra-message navigation controls.
    const CodeBlockNavigator = {
        processTurns(allTurns) {
            if (!allTurns) return;
            allTurns.forEach(turn => {
                const codeBlocksInTurn = Array.from(turn.querySelectorAll('ms-code-block'));
                if (codeBlocksInTurn.length === 0) return;

                codeBlocksInTurn.forEach((block, index) => {
                    const header = block.querySelector('mat-expansion-panel-header .mat-content');
                    const actionsContainer = header ? header.querySelector('.actions-container') : null;
                    if (!header || !actionsContainer) return;

                    let navContainer = header.querySelector('.code-block-nav-container');

                    if (!navContainer) {
                        navContainer = document.createElement('div');
                        navContainer.className = 'code-block-nav-container';

                        const pathUp = 'M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z';
                        const pathDown = 'M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z';

                        const btnUp = this._createNavButton(pathUp);
                        const counter = document.createElement('div');
                        counter.className = 'code-nav-counter';
                        const btnDown = this._createNavButton(pathDown);

                        btnUp.addEventListener('click', (e) => this._handleNavClick(e));
                        btnDown.addEventListener('click', (e) => this._handleNavClick(e));

                        navContainer.append(btnUp, counter, btnDown);
                        actionsContainer.appendChild(navContainer);
                    }

                    const [btnUp, counter, btnDown] = navContainer.children;
                    const totalBlocks = codeBlocksInTurn.length;
                    const currentBlockNum = index + 1;
                    const isFirst = index === 0;
                    const isLast = index === totalBlocks - 1;

                    counter.textContent = `${currentBlockNum} / ${totalBlocks}`;
                    counter.title = `Code block ${currentBlockNum} of ${totalBlocks}`;

                    if (isFirst) {
                        btnUp.dataset.navTarget = 'header';
                        btnUp.title = `Scroll to the header of this block (${currentBlockNum}/${totalBlocks})`;
                    } else {
                        btnUp.dataset.navTarget = 'previous';
                        btnUp.title = `Go to previous block (${currentBlockNum - 1}/${totalBlocks})`;
                    }

                    if (isLast) {
                        btnDown.dataset.navTarget = 'footer';
                        btnDown.title = `Scroll to the footer of this block (${currentBlockNum}/${totalBlocks})`;
                    } else {
                        btnDown.dataset.navTarget = 'next';
                        btnDown.title = `Go to next block (${currentBlockNum + 1}/${totalBlocks})`;
                    }
                });
            });
        },

        _createNavButton(pathData) {
            const button = document.createElement('button');
            button.className = 'code-nav-button';
            const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svg.setAttribute('height', '16px');
            svg.setAttribute('viewBox', '0 0 24 24');
            svg.setAttribute('width', '16px');
            svg.setAttribute('fill', 'currentColor');
            const path = document.createElementNS("http://www.w3.org/2000/svg", 'path');
            path.setAttribute('d', pathData);
            svg.appendChild(path);
            button.appendChild(svg);
            return button;
        },

        _handleNavClick(event) {
            event.stopPropagation();
            event.preventDefault();

            const button = event.currentTarget;
            const navTarget = button.dataset.navTarget;
            const currentCodeBlock = button.closest('ms-code-block');
            if (!currentCodeBlock) return;

            const parentTurn = currentCodeBlock.closest('ms-chat-turn');
            if (!parentTurn) return;

            const turnCodeBlocks = Array.from(parentTurn.querySelectorAll('ms-code-block'));
            const currentIndex = turnCodeBlocks.indexOf(currentCodeBlock);

            let targetBlock = null;

            switch (navTarget) {
                case 'header':
                    this._scrollToElement(currentCodeBlock, 'header');
                    break;
                case 'footer':
                    this._scrollToElement(currentCodeBlock, 'footer');
                    break;
                case 'previous':
                    if (currentIndex > 0) {
                        targetBlock = turnCodeBlocks[currentIndex - 1];
                        this._scrollToElement(targetBlock, 'header');
                    }
                    break;
                case 'next':
                    if (currentIndex < turnCodeBlocks.length - 1) {
                        targetBlock = turnCodeBlocks[currentIndex + 1];
                        this._scrollToElement(targetBlock, 'header');
                    }
                    break;
            }
        },

        _scrollToElement(element, position = 'header') {
            if (!element) return;
            ChatController.isScrollingProgrammatically = true;

            const anchor = document.createElement('div');
            let scrollOptions = { behavior: 'smooth', block: 'center' };
            let targetNodeForAnchor;

            if (position === 'header') {
                targetNodeForAnchor = element.querySelector('mat-expansion-panel-header');
                if (targetNodeForAnchor) {
                    anchor.style.cssText = 'position: absolute; height: 0; width: 0; margin-top: -30px;';
                    targetNodeForAnchor.parentNode.insertBefore(anchor, targetNodeForAnchor);
                }
            } else {
                targetNodeForAnchor = element;
                anchor.style.cssText = 'display: block; height: 1px;';
                targetNodeForAnchor.appendChild(anchor);
                scrollOptions.block = 'end';
            }

            if (targetNodeForAnchor) {
                anchor.scrollIntoView(scrollOptions);
            }

            setTimeout(() => {
                anchor.remove();
                ChatController.isScrollingProgrammatically = false;
            }, 700);
        }
    };

// --- MODULE: Hotkeys Manager ---
    // Handles global keyboard shortcuts for navigation and styling.
    const HotkeysManager = {
        pressedKeys: new Set(),
        lastStyleChange: 0,
        keyMap: {
            'Alt_PageUp': '#nav-up',
            'Alt_PageDown': '#nav-down',
            'Shift_Alt_PageUp': '#nav-top',
            'Shift_Alt_PageDown': '#nav-bottom',
            'Alt_KeyM': '#chat-nav-counter'
        },

        init() {
            document.addEventListener('keydown', this.handleKeyDown.bind(this));
            document.addEventListener('keyup', this.handleKeyUp.bind(this));
            window.addEventListener('blur', this.handleBlur.bind(this));
        },

        getKeyCombination(e) {
            let key = '';
            if (e.shiftKey) key += 'Shift_';
            if (e.altKey) key += 'Alt_';
            key += e.code;
            return key;
        },

// Handles global keyboard events, including new reset shortcuts.
        handleKeyDown(e) {
            if (e.altKey && e.code === 'KeyP') {
                const promptInput = document.querySelector('ms-prompt-box textarea') || document.querySelector('textarea[placeholder="Start typing a prompt"]');
                if (promptInput && document.activeElement !== promptInput) {
                    e.preventDefault();
                    e.stopPropagation();
                    ChatController.focusPromptInput();
                    return;
                }
            }

            if (e.altKey && (e.code === 'Minus' || e.code === 'Equal')) {
                e.preventDefault();
                e.stopPropagation();

                const now = Date.now();
                if (now - this.lastStyleChange < 50) return;
                this.lastStyleChange = now;

                const isShift = e.shiftKey;
                const isPlus = e.code === 'Equal';
                
                const type = isShift ? 'WIDTH' : 'FONT';
                const config = StyleManager[type];
                const step = isPlus ? config.STEP : -config.STEP;

                if (!config.enabled) {
                    StyleManager.toggleSetting(type, true);
                }

                StyleManager.changeValue(type, step);
                return;
            }

            if (e.altKey && e.code === 'Digit0') {
                e.preventDefault();
                e.stopPropagation();
                
                const type = e.shiftKey ? 'WIDTH' : 'FONT';
                
                if (!StyleManager[type].enabled) {
                    StyleManager.toggleSetting(type, true);
                }
                
                StyleManager.resetValue(type);
                return;
            }

            const isTypingArea = e.target.isContentEditable || e.target.closest('[contenteditable="true"]') || ['INPUT', 'TEXTAREA', 'SELECT'].includes(e.target.tagName);
            
            if (e.repeat || (!e.altKey && isTypingArea)) {
                return;
            }

            const combination = this.getKeyCombination(e);
            const targetSelector = this.keyMap[combination];
            
            if (targetSelector) {
                e.preventDefault();
                e.stopPropagation();
                if (!this.pressedKeys.has(combination)) {
                    this.pressedKeys.add(combination);
                    const targetElement = document.querySelector(targetSelector);
                    if (targetElement) {
                        targetElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window, buttons: 1 }));
                    }
                }
            }
        },

        handleKeyUp(e) {
            const releasedCombos = [];
            this.pressedKeys.forEach(combo => {
                const parts = combo.split('_');
                const mainKey = parts[parts.length - 1];
                let isReleased = false;
                
                if (mainKey === e.code) {
                    isReleased = true;
                } else if ((parts.includes('Shift') && (e.code === 'ShiftLeft' || e.code === 'ShiftRight')) || (parts.includes('Alt') && (e.code === 'AltLeft' || e.code === 'AltRight'))) {
                    const requiredAlt = parts.includes('Alt');
                    const requiredShift = parts.includes('Shift');
                    if ((requiredAlt && !e.altKey) || (requiredShift && !e.shiftKey)) {
                        isReleased = true;
                    }
                }
                
                if (isReleased) {
                    releasedCombos.push(combo);
                }
            });

            if (releasedCombos.length > 0) {
                e.preventDefault();
                e.stopPropagation();
                releasedCombos.forEach(combo => {
                    this.pressedKeys.delete(combo);
                    const targetSelector = this.keyMap[combo];
                    if (targetSelector) {
                        const targetElement = document.querySelector(targetSelector);
                        if (targetElement) {
                            targetElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window, buttons: 0 }));
                            targetElement.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window, buttons: 1 }));
                        }
                    }
                });
            }
        },

        handleBlur() {
            this.pressedKeys.forEach(combo => {
                const targetSelector = this.keyMap[combo];
                if (targetSelector) {
                    const targetElement = document.querySelector(targetSelector);
                    if (targetElement) {
                        targetElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window, buttons: 0 }));
                    }
                }
            });
            this.pressedKeys.clear();
        }
    };

// Robustly watches for the chat interface using MutationObserver and efficient polling state machine.
    const DOMObserver = {
        observer: null,
        isChatActive: false,
        checkInterval: null,
        onChatReady: null,
        onChatDestroyed: null,
        CHAT_CONTAINER_SELECTOR: 'ms-chunk-editor, .chat-container, ms-autoscroll-container',

        start(onReady, onDestroyed) {
            this.onChatReady = onReady;
            this.onChatDestroyed = onDestroyed;
            this.observer = new MutationObserver(this.debounce(this.checkState.bind(this), 200));
            this.observer.observe(document.body, { childList: true, subtree: true });
            this.startPolling();
        },

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

        startPolling() {
            if (this.checkInterval) return;
            this.checkState();
            this.checkInterval = setInterval(() => {
                this.checkState();
            }, 1000);
        },

        stopPolling() {
            if (this.checkInterval) {
                clearInterval(this.checkInterval);
                this.checkInterval = null;
            }
        },

        checkState() {
            const chatContainer = document.querySelector(this.CHAT_CONTAINER_SELECTOR);
            const areElementsPresent = !!chatContainer;

            if (areElementsPresent && !this.isChatActive) {
                console.log(`[QuickNav] Chat detected via ${chatContainer.tagName}. UI injected.`);
                this.isChatActive = true;
                
                this.stopPolling();
                
                this.onChatReady(chatContainer, chatContainer); 
            } 
            else if (!areElementsPresent && this.isChatActive) {
                console.log('[QuickNav] Chat elements lost. Destroying UI and restarting search...');
                this.isChatActive = false;
                
                this.onChatDestroyed();
                
                this.startPolling();
            }
        }
    };

    // --- MAIN APP ORCHESTRATOR ---
    // Initializes and coordinates all modules.
    const QuickNavApp = {
        init() {
            DOMObserver.start(
                this.handleChatReady.bind(this),
                this.handleChatDestroyed.bind(this)
            );
            HotkeysManager.init();
        },

        handleChatReady(chatContainer, uiAnchor) {
            try {
                UIManager.create(uiAnchor);
                ChatController.init(chatContainer);
            } catch (e) {
                console.error('[QuickNav] Error during UI initialization:', e);
            }
        },

        handleChatDestroyed() {
            UIManager.destroy();
            ChatController.destroy();
        }
    };

    QuickNavApp.init();

})();