Civitai Prompt Autocomplete & Tag Wiki

Adds tag autocomplete and wiki lookup features

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Civitai Prompt Autocomplete & Tag Wiki
// @namespace    http://tampermonkey.net/
// @version      4.6
// @description  Adds tag autocomplete and wiki lookup features
// @author       AndroidXL
// @match        https://civitai.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=civitai.com
// @grant        GM.xmlHttpRequest
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // All variable declarations moved to top
    let promptInput = null;
    let negativePromptInput = null;  // Add negative prompt input reference
    let activeInput = null;  // Track which input is currently active
    let suggestionsBox = null;
    let currentSuggestions = [];
    let selectedSuggestionIndex = -1;
    let debounceTimer;
    const debounceDelay = 50;
    let lastCurrentWord = "";
    let lastStartPos = 0; // New variable to track word start position
    let wikiOverlay = null;
    let wikiSearchContainer = null;
    let wikiContent = null;
    let currentPosts = [];
    let currentPostIndex = 0;
    let wikiInitialized = false;
    let autocompleteEnabled = true; // Default state for autocomplete
    let wikiHotkey = 't'; // Default hotkey for wiki
    let settingsOpen = false;

    // Wiki history navigation variables
    let wikiHistory = [];
    let historyIndex = -1;
    let isNavigatingHistory = false;

    // Initialize customTags with defaults, will be overridden by localStorage if available
    let customTags = {
        'quality': 'masterpiece, best quality, amazing quality, very detailed',
        'quality_pony': 'score_9, score_8_up, score_7_up, score_6_up',
    };

    // Create and inject styles without GM_addStyle
    const styleElement = document.createElement('style');
    styleElement.textContent = `
        #autocomplete-suggestions-box {
            position: absolute;
            background-color: #1a1b1e;
            border: 1px solid #333;
            border-radius: 5px;
            margin-top: 2px;
            z-index: 100;
            overflow-y: auto;
            max-height: 150px;
            width: calc(100% - 6px);
            padding: 2px;
            box-shadow: 2px 2px 5px rgba(0,0,0,0.3);
        }
        #autocomplete-suggestions-box div {
            padding: 4px 8px;
            cursor: pointer;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            color: #C1C2C5;
            font-size: 14px;
        }
        #autocomplete-suggestions-box div:hover {
            background-color: #282a2d;
        }
        .autocomplete-selected {
            background-color: #383a3e;
        }
        .suggestion-count {
            color: #98C379;
            font-weight: normal;
            margin-left: 8px;
            font-size: 0.9em;
        }

        .wiki-search-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
            z-index: 9999;
            display: none;
            overflow-y: auto;
            padding: 20px;
        }

        .wiki-search-container {
            position: relative;
            width: 90%;
            max-width: 800px;
            margin: 40px auto;
            transition: all 0.3s ease;
        }

        .wiki-search-bar {
            width: 100%;
            padding: 12px;
            background: rgba(26,27,30,0.95);
            border: 1px solid #383a3e;
            border-radius: 8px;
            color: #fff;
            font-size: 16px;
        }

        /* Container for all buttons on the right */
        .wiki-buttons-container {
            position: absolute;
            top: 12px;
            right: 12px;
            display: flex;
            align-items: center;
            gap: 8px;
            z-index: 10002;
        }

        .wiki-settings-button {
            background: rgba(26,27,30,0.95);
            color: #C1C2C5;
            border: 1px solid #383a3e;
            border-radius: 4px;
            padding: 5px 10px;
            cursor: pointer;
            font-size: 14px;
            height: 30px;
            display: flex;
            align-items: center;
        }

        /* Wiki navigation buttons */
        .wiki-nav-history {
            display: flex;
            gap: 5px;
        }

        .wiki-nav-button {
            background: rgba(26,27,30,0.95);
            color: #C1C2C5;
            border: 1px solid #383a3e;
            border-radius: 4px;
            width: 30px;
            height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 16px;
            opacity: 0.7;
            transition: opacity 0.3s, background-color 0.3s;
        }

        .wiki-nav-button:hover:not(:disabled) {
            background: #383a3e;
            opacity: 1;
        }

        .wiki-nav-button:disabled {
            cursor: not-allowed;
            opacity: 0.3;
        }

        .wiki-settings-button:hover {
            background: #383a3e;
        }

        .wiki-settings-panel {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 90%;
            max-width: 600px;
            background: rgba(26,27,30,0.98);
            border: 1px solid #383a3e;
            border-radius: 8px;
            padding: 20px;
            z-index: 10003;
            color: #C1C2C5;
            box-shadow: 0 4px 20px rgba(0,0,0,0.4);
        }

        .wiki-settings-panel h2 {
            margin-top: 0;
            border-bottom: 1px solid #383a3e;
            padding-bottom: 10px;
        }

        .settings-section {
            margin-bottom: 20px;
        }

        .settings-section h3 {
            margin-bottom: 10px;
            font-size: 16px;
            color: #98C379;
        }

        .hotkey-setting {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }

        .hotkey-setting label {
            margin-right: 10px;
        }

        .hotkey-setting input {
            width: 50px;
            background: #1a1b1e;
            border: 1px solid #383a3e;
            border-radius: 4px;
            padding: 5px;
            color: #fff;
            text-align: center;
        }

        .custom-tags-section {
            margin-top: 15px;
        }

        .custom-tag-row {
            display: flex;
            margin-bottom: 8px;
            gap: 10px;
        }

        .custom-tag-name,
        .custom-tag-value {
            flex: 1;
            background: #1a1b1e;
            border: 1px solid #383a3e;
            border-radius: 4px;
            padding: 5px 8px;
            color: #fff;
        }

        .custom-tag-controls {
            display: flex;
            gap: 5px;
        }

        .btn {
            background: #383a3e;
            color: #C1C2C5;
            border: none;
            border-radius: 4px;
            padding: 5px 10px;
            cursor: pointer;
            font-size: 14px;
        }

        .btn:hover {
            background: #4a4c52;
        }

        .btn-save {
            background: #2c6e49;
        }

        .btn-save:hover {
            background: #358f5f;
        }

        .btn-delete {
            background: #6e2c2c;
        }

        .btn-delete:hover {
            background: #913a3a;
        }

        .btn-add {
            background: #2c4a6e;
            margin-top: 10px;
        }

        .btn-add:hover {
            background: #385d89;
        }

        .settings-panel-footer {
            display: flex;
            justify-content: flex-end;
            margin-top: 20px;
            padding-top: 15px;
            border-top: 1px solid #383a3e;
            gap: 10px;
        }

        .wiki-content {
            background: rgba(26,27,30,0.95);
            border-radius: 8px;
            margin-top: 20px;
            padding: 20px;
            width: 100%;
            position: relative;
        }

        .wiki-text-content {
            padding-right: 420px;
            min-height: 500px;
            word-break: break-word;
            overflow-wrap: break-word;
        }

        .wiki-description {
            line-height: 1.4;
            white-space: pre-line;
            font-size: 15px;
        }

        .wiki-image-section {
            position: absolute;
            top: 20px;
            right: 20px;
            width: 400px;
            background: rgba(0,0,0,0.2);
            border-radius: 8px;
            padding: 10px;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        .wiki-image-navigation {
            display: flex;
            justify-content: space-between;
            align-items: center;
            width: 100%;
            padding: 0 10px;
            position: relative;
            height: 40px;
        }

        .image-nav-button {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(0,0,0,0.7);
            color: white;
            border: none;
            width: 40px;
            height: 40px;
            cursor: pointer;
            border-radius: 20px;
            opacity: 0.8;
            transition: opacity 0.3s, background-color 0.3s;
            font-size: 18px;
            z-index: 2;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .image-nav-button:hover {
            opacity: 1;
            background: rgba(0,0,0,0.9);
        }

        .image-nav-button.prev {
            left: 10px;
        }

        .image-nav-button.next {
            right: 10px;
        }

        .wiki-image-container {
            width: 100%;
            height: 350px;
            position: relative;
            margin: 0;
            background: rgba(0,0,0,0.1);
            border-radius: 4px;
            overflow: hidden;
        }

        .wiki-image {
            width: 100%;
            height: 100%;
            object-fit: contain;
            border-radius: 4px;
            transition: transform 0.3s ease;
        }

        .wiki-image:hover {
            transform: scale(1.03);
        }

        .wiki-image-section {
            position: absolute;
            top: 20px;
            right: 20px;
            width: 400px;
            background: rgba(0,0,0,0.2);
            border-radius: 8px;
            padding: 10px;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        .wiki-image-navigation {
            display: flex;
            justify-content: space-between;
            align-items: center;
            width: 100%;
            padding: 0 10px;
        }

        .image-nav-button {
            background: rgba(0,0,0,0.5);
            color: white;
            border: none;
            padding: 8px 12px;
            cursor: pointer;
            border-radius: 4px;
            opacity: 0.7;
            transition: opacity 0.3s;
            font-size: 16px;
        }

        .wiki-image-container {
            width: 100%;
            height: 350px;
            display: flex;
            justify-content: center;
            align-items: center;
            position: relative;
            margin: 0;
            background: rgba(0,0,0,0.1);
            border-radius: 4px;
        }

        .wiki-image {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
            border-radius: 4px;
        }

        .wiki-nav-buttons {
            width: 100%;
            display: flex;
            justify-content: center;
        }

        .wiki-button {
            padding: 8px 16px;
            background: #383a3e;
            border: none;
            border-radius: 4px;
            color: #fff;
            cursor: pointer;
            width: 100%;
            text-align: center;
        }

        .wiki-tag {
            display: inline-block;
            margin: 2px 4px;
            padding: 2px 4px;
            background: rgba(97, 175, 239, 0.1);
            border-radius: 3px;
            color: #61afef;
            cursor: pointer;
            text-decoration: underline;
        }

        .wiki-tag:hover {
            background: rgba(97, 175, 239, 0.2);
        }

        .wiki-link {
            color: #98c379;
            text-decoration: underline;
        }

        .wiki-loading {
            text-align: center;
            padding: 20px;
        }

        .wiki-description {
            line-height: 1.6;
            white-space: pre-wrap;
            font-size: 15px;
        }

        .wiki-description p {
            margin: 1em 0;
        }

        .wiki-search-suggestions {
            position: fixed;
            margin-top: 2px;
            background: rgba(26,27,30,0.95);
            border: 1px solid #383a3e;
            border-radius: 0 0 8px 8px;
            max-height: 200px;
            overflow-y: auto;
            z-index: 10001;
            width: 90%;
            max-width: 800px;
            left: 50%;
            transform: translateX(-50%);
        }

        .wiki-search-suggestion {
            padding: 8px 12px;
            cursor: pointer;
            color: #fff;
        }

        .wiki-search-suggestion:hover,
        .wiki-search-suggestion.selected {
            background: #383a3e;
        }

        .no-images-message {
            color: #666;
            text-align: center;
            padding: 20px;
            font-style: italic;
        }

        @keyframes slideUp {
            from { transform: translateY(20px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }

        .wiki-description h1 { font-size: 1.8em; margin: 0.8em 0 0.4em; }
        .wiki-description h2 { font-size: 1.6em; margin: 0.7em 0 0.4em; }
        .wiki-description h3 { font-size: 1.4em; margin: 0.6em 0 0.4em; }
        .wiki-description h4 { font-size: 1.2em; margin: 0.5em 0 0.4em; }
        .wiki-description h5 { font-size: 1.1em; margin: 0.5em 0 0.4em; }
        .wiki-description h6 { font-size: 1em; margin: 0.5em 0 0.4em; }
        .wiki-description p { margin: 0.5em 0; }

        .wiki-description ul {
            margin: 0.5em 0 0.5em 1.5em;
            padding: 0;
        }

        .wiki-description li {
            margin: 0.3em 0;
            line-height: 1.4;
        }

        /* Autocomplete toggle checkbox styles */
        .autocomplete-toggle {
            display: flex;
            align-items: center;
            margin-bottom: 5px;
            font-size: 0.9em;
            color: #C1C2C5;
        }

        .autocomplete-toggle input {
            margin-right: 5px;
        }

        .tag-validation-error {
            color: #f55;
            font-size: 12px;
            margin-top: 5px;
        }
    `;
    document.head.appendChild(styleElement);

    // Load settings from localStorage
    function loadSettings() {
        try {
            // Load autocomplete preference
            const savedAutoComplete = localStorage.getItem('civitai-autocomplete-enabled');
            if (savedAutoComplete !== null) {
                autocompleteEnabled = savedAutoComplete === 'true';
            }

            // Load wiki hotkey
            const savedHotkey = localStorage.getItem('civitai-wiki-hotkey');
            if (savedHotkey) {
                wikiHotkey = savedHotkey;
            }

            // Load custom tags
            const savedTags = localStorage.getItem('civitai-custom-tags');
            if (savedTags) {
                try {
                    customTags = JSON.parse(savedTags);
                } catch (e) {
                    console.error('Error parsing custom tags:', e);
                    // If parsing fails, keep the default tags
                }
            }

            debug('Settings loaded from localStorage');
        } catch (e) {
            console.error('Error loading settings:', e);
            // Use defaults if there's an error
        }
    }

    // Save settings to localStorage
    function saveSettings() {
        try {
            localStorage.setItem('civitai-autocomplete-enabled', autocompleteEnabled);
            localStorage.setItem('civitai-wiki-hotkey', wikiHotkey);
            localStorage.setItem('civitai-custom-tags', JSON.stringify(customTags));
            debug('Settings saved to localStorage');
        } catch (e) {
            console.error('Error saving settings:', e);
        }
    }

    // Load settings when script starts
    loadSettings();

   // Replace handleInputEvents function
    function handleInputEvents(e) {
        const input = e.target;
        if ((input.id === 'input_prompt' || input.id === 'input_negativePrompt') && autocompleteEnabled) {
            activeInput = input; // Set the active input
            const currentWordObj = getCurrentWord(input.value, input.selectionStart);
            lastCurrentWord = currentWordObj.word;
            lastStartPos = currentWordObj.startPos;
            fetchSuggestions(lastCurrentWord);

            // Position suggestions box below the active input
            if (suggestionsBox) {
                const inputRect = input.getBoundingClientRect();
                suggestionsBox.style.position = 'absolute';
                suggestionsBox.style.left = `${inputRect.left}px`;
                suggestionsBox.style.top = `${inputRect.bottom + window.scrollY}px`;
                suggestionsBox.style.width = `${inputRect.width}px`;
            }
        }
    }

    // Create the toggle checkbox
    function createAutocompleteToggle() {
        const toggleContainer = document.createElement('div');
        toggleContainer.className = 'autocomplete-toggle';

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.id = 'autocomplete-toggle-checkbox';
        checkbox.checked = autocompleteEnabled;

        const label = document.createElement('label');
        label.htmlFor = 'autocomplete-toggle-checkbox';
        label.textContent = 'Enable Tag Autocomplete';

        toggleContainer.appendChild(checkbox);
        toggleContainer.appendChild(label);

        checkbox.addEventListener('change', function() {
            autocompleteEnabled = this.checked;
            saveSettings();
            if (!autocompleteEnabled) {
                clearSuggestions();
            }
        });

        return toggleContainer;
    }

    function handleKeydownEvents(e) {
        if (e.target.id !== 'input_prompt' && e.target.id !== 'input_negativePrompt') return;
        
        activeInput = e.target; // Update active input
    
        if (e.key === 'ArrowDown') {
            if (suggestionsBox?.style.display === 'block' && currentSuggestions.length > 0) {
                e.preventDefault();
                selectedSuggestionIndex = Math.min(selectedSuggestionIndex + 1, currentSuggestions.length - 1);
                updateSuggestionSelection();
            }
        } else if (e.key === 'ArrowUp') {
            if (suggestionsBox?.style.display === 'block' && currentSuggestions.length > 0) {
                e.preventDefault();
                selectedSuggestionIndex = Math.max(selectedSuggestionIndex - 1, -1);
                updateSuggestionSelection();
            }
        } else if (e.key === 'Tab' || e.key === 'Enter') {
            if (suggestionsBox?.style.display === 'block' && currentSuggestions.length > 0) {
                e.preventDefault();
                if (selectedSuggestionIndex !== -1) {
                    insertSuggestion(currentSuggestions[selectedSuggestionIndex].label);
                } else {
                    insertSuggestion(currentSuggestions[0].label);
                }
            }
        } else if (e.key === 'Escape') {
            clearSuggestions();
        }
    }

    function setupAutocomplete() {
        // Clean up old elements
        if (suggestionsBox) {
            suggestionsBox.remove();
        }

        // Remove old toggle if it exists
        const oldToggle = document.getElementById('autocomplete-toggle-checkbox');
        if (oldToggle && oldToggle.parentNode) {
            oldToggle.parentNode.remove();
        }

        // Get both input elements
        promptInput = document.getElementById('input_prompt');
        negativePromptInput = document.getElementById('input_negativePrompt');

        // Exit if neither input exists
        if (!promptInput && !negativePromptInput) return;

        // Create suggestions box (attach to document body instead of a specific input)
        suggestionsBox = document.createElement('div');
        suggestionsBox.id = 'autocomplete-suggestions-box';
        suggestionsBox.style.display = 'none';
        document.body.appendChild(suggestionsBox);

        // Create the toggle and insert it before the positive prompt if it exists
        if (promptInput) {
            const toggleContainer = createAutocompleteToggle();
            promptInput.parentNode.parentNode.parentNode.parentNode.insertBefore(
                toggleContainer,
                promptInput.parentNode.parentNode.parentNode.parentNode.firstChild
            );
        }

        // Remove old event listeners and add new ones using event delegation
        document.removeEventListener('input', handleInputEvents, true);
        document.removeEventListener('keydown', handleKeydownEvents, true);
        document.addEventListener('input', handleInputEvents, true);
        document.addEventListener('keydown', handleKeydownEvents, true);

        // Handle clicks outside
        document.addEventListener('click', (e) => {
            if ((!promptInput?.contains(e.target) && !negativePromptInput?.contains(e.target)) &&
                !suggestionsBox?.contains(e.target)) {
                clearSuggestions();
            }
        });
    }

    // Set up a more aggressive observer
    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            const addedNodes = Array.from(mutation.addedNodes);
            const hasPromptInput = addedNodes.some(node =>
                node.id === 'input_prompt' ||
                node.querySelector?.('#input_prompt')
            );

            if (hasPromptInput || !document.getElementById('autocomplete-suggestions-box')) {
                setupAutocomplete();
                break;
            }
        }
    });

    // Start observing with more specific config
    observer.observe(document.body, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['id']
    });

    // Initial setup
    setupAutocomplete();
    initializeWiki();

    function fetchSuggestions(term) {
        if (!term || !autocompleteEnabled) {
            clearSuggestions();
            return;
        }

        // First, check custom tags
        const matchingCustomTags = Object.keys(customTags)
            .filter(tag => tag.toLowerCase().startsWith(term.toLowerCase()))
            .map(tag => ({
                label: tag,
                count: '⭐', // Star to indicate custom tag
                isCustom: true,
                insertText: customTags[tag]
            }));

        // If we have matching custom tags, show them immediately
        if (matchingCustomTags.length > 0) {
            currentSuggestions = matchingCustomTags;
            showSuggestions();
        }

        // Continue with API request for regular tags
        const apiTerm = term.replace(/ /g, '_');

        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            GM.xmlHttpRequest({
                method: 'GET',
                url: `https://gelbooru.com/index.php?page=autocomplete2&term=${encodeURIComponent(apiTerm)}&type=tag_query&limit=10`,
                onload: function(response) {
                    if (response.status === 200) {
                        try {
                            const data = JSON.parse(response.responseText);
                            const fetchedSuggestions = data.map(item => ({
                                label: item.label.replace(/[()]/g, '\\$&'),
                                count: item.post_count,
                                isCustom: false
                            }));
                            // Combine custom and API suggestions
                            filterAndShowSuggestions([...matchingCustomTags, ...fetchedSuggestions]);
                        } catch (e) {
                            console.error("Error parsing Gelbooru API response:", e);
                            clearSuggestions();
                        }
                    } else {
                        console.error("Gelbooru API request failed:", response.status, response.statusText);
                        clearSuggestions();
                    }
                },
                onerror: function(error) {
                    console.error("Gelbooru API request error:", error);
                    clearSuggestions();
                }
            });
        }, debounceDelay);
    }

    function filterAndShowSuggestions(fetchedSuggestions) {
        const existingTags = promptInput.value.split(',').map(tag => tag.trim().toLowerCase());
        const filteredSuggestions = fetchedSuggestions.filter(suggestion => {
            return !existingTags.includes(suggestion.label.toLowerCase())
        });

        currentSuggestions = filteredSuggestions;

        showSuggestions();
    }


    function showSuggestions() {
        if (currentSuggestions.length === 0) {
            clearSuggestions();
            return;
        }

        suggestionsBox.innerHTML = '';


        currentSuggestions.forEach((suggestion, index) => {
            const suggestionDiv = document.createElement('div');
            suggestionDiv.innerHTML = `${suggestion.label} <span class="suggestion-count">[${suggestion.count}]</span>`;
            suggestionDiv.addEventListener('click', () => {
                insertSuggestion(suggestion.label);
            });
            suggestionsBox.appendChild(suggestionDiv);
        });

        suggestionsBox.style.display = 'block';
        selectedSuggestionIndex = -1;
    }

    function clearSuggestions() {
        if (suggestionsBox) {
            suggestionsBox.style.display = 'none';
            suggestionsBox.innerHTML = '';
        }
        currentSuggestions = [];
        selectedSuggestionIndex = -1;
    }

    function insertSuggestion(suggestion) {
        // Make sure we have an active input
        if (!activeInput) return;
    
        // Find the matching suggestion object
        const suggestionObj = currentSuggestions.find(s => s.label === suggestion);
        const textToInsert = (suggestionObj?.isCustom ? suggestionObj.insertText : suggestion)
    
        // Use setRangeText to replace the current word with the suggestion
        const start = lastStartPos;
        const end = activeInput.selectionStart;
    
        // Focus the input to ensure changes register in the undo stack
        activeInput.focus();
    
        // Create a composition session to properly register in the undo stack
        // First delete the current word manually
        activeInput.setSelectionRange(start, end);
        document.execCommand('delete');
    
        // Then insert the new text with execCommand
        document.execCommand('insertText', false, textToInsert + ', ');
    
        // Simulate focus and blur to mimic user interaction
        activeInput.focus();
        activeInput.blur();
        setTimeout(() => {
            activeInput.focus();
        }, 0); // Delay refocus to allow React to process
    
        // Clear suggestions and keep focus
        clearSuggestions();
        activeInput.focus();
    }

    function updateSuggestionSelection() {
        if (!suggestionsBox) return;

        const suggestionDivs = suggestionsBox.querySelectorAll('div');
        suggestionDivs.forEach((div, index) => {
            if (index === selectedSuggestionIndex) {
                div.classList.add('autocomplete-selected');
                div.scrollIntoView({ block: 'nearest' });
            } else {
                div.classList.remove('autocomplete-selected');
            }
        });
    }

    function getCurrentWord(text, cursorPosition) {
        if (cursorPosition === undefined) cursorPosition = text.length;

        const textBeforeCursor = text.substring(0, cursorPosition);
        const lastCommaIndex = textBeforeCursor.lastIndexOf(',');
        let startPos, word;

        if (lastCommaIndex !== -1) {
            startPos = lastCommaIndex + 1;
            word = textBeforeCursor.substring(startPos).trim();
            // Find the exact position where the trimmed word starts
            if (word) {
                const leadingSpaces = textBeforeCursor.substring(startPos).length - textBeforeCursor.substring(startPos).trimLeft().length;
                startPos = startPos + leadingSpaces;
            }
        } else {
            startPos = 0;
            word = textBeforeCursor.trim();
            // If the text has leading spaces, adjust the start position
            if (word && textBeforeCursor !== word) {
                startPos = textBeforeCursor.indexOf(word);
            }
        }
        
        return { word, startPos };
    }

    // Add debug logging function
    function debug(msg) {
        console.log(`[Wiki Debug] ${msg}`);
    }

    // Create settings panel DOM
    function createSettingsPanel() {
        const settingsPanel = document.createElement('div');
        settingsPanel.className = 'wiki-settings-panel';

        // Header
        const header = document.createElement('h2');
        header.textContent = 'Wiki & Autocomplete Settings';
        settingsPanel.appendChild(header);

        // Hotkey section
        const hotkeySection = document.createElement('div');
        hotkeySection.className = 'settings-section';

        const hotkeyTitle = document.createElement('h3');
        hotkeyTitle.textContent = 'Hotkeys';
        hotkeySection.appendChild(hotkeyTitle);

        const hotkeyContent = document.createElement('div');
        hotkeyContent.className = 'hotkey-setting';

        const hotkeyLabel = document.createElement('label');
        hotkeyLabel.textContent = 'Wiki search hotkey:';

        const hotkeyInput = document.createElement('input');
        hotkeyInput.type = 'text';
        hotkeyInput.value = wikiHotkey;
        hotkeyInput.maxLength = 1;
        hotkeyInput.addEventListener('keydown', function(e) {
            e.preventDefault();
            this.value = e.key.toLowerCase();
        });

        hotkeyContent.appendChild(hotkeyLabel);
        hotkeyContent.appendChild(hotkeyInput);
        hotkeySection.appendChild(hotkeyContent);
        settingsPanel.appendChild(hotkeySection);

        // Custom tags section
        const tagsSection = document.createElement('div');
        tagsSection.className = 'settings-section';

        const tagsTitle = document.createElement('h3');
        tagsTitle.textContent = 'Custom Tags';
        tagsSection.appendChild(tagsTitle);

        const tagsContainer = document.createElement('div');
        tagsContainer.className = 'custom-tags-section';

        // Create UI for each existing tag
        Object.keys(customTags).forEach(tag => {
            const tagRow = createTagRow(tag, customTags[tag]);
            tagsContainer.appendChild(tagRow);
        });

        // Add new tag button
        const addTagBtn = document.createElement('button');
        addTagBtn.className = 'btn btn-add';
        addTagBtn.textContent = '+ Add New Tag';
        addTagBtn.addEventListener('click', function() {
            const newTagRow = createTagRow('', '');
            tagsContainer.insertBefore(newTagRow, addTagBtn);
            newTagRow.querySelector('.custom-tag-name').focus();
        });

        tagsContainer.appendChild(addTagBtn);
        tagsSection.appendChild(tagsContainer);
        settingsPanel.appendChild(tagsSection);

        // Footer with buttons
        const footer = document.createElement('div');
        footer.className = 'settings-panel-footer';

        const cancelBtn = document.createElement('button');
        cancelBtn.className = 'btn';
        cancelBtn.textContent = 'Cancel';
        cancelBtn.addEventListener('click', hideSettingsPanel);

        const saveBtn = document.createElement('button');
        saveBtn.className = 'btn btn-save';
        saveBtn.textContent = 'Save Settings';
        saveBtn.addEventListener('click', function() {
            const errors = validateAndSaveSettings(hotkeyInput, tagsContainer);
            if (errors.length === 0) {
                hideSettingsPanel();
            } else {
                // Display errors
                const existingError = settingsPanel.querySelector('.tag-validation-error');
                if (existingError) existingError.remove();

                const errorDiv = document.createElement('div');
                errorDiv.className = 'tag-validation-error';
                errorDiv.textContent = errors.join(', ');
                footer.insertBefore(errorDiv, cancelBtn);
            }
        });

        footer.appendChild(cancelBtn);
        footer.appendChild(saveBtn);
        settingsPanel.appendChild(footer);

        return settingsPanel;
    }

    // Helper function to create a tag row
    function createTagRow(name, value) {
        const row = document.createElement('div');
        row.className = 'custom-tag-row';

        const nameInput = document.createElement('input');
        nameInput.type = 'text';
        nameInput.className = 'custom-tag-name';
        nameInput.placeholder = 'Tag name';
        nameInput.value = name;

        const valueInput = document.createElement('input');
        valueInput.type = 'text';
        valueInput.className = 'custom-tag-value';
        valueInput.placeholder = 'Tag value (comma separated)';
        valueInput.value = value;

        const controlsDiv = document.createElement('div');
        controlsDiv.className = 'custom-tag-controls';

        const deleteBtn = document.createElement('button');
        deleteBtn.className = 'btn btn-delete';
        deleteBtn.textContent = '🗑️';
        deleteBtn.title = 'Delete tag';
        deleteBtn.addEventListener('click', function() {
            row.remove();
        });

        controlsDiv.appendChild(deleteBtn);

        row.appendChild(nameInput);
        row.appendChild(valueInput);
        row.appendChild(controlsDiv);

        return row;
    }

    // Validate settings and save
    function validateAndSaveSettings(hotkeyInput, tagsContainer) {
        const errors = [];

        // Validate hotkey
        const newHotkey = hotkeyInput.value.trim();
        if (!newHotkey) {
            errors.push('Hotkey cannot be empty');
        } else {
            wikiHotkey = newHotkey;
        }

        // Validate and collect tags
        const newCustomTags = {};
        const tagRows = tagsContainer.querySelectorAll('.custom-tag-row');
        const tagNames = new Set();

        tagRows.forEach(row => {
            const nameInput = row.querySelector('.custom-tag-name');
            const valueInput = row.querySelector('.custom-tag-value');

            const name = nameInput.value.trim();
            const value = valueInput.value.trim();

            if (name && value) {
                if (tagNames.has(name)) {
                    errors.push(`Duplicate tag name: ${name}`);
                } else {
                    tagNames.add(name);
                    newCustomTags[name] = value;
                }
            } else if (name || value) {
                errors.push(`Tag ${name || 'name'} is missing ${name ? 'value' : 'name'}`);
            }
            // Skip empty rows (both name and value empty)
        });

        if (errors.length === 0) {
            customTags = newCustomTags;
            saveSettings();
        }

        return errors;
    }

    // Show settings panel
    function showSettingsPanel() {
        settingsOpen = true;

        // Remove any existing panel
        const existingPanel = document.querySelector('.wiki-settings-panel');
        if (existingPanel) existingPanel.remove();

        // Create and append new panel
        const settingsPanel = createSettingsPanel();
        wikiOverlay.appendChild(settingsPanel);
    }

    // Hide settings panel
    function hideSettingsPanel() {
        const panel = document.querySelector('.wiki-settings-panel');
        if (panel) panel.remove();
        settingsOpen = false;
    }

    // Initialize wiki interface immediately
    function initializeWiki() {
        if (wikiInitialized) {
            debug('Wiki already initialized');
            return;
        }

        debug('Initializing wiki interface');

        // Make sure settings are loaded
        loadSettings();
        
        // Continue with wiki initialization
        wikiOverlay = document.createElement('div');
        wikiOverlay.className = 'wiki-search-overlay';

        wikiSearchContainer = document.createElement('div');
        wikiSearchContainer.className = 'wiki-search-container';

        const searchBar = document.createElement('input');
        searchBar.className = 'wiki-search-bar';
        searchBar.placeholder = 'Search tag wiki...';

        // Create container for all buttons
        const buttonsContainer = document.createElement('div');
        buttonsContainer.className = 'wiki-buttons-container';

        // Add navigation history buttons
        const navContainer = document.createElement('div');
        navContainer.className = 'wiki-nav-history';

        const backButton = document.createElement('button');
        backButton.className = 'wiki-nav-button back';
        backButton.textContent = '<';
        backButton.disabled = true;
        backButton.title = 'Go back to previous tag';
        backButton.addEventListener('click', navigateWikiHistory.bind(null, -1));

        const forwardButton = document.createElement('button');
        forwardButton.className = 'wiki-nav-button forward';
        forwardButton.textContent = '>';
        forwardButton.disabled = true;
        forwardButton.title = 'Go forward to next tag';
        forwardButton.addEventListener('click', navigateWikiHistory.bind(null, 1));

        navContainer.appendChild(backButton);
        navContainer.appendChild(forwardButton);

        // Add settings button
        const settingsButton = document.createElement('button');
        settingsButton.className = 'wiki-settings-button';
        settingsButton.textContent = '⚙️ Settings';
        settingsButton.addEventListener('click', function(e) {
            e.preventDefault();
            showSettingsPanel();
        });

        // Add navigation buttons first, then settings button
        buttonsContainer.appendChild(navContainer);
        buttonsContainer.appendChild(settingsButton);

        wikiContent = document.createElement('div');
        wikiContent.className = 'wiki-content';
        wikiContent.style.display = 'none';

        wikiSearchContainer.appendChild(searchBar);
        wikiSearchContainer.appendChild(buttonsContainer);
        wikiSearchContainer.appendChild(wikiContent);
        wikiOverlay.appendChild(wikiSearchContainer);
        document.body.appendChild(wikiOverlay);

        // Separate key handler based on configurable hotkey
        document.addEventListener('keydown', function(e) {
            if (e.key.toLowerCase() === wikiHotkey.toLowerCase() && !isInputFocused()) {
                debug(`Hotkey ${wikiHotkey} pressed, showing wiki search`);
                e.preventDefault();
                showWikiSearch();
            }
        });

        searchBar.addEventListener('keydown', async function(e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                await loadWikiInfo(searchBar.value);
            } else if (e.key === 'Escape') {
                if (settingsOpen) {
                    hideSettingsPanel();
                } else {
                    hideWikiSearch();
                }
            }
        });

        wikiOverlay.addEventListener('click', function(e) {
            if (e.target === wikiOverlay) {
                if (settingsOpen) {
                    hideSettingsPanel();
                } else {
                    hideWikiSearch();
                }
            }
        });

        setupWikiSearchAutocomplete(searchBar);

        wikiInitialized = true;
        debug('Wiki interface initialized');
    }

    // Navigate through wiki history
    function navigateWikiHistory(direction) {
        if (!wikiHistory.length) return;

        const newIndex = historyIndex + direction;

        if (newIndex >= 0 && newIndex < wikiHistory.length) {
            isNavigatingHistory = true;
            historyIndex = newIndex;
            updateHistoryButtons();
            loadWikiInfo(wikiHistory[historyIndex]);
        }
    }

    // Update the state of history navigation buttons
    function updateHistoryButtons() {
        const backButton = document.querySelector('.wiki-nav-button.back');
        const forwardButton = document.querySelector('.wiki-nav-button.forward');

        if (!backButton || !forwardButton) return;

        backButton.disabled = historyIndex <= 0;
        forwardButton.disabled = historyIndex >= wikiHistory.length - 1;
    }

    function hideWikiSearch() {
        debug('Hiding wiki search interface');
        wikiOverlay.style.display = 'none';
        hideSettingsPanel();
    }

    // Modified showWikiSearch function
    function showWikiSearch() {
        if (!wikiInitialized) {
            debug('Attempting to show wiki before initialization');
            initializeWiki();
        }
        debug('Showing wiki search interface');
        wikiOverlay.style.display = 'block';
        const searchBar = wikiSearchContainer.querySelector('.wiki-search-bar');
        searchBar.value = '';
        searchBar.focus();
        wikiContent.style.display = 'none';

        // Reset navigation buttons when opening search
        updateHistoryButtons();
    }

    // Add keyboard shortcut for closing with escape
    document.addEventListener('keydown', e => {
        if (e.key === 'Escape' && wikiOverlay.style.display === 'block') {
            if (settingsOpen) {
                hideSettingsPanel();
            } else {
                hideWikiSearch();
            }
        }
    });

    // Initialize wiki immediately
    initializeWiki();

    // The rest of the script remains unchanged
    function isInputFocused() {
        const activeElement = document.activeElement;
        return activeElement && (
            activeElement.tagName === 'INPUT' ||
            activeElement.tagName === 'TEXTAREA' ||
            activeElement.isContentEditable
        );
    }

    // Wiki helper functions
    async function loadWikiInfo(tag) {
        // Reset animation
        wikiSearchContainer.style.animation = 'none';
        wikiSearchContainer.offsetHeight; // Trigger reflow
        wikiSearchContainer.style.animation = null;

        // Update search bar value
        const searchBar = wikiSearchContainer.querySelector('.wiki-search-bar');
        searchBar.value = tag;

        // Add to history if not navigating through history
        if (!isNavigatingHistory) {
            // If we're in the middle of the history and searching a new tag,
            // remove all entries after current position
            if (historyIndex < wikiHistory.length - 1 && historyIndex >= 0) {
                wikiHistory = wikiHistory.slice(0, historyIndex + 1);
            }

            // Don't add duplicate consecutive entries
            if (wikiHistory.length === 0 || wikiHistory[wikiHistory.length - 1] !== tag) {
                wikiHistory.push(tag);
                historyIndex = wikiHistory.length - 1;
            }
        } else {
            // Reset the flag after navigation
            isNavigatingHistory = false;
        }

        // Update button states
        updateHistoryButtons();

        wikiContent.innerHTML = '<div class="wiki-loading">Loading...</div>';
        wikiContent.style.display = 'block';
        wikiSearchContainer.style.animation = 'slideUp 0.3s forwards';

        try {
            const [wikiData, postsData] = await Promise.all([
                fetchDanbooruWiki(tag),
                fetchDanbooruPosts(tag)
            ]);

            currentPosts = postsData;
            currentPostIndex = 0;

            displayWikiContent(wikiData, tag);
            if (currentPosts.length > 0) {
                displayPostImage(currentPosts[0]);
            }
        } catch (error) {
            wikiContent.innerHTML = `<div class="error">Error loading wiki: ${error.message}</div>`;
        }
    }

    function fetchDanbooruWiki(tag) {
        // Convert to lowercase and replace spaces with underscores
        const formattedTag = tag.trim().toLowerCase().replace(/\s+/g, '_');
        return new Promise((resolve, reject) => {
            GM.xmlHttpRequest({
                method: 'GET',
                url: `https://danbooru.donmai.us/wiki_pages.json?search[title]=${encodeURIComponent(formattedTag)}`,
                onload: response => resolve(JSON.parse(response.responseText)),
                onerror: reject
            });
        });
    }

    function fetchDanbooruPosts(tag) {
        const formattedTag = tag.trim().toLowerCase().replace(/\s+/g, '_');
        return new Promise((resolve, reject) => {
            GM.xmlHttpRequest({
                method: 'GET',
                url: `https://danbooru.donmai.us/posts.json?tags=${encodeURIComponent(formattedTag)}&limit=10`,
                onload: response => resolve(JSON.parse(response.responseText)),
                onerror: reject
            });
        });
    }

    function displayWikiContent(wikiData, tag) {
        const hasWiki = wikiData && wikiData[0];
        const hasPosts = currentPosts && currentPosts.length > 0;

        wikiContent.innerHTML = `
            <div class="wiki-text-content">
                <h2>${tag}</h2>
                <div class="wiki-description">
                    ${hasWiki ? `<p>${formatWikiText(wikiData[0].body)}</p>` :
                    `<p>No wiki information available for this tag${hasPosts ? ', but images are available.' : '.'}</p>`}
                </div>
            </div>
            <div class="wiki-image-section">
                ${hasPosts ? `
                    <div class="wiki-image-container">
                        <button class="image-nav-button prev" title="Previous image">←</button>
                        <img class="wiki-image" src="" alt="Tag example">
                        <button class="image-nav-button next" title="Next image">→</button>
                    </div>
                    <div class="wiki-nav-buttons">
                        <button class="wiki-button view-on-danbooru">View on Danbooru</button>
                    </div>
                ` : `
                    <div class="no-images-message">No images available for this tag</div>
                `}
            </div>
        `;

        // Always attach wiki tag event listeners
        attachWikiEventListeners();

        // Only display images if we have posts
        if (hasPosts) {
            displayPostImage(currentPosts[0]);
        }
    }

    function formatWikiText(text) {
        // Remove backticks that sometimes wrap the content
        text = text.replace(/^`|`$/g, '');

        // First handle the complex patterns
        text = text
            // Handle list items with proper indentation
            .replace(/^\* (.+)$/gm, '<li>$1</li>')


            // Handle Danbooru internal paths (using absolute URLs)
            .replace(/"([^"]+)":\s*\/((?:[\w-]+\/)*[\w-]+(?:\?[^"\s]+)?)/g, (match, text, path) => {
                const fullUrl = `https://danbooru.donmai.us/${path.trim()}`;
                return `<a class="wiki-link" href="${fullUrl}" target="_blank">${text}</a>`;
            })

            // Handle named links with square brackets
            .replace(/"([^"]+)":\[([^\]]+)\]/g, '<a class="wiki-link" href="$2" target="_blank">$1</a>')

            // Handle post references
            .replace(/!post #(\d+)/g, '<a class="wiki-link" href="https://danbooru.donmai.us/posts/$1" target="_blank">post #$1</a>')

            // Handle external links with proper URL capture (must come before wiki links)
            .replace(/"([^"]+)":\s*(https?:\/\/[^\s"]+)/g, '<a class="wiki-link" href="$2" target="_blank">$1</a>')

            // Handle wiki links with display text, preserving special characters
            .replace(/\[\[([^\]|]+)\|([^\]]+)\]\]/g, (match, tag, display) => {
                const cleanTag = tag.trim();
                return `<span class="wiki-tag" data-tag="${cleanTag}">${display}</span>`;
            })

            // Handle simple wiki links, preserving special characters
            .replace(/\[\[([^\]]+)\]\]/g, (match, tag) => {
                const cleanTag = tag.trim();
                return `<span class="wiki-tag" data-tag="${cleanTag}">${cleanTag}</span>`;
            })

            // Handle BBCode
            .replace(/\[b\](.*?)\[\/b\]/g, '<strong>$1</strong>')
            .replace(/\[i\](.*?)\[\/i\]/g, '<em>$1</em>')
            .replace(/\[code\](.*?)\[\/code\]/g, '<code>$1</code>')
            .replace(/\[u\](.*?)\[\/u\]/g, '<u>$1</u>')

            // Handle headers with proper spacing
            .replace(/^h([1-6])\.\s*(.+)$/gm, (_, size, content) => `\n<h${size}>${content}</h${size}>\n`)

            // Add spacing after tag name at start of line
        // Handle line breaks and paragraphs
        text = text
            .replace(/\r\n/g, '\n')  // Normalize line endings
            .replace(/\n\n+/g, '</p><p>')
            .replace(/\n/g, '<br>');

        // Wrap lists in ul tags
        text = text.replace(/(<li>.*?<\/li>)\s*(?=<li>|$)/gs, '<ul>$1</ul>');

        // Wrap in paragraph if not already wrapped
        if (!text.startsWith('<p>')) {
            text = `<p>${text}</p>`;
        }

        return text;
    }

    // Separate the keyboard handler into its own function
    function handleWikiKeydown(e) {
        if (wikiOverlay.style.display === 'block') {
            if (e.key === 'ArrowLeft') navigateImage(-1);
            if (e.key === 'ArrowRight') navigateImage(1);
        }
    }

    function attachWikiEventListeners() {
        const prevButton = wikiContent.querySelector('.image-nav-button.prev');
        const nextButton = wikiContent.querySelector('.image-nav-button.next');
        const viewButton = wikiContent.querySelector('.view-on-danbooru');
        const wikiImage = wikiContent.querySelector('.wiki-image');
        const wikiTags = wikiContent.querySelectorAll('.wiki-tag');

        // Only attach image navigation related listeners if we have posts
        if (currentPosts.length > 0) {
            if (prevButton) {
                prevButton.addEventListener('click', () => navigateImage(-1));
            }
            if (nextButton) {
                nextButton.addEventListener('click', () => navigateImage(1));
            }

            // Add keyboard navigation only if we have posts
            document.removeEventListener('keydown', handleWikiKeydown);
            document.addEventListener('keydown', handleWikiKeydown);

            if (wikiImage) {
                wikiImage.addEventListener('click', () => {
                    if (currentPosts[currentPostIndex]) {
                        window.open(currentPosts[currentPostIndex].large_file_url, '_blank');
                    }
                });
            }

            if (viewButton) {
                viewButton.addEventListener('click', () => {
                    if (currentPosts[currentPostIndex]) {
                        window.open(`https://danbooru.donmai.us/posts/${currentPosts[currentPostIndex].id}`, '_blank');
                    }
                });
            }
        }

        // Wiki tag navigation works regardless of posts
        if (wikiTags) {
            wikiTags.forEach(tag => {
                tag.addEventListener('click', () => {
                    const tagName = tag.dataset.tag;
                    loadWikiInfo(tagName);
                });
            });
        }
    }

    function displayPostImage(post) {
        const imageContainer = wikiContent.querySelector('.wiki-image-container');
        if (!imageContainer) return; // Guard against missing container

        if (!post || (!post.preview_file_url && !post.file_url)) return;

        const prevButton = imageContainer.querySelector('.image-nav-button.prev');
        const nextButton = imageContainer.querySelector('.image-nav-button.next');
        const image = imageContainer.querySelector('.wiki-image');

        if (!image) return; // Guard against missing image element

        image.src = post.large_file_url || post.preview_file_url || post.file_url;

        if (prevButton) prevButton.style.visibility = currentPostIndex <= 0 ? 'hidden' : 'visible';
        if (nextButton) nextButton.style.visibility = currentPostIndex >= currentPosts.length - 1 ? 'hidden' : 'visible';

        // Remove any existing event listeners first to prevent duplicates
        const newPrevButton = prevButton.cloneNode(true);
        const newNextButton = nextButton.cloneNode(true);

        prevButton.parentNode.replaceChild(newPrevButton, prevButton);
        nextButton.parentNode.replaceChild(newNextButton, nextButton);

        // Attach fresh event listeners
        newPrevButton.addEventListener('click', (e) => {
            e.stopPropagation();
            navigateImage(-1);
        });

        newNextButton.addEventListener('click', (e) => {
            e.stopPropagation();
            navigateImage(1);
        });

        // Reattach image click listener
        image.addEventListener('click', () => {
            window.open(post.large_file_url || post.file_url, '_blank');
        });
    }

    function navigateImage(direction) {
        const newIndex = currentPostIndex + direction;
        if (newIndex >= 0 && newIndex < currentPosts.length) {
            currentPostIndex = newIndex;
            displayPostImage(currentPosts[newIndex]);
        }
    }

    // Add new function for wiki search autocomplete
    function setupWikiSearchAutocomplete(searchBar) {
        const suggestionsBox = document.createElement('div');
        suggestionsBox.className = 'wiki-search-suggestions';
        suggestionsBox.style.display = 'none';
        document.body.appendChild(suggestionsBox); // Append to body instead

        let selectedIndex = -1;

        // Update suggestions box position when showing
        function updateSuggestionsPosition() {
            const searchBarRect = searchBar.getBoundingClientRect();
            suggestionsBox.style.top = `${searchBarRect.bottom + window.scrollY}px`;
        }

        searchBar.addEventListener('input', () => {
            const term = searchBar.value.replace(/\s+/g, '_').trim();
            if (term) {
                fetchSuggestionsForWiki(term, suggestionsBox);
                updateSuggestionsPosition();
            } else {
                suggestionsBox.style.display = 'none';
            }
        });

        // Update position on scroll or resize
        window.addEventListener('scroll', () => {
            if (suggestionsBox.style.display === 'block') {
                updateSuggestionsPosition();
            }
        });

        window.addEventListener('resize', () => {
            if (suggestionsBox.style.display === 'block') {
                updateSuggestionsPosition();
            }
        });

        searchBar.addEventListener('keydown', (e) => {
            const suggestions = suggestionsBox.children;
            if (suggestions.length === 0) return;

            if (e.key === 'ArrowDown') {
                e.preventDefault();
                selectedIndex = Math.min(selectedIndex + 1, suggestions.length - 1);
                updateWikiSuggestionSelection(suggestions, selectedIndex);
            } else if (e.key === 'ArrowUp') {
                e.preventDefault();
                selectedIndex = Math.max(selectedIndex - 1, -1);
                updateWikiSuggestionSelection(suggestions, selectedIndex);
            } else if (e.key === 'Enter' && selectedIndex !== -1) {
                e.preventDefault();
                searchBar.value = suggestions[selectedIndex].textContent;
                suggestionsBox.style.display = 'none';
                loadWikiInfo(searchBar.value);
            }
        });

        // Close suggestions when clicking outside
        document.addEventListener('click', (e) => {
            if (!searchBar.contains(e.target) && !suggestionsBox.contains(e.target)) {
                suggestionsBox.style.display = 'none';
            }
        });
    }

    function fetchSuggestionsForWiki(term, suggestionsBox) {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            GM.xmlHttpRequest({
                method: 'GET',
                url: `https://gelbooru.com/index.php?page=autocomplete2&term=${encodeURIComponent(term)}&type=tag_query&limit=10`,
                onload: function(response) {
                    if (response.status === 200) {
                        try {
                            const data = JSON.parse(response.responseText);
                            showWikiSuggestions(data, suggestionsBox);
                        } catch (e) {
                            console.error("Error parsing suggestions:", e);
                        }
                    }
                }
            });
        }, debounceDelay);
    }

    function showWikiSuggestions(suggestions, suggestionsBox) {
        suggestionsBox.innerHTML = '';
        if (suggestions.length === 0) {
            suggestionsBox.style.display = 'none';
            return;
        }

        suggestions.forEach(suggestion => {
            const div = document.createElement('div');
            div.className = 'wiki-search-suggestion';
            div.textContent = suggestion.label;
            div.addEventListener('click', () => {
                const searchBar = suggestionsBox.parentNode.querySelector('.wiki-search-bar');
                searchBar.value = suggestion.label;
                suggestionsBox.style.display = 'none';
                loadWikiInfo(suggestion.label);
            });
            suggestionsBox.appendChild(div);
        });

        suggestionsBox.style.display = 'block';
    }

    function updateWikiSuggestionSelection(suggestions, selectedIndex) {
        Array.from(suggestions).forEach((suggestion, index) => {
            suggestion.classList.toggle('selected', index === selectedIndex);
            if (index === selectedIndex) {
                suggestion.scrollIntoView({ block: 'nearest' });
            }
        });
    }

    // Ensure script runs as soon as DOM is ready
    document.addEventListener('DOMContentLoaded', () => {
        loadSettings();
        setupAutocomplete();
        initializeWiki();
    });

})();