Perplexity Playground Advanced Pro

Restores the Saving, exporting, and loading conversations,Managing prompts,Integrated JavaScript executor in a draggable box

// ==UserScript==
// @name         Perplexity Playground Advanced Pro
// @namespace    http://tampermonkey.net/
// @version      3.2
// @description  Restores the Saving, exporting, and loading conversations,Managing prompts,Integrated JavaScript executor in a draggable box
// @match        https://www.perplexity.ai/*
// @author       YouTubeDrawaria
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// @icon         https://web.archive.org/web/20250804233216im_/https://playground.perplexity.ai/favicon.ico
// ==/UserScript==

(function() {
    'use strict';

    // --- Configuration ---
    const CONFIG = {
        DEFAULT_MODEL_VALUE: 'sonar-pro',
        INIT_TIMEOUT: 10000,
        RETRY_INTERVAL: 500,
        MAX_RETRIES: 20,
        AUTO_SAVE_INTERVAL: 30000, // 30 segundos
        MAX_AUTO_SAVES: 50, // Máximo de autoguardados
        FLOATING_UI_INITIAL_POS_X: 20,
        FLOATING_UI_INITIAL_POS_Y: 80,
    };

    // --- CSS Selectors (kept for general element finding) ---
    const SELECTORS = {
        INPUT_TEXTAREA: 'textarea[placeholder*="Ask anything"]', // Adjusted for broad matching
        PERPLEXITY_MESSAGES: 'div[class*="bg-offset"][class*="px-md py-sm"]',
        USER_MESSAGES: 'div[class*="bg-base"][class*="px-md py-sm"][class*="inline-block"]',
        MESSAGE_TEXT_PROSE_P: '.prose p[class*="my-2"]',
        // The CONTROLS_AREA is no longer an injection point, but can be used for reference if needed.
        CONTROLS_AREA: 'div[class*="gap-x-sm flex items-center"]',
        CLEAR_BUTTON: 'button[aria-label="Clear Chat"]',
        STOP_BUTTON: 'button[aria-label="Stop Generating"]',
        SUBMIT_BUTTON: 'button[aria-label="Submit"]',
        CODE_BLOCKS: 'div[class*="-mt-xl"] code',
        CODE_CONTAINERS: 'div[data-testid="code-language-indicator"]',
        CODE_CONTENT: 'code[style*="white-space: pre-wrap"]'
    };

    // --- Categorized Prompts (unchanged) ---
    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, incluyendo el análisis del juego original, la identificación de mecánicas clave, la creación de assets, la implementación del código y las fases de prueba. Sé minucioso en cada detalle.` },
            { 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. Sé preciso, inteligente y conciso. Usa solo formas y SVG para todos los gráficos (sin base64encoded o imágenes PNG). Todos los gráficos deben ser creados usando formas y trazados SVG, sin recursos externos, con animaciones y transiciones fluidas, mecánicas de batalla por turnos adecuadas, elementos de UI responsivos, un sistema de gestión de salud, cuatro movimientos diferentes con cálculo de daño aleatorio, IA enemesa con lógica de ataque básica, y retroalimentación visual para ataques y daño.` },
            { name: "Juego Detallado", text: `Mejora, expande y perfecciona un juego existente. El juego debe tener un mapa grande, y debe incluir elementos, objetos, detalles y los mejores gráficos, junto con personajes mejorados y detallados. Quiero que todo el juego esté contenido en un solo archivo. No uses imágenes base64encoded o PNG; debes crear los gráficos con la máxima complejidad, detalle y mejora posible, utilizando únicamente formas y SVG. Haz que el juego sea lo mejor y más grande que pueda ser. Además, añade más tipos de plataformas, crea más tipos de enemigos, implementa diferentes efectos de power-up, establece un sistema de niveles, diseña distintos entornos, desarrolla una IA enemesa más compleja, haz que los movimientos de los jugadores sean más suaves y mejora la interfaz de usuario tanto para el jugador como para los enemigos.` }
        ],
        "Prompts Web": [
            { name: "Web Moderna", text: `Crea el código para una landing page de un sitio web moderno que . Make the code for landing page. 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. Haz una descripción profesional describiendo detalladamente todo sobre la imagen con información más detallada.` }
        ],
        "Prompts Canción": [
            { name: "Atributos de Canción", text: `Dame los atributos de la canción separados por comas. Atributos de la canción separados por comas.` }
        ],
        "Prompts Gemini": [
            { name: "Generar 4 Imágenes X", text: `Genera 4 nuevas [X] diferentes en 4 imágenes cada una.` }
        ],
        "Prompts de Scripting/Desarrollo": [
            { 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 retryCount = 0;
    let autoSaveInterval = null;
    let isAutoSaveActive = false;

    // --- SVG Icons (for internal windows or if text isn't chosen) ---
    const ICON_SVG = {
        DOWNLOAD: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"></path><polyline points="7 11 12 16 17 11"></polyline><line x1="12" y1="4" x2="12" y2="16"></line></svg>`,
        UPLOAD: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-10"></path><polyline points="17 7 12 2 7 7"></polyline><line x1="12" y1="4" x2="12" y2="14"></line></svg>`,
        CODE: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>`,
        AUTO_SAVE: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle><path d="M12 1v6M12 17v6M4.22 4.22l4.24 4.24M15.54 15.54l4.24 4.24"></path></svg>`,
        TOGGLE: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 8h16M4 16h16"></path></svg>`, // Example toggle icon
        PROMPTS: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2h6a2 2 0 0 1 2 2v6m-2 4v6a2 2 0 0 1 -2 2H4a2 2 0 0 1 -2 -2V4a2 2 0 0 1 2 -2h6"></path><path d="M10 9h4v4h-4z"></path></svg>`
    };


    // --- Robust Storage Manager ---
    const RobustStorage = {
        setItem: function(key, value) {
            const serialized = JSON.stringify(value);
            try {
                localStorage.setItem(key, serialized);
                return true;
            } catch (e) {
                console.warn(`⚠️ Error con localStorage para ${key}:`, e);
                try {
                    sessionStorage.setItem(key, serialized);
                    return true;
                } catch (e2) {
                    console.error(`❌ Error con sessionStorage para ${key}:`, e2);
                    return false;
                }
            }
        },
        getItem: function(key, defaultValue = null) {
            let result = null;
            try {
                result = localStorage.getItem(key);
            } catch (e) {
                console.warn(`⚠️ Error leyendo localStorage para ${key}:`, e);
                try {
                    result = sessionStorage.getItem(key);
                } catch (e2) {
                    console.error(`❌ Error leyendo sessionStorage para ${key}:`, e2);
                }
            }
            return result ? JSON.parse(result) : defaultValue;
        }
    };

    // --- Helper Functions ---
    function extractCleanCodeContent(codeElement) {
        try {
            let codeText = codeElement.innerText || codeElement.textContent || '';
            if (!codeText || codeText.length < 10) {
                const spans = codeElement.querySelectorAll('span');
                if (spans.length > 0) {
                    codeText = Array.from(spans)
                        .map(span => span.innerText || span.textContent || '')
                        .join('');
                }
            }
            if (!codeText || codeText.length < 10) {
                const codeContainer = codeElement.closest('div[class*="pr-lg"]');
                if (codeContainer) {
                    codeText = codeContainer.innerText || codeContainer.textContent || '';
                }
            }
            codeText = codeText
                .replace(/^\s*[\d\s]+/gm, '')
                .replace(/\s*\n\s*\n\s*/g, '\n')
                .trim();
            if (codeText.length > 5 && /[a-zA-Z(){};=]/.test(codeText)) {
                return codeText;
            }
            return null;
        } catch (error) {
            console.warn('⚠️ Error extrayendo código:', error);
            return null;
        }
    }

    function findElement(selectors) {
        const specificSelectors = [SELECTORS.INPUT_TEXTAREA, SELECTORS.CLEAR_BUTTON];
        if (typeof selectors === 'string') {
            const element = document.querySelector(selectors);
            if (element) return element;
        }
        const allSelectors = Array.isArray(selectors) ? [...specificSelectors, ...selectors] : specificSelectors;
        for (const selector of allSelectors) {
            const element = document.querySelector(selector);
            if (element) return element;
        }
        return null;
    }

    function createStylizedButton(text, onClick, iconHtml = null, customStyles = {}) {
        const button = document.createElement('button');
        button.className = `advanced-pro-btn`; // Custom class for styling
        button.innerHTML = iconHtml ? `<span class="icon">${iconHtml}</span> <span class="text">${text}</span>` : `<span class="text">${text}</span>`;
        if (onClick) {
            button.addEventListener('click', onClick);
        }
        Object.assign(button.style, customStyles);
        return button;
    }

    function createCategorizedDropdown(categorizedOptions, onSelect, placeholder = "Seleccionar Prompt") {
        const selectWrapper = document.createElement('div');
        selectWrapper.className = 'advanced-pro-dropdown-wrapper';

        const select = document.createElement('select');
        select.className = 'advanced-pro-dropdown-select';

        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;
            categorizedOptions[category].forEach(opt => {
                const option = document.createElement('option');
                option.value = opt.text;
                option.textContent = opt.name;
                optgroup.appendChild(option);
            });
            select.appendChild(optgroup);
        }

        select.addEventListener('change', (event) => {
            if (event.target.value) {
                onSelect(event.target.value);
                event.target.value = "";
                setTimeout(() => {
                    defaultOption.selected = true;
                }, 0);
            }
        });
        selectWrapper.appendChild(select);

        const arrow = document.createElement('span');
        arrow.className = 'advanced-pro-dropdown-arrow';
        arrow.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>`;
        selectWrapper.appendChild(arrow);

        return selectWrapper;
    }

    function getCurrentChatContent() {
        const chatContent = [];
        const allMessageContainers = document.querySelectorAll([
            'div[class*="bg-offset"]', // Perplexity responses
            'div[class*="bg-base"]',   // User messages
            'div[class*="px-md"]',     // General message container class
            '#playground-initial-message' // For Perplexity Playground Reimagined's initial message
        ].join(','));

        allMessageContainers.forEach((container, index) => {
            let fullText = '';
            // Prioritize specific text elements within the message bubble
            const messageBubble = container.querySelector('.px-md.py-sm.max-w-full.break-words');
            if (messageBubble) {
                 const proseElements = messageBubble.querySelectorAll('.prose p');
                 if (proseElements.length > 0) {
                     fullText += Array.from(proseElements).map(p => p.innerText || p.textContent || '').join('\n').trim();
                 } else {
                     fullText += (messageBubble.innerText || messageBubble.textContent || '').trim();
                 }
            } else {
                // Fallback for other message structures
                const textElements = container.querySelectorAll('p, div, span');
                textElements.forEach(el => {
                    const text = el.innerText || el.textContent || '';
                    if (text.trim() && !fullText.includes(text.trim())) {
                        fullText += text.trim() + '\n';
                    }
                });
            }


            const codeElements = container.querySelectorAll('code, pre, [class*="code"], [data-testid*="code"]');
            codeElements.forEach(codeEl => {
                const codeText = extractCleanCodeContent(codeEl);
                if (codeText && !fullText.includes(codeText)) {
                    const languageIndicator = codeEl.closest('div[class*="-mt-xl"]')
                    ?.querySelector('[data-testid="code-language-indicator"]');
                    const language = languageIndicator?.textContent?.trim() || '';
                    fullText += `\n\`\`\`${language}\n${codeText}\n\`\`\`\n`;
                }
            });

            if (fullText.trim()) {
                const messageType = container.matches('[class*="bg-base"]') || container.querySelector('.text-right') ? 'User' : 'Perplexity';
                chatContent.push({
                    type: messageType,
                    text: fullText.trim(),
                    timestamp: new Date().toISOString(),
                    index: index
                });
            }
        });

        console.log(`✅ Mensajes extraídos correctamente: ${chatContent.length}`);
        return chatContent;
    }

    function insertTextIntoTextarea(text) {
        const textarea = findElement(SELECTORS.INPUT_TEXTAREA);
        if (textarea) {
            const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
            nativeInputValueSetter.call(textarea, text);
            textarea.dispatchEvent(new Event('input', { bubbles: true }));
            textarea.dispatchEvent(new Event('change', { bubbles: true }));
            textarea.focus();
            return true;
        }
        console.warn('⚠️ No se encontró el textarea');
        return false;
    }

    function handlePromptSelection(promptText) {
        if (!insertTextIntoTextarea(promptText)) {
            navigator.clipboard.writeText(promptText).then(() => {
                console.log('📋 Contenido copiado al portapapeles: ' + promptText);
            }).catch(() => {
                console.error('❌ No se pudo copiar el prompt al portapapeles. Inténtalo de nuevo.');
            });
        } else {
            console.log('✅ Prompt insertado en el textarea.');
        }
    }

    // --- JavaScript Executor ---
    function openJSExecutorWindow() {
        console.log('⚡ === ABRIENDO EJECUTOR DE JAVASCRIPT ===');

        const newWindow = window.open('', '_blank', 'width=1200,height=800,scrollbars=yes,resizable=yes,menubar=no,toolbar=no');

        if (!newWindow) {
            console.error('❌ El navegador bloqueó la ventana emergente. Permite ventanas emergentes para perplexity.ai');
            return;
        }

        newWindow.document.open();
        newWindow.document.write('<!DOCTYPE html><html><head>');
        newWindow.document.write('<title>⚡ JavaScript Executor - Perplexity Advanced</title>');
        newWindow.document.write('<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">');

        const jsExecutorCSS = `
            * { box-sizing: border-box; margin: 0; padding: 0; }
            body {
                font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
                background: linear-gradient(135deg, #0f0f14 0%, #1a1a1f 50%, #2a2a30 100%);
                color: #e0e0e0;
                line-height: 1.6;
                min-height: 100vh;
                overflow-x: hidden;
            }
            .header {
                background: linear-gradient(90deg, #ff6b6b 0%, #feca57 50%, #48cae4 100%);
                padding: 25px 20px;
                text-align: center;
                box-shadow: 0 4px 20px rgba(255, 107, 107, 0.3);
                position: sticky;
                top: 0;
                z-index: 100;
            }
            .header h1 {
                font-size: 28px;
                font-weight: 700;
                margin-bottom: 10px;
                text-shadow: 0 2px 4px rgba(0,0,0,0.3);
                color: white;
            }
            .controls-bar {
                background: #2a2a30;
                padding: 20px;
                display: flex;
                justify-content: center;
                gap: 15px;
                flex-wrap: wrap;
                border-bottom: 1px solid #404040;
            }
            .btn {
                background: #4a4a50;
                color: white;
                border: none;
                padding: 12px 20px;
                border-radius: 8px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 600;
                transition: all 0.3s ease;
                display: flex;
                align-items: center;
                gap: 8px;
                box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            }
            .btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            }
            .btn-success { background: #10b981; }
            .btn-success:hover { background: #059669; }
            .btn-danger { background: #ef4444; }
            .btn-danger:hover { background: #dc2626; }
            .btn-warning { background: #f59e0b; }
            .btn-warning:hover { background: #d97706; }
            .btn-secondary { background: #6b7280; }
            .btn-secondary:hover { background: #4b5563; }
            .container {
                max-width: 1400px;
                margin: 0 auto;
                padding: 20px;
                display: grid;
                grid-template-columns: 1fr 1fr;
                gap: 20px;
                height: calc(100vh - 140px);
            }
            .editor-panel, .output-panel {
                background: #1e1e1e;
                border: 1px solid #404040;
                border-radius: 12px;
                padding: 20px;
                display: flex;
                flex-direction: column;
            }
            .panel-header {
                font-size: 18px;
                font-weight: bold;
                margin-bottom: 15px;
                color: #6366f1;
                display: flex;
                align-items: center;
                gap: 10px;
            }
            .code-editor {
                flex: 1;
                background: #0d1117;
                border: 1px solid #30363d;
                border-radius: 8px;
                padding: 15px;
                font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
                font-size: 14px;
                color: #c9d1d9;
                resize: none;
                outline: none;
                line-height: 1.5;
            }
            .output-area {
                flex: 1;
                background: #0d1117;
                border: 1px solid #30363d;
                border-radius: 8px;
                padding: 15px;
                font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
                font-size: 13px;
                color: #c9d1d9;
                overflow-y: auto;
                white-space: pre-wrap;
                word-wrap: break-word;
            }
            .editor-controls {
                display: flex;
                gap: 10px;
                margin-top: 15px;
                flex-wrap: wrap;
            }
            .small-btn {
                padding: 8px 12px;
                font-size: 12px;
                border-radius: 6px;
            }
            .history-panel {
                grid-column: 1 / -1;
                max-height: 200px;
                overflow-y: auto;
                background: #1e1e1e;
                border: 1px solid #404040;
                border-radius: 12px;
                padding: 15px;
                margin-top: 20px;
            }
            .history-item {
                background: #2d2d30;
                border: 1px solid #404040;
                border-radius: 8px;
                padding: 10px;
                margin-bottom: 10px;
                cursor: pointer;
                transition: all 0.2s ease;
            }
            .history-item:hover {
                border-color: #6366f1;
                background: #3a3a40;
            }
            .history-time {
                font-size: 11px;
                color: #888;
                margin-bottom: 5px;
            }
            .history-code {
                font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
                font-size: 12px;
                color: #c9d1d9;
                background: #0d1117;
                padding: 8px;
                border-radius: 4px;
                max-height: 60px;
                overflow: hidden;
                text-overflow: ellipsis;
            }
            .log-entry {
                margin: 5px 0;
                padding: 5px 8px;
                border-radius: 4px;
                border-left: 3px solid #6366f1;
            }
            .log-error {
                background: rgba(239, 68, 68, 0.1);
                border-left-color: #ef4444;
                color: #fca5a5;
            }
            .log-warn {
                background: rgba(245, 158, 11, 0.1);
                border-left-color: #f59e0b;
                color: #fbbf24;
            }
            .log-info {
                background: rgba(59, 130, 246, 0.1);
                border-left-color: #3b82f6;
                color: #93c5fd;
            }
            .log-success {
                background: rgba(16, 185, 129, 0.1);
                border-left-color: #10b981;
                color: #6ee7b7;
            }
            @media (max-width: 1200px) {
                .container {
                    grid-template-columns: 1fr;
                    gap: 15px;
                }
            }
        `;

        newWindow.document.write('<style>' + jsExecutorCSS + '</style>');
        newWindow.document.write('</head><body>');

        newWindow.document.write('<div class="header">');
        newWindow.document.write('<h1>⚡ JavaScript Executor - Perplexity Advanced</h1>');
        newWindow.document.write('<div>Ejecuta código JavaScript directamente en la página principal</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="controls-bar">');
        newWindow.document.write('<button class="btn btn-success" onclick="executeCode()">▶️ Ejecutar Código</button>');
        newWindow.document.write('<button class="btn btn-warning" onclick="clearEditor()">🗑️ Limpiar Editor</button>');
        newWindow.document.write('<button class="btn btn-secondary" onclick="clearOutput()">📄 Limpiar Salida</button>');
        newWindow.document.write('<button class="btn btn-secondary" onclick="formatCode()">✨ Formatear Código</button>');
        newWindow.document.write('<button class="btn btn-danger" onclick="window.close()">❌ Cerrar</button>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="container">');

        newWindow.document.write('<div class="editor-panel">');
        newWindow.document.write('<div class="panel-header">📝 Editor de Código JavaScript</div>');
        newWindow.document.write('<textarea id="codeEditor" class="code-editor" placeholder="// Escribe tu código JavaScript aquí...\n// Ejemplos:\n// console.log(\'Hola mundo!\');\n// document.title = \'Nuevo título\';\n// alert(\'Código ejecutado!\');\n\nconsole.log(\'¡Ejecutor de JavaScript listo!\');\ndocument.querySelector(\'body\').style.backgroundColor = \'#ff6b6b\';\nsetTimeout(() => {\n    document.querySelector(\'body\').style.backgroundColor = \'\';\n}, 2000);"></textarea>');
        newWindow.document.write('<div class="editor-controls">');
        newWindow.document.write('<button class="btn small-btn btn-success" onclick="executeCode()">▶️ Ejecutar</button>');
        newWindow.document.write('<button class="btn small-btn btn-secondary" onclick="saveToHistory()">💾 Guardar</button>');
        newWindow.document.write('<button class="btn small-btn btn-secondary" onclick="loadPreset(\'dom\')">[DOM] Preset</button>');
        newWindow.document.write('<button class="btn small-btn btn-secondary" onclick="loadPreset(\'style\')">[Style] Preset</button>');
        newWindow.document.write('<button class="btn small-btn btn-secondary" onclick="loadPreset(\'fetch\')">[Fetch] Preset</button>');
        newWindow.document.write('</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="output-panel">');
        newWindow.document.write('<div class="panel-header">📊 Salida y Logs</div>');
        newWindow.document.write('<div id="outputArea" class="output-area">⚡ Ejecutor de JavaScript iniciado...\n\n📝 Escribe código en el editor y presiona "Ejecutar" para ver los resultados aquí.\n\n💡 Tips:\n- Los console.log() aparecerán aquí\n- Los errores se mostrarán en rojo\n- El código se ejecuta en la página principal\n</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="history-panel">');
        newWindow.document.write('<div class="panel-header">🕒 Historial de Código (click para cargar)</div>');
        newWindow.document.write('<div id="historyContainer">No hay código en el historial aún...</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('</div>'); // End container

        // JavaScript funcional para el ejecutor
        const jsExecutorScript = newWindow.document.createElement('script');
        jsExecutorScript.textContent = `
            let executionHistory = JSON.parse(localStorage.getItem('perplexity_js_history') || '[]');
            const parentWindow = window.opener;
            const outputArea = document.getElementById('outputArea');
            const codeEditor = document.getElementById('codeEditor');
            const historyContainer = document.getElementById('historyContainer');

            // Interceptar console.log para mostrarlos en nuestra ventana
            const originalConsole = parentWindow.console;
            let logBuffer = [];

            function addLogEntry(message, type = 'info') {
                const timestamp = new Date().toLocaleTimeString();
                const logEntry = document.createElement('div');
                logEntry.className = 'log-entry log-' + type;
                logEntry.innerHTML = '[' + timestamp + '] ' + message;

                // Add to buffer for our output
                logBuffer.push({
                    timestamp,
                    message,
                    type
                });

                updateOutput();
            }

            function updateOutput() {
                let output = logBuffer.map(entry =>
                    '[' + entry.timestamp + '] [' + entry.type.toUpperCase() + '] ' + entry.message
                ).join('\\n');

                if (!output) {
                    output = '⚡ Listo para ejecutar código...\\n\\n💡 Los console.log() y errores aparecerán aquí.';
                }
                outputArea.textContent = output;
                outputArea.scrollTop = outputArea.scrollHeight;
            }

            function executeCode() {
                const code = codeEditor.value.trim();
                if (!code) {
                    addLogEntry('❌ No hay código para ejecutar', 'error');
                    return;
                }

                try {
                    addLogEntry('🚀 Ejecutando código...', 'info');

                    // Crear función para capturar console.log
                    const captureConsole = \`
                        const originalLog = console.log;
                        const originalError = console.error;
                        const originalWarn = console.warn;

                        console.log = function(...args) {
                            originalLog.apply(console, args);
                            if (window.jsExecutorCallback) {
                                window.jsExecutorCallback(args.join(' '), 'info');
                            }
                        };

                        console.error = function(...args) {
                            originalError.apply(console, args);
                            if (window.jsExecutorCallback) {
                                window.jsExecutorCallback(args.join(' '), 'error');
                            }
                        };

                        console.warn = function(...args) {
                            originalWarn.apply(console, args);
                            if (window.jsExecutorCallback) {
                                window.jsExecutorCallback(args.join(' '), 'warn');
                            }
                        };
                    \`;

                    // Inyectar callback en la ventana principal
                    parentWindow.jsExecutorCallback = (message, type) => {
                        addLogEntry(message, type);
                    };

                    // Ejecutar código en la ventana principal
                    parentWindow.eval(captureConsole);
                    const result = parentWindow.eval(code);

                    if (result !== undefined) {
                        addLogEntry('✅ Resultado: ' + JSON.stringify(result), 'success');
                    } else {
                        addLogEntry('✅ Código ejecutado correctamente', 'success');
                    }

                    // Guardar en historial
                    saveToHistory();

                } catch (error) {
                    addLogEntry('❌ Error: ' + error.message, 'error');
                    console.error('Error ejecutando código:', error);
                }
            }

            function clearEditor() {
                codeEditor.value = '';
                codeEditor.focus();
            }

            function clearOutput() {
                logBuffer = [];
                updateOutput();
            }

            function formatCode() {
                try {
                    const code = codeEditor.value;
                    // Formateo básico
                    const formatted = code
                        .replace(/;/g, ';\\n')
                        .replace(/{/g, '{\\n')
                        .replace(/}/g, '\\n}')
                        .replace(/\\n\\s*\\n/g, '\\n');
                    codeEditor.value = formatted;
                } catch (e) {
                    addLogEntry('⚠️ Error formateando código', 'warn');
                }
            }

            function saveToHistory() {
                const code = codeEditor.value.trim();
                if (!code) return;

                const historyItem = {
                    id: Date.now(),
                    code: code,
                    timestamp: new Date().toISOString(),
                    preview: code.substring(0, 100) + (code.length > 100 ? '...' : '')
                };

                executionHistory.unshift(historyItem);
                if (executionHistory.length > 20) {
                    executionHistory = executionHistory.slice(0, 20);
                }

                localStorage.setItem('perplexity_js_history', JSON.stringify(executionHistory));
                updateHistoryDisplay();
                addLogEntry('💾 Código guardado en historial', 'info');
            }

            function loadFromHistory(id) {
                const item = executionHistory.find(h => h.id === id);
                if (item) {
                    codeEditor.value = item.code;
                    addLogEntry('📂 Código cargado desde historial', 'info');
                }
            }

            function updateHistoryDisplay() {
                if (executionHistory.length === 0) {
                    historyContainer.innerHTML = 'No hay código en el historial aún...';
                    return;
                }

                historyContainer.innerHTML = '';
                executionHistory.forEach(item => {
                    const historyDiv = document.createElement('div');
                    historyDiv.className = 'history-item';
                    historyDiv.onclick = () => loadFromHistory(item.id);

                    historyDiv.innerHTML = \`
                        <div class="history-time">\${new Date(item.timestamp).toLocaleString()}</div>
                        <div class="history-code">\${item.preview}</div>
                    \`;

                    historyContainer.appendChild(historyDiv);
                });
            }

            function loadPreset(type) {
                const presets = {
                    dom: \`// Manipular DOM
// Cambiar texto de un elemento
document.querySelector('h1')?.textContent = 'Texto cambiado';

// Crear nuevo elemento
const newDiv = document.createElement('div');
newDiv.textContent = 'Elemento creado por JS';
newDiv.style.cssText = 'background: #ff6b6b; color: white; padding: 10px; margin: 10px; border-radius: 5px;';
document.body.appendChild(newDiv);

// Eliminar después de 3 segundos
setTimeout(() => newDiv.remove(), 3000);\`,

                    style: \`// Cambiar estilos de la página
// Cambiar fondo del body
document.body.style.background = 'linear-gradient(45deg, #ff6b6b, #4ecdc4)';

// Aplicar efecto a todos los botones
document.querySelectorAll('button').forEach(btn => {
    btn.style.transform = 'scale(1.1)';
    btn.style.transition = 'all 0.3s ease';
    btn.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
});

// Restaurar después de 5 segundos
setTimeout(() => {
    document.body.style.background = '';
    document.querySelectorAll('button').forEach(btn => {
        btn.style.transform = '';
        btn.style.boxShadow = '';
    });
}, 5000);\`,

                    fetch: \`// Hacer petición fetch
fetch('https://api.github.com/users/octocat')
    .then(response => response.json())
    .then(data => {
        console.log('Usuario GitHub:', data.name);
        console.log('Repositorios públicos:', data.public_repos);
        console.log('Seguidores:', data.followers);

        // Mostrar datos en la página
        const infoDiv = document.createElement('div');
        infoDiv.innerHTML = \\\`
            <h3>Información de GitHub</h3>
            <p>Nombre: \\\${data.name}</p>
            <p>Repos: \\\${data.public_repos}</p>
            <p>Seguidores: \\\${data.followers}</p>
        \\\`;
        infoDiv.style.cssText = 'background: #333; color: white; padding: 15px; margin: 10px; border-radius: 8px; position: fixed; top: 20px; right: 20px; z-index: 9999;';
        document.body.appendChild(infoDiv);

        setTimeout(() => infoDiv.remove(), 8000);
    })
    .catch(error => console.error('Error:', error));\`
                };

                if (presets[type]) {
                    codeEditor.value = presets[type];
                    addLogEntry('📝 Preset "' + type + '" cargado', 'info');
                }
            }

            // Inicializar
            updateHistoryDisplay();
            updateOutput();

            // Atajos de teclado
            codeEditor.addEventListener('keydown', (e) => {
                if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
                    e.preventDefault();
                    executeCode();
                }
            });

            // Focus automático
            window.addEventListener('load', () => {
                codeEditor.focus();
            });
        `;

        newWindow.document.body.appendChild(jsExecutorScript);
        newWindow.document.close();
        newWindow.focus();

        console.log('✅ Ejecutor de JavaScript abierto correctamente');
    }

    // --- Auto-Save System ---
    function startAutoSave() {
        if (isAutoSaveActive) return;

        isAutoSaveActive = true;
        console.log('🔄 Iniciando autoguardado cada', CONFIG.AUTO_SAVE_INTERVAL / 1000, 'segundos');

        autoSaveInterval = setInterval(() => {
            const chatContent = getCurrentChatContent();
            if (chatContent.length > 0) {
                saveAutoChat(chatContent);
            }
        }, CONFIG.AUTO_SAVE_INTERVAL);
    }

    function stopAutoSave() {
        if (autoSaveInterval) {
            clearInterval(autoSaveInterval);
            autoSaveInterval = null;
            isAutoSaveActive = false;
            console.log('⏹️ Autoguardado detenido');
        }
    }

    function saveAutoChat(chatContent) {
        try {
            const autoSaves = RobustStorage.getItem('perplexity_auto_saves', []);
            const timestamp = new Date().toISOString();

            let preview = 'Sin vista previa';
            if (chatContent && Array.isArray(chatContent) && chatContent.length > 0 && chatContent[0].text) {
                const firstMessage = chatContent[0].text;
                preview = firstMessage.length > 100 ? firstMessage.substring(0, 100) + '...' : firstMessage;
            }

            const autoSave = {
                id: Date.now(),
                timestamp,
                url: window.location.href,
                messageCount: chatContent.length,
                messages: chatContent,
                preview: preview,
                type: 'auto'
            };

            autoSaves.unshift(autoSave);
            if (autoSaves.length > CONFIG.MAX_AUTO_SAVES) {
                autoSaves.splice(CONFIG.MAX_AUTO_SAVES);
            }

            RobustStorage.setItem('perplexity_auto_saves', autoSaves);
            console.log('💾 Chat autoguardado:', timestamp, 'con', chatContent.length, 'mensajes');
            notifyAutoSaveWindow();

        } catch (error) {
            console.error('❌ Error autoguardando:', error);
            console.error('Error stack:', error.stack);
            console.error('Problema al procesar:', {
                chatContent: chatContent,
                chatContentLength: chatContent ? chatContent.length : 'undefined',
                firstMessageContent: chatContent && chatContent[0] ? chatContent[0].text : 'n/a'
            });
        }
    }

    function notifyAutoSaveWindow() {
        if (window.autoSaveWindows) {
            window.autoSaveWindows.forEach(win => {
                if (!win.closed) {
                    try {
                        win.postMessage({ action: 'refreshAutoSaves' }, window.location.origin);
                    } catch (e) {
                        console.warn('⚠️ Error notificando ventana autoguardado:', e);
                    }
                }
            });
        }
    }

    function openAutoSaveWindow() {
        console.log('🔄 === ABRIENDO VENTANA DE AUTOGUARDADO ===');

        const newWindow = window.open('', '_blank', 'width=1400,height=900,scrollbars=yes,resizable=yes');

        if (!newWindow) {
            console.error('❌ El navegador bloqueó la ventana emergente. Permite ventanas emergentes para perplexity.ai');
            return;
        }

        if (!window.autoSaveWindows) {
            window.autoSaveWindows = [];
        }
        window.autoSaveWindows.push(newWindow);

        const autoSaves = RobustStorage.getItem('perplexity_auto_saves', []);
        const manualSaves = RobustStorage.getItem('perplexity_playground_chats', []);

        newWindow.document.open();
        newWindow.document.write('<!DOCTYPE html><html><head>');
        newWindow.document.write('<title>🔄 Auto-Guardado Perplexity - Chats en Tiempo Real</title>');
        newWindow.document.write('<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">');

        const autoSaveCSS = `
            * { box-sizing: border-box; margin: 0; padding: 0; }
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
                background: linear-gradient(135deg, #0f0f14 0%, #1a1a1f 50%, #2a2a30 100%);
                color: white;
                line-height: 1.6;
                min-height: 100vh;
            }
            .header {
                background: linear-gradient(90deg, #10b981 0%, #059669 50%, #047857 100%);
                padding: 25px 20px;
                text-align: center;
                box-shadow: 0 4px 20px rgba(16, 185, 129, 0.3);
                position: sticky;
                top: 0;
                z-index: 100;
            }
            .header h1 {
                font-size: 28px;
                font-weight: 700;
                margin-bottom: 10px;
                text-shadow: 0 2px 4px rgba(0,0,0,0.3);
                color: white;
            }
            .header .stats {
                font-size: 16px;
                opacity: 0.9;
                font-weight: 500;
            }
            .controls-bar {
                background: #2a2a30;
                padding: 20px;
                display: flex;
                justify-content: center;
                gap: 15px;
                flex-wrap: wrap;
                border-bottom: 1px solid #404040;
            }
            .btn {
                background: #4a4a50;
                color: white;
                border: none;
                padding: 12px 20px;
                border-radius: 8px;
                cursor: pointer;
                font-size: 14px;
                font-weight: 600;
                transition: all 0.3s ease;
                display: flex;
                align-items: center;
                gap: 8px;
                box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            }
            .btn:hover {
                transform: translateY(-2px);
                box-shadow: 0 4px 12px rgba(0,0,0,0.3);
            }
            .btn-success { background: #10b981; }
            .btn-success:hover { background: #059669; }
            .btn-danger { background: #ef4444; }
            .btn-danger:hover { background: #dc2626; }
            .btn-warning { background: #f59e0b; }
            .btn-warning:hover { background: #d97706; }
            .btn-secondary { background: #6b7280; }
            .btn-secondary:hover { background: #4b5563; }
            .container {
                max-width: 1300px;
                margin: 0 auto;
                padding: 20px;
            }
            .status-panel {
                background: #1e1e1e;
                border: 1px solid #404040;
                border-radius: 12px;
                padding: 20px;
                margin-bottom: 20px;
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                gap: 20px;
            }
            .status-item {
                text-align: center;
                padding: 15px;
                background: #2a2a30;
                border-radius: 8px;
                border: 1px solid #404040;
            }
            .status-number {
                font-size: 24px;
                font-weight: bold;
                color: #10b981;
                margin-bottom: 5px;
            }
            .status-label {
                font-size: 14px;
                color: #94a3b8;
            }
            .tabs {
                display: flex;
                background: #2a2a30;
                border-radius: 10px 10px 0 0;
                overflow: hidden;
            }
            .tab {
                flex: 1;
                padding: 15px 20px;
                background: #2a2a30;
                border: none;
                color: #94a3b8;
                cursor: pointer;
                font-size: 14px;
                font-weight: 600;
                transition: all 0.3s ease;
                border-bottom: 3px solid transparent;
            }
            .tab.active {
                background: #1e1e1e;
                color: #10b981;
                border-bottom-color: #10b981;
            }
            .tab:hover:not(.active) {
                background: #3a3a40;
                color: #e0e0e0;
            }
            .tab-content {
                background: #1e1e1e;
                border: 1px solid #404040;
                border-top: none;
                border-radius: 0 0 10px 10px;
                padding: 20px;
                min-height: 400px;
                max-height: 600px;
                overflow-y: auto;
            }
            .saves-grid {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
                gap: 15px;
            }
            .save-card {
                background: #2a2a30;
                border: 1px solid #404040;
                border-radius: 8px;
                padding: 15px;
                transition: all 0.3s ease;
                position: relative;
                cursor: pointer;
            }
            .save-card:hover {
                border-color: #10b981;
                box-shadow: 0 4px 12px rgba(16, 185, 129, 0.2);
            }
            .save-card.auto-save {
                border-left: 4px solid #10b981;
            }
            .save-card.manual-save {
                border-left: 4px solid #6366f1;
            }
            .save-header {
                display: flex;
                justify-content: space-between;
                align-items: flex-start;
                margin-bottom: 10px;
            }
            .save-title {
                font-weight: bold;
                color: #e0e0e0;
                font-size: 16px;
                line-height: 1.2;
            }
            .save-type {
                font-size: 11px;
                padding: 4px 8px;
                border-radius: 12px;
                font-weight: 600;
                text-transform: uppercase;
            }
            .save-type.auto {
                background: rgba(16, 185, 129, 0.2);
                color: #10b981;
            }
            .save-type.manual {
                background: rgba(99, 102, 241, 0.2);
                color: #6366f1;
            }
            .save-meta {
                font-size: 12px;
                color: #94a3b8;
                margin-bottom: 10px;
                display: flex;
                flex-direction: column;
                gap: 3px;
            }
            .save-preview {
                background: #1a1a1f;
                padding: 10px;
                border-radius: 5px;
                font-size: 13px;
                color: #cbd5e1;
                max-height: 60px;
                overflow: hidden;
                text-overflow: ellipsis;
                position: relative;
            }
            .save-preview::after {
                content: '';
                position: absolute;
                bottom: 0;
                left: 0;
                right: 0;
                height: 15px;
                background: linear-gradient(transparent, #1a1a1f);
            }
            .save-actions {
                display: flex;
                gap: 8px;
                margin-top: 10px;
            }
            .action-btn {
                flex: 1;
                padding: 8px 12px;
                border: none;
                border-radius: 5px;
                cursor: pointer;
                font-size: 11px;
                font-weight: 600;
                transition: all 0.2s ease;
                text-align: center;
            }
            .view-btn {
                background: #6366f1;
                color: white;
            }
            .view-btn:hover {
                background: #5856eb;
            }
            .export-btn {
                background: #10b981;
                color: white;
            }
            .export-btn:hover {
                background: #059669;
            }
            .delete-btn {
                background: #ef4444;
                color: white;
            }
            .delete-btn:hover {
                background: #dc2626;
            }
            .empty-state {
                text-align: center;
                padding: 60px 20px;
                color: #94a3b8;
            }
            .empty-state h3 {
                font-size: 20px;
                margin-bottom: 10px;
                color: #6b7280;
            }
            .refresh-indicator {
                position: fixed;
                top: 20px;
                right: 20px;
                background: #10b981;
                color: white;
                padding: 10px 15px;
                border-radius: 20px;
                font-size: 12px;
                font-weight: bold;
                opacity: 0;
                transition: opacity 0.3s ease;
                z-index: 1000;
            }
            .refresh-indicator.show {
                opacity: 1;
            }
            @media (max-width: 768px) {
                .saves-grid {
                    grid-template-columns: 1fr;
                }
                .status-panel {
                    grid-template-columns: repeat(2, 1fr);
                }
            }
        `;

        newWindow.document.write('<style>' + autoSaveCSS + '</style>');
        newWindow.document.write('</head><body>');

        newWindow.document.write('<div class="header">');
        newWindow.document.write('<h1>🔄 Auto-Guardado en Tiempo Real</h1>');
        newWindow.document.write('<div class="stats">Chats guardados automáticamente • Actualización en tiempo real</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="controls-bar">');
        newWindow.document.write('<button class="btn btn-success" onclick="toggleAutoSave()">🔄 Toggle Auto-Guardado</button>');
        newWindow.document.write('<button class="btn btn-warning" onclick="exportAllSaves()">📤 Exportar Todo</button>');
        newWindow.document.write('<button class="btn btn-secondary" onclick="refreshData()">🔃 Actualizar</button>');
        newWindow.document.write('<button class="btn btn-danger" onclick="clearAutoSaves()">🗑️ Limpiar Auto-Guardados</button>');
        newWindow.document.write('<button class="btn btn-secondary" onclick="window.close()">❌ Cerrar</button>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="container">');

        newWindow.document.write('<div class="status-panel">');
        newWindow.document.write('<div class="status-item">');
        newWindow.document.write('<div class="status-number" id="autoSaveCount">' + autoSaves.length + '</div>');
        newWindow.document.write('<div class="status-label">Auto-Guardados</div>');
        newWindow.document.write('</div>');
        newWindow.document.write('<div class="status-item">');
        newWindow.document.write('<div class="status-number" id="manualSaveCount">' + manualSaves.length + '</div>');
        newWindow.document.write('<div class="status-label">Guardados Manuales</div>');
        newWindow.document.write('</div>');
        newWindow.document.write('<div class="status-item">');
        newWindow.document.write('<div class="status-number" id="totalMessages">' + (autoSaves.reduce((sum, save) => sum + (save.messageCount || 0), 0) + manualSaves.reduce((sum, save) => sum + (save.messages?.length || 0), 0)) + '</div>');
        newWindow.document.write('<div class="status-label">Mensajes Totales</div>');
        newWindow.document.write('</div>');
        newWindow.document.write('<div class="status-item">');
        newWindow.document.write('<div class="status-number" id="autoSaveStatus">' + (isAutoSaveActive ? 'ON' : 'OFF') + '</div>');
        newWindow.document.write('<div class="status-label">Auto-Guardado</div>');
        newWindow.document.write('</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="tabs">');
        newWindow.document.write('<button class="tab active" onclick="switchTab(\'auto\')">🔄 Auto-Guardados (' + autoSaves.length + ')</button>');
        newWindow.document.write('<button class="tab" onclick="switchTab(\'manual\')">💾 Guardados Manuales (' + manualSaves.length + ')</button>');
        newWindow.document.write('<button class="tab" onclick="switchTab(\'all\')">📚 Todos (' + (autoSaves.length + manualSaves.length) + ')</button>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="tab-content">');
        newWindow.document.write('<div id="savesContainer" class="saves-grid"></div>');
        newWindow.document.write('</div>');

        newWindow.document.write('</div>'); // End container

        newWindow.document.write('<div id="refreshIndicator" class="refresh-indicator">🔄 Actualizando...</div>');

        const autoSaveScript = newWindow.document.createElement('script');
        autoSaveScript.textContent = `
            let currentTab = 'auto';
            let autoSaveData = ${JSON.stringify(autoSaves)};
            let manualSaveData = ${JSON.stringify(manualSaves)};
            let isAutoSaveOn = ${isAutoSaveActive};

            function escapeHTML(str) {
                const div = document.createElement('div');
                div.appendChild(document.createTextNode(str));
                return div.innerHTML;
            }

            function switchTab(tab) {
                currentTab = tab;

                document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                event.target.classList.add('active');

                updateSavesDisplay();
            }

            function updateSavesDisplay() {
                const container = document.getElementById('savesContainer');
                let saves = [];

                switch(currentTab) {
                    case 'auto':
                        saves = autoSaveData.map(s => ({...s, type: 'auto'}));
                        break;
                    case 'manual':
                        saves = manualSaveData.map(s => ({...s, type: 'manual'}));
                        break;
                    case 'all':
                        saves = [
                            ...autoSaveData.map(s => ({...s, type: 'auto'})),
                            ...manualSaveData.map(s => ({...s, type: 'manual'}))
                        ].sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
                        break;
                }

                if (saves.length === 0) {
                    container.innerHTML = '<div class="empty-state"><h3>📭 No hay guardados en esta categoría</h3><p>Los chats aparecerán aquí automáticamente</p></div>';
                    return;
                }

                container.innerHTML = '';
                saves.forEach((save, index) => {
                    const isAuto = save.type === 'auto';
                    const title = isAuto ?
                        'Auto-Guardado ' + new Date(save.timestamp).toLocaleTimeString() :
                        save.name || 'Chat Guardado';

                    const preview = save.preview ||
                        (save.messages && save.messages.length > 0 && save.messages[0]?.text
                            ? save.messages[0].text.substring(0, 100) + '...'
                            : 'Sin vista previa');

                    const messageCount = save.messageCount || save.messages?.length || 0;

                    const cardHTML = \`
                        <div class="save-card \${isAuto ? 'auto-save' : 'manual-save'}" data-index="\${index}" data-type="\${save.type}">
                            <div class="save-header">
                                <div class="save-title">\${escapeHTML(title)}</div>
                                <div class="save-type \${save.type}">\${save.type}</div>
                            </div>
                            <div class="save-meta">
                                <span>🕒 \${new Date(save.timestamp).toLocaleString()}</span>
                                <span>💬 \${messageCount} mensajes</span>
                                \${save.url ? \`<span>🔗 \${new URL(save.url).pathname}</span>\` : ''}
                            </div>
                            <div class="save-preview">\${escapeHTML(preview)}</div>
                            <div class="save-actions">
                                <button class="action-btn view-btn" onclick="viewSave('\${save.type}', \${index})">👁️ Ver</button>
                                <button class="action-btn export-btn" onclick="exportSave('\${save.type}', \${index})">📤 Exportar</button>
                                <button class="action-btn delete-btn" onclick="deleteSave('\${save.type}', \${index})">🗑️ Eliminar</button>
                            </div>
                        </div>
                    \`;

                    container.insertAdjacentHTML('beforeend', cardHTML);
                });
            }

            function viewSave(type, index) {
                const save = type === 'auto' ? autoSaveData[index] : manualSaveData[index];
                if (!save) return;

                const viewWindow = window.open('', '_blank', 'width=1000,height=800,scrollbars=yes,resizable=yes');
                if (!viewWindow) {
                    console.error('❌ Ventana emergente bloqueada');
                    return;
                }

                const title = type === 'auto' ?
                    'Auto-Guardado ' + new Date(save.timestamp).toLocaleTimeString() :
                    save.name || 'Chat Guardado';

                viewWindow.document.open();
                viewWindow.document.write(\`
                <!DOCTYPE html>
                <html>
                <head>
                    <title>\${escapeHTML(title)} - Vista Completa</title>
                    <meta charset="UTF-8">
                    <style>
                        body { font-family: system-ui, sans-serif; background: #1a1a1f; color: white; margin: 0; padding: 20px; line-height: 1.6; }
                        .header { background: #2a2a30; padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #10b981; text-align: center; }
                        .header h1 { color: #10b981; margin-bottom: 10px; font-size: 24px; }
                        .header .meta { color: #94a3b8; font-size: 14px; }
                        .message { margin: 20px 0; padding: 18px; border-radius: 12px; max-width: 85%; word-wrap: break-word; white-space: pre-wrap; box-shadow: 0 2px 8px rgba(0,0,0,0.3); }
                        .user { background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); margin-left: auto; text-align: right; }
                        .perplexity { background: linear-gradient(135deg, #374151 0%, #111827 100%); margin-right: auto; text-align: left; }
                        .type-label { font-weight: bold; font-size: 11px; text-transform: uppercase; margin-bottom: 10px; opacity: 0.7; letter-spacing: 1px; }
                        .controls { position: fixed; top: 20px; right: 20px; background: rgba(42, 42, 48, 0.95); padding: 15px; border-radius: 10px; border: 1px solid #444; backdrop-filter: blur(10px); }
                        .control-btn { background: #10b981; color: white; border: none; padding: 10px 15px; border-radius: 6px; cursor: pointer; margin: 0 5px 5px 0; font-size: 13px; transition: all 0.2s ease; }
                        .control-btn:hover { background: #059669; transform: translateY(-1px); }
                        .close-btn { background: #ef4444; } .close-btn:hover { background: #dc2626; }
                    </style>
                </head>
                <body>
                    <div class="controls">
                        <button class="control-btn close-btn" onclick="window.close()">❌ Cerrar</button>
                    </div>
                    <div class="header">
                        <h1>\${escapeHTML(title)}</h1>
                        <div class="meta">🕒 \${new Date(save.timestamp).toLocaleString()} • 💬 \${save.messageCount || save.messages?.length || 0} mensajes</div>
                    </div>
                    <div class="container" style="max-width: 900px; margin: 0 auto;">
                \`);

                const messages = save.messages || [];
                if (messages.length > 0) {
                    messages.forEach((msg, i) => {
                        const isUser = msg.type === 'User';
                        const className = isUser ? 'user' : 'perplexity';
                        const labelColor = isUser ? '#bfdbfe' : '#a7f3d0';

                        viewWindow.document.write(\`
                            <div class="message \${className}">
                                <div class="type-label" style="color: \${labelColor};">\${msg.type}</div>
                                <div>\${escapeHTML(msg.text)}</div>
                            </div>
                        \`);
                    });
                } else {
                    viewWindow.document.write('<div style="text-align: center; color: #94a3b8; padding: 60px 20px; font-size: 16px;">📭 Esta conversación no tiene mensajes</div>');
                }

                viewWindow.document.write('</div></body></html>');
                viewWindow.document.close();
                viewWindow.focus();
            }

            function exportSave(type, index) {
                const save = type === 'auto' ? autoSaveData[index] : manualSaveData[index];
                if (!save) return;

                const title = type === 'auto' ?
                    'Auto-Guardado ' + new Date(save.timestamp).toLocaleTimeString() :
                    save.name || 'Chat Guardado';

                let content = '=== ' + title + ' ===\\n';
                content += 'Fecha: ' + new Date(save.timestamp).toLocaleString() + '\\n';
                content += 'Tipo: ' + (type === 'auto' ? 'Auto-Guardado' : 'Guardado Manual') + '\\n';
                content += 'Mensajes: ' + (save.messageCount || save.messages?.length || 0) + '\\n\\n';

                const messages = save.messages || [];
                if (messages.length > 0) {
                    messages.forEach((msg, i) => {
                        content += '[' + (i + 1) + '] ' + msg.type + ':\\n';
                        content += msg.text + '\\n';
                        content += '============================================================\\n\\n';
                    });
                }

                const blob = new Blob([content], { type: 'text/plain; charset=utf-8' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = title.replace(/[^a-zA-Z0-9\\s]/g, '_').replace(/\\s+/g, '_') + '_' + new Date().toISOString().slice(0,10) + '.txt';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);

                showRefreshIndicator('✅ Exportado: ' + title);
            }

            function deleteSave(type, index) {
                const save = type === 'auto' ? autoSaveData[index] : manualSaveData[index];
                if (!save) return;

                const title = type === 'auto' ?
                    'Auto-Guardado ' + new Date(save.timestamp).toLocaleTimeString() :
                    save.name || 'Chat Guardado';

                if (confirm('⚠️ ¿Eliminar "' + title + '"?\\n\\nEsta acción no se puede deshacer.')) {
                    try {
                        if (type === 'auto') {
                            autoSaveData.splice(index, 1);
                            localStorage.setItem('perplexity_auto_saves', JSON.stringify(autoSaveData));
                        } else {
                            manualSaveData.splice(index, 1);
                            localStorage.setItem('perplexity_playground_chats', JSON.stringify(manualSaveData));
                        }

                        updateStats();
                        updateSavesDisplay();
                        showRefreshIndicator('🗑️ Eliminado: ' + title);
                    } catch (error) {
                        console.error('❌ Error al eliminar: ' + error.message);
                    }
                }
            }

            function toggleAutoSave() {
                try {
                    if (window.opener && !window.opener.closed) {
                        if (isAutoSaveOn) {
                            window.opener.postMessage({ action: 'stopAutoSave' }, window.location.origin);
                            isAutoSaveOn = false;
                            showRefreshIndicator('⏹️ Auto-guardado desactivado');
                        } else {
                            window.opener.postMessage({ action: 'startAutoSave' }, window.location.origin);
                            isAutoSaveOn = true;
                            showRefreshIndicator('▶️ Auto-guardado activado');
                        }
                        updateStats();
                    }
                } catch (error) {
                        console.error('❌ Error al comunicarse con la ventana principal: ' + error.message);
                }
            }

            function exportAllSaves() {
                const allSaves = [...autoSaveData, ...manualSaveData];
                if (allSaves.length === 0) {
                    console.warn('❌ No hay guardados para exportar');
                    return;
                }

                let content = '=== EXPORTACIÓN COMPLETA - PERPLEXITY AUTO-GUARDADO ===\\n';
                content += 'Fecha de exportación: ' + new Date().toLocaleString() + '\\n';
                content += 'Auto-guardados: ' + autoSaveData.length + '\\n';
                content += 'Guardados manuales: ' + manualSaveData.length + '\\n';
                content += 'Total: ' + allSaves.length + '\\n\\n';
                content += '================================================================================\\n\\n';

                allSaves.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));

                allSaves.forEach((save, saveIndex) => {
                    const isAuto = autoSaveData.includes(save);
                    const title = isAuto ?
                        'Auto-Guardado ' + new Date(save.timestamp).toLocaleTimeString() :
                        save.name || 'Chat Guardado';

                    content += '[' + (isAuto ? 'AUTO' : 'MANUAL') + ' - ' + (saveIndex + 1) + '] ' + title + '\\n';
                    content += 'Fecha: ' + new Date(save.timestamp).toLocaleString() + '\\n';
                    content += 'Mensajes: ' + (save.messageCount || save.messages?.length || 0) + '\\n\\n';

                    const messages = save.messages || [];
                    if (messages.length > 0) {
                        messages.forEach((msg, msgIndex) => {
                            content += '  [' + (msgIndex + 1) + '] ' + msg.type + ':\\n';
                            content += '  ' + msg.text.replace(/\\n/g, '\\n  ') + '\\n\\n';
                        });
                    }
                    content += '================================================================================\\n\\n';
                });

                const blob = new Blob([content], { type: 'text/plain; charset=utf-8' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = 'perplexity_complete_backup_' + new Date().toISOString().slice(0,19).replace(/[:.]/g, '-') + '.txt';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);

                showRefreshIndicator('✅ Exportación completa realizada (' + allSaves.length + ' guardados)');
            }

            function clearAutoSaves() {
                if (confirm('⚠️ ¿ELIMINAR TODOS LOS AUTO-GUARDADOS?\\n\\nEsta acción es PERMANENTE y eliminará:\\n\\n📊 ' + autoSaveData.length + ' auto-guardados\\n\\n¿Estás completamente seguro?')) {
                    try {
                        localStorage.removeItem('perplexity_auto_saves');
                        autoSaveData = [];
                        updateStats();
                        updateSavesDisplay();
                        showRefreshIndicator('🗑️ Todos los auto-guardados eliminados');
                    } catch (error) {
                        console.error('❌ Error: ' + error.message);
                    }
                }
            }

            function refreshData() {
                try {
                    autoSaveData = JSON.parse(localStorage.getItem('perplexity_auto_saves') || '[]');
                    manualSaveData = JSON.parse(localStorage.getItem('perplexity_playground_chats') || '[]');
                    updateStats();
                    updateSavesDisplay();
                    showRefreshIndicator('🔄 Datos actualizados');
                } catch (error) {
                    console.error('❌ Error actualizando: ' + error.message);
                }
            }

            function updateStats() {
                document.getElementById('autoSaveCount').textContent = autoSaveData.length;
                document.getElementById('manualSaveCount').textContent = manualSaveData.length;
                document.getElementById('totalMessages').textContent =
                    autoSaveData.reduce((sum, save) => sum + (save.messageCount || 0), 0) +
                    manualSaveData.reduce((sum, save) => sum + (save.messages?.length || 0), 0);
                document.getElementById('autoSaveStatus').textContent = isAutoSaveOn ? 'ON' : 'OFF';

                document.querySelectorAll('.tab').forEach((tab, index) => {
                    switch(index) {
                        case 0:
                            tab.textContent = '🔄 Auto-Guardados (' + autoSaveData.length + ')';
                            break;
                        case 1:
                            tab.textContent = '💾 Guardados Manuales (' + manualSaveData.length + ')';
                            break;
                        case 2:
                            tab.textContent = '📚 Todos (' + (autoSaveData.length + manualSaveData.length) + ')';
                            break;
                    }
                });
            }

            function showRefreshIndicator(message) {
                const indicator = document.getElementById('refreshIndicator');
                indicator.textContent = message;
                indicator.classList.add('show');
                setTimeout(() => {
                    indicator.classList.remove('show');
                }, 3000);
            }

            window.addEventListener('message', (event) => {
                if (event.origin !== window.location.origin) return;

                if (event.data && event.data.action === 'refreshAutoSaves') {
                    refreshData();
                }
            });

            setInterval(refreshData, 10000); // Cada 10 segundos

            window.addEventListener('load', () => {
                document.body.focus();
                showRefreshIndicator('🔄 Auto-guardado iniciado - Actualizaciones en tiempo real');
            });
        `;

        newWindow.document.body.appendChild(autoSaveScript);
        newWindow.document.close();
        newWindow.focus();

        console.log('✅ Ventana de autoguardado abierta correctamente');
    }

    // --- Core Chat Management Functions ---
    function saveCurrentChat() {
        const chatContent = getCurrentChatContent();
        if (chatContent.length === 0) {
            console.warn('❌ No hay conversación para guardar. Asegúrate de que hay mensajes en el chat.');
            return;
        }
        const chatName = prompt("💾 Introduce un nombre para esta conversación:", `Chat ${new Date().toLocaleString()}`);
        if (chatName && chatName.trim()) {
            try {
                const savedChats = RobustStorage.getItem('perplexity_playground_chats', []);
                const newChat = {
                    name: chatName.trim(),
                    timestamp: new Date().toISOString(),
                    messages: chatContent,
                    messageCount: chatContent.length,
                    url: window.location.href
                };
                savedChats.push(newChat);
                RobustStorage.setItem('perplexity_playground_chats', savedChats);
                console.log(`✅ Conversación "${chatName}" guardada con éxito. ${chatContent.length} mensajes guardados.`);
            } catch (e) {
                console.error("❌ Error al guardar:", e);
                console.error("❌ Error al guardar la conversación: " + e.message);
            }
        }
    }

    function exportChatToText() {
        const chatContent = getCurrentChatContent();
        if (chatContent.length === 0) {
            console.warn('❌ No se encontraron mensajes para exportar.');
            return;
        }
        try {
            let exportText = `=== Conversación Perplexity Playground ===\n`;
            exportText += `Fecha: ${new Date().toLocaleString()}\n`;
            exportText += `URL: ${window.location.href}\n`;
            exportText += `Mensajes: ${chatContent.length}\n\n`;
            chatContent.forEach((msg, index) => {
                exportText += `[${index + 1}] ${msg.type}:\n`;
                exportText += `${msg.text}\n\n`;
                exportText += `${'='.repeat(80)}\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 = `perplexity_chat_${new Date().toISOString().slice(0,19).replace(/[:.]/g, '-')}.txt`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            console.log(`✅ Conversación exportada exitosamente. ${chatContent.length} mensajes exportados.`);
        } catch (error) {
            console.error('❌ Error al exportar:', error);
            console.error('❌ Error al exportar la conversación: ' + error.message);
        }
    }

    // --- File Import Functions ---
    function loadTesseractJs() { return new Promise((resolve, reject) => { if (window.Tesseract) { resolve(); return; } console.log("📷 Cargando Tesseract.js para OCR..."); const script = document.createElement('script'); script.src = "https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js"; script.onload = () => window.Tesseract ? resolve() : reject(new Error("Tesseract.js no disponible")); script.onerror = reject; document.head.appendChild(script); }); }
    function loadPdfJs() { return new Promise((resolve, reject) => { if (window.pdfjsLib) { resolve(); return; } console.log("📄 Cargando PDF.js..."); const script = document.createElement('script'); script.src = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.min.js"; script.onload = () => { if (window.pdfjsLib) { window.pdfjsLib.GlobalWorkerOptions.workerSrc = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.worker.min.js"; resolve(); } else { reject(new Error("PDF.js no disponible")); } }; script.onerror = reject; document.head.appendChild(script); }); }
    function loadMammothJs() { return new Promise((resolve, reject) => { if (window.mammoth) { resolve(); return; } console.log("📝 Cargando Mammoth.js para DOCX..."); const script = document.createElement('script'); script.src = "https://unpkg.com/mammoth/mammoth.browser.min.js"; script.onload = () => window.mammoth ? resolve() : reject(new Error("Mammoth.js no disponible")); script.onerror = reject; document.head.appendChild(script); }); }
    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(new Error(`Error al procesar PDF: ${err.message}`)); } }; 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 arrayBuffer = e.target.result; const result = await mammoth.extractRawText({ arrayBuffer }); resolve(result.value.trim()); } catch (err) { reject(new Error(`Error al procesar DOCX: ${err.message}`)); } }; reader.onerror = reject; reader.readAsArrayBuffer(file); }); }

    async function processDroppedFiles(files) {
        const textarea = findElement(SELECTORS.INPUT_TEXTAREA);
        if (!textarea) {
            console.error('❌ No se encontró el área de texto');
            return;
        }
        let allContent = '';
        // Find the import button specifically for updating its text/icon during processing
        const importButtonTextSpan = document.querySelector('#perplexity-import-button .text');
        const originalButtonText = importButtonTextSpan ? importButtonTextSpan.textContent : 'Importar';

        const updateButtonStatus = (text) => {
            if (importButtonTextSpan) {
                importButtonTextSpan.textContent = text;
            }
        };

        for (const file of files) {
            const textExtensions = new Set(['txt', 'html', 'htm', 'css', 'js', 'json', 'csv', 'xml', 'md', 'log', 'yaml', 'yml', 'py', 'java', 'c', 'cpp', 'h', 'hpp', 'go', 'php', 'rb', 'sh', 'bat', 'ps1', 'ini', 'cfg', 'conf', 'rs', 'ts', 'jsx', 'tsx', 'vue']);
            const imageExtensions = new Set(['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp']);
            const fileExt = file.name.split('.').pop()?.toLowerCase() || '';
            const isTextFile = textExtensions.has(fileExt) || file.type.startsWith('text/');
            const isImage = imageExtensions.has(fileExt) || file.type.startsWith('image/');
            const isPdf = fileExt === 'pdf' || file.type === 'application/pdf';
            const isDocx = fileExt === 'docx' || file.type.includes('wordprocessingml');
            try {
                if (allContent) allContent += `\n\n--- ${file.name} ---\n\n`;
                if (isTextFile) {
                    const content = await readFileAsText(file);
                    allContent += content;
                }
                else if (isImage) {
                    updateButtonStatus(`OCR ${file.name}...`);
                    await loadTesseractJs();
                    const { data: { text } } = await Tesseract.recognize(file, 'spa+eng', {
                        logger: m => {
                            if (m.status === 'recognizing') {
                                updateButtonStatus(`OCR ${file.name}: ${Math.round(m.progress * 100)}%`);
                            }
                        }
                    });
                    allContent += text.trim();
                }
                else if (isPdf) {
                    updateButtonStatus(`PDF ${file.name}...`);
                    await loadPdfJs();
                    const text = await extractTextFromPdf(file);
                    allContent += text.trim();
                }
                else if (isDocx) {
                    updateButtonStatus(`DOCX ${file.name}...`);
                    await loadMammothJs();
                    const text = await extractTextFromDocx(file);
                    allContent += text;
                }
                else {
                    console.warn(`⚠️ Tipo de archivo no soportado: ${file.name}`);
                    continue;
                }
            } catch (error) {
                console.error(`❌ Error procesando ${file.name}:`, error);
            }
        }
        updateButtonStatus(originalButtonText); // Restore original button text
        if (allContent.trim()) {
            insertTextIntoTextarea(textarea.value + (textarea.value ? '\n\n' : '') + allContent);
        }
    }

    function createImportButton() {
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.multiple = true;
        fileInput.accept = `.txt,.html,.htm,.css,.js,.json,.csv,.xml,.md,.log,.yaml,.yml,.py,.java,.c,.cpp,.h,.hpp,.go,.php,.rb,.sh,.bat,.ps1,.ini,.cfg,.conf,.rs,.ts,.jsx,.tsx,.vue,.png,.jpg,.jpeg,.bmp,.gif,.webp,.pdf,application/pdf,.docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document,text/*,application/json,application/xml,application/javascript,image/*`.replace(/\s/g, '');
        fileInput.style.display = 'none';

        const importButton = createStylizedButton('Importar', () => fileInput.click(), ICON_SVG.UPLOAD);
        importButton.id = 'perplexity-import-button';

        ['dragover', 'dragenter'].forEach(eventName => {
            importButton.addEventListener(eventName, (e) => {
                e.preventDefault();
                e.stopPropagation();
                importButton.classList.add('drag-active'); // Add a class for drag styles
            });
        });
        ['dragleave', 'dragend'].forEach(eventName => {
            importButton.addEventListener(eventName, (e) => {
                e.preventDefault();
                e.stopPropagation();
                importButton.classList.remove('drag-active');
            });
        });
        importButton.addEventListener('drop', (e) => {
            e.preventDefault();
            e.stopPropagation();
            importButton.classList.remove('drag-active');
            if (e.dataTransfer.files.length > 0) {
                processDroppedFiles(e.dataTransfer.files);
            }
        });
        fileInput.addEventListener('change', (event) => {
            if (event.target.files.length > 0) {
                processDroppedFiles(event.target.files);
                event.target.value = '';
            }
        });
        document.body.appendChild(fileInput); // Append hidden input to body
        return importButton;
    }

    function setupCharacterCounter() {
        const textarea = findElement(SELECTORS.INPUT_TEXTAREA);
        if (!textarea) return;
        if (document.getElementById('char-counter-perplexity')) return;

        const counter = document.createElement('div');
        counter.id = 'char-counter-perplexity';
        // Add basic inline styles, can be overridden by GM_addStyle
        counter.style.cssText = `
            position: absolute; bottom: 8px; right: 12px; font-size: 11px;
            color: #888; background: rgba(0,0,0,0.7); padding: 2px 6px;
            border-radius: 4px; pointer-events: none; z-index: 1000;
        `;

        const textareaParent = textarea.parentElement; // Direct parent, not necessarily the lexical editor wrapper
        if (textareaParent && getComputedStyle(textareaParent).position === 'static') {
            textareaParent.style.position = 'relative'; // Ensure positioning context
        }

        // Find a suitable wrapper element for the counter.
        // It should be within the main input area but allow for relative/absolute positioning.
        let counterWrapper = textarea.closest('div[class*="overflow-hidden.relative.flex.h-full.w-full"]') || textarea.closest('div[class*="rounded-2xl.border-subtlest"]');
        if (!counterWrapper) {
             counterWrapper = textarea.closest('div.relative') || textarea.parentElement;
             if (counterWrapper && getComputedStyle(counterWrapper).position === 'static') {
                 counterWrapper.style.position = 'relative';
             }
        }

        if (counterWrapper) {
            counterWrapper.appendChild(counter);
        } else {
            console.warn('Could not find a suitable wrapper for the character counter, appending to body.');
            document.body.appendChild(counter);
        }

        const updateCounter = () => {
            const text = textarea.value;
            const chars = text.length;
            const words = text.trim() ? text.trim().split(/\s+/).length : 0;
            counter.textContent = `${chars} chars | ${words} words`;
        };
        textarea.addEventListener('input', updateCounter);
        updateCounter(); // Initial update
    }

    // --- Floating UI Creation and Drag Logic ---
    let floatingContainer = null;
    let isDragging = false;
    let offsetX, offsetY;

    function savePosition(x, y) {
        RobustStorage.setItem('perplexity_floating_ui_pos', { x, y });
    }

    function loadPosition() {
        const savedPos = RobustStorage.getItem('perplexity_floating_ui_pos');
        if (savedPos) {
            return { x: savedPos.x, y: savedPos.y };
        }
        return { x: CONFIG.FLOATING_UI_INITIAL_POS_X, y: CONFIG.FLOATING_UI_INITIAL_POS_Y };
    }

    function toggleFloatingUI() {
        if (floatingContainer) {
            const isHidden = floatingContainer.classList.toggle('hidden-ui');
            RobustStorage.setItem('perplexity_floating_ui_hidden', isHidden);
            // Update the toggle button text
            const toggleButton = document.getElementById('perplexity-toggle-ui-button');
            if (toggleButton && toggleButton.querySelector('.text')) {
                toggleButton.querySelector('.text').textContent = isHidden ? 'Mostrar UI' : 'Ocultar UI';
            }
        }
    }

    function addControlsToFloatingUI() {
        if (document.getElementById('perplexity-floating-container')) {
            console.log('Floating UI already exists.');
            return;
        }

        floatingContainer = document.createElement('div');
        floatingContainer.id = 'perplexity-floating-container';
        floatingContainer.className = 'advanced-pro-floating-container';

        const savedHiddenState = RobustStorage.getItem('perplexity_floating_ui_hidden', false);
        if (savedHiddenState) {
            floatingContainer.classList.add('hidden-ui');
        }

        const initialPos = loadPosition();
        floatingContainer.style.left = `${initialPos.x}px`;
        floatingContainer.style.top = `${initialPos.y}px`;

        // Make draggable
        const header = document.createElement('div');
        header.className = 'advanced-pro-header';
        header.textContent = '🛠️ Perplexity Advanced Pro';
        header.style.cursor = 'grab'; // Indicate it's draggable
        floatingContainer.appendChild(header);

        header.addEventListener('mousedown', (e) => {
            isDragging = true;
            offsetX = e.clientX - floatingContainer.getBoundingClientRect().left;
            offsetY = e.clientY - floatingContainer.getBoundingClientRect().top;
            floatingContainer.style.cursor = 'grabbing';
            floatingContainer.style.userSelect = 'none'; // Prevent text selection during drag
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            e.preventDefault();
            let newX = e.clientX - offsetX;
            let newY = e.clientY - offsetY;

            // Boundary checks
            newX = Math.max(0, Math.min(newX, window.innerWidth - floatingContainer.offsetWidth));
            newY = Math.max(0, Math.min(newY, window.innerHeight - floatingContainer.offsetHeight));

            floatingContainer.style.left = `${newX}px`;
            floatingContainer.style.top = `${newY}px`;
        });

        document.addEventListener('mouseup', () => {
            if (isDragging) {
                isDragging = false;
                floatingContainer.style.cursor = 'grab';
                floatingContainer.style.userSelect = 'auto'; // Re-enable text selection
                savePosition(
                    parseFloat(floatingContainer.style.left),
                    parseFloat(floatingContainer.style.top)
                );
            }
        });

        // Controls container inside floating UI
        const controlsPanel = document.createElement('div');
        controlsPanel.className = 'advanced-pro-controls-panel';

        // Dropdown for prompts
        const promptsDropdown = createCategorizedDropdown(ALL_CATEGORIZED_PROMPTS, handlePromptSelection, "🎯 Seleccionar Prompt");
        controlsPanel.appendChild(promptsDropdown);

        // Buttons
        const buttonsContainer = document.createElement('div');
        buttonsContainer.className = 'advanced-pro-buttons-grid';

        buttonsContainer.appendChild(createStylizedButton('Guardar Chat', saveCurrentChat, ICON_SVG.DOWNLOAD));
        buttonsContainer.appendChild(createStylizedButton('Cargar Chats', loadSavedChatsMain, ICON_SVG.DOWNLOAD));
        buttonsContainer.appendChild(createStylizedButton('Exportar Chat', exportChatToText, ICON_SVG.DOWNLOAD));
        buttonsContainer.appendChild(createImportButton()); // This creates its own button and hidden input
        buttonsContainer.appendChild(createStylizedButton('JS Executor', openJSExecutorWindow, ICON_SVG.CODE));
        buttonsContainer.appendChild(createStylizedButton('Auto-Guardado', openAutoSaveWindow, ICON_SVG.AUTO_SAVE));

        controlsPanel.appendChild(buttonsContainer);
        floatingContainer.appendChild(controlsPanel);

        // Toggle UI button (always visible, outside the main panel, at the bottom of floatingContainer)
        const toggleButton = createStylizedButton(savedHiddenState ? 'Mostrar UI' : 'Ocultar UI', toggleFloatingUI, ICON_SVG.TOGGLE);
        toggleButton.id = 'perplexity-toggle-ui-button';
        toggleButton.classList.add('advanced-pro-toggle-button');
        floatingContainer.appendChild(toggleButton);


        document.body.appendChild(floatingContainer);
        console.log('✅ Interfaz flotante y arrastrable creada.');
    }

    // --- Chat Manager ---
    function loadSavedChatsMain() {
        console.log('📂 === CARGANDO CHATS EN NUEVA VENTANA (MÉTODO ROBUSTO) ===');
        try {
            const savedChats = RobustStorage.getItem('perplexity_playground_chats', []);
            if (!savedChats || savedChats.length === 0) {
                console.warn('📂 No hay conversaciones guardadas. Primero guarda una conversación con "💾 Guardar Chat".');
                return;
            }
            openChatsManagerWindow(savedChats);
        } catch (error) {
            console.error('❌ Error en loadSavedChatsMain:', error);
        }
    }

    function openChatsManagerWindow(savedChats) {
        console.log('🪟 === ABRIENDO GESTOR DE CHATS EN NUEVA VENTANA ===');

        const newWindow = window.open('', '_blank', 'width=1300,height=900,scrollbars=yes,resizable=yes,menubar=no,toolbar=no,location=no');

        if (!newWindow) {
            console.error('❌ El navegador bloqueó la ventana emergente. Permite ventanas emergentes para perplexity.ai o usa Ctrl+Click en el botón "📂 Cargar Chat"');
            return;
        }

        newWindow.document.open();
        newWindow.document.write('<!DOCTYPE html><html><head>');
        newWindow.document.write('<title>📚 Perplexity Chats Manager - ' + savedChats.length + ' conversaciones</title>');
        newWindow.document.write('<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">');

        const cssContent = `
            * { box-sizing: border-box; margin: 0; padding: 0; }
            body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif; background: linear-gradient(135deg, #0f0f14 0%, #1a1a1f 50%, #2a2a30 100%); color: white; line-height: 1.6; min-height: 100vh; overflow-x: hidden; }
            .header { background: linear-gradient(90deg, #6366f1 0%, #8b5cf6 100%); padding: 30px 20px; text-align: center; box-shadow: 0 4px 20px rgba(99, 102, 241, 0.3); position: sticky; top: 0; z-index: 100; }
            .header h1 { font-size: 28px; font-weight: 700; margin-bottom: 10px; text-shadow: 0 2px 4px rgba(0,0,0,0.3); }
            .header .stats { font-size: 16px; opacity: 0.9; font-weight: 500; }
            .controls-bar { background: #2a2a30; padding: 20px; display: flex; justify-content: center; gap: 15px; flex-wrap: wrap; border-bottom: 1px solid #404040; }
            .btn { background: #4a4a50; color: white; border: none; padding: 12px 20px; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 600; transition: all 0.3s ease; display: flex; align-items: center; gap: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.2); }
            .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.3); }
            .btn-primary { background: #6366f1; } .btn-primary:hover { background: #5856eb; }
            .btn-success { background: #10b981; } .btn-success:hover { background: #059669; }
            .btn-danger { background: #ef4444; } .btn-danger:hover { background: #dc2626; }
            .btn-warning { background: #f59e0b; } .btn-warning:hover { background: #d97706; }
            .container { max-width: 1200px; margin: 0 auto; padding: 30px 20px; }
            .chats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 20px; margin-top: 20px; }
            .chat-card { background: linear-gradient(145deg, #2a2a30 0%, #1f1f24 100%); border: 1px solid #404040; border-radius: 12px; padding: 20px; transition: all 0.3s ease; position: relative; overflow: hidden; }
            .chat-card:hover { transform: translateY(-5px); border-color: #6366f1; box-shadow: 0 10px 30px rgba(99, 102, 241, 0.2); }
            .chat-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, #6366f1, #8b5cf6, #ec4899); }
            .chat-name { font-size: 18px; font-weight: 700; color: #f8fafc; margin-bottom: 10px; word-wrap: break-word; line-height: 1.4; }
            .chat-meta { color: #94a3b8; font-size: 13px; margin-bottom: 15px; display: flex; flex-direction: column; gap: 5px; }
            .chat-preview { background: #1a1a1f; padding: 12px; border-radius: 8px; border-left: 3px solid #6366f1; margin: 15px 0; font-size: 13px; color: #cbd5e1; max-height: 80px; overflow: hidden; position: relative; }
            .chat-preview::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 20px; background: linear-gradient(transparent, #1a1a1f); }
            .chat-actions { display: flex; gap: 10px; margin-top: 15px; }
            .action-btn { flex: 1; padding: 10px; border: none; border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 600; transition: all 0.2s ease; text-align: center; }
            .view-btn { background: #6366f1; color: white; } .view-btn:hover { background: #5856eb; }
            .delete-btn { background: #ef4444; color: white; } .delete-btn:hover { background: #dc2626; }
            .export-btn { background: #10b981; color: white; } .export-btn:hover { background: #059669; }
            .empty-state { text-align: center; padding: 60px 20px; color: #94a3b8; }
            .empty-state h2 { font-size: 24px; margin-bottom: 15px; color: #6366f1; }
            @media (max-width: 768px) { .chats-grid { grid-template-columns: 1fr; } .controls-bar { flex-direction: column; align-items: center; } }
        `;
        newWindow.document.write('<style>' + cssContent + '</style>');
        newWindow.document.write('</head><body>');

        newWindow.document.write('<div class="header">');
        newWindow.document.write('<h1>📚 Gestor de Conversaciones Perplexity Pro</h1>');
        newWindow.document.write('<div class="stats">💬 ' + savedChats.length + ' conversaciones guardadas • 📊 ' + savedChats.reduce((total, chat) => total + (chat.messages?.length || 0), 0) + ' mensajes totales</div>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="controls-bar">');
        newWindow.document.write('<button class="btn btn-success" onclick="exportAllChats()">📤 Exportar Todas las Conversaciones</button>');
        newWindow.document.write('<button class="btn btn-warning" onclick="refreshFromParent()">🔄 Actualizar Lista</button>');
        newWindow.document.write('<button class="btn btn-danger" onclick="clearAllChats()">🗑️ Eliminar Todas</button>');
        newWindow.document.write('<button class="btn btn-primary" onclick="window.close()">❌ Cerrar Ventana</button>');
        newWindow.document.write('</div>');

        newWindow.document.write('<div class="container">');

        if (savedChats.length === 0) {
            newWindow.document.write('<div class="empty-state"><h2>📂 No hay conversaciones guardadas</h2><p>Regresa a Perplexity Playground y usa el botón <strong>"💾 Guardar Chat"</strong> para guardar tu conversación actual.</p></div>');
        } else {
            newWindow.document.write('<div class="chats-grid">');

            savedChats.forEach((chat, index) => {
                const previewText = chat.messages && chat.messages.length > 0 && chat.messages[0]?.text
                    ? (chat.messages[0].text.length > 150
                        ? chat.messages[0].text.substring(0, 150) + '...'
                        : (chat.messages[0].text || 'Sin contenido de vista previa'))
                    : 'Sin contenido de vista previa';

                const safeChatName = escapeHTML(chat.name);
                const safePreviewText = escapeHTML(previewText);

                newWindow.document.write('<div class="chat-card" data-chat-index="' + index + '">');
                newWindow.document.write('<div class="chat-name">' + safeChatName + '</div>');
                newWindow.document.write('<div class="chat-meta">');
                newWindow.document.write('<span>🕒 ' + new Date(chat.timestamp).toLocaleString() + '</span>');
                newWindow.document.write('<span>💬 ' + (chat.messages?.length || 0) + ' mensajes</span>');
                newWindow.document.write('</div>');
                newWindow.document.write('<div class="chat-preview">' + safePreviewText + '</div>');
                newWindow.document.write('<div class="chat-actions">');
                newWindow.document.write('<button class="action-btn view-btn" onclick="viewChat(' + index + ')">👁️ Ver Completo</button>');
                newWindow.document.write('<button class="action-btn export-btn" onclick="exportSingleChat(' + index + ')">📤 Exportar</button>');
                newWindow.document.write('<button class="action-btn delete-btn" onclick="deleteChat(' + index + ')">🗑️ Eliminar</button>');
                newWindow.document.write('</div>');
                newWindow.document.write('</div>');
            });

            newWindow.document.write('</div>');
        }
        newWindow.document.write('</div>'); // End container

        const scriptElement = newWindow.document.createElement('script');
        scriptElement.textContent = `
            let savedChatsData = ${JSON.stringify(savedChats)};
            const parentOrigin = '${window.location.origin}';

            function escapeHTML(str) {
                if (!str) return '';
                const div = document.createElement('div');
                div.appendChild(document.createTextNode(str));
                return div.innerHTML;
            }

            function getFormattedTime(timestamp) {
                return new Date(timestamp).toLocaleString();
            }

            function getChatPreview(chat) {
                if (!chat.messages || chat.messages.length === 0) return 'Sin contenido de vista previa';

                for (const msg of chat.messages) {
                    if (msg.text && msg.text.trim()) {
                        return msg.text.trim().substring(0, 150) +
                               (msg.text.length > 150 ? '...' : '');
                    }
                }
                return 'Sin contenido de vista previa';
            }

            function viewChat(index) {
                const chat = savedChatsData[index];
                if (!chat) return;

                const viewWindow = window.open('', 'chat_view_' + index, 'width=800,height=700,scrollbars=yes,resizable=yes');
                if (!viewWindow) {
                    console.error('❌ No se pudo abrir la ventana de visualización');
                    return;
                }

                viewWindow.document.open();
                viewWindow.document.write('<!DOCTYPE html><html><head>');
                viewWindow.document.write('<title>👁️ Vista Completa: ' + escapeHTML(chat.name) + '</title>');
                viewWindow.document.write('<style>');
                viewWindow.document.write('body { background: #1a1a1f; color: white; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; margin: 20px; line-height: 1.6; }');
                viewWindow.document.write('.message { margin: 15px 0; padding: 15px; border-radius: 8px; }');
                viewWindow.document.write('.user { background: #2a2a30; border-left: 3px solid #3b82f6; margin-left: 20%; }');
                viewWindow.document.write('.perplexity { background: #2a2a30; border-left: 3px solid #10b981; margin-right: 20%; }');
                viewWindow.document.write('.message-header { font-weight: bold; margin-bottom: 5px; }');
                viewWindow.document.write('.timestamp { color: #888; font-size: 12px; }');
                viewWindow.document.write('</style>');
                viewWindow.document.write('</head><body>');

                viewWindow.document.write('<h1>' + escapeHTML(chat.name) + '</h1>');
                viewWindow.document.write('<p>📅 ' + getFormattedTime(chat.timestamp) + ' | 💬 ' + (chat.messages?.length || 0) + ' mensajes</p>');

                if (chat.messages && chat.messages.length > 0) {
                    chat.messages.forEach((msg, i) => {
                        if (!msg.text) return;

                        const msgClass = msg.type === 'User' ? 'user' : 'perplexity';
                        const formattedText = msg.text.replace(/\\n/g, '<br>');

                        viewWindow.document.write('<div class="message ' + msgClass + '">');
                        viewWindow.document.write('<div class="message-header">' +
                                                 msg.type +
                                                 ' <span class="timestamp">' + (i + 1) + '.</span></div>');
                        viewWindow.document.write('<div>' + escapeHTML(formattedText) + '</div>');
                        viewWindow.document.write('</div>');
                    });
                }

                viewWindow.document.write('<div style="text-align: center; margin-top: 20px;">');
                viewWindow.document.write('<button onclick="window.close()" style="padding: 8px 15px; background: #4a4a50; color: white; border: none; border-radius: 4px; cursor: pointer;">Cerrar</button>');
                viewWindow.document.write('</div>');

                viewWindow.document.write('</body></html>');
                viewWindow.document.close();
            }

            function exportSingleChat(index) {
                const chat = savedChatsData[index];
                if (!chat) {
                    console.warn('❌ Conversación no encontrada');
                    return;
                }

                let exportText = '=== ' + (chat.name || 'Conversación') + ' ===\\n';
                exportText += 'Fecha: ' + getFormattedTime(chat.timestamp) + '\\n';
                exportText += 'Mensajes: ' + (chat.messages?.length || 0) + '\\n\\n';

                if (chat.messages && chat.messages.length > 0) {
                    chat.messages.forEach((msg, i) => {
                        if (msg.text) {
                            exportText += '[' + (i + 1) + '] ' + msg.type + ':\\n';
                            exportText += msg.text + '\\n';
                            exportText += '============================================================\\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 = 'perplexity_chat_' + chat.name.replace(/[^a-z0-9]/gi, '_').toLowerCase() + '_' + Date.now() + '.txt';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);

                console.log('✅ Conversación exportada correctamente');
            }

            function deleteChat(index) {
                if (confirm('⚠️ ¿Estás seguro de querer eliminar "' + savedChatsData[index].name + '"?\\n\\nEsta acción no se puede deshacer.')) {
                    try {
                        window.opener.postMessage({ action: 'deleteChat', chatName: savedChatsData[index].name }, parentOrigin);
                    } catch (e) {
                        console.warn('⚠️ No se pudo notificar a la ventana principal:', e);
                    }

                    savedChatsData.splice(index, 1);
                    localStorage.setItem('perplexity_playground_chats', JSON.stringify(savedChatsData));
                    refreshUI();

                    console.log('✅ Conversación eliminada');
                }
            }

            function exportAllChats() {
                if (savedChatsData.length === 0) {
                    console.warn('❌ No hay conversaciones para exportar');
                    return;
                }

                let exportText = '=== EXPORTACIÓN DE CONVERSACIONES PERPLEXITY ===\\n';
                exportText += 'Fecha: ' + getFormattedTime(new Date().toISOString()) + '\\n';
                exportText += 'Total de conversaciones: ' + savedChatsData.length + '\\n\\n';

                savedChatsData.forEach((chat, chatIndex) => {
                    exportText += '--- [' + (chatIndex + 1) + '] ' + (chat.name || 'Conversación') + ' ---\\n';
                    exportText += 'Fecha: ' + getFormattedTime(chat.timestamp) + '\\n';
                    exportText += 'Mensajes: ' + (chat.messages?.length || 0) + '\\n\\n';

                    if (chat.messages && chat.messages.length > 0) {
                        chat.messages.forEach((msg, msgIndex) => {
                            if (msg.text) {
                                exportText += '[' + (msgIndex + 1) + '] ' + msg.type + ':\\n';
                                exportText += msg.text + '\\n\\n';
                            }
                        });
                    }

                    exportText += '\\n============================================================\\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 = 'perplexity_conversations_' + Date.now() + '.txt';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);

                console.log('✅ Exportación completada con ' + savedChatsData.length + ' conversaciones');
            }

            function clearAllChats() {
                if (confirm('⚠️ ¡ADVERTENCIA!\\n\\nEsta acción eliminará todas las conversaciones guardadas (' + savedChatsData.length + ').\\n\\n¿Estás seguro de que quieres continuar?')) {
                    try {
                        window.opener.postMessage({ action: 'clearAllChats' }, parentOrigin);
                    } catch (e) {
                        console.warn('⚠️ No se pudo notificar a la ventana principal:', e);
                    }

                    savedChatsData = [];
                    localStorage.removeItem('perplexity_playground_chats');
                    refreshUI();

                    console.log('✅ Todas las conversaciones han sido eliminadas');
                }
            }

            function refreshFromParent() {
                try {
                    if (window.opener && !window.opener.closed) {
                        const updatedChats = window.opener.RobustStorage.getItem('perplexity_playground_chats', []);
                        if (updatedChats && Array.isArray(updatedChats)) {
                            savedChatsData = updatedChats;
                            refreshUI();
                            console.log('✅ Lista de conversaciones actualizada desde la ventana principal');
                        }
                    }
                } catch (e) {
                    console.error('❌ Error actualizando: ' + e.message);
                }
            }

            function refreshUI() {
                const container = document.querySelector('.chats-grid');
                if (!container) return;

                if (savedChatsData.length === 0) {
                    container.innerHTML = '<div class="empty-state"><h2>📂 No hay conversaciones guardadas</h2><p>Regresa a Perplexity Playground y usa el botón <strong>"💾 Guardar Chat"</strong> para guardar tu conversación actual.</p></div>';
                    document.querySelector('.header .stats').textContent = '💬 0 conversaciones guardadas • 📊 0 mensajes totales';
                    return;
                }

                const totalMessages = savedChatsData.reduce((sum, chat) => sum + (chat.messages?.length || 0), 0);
                document.querySelector('.header .stats').textContent = '💬 ' + savedChatsData.length + ' conversaciones guardadas • 📊 ' + totalMessages + ' mensajes totales';

                let cardsHTML = '';
                savedChatsData.forEach((chat, index) => {
                    const previewText = getChatPreview(chat);
                    const safeChatName = escapeHTML(chat.name);
                    const safePreviewText = escapeHTML(previewText);

                    cardsHTML += '<div class="chat-card" data-chat-index="' + index + '">';
                    cardsHTML += '<div class="chat-name">' + safeChatName + '</div>';
                    cardsHTML += '<div class="chat-meta">';
                    cardsHTML += '<span>🕒 ' + getFormattedTime(chat.timestamp) + '</span>';
                    cardsHTML += '<span>💬 ' + (chat.messages?.length || 0) + ' mensajes</span>';
                    cardsHTML += '</div>';
                    cardsHTML += '<div class="chat-preview">' + safePreviewText + '</div>';
                    cardsHTML += '<div class="chat-actions">';
                    cardsHTML += '<button class="action-btn view-btn" onclick="viewChat(' + index + ')">👁️ Ver Completo</button>');
                    cardsHTML += '<button class="action-btn export-btn" onclick="exportSingleChat(' + index + ')">📤 Exportar</button>');
                    cardsHTML += '<button class="action-btn delete-btn" onclick="deleteChat(' + index + ')">🗑️ Eliminar</button>');
                    cardsHTML += '</div>';
                    cardsHTML += '</div>';
                });

                container.innerHTML = cardsHTML;
            }

            window.addEventListener('message', function(event) {
                if (event.origin !== parentOrigin) return;
                if (event.data && event.data.action === 'refreshChatData') {
                    try {
                        const updatedChats = JSON.parse(event.data.chats);
                        if (Array.isArray(updatedChats)) {
                            savedChatsData = updatedChats;
                            refreshUI();
                        }
                    } catch (e) {
                        console.error('Error procesando actualización:', e);
                    }
                }
            });

            setInterval(function() {
                if (window.opener && !window.opener.closed) {
                    try {
                        const updatedChats = window.opener.RobustStorage.getItem('perplexity_playground_chats', []);
                        if (JSON.stringify(updatedChats) !== JSON.stringify(savedChatsData)) {
                            savedChatsData = updatedChats;
                            refreshUI();
                        }
                    } catch (e) {
                        console.warn('No se pudo verificar actualizaciones:', e);
                    }
                } else {
                    console.log('Ventana principal cerrada, deteniendo comprobación periódica');
                    clearInterval(this);
                }
            }, 5000);

            window.addEventListener('load', function() {
                document.body.focus();
            });

            console.log('✅ Chat Manager completamente inicializado');
        `;

        newWindow.document.body.appendChild(scriptElement);
        newWindow.document.close();
        newWindow.focus();

        console.log('✅ Gestor de chats abierto en nueva ventana con JavaScript funcional.');
    }

    // --- Initialization and Observers ---
    function initializeFeatures() {
        if (featuresInitialized) return;
        console.log('🚀 Iniciando Perplexity Playground Advanced Pro...');

        try {
            GM_addStyle(`
                .advanced-pro-floating-container {
                    position: fixed;
                    z-index: 2000; /* Ensure it's above most UI elements */
                    background: #2a2a30; /* Dark background */
                    border: 1px solid #404040;
                    border-radius: 12px;
                    box-shadow: 0 4px 20px rgba(0,0,0,0.4);
                    padding: 10px;
                    display: flex;
                    flex-direction: column;
                    gap: 10px;
                    min-width: 250px;
                    max-height: 90vh; /* Limit height */
                    overflow-y: auto; /* Allow scrolling if many buttons */
                    resize: both; /* Allow resizing */
                    overflow: auto; /* Ensure scrollbars appear if resized too small */
                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
                }
                .advanced-pro-floating-container.hidden-ui .advanced-pro-controls-panel {
                    display: none !important;
                }
                .advanced-pro-floating-container.hidden-ui {
                    padding: 5px; /* Smaller padding when hidden */
                    min-width: unset;
                    max-height: unset;
                    height: auto;
                    width: auto;
                    overflow: visible;
                }
                .advanced-pro-floating-container.hidden-ui .advanced-pro-header {
                    margin-bottom: 0;
                }

                .advanced-pro-header {
                    font-weight: bold;
                    color: #6366f1; /* Accent color */
                    text-align: center;
                    padding: 8px;
                    margin-bottom: 10px;
                    border-bottom: 1px solid #404040;
                    cursor: grab;
                }
                .advanced-pro-controls-panel {
                    display: flex;
                    flex-direction: column;
                    gap: 8px;
                }

                .advanced-pro-buttons-grid {
                    display: grid;
                    grid-template-columns: 1fr 1fr; /* Two columns */
                    gap: 6px;
                }

                .advanced-pro-btn {
                    background: #4a4a50; /* Button background */
                    color: white;
                    border: none;
                    padding: 8px 12px;
                    border-radius: 8px;
                    cursor: pointer;
                    font-size: 13px;
                    font-weight: 500;
                    transition: all 0.2s ease;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: 6px;
                    white-space: nowrap;
                    text-align: center;
                }
                .advanced-pro-btn:hover {
                    background: #5c5c63;
                    transform: translateY(-1px);
                    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
                }
                .advanced-pro-btn .icon {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    width: 16px;
                    height: 16px;
                }
                .advanced-pro-btn .icon svg {
                    width: 100%;
                    height: 100%;
                }

                .advanced-pro-dropdown-wrapper {
                    position: relative;
                    margin-bottom: 8px;
                    display: block;
                }
                .advanced-pro-dropdown-select {
                    width: 100%;
                    background: #4a4a50;
                    color: white;
                    padding: 8px 12px;
                    border: none;
                    border-radius: 8px;
                    cursor: pointer;
                    font-size: 13px;
                    min-height: 34px;
                    appearance: none; /* Remove native dropdown arrow */
                    padding-right: 30px; /* Space for custom arrow */
                }
                .advanced-pro-dropdown-select:focus {
                    outline: none;
                    box-shadow: 0 0 0 2px #6366f1;
                }
                .advanced-pro-dropdown-select option {
                    background: #2a2a30; /* Options background */
                    color: white;
                }
                .advanced-pro-dropdown-select optgroup {
                    background: #2a2a30;
                    color: #ccc;
                }
                .advanced-pro-dropdown-arrow {
                    position: absolute;
                    right: 10px;
                    top: 50%;
                    transform: translateY(-50%);
                    pointer-events: none;
                    color: #ccc;
                }

                .advanced-pro-toggle-button {
                    width: 100%;
                    margin-top: 10px;
                    background: #3a3a40;
                    border-top: 1px solid #404040;
                    border-radius: 0 0 10px 10px;
                }
                .advanced-pro-floating-container.hidden-ui .advanced-pro-toggle-button {
                    border-radius: 10px; /* Full border when only toggle button visible */
                }
                .advanced-pro-toggle-button:hover {
                    background: #4b4b50;
                }

                .advanced-pro-btn.drag-active {
                    border: 2px dashed #6366f1;
                    background-color: #3b82f620; /* Light blue background for drag indication */
                }
            `);

            setTimeout(() => setDefaultModel(), 1000);
            addControlsToFloatingUI();
            setupCharacterCounter();

            const autoSaveEnabled = RobustStorage.getItem('auto_save_enabled', true);
            if (autoSaveEnabled) {
                startAutoSave();
            }

            featuresInitialized = true;
            console.log('✅ Perplexity Playground Advanced Pro inicializado correctamente');
        }
        catch (error) {
            console.error('❌ Error durante la inicialización:', error);
        }
    }

    function setDefaultModel() {
        const possibleSelectors = ['#lamma-select', 'select[value*="sonar"]', 'select option[value*="sonar"]', '[data-testid*="model"] select', 'select'];
        for (const selector of possibleSelectors) {
            const element = document.querySelector(selector);
            if (element && element.tagName === 'SELECT') {
                const sonarOption = Array.from(element.options).find(option => option.value.includes('sonar') || option.textContent.includes('sonar'));
                if (sonarOption) {
                    element.value = sonarOption.value;
                    element.dispatchEvent(new Event('change', { bubbles: true }));
                    console.log(`✅ Modelo establecido a: ${sonarOption.value}`);
                    return true;
                }
            }
        }
        return false;
    }

    function checkPageReady() {
        const textarea = findElement(SELECTORS.INPUT_TEXTAREA);
        const hasContent = document.body.children.length > 5;
        const floatingUIExists = document.getElementById('perplexity-floating-container');

        // Page is ready if textarea and basic content are there, AND our UI is either present or we haven't tried to create it yet (featuresInitialized == false)
        if (textarea && hasContent && (floatingUIExists || !featuresInitialized)) {
            console.log('✅ Página lista o controles no inicializados, procediendo a verificar/inicializar.');
            return true;
        }
        return false;
    }

    function startInitialization() {
        if (featuresInitialized && document.getElementById('perplexity-floating-container')) {
            console.log('Advanced Pro ya inicializado y UI presente.');
            return;
        }

        if (checkPageReady()) {
            initializeFeatures();
            return;
        }

        retryCount++;
        if (retryCount >= CONFIG.MAX_RETRIES) {
            console.warn('⚠️ Máximo de reintentos alcanzado. La página podría no estar completamente cargada, forzando inicialización.');
            initializeFeatures(); // Force initialize even if not fully ready to avoid a completely dead script
            return;
        }

        console.log(`🔄 Reintento ${retryCount}/${CONFIG.MAX_RETRIES}...`);
        setTimeout(startInitialization, CONFIG.RETRY_INTERVAL);
    }

    // --- Inter-window Message Handling ---
    window.addEventListener('message', (event) => {
        if (event.origin !== window.location.origin) return;

        if (event.data && event.data.action) {
            switch(event.data.action) {
                case 'startAutoSave':
                    startAutoSave();
                    RobustStorage.setItem('auto_save_enabled', true);
                    break;
                case 'stopAutoSave':
                    stopAutoSave();
                    RobustStorage.setItem('auto_save_enabled', false);
                    break;
                case 'deleteChat':
                    try {
                        const currentChats = RobustStorage.getItem('perplexity_playground_chats', []);
                        const chatIndexToDelete = currentChats.findIndex(c => c.name === event.data.chatName);
                        if (chatIndexToDelete !== -1) {
                            currentChats.splice(chatIndexToDelete, 1);
                            RobustStorage.setItem('perplexity_playground_chats', currentChats);
                            console.log(`✅ Chat "${event.data.chatName}" eliminado desde ventana hija.`);
                        }
                    } catch (error) {
                        console.error('❌ Error eliminando chat desde ventana hija:', error);
                    }
                    break;
                case 'clearAllChats':
                    try {
                        RobustStorage.setItem('perplexity_playground_chats', []);
                        console.log('✅ Todos los chats eliminados desde ventana hija.');
                    } catch (error) {
                        console.error('❌ Error limpiando chats desde ventana hija:', error);
                    }
                    break;
            }
        }
    });

    // --- Lifecycle Hooks ---
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', startInitialization);
    } else {
        startInitialization();
    }

    // Use a MutationObserver to react to significant DOM changes that might indicate a page transition or dynamic loading
    const observer = new MutationObserver((mutations) => {
        // If features are not initialized OR if our floating container has been removed (e.g., page navigation)
        if (!featuresInitialized || !document.getElementById('perplexity-floating-container')) {
            console.log('Detectado cambio en el DOM o UI faltante, verificando estado de inicialización...');
            startInitialization();
        }
    });
    observer.observe(document.body, { childList: true, subtree: true, attributes: false }); // Observe for child list changes, but not attribute changes to avoid noise

    window.addEventListener('beforeunload', () => {
        stopAutoSave();
        if (window.autoSaveWindows) {
            window.autoSaveWindows.forEach(win => {
                if (!win.closed) { try { win.close(); } catch (e) { console.warn('⚠️ Error cerrando ventana:', e); } }
            });
        }
        observer.disconnect();
    });

    // --- Global Functions for Debugging/Control (unchanged) ---
    function testChatExtraction() {
        console.log('🧪 === TESTING EXTRACCIÓN DE CHAT ===');
        const chatContent = getCurrentChatContent();
        console.log('📊 Resultado de extracción:', chatContent);
        if (chatContent.length === 0) {
            console.warn('❌ No se encontraron mensajes en el chat actual. Abre la consola (F12) para ver los detalles del debugging.');
        } else {
            console.log(`✅ Extracción exitosa: ${chatContent.length} mensajes encontrados.`);
            console.log(`📝 Primeros 2 mensajes:`);
            console.log(`1. [${chatContent[0].type}]: ${chatContent[0].text.substring(0, Math.min(chatContent[0].text.length, 100))}...`);
            if (chatContent[1]) {
                console.log(`2. [${chatContent[1].type}]: ${chatContent[1].text.substring(0, Math.min(chatContent[1].text.length, 100))}...`);
            }
        }
        return chatContent;
    }
    function clearAllSavedChats() {
        if (confirm('⚠️ ¿Estás seguro de que quieres eliminar TODAS las conversaciones guardadas?\n\nEsta acción es PERMANENTE y no se puede deshacer.')) {
            try {
                RobustStorage.setItem('perplexity_playground_chats', []);
                console.log('✅ Todas las conversaciones han sido eliminadas del almacenamiento local.');
            } catch (e) {
                console.error('❌ Error limpiando localStorage:', e);
            }
        }
    }
    function clearAutoSavedChats() {
        if (confirm('⚠️ ¿Eliminar TODOS los chats autoguardados?\n\nEsta acción es PERMANENTE.')) {
            try {
                RobustStorage.setItem('perplexity_auto_saves', []);
                console.log('✅ Todos los autoguardados han sido eliminados.');
            } catch (e) {
                console.error('❌ Error limpiando autoguardados:', e);
            }
        }
    }
    function getAutoSaveStatus() {
        return {
            isActive: isAutoSaveActive,
            interval: CONFIG.AUTO_SAVE_INTERVAL,
            maxSaves: CONFIG.MAX_AUTO_SAVES,
            currentSaves: RobustStorage.getItem('perplexity_auto_saves', []).length,
            lastSave: RobustStorage.getItem('perplexity_auto_saves', [])[0]?.timestamp || 'Nunca'
        };
    }

    window.testChatExtraction = testChatExtraction;
    window.clearAllSavedChats = clearAllSavedChats;
    window.loadSavedChatsMain = loadSavedChatsMain;
    window.openChatsManagerWindow = openChatsManagerWindow;
    window.openJSExecutorWindow = openJSExecutorWindow;
    window.openAutoSaveWindow = openAutoSaveWindow;
    window.startAutoSave = startAutoSave;
    window.stopAutoSave = stopAutoSave;
    window.clearAutoSavedChats = clearAutoSavedChats;
    window.getAutoSaveStatus = getAutoSaveStatus;
    window.getCurrentChatContent = getCurrentChatContent;
    window.RobustStorage = RobustStorage;

    console.log('✨ Perplexity Playground Advanced Pro - Draggable UI v3.4 cargado');
    console.log('🔧 Funciones disponibles en consola para debugging:');
    console.log('- window.testChatExtraction()');
    console.log('- window.openJSExecutorWindow()');
    console.log('- window.openAutoSaveWindow()');
    console.log('- window.startAutoSave()');
    console.log('- window.stopAutoSave()');
    console.log('- window.getAutoSaveStatus()');
    console.log('- window.clearAllSavedChats()');
    console.log('- window.clearAutoSavedChats()');
})();