🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

Smart Grammar Fixer Pro

Smart grammar fixing with LanguageTool and language detection

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

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

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

// ==UserScript==
// @name         Smart Grammar Fixer Pro
// @namespace    http://tampermonkey.net/
// @version      6.5
// @description  Smart grammar fixing with LanguageTool and language detection
// @author       You
// @match        *://*/*
// @exclude      https://docs.google.com/*
// @exclude      https://*.office.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @grant        unsafeWindow
// @connect      api.languagetool.org
// @connect      ws.detectlanguage.com
// @antifeature  none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // API Configuration
    const API_CONFIG = {
        languagetool: 'https://api.languagetool.org/v2/check',
        detectlanguage: 'https://ws.detectlanguage.com/0.2/detect'
    };

    // Language Support
    const LANGUAGE_SUPPORT = {
        'en-US': 'English (US)',
        'en-GB': 'English (GB)',
        'ar': 'Arabic',
        'de-DE': 'German',
        'fr-FR': 'French',
        'es-ES': 'Spanish',
        'it-IT': 'Italian',
        'pt-PT': 'Portuguese',
        'pt-BR': 'Portuguese (BR)',
        'nl-NL': 'Dutch',
        'ru-RU': 'Russian',
        'ja-JP': 'Japanese',
        'zh-CN': 'Chinese',
        'ko-KR': 'Korean',
        'pl-PL': 'Polish',
        'sv-SE': 'Swedish',
        'da-DK': 'Danish',
        'fi-FI': 'Finnish',
        'no-NO': 'Norwegian',
        'tr-TR': 'Turkish'
    };

    // Default settings
    const DEFAULT_SETTINGS = {
        // Core Behavior
        enabled: true,
        debugMode: false,

        // API Keys
        apiKeys: {
            detectlanguage: 'a40f80d21131976bdedf653088a12ce0'
        },

        // Language Configuration
        language: {
            main: 'en-US',
            fallback: 'en-US',
            autoDetect: true,
            confidenceThreshold: 0.7,
            forceLanguage: false,
            correctionLanguage: 'auto'
        },

        // Correction Settings
        correction: {
            autoFixOnSend: true,
            minTextLength: 3,
            maxTextLength: 5000,
            fixPunctuation: true,
            fixCapitalization: true,
            aggressiveCorrection: false
        },

        // User Interface
        ui: {
            showIcons: true,
            showNotifications: true,
            iconPosition: 'top-right',
            iconSize: 'medium',
            darkMode: 'auto',
            animations: true,
            showLoadingBar: true
        },

        // Shortcuts
        shortcuts: {
            smartFix: 'Alt+A',
            fixAndSend: 'Alt+Enter',
            quickFix: 'Alt+Q',
            toggleEnabled: 'Alt+Shift+G',
            openSettings: 'Alt+Shift+S'
        },

        // Domain-specific Rules
        domainRules: {
            'gmail.com': { autoFixOnSend: true },
            'outlook.com': { autoFixOnSend: true },
            'twitter.com': { minTextLength: 5 },
            'facebook.com': { minTextLength: 10 },
            'chat.openai.com': { enabled: false },
            'docs.google.com': { enabled: false }
        }
    };

    let settings = JSON.parse(JSON.stringify(DEFAULT_SETTINGS));
    let isProcessing = false;
    let currentDomain = window.location.hostname;
    let observedElements = new Set();
    let isRecordingShortcut = false;
    let currentRecordingInput = null;
    let mainObserver = null;

    // Inject styles
    function injectStyles() {
        const styles = `
            .grammar-helper-icon {
                position: absolute;
                width: 24px;
                height: 24px;
                background: #4CAF50;
                color: white;
                border-radius: 50%;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 11px;
                font-weight: bold;
                cursor: pointer;
                z-index: 10000;
                box-shadow: 0 2px 8px rgba(0,0,0,0.3);
                transition: all 0.3s ease;
                border: 2px solid white;
            }
            .grammar-helper-icon:hover {
                transform: scale(1.2);
                box-shadow: 0 4px 12px rgba(0,0,0,0.4);
            }
            .grammar-language-badge {
                position: absolute;
                top: -5px;
                right: -5px;
                background: #2196F3;
                color: white;
                border-radius: 50%;
                width: 16px;
                height: 16px;
                font-size: 9px;
                display: flex;
                align-items: center;
                justify-content: center;
                border: 1px solid white;
                font-weight: bold;
            }

            /* Loading bar container around text area */
            .grammar-loading-container {
                position: relative;
                transition: all 0.3s ease;
            }

            .grammar-loading-bar {
                position: absolute;
                top: -3px;
                left: -3px;
                right: -3px;
                bottom: -3px;
                border: 3px solid transparent;
                border-radius: 8px;
                background:
                    linear-gradient(white, white) padding-box,
                    linear-gradient(45deg, #4CAF50, #2196F3, #9C27B0, #4CAF50) border-box;
                background-size: 400% 400%;
                animation: loadingBorder 2s linear infinite, borderPulse 3s ease-in-out infinite;
                z-index: 9999;
                pointer-events: none;
                opacity: 0;
                transition: opacity 0.3s ease;
            }

            .grammar-loading-bar.show {
                opacity: 1;
            }

            .grammar-loading-bar.processing::before {
                content: '';
                position: absolute;
                top: -3px;
                left: -3px;
                right: -3px;
                height: 3px;
                background: linear-gradient(90deg, #4CAF50, #2196F3, #9C27B0, #4CAF50);
                background-size: 400% 100%;
                animation: loadingProgress 2s linear infinite;
                border-radius: 8px 8px 0 0;
            }

            .grammar-loading-bar.processing::after {
                content: 'Fixing grammar...';
                position: absolute;
                top: -30px;
                left: 50%;
                transform: translateX(-50%);
                background: #333;
                color: white;
                padding: 4px 8px;
                border-radius: 4px;
                font-size: 11px;
                font-family: Arial, sans-serif;
                white-space: nowrap;
                z-index: 10001;
                animation: fadeIn 0.3s ease;
            }

            @keyframes loadingBorder {
                0% {
                    background-position: 0% 50%;
                }
                50% {
                    background-position: 100% 50%;
                }
                100% {
                    background-position: 0% 50%;
                }
            }

            @keyframes borderPulse {
                0%, 100% {
                    box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.4);
                }
                50% {
                    box-shadow: 0 0 0 4px rgba(76, 175, 80, 0.2);
                }
            }

            @keyframes loadingProgress {
                0% {
                    background-position: 0% 50%;
                    width: 0%;
                }
                50% {
                    background-position: 100% 50%;
                    width: 100%;
                }
                100% {
                    background-position: 0% 50%;
                    width: 0%;
                }
            }

            @keyframes fadeIn {
                from { opacity: 0; }
                to { opacity: 1; }
            }

            /* Enhanced notification animations */
            .grammar-notification {
                position: absolute;
                background: #4CAF50;
                color: white;
                padding: 8px 12px;
                border-radius: 6px;
                font-size: 12px;
                font-family: Arial, sans-serif;
                z-index: 10002;
                box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                max-width: 200px;
                white-space: nowrap;
                transform: translateY(-20px);
                opacity: 0;
            }
            .grammar-notification.error {
                background: #f44336;
            }
            .grammar-notification.warning {
                background: #FF9800;
            }
            .grammar-notification.info {
                background: #2196F3;
            }
            .grammar-notification.processing {
                background: #9C27B0;
            }
            .grammar-notification.success {
                background: #4CAF50;
            }

            /* Animation classes */
            .grammar-notification.show {
                animation: slideInBounce 0.5s ease-out forwards;
            }
            .grammar-notification.hide {
                animation: slideOutUp 0.3s ease-in forwards;
            }

            /* Processing animation */
            .grammar-notification.processing::after {
                content: '';
                position: absolute;
                bottom: 0;
                left: 0;
                height: 3px;
                background: rgba(255,255,255,0.7);
                border-radius: 0 0 6px 6px;
                animation: processingBar 2s linear infinite;
            }

            @keyframes slideInBounce {
                0% {
                    transform: translateY(-20px);
                    opacity: 0;
                }
                60% {
                    transform: translateY(5px);
                    opacity: 1;
                }
                100% {
                    transform: translateY(0);
                    opacity: 1;
                }
            }

            @keyframes slideOutUp {
                0% {
                    transform: translateY(0);
                    opacity: 1;
                }
                100% {
                    transform: translateY(-20px);
                    opacity: 0;
                }
            }

            @keyframes processingBar {
                0% {
                    width: 0%;
                }
                50% {
                    width: 100%;
                }
                100% {
                    width: 0%;
                }
            }

            /* Pulse animation for icon when processing */
            .grammar-helper-icon.processing {
                animation: pulse 1.5s ease-in-out infinite;
            }

            @keyframes pulse {
                0% {
                    transform: scale(1);
                    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
                }
                50% {
                    transform: scale(1.1);
                    box-shadow: 0 4px 16px rgba(76, 175, 80, 0.4);
                }
                100% {
                    transform: scale(1);
                    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
                }
            }

            .grammar-global-notification {
                position: fixed;
                top: 20px;
                right: 20px;
                background: #2196F3;
                color: white;
                padding: 12px 16px;
                border-radius: 8px;
                z-index: 100000;
                box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                font-family: Arial, sans-serif;
                font-size: 14px;
                max-width: 400px;
                word-wrap: break-word;
                transform: translateX(100%);
                transition: transform 0.3s ease;
            }
            .grammar-global-notification.show {
                transform: translateX(0);
            }
            .grammar-global-notification.success {
                background: #4CAF50;
            }
            .grammar-global-notification.error {
                background: #f44336;
            }
            .grammar-global-notification.warning {
                background: #FF9800;
            }
        `;

        const styleSheet = document.createElement('style');
        styleSheet.textContent = styles;
        document.head.appendChild(styleSheet);

        // Inject settings panel styles
        injectSettingsPanelStyles();
    }

    function injectSettingsPanelStyles() {
        const settingsStyles = `
        .grammar-settings-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.7);
            z-index: 99998;
            backdrop-filter: blur(5px);
            animation: fadeIn 0.3s ease;
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        .grammar-settings-panel {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%) scale(0.9);
            background: white;
            border-radius: 12px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
            z-index: 99999;
            width: 90%;
            max-width: 700px;
            max-height: 90vh;
            overflow: hidden;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            animation: scaleIn 0.3s ease forwards;
        }

        @keyframes scaleIn {
            to {
                transform: translate(-50%, -50%) scale(1);
            }
        }

        .grammar-settings-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 20px 24px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .grammar-settings-title h2 {
            margin: 0;
            font-size: 1.5em;
            font-weight: 600;
        }

        .grammar-settings-subtitle {
            opacity: 0.9;
            font-size: 0.9em;
            margin-top: 4px;
        }

        .grammar-settings-close {
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            font-size: 24px;
            cursor: pointer;
            padding: 0;
            width: 36px;
            height: 36px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: background 0.2s ease;
        }

        .grammar-settings-close:hover {
            background: rgba(255, 255, 255, 0.3);
        }

        .grammar-settings-content {
            padding: 24px;
            max-height: 60vh;
            overflow-y: auto;
        }

        .settings-section {
            margin-bottom: 24px;
            animation: slideDown 0.4s ease;
        }

        @keyframes slideDown {
            from {
                opacity: 0;
                transform: translateY(-10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .settings-section h3 {
            margin: 0 0 16px 0;
            font-size: 1.1em;
            color: #495057;
            border-bottom: 1px solid #e9ecef;
            padding-bottom: 8px;
        }

        .settings-row {
            display: flex;
            align-items: center;
            margin-bottom: 12px;
            padding: 8px 0;
        }

        .settings-row label {
            flex: 1;
            margin-right: 16px;
            font-size: 14px;
            color: #495057;
        }

        .settings-row input[type="text"],
        .settings-row input[type="password"],
        .settings-row input[type="number"],
        .settings-row select {
            padding: 8px 12px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 14px;
            min-width: 200px;
            transition: border-color 0.2s ease;
        }

        .settings-row input:focus,
        .settings-row select:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
        }

        .settings-row input[type="checkbox"] {
            margin-right: 8px;
            transform: scale(1.1);
        }

        .shortcut-input {
            background: #f8f9fa !important;
            cursor: pointer;
            min-width: 120px !important;
            text-align: center;
            font-family: monospace;
        }

        .shortcut-input.recording {
            background: #fff3cd !important;
            border-color: #ffc107;
            color: #856404;
        }

        .grammar-settings-footer {
            padding: 20px 24px;
            background: #f8f9fa;
            border-top: 1px solid #e9ecef;
            display: flex;
            justify-content: flex-end;
            gap: 12px;
        }

        .grammar-settings-btn {
            padding: 10px 20px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: all 0.2s ease;
        }

        .grammar-settings-btn.primary {
            background: #667eea;
            color: white;
        }

        .grammar-settings-btn.primary:hover {
            background: #5a6fd8;
            transform: translateY(-1px);
        }

        .grammar-settings-btn.secondary {
            background: #6c757d;
            color: white;
        }

        .grammar-settings-btn.secondary:hover {
            background: #5a6268;
            transform: translateY(-1px);
        }

        @media (max-width: 768px) {
            .grammar-settings-panel {
                width: 95%;
                height: 95vh;
            }

            .settings-row {
                flex-direction: column;
                align-items: flex-start;
            }

            .settings-row label {
                margin-bottom: 8px;
                margin-right: 0;
            }
        }
        `;

        const styleSheet = document.createElement('style');
        styleSheet.textContent = settingsStyles;
        document.head.appendChild(styleSheet);
    }

    // Initialize the script
    async function init() {
        try {
            console.log('🔄 Starting Grammar Fixer initialization...');
            await loadSettings();
            applyDomainSpecificRules();
            injectStyles();
            setupGlobalShortcuts();
            setupSmartElementObservers();
            registerMenuCommands();

            console.log('✅ Smart Grammar Fixer Pro initialized successfully');
            console.log('🌐 Current domain:', currentDomain);

            showGlobalNotification('Grammar Fixer Pro ready! Use ' + settings.shortcuts.smartFix + ' to fix grammar.', 'success', 3000);

        } catch (error) {
            console.error('❌ Failed to initialize grammar fixer:', error);
            showGlobalNotification('Grammar fixer failed to initialize', 'error');
        }
    }

    function applyDomainSpecificRules() {
        const domainRule = settings.domainRules[currentDomain];
        if (domainRule) {
            // Merge domain rules with current settings
            Object.keys(domainRule).forEach(key => {
                if (typeof settings[key] === 'object' && settings[key] !== null && typeof domainRule[key] === 'object') {
                    Object.assign(settings[key], domainRule[key]);
                } else {
                    settings[key] = domainRule[key];
                }
            });
            if (settings.debugMode) {
                console.log('🔧 Applied domain-specific rules for:', currentDomain, domainRule);
            }
        }
    }

    // Settings management
    async function loadSettings() {
        try {
            const savedSettings = await GM_getValue('grammarSettings');
            if (savedSettings) {
                // Deep merge settings
                settings = deepMerge(DEFAULT_SETTINGS, savedSettings);
            }
        } catch (error) {
            console.error('Error loading settings:', error);
            settings = JSON.parse(JSON.stringify(DEFAULT_SETTINGS));
        }
    }

    function deepMerge(target, source) {
        const result = { ...target };
        for (const key in source) {
            if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
                result[key] = deepMerge(target[key] || {}, source[key]);
            } else {
                result[key] = source[key];
            }
        }
        return result;
    }

    async function saveSettings() {
        try {
            await GM_setValue('grammarSettings', settings);
            return true;
        } catch (error) {
            console.error('Error saving settings:', error);
            showGlobalNotification('Failed to save settings', 'error');
            return false;
        }
    }

    // Menu commands
    function registerMenuCommands() {
        try {
            GM_registerMenuCommand('⚙️ Grammar Settings', showSettingsPanel);
            GM_registerMenuCommand('🔄 Toggle Enabled', toggleEnabled);
            GM_registerMenuCommand('📊 Status Info', showStatusInfo);
        } catch (error) {
            console.warn('Menu commands not available:', error);
        }
    }

    function toggleEnabled() {
        settings.enabled = !settings.enabled;
        saveSettings();
        showGlobalNotification(`Grammar fixer ${settings.enabled ? 'enabled' : 'disabled'}`);

        if (!settings.enabled) {
            removeAllUIElements();
            if (mainObserver) {
                mainObserver.disconnect();
            }
        } else {
            setupSmartElementObservers();
            setTimeout(() => {
                scanForWritableElements();
            }, 1000);
        }
    }

    function showStatusInfo() {
        const status = `
Status: ${settings.enabled ? '✅ Enabled' : '❌ Disabled'}
Domain: ${currentDomain}
Main Language: ${settings.language.main}
Correction Language: ${settings.language.correctionLanguage}
Auto-detect: ${settings.language.autoDetect ? '✅' : '❌'}
Loading Bar: ${settings.ui.showLoadingBar ? '✅ Enabled' : '❌ Disabled'}
Observed Elements: ${observedElements.size}
Shortcuts: ${Object.values(settings.shortcuts).join(', ')}
        `.trim();

        showGlobalNotification(status, 'info', 5000);
    }

    // Shortcuts
    function setupGlobalShortcuts() {
        document.addEventListener('keydown', function(e) {
            if (!settings.enabled) return;

            const activeEl = document.activeElement;
            if (!isWritableElement(activeEl)) return;

            // Smart Fix
            if (checkShortcut(e, settings.shortcuts.smartFix)) {
                e.preventDefault();
                e.stopPropagation();
                handleSmartGrammarFix(activeEl);
            }

            // Fix and Send
            if (checkShortcut(e, settings.shortcuts.fixAndSend)) {
                e.preventDefault();
                e.stopPropagation();
                handleFixAndSend(activeEl);
            }

            // Quick Fix
            if (checkShortcut(e, settings.shortcuts.quickFix)) {
                e.preventDefault();
                e.stopPropagation();
                handleQuickFix(activeEl);
            }

            // Toggle Enabled
            if (checkShortcut(e, settings.shortcuts.toggleEnabled)) {
                e.preventDefault();
                e.stopPropagation();
                toggleEnabled();
            }

            // Open Settings
            if (checkShortcut(e, settings.shortcuts.openSettings)) {
                e.preventDefault();
                e.stopPropagation();
                showSettingsPanel();
            }
        }, true);
    }

    function checkShortcut(event, shortcut) {
        const keys = shortcut.split('+');
        let match = true;

        keys.forEach(key => {
            key = key.trim().toLowerCase();
            if (key === 'alt' && !event.altKey) match = false;
            else if (key === 'ctrl' && !event.ctrlKey) match = false;
            else if (key === 'shift' && !event.shiftKey) match = false;
            else if (key === 'enter' && event.key !== 'Enter') match = false;
            else if (key.length === 1 && event.key.toLowerCase() !== key) match = false;
            else if (key.length > 1 && !['alt', 'ctrl', 'shift', 'enter'].includes(key)) {
                // Handle special keys
                if (key === 'space' && event.key !== ' ') match = false;
                else if (event.key.toLowerCase() !== key) match = false;
            }
        });

        return match;
    }

    // Keyboard Shortcut Recording
    function setupShortcutRecording() {
        document.addEventListener('keydown', function(e) {
            if (!isRecordingShortcut || !currentRecordingInput) return;

            e.preventDefault();
            e.stopPropagation();

            const keys = [];
            if (e.ctrlKey) keys.push('Ctrl');
            if (e.altKey) keys.push('Alt');
            if (e.shiftKey) keys.push('Shift');

            // Don't include modifier keys alone
            if (!['Control', 'Alt', 'Shift', 'Meta'].includes(e.key)) {
                let key = e.key;
                if (key === ' ') key = 'Space';
                else if (key.length === 1) key = key.toUpperCase();

                keys.push(key);

                // Set the shortcut
                const shortcutName = currentRecordingInput.dataset.shortcut;
                if (shortcutName && keys.length > 0) {
                    const shortcutString = keys.join('+');
                    currentRecordingInput.value = shortcutString;
                    settings.shortcuts[shortcutName] = shortcutString;

                    // Stop recording
                    stopShortcutRecording();
                }
            }
        }, true);

        // Stop recording when clicking elsewhere
        document.addEventListener('click', function(e) {
            if (isRecordingShortcut && currentRecordingInput && !currentRecordingInput.contains(e.target)) {
                stopShortcutRecording();
            }
        }, true);
    }

    function startShortcutRecording(input, shortcutName) {
        if (isRecordingShortcut) {
            stopShortcutRecording();
        }

        isRecordingShortcut = true;
        currentRecordingInput = input;
        input.classList.add('recording');
        input.value = 'Press shortcut...';

        showGlobalNotification('Press a key combination for the shortcut...', 'info', 2000);
    }

    function stopShortcutRecording() {
        if (currentRecordingInput) {
            currentRecordingInput.classList.remove('recording');

            // Restore the current shortcut value
            const shortcutName = currentRecordingInput.dataset.shortcut;
            if (shortcutName && settings.shortcuts[shortcutName]) {
                currentRecordingInput.value = settings.shortcuts[shortcutName];
            }
        }

        isRecordingShortcut = false;
        currentRecordingInput = null;
    }

    function handleQuickFix(element) {
        if (!settings.enabled || isProcessing) return;

        const text = getElementText(element);
        if (text.length < settings.correction.minTextLength) return;

        fixWithLanguageTool(text, settings.language.main)
            .then(fixedText => {
                setElementText(element, fixedText);
                showNotification(element, 'Quick fix applied', 'success');
            })
            .catch(error => {
                console.error('Quick fix error:', error);
                showNotification(element, 'Quick fix failed', 'error');
            });
    }

    // Smart Element Detection - IMPROVED VERSION
    function setupSmartElementObservers() {
        if (!settings.enabled || !settings.ui.showIcons) return;

        // Clean up any existing observers
        if (mainObserver) {
            mainObserver.disconnect();
        }

        // Initial scan
        scanForWritableElements();

        // Observe DOM changes for elements being removed
        mainObserver = new MutationObserver((mutations) => {
            if (!settings.enabled) return;

            for (const mutation of mutations) {
                // Handle removed nodes - Clean up icons for removed elements
                if (mutation.removedNodes.length > 0) {
                    mutation.removedNodes.forEach(node => {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            // Remove icon if the element itself was removed
                            if (observedElements.has(node)) {
                                removeIconFromElement(node);
                            }

                            // Remove icons for any child elements that were removed
                            const childElements = findWritableElements(node);
                            childElements.forEach(childElement => {
                                if (observedElements.has(childElement)) {
                                    removeIconFromElement(childElement);
                                }
                            });
                        }
                    });
                }

                // Handle added nodes
                if (mutation.addedNodes.length > 0) {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            // Check the node itself
                            if (isWritableElement(node)) {
                                addSmartIconToElement(node);
                            }
                            // Check all writable elements within the node
                            const writableElements = findWritableElements(node);
                            writableElements.forEach(addSmartIconToElement);
                        }
                    });
                }

                // Handle attribute changes (like when contenteditable becomes true/false)
                if (mutation.type === 'attributes' &&
                    (mutation.attributeName === 'contenteditable' ||
                     mutation.attributeName === 'disabled' ||
                     mutation.attributeName === 'readonly' ||
                     mutation.attributeName === 'style' ||
                     mutation.attributeName === 'class')) {

                    if (isWritableElement(mutation.target)) {
                        addSmartIconToElement(mutation.target);
                    } else {
                        removeIconFromElement(mutation.target);
                    }
                }
            }
        });

        mainObserver.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeFilter: ['contenteditable', 'disabled', 'readonly', 'style', 'class']
        });

        // Also observe focus and blur events to catch dynamic elements
        document.addEventListener('focusin', handleFocusIn, true);
        document.addEventListener('focusout', handleFocusOut, true);

        // Handle page navigation in single-page applications
        setupSPANavigationHandler();
    }

    function handleFocusIn(e) {
        if (isWritableElement(e.target)) {
            addSmartIconToElement(e.target);
        }
    }

    function handleFocusOut(e) {
        // Don't immediately remove on blur - keep it visible but check if element still exists
        setTimeout(() => {
            if (!document.body.contains(e.target)) {
                removeIconFromElement(e.target);
            }
        }, 100);
    }

    function setupSPANavigationHandler() {
        // Handle Single Page Application navigation
        let currentUrl = window.location.href;

        const checkUrlChange = () => {
            if (window.location.href !== currentUrl) {
                currentUrl = window.location.href;
                console.log('🔗 URL changed, cleaning up icons');
                cleanupOrphanedIcons();
                setTimeout(scanForWritableElements, 500);
            }
        };

        // Check for URL changes periodically
        setInterval(checkUrlChange, 1000);

        // Also listen for pushState and replaceState (common in SPAs)
        const originalPushState = history.pushState;
        const originalReplaceState = history.replaceState;

        history.pushState = function(...args) {
            originalPushState.apply(this, args);
            setTimeout(() => {
                console.log('🔗 pushState detected, cleaning up icons');
                cleanupOrphanedIcons();
                setTimeout(scanForWritableElements, 500);
            }, 100);
        };

        history.replaceState = function(...args) {
            originalReplaceState.apply(this, args);
            setTimeout(() => {
                console.log('🔗 replaceState detected, cleaning up icons');
                cleanupOrphanedIcons();
                setTimeout(scanForWritableElements, 500);
            }, 100);
        };
    }

    function cleanupOrphanedIcons() {
        // Remove icons for elements that no longer exist in the DOM
        observedElements.forEach(element => {
            if (!document.body.contains(element)) {
                removeIconFromElement(element);
            }
        });
    }

    function scanForWritableElements() {
        if (!settings.enabled) return;

        const writableElements = findWritableElements(document.body);
        console.log(`🔍 Found ${writableElements.length} writable elements`);

        writableElements.forEach(element => {
            addSmartIconToElement(element);
        });

        // Clean up any orphaned icons
        cleanupOrphanedIcons();
    }

    function findWritableElements(root = document) {
        const selectors = [
            'textarea',
            'input[type="text"]',
            'input[type="email"]',
            'input[type="search"]',
            'input[type="url"]',
            'input[type="password"]',
            'input:not([type])', // Inputs without type attribute (defaults to text)
            '[contenteditable="true"]',
            '[contenteditable=""]', // contenteditable without value also means true
            '.editable',
            '.text-input',
            '.composer',
            '.message-input',
            '.chat-input',
            '.post-input',
            '.comment-input'
        ];

        const elements = Array.from(root.querySelectorAll(selectors.join(',')));

        // Filter to only actually writable elements
        return elements.filter(element => isWritableElement(element));
    }

    function isWritableElement(element) {
        if (!element || !element.nodeName) return false;

        // Skip hidden or disabled elements
        if (element.offsetWidth === 0 || element.offsetHeight === 0) return false;
        if (element.disabled) return false;
        if (element.readOnly) return false;

        // Check computed style for visibility
        const style = window.getComputedStyle(element);
        if (style.visibility === 'hidden' || style.display === 'none') return false;

        // Check for common hidden patterns
        if (element.closest('[style*="display: none"], [style*="visibility: hidden"]')) return false;

        // Specific element type checks
        if (element.nodeName === 'TEXTAREA') return true;

        if (element.nodeName === 'INPUT') {
            const type = element.type.toLowerCase();
            const writableTypes = ['text', 'email', 'search', 'url', 'password', 'tel'];
            return writableTypes.includes(type) || !type; // No type defaults to text
        }

        // Contenteditable elements
        if (element.isContentEditable) {
            // Make sure it's not just a container but actually editable
            return element.closest('[contenteditable="false"]') === null;
        }

        // Common class patterns for editable areas
        const editableClasses = ['editable', 'text-input', 'composer', 'message-input', 'chat-input', 'post-input', 'comment-input'];
        if (editableClasses.some(className => element.classList.contains(className))) {
            return true;
        }

        return false;
    }

    function addSmartIconToElement(element) {
        if (!settings.ui.showIcons) return;
        if (observedElements.has(element)) return;
        if (!isWritableElement(element)) return;

        const rect = element.getBoundingClientRect();
        if (rect.width === 0 || rect.height === 0) return;

        // Don't add to very small elements (like search boxes)
        if (rect.width < 100 || rect.height < 20) return;

        const icon = createSmartIcon(element);
        positionIcon(icon, element);
        document.body.appendChild(icon);

        observedElements.add(element);
        element._grammarIcon = icon;

        if (settings.debugMode) {
            console.log('➕ Added icon to element:', element);
        }
    }

    function removeIconFromElement(element) {
        if (element._grammarIcon) {
            if (element._grammarIcon._cleanup) {
                element._grammarIcon._cleanup();
            }
            element._grammarIcon.remove();
            delete element._grammarIcon;
        }
        observedElements.delete(element);

        if (settings.debugMode) {
            console.log('➖ Removed icon from element:', element);
        }
    }

    function createSmartIcon(element) {
        const icon = document.createElement('div');
        icon.className = 'grammar-helper-icon';
        icon.innerHTML = 'A<div class="grammar-language-badge">LT</div>';
        icon.title = `Fix Grammar (${settings.shortcuts.smartFix})`;

        icon.addEventListener('click', async (e) => {
            e.stopPropagation();
            const text = getElementText(element);
            if (text.trim()) {
                await handleSmartGrammarFix(element);
            }
        });

        return icon;
    }

    function positionIcon(icon, element) {
        const updatePosition = () => {
            // Check if element still exists and is visible
            if (!document.body.contains(element)) {
                removeIconFromElement(element);
                return;
            }

            const rect = element.getBoundingClientRect();
            const scrollX = window.scrollX || window.pageXOffset;
            const scrollY = window.scrollY || window.pageYOffset;

            if (rect.width === 0 || rect.height === 0) {
                icon.style.display = 'none';
                return;
            }

            icon.style.display = 'flex';

            const top = rect.top + scrollY - 30;
            const left = rect.right + scrollX - 30;

            icon.style.top = top + 'px';
            icon.style.left = left + 'px';
        };

        updatePosition();

        // Update position on scroll and resize
        const debouncedUpdate = debounce(updatePosition, 100);
        window.addEventListener('scroll', debouncedUpdate);
        window.addEventListener('resize', debouncedUpdate);

        // Also update when element moves (for dynamic content)
        const elementObserver = new MutationObserver(debouncedUpdate);
        if (element.parentNode) {
            elementObserver.observe(element, {
                attributes: true,
                attributeFilter: ['style', 'class']
            });
        }

        icon._cleanup = () => {
            window.removeEventListener('scroll', debouncedUpdate);
            window.removeEventListener('resize', debouncedUpdate);
            elementObserver.disconnect();
        };
    }

    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }

    function removeAllUIElements() {
        document.querySelectorAll('.grammar-helper-icon, .grammar-notification, .grammar-loading-bar, .grammar-loading-container')
            .forEach(el => {
                if (el._cleanup) el._cleanup();
                el.remove();
            });

        observedElements.forEach(element => {
            delete element._grammarIcon;
        });
        observedElements.clear();
    }

    // Loading Bar Functions
    function showLoadingBar(element) {
        if (!settings.ui.showLoadingBar) return;

        // Remove existing loading bar
        hideLoadingBar(element);

        // Create loading container if needed
        let container = element.parentNode;
        if (!container.classList.contains('grammar-loading-container')) {
            const newContainer = document.createElement('div');
            newContainer.className = 'grammar-loading-container';
            element.parentNode.insertBefore(newContainer, element);
            newContainer.appendChild(element);
            container = newContainer;
        }

        // Create loading bar
        const loadingBar = document.createElement('div');
        loadingBar.className = 'grammar-loading-bar processing';
        container.appendChild(loadingBar);

        // Show with animation
        setTimeout(() => {
            loadingBar.classList.add('show');
        }, 10);

        return loadingBar;
    }

    function hideLoadingBar(element) {
        if (!settings.ui.showLoadingBar) return;

        const container = element.closest('.grammar-loading-container');
        if (container) {
            const loadingBar = container.querySelector('.grammar-loading-bar');
            if (loadingBar) {
                loadingBar.classList.remove('show');
                setTimeout(() => {
                    if (loadingBar.parentNode) {
                        loadingBar.remove();
                    }
                }, 300);
            }
        }
    }

    // Core Grammar Functions
    async function handleSmartGrammarFix(element) {
        if (isProcessing) {
            showNotification(element, 'Already fixing grammar...', 'warning');
            return;
        }

        isProcessing = true;

        const text = getElementText(element);
        if (!text.trim() || text.length < settings.correction.minTextLength) {
            showNotification(element, 'Text too short to fix', 'warning');
            isProcessing = false;
            return;
        }

        if (text.length > settings.correction.maxTextLength) {
            showNotification(element, 'Text too long to fix', 'warning');
            isProcessing = false;
            return;
        }

        let loadingBar = null;

        try {
            // Add processing animation to icon
            const icon = element._grammarIcon;
            if (icon && settings.ui.animations) {
                icon.classList.add('processing');
            }

            // Show loading bar around text area
            loadingBar = showLoadingBar(element);

            showNotification(element, 'Fixing grammar...', 'processing');

            let languageCode = settings.language.correctionLanguage;

            // Auto-detect language if set to auto
            if (languageCode === 'auto') {
                if (settings.language.autoDetect && settings.apiKeys.detectlanguage) {
                    try {
                        const detectedLang = await detectLanguage(text);
                        languageCode = detectedLang.code;
                        console.log(`🌍 Detected language: ${detectedLang.name} (${detectedLang.code})`);
                    } catch (error) {
                        console.warn('Language detection failed, using main language:', error);
                        languageCode = settings.language.main;
                    }
                } else {
                    languageCode = settings.language.main;
                }
            }

            const fixedText = await fixWithLanguageTool(text, languageCode);
            setElementText(element, fixedText);

            // Remove processing animation
            if (icon && settings.ui.animations) {
                icon.classList.remove('processing');
            }

            // Hide loading bar
            hideLoadingBar(element);

            showNotification(element, `Grammar fixed! (${LANGUAGE_SUPPORT[languageCode] || languageCode})`, 'success');

        } catch (error) {
            console.error('Smart grammar fix error:', error);

            // Remove processing animation on error
            const icon = element._grammarIcon;
            if (icon && settings.ui.animations) {
                icon.classList.remove('processing');
            }

            // Hide loading bar on error
            hideLoadingBar(element);

            showNotification(element, 'Failed to fix grammar', 'error');
        } finally {
            isProcessing = false;
        }
    }

    async function detectLanguage(text) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'POST',
                url: API_CONFIG.detectlanguage,
                headers: {
                    'Authorization': `Bearer ${settings.apiKeys.detectlanguage}`,
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify({ q: text }),
                timeout: 10000,
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.data && data.data.detections && data.data.detections.length > 0) {
                            const detection = data.data.detections[0];
                            if (detection.confidence >= settings.language.confidenceThreshold) {
                                const langName = LANGUAGE_SUPPORT[detection.language] || detection.language;
                                resolve({
                                    code: detection.language,
                                    name: langName,
                                    confidence: detection.confidence
                                });
                            } else {
                                reject('Language detection confidence too low: ' + detection.confidence);
                            }
                        } else {
                            reject('No language detections found');
                        }
                    } catch (e) {
                        reject('Error parsing language detection response: ' + e);
                    }
                },
                onerror: reject,
                ontimeout: () => reject('Language detection timeout')
            });
        });
    }

    async function fixWithLanguageTool(text, languageCode) {
        return new Promise((resolve, reject) => {
            const params = new URLSearchParams();
            params.append('text', text);
            params.append('language', languageCode);
            params.append('enabledOnly', 'false');

            GM_xmlhttpRequest({
                method: 'POST',
                url: API_CONFIG.languagetool,
                data: params.toString(),
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                timeout: 15000,
                onload: function(response) {
                    try {
                        if (response.status !== 200) {
                            reject(`LanguageTool API error: ${response.status}`);
                            return;
                        }

                        const result = JSON.parse(response.responseText);
                        let fixedText = text;

                        if (result.matches && result.matches.length > 0) {
                            // Sort matches by offset in reverse order to avoid position shifts
                            const matches = [...result.matches].sort((a, b) => b.offset - a.offset);

                            for (const match of matches) {
                                if (match.replacements && match.replacements.length > 0) {
                                    const replacement = match.replacements[0].value;
                                    const before = fixedText.substring(0, match.offset);
                                    const after = fixedText.substring(match.offset + match.length);
                                    fixedText = before + replacement + after;
                                }
                            }
                        }

                        resolve(fixedText);
                    } catch (e) {
                        reject('Error parsing LanguageTool response: ' + e);
                    }
                },
                onerror: reject,
                ontimeout: () => reject('LanguageTool request timeout')
            });
        });
    }

    async function handleFixAndSend(element) {
        await handleSmartGrammarFix(element);
        if (settings.correction.autoFixOnSend) {
            setTimeout(() => clickSendButton(element), 500);
        }
    }

    function clickSendButton(element) {
        const sendSelectors = [
            'button[type="submit"]', 'input[type="submit"]',
            'button[data-testid*="send"]', 'button[data-testid*="submit"]',
            '[aria-label*="send" i]', '[aria-label*="submit" i]'
        ];

        let sendButton = null;
        const form = element.closest('form');

        if (form) {
            for (const selector of sendSelectors) {
                sendButton = form.querySelector(selector);
                if (sendButton && sendButton.offsetParent !== null) break;
            }
        }

        if (sendButton) {
            sendButton.click();
            return true;
        }

        return false;
    }

    // Utility Functions
    function getElementText(element) {
        if (element.nodeName === 'TEXTAREA' || element.nodeName === 'INPUT') {
            return element.value;
        } else {
            return element.textContent || element.innerText || '';
        }
    }

    function setElementText(element, text) {
        if (element.nodeName === 'TEXTAREA' || element.nodeName === 'INPUT') {
            element.value = text;
        } else {
            element.textContent = text;
        }

        // Trigger events to notify the page of the change
        const inputEvent = new Event('input', { bubbles: true });
        const changeEvent = new Event('change', { bubbles: true });
        element.dispatchEvent(inputEvent);
        element.dispatchEvent(changeEvent);
    }

    function showNotification(element, message, type = 'info') {
        if (!settings.ui.showNotifications) return;

        // Remove existing notification
        const existingNotification = document.querySelector('.grammar-notification');
        if (existingNotification) {
            if (settings.ui.animations) {
                existingNotification.classList.add('hide');
                setTimeout(() => existingNotification.remove(), 300);
            } else {
                existingNotification.remove();
            }
        }

        const notification = document.createElement('div');
        notification.className = `grammar-notification ${type}`;
        notification.textContent = message;

        const rect = element.getBoundingClientRect();
        const scrollX = window.scrollX || window.pageXOffset;
        const scrollY = window.scrollY || window.pageYOffset;

        notification.style.top = (rect.top + scrollY - 40) + 'px';
        notification.style.left = (rect.right + scrollX - 10) + 'px';

        document.body.appendChild(notification);

        // Add show animation
        if (settings.ui.animations) {
            setTimeout(() => {
                notification.classList.add('show');
            }, 10);

            // Auto hide after 3 seconds
            setTimeout(() => {
                notification.classList.add('hide');
                setTimeout(() => {
                    if (notification.parentNode) notification.remove();
                }, 300);
            }, 3000);
        } else {
            // No animation - just remove after 3 seconds
            setTimeout(() => {
                if (notification.parentNode) notification.remove();
            }, 3000);
        }
    }

    function showGlobalNotification(message, type = 'info', duration = 3000) {
        if (!settings.ui.showNotifications) return;

        const notification = document.createElement('div');
        notification.className = `grammar-global-notification ${type}`;
        notification.textContent = message;

        document.body.appendChild(notification);

        if (settings.ui.animations) {
            setTimeout(() => {
                notification.classList.add('show');
            }, 10);

            setTimeout(() => {
                notification.classList.remove('show');
                setTimeout(() => {
                    if (notification.parentNode) notification.remove();
                }, 300);
            }, duration);
        } else {
            setTimeout(() => {
                if (notification.parentNode) notification.remove();
            }, duration);
        }
    }

    // Settings Panel
    function showSettingsPanel() {
        // Remove existing settings panel if any
        const existingPanel = document.querySelector('.grammar-settings-overlay');
        if (existingPanel) existingPanel.remove();

        // Create overlay
        const overlay = document.createElement('div');
        overlay.className = 'grammar-settings-overlay';

        // Create settings panel
        const panel = document.createElement('div');
        panel.className = 'grammar-settings-panel';

        // Header
        const header = document.createElement('div');
        header.className = 'grammar-settings-header';
        header.innerHTML = `
            <div class="grammar-settings-title">
                <h2>Smart Grammar Fixer Pro</h2>
                <div class="grammar-settings-subtitle">Version 6.5</div>
            </div>
            <button class="grammar-settings-close">&times;</button>
        `;

        // Content
        const content = document.createElement('div');
        content.className = 'grammar-settings-content';
        content.innerHTML = createSettingsContent();

        // Footer
        const footer = document.createElement('div');
        footer.className = 'grammar-settings-footer';
        footer.innerHTML = `
            <button class="grammar-settings-btn secondary" id="grammar-settings-reset">Reset to Defaults</button>
            <button class="grammar-settings-btn secondary" id="grammar-settings-cancel">Cancel</button>
            <button class="grammar-settings-btn primary" id="grammar-settings-save">Save Settings</button>
        `;

        // Assemble panel
        panel.appendChild(header);
        panel.appendChild(content);
        panel.appendChild(footer);
        overlay.appendChild(panel);
        document.body.appendChild(overlay);

        // Add event listeners
        header.querySelector('.grammar-settings-close').addEventListener('click', closeSettings);
        footer.querySelector('#grammar-settings-cancel').addEventListener('click', closeSettings);
        footer.querySelector('#grammar-settings-reset').addEventListener('click', resetSettings);
        footer.querySelector('#grammar-settings-save').addEventListener('click', saveSettingsFromPanel);

        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) closeSettings();
        });

        // Setup shortcut recording
        setupShortcutInputs();

        // Focus first input
        const firstInput = panel.querySelector('input, select, textarea');
        if (firstInput) firstInput.focus();
    }

    function createSettingsContent() {
        return `
            <div class="settings-section">
                <h3>Core Settings</h3>
                <div class="settings-row">
                    <label for="grammar-enabled">Enabled</label>
                    <input type="checkbox" id="grammar-enabled" ${settings.enabled ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-debug">Debug Mode</label>
                    <input type="checkbox" id="grammar-debug" ${settings.debugMode ? 'checked' : ''}>
                </div>
            </div>

            <div class="settings-section">
                <h3>Keyboard Shortcuts</h3>
                <div class="settings-row">
                    <label for="grammar-shortcut-smartfix">Smart Fix</label>
                    <input type="text" id="grammar-shortcut-smartfix" class="shortcut-input"
                           data-shortcut="smartFix" value="${settings.shortcuts.smartFix}" readonly>
                </div>
                <div class="settings-row">
                    <label for="grammar-shortcut-fixandsend">Fix and Send</label>
                    <input type="text" id="grammar-shortcut-fixandsend" class="shortcut-input"
                           data-shortcut="fixAndSend" value="${settings.shortcuts.fixAndSend}" readonly>
                </div>
                <div class="settings-row">
                    <label for="grammar-shortcut-quickfix">Quick Fix</label>
                    <input type="text" id="grammar-shortcut-quickfix" class="shortcut-input"
                           data-shortcut="quickFix" value="${settings.shortcuts.quickFix}" readonly>
                </div>
                <div class="settings-row">
                    <label for="grammar-shortcut-toggle">Toggle Enabled</label>
                    <input type="text" id="grammar-shortcut-toggle" class="shortcut-input"
                           data-shortcut="toggleEnabled" value="${settings.shortcuts.toggleEnabled}" readonly>
                </div>
                <div class="settings-row">
                    <label for="grammar-shortcut-settings">Open Settings</label>
                    <input type="text" id="grammar-shortcut-settings" class="shortcut-input"
                           data-shortcut="openSettings" value="${settings.shortcuts.openSettings}" readonly>
                </div>
            </div>

            <div class="settings-section">
                <h3>Language Settings</h3>
                <div class="settings-row">
                    <label for="grammar-main-language">Main Language</label>
                    <select id="grammar-main-language">
                        ${Object.entries(LANGUAGE_SUPPORT).map(([code, name]) =>
                            `<option value="${code}" ${settings.language.main === code ? 'selected' : ''}>${name}</option>`
                        ).join('')}
                    </select>
                </div>
                <div class="settings-row">
                    <label for="grammar-correction-language">Correction Language</label>
                    <select id="grammar-correction-language">
                        <option value="auto" ${settings.language.correctionLanguage === 'auto' ? 'selected' : ''}>Auto-detect</option>
                        ${Object.entries(LANGUAGE_SUPPORT).map(([code, name]) =>
                            `<option value="${code}" ${settings.language.correctionLanguage === code ? 'selected' : ''}>${name}</option>`
                        ).join('')}
                    </select>
                </div>
                <div class="settings-row">
                    <label for="grammar-auto-detect">Auto-detect Language</label>
                    <input type="checkbox" id="grammar-auto-detect" ${settings.language.autoDetect ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-confidence">Confidence Threshold</label>
                    <input type="number" id="grammar-confidence" min="0.1" max="1.0" step="0.1" value="${settings.language.confidenceThreshold}">
                </div>
            </div>

            <div class="settings-section">
                <h3>Correction Settings</h3>
                <div class="settings-row">
                    <label for="grammar-auto-fix">Auto-fix on Send</label>
                    <input type="checkbox" id="grammar-auto-fix" ${settings.correction.autoFixOnSend ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-min-length">Minimum Text Length</label>
                    <input type="number" id="grammar-min-length" min="1" max="1000" value="${settings.correction.minTextLength}">
                </div>
                <div class="settings-row">
                    <label for="grammar-max-length">Maximum Text Length</label>
                    <input type="number" id="grammar-max-length" min="100" max="10000" value="${settings.correction.maxTextLength}">
                </div>
                <div class="settings-row">
                    <label for="grammar-punctuation">Fix Punctuation</label>
                    <input type="checkbox" id="grammar-punctuation" ${settings.correction.fixPunctuation ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-capitalization">Fix Capitalization</label>
                    <input type="checkbox" id="grammar-capitalization" ${settings.correction.fixCapitalization ? 'checked' : ''}>
                </div>
            </div>

            <div class="settings-section">
                <h3>UI Settings</h3>
                <div class="settings-row">
                    <label for="grammar-show-icons">Show Icons</label>
                    <input type="checkbox" id="grammar-show-icons" ${settings.ui.showIcons ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-show-notifications">Show Notifications</label>
                    <input type="checkbox" id="grammar-show-notifications" ${settings.ui.showNotifications ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-show-loading">Show Loading Bar</label>
                    <input type="checkbox" id="grammar-show-loading" ${settings.ui.showLoadingBar ? 'checked' : ''}>
                </div>
                <div class="settings-row">
                    <label for="grammar-animations">Enable Animations</label>
                    <input type="checkbox" id="grammar-animations" ${settings.ui.animations ? 'checked' : ''}>
                </div>
            </div>

            <div class="settings-section">
                <h3>API Keys</h3>
                <div class="settings-row">
                    <label for="grammar-detection-key">Detect Language API Key</label>
                    <input type="password" id="grammar-detection-key" value="${settings.apiKeys.detectlanguage || ''}">
                </div>
            </div>
        `;
    }

    function setupShortcutInputs() {
        const shortcutInputs = document.querySelectorAll('.shortcut-input');
        shortcutInputs.forEach(input => {
            input.addEventListener('click', function(e) {
                e.preventDefault();
                startShortcutRecording(this, this.dataset.shortcut);
            });
        });
    }

    function closeSettings() {
        stopShortcutRecording();
        const overlay = document.querySelector('.grammar-settings-overlay');
        if (overlay) overlay.remove();
    }

    function resetSettings() {
        if (confirm('Are you sure you want to reset all settings to defaults?')) {
            settings = JSON.parse(JSON.stringify(DEFAULT_SETTINGS));
            saveSettings();
            closeSettings();
            showGlobalNotification('Settings reset to defaults', 'success');

            // Restart the script
            removeAllUIElements();
            setTimeout(init, 500);
        }
    }

    function saveSettingsFromPanel() {
        // Core Settings
        settings.enabled = document.getElementById('grammar-enabled').checked;
        settings.debugMode = document.getElementById('grammar-debug').checked;

        // Language Settings
        settings.language.main = document.getElementById('grammar-main-language').value;
        settings.language.correctionLanguage = document.getElementById('grammar-correction-language').value;
        settings.language.autoDetect = document.getElementById('grammar-auto-detect').checked;
        settings.language.confidenceThreshold = parseFloat(document.getElementById('grammar-confidence').value);

        // Correction Settings
        settings.correction.autoFixOnSend = document.getElementById('grammar-auto-fix').checked;
        settings.correction.minTextLength = parseInt(document.getElementById('grammar-min-length').value);
        settings.correction.maxTextLength = parseInt(document.getElementById('grammar-max-length').value);
        settings.correction.fixPunctuation = document.getElementById('grammar-punctuation').checked;
        settings.correction.fixCapitalization = document.getElementById('grammar-capitalization').checked;

        // UI Settings
        settings.ui.showIcons = document.getElementById('grammar-show-icons').checked;
        settings.ui.showNotifications = document.getElementById('grammar-show-notifications').checked;
        settings.ui.showLoadingBar = document.getElementById('grammar-show-loading').checked;
        settings.ui.animations = document.getElementById('grammar-animations').checked;

        // API Keys
        settings.apiKeys.detectlanguage = document.getElementById('grammar-detection-key').value;

        if (saveSettings()) {
            closeSettings();
            showGlobalNotification('Settings saved successfully', 'success');

            // Restart observers with new settings
            removeAllUIElements();
            setTimeout(init, 500);
        }
    }

    function formatActionName(action) {
        return action.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
    }

    // Initialize shortcut recording system
    setupShortcutRecording();

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

    // Global access for debugging
    unsafeWindow.grammarFixer = {
        settings: settings,
        fixText: handleSmartGrammarFix,
        showSettings: showSettingsPanel,
        scanElements: scanForWritableElements,
        getObservedElements: () => Array.from(observedElements)
    };

})();;