DeepSeek Chat Advanced

Añade funcionalidades avanzadas a DeepSeek!

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

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

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

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

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name         DeepSeek Chat Advanced
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Añade funcionalidades avanzadas a DeepSeek!
// @match        https://chat.deepseek.com/*
// @author       YouTubeDrawaria
// @grant        none
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=chat.deepseek.com
// ==/UserScript==

(function() {
    'use strict';

    // Selectores específicos para DeepSeek
    const SELECTORS = {
        CHAT_INPUT_TEXTAREA: 'textarea#chat-input',
        CHAT_INPUT_CONTAINER: '.dd442025._42b6996',
        RESPONSE_CONTAINER: '.ds-markdown.ds-markdown--block',
        MESSAGE_CONTENT: '.ds-markdown-paragraph',
        SEND_BUTTON: '.ds-button.ds-button--primary',
        FILE_INPUT: 'input[type="file"]',
        CHAR_COUNTER: '#deepseek-char-counter'
    };

    // Prompts categorizados
    const ALL_CATEGORIZED_PROMPTS = {
        "Prompts de Juego": [
            { name: "Juego Simple HTML", text: `Crea un juego en un solo archivo HTML. No uses data:image/png;base64. Genera los gráficos usando formas y SVG.` },
            { name: "Juego Completo", text: `Genera recursos, sprites, assets, sfx, música, mecánicas, conceptos, diseños de juego, ideas y características para un juego completo. Sé preciso, inteligente y conciso.` },
            { name: "Recrear Juego", text: `Crea un prompt detallado para que una IA recree un juego existente. Explica paso a paso cómo debe abordar la recreación.` },
            { name: "Juego Complejo HTML", text: `Crea un juego en un solo archivo HTML con un mapa grande, añade elementos, objetos, detalles y los mejores gráficos.` }
        ],
        "Prompts Web": [
            { name: "Web Moderna", text: `Crea el código para una landing page de un sitio web moderno. Make sure it looks nice and well designed` }
        ],
        "Prompts Personaje": [
            { name: "Descripción Personaje", text: `Haz una descripción larga describiendo todo sobre el personaje con información extra detallada.` }
        ],
        "Prompts de Scripting/Desarrollo": [
            { name: "Script Tampermonkey", text: `Crea un script tampermonkey completo con funcionalidades avanzadas. No uses placeholders ni archivos externos.` },
            { name: "API Integration", text: `Proporciona información sobre APIs gratuitas que se puedan integrar rápidamente sin problemas de CORS.` }
        ],
        "Prompts Análisis y Razonamiento": [
            { name: "Crear Script Drawaria", text: `Crea un script tampermonkey completo para drawaria.online con la siguiente estructura inicial:\n // ==UserScript==\n// @name New Userscript\n// @namespace http://tampermonkey.net/\n// @version 1.0\n// @description try to take over the world!\n// @author YouTubeDrawaria\n// @match https://drawaria.online/*\n// @grant none\n// @license MIT\n// @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online\n// ==/UserScript==\n\n(function() {\n    'use strict';\n\n    // Your code here...\n})();\n` },
            { name: "Script Drawaria Avanzado", text: "Crea un script tampermonkey completo para drawaria.online con funcionalidades avanzadas: efectos visuales, partículas, animaciones, interfaz mejorada, y características especiales. No uses placeholders ni archivos externos." },
            { name: "Mejorar Script Drawaria", text: `Mejora, actualiza, maximiza, sorprende, crea realismo y alto nivel de detalle en el script para drawaria.online. Quiero elementos de X en pantalla, música, efectos, partículas, brillos y una interfaz bien animada y detallada con todo. No uses placeholders, .mp3 ni data:image/png;base64. Debes crear los gráficos tú mismo, sin archivos reemplazables.` },
            { name: "Atributos de Juego", text: `Dame los atributos de un juego. Incluye: icono del juego (<link rel="icon" href="https://drawaria.online/avatar/cache/ab53c430-1b2c-11f0-af95-072f6d4ed084.1749767757401.jpg" type="image/x-icon">) y música de fondo con reproducción automática al hacer clic: (<audio id="bg-music" src="https://www.myinstants.com/media/sounds/super-mini-juegos-2.mp3" loop></audio><script>const music = document.getElementById('bg-music'); document.body.addEventListener('click', () => { if (music.paused) { music.play(); } });</script>).` },
            { name: "API Cubic Engine Info", text: `Proporciona información sobre APIs ampliamente utilizadas que no estén alojadas en Vercel, no presenten problemas con CORS al usarlas desde navegadores/shell, se puedan integrar rápidamente en Cubic Engine / Drawaria, y sean gratuitas y de uso inmediato.` },
            { name: "Integrar Función Cubic Engine", text: `Para integrar una nueva adición a un módulo de Cubic Engine, necesito el código completo actualizado de la función. Esto incluye el botón con todas sus propiedades, los activadores con sus IDs, los listeners de este evento y los archivos que lo ejecutan. Solo proporciona el código de la función actualizada, no el código de Cubic Engine desde cero.` }
        ]
    };

    let featuresInitialized = false;
    let draggableMenu = null; // Referencia global para el menú draggable

    /**
     * Crea un botón con estilos de DeepSeek
     */
    function createButton(text, onClick, styles = {}) {
        const button = document.createElement('button');
        button.textContent = text;
        button.className = 'ds-button ds-button--primary ds-button--filled ds-button--rect ds-button--m';
        button.style.cssText = `
            background: linear-gradient(135deg, #1B73FF 0%, #0C5ADB 100%);
            color: white;
            padding: 8px 16px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            margin: 0;
            transition: all 0.3s ease;
            white-space: nowrap;
            box-shadow: 0 2px 8px rgba(27, 115, 255, 0.2);
            ${Object.entries(styles).map(([key, value]) => `${key}:${value};`).join('')}
        `;
        button.onmouseover = () => {
            button.style.transform = 'translateY(-1px)';
            button.style.boxShadow = '0 4px 12px rgba(27, 115, 255, 0.3)';
            button.style.background = 'linear-gradient(135deg, #2B7EFF 0%, #1C64E5 100%)';
        };
        button.onmouseout = () => {
            button.style.transform = 'translateY(0)';
            button.style.boxShadow = '0 2px 8px rgba(27, 115, 255, 0.2)';
            button.style.background = 'linear-gradient(135deg, #1B73FF 0%, #0C5ADB 100%)';
        };
        button.onclick = onClick;
        return button;
    }

    /**
     * Crea un menú desplegable categorizado
     */
    function createCategorizedDropdown(categorizedOptions, onSelect, placeholder = "Seleccionar Prompt") {
        const select = document.createElement('select');
        select.style.cssText = `
            background: linear-gradient(135deg, #1B73FF 0%, #0C5ADB 100%);
            color: white;
            padding: 8px 12px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            margin: 0;
            min-width: 100%;
            transition: all 0.3s ease;
            box-shadow: 0 2px 8px rgba(27, 115, 255, 0.2);
            -webkit-appearance: none;
            -moz-appearance: none;
            appearance: none;
            background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20256%20256%22%3E%3Cpolygon%20points%3D%22208%2C80%20128%2C160%2048%2C80%22%20fill%3D%22%23ffffff%22%2F%3E%3C%2Fsvg%3E');
            background-repeat: no-repeat;
            background-position: right 8px center;
            background-size: 16px;
        `;

        const defaultOption = document.createElement('option');
        defaultOption.value = "";
        defaultOption.textContent = placeholder;
        defaultOption.disabled = true;
        defaultOption.selected = true;
        select.appendChild(defaultOption);

        for (const category in categorizedOptions) {
            const optgroup = document.createElement('optgroup');
            optgroup.label = category;
            optgroup.style.cssText = 'background: #1a1a1a; color: white;';
            categorizedOptions[category].forEach(opt => {
                const option = document.createElement('option');
                option.value = opt.text;
                option.textContent = opt.name;
                option.style.cssText = 'background: #1a1a1a; color: white; padding: 4px;';
                optgroup.appendChild(option);
            });
            select.appendChild(optgroup);
        }

        select.onchange = (event) => {
            if (event.target.value) {
                onSelect(event.target.value);
                event.target.value = "";
                defaultOption.selected = true;
            }
        };

        select.onmouseover = () => {
            select.style.transform = 'translateY(-1px)';
            select.style.boxShadow = '0 4px 12px rgba(27, 115, 255, 0.3)';
        };

        select.onmouseout = () => {
            select.style.transform = 'translateY(0)';
            select.style.boxShadow = '0 2px 8px rgba(27, 115, 255, 0.2)';
        };

        return select;
    }

    /**
     * Crea y muestra un modal
     */
    function showModal(title, contentHtml) {
        const existingModal = document.getElementById('deepseek-custom-modal-overlay');
        if (existingModal) {
            existingModal.remove();
        }

        const modalOverlay = document.createElement('div');
        modalOverlay.id = 'deepseek-custom-modal-overlay';
        modalOverlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10000;
            backdrop-filter: blur(5px);
        `;

        const modalContent = document.createElement('div');
        modalContent.style.cssText = `
            background: linear-gradient(135deg, #0F0F0F 0%, #1a1a1a 100%);
            color: white;
            padding: 30px;
            border-radius: 16px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
            max-width: 80%;
            max-height: 80%;
            overflow-y: auto;
            position: relative;
            border: 1px solid #333;
        `;

        const modalTitle = document.createElement('h3');
        modalTitle.textContent = title;
        modalTitle.style.cssText = `
            margin-top: 0;
            margin-bottom: 20px;
            color: #1B73FF;
            font-size: 1.4em;
            text-align: center;
            font-weight: 600;
        `;

        const closeButton = document.createElement('button');
        closeButton.textContent = '×';
        closeButton.style.cssText = `
            position: absolute;
            top: 15px;
            right: 20px;
            background: none;
            border: none;
            color: #ccc;
            font-size: 1.5em;
            cursor: pointer;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s ease;
        `;
        closeButton.onmouseover = () => {
            closeButton.style.backgroundColor = '#333';
            closeButton.style.color = 'white';
        };
        closeButton.onmouseout = () => {
            closeButton.style.backgroundColor = 'transparent';
            closeButton.style.color = '#ccc';
        };
        closeButton.onclick = () => modalOverlay.remove();

        modalContent.appendChild(closeButton);
        modalContent.appendChild(modalTitle);

        const contentDiv = document.createElement('div');
        contentDiv.innerHTML = contentHtml;
        modalContent.appendChild(contentDiv);

        modalOverlay.appendChild(modalContent);
        document.body.appendChild(modalOverlay);
    }

    /**
     * Establece el valor del textarea de forma que React lo reconozca
     */
    function setNativeValue(element, value) {
        const lastValue = element.value;
        element.value = value;
        const event = new Event('input', { bubbles: true });
        event.simulated = true;
        const tracker = element._valueTracker;
        if (tracker) {
            tracker.setValue(lastValue);
        }
        element.dispatchEvent(event);

        // También disparamos eventos de cambio para DeepSeek
        element.dispatchEvent(new Event('change', { bubbles: true }));
        element.dispatchEvent(new Event('keyup', { bubbles: true }));
    }

    /**
     * Obtiene el contenido actual del chat
     */
    function getCurrentChatContent() {
        const responses = document.querySelectorAll(SELECTORS.MESSAGE_CONTENT);
        let chatContent = [];

        responses.forEach((response, index) => {
            const messageText = response.textContent.trim();
            if (messageText) {
                chatContent.push({
                    type: 'DeepSeek',
                    text: messageText,
                    timestamp: new Date().toISOString(),
                    index: index
                });
            }
        });

        return chatContent;
    }

    /**
     * Guarda la conversación actual
     */
    function saveCurrentChat() {
        const chatContent = getCurrentChatContent();
        if (chatContent.length === 0) {
            alert('No hay conversación para guardar.');
            return;
        }

        const chatName = prompt("Introduce un nombre para esta conversación:", `DeepSeek Chat ${new Date().toLocaleString()}`);
        if (chatName) {
            try {
                const savedChats = JSON.parse(localStorage.getItem('deepseek_chat_conversations') || '[]');
                savedChats.push({
                    name: chatName,
                    timestamp: new Date().toISOString(),
                    messages: chatContent,
                    url: window.location.href
                });
                localStorage.setItem('deepseek_chat_conversations', JSON.stringify(savedChats));
                alert(`Conversación "${chatName}" guardada con éxito.`);
            } catch (e) {
                console.error("Error al guardar la conversación:", e);
                alert("Error al guardar la conversación.");
            }
        }
    }

    /**
     * Carga las conversaciones guardadas
     */
    function loadSavedChats() {
        const savedChats = JSON.parse(localStorage.getItem('deepseek_chat_conversations') || '[]');
        if (savedChats.length === 0) {
            alert('No hay conversaciones guardadas.');
            return;
        }

        let chatListHtml = '<div style="max-height: 400px; overflow-y: auto;">';
        savedChats.forEach((chat, index) => {
            chatListHtml += `
                <div style="margin-bottom: 15px; background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%); padding: 15px; border-radius: 12px; border: 1px solid #333;">
                    <div style="display: flex; justify-content: space-between; align-items: center;">
                        <div>
                            <div style="font-size: 1.1em; font-weight: 600; color: #1B73FF; margin-bottom: 4px;">${chat.name}</div>
                            <div style="font-size: 0.9em; color: #aaa;">${new Date(chat.timestamp).toLocaleString()}</div>
                            <div style="font-size: 0.8em; color: #888;">${chat.messages.length} respuestas</div>
                        </div>
                        <div>
                            <button class="view-chat-btn" data-index="${index}" style="background: #1B73FF; color: white; border: none; padding: 8px 12px; border-radius: 8px; cursor: pointer; margin-right: 8px; font-size: 12px;">Ver</button>
                            <button class="delete-chat-btn" data-index="${index}" style="background: #dc3545; color: white; border: none; padding: 8px 12px; border-radius: 8px; cursor: pointer; font-size: 12px;">Eliminar</button>
                        </div>
                    </div>
                </div>
            `;
        });
        chatListHtml += '</div>';

        showModal('Conversaciones Guardadas', chatListHtml);

        // Event listeners para los botones
        document.querySelectorAll('.view-chat-btn').forEach(button => {
            button.onclick = (e) => {
                const index = e.target.dataset.index;
                const chatToView = savedChats[index];
                let chatViewHtml = '<div style="background: #0F0F0F; padding: 15px; border-radius: 12px; max-height: 400px; overflow-y: auto; border: 1px solid #333;">';
                chatToView.messages.forEach((msg, msgIndex) => {
                    chatViewHtml += `
                        <div style="margin-bottom: 15px; padding: 12px; background: #1a1a1a; border-radius: 12px; border-left: 4px solid #1B73FF;">
                            <div style="color: #1B73FF; font-weight: 600; margin-bottom: 8px;">Respuesta ${msgIndex + 1}:</div>
                            <div style="color: #e0e0e0; line-height: 1.5;">${msg.text}</div>
                        </div>
                    `;
                });
                chatViewHtml += '</div>';
                showModal(`Ver Conversación: ${chatToView.name}`, chatViewHtml);
            };
        });

        document.querySelectorAll('.delete-chat-btn').forEach(button => {
            button.onclick = (e) => {
                const indexToDelete = parseInt(e.target.dataset.index);
                if (confirm(`¿Estás seguro de que quieres eliminar la conversación "${savedChats[indexToDelete].name}"?`)) {
                    savedChats.splice(indexToDelete, 1);
                    localStorage.setItem('deepseek_chat_conversations', JSON.stringify(savedChats));
                    alert('Conversación eliminada.');
                    document.getElementById('deepseek-custom-modal-overlay')?.remove();
                    loadSavedChats();
                }
            };
        });
    }

    /**
     * Exporta la conversación a un archivo de texto
     */
    function exportChatToText() {
        const chatContent = getCurrentChatContent();
        if (chatContent.length === 0) {
            alert('No hay conversación para exportar.');
            return;
        }

        let exportText = `--- Conversación DeepSeek Chat (${new Date().toLocaleString()}) ---\n\n`;
        chatContent.forEach((msg, index) => {
            exportText += `Respuesta ${index + 1}:\n${msg.text}\n\n`;
        });
        exportText += `--- Fin de la Conversación ---\n`;

        const blob = new Blob([exportText], { type: 'text/plain; charset=utf-8' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `deepseek_chat_${new Date().toISOString().replace(/[:.]/g, '-')}.txt`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        alert('Conversación exportada a un archivo de texto.');
    }

    /**
     * Inserta un prompt en el textarea
     */
    function handlePromptSelection(promptText) {
        const inputTextArea = document.querySelector(SELECTORS.CHAT_INPUT_TEXTAREA);
        if (inputTextArea) {
            setNativeValue(inputTextArea, promptText);
            inputTextArea.focus();
        }
    }

    /**
     * Carga bibliotecas dinámicamente para OCR y procesamiento de archivos
     */
    function loadTesseractJs() {
        return new Promise((resolve, reject) => {
            if (window.Tesseract) {
                resolve();
                return;
            }
            const script = document.createElement('script');
            script.src = "https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js";
            script.onload = () => resolve();
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }

    function loadPdfJs() {
        return new Promise((resolve, reject) => {
            if (window.pdfjsLib) {
                resolve();
                return;
            }
            const script = document.createElement('script');
            script.src = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.min.js";
            script.onload = () => {
                window.pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.worker.min.js";
                resolve();
            };
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }

    function loadMammothJs() {
        return new Promise((resolve, reject) => {
            if (window.mammoth) {
                resolve();
                return;
            }
            const script = document.createElement('script');
            script.src = "https://unpkg.com/mammoth/mammoth.browser.min.js";
            script.onload = () => resolve();
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }

    /**
     * Procesa archivos importados
     */
    async function processDroppedFiles(files) {
        const inputTextArea = document.querySelector(SELECTORS.CHAT_INPUT_TEXTAREA);
        if (!inputTextArea) return;

        let allContent = '';
        for (const file of files) {
            const extension = file.name.split('.').pop().toLowerCase();
            try {
                if (['txt', 'md', 'html', 'css', 'js', 'json'].includes(extension)) {
                    const content = await readFileAsText(file);
                    allContent += `\n\n--- Contenido de ${file.name} ---\n${content}`;
                } else if (['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'].includes(extension)) {
                    await loadTesseractJs();
                    const originalText = document.getElementById('deepseek-main-draggable-menu').querySelector('#deepseek-menu-header').textContent;
                    document.getElementById('deepseek-main-draggable-menu').querySelector('#deepseek-menu-header').textContent = 'DeepSeek Advanced Menu (Procesando OCR...)';
                    const { data: { text } } = await Tesseract.recognize(file, 'spa+eng');
                    allContent += `\n\n--- OCR de ${file.name} ---\n${text.trim()}`;
                    document.getElementById('deepseek-main-draggable-menu').querySelector('#deepseek-menu-header').textContent = originalText;
                } else if (extension === 'pdf') {
                    await loadPdfJs();
                    const text = await extractTextFromPdf(file);
                    allContent += `\n\n--- Contenido de PDF ${file.name} ---\n${text}`;
                } else if (extension === 'docx') {
                    await loadMammothJs();
                    const text = await extractTextFromDocx(file);
                    allContent += `\n\n--- Contenido de Word ${file.name} ---\n${text}`;
                } else {
                    alert(`Tipo de archivo no soportado: ${file.name}`);
                    continue;
                }
            } catch (error) {
                console.error(`Error procesando ${file.name}:`, error);
                alert(`Error procesando ${file.name}: ${error.message}`);
            }
        }

        if (allContent) {
            const currentValue = inputTextArea.value;
            setNativeValue(inputTextArea, currentValue + allContent);
        }
    }

    function readFileAsText(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => resolve(e.target.result);
            reader.onerror = reject;
            reader.readAsText(file);
        });
    }

    async function extractTextFromPdf(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const typedarray = new Uint8Array(e.target.result);
                    const loadingTask = window.pdfjsLib.getDocument({ data: typedarray });
                    const pdf = await loadingTask.promise;
                    let text = '';
                    for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
                        const page = await pdf.getPage(pageNum);
                        const content = await page.getTextContent();
                        text += content.items.map(item => item.str).join(' ') + '\n';
                    }
                    resolve(text);
                } catch (err) {
                    reject(err);
                }
            };
            reader.onerror = reject;
            reader.readAsArrayBuffer(file);
        });
    }

    async function extractTextFromDocx(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const result = await mammoth.extractRawText({ arrayBuffer: e.target.result });
                    resolve(result.value.trim());
                } catch (err) {
                    reject(err);
                }
            };
            reader.onerror = reject;
            reader.readAsArrayBuffer(file);
        });
    }

    /**
     * Añade contador de caracteres
     */
    function addCharCounter() {
        const inputTextArea = document.querySelector(SELECTORS.CHAT_INPUT_TEXTAREA);
        const inputContainer = document.querySelector(SELECTORS.CHAT_INPUT_CONTAINER);

        if (!inputTextArea || !inputContainer) return;

        // Verificar si ya existe
        if (document.querySelector(SELECTORS.CHAR_COUNTER)) return;

        const counter = document.createElement('div');
        counter.id = 'deepseek-char-counter';
        counter.style.cssText = `
            position: absolute;
            bottom: 8px;
            right: 12px;
            font-size: 11px;
            color: #1B73FF;
            background: rgba(27, 115, 255, 0.1);
            padding: 4px 8px;
            border-radius: 8px;
            z-index: 10;
            pointer-events: none;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            border: 1px solid rgba(27, 115, 255, 0.2);
            font-weight: 500;
        `;

        const updateCounter = () => {
            const count = inputTextArea.value.length;
            counter.textContent = `${count} chars`;
        };

        inputTextArea.addEventListener('input', updateCounter);
        updateCounter();

        inputContainer.style.position = 'relative';
        inputContainer.appendChild(counter);
    }

    /**
     * Configura la funcionalidad de editar y reenviar mensajes
     */
    function setupEditAndResend() {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach((node) => {
                        if (node.nodeType === 1) {
                            const responses = node.querySelectorAll ? node.querySelectorAll(SELECTORS.MESSAGE_CONTENT) : [];
                            responses.forEach(addEditFunctionality);
                            if (node.matches && node.matches(SELECTORS.MESSAGE_CONTENT)) {
                                addEditFunctionality(node);
                            }
                        }
                    });
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });

        // Añadir a elementos existentes
        document.querySelectorAll(SELECTORS.MESSAGE_CONTENT).forEach(addEditFunctionality);
    }

    function addEditFunctionality(element) {
        if (element.dataset.editEnabled) return;
        element.dataset.editEnabled = 'true';

        element.style.cursor = 'pointer';
        element.style.transition = 'all 0.3s ease';
        element.title = 'Clic para usar esta respuesta como prompt';

        element.addEventListener('click', () => {
            const text = element.textContent.trim();
            if (text) {
                const textarea = document.querySelector(SELECTORS.CHAT_INPUT_TEXTAREA);
                if (textarea) {
                    setNativeValue(textarea, text);
                    textarea.focus();
                    element.style.background = 'rgba(27, 115, 255, 0.1)';
                    element.style.borderRadius = '12px';
                    element.style.padding = '8px';
                    setTimeout(() => {
                        element.style.background = '';
                        element.style.borderRadius = '';
                        element.style.padding = '';
                    }, 1000);
                }
            }
        });

        element.addEventListener('mouseenter', () => {
            element.style.background = 'rgba(27, 115, 255, 0.05)';
            element.style.borderRadius = '12px';
            element.style.padding = '8px';
        });

        element.addEventListener('mouseleave', () => {
            if (!element.style.background.includes('0.1')) {
                element.style.background = '';
                element.style.borderRadius = '';
                element.style.padding = '';
            }
        });
    }

    /**
     * Crea el menú principal draggable
     */
    function createDraggableMainMenu() {
        if (draggableMenu) return draggableMenu;

        draggableMenu = document.createElement('div');
        draggableMenu.id = 'deepseek-main-draggable-menu';
        draggableMenu.style.cssText = `
            position: fixed;
            top: 100px;
            right: 20px;
            background: linear-gradient(135deg, #0F0F0F 0%, #1a1a1a 100%);
            border: 1px solid #333;
            border-radius: 16px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
            z-index: 10001;
            width: auto;
            max-width: 320px;
            min-width: 220px;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            resize: both;
            min-height: 120px;
            backdrop-filter: blur(12px);
        `;

        const menuHeader = document.createElement('div');
        menuHeader.id = 'deepseek-menu-header';
        menuHeader.style.cssText = `
            background: linear-gradient(135deg, #1B73FF 0%, #0C5ADB 100%);
            color: white;
            padding: 12px 16px;
            cursor: grab;
            border-top-left-radius: 14px;
            border-top-right-radius: 14px;
            font-weight: 600;
            display: flex;
            justify-content: space-between;
            align-items: center;
            user-select: none;
        `;
        menuHeader.textContent = 'DeepSeek Advanced Menu';

        const closeButton = document.createElement('button');
        closeButton.textContent = '×';
        closeButton.style.cssText = `
            background: none;
            border: none;
            color: white;
            font-size: 1.5em;
            cursor: pointer;
            line-height: 1;
            padding: 0 5px;
            transition: color 0.2s;
        `;
        closeButton.onmouseover = () => closeButton.style.color = '#eee';
        closeButton.onmouseout = () => closeButton.style.color = 'white';
        closeButton.onclick = () => draggableMenu.style.display = 'none';

        menuHeader.appendChild(closeButton);
        draggableMenu.appendChild(menuHeader);

        const menuContent = document.createElement('div');
        menuContent.id = 'deepseek-menu-content';
        menuContent.style.cssText = `
            padding: 16px;
            display: flex;
            flex-direction: column;
            gap: 12px;
            align-items: stretch;
        `;
        draggableMenu.appendChild(menuContent);
        document.body.appendChild(draggableMenu);

        // Funcionalidad de arrastrar
        let isDragging = false;
        let offsetX, offsetY;

        menuHeader.addEventListener('mousedown', (e) => {
            isDragging = true;
            offsetX = e.clientX - draggableMenu.getBoundingClientRect().left;
            offsetY = e.clientY - draggableMenu.getBoundingClientRect().top;
            menuHeader.style.cursor = 'grabbing';
            document.body.style.userSelect = 'none';
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            draggableMenu.style.left = (e.clientX - offsetX) + 'px';
            draggableMenu.style.top = (e.clientY - offsetY) + 'px';
            draggableMenu.style.right = 'auto';
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
            menuHeader.style.cursor = 'grab';
            document.body.style.userSelect = '';
        });

        return draggableMenu;
    }

    /**
     * Crea un botón flotante para alternar el menú principal
     */
    function createToggleMenuButton() {
        const existingToggleButton = document.getElementById('deepseek-toggle-menu-button');
        if (existingToggleButton) return;

        const toggleButton = document.createElement('button');
        toggleButton.id = 'deepseek-toggle-menu-button';
        toggleButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <path d="M12 2v6h4"/>
            <path d="M12 8V4H8"/>
            <path d="M22 13a8 8 0 0 1-8 8H6a2 2 0 0 0-2 2v-4a2 2 0 0 0-2-2 8 8 0 0 1 8-8h2a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H6C2.686 0 0 2.686 0 6v6c0 3.314 2.686 6 6 6h8c4.418 0 8-3.582 8-8z"/>
        </svg>`;
        toggleButton.title = "Toggle DeepSeek Advanced Menu";
        toggleButton.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: linear-gradient(135deg, #1B73FF 0%, #0C5ADB 100%);
            color: white;
            border: none;
            border-radius: 50%;
            width: 56px;
            height: 56px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            box-shadow: 0 4px 15px rgba(27, 115, 255, 0.3);
            z-index: 10002;
            transition: all 0.3s ease;
        `;
        toggleButton.onmouseover = () => {
            toggleButton.style.transform = 'scale(1.05)';
            toggleButton.style.boxShadow = '0 6px 20px rgba(27, 115, 255, 0.4)';
        };
        toggleButton.onmouseout = () => {
            toggleButton.style.transform = 'scale(1)';
            toggleButton.style.boxShadow = '0 4px 15px rgba(27, 115, 255, 0.3)';
        };
        toggleButton.onclick = () => {
            if (draggableMenu) {
                draggableMenu.style.display = draggableMenu.style.display === 'none' ? 'flex' : 'none';
            }
        };
        document.body.appendChild(toggleButton);
    }

    /**
     * Inicializa todas las funcionalidades
     */
    function initializeFeatures() {
        if (featuresInitialized) return;

        const chatInputTextArea = document.querySelector(SELECTORS.CHAT_INPUT_TEXTAREA);
        if (!chatInputTextArea) {
            return;
        }

        featuresInitialized = true;

        const menu = createDraggableMainMenu();
        const menuContent = document.getElementById('deepseek-menu-content');

        // Crear elementos del menú
        const promptsDropdown = createCategorizedDropdown(ALL_CATEGORIZED_PROMPTS, handlePromptSelection, "🚀 Seleccionar Prompt");
        const saveButton = createButton('💾 Guardar Conversación', saveCurrentChat, {width: '100%'});
        const loadButton = createButton('📂 Cargar Conversaciones', loadSavedChats, {width: '100%'});
        const exportButton = createButton('📤 Exportar (TXT)', exportChatToText, {width: '100%'});

        // Input de archivos oculto
        const fileInputForMenu = document.createElement('input');
        fileInputForMenu.type = 'file';
        fileInputForMenu.multiple = true;
        fileInputForMenu.accept = '.txt,.md,.html,.css,.js,.json,.png,.jpg,.jpeg,.gif,.bmp,.webp,.pdf,.docx';
        fileInputForMenu.style.display = 'none';

        const importButtonInMenu = createButton('📁 Importar Archivos (OCR)', () => fileInputForMenu.click(), {
            background: 'linear-gradient(135deg, #10B981 0%, #059669 100%)',
            fontSize: '14px',
            width: '100%',
            marginBottom: '10px'
        });

        // Eventos drag and drop para importar
        importButtonInMenu.addEventListener('dragover', (e) => {
            e.preventDefault();
            importButtonInMenu.style.background = 'linear-gradient(135deg, #34D399 0%, #10B981 100%)';
            importButtonInMenu.style.boxShadow = '0 6px 12px rgba(16, 185, 129, 0.3)';
        });

        importButtonInMenu.addEventListener('dragleave', () => {
            importButtonInMenu.style.background = 'linear-gradient(135deg, #10B981 0%, #059669 100%)';
            importButtonInMenu.style.boxShadow = '0 2px 8px rgba(16, 185, 129, 0.2)';
        });

        importButtonInMenu.addEventListener('drop', (e) => {
            e.preventDefault();
            importButtonInMenu.style.background = 'linear-gradient(135deg, #10B981 0%, #059669 100%)';
            importButtonInMenu.style.boxShadow = '0 2px 8px rgba(16, 185, 129, 0.2)';
            if (e.dataTransfer.files.length > 0) {
                processDroppedFiles(e.dataTransfer.files);
            }
        });

        fileInputForMenu.addEventListener('change', (e) => {
            if (e.target.files.length > 0) {
                processDroppedFiles(e.target.files);
                e.target.value = '';
            }
        });

        document.body.appendChild(fileInputForMenu);

        // Añadir elementos al menú
        menuContent.appendChild(promptsDropdown);
        menuContent.appendChild(importButtonInMenu);
        menuContent.appendChild(saveButton);
        menuContent.appendChild(loadButton);
        menuContent.appendChild(exportButton);

        // Crear botón de toggle
        createToggleMenuButton();

        // Inicializar otras funcionalidades
        addCharCounter();
        setupEditAndResend();

        console.log('DeepSeek Chat Advanced: Todas las funcionalidades inicializadas.');
    }

    // Observer para esperar a que se cargue la interfaz
    const observer = new MutationObserver((mutations, obs) => {
        if (!featuresInitialized && document.querySelector(SELECTORS.CHAT_INPUT_TEXTAREA)) {
            initializeFeatures();
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    // Intentar inicializar inmediatamente si ya está cargado
    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        setTimeout(initializeFeatures, 1000);
    }
})();