Grok Imagine Manager (Updated V4.1)

Prevents duplicate tracking. Video tab now includes Sort by High/Low Percentage. Includes Silent Mode and specific Image Input targeting. Features custom Keybinds. Fixed Import/Export data loss.

Verzia zo dňa 19.11.2025. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Grok Imagine Manager (Updated V4.1)
// @namespace    http://tampermonkey.net/
// @version      4.1
// @description  Prevents duplicate tracking. Video tab now includes Sort by High/Low Percentage. Includes Silent Mode and specific Image Input targeting. Features custom Keybinds. Fixed Import/Export data loss.
// @author       You
// @license MIT
// @match        https://grok.com/*
// @match        https://*.grok.com/*
// @match        https://grok.x.ai/*
// @match        https://*.grok.x.ai/*
// @match        https://x.com/*
// @match        https://*.x.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    if (window.grokPromptManagerLoaded) return;
    window.grokPromptManagerLoaded = true;

    function initScript() {
        // --- MODERN CSS ---
        GM_addStyle(`
            :root {
                --grok-bg: #000000;
                --grok-surface: #16181c;
                --grok-surface-hover: #1d1f23;
                --grok-border: #2f3336;
                --grok-primary: #1d9bf0;
                --grok-primary-hover: #1a8cd8;
                --grok-text-main: #e7e9ea;
                --grok-text-muted: #71767b;
                --grok-danger: #f4212e;
                --grok-warning: #ffd400;
                --grok-success: #00ba7c;
                --grok-radius: 16px;
                --grok-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
            }

            .grok-prompt-overlay { position: fixed; inset: 0; z-index: 10000; background: rgba(0, 0, 0, 0.4); backdrop-filter: blur(4px); display: none; opacity: 0; transition: opacity 0.2s ease; }
            .grok-prompt-overlay.open { display: flex; opacity: 1; pointer-events: auto; }
            /* INCREASED DEFAULT SIZE HERE */
            .grok-prompt-modal { position: fixed; background: rgba(22, 24, 28, 0.95); border: 1px solid var(--grok-border); border-radius: var(--grok-radius); width: 950px; height: 800px; min-width: 500px; min-height: 500px; display: flex; flex-direction: column; box-shadow: var(--grok-shadow); top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.95); transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1); color: var(--grok-text-main); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
            .grok-prompt-overlay.open .grok-prompt-modal { transform: translate(-50%, -50%) scale(1); }
            .grok-prompt-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 24px; border-bottom: 1px solid var(--grok-border); cursor: move; background: rgba(255,255,255,0.02); }
            .grok-prompt-title { font-size: 18px; font-weight: 700; display: flex; align-items: center; gap: 10px; }
            .grok-prompt-close { background: transparent; border: none; color: var(--grok-text-muted); cursor: pointer; padding: 8px; border-radius: 50%; transition: all 0.2s; }
            .grok-prompt-close:hover { background: rgba(239, 68, 68, 0.1); color: var(--grok-danger); }
            .grok-prompt-tabs { display: flex; padding: 0 16px; border-bottom: 1px solid var(--grok-border); background: var(--grok-bg); }
            .grok-prompt-tab { padding: 16px; background: none; border: none; color: var(--grok-text-muted); font-weight: 600; font-size: 14px; cursor: pointer; border-bottom: 3px solid transparent; transition: all 0.2s; }
            .grok-prompt-tab:hover { color: var(--grok-text-main); background: rgba(255,255,255,0.03); }
            .grok-prompt-tab.active { color: var(--grok-primary); border-bottom-color: var(--grok-primary); }
            .grok-prompt-content { flex: 1; overflow-y: auto; padding: 24px; scroll-behavior: smooth; }
            .grok-prompt-content::-webkit-scrollbar { width: 8px; }
            .grok-prompt-content::-webkit-scrollbar-track { background: transparent; }
            .grok-prompt-content::-webkit-scrollbar-thumb { background: var(--grok-border); border-radius: 4px; }
            .grok-prompt-form { display: flex; flex-direction: column; gap: 20px; }
            .grok-prompt-label { display: block; font-size: 13px; font-weight: 600; color: var(--grok-text-muted); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
            .grok-prompt-select, .grok-prompt-textarea, .grok-prompt-category-input { width: 100%; background: black; border: 1px solid var(--grok-border); border-radius: 8px; padding: 12px; color: var(--grok-text-main); font-size: 15px; font-family: inherit; transition: border-color 0.2s, box-shadow 0.2s; box-sizing: border-box; }
            .grok-prompt-select:focus, .grok-prompt-textarea:focus, .grok-prompt-category-input:focus { outline: none; border-color: var(--grok-primary); box-shadow: 0 0 0 2px rgba(29, 155, 240, 0.2); }
            .grok-prompt-textarea { height: 140px; line-height: 1.5; resize: vertical; }
            .grok-prompt-button, .grok-prompt-add-btn { background: var(--grok-primary); color: white; border: none; padding: 12px 20px; border-radius: 24px; font-weight: 700; cursor: pointer; transition: transform 0.1s, background 0.2s; display: flex; align-items: center; justify-content: center; gap: 8px; }
            .grok-prompt-button:hover { background: var(--grok-primary-hover); transform: translateY(-1px); }
            .grok-prompt-list { display: flex; flex-direction: column; gap: 12px; }
            .grok-prompt-item { background: transparent; border: 1px solid var(--grok-border); border-radius: 12px; padding: 16px; transition: background 0.2s, border-color 0.2s; }
            .grok-prompt-item:hover { background: rgba(255,255,255,0.02); border-color: #555; }
            .grok-prompt-item-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 15px; margin-bottom: 10px; }
            .grok-prompt-item-text { flex: 1; color: var(--grok-text-main); line-height: 1.5; font-size: 15px; white-space: pre-wrap; }
            .grok-prompt-item-delete { opacity: 0; color: var(--grok-text-muted); background: none; border: none; cursor: pointer; transition: opacity 0.2s, color 0.2s; padding: 4px; }
            .grok-prompt-item:hover .grok-prompt-item-delete { opacity: 1; }
            .grok-prompt-item-delete:hover { color: var(--grok-danger); }

            .grok-prompt-item-footer { display: flex; align-items: center; gap: 12px; margin-top: 12px; flex-wrap: wrap; }
            .grok-prompt-category-badge { background: rgba(29, 155, 240, 0.1); color: var(--grok-primary); padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 700; text-transform: uppercase; flex-shrink: 0; }
            .grok-prompt-category-badge.auto { background: rgba(0, 186, 124, 0.1); color: var(--grok-success); }
            .grok-prompt-copy-btn { flex-shrink: 0; background: transparent; border: 1px solid var(--grok-border); color: var(--grok-text-muted); padding: 6px 12px; border-radius: 16px; font-size: 12px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s; }
            .grok-prompt-copy-btn:hover { border-color: var(--grok-text-main); color: var(--grok-text-main); background: rgba(255,255,255,0.05); }
            .grok-prompt-stars { display: flex; gap: 6px; }
            .grok-prompt-star { width: 32px; height: 32px; cursor: pointer; color: #333; transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); }
            .grok-prompt-star.filled { color: #ffd700; filter: drop-shadow(0 0 2px rgba(255, 215, 0, 0.4)); }
            .grok-prompt-star:hover { transform: scale(1.15); }
            .grok-toast-container { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; gap: 8px; z-index: 11000; pointer-events: none; }
            .grok-toast { background: var(--grok-primary); color: white; padding: 10px 20px; border-radius: 24px; box-shadow: 0 4px 12px rgba(0,0,0,0.3); font-weight: 600; font-size: 14px; animation: slideUpFade 0.3s ease forwards; display: flex; align-items: center; gap: 8px; }
            @keyframes slideUpFade { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
            .grok-prompt-category-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
            .grok-prompt-category-tag { background: var(--grok-surface-hover); border: 1px solid var(--grok-border); color: var(--grok-text-main); padding: 8px 14px; border-radius: 20px; font-size: 13px; display: flex; align-items: center; gap: 8px; }
            .grok-prompt-export-section { margin-top: 32px; padding-top: 24px; border-top: 1px solid var(--grok-border); }
            .grok-prompt-export-btn { flex: 1; background: transparent; border: 1px solid var(--grok-border); color: var(--grok-text-main); padding: 12px; border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; transition: all 0.2s; font-weight: 600; }
            .grok-prompt-export-btn:hover { background: var(--grok-surface-hover); border-color: #666; }
            .grok-prompt-export-btn.danger { color: var(--grok-danger); border-color: rgba(244, 33, 46, 0.3); }
            .grok-prompt-export-btn.danger:hover { background: rgba(244, 33, 46, 0.1); border-color: var(--grok-danger); }
            .grok-prompt-hint { position: fixed; bottom: 20px; right: 20px; background: var(--grok-surface); border: 1px solid var(--grok-border); padding: 10px 16px; border-radius: 12px; color: var(--grok-text-muted); font-size: 13px; font-weight: 500; box-shadow: 0 10px 20px rgba(0,0,0,0.3); display: flex; align-items: center; gap: 10px; z-index: 9999; }
            .grok-prompt-kbd { background: #333; color: white; padding: 2px 6px; border-radius: 4px; font-family: monospace; font-size: 12px; border-bottom: 2px solid #111; }
            .grok-prompt-resize-handle { position: absolute; width: 20px; height: 20px; right: 0; bottom: 0; cursor: se-resize; z-index: 10; }

            /* --- FILTER & SORT BAR --- */
            .grok-control-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 10px; }
            .grok-filter-group { display: flex; gap: 6px; flex-wrap: wrap; }
            .grok-sort-group { display: flex; gap: 4px; align-items: center; padding-left: 10px; border-left: 1px solid var(--grok-border); }

            .grok-prompt-filter-btn { background: transparent; border: 1px solid var(--grok-border); color: var(--grok-text-muted); padding: 6px 14px; border-radius: 20px; cursor: pointer; font-size: 13px; font-weight: 500; transition: 0.2s; }
            .grok-prompt-filter-btn.active { background: var(--grok-primary); border-color: var(--grok-primary); color: white; }

            .grok-prompt-sort-btn { background: transparent; border: none; color: var(--grok-text-muted); padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 11px; font-weight: 600; text-transform: uppercase; transition: 0.2s; }
            .grok-prompt-sort-btn:hover { color: var(--grok-text-main); background: rgba(255,255,255,0.05); }
            .grok-prompt-sort-btn.active { color: var(--grok-primary); background: rgba(29, 155, 240, 0.1); }

            .grok-checkbox-wrapper { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; padding: 16px; background: rgba(255,255,255,0.03); border-radius: 12px; }
            .grok-checkbox { width: 20px; height: 20px; accent-color: var(--grok-primary); cursor: pointer; }

            /* Keybind Recorder Styles */
            .grok-keybind-wrapper { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; background: black; border: 1px solid var(--grok-border); padding: 10px; border-radius: 8px; }
            .grok-keybind-display { font-family: monospace; background: #222; color: var(--grok-primary); padding: 4px 8px; border-radius: 4px; border: 1px solid #333; min-width: 80px; text-align: center; font-weight: 700; }
            .grok-keybind-btn { background: var(--grok-surface-hover); border: 1px solid var(--grok-border); color: white; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; }
            .grok-keybind-btn.recording { background: var(--grok-danger); border-color: var(--grok-danger); animation: pulse 1s infinite; }
            @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.7; } 100% { opacity: 1; } }

            /* Video & Image Styles */
            .grok-video-section { margin-top: 12px; background: rgba(255, 255, 255, 0.03); padding: 10px; border-radius: 8px; border: 1px dashed var(--grok-border); }
            .grok-video-input { width: 100%; background: transparent; border: none; color: var(--grok-text-muted); font-size: 13px; font-family: inherit; resize: none; outline: none; height: 32px; transition: height 0.2s; }
            .grok-video-input:focus { color: var(--grok-text-main); height: 60px; }
            .grok-video-label { font-size: 11px; color: var(--grok-primary); font-weight: 700; text-transform: uppercase; margin-bottom: 4px; display: block; }
            .grok-video-save-hint { font-size: 10px; color: #555; text-align: right; display: none; }
            .grok-video-input:focus + .grok-video-save-hint { display: block; }

            /* Snapshot Grid Layout */
            .grok-image-item-grid { display: flex; gap: 16px; }
            .grok-image-content-col { flex: 1; }
            .grok-image-preview-col { width: 120px; display: flex; flex-direction: column; gap: 8px; align-items: center; justify-content: flex-start; }

            .grok-snapshot-thumb { width: 100%; height: 100px; object-fit: cover; border-radius: 8px; border: 1px solid var(--grok-border); cursor: zoom-in; transition: transform 0.2s; background: #000; }
            .grok-snapshot-thumb:hover { transform: scale(1.05); border-color: var(--grok-primary); }

            .grok-snapshot-upload-btn { position: relative; width: 100%; height: 100px; border: 1px dashed var(--grok-border); border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-direction: column; color: var(--grok-text-muted); cursor: pointer; font-size: 12px; transition: 0.2s; background: rgba(255,255,255,0.02); }
            .grok-snapshot-upload-btn:hover { border-color: var(--grok-primary); color: var(--grok-primary); background: rgba(29, 155, 240, 0.05); }
            .grok-snapshot-input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }

            .grok-snapshot-del { background: rgba(0,0,0,0.7); color: white; border: none; border-radius: 50%; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; cursor: pointer; position: absolute; top: -5px; right: -5px; font-size: 12px; line-height: 1; }
            .grok-snapshot-wrapper { position: relative; width: 100%; }

            /* --- MODERATION SLIDER --- */
            .grok-mod-wrapper { display: flex; align-items: center; gap: 10px; flex-grow: 1; min-width: 140px; max-width: 300px; background: rgba(0,0,0,0.2); padding: 4px 10px; border-radius: 20px; border: 1px solid var(--grok-border); margin-right: 8px; }
            .grok-mod-label { font-size: 10px; text-transform: uppercase; color: var(--grok-text-muted); font-weight: 700; white-space: nowrap; }
            .grok-mod-slider { -webkit-appearance: none; appearance: none; flex: 1; height: 4px; background: #333; border-radius: 2px; outline: none; cursor: ew-resize; }
            .grok-mod-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 14px; height: 14px; background: var(--grok-text-main); border-radius: 50%; cursor: pointer; transition: 0.2s; }
            .grok-mod-slider::-webkit-slider-thumb:hover { transform: scale(1.2); }
            .grok-mod-val { font-size: 12px; font-weight: 700; min-width: 35px; text-align: right; font-variant-numeric: tabular-nums; }
            .grok-mod-val.low { color: var(--grok-danger); }
            .grok-mod-val.med { color: var(--grok-warning); }
            .grok-mod-val.high { color: var(--grok-success); }

            /* Lightbox */
            .grok-lightbox { position: fixed; inset: 0; z-index: 12000; background: rgba(0,0,0,0.9); display: none; align-items: center; justify-content: center; cursor: zoom-out; }
            .grok-lightbox.open { display: flex; animation: fadeIn 0.2s; }
            .grok-lightbox img { max-width: 90%; max-height: 90%; border-radius: 4px; box-shadow: 0 0 50px rgba(0,0,0,0.5); }
            @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
        `);

        // --- STATE ---
        let isOpen = false;
        let currentRating = 0;
        let currentCategory = '';
        let filterCategory = 'all';
        let videoSortMode = 'newest'; // 'newest', 'high', 'low'
        let isDragging = false, isResizing = false;
        let dragOffset = { x: 0, y: 0 };
        let modalElement = null;
        let isRecordingKeybind = false;

        // --- HELPERS ---
        function showToast(message, type = 'success') {
            let container = document.querySelector('.grok-toast-container');
            if (!container) {
                container = document.createElement('div');
                container.className = 'grok-toast-container';
                document.body.appendChild(container);
            }

            const toast = document.createElement('div');
            toast.className = 'grok-toast';
            if(type === 'error') toast.style.background = 'var(--grok-danger)';

            toast.innerHTML = `
                <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg>
                <span>${message}</span>
            `;
            container.appendChild(toast);

            setTimeout(() => {
                toast.style.opacity = '0';
                toast.style.transform = 'translateY(10px)';
                setTimeout(() => toast.remove(), 300);
            }, 3000);
        }

        function getCategories() {
            let cats = JSON.parse(GM_getValue('grok_categories', '["General"]'));
            if (!cats.includes('Image')) { cats.push('Image'); saveCategories(cats); }
            if (!cats.includes('Auto-History')) { cats.push('Auto-History'); saveCategories(cats); }
            return cats;
        }
        function saveCategories(cats) { GM_setValue('grok_categories', JSON.stringify(cats)); }
        function getPrompts() { return JSON.parse(GM_getValue('grok_prompts', '[]')); }
        function savePrompts(prompts) { GM_setValue('grok_prompts', JSON.stringify(prompts)); }

        function getSettings() {
            const defaults = {
                autoTrack: true,
                silentMode: false,
                keybind: { key: 'k', altKey: true, ctrlKey: false, shiftKey: false, metaKey: false }
            };
            const saved = JSON.parse(GM_getValue('grok_settings', '{}'));
            return { ...defaults, ...saved };
        }

        function saveSettings(s) { GM_setValue('grok_settings', JSON.stringify(s)); }

        function getKeybindString(kb) {
            if (!kb) return 'Alt + K';
            const parts = [];
            if (kb.ctrlKey) parts.push('Ctrl');
            if (kb.altKey) parts.push('Alt');
            if (kb.shiftKey) parts.push('Shift');
            if (kb.metaKey) parts.push('Meta');
            parts.push((kb.key === ' ' ? 'Space' : kb.key).toUpperCase());
            return parts.join(' + ');
        }

        // --- IMAGE COMPRESSION ---
        function compressImage(file, callback) {
            const reader = new FileReader();
            reader.onload = (e) => {
                const img = new Image();
                img.onload = () => {
                    const canvas = document.createElement('canvas');
                    const ctx = canvas.getContext('2d');
                    const MAX_SIZE = 400;
                    let width = img.width;
                    let height = img.height;

                    if (width > height) {
                        if (width > MAX_SIZE) {
                            height *= MAX_SIZE / width;
                            width = MAX_SIZE;
                        }
                    } else {
                        if (height > MAX_SIZE) {
                            width *= MAX_SIZE / height;
                            height = MAX_SIZE;
                        }
                    }

                    canvas.width = width;
                    canvas.height = height;
                    ctx.drawImage(img, 0, 0, width, height);
                    callback(canvas.toDataURL('image/jpeg', 0.7));
                };
                img.src = e.target.result;
            };
            reader.readAsDataURL(file);
        }

        // --- AUTO TRACKING ---
        function setupAutoTracker() {
            const sendIconPath = "M5 11L12 4M12 4L19 11M12 4V21";

            const capture = () => {
                if (!getSettings().autoTrack) return;

                let text = '';
                let sourceType = 'Image';

                const editor = document.querySelector('.tiptap.ProseMirror');
                // TARGETED SPECIFIC IMAGE INPUT
                const imageInput = document.querySelector('textarea[aria-label="Image prompt"]');
                const videoInput = document.querySelector('textarea[aria-label="Make a video"]');

                if (videoInput && (document.activeElement === videoInput || (videoInput.value.trim().length > 0 && (!editor || !editor.textContent.trim())))) {
                    text = videoInput.value.trim();
                    sourceType = 'Video';
                }
                else if (imageInput && (document.activeElement === imageInput || (imageInput.value.trim().length > 0 && (!editor || !editor.textContent.trim())))) {
                    text = imageInput.value.trim();
                    sourceType = 'Image';
                }
                else if (editor && editor.textContent.trim().length > 0) {
                    text = editor.textContent.trim();
                    sourceType = 'Image';
                }

                // Fallbacks
                if (!text && videoInput && videoInput.value.trim()) { text = videoInput.value.trim(); sourceType = 'Video'; }
                if (!text && imageInput && imageInput.value.trim()) { text = imageInput.value.trim(); sourceType = 'Image'; }

                if (!text || text.length < 2) return;

                const prompts = getPrompts();
                if (prompts.some(p => p.text === text)) return;

                prompts.push({
                    id: 'auto_' + Date.now().toString(),
                    text: text,
                    rating: 0,
                    category: 'Auto-History',
                    sourceType: sourceType,
                    timestamp: Date.now()
                });
                savePrompts(prompts);

                // CHECK SILENT MODE SETTING
                if (!getSettings().silentMode) {
                    showToast(`Auto-Captured (${sourceType})`);
                }

                if (isOpen && document.querySelector('.grok-prompt-tab.active[data-tab="recent"]')) {
                    renderPromptsList('grokRecentTab', null, (a,b) => b.timestamp - a.timestamp);
                }
            };

            document.addEventListener('keydown', (e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                    if (e.target.closest('.ProseMirror') || e.target.closest('textarea[aria-label="Image prompt"]') || e.target.closest('textarea[aria-label="Make a video"]')) {
                        capture();
                    }
                }
            }, true);

            document.addEventListener('mousedown', (e) => {
                const ariaBtn = e.target.closest('button[aria-label="Submit"]');
                const videoBtn = e.target.closest('button[aria-label="Make video"]');
                const btn = e.target.closest('button') || e.target.closest('[role="button"]') || e.target.closest('div');

                if (videoBtn) { capture(); return; }
                if (ariaBtn && ariaBtn.querySelector(`path[d="${sendIconPath}"]`)) { capture(); return; }
                if (btn && btn.querySelector(`path[d="${sendIconPath}"]`)) capture();
            }, true);
        }

        // --- UI CREATION ---
        function createUI() {
            document.querySelector('.grok-prompt-overlay')?.remove();
            document.querySelector('.grok-lightbox')?.remove();
            document.querySelector('.grok-prompt-hint')?.remove();

            const lightbox = document.createElement('div');
            lightbox.className = 'grok-lightbox';
            lightbox.innerHTML = '<img src="" id="grokLightboxImg">';
            lightbox.onclick = () => { lightbox.classList.remove('open'); setTimeout(()=>lightbox.style.display='none', 200); };
            document.body.appendChild(lightbox);

            const overlay = document.createElement('div');
            overlay.className = 'grok-prompt-overlay';

            const modal = document.createElement('div');
            modal.className = 'grok-prompt-modal';
            modalElement = modal;

            const pos = GM_getValue('grok_modal_position', null);
            const size = GM_getValue('grok_modal_size', null);
            if (pos) { modal.style.top = pos.top; modal.style.left = pos.left; modal.style.transform = 'translate(0,0)'; }
            if (size) { modal.style.width = size.width; modal.style.height = size.height; }

            const settings = getSettings();
            const kbString = getKeybindString(settings.keybind);

            modal.innerHTML = `
                <div class="grok-prompt-header" id="grokDragHandle">
                    <div class="grok-prompt-title">
                        <svg width="24" height="24" fill="currentColor" viewBox="0 0 24 24" style="color: var(--grok-primary);">
                            <path d="M2 21L23 12L2 3V10L17 12L2 14V21Z"/>
                        </svg>
                        <span>Grok Imagine Manager</span>
                    </div>
                    <button class="grok-prompt-close" id="grokCloseBtn" title="Close (Esc)">
                        <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
                    </button>
                </div>
                <div class="grok-prompt-tabs">
                    <button class="grok-prompt-tab active" data-tab="generate">New Prompt</button>
                    <button class="grok-prompt-tab" data-tab="recent">History</button>
                    <button class="grok-prompt-tab" data-tab="saved">Video</button>
                    <button class="grok-prompt-tab" data-tab="quick">Images</button>
                    <button class="grok-prompt-tab" data-tab="categories">Tags</button>
                    <button class="grok-prompt-tab" data-tab="settings">Settings</button>
                </div>
                <div class="grok-prompt-content">
                    <div id="grokGenerateTab" class="grok-prompt-form">
                        <div>
                            <label class="grok-prompt-label">Category</label>
                            <select class="grok-prompt-select" id="grokCategorySelect"></select>
                        </div>
                        <div>
                            <label class="grok-prompt-label">Your Prompt</label>
                            <textarea class="grok-prompt-textarea" id="grokPromptInput" placeholder="What do you want to see?"></textarea>
                        </div>
                        <div>
                            <label class="grok-prompt-label">Rating</label>
                            <div class="grok-prompt-stars" id="grokStars">
                                ${[1,2,3,4,5].map(i => `<svg class="grok-prompt-star" data-rating="${i}" fill="currentColor" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>`).join('')}
                            </div>
                        </div>
                        <button class="grok-prompt-button" id="grokSaveBtn">
                            <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"/></svg>
                            Save Prompt
                        </button>
                    </div>

                    <div id="grokRecentTab" class="grok-prompt-list" style="display: none;"></div>
                    <div id="grokSavedTab" class="grok-prompt-list" style="display: none;"></div>
                    <div id="grokQuickTab" class="grok-prompt-list" style="display: none;"></div>

                    <div id="grokCategoriesTab" class="grok-prompt-form" style="display: none;">
                        <div>
                            <label class="grok-prompt-label">Add Category</label>
                            <div style="display:flex; gap:10px;">
                                <input type="text" class="grok-prompt-category-input" id="grokNewCategory" placeholder="e.g. Sci-Fi, Portraits...">
                                <button class="grok-prompt-add-btn" id="grokAddCategoryBtn">Add</button>
                            </div>
                            <div class="grok-prompt-category-list" id="grokCategoryList"></div>
                        </div>
                    </div>

                    <div id="grokSettingsTab" style="display: none;">
                        <label class="grok-prompt-label">Shortcuts</label>
                        <div class="grok-keybind-wrapper">
                            <div class="grok-keybind-display" id="grokKeybindDisplay">${kbString}</div>
                            <button class="grok-keybind-btn" id="grokKeybindBtn">Change Keybind</button>
                        </div>

                        <label class="grok-prompt-label">Automation</label>
                        <div class="grok-checkbox-wrapper">
                            <input type="checkbox" id="grokAutoTrackToggle" class="grok-checkbox">
                            <div>
                                <div style="font-weight:600; color:var(--grok-text-main);">Auto-Capture Prompts</div>
                                <div style="font-size:12px; color:var(--grok-text-muted);">Automatically save prompts from Chat and Image Input.</div>
                            </div>
                        </div>
                        <div class="grok-checkbox-wrapper">
                            <input type="checkbox" id="grokSilentModeToggle" class="grok-checkbox">
                            <div>
                                <div style="font-weight:600; color:var(--grok-text-main);">Silent Mode</div>
                                <div style="font-size:12px; color:var(--grok-text-muted);">Turn off pop-up notifications when a prompt is auto-saved.</div>
                            </div>
                        </div>
                        <label class="grok-prompt-label">Data Management</label>
                        <div style="display:flex; gap:12px; margin-bottom:24px;">
                            <button class="grok-prompt-export-btn" id="grokExportBtn">Export JSON</button>
                            <button class="grok-prompt-export-btn" id="grokImportBtn">Import JSON</button>
                            <input type="file" id="grokImportFile" style="display:none" accept=".json">
                        </div>
                        <div class="grok-prompt-export-section">
                            <label class="grok-prompt-label" style="color: var(--grok-danger);">Danger Zone</label>
                            <button class="grok-prompt-export-btn danger" id="grokClearBtn">Wipe All Data</button>
                        </div>
                    </div>
                </div>
                <div class="grok-prompt-resize-handle" id="grokResizeHandle"></div>
            `;

            overlay.appendChild(modal);
            document.body.appendChild(overlay);

            if (!GM_getValue('grok_hint_hidden', false)) {
                const hint = document.createElement('div');
                hint.className = 'grok-prompt-hint';
                hint.innerHTML = `<span>Press <span class="grok-prompt-kbd">${kbString}</span> to manage prompts</span>`;
                const closeHint = document.createElement('div');
                closeHint.innerHTML = '&times;';
                closeHint.style.cssText = 'cursor:pointer; font-size:16px; padding:0 5px;';
                closeHint.onclick = () => { hint.remove(); GM_setValue('grok_hint_hidden', true); };
                hint.appendChild(closeHint);
                document.body.appendChild(hint);
            }

            return overlay;
        }

        // --- RENDERERS ---
        function renderPromptsList(targetId, filterFn, sortFn) {
            const container = document.getElementById(targetId);
            let prompts = getPrompts();
            if (filterFn) prompts = prompts.filter(filterFn);

            // -- VIDEO TAB LOGIC (Includes Sort) --
            if (targetId === 'grokSavedTab') {
                const categories = getCategories().filter(cat => cat !== 'Image' && cat !== 'Auto-History');

                // Control Bar: Filters Left, Sort Right
                const controlsHTML = `
                    <div class="grok-control-bar">
                        <div class="grok-filter-group">
                            <button class="grok-prompt-filter-btn ${filterCategory === 'all' ? 'active' : ''}" data-f="all">All</button>
                            ${categories.map(c => `<button class="grok-prompt-filter-btn ${filterCategory === c ? 'active' : ''}" data-f="${c}">${c}</button>`).join('')}
                        </div>
                        <div class="grok-sort-group">
                             <span style="font-size:10px; color:#555; font-weight:700; text-transform:uppercase; margin-right:4px;">Sort:</span>
                             <button class="grok-prompt-sort-btn ${videoSortMode === 'newest' ? 'active' : ''}" data-sort="newest">Newest</button>
                             <button class="grok-prompt-sort-btn ${videoSortMode === 'high' ? 'active' : ''}" data-sort="high">High %</button>
                             <button class="grok-prompt-sort-btn ${videoSortMode === 'low' ? 'active' : ''}" data-sort="low">Low %</button>
                        </div>
                    </div>`;

                if (filterCategory !== 'all') prompts = prompts.filter(p => p.category === filterCategory);

                // Apply Video Sort Logic
                if (videoSortMode === 'high') {
                    prompts.sort((a, b) => (b.moderation || 0) - (a.moderation || 0));
                } else if (videoSortMode === 'low') {
                    prompts.sort((a, b) => (a.moderation || 0) - (b.moderation || 0));
                } else {
                    // Default: Newest
                    prompts.sort((a, b) => b.timestamp - a.timestamp);
                }

                if (prompts.length === 0) {
                    container.innerHTML = controlsHTML + `<div style="text-align:center; color:#666; padding:40px;">No saved prompts found.</div>`;
                    bindControls();
                    return;
                }
                container.innerHTML = controlsHTML + '<div class="grok-prompt-list">' + prompts.map(p => generatePromptHTML(p, 'video')).join('') + '</div>';
                bindControls();
                bindMediaEvents(container);
            }

            // -- IMAGE TAB --
            else if (targetId === 'grokQuickTab') {
                if (sortFn) prompts.sort(sortFn);
                 if (prompts.length === 0) {
                    container.innerHTML = `<div style="text-align:center; color:#666; padding:40px;">No image prompts saved yet.</div>`;
                    return;
                }
                container.innerHTML = '<div class="grok-prompt-list">' + prompts.map(p => generatePromptHTML(p, 'image')).join('') + '</div>';
                bindMediaEvents(container);
            }

            // -- HISTORY TAB --
            else {
                if (sortFn) prompts.sort(sortFn);
                if (prompts.length === 0) {
                    container.innerHTML = `<div style="text-align:center; color:#666; padding:40px;">History is empty.</div>`;
                    return;
                }
                container.innerHTML = '<div class="grok-prompt-list">' + prompts.map(p => generatePromptHTML(p, 'history')).join('') + '</div>';
                bindMediaEvents(container);
            }

            bindPromptEvents(container);
        }

        function generatePromptHTML(p, renderMode) {
            const isAuto = p.category === 'Auto-History' || p.id.startsWith('auto_');
            const videoPromptValue = p.videoPrompt || '';
            let badgeLabel = isAuto ? (p.sourceType || 'Auto-History') : p.category;

            let snapshotHtml = '';
            let videoInputHtml = '';

            if (renderMode === 'image') {
                snapshotHtml = p.snapshot
                    ? `<div class="grok-snapshot-wrapper"><img src="${p.snapshot}" class="grok-snapshot-thumb" data-src="${p.snapshot}" title="Click to Zoom"><button class="grok-snapshot-del" data-id="${p.id}" title="Remove Snapshot">&times;</button></div>`
                    : `<label class="grok-snapshot-upload-btn">+ Snapshot<input type="file" class="grok-snapshot-input" data-id="${p.id}" accept="image/jpeg, image/png, image/webp"></label>`;
            }

            if (renderMode === 'video') {
                 videoInputHtml = `
                 <div class="grok-video-section">
                    <label class="grok-video-label">Video Prompt</label>
                    <textarea class="grok-video-input" data-id="${p.id}" placeholder="Add video description...">${videoPromptValue}</textarea>
                    <div class="grok-video-save-hint">Press Tab to save</div>
                </div>`;
            }

            const previewCol = renderMode === 'image' ? `<div class="grok-image-preview-col">${snapshotHtml}</div>` : '';
            const modVal = p.moderation || 0;
            const modClass = modVal < 40 ? 'low' : (modVal < 80 ? 'med' : 'high');

            return `
            <div class="grok-prompt-item">
                <div class="grok-image-item-grid">
                    <div class="grok-image-content-col">
                        <div class="grok-prompt-item-header">
                            <div class="grok-prompt-item-text">${p.text}</div>
                            <button class="grok-prompt-item-delete" data-id="${p.id}" title="Delete"><svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg></button>
                        </div>
                        ${videoInputHtml}
                    </div>
                    ${previewCol}
                </div>
                <div class="grok-prompt-item-footer">
                    <span class="grok-prompt-category-badge ${isAuto ? 'auto' : ''}">${badgeLabel}</span>
                    <div class="grok-mod-wrapper">
                        <label class="grok-mod-label">Moderation Pass:</label>
                        <input type="range" min="0" max="100" value="${modVal}" class="grok-mod-slider" data-id="${p.id}">
                        <span class="grok-mod-val ${modClass}" id="mod-val-${p.id}">${modVal}%</span>
                    </div>
                    <button class="grok-prompt-copy-btn" data-text="${p.text.replace(/"/g, '&quot;')}">Copy</button>
                     ${isAuto ? `<button class="grok-prompt-copy-btn save-btn" data-id="${p.id}" style="color:var(--grok-primary); border-color:var(--grok-primary);">Save to Favorites</button>` : ''}
                     <span style="margin-left:auto; font-size:11px; color:#555;">${new Date(p.timestamp).toLocaleDateString()}</span>
                </div>
            </div>`;
        }

        function bindControls() {
            // Bind Filter Buttons
            document.querySelectorAll('.grok-prompt-filter-btn').forEach(b => {
                b.onclick = () => {
                    filterCategory = b.dataset.f;
                    renderPromptsList('grokSavedTab', p => p.category !== 'Image' && p.category !== 'Auto-History');
                };
            });

            // Bind Sort Buttons
            document.querySelectorAll('.grok-prompt-sort-btn').forEach(b => {
                b.onclick = () => {
                    videoSortMode = b.dataset.sort;
                    renderPromptsList('grokSavedTab', p => p.category !== 'Image' && p.category !== 'Auto-History');
                };
            });
        }

        function bindMediaEvents(container) {
             container.querySelectorAll('.grok-video-input').forEach(input => {
                 input.addEventListener('blur', (e) => {
                     const id = e.target.dataset.id;
                     const val = e.target.value;
                     let prompts = getPrompts();
                     let p = prompts.find(x => x.id === id);
                     if (p && p.videoPrompt !== val) {
                         p.videoPrompt = val;
                         savePrompts(prompts);
                         showToast('Video prompt saved');
                     }
                 });
             });

             container.querySelectorAll('.grok-mod-slider').forEach(slider => {
                 slider.addEventListener('input', (e) => {
                    const val = e.target.value;
                    const id = e.target.dataset.id;
                    const display = document.getElementById(`mod-val-${id}`);
                    if(display) {
                        display.innerText = val + '%';
                        display.className = `grok-mod-val ${val < 40 ? 'low' : (val < 80 ? 'med' : 'high')}`;
                    }
                 });
                 slider.addEventListener('change', (e) => {
                     const val = parseInt(e.target.value);
                     const id = e.target.dataset.id;
                     let prompts = getPrompts();
                     let p = prompts.find(x => x.id === id);
                     if (p) {
                         p.moderation = val;
                         savePrompts(prompts);
                         // If sorting by percentage, refresh list to reflect new order
                         if (videoSortMode !== 'newest') {
                             refreshActiveTab();
                         }
                     }
                 });
             });

             container.querySelectorAll('.grok-snapshot-input').forEach(input => {
                 input.addEventListener('change', (e) => {
                     const file = e.target.files[0];
                     if (!file) return;
                     const id = e.target.dataset.id;
                     compressImage(file, (base64) => {
                         let prompts = getPrompts();
                         let p = prompts.find(x => x.id === id);
                         if (p) {
                             p.snapshot = base64;
                             savePrompts(prompts);
                             refreshActiveTab();
                             showToast('Snapshot attached!');
                         }
                     });
                 });
             });

             container.querySelectorAll('.grok-snapshot-del').forEach(btn => {
                 btn.addEventListener('click', (e) => {
                     if (!confirm('Remove snapshot?')) return;
                     const id = e.target.dataset.id;
                     let prompts = getPrompts();
                     let p = prompts.find(x => x.id === id);
                     if (p) {
                         delete p.snapshot;
                         savePrompts(prompts);
                         refreshActiveTab();
                     }
                 });
             });

             container.querySelectorAll('.grok-snapshot-thumb').forEach(img => {
                 img.addEventListener('click', (e) => {
                     const lightbox = document.querySelector('.grok-lightbox');
                     const lbImg = document.getElementById('grokLightboxImg');
                     lbImg.src = e.target.dataset.src;
                     lightbox.style.display = 'flex';
                     lightbox.offsetHeight;
                     lightbox.classList.add('open');
                 });
             });
        }

        function bindPromptEvents(container) {
            container.onclick = (e) => {
                const btn = e.target.closest('button');
                if (!btn) return;

                if (btn.classList.contains('grok-prompt-copy-btn') && btn.dataset.text) {
                    navigator.clipboard.writeText(btn.dataset.text).then(() => showToast('Copied to clipboard!'));
                }
                else if (btn.classList.contains('grok-prompt-item-delete')) {
                    if (confirm('Delete this prompt?')) {
                        let prompts = getPrompts().filter(p => p.id !== btn.dataset.id);
                        savePrompts(prompts);
                        refreshActiveTab();
                    }
                }
                else if (btn.classList.contains('save-btn')) {
                    let prompts = getPrompts();
                    let p = prompts.find(x => x.id === btn.dataset.id);
                    if (p) {
                        document.querySelector('[data-tab="generate"]').click();
                        document.getElementById('grokPromptInput').value = p.text;
                        showToast('Edit and rate to save permanently', 'success');
                    }
                }
            };
        }

        function refreshActiveTab() {
            const active = document.querySelector('.grok-prompt-tab.active').dataset.tab;
            if (active === 'saved') renderPromptsList('grokSavedTab', p => p.category !== 'Image' && p.category !== 'Auto-History');
            else if (active === 'recent') renderPromptsList('grokRecentTab', null, (a,b) => b.timestamp - a.timestamp);
            else if (active === 'quick') renderPromptsList('grokQuickTab', p => p.category === 'Image', (a,b) => b.timestamp - a.timestamp);
            else if (active === 'categories') renderCategories();
            updateCounts();
        }

        function renderCategories() {
            const div = document.getElementById('grokCategoryList');
            div.innerHTML = getCategories().filter(c => c !== 'Auto-History').map(c => `
                <div class="grok-prompt-category-tag">
                    ${c}
                    <span style="cursor:pointer; color:#666; padding:0 4px;" data-rem="${c}">&times;</span>
                </div>
            `).join('');
            div.querySelectorAll('[data-rem]').forEach(span => {
                span.onclick = () => {
                    let c = span.dataset.rem;
                    let cats = getCategories();
                    if (cats.length <= 1) return alert('Keep at least one category.');
                    saveCategories(cats.filter(x => x !== c));
                    renderCategories();
                    updateCategorySelect();
                };
            });
        }

        function updateCategorySelect() {
            const sel = document.getElementById('grokCategorySelect');
            const cats = getCategories().filter(c => c !== 'Auto-History');
            sel.innerHTML = cats.map(c => `<option value="${c}">${c}</option>`).join('');
            if (!currentCategory) currentCategory = cats[0];
        }

        function updateCounts() {
            const p = getPrompts();
            document.querySelector('[data-tab="saved"]').innerText = `Video (${p.filter(x=>x.category!=='Image' && x.category!=='Auto-History').length})`;
            document.querySelector('[data-tab="quick"]').innerText = `Images (${p.filter(x=>x.category==='Image').length})`;
        }

        // --- INITIALIZATION ---
        const overlay = createUI();
        const modal = modalElement;
        setupAutoTracker();

        const handle = document.getElementById('grokDragHandle');
        handle.onmousedown = (e) => {
            if(e.target.closest('button')) return;
            isDragging = true;
            const rect = modal.getBoundingClientRect();
            dragOffset = { x: e.clientX - rect.left, y: e.clientY - rect.top };
            modal.style.transition = 'none';
            modal.style.transform = 'none';
            modal.style.left = rect.left + 'px';
            modal.style.top = rect.top + 'px';
        };

        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                modal.style.left = (e.clientX - dragOffset.x) + 'px';
                modal.style.top = (e.clientY - dragOffset.y) + 'px';
            }
            if (isResizing) {
                const rect = modal.getBoundingClientRect();
                modal.style.width = Math.max(400, e.clientX - rect.left) + 'px';
                modal.style.height = Math.max(300, e.clientY - rect.top) + 'px';
            }
        });

        document.addEventListener('mouseup', () => {
            if (isDragging || isResizing) {
                modal.style.transition = '';
                GM_setValue('grok_modal_position', { top: modal.style.top, left: modal.style.left });
                GM_setValue('grok_modal_size', { width: modal.style.width, height: modal.style.height });
            }
            isDragging = false; isResizing = false;
        });

        document.getElementById('grokResizeHandle').onmousedown = (e) => { e.preventDefault(); isResizing = true; };

        document.getElementById('grokCloseBtn').onclick = () => {
            overlay.classList.remove('open');
            setTimeout(() => overlay.style.display = 'none', 200);
            isOpen = false;
        };

        document.querySelectorAll('.grok-prompt-tab').forEach(tab => {
            tab.onclick = () => {
                document.querySelectorAll('.grok-prompt-tab').forEach(t => t.classList.remove('active'));
                tab.classList.add('active');
                const t = tab.dataset.tab;
                ['generate','recent','saved','quick','categories','settings'].forEach(id => {
                    document.getElementById('grok'+id.charAt(0).toUpperCase()+id.slice(1)+'Tab').style.display = (id === t ? (id==='categories' || id==='generate' || id==='settings' ? 'flex' : 'block') : 'none');
                });
                refreshActiveTab();
            };
        });

        // SETTINGS LOGIC
        const currentSettings = getSettings();

        // Keybind Recorder
        const kbBtn = document.getElementById('grokKeybindBtn');
        const kbDisplay = document.getElementById('grokKeybindDisplay');

        kbBtn.onclick = () => {
            isRecordingKeybind = true;
            kbBtn.classList.add('recording');
            kbBtn.innerText = 'Press keys...';
        };

        // Auto Track Toggle
        const autoTrackToggle = document.getElementById('grokAutoTrackToggle');
        autoTrackToggle.checked = currentSettings.autoTrack;
        autoTrackToggle.onchange = () => {
            const s = getSettings();
            s.autoTrack = autoTrackToggle.checked;
            saveSettings(s);
            showToast(autoTrackToggle.checked ? 'Auto-Capture Enabled' : 'Auto-Capture Disabled');
        };

        // Silent Mode Toggle
        const silentModeToggle = document.getElementById('grokSilentModeToggle');
        silentModeToggle.checked = currentSettings.silentMode;
        silentModeToggle.onchange = () => {
            const s = getSettings();
            s.silentMode = silentModeToggle.checked;
            saveSettings(s);
            showToast(silentModeToggle.checked ? 'Silent Mode Enabled' : 'Silent Mode Disabled');
        };

        document.querySelectorAll('.grok-prompt-star').forEach(s => {
            s.onclick = () => {
                currentRating = parseInt(s.dataset.rating);
                document.querySelectorAll('.grok-prompt-star').forEach((st,i) => {
                    st.classList.toggle('filled', i < currentRating);
                });
            };
        });

        document.getElementById('grokSaveBtn').onclick = () => {
            const text = document.getElementById('grokPromptInput').value.trim();
            if (!text || !currentRating) return alert('Please add text and a rating.');
            const cat = document.getElementById('grokCategorySelect').value;
            const prompts = getPrompts();
            prompts.push({ id: Date.now().toString(), text, rating: currentRating, category: cat, timestamp: Date.now() });
            savePrompts(prompts);
            document.getElementById('grokPromptInput').value = '';
            currentRating = 0;
            document.querySelectorAll('.grok-prompt-star').forEach(s => s.classList.remove('filled'));
            showToast('Prompt Saved!');
            document.querySelector('[data-tab="saved"]').click();
        };

        document.getElementById('grokAddCategoryBtn').onclick = () => {
            const val = document.getElementById('grokNewCategory').value.trim();
            if (!val) return;
            const cats = getCategories();
            if (!cats.includes(val)) {
                cats.push(val);
                saveCategories(cats);
                document.getElementById('grokNewCategory').value = '';
                renderCategories();
                updateCategorySelect();
                showToast('Category added');
            }
        };

        document.getElementById('grokExportBtn').onclick = () => {
            const data = JSON.stringify({ prompts: getPrompts(), categories: getCategories() }, null, 2);
            const blob = new Blob([data], {type: 'application/json'});
            const a = document.createElement('a');
            a.href = URL.createObjectURL(blob);
            a.download = `grok-prompts-${new Date().toISOString().split('T')[0]}.json`;
            a.click();
        };

        document.getElementById('grokImportBtn').onclick = () => document.getElementById('grokImportFile').click();
        document.getElementById('grokImportFile').onchange = (e) => {
            const fr = new FileReader();
            fr.onload = (ev) => {
                try {
                    const d = JSON.parse(ev.target.result);

                    if (confirm('Merge with existing (OK) or Replace All (Cancel)?')) {
                        const currentPrompts = getPrompts();
                        const importedPrompts = d.prompts || [];

                        // Create a map of existing prompts by ID
                        const promptMap = new Map(currentPrompts.map(p => [p.id, p]));

                        // Smart Merge: Update existing, Add new
                        importedPrompts.forEach(newP => {
                            if (promptMap.has(newP.id)) {
                                // If ID exists, merge properties (preserves your recent edits + imported data)
                                const existing = promptMap.get(newP.id);
                                promptMap.set(newP.id, { ...existing, ...newP });
                            } else {
                                // If ID is new, add it
                                promptMap.set(newP.id, newP);
                            }
                        });

                        savePrompts(Array.from(promptMap.values()));

                        // Merge Categories
                        const newCats = new Set([...getCategories(), ...(d.categories || [])]);
                        saveCategories(Array.from(newCats));

                    } else {
                        // Replace All Logic
                        savePrompts(d.prompts || []);
                        saveCategories(d.categories || ['General']);
                    }

                    showToast('Import Successful');
                    refreshActiveTab();
                    // Reload categories drop down
                    renderCategories();
                    updateCategorySelect();

                } catch(err) {
                    console.error(err);
                    alert('Invalid file format');
                }
            };
            fr.readAsText(e.target.files[0]);
        };

        document.getElementById('grokClearBtn').onclick = () => {
            if (confirm('PERMANENTLY DELETE ALL DATA?')) {
                savePrompts([]);
                saveCategories(['General']);
                location.reload();
            }
        };

        document.addEventListener('keydown', (e) => {
            // Handle Keybind Recording
            if (isRecordingKeybind) {
                e.preventDefault();
                e.stopPropagation();

                // Ignore isolated modifier presses
                if (['Control','Alt','Shift','Meta'].includes(e.key)) return;

                const newKb = {
                    key: e.key,
                    altKey: e.altKey,
                    ctrlKey: e.ctrlKey,
                    shiftKey: e.shiftKey,
                    metaKey: e.metaKey
                };

                const s = getSettings();
                s.keybind = newKb;
                saveSettings(s);

                kbDisplay.innerText = getKeybindString(newKb);
                kbBtn.classList.remove('recording');
                kbBtn.innerText = 'Change Keybind';
                isRecordingKeybind = false;
                showToast('Keybind Saved');
                return;
            }

            // Handle Trigger
            const s = getSettings();
            const kb = s.keybind || { key: 'k', altKey: true };

            const matchKey = e.key.toLowerCase() === kb.key.toLowerCase();
            const matchAlt = e.altKey === (kb.altKey || false);
            const matchCtrl = e.ctrlKey === (kb.ctrlKey || false);
            const matchShift = e.shiftKey === (kb.shiftKey || false);
            const matchMeta = e.metaKey === (kb.metaKey || false);

            if (matchKey && matchAlt && matchCtrl && matchShift && matchMeta) {
                e.preventDefault();
                isOpen = !isOpen;
                if (isOpen) {
                    overlay.style.display = 'flex';
                    overlay.offsetHeight;
                    overlay.classList.add('open');
                    updateCounts();
                    updateCategorySelect();
                    refreshActiveTab();
                } else {
                    overlay.classList.remove('open');
                    setTimeout(() => overlay.style.display = 'none', 200);
                }
            }

            if (e.key === 'Escape' && isOpen) document.getElementById('grokCloseBtn').click();
        });

        updateCounts();
        updateCategorySelect();
    }

    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initScript);
    else initScript();

})();