Perplexity Playground Advanced Pro

Funcionalidades avanzadas para Perplexity: guardar/exportar/cargar conversaciones, prompts, contador de caracteres, ejecutor de JavaScript integrado, y sistema de autoguardado robusto con vista en tiempo real.

// ==UserScript==
// @name         Perplexity Playground Advanced Pro
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Funcionalidades avanzadas para Perplexity: guardar/exportar/cargar conversaciones, prompts, contador de caracteres, ejecutor de JavaScript integrado, y sistema de autoguardado robusto con vista en tiempo real.
// @match        https://playground.perplexity.ai/*
// @author       YouTubeDrawaria
// @grant        none
// @license      MIT
// @icon         https://playground.perplexity.ai/favicon.ico
// ==/UserScript==

(function() {
    'use strict';

    // Configuración actualizada
    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
    };

    // Selectores CSS actualizados
    const SELECTORS = {
        INPUT_TEXTAREA: 'textarea[placeholder="Ask anything…"]',
        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"]',
        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"]'
    };

    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 enemiga 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 enemiga 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
    const DOWNLOAD_ICON_SVG = `<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>`;
    const UPLOAD_ICON_SVG = `<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>`;
    const CODE_ICON_SVG = `<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>`;
    const AUTO_SAVE_ICON_SVG = `<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"></svg>`;

    // =========================================================
    // STORAGE MANAGER ROBUSTO
    // =========================================================
    const RobustStorage = {
        // Intentar múltiples métodos de almacenamiento
        setItem: function(key, value) {
            const serialized = JSON.stringify(value);
            const attempts = [
                () => localStorage.setItem(key, serialized),
                () => sessionStorage.setItem(key, serialized),
                () => this.setIndexedDB(key, value)
            ];

            for (let attempt of attempts) {
                try {
                    attempt();
                    return true;
                } catch (e) {
                    console.warn(`⚠️ Error con método de almacenamiento:`, e);
                }
            }
            return false;
        },

        getItem: function(key, defaultValue = null) {
            const attempts = [
                () => localStorage.getItem(key),
                () => sessionStorage.getItem(key),
                () => this.getIndexedDB(key)
            ];

            for (let attempt of attempts) {
                try {
                    const result = attempt();
                    if (result) return JSON.parse(result);
                } catch (e) {
                    console.warn(`⚠️ Error leyendo almacenamiento:`, e);
                }
            }
            return defaultValue;
        },

        // IndexedDB como fallback (versión simplificada)
        setIndexedDB: function(key, value) {
            // Para simplicidad, usar localStorage como backup principal
            // En una implementación completa, usaríamos IndexedDB
            try {
                const backupKey = `backup_${key}`;
                sessionStorage.setItem(backupKey, JSON.stringify(value));
            } catch (e) {
                console.error('Error en backup IndexedDB:', e);
            }
        },

        getIndexedDB: function(key) {
            try {
                const backupKey = `backup_${key}`;
                return sessionStorage.getItem(backupKey);
            } catch (e) {
                return null;
            }
        }
    };

    // =========================================================
    // FUNCIONES PRINCIPALES EXISTENTES (mantenidas)
    // =========================================================

    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.CONTROLS_AREA, 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 findElements(selectors) {
        if (typeof selectors === 'string') {
            return document.querySelectorAll(selectors);
        }
        for (const selector of selectors) {
            const elements = document.querySelectorAll(selector);
            if (elements.length > 0) return elements;
        }
        return [];
    }

    function createPerplexityButton(iconHtml, tooltip, onClick) {
        const button = document.createElement('button');
        button.innerHTML = `<div class="flex items-center min-w-0 gap-two justify-center"><span style="font-size: 16px;">${iconHtml}</span></div>`;
        button.title = tooltip;
        button.className = `focus-visible:bg-offsetPlus hover:bg-offsetPlus text-quiet hover:text-foreground dark:hover:bg-offsetPlus font-sans focus:outline-none outline-none outline-transparent transition duration-300 ease-out select-none items-center relative group/button font-semimedium justify-center text-center items-center rounded-full cursor-pointer active:scale-[0.97] active:duration-150 active:ease-outExpo origin-center whitespace-nowrap inline-flex text-base h-10 aspect-square`.replace(/\s+/g, ' ').trim();
        if (onClick) {
            button.addEventListener('click', onClick);
        }
        return button;
    }

    function createCategorizedDropdown(categorizedOptions, onSelect, placeholder = "Seleccionar Prompt") {
        const select = document.createElement('select');
        Object.assign(select.style, {
            backgroundColor: '#4a4a50', color: 'white', padding: '8px 12px', border: 'none', borderRadius: '8px', cursor: 'pointer', fontSize: '14px', marginLeft: '8px', minWidth: '180px', transition: 'all 0.2s ease', height: '40px', appearance: 'none', backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E")`, backgroundRepeat: 'no-repeat', backgroundPosition: 'right 8px center', backgroundSize: '16px', paddingRight: '30px'
        });
        const defaultOption = document.createElement('option');
        defaultOption.value = "";
        defaultOption.textContent = placeholder;
        defaultOption.disabled = true;
        defaultOption.selected = true;
        select.appendChild(defaultOption);

        for (const category in categorizedOptions) {
            const optgroup = document.createElement('optgroup');
            optgroup.label = category;
            optgroup.style.color = '#cccccc';
            categorizedOptions[category].forEach(opt => {
                const option = document.createElement('option');
                option.value = opt.text;
                option.textContent = opt.name;
                option.style.color = 'white';
                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);
            }
        });

        return select;
    }

    function getCurrentChatContent() {
        const chatContent = [];
        console.log('🔍 Buscando mensajes con selectores específicos de Perplexity...');

        const allMessageContainers = document.querySelectorAll([
            'div[class*="bg-offset"]',
            'div[class*="bg-base"]',
            'div[class*="px-md"]'
        ].join(','));

        allMessageContainers.forEach((container, index) => {
            let fullText = '';

            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"]') ? '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(() => {
                alert('📋 Prompt copiado al portapapeles. Pégalo manualmente en el chat.');
            }).catch(() => {
                alert('❌ No se pudo insertar el prompt automáticamente. Inténtalo de nuevo.');
            });
        }
    }

    // =========================================================
    // NUEVO: EJECUTOR DE JAVASCRIPT INTEGRADO
    // =========================================================

    function createJavaScriptExecutor() {
        const jsExecutorButton = createPerplexityButton(CODE_ICON_SVG, '⚡ Ejecutor de JavaScript - Ejecuta código JS en la página', openJSExecutorWindow);
        jsExecutorButton.id = 'perplexity-js-executor';
        return jsExecutorButton;
    }

    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) {
            alert('❌ El navegador bloqueó la ventana emergente.\n\n🔧 Permite ventanas emergentes para playground.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');
    }

    // =========================================================
    // NUEVO: SISTEMA DE AUTOGUARDADO ROBUSTO
    // =========================================================

    function createAutoSaveButton() {
        const autoSaveButton = createPerplexityButton(AUTO_SAVE_ICON_SVG, '🔄 Auto-Guardado - Ver chats en tiempo real y gestionar autoguardado', openAutoSaveWindow);
        autoSaveButton.id = 'perplexity-auto-save';
        return autoSaveButton;
    }

    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();

        // Verificación segura de los mensajes
        let preview = 'Sin vista previa';
        if (chatContent && Array.isArray(chatContent) && chatContent.length > 0 && chatContent.text) {
            // Obtener solo el primer mensaje para la vista previa
            const firstMessage = chatContent.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);

        // Mantener solo los últimos N autoguardados
        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');

        // Actualizar ventana si está abierta
        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 ? chatContent.text : 'n/a'
        });
    }
}


    function notifyAutoSaveWindow() {
        // Notificar a las ventanas de autoguardado abiertas
        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) {
            alert('❌ El navegador bloqueó la ventana emergente.\n\n🔧 Permite ventanas emergentes para playground.perplexity.ai');
            return;
        }

        // Registrar ventana para notificaciones
        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>');

        // Header
        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>');

        // Controls
        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">');

        // Status Panel
        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>');

        // Tabs
        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>');

        // Tab Content
        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

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

        // JavaScript para la funcionalidad de autoguardado
        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;

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

                // Update content
                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.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) {
                    alert('❌ 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) {
                        alert('❌ 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) {
                    alert('❌ Error: ' + error.message);
                }
            }

            function exportAllSaves() {
                const allSaves = [...autoSaveData, ...manualSaveData];
                if (allSaves.length === 0) {
                    alert('❌ 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) {
                        alert('❌ 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) {
                    alert('❌ 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';

                // Update tab labels
                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);
            }

            // Escuchar mensajes de la ventana principal
            window.addEventListener('message', (event) => {
                if (event.origin !== window.location.origin) return;

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

            // Verificar actualizaciones periódicamente
            setInterval(refreshData, 10000); // Cada 10 segundos

            // Inicializar
            updateSavesDisplay();

            // Focus inicial
            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');
    }

    // =========================================================
    // FUNCIONES EXISTENTES MANTENIDAS
    // =========================================================

    function saveCurrentChat() {
        const chatContent = getCurrentChatContent();
        console.log('💾 Intentando guardar chat...', chatContent);
        if (chatContent.length === 0) {
            alert('❌ 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);
                alert(`✅ Conversación "${chatName}" guardada con éxito.\n📊 ${chatContent.length} mensajes guardados.`);
                console.log('✅ Chat guardado exitosamente:', newChat);
            } catch (e) {
                console.error("❌ Error al guardar:", e);
                alert("❌ Error al guardar la conversación: " + e.message);
            }
        }
    }

    function exportChatToText() {
        console.log('📤 Iniciando exportación específica de Perplexity...');
        const chatContent = getCurrentChatContent();
        if (chatContent.length === 0) {
            alert('❌ 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);
            alert(`✅ Conversación exportada exitosamente.\n📊 ${chatContent.length} mensajes exportados.`);
            console.log('✅ Exportación completada');
        } catch (error) {
            console.error('❌ Error al exportar:', error);
            alert('❌ Error al exportar la conversación: ' + error.message);
        }
    }

        // Funciones auxiliares y de importación (mantener las existentes)
    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 = '';
        const importButton = document.getElementById('perplexity-import-button');
        const originalTitle = importButton?.title || '';
        const updateButtonStatus = (title, iconHtml = UPLOAD_ICON_SVG) => {
            if (importButton) {
                importButton.title = title;
                const iconSpan = importButton.querySelector('span');
                if (iconSpan) iconSpan.innerHTML = iconHtml;
            }
        };
        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(originalTitle, UPLOAD_ICON_SVG);
        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 = createPerplexityButton(UPLOAD_ICON_SVG, '📎 Importar archivos (texto, imagen con OCR, PDF, DOCX) - Arrastra y suelta o haz clic', () => fileInput.click());
        importButton.id = 'perplexity-import-button';
        ['dragover', 'dragenter'].forEach(eventName => {
            importButton.addEventListener(eventName, (e) => {
                e.preventDefault();
                e.stopPropagation();
                importButton.classList.add('bg-offsetPlus');
                importButton.style.border = '2px dashed #6366f1';
            });
        });
        ['dragleave', 'dragend'].forEach(eventName => {
            importButton.addEventListener(eventName, (e) => {
                e.preventDefault();
                e.stopPropagation();
                importButton.classList.remove('bg-offsetPlus');
                importButton.style.border = 'none';
            });
        });
        importButton.addEventListener('drop', (e) => {
            e.preventDefault();
            e.stopPropagation();
            importButton.classList.remove('bg-offsetPlus');
            importButton.style.border = 'none';
            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);
        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';
        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 container = textarea.closest('[class*="relative"], div') || textarea.parentElement;
        if (container) {
            if (getComputedStyle(container).position === 'static') {
                container.style.position = 'relative';
            }
            container.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();
    }

    // =========================================================
    // UI INTEGRADA CON NUEVAS FUNCIONALIDADES
    // =========================================================

    function addControlsToUI() {
        const buttonContainer = document.querySelector(SELECTORS.CONTROLS_AREA);
        if (!buttonContainer) {
            console.warn('⚠️ No se encontró el contenedor de botones específico, creando controles flotantes.');
            createFloatingControls();
            return;
        }
        if (buttonContainer.querySelector('[data-perplexity-controls]')) {
            return;
        }

        const controlsContainer = document.createElement('div');
        controlsContainer.setAttribute('data-perplexity-controls', 'true');

        // GRID actualizado para incluir las nuevas funcionalidades
        controlsContainer.style.cssText = `
            display: grid;
            grid-template-columns: repeat(3, minmax(0, 1fr));
            grid-template-rows: auto auto auto;
            gap: 4px;
            margin-left: 4px;
            max-width: 380px;
            grid-template-areas:
                "dropdown dropdown dropdown"
                "save load export"
                "import jsexec autosave";
            align-items: center;
            justify-items: stretch;
        `;

        // Dropdown de prompts
        const promptsDropdown = createCategorizedDropdown(ALL_CATEGORIZED_PROMPTS, handlePromptSelection, "🎯 Prompts");
        promptsDropdown.style.gridArea = 'dropdown';
        promptsDropdown.style.width = '100%';
        promptsDropdown.style.margin = '0';
        promptsDropdown.style.fontSize = '12px';
        promptsDropdown.style.height = '30px';
        promptsDropdown.style.padding = '3px 8px';

        // Función para hacer botones más compactos
        function buttonCompact(button) {
            button.style.width = '100%';
            button.style.margin = '0';
            button.style.fontSize = '12px';
            button.style.height = '28px';
            button.style.padding = '3px 6px';
            button.style.minWidth = '0';
            button.style.minHeight = '0';
            return button;
        }

        // Botones existentes
        const saveButton = buttonCompact(createPerplexityButton('💾', 'Guardar Chat', saveCurrentChat));
        saveButton.style.gridArea = 'save';

        const loadButton = buttonCompact(createPerplexityButton('📂', 'Cargar Chat', loadSavedChatsMain));
        loadButton.style.gridArea = 'load';

        const exportButton = buttonCompact(createPerplexityButton('📤', 'Exportar Chat', exportChatToText));
        exportButton.style.gridArea = 'export';

        const importButton = buttonCompact(createImportButton());
        importButton.style.gridArea = 'import';

        // NUEVOS BOTONES
        const jsExecutorButton = buttonCompact(createJavaScriptExecutor());
        jsExecutorButton.style.gridArea = 'jsexec';

        const autoSaveButton = buttonCompact(createAutoSaveButton());
        autoSaveButton.style.gridArea = 'autosave';

        // Agregar todos los controles
        controlsContainer.appendChild(promptsDropdown);
        controlsContainer.appendChild(saveButton);
        controlsContainer.appendChild(loadButton);
        controlsContainer.appendChild(exportButton);
        controlsContainer.appendChild(importButton);
        controlsContainer.appendChild(jsExecutorButton);
        controlsContainer.appendChild(autoSaveButton);

        buttonContainer.appendChild(controlsContainer);
        console.log('✅ Controles compactos GRID añadidos con nuevas funcionalidades');
    }

    function createFloatingControls() {
        const floatingContainer = document.createElement('div');
        floatingContainer.style.cssText = `position: fixed; top: 80px; right: 20px; z-index: 1000; background: rgba(42, 42, 48, 0.95); padding: 12px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); display: flex; flex-direction: column; gap: 8px; min-width: 220px;`;
        const title = document.createElement('div');
        title.textContent = '🛠️ Perplexity Advanced Pro';
        title.style.cssText = `color: #6366f1; font-weight: bold; text-align: center; margin-bottom: 8px; font-size: 14px;`;
        floatingContainer.appendChild(title);

        const promptsDropdown = createCategorizedDropdown(ALL_CATEGORIZED_PROMPTS, handlePromptSelection, "🎯 Prompts");
        floatingContainer.appendChild(promptsDropdown);

        const controls = [
            { text: '💾 Guardar', func: saveCurrentChat },
            { text: '📂 Cargar', func: loadSavedChatsMain },
            { text: '📤 Exportar', func: exportChatToText },
            { text: '📎 Importar', func: () => { const input = document.createElement('input'); input.type = 'file'; input.multiple = true; input.accept = '.txt,.pdf,.docx,.png,.jpg,.jpeg'; input.onchange = (e) => processDroppedFiles(e.target.files); input.click(); } },
            { text: '⚡ JS Executor', func: openJSExecutorWindow },
            { text: '🔄 Auto-Guard', func: openAutoSaveWindow }
        ];

        controls.forEach(control => {
            const btn = createButton(control.text, control.func, { width: '100%', margin: '0', fontSize: '13px' });
            floatingContainer.appendChild(btn);
        });

        document.body.appendChild(floatingContainer);
        console.log('✅ Controles flotantes creados con nuevas funcionalidades');
    }

    function createButton(text, onClick, styles = {}) {
        const button = document.createElement('button');
        button.textContent = text;
        const defaultStyles = {
            backgroundColor: '#4a4a50', color: 'white', padding: '8px 16px', border: 'none', borderRadius: '8px', cursor: 'pointer', fontSize: '14px', fontWeight: '500', marginLeft: '8px', transition: 'all 0.2s ease', whiteSpace: 'nowrap', ...styles
        };
        Object.assign(button.style, defaultStyles);
        button.addEventListener('mouseenter', () => {
            button.style.backgroundColor = '#5c5c63';
            button.style.transform = 'translateY(-1px)';
        });
        button.addEventListener('mouseleave', () => {
            button.style.backgroundColor = defaultStyles.backgroundColor;
            button.style.transform = 'translateY(0)';
        });
        if (onClick) {
            button.addEventListener('click', onClick);
        }
        return button;
    }

    // =========================================================
    // GESTOR DE CHATS EXISTENTE (mantener loadSavedChatsMain y openChatsManagerWindow)
    // =========================================================

    function loadSavedChatsMain() {
        console.log('📂 === CARGANDO CHATS EN NUEVA VENTANA (MÉTODO ROBUSTO) ===');
        try {
            const savedChatsString = RobustStorage.getItem('perplexity_playground_chats', []);
            if (!savedChatsString || savedChatsString.length === 0) {
                alert('📂 No hay conversaciones guardadas.\n\n💡 Primero guarda una conversación con "💾 Guardar".');
                return;
            }
            openChatsManagerWindow(savedChatsString);
        } catch (error) {
            console.error('❌ Error en loadSavedChatsMain:', error);
            alert(`❌ Error al cargar conversaciones: ${error.message}`);
        }
    }

    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) {
        alert('❌ El navegador bloqueó la ventana emergente.\n\n🔧 Solución:\n1. Permite ventanas emergentes para playground.perplexity.ai\n2. 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"</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
                ? (chat.messages.text && chat.messages.text.length > 150
                    ? chat.messages.text.substring(0, 150) + '...'
                    : (chat.messages.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

    // JavaScript funcional COMPLETO para el gestor de chats
    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';

            // Buscar el primer mensaje que tenga texto real
            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) {
                alert('❌ 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>');

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

            // Messages
            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>');
                });
            }

            // Close button
            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) {
                alert('❌ 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);

            alert('✅ 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.')) {
                // Primero notificar a la ventana principal
                try {
                    window.opener.postMessage({
                        action: 'deleteChat',
                        chatName: savedChatsData[index].name
                    }, parentOrigin);
                } catch (e) {
                    console.warn('⚠️ No se pudo notificar a la ventana principal:', e);
                }

                // Después eliminar localmente
                savedChatsData.splice(index, 1);
                localStorage.setItem('perplexity_playground_chats', JSON.stringify(savedChatsData));
                refreshUI();

                alert('✅ Conversación eliminada');
            }
        }

        function exportAllChats() {
            if (savedChatsData.length === 0) {
                alert('❌ 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);

            alert('✅ 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?')) {
                // Notificar a la ventana principal
                try {
                    window.opener.postMessage({
                        action: 'clearAllChats'
                    }, parentOrigin);
                } catch (e) {
                    console.warn('⚠️ No se pudo notificar a la ventana principal:', e);
                }

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

                alert('✅ 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();
                        alert('✅ Lista de conversaciones actualizada desde la ventana principal');
                    }
                }
            } catch (e) {
                alert('❌ 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"</strong> para guardar tu conversación actual.</p></div>';
                document.querySelector('.header .stats').textContent = '💬 0 conversaciones guardadas • 📊 0 mensajes totales';
                return;
            }

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

            // Build chat cards
            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;
        }

        // Mantener sincronizado con la ventana principal
        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);
                }
            }
        });

        // Comprobar actualizaciones periódicas
        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);

        // Focus inicial
        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.');
}


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

    // =========================================================
    // INICIALIZACIÓN Y MANEJO DE MENSAJES
    // =========================================================

    function initializeFeatures() {
        if (featuresInitialized) return;
        console.log('🚀 Iniciando Perplexity Playground Advanced Pro...');

        try {
            setTimeout(() => setDefaultModel(), 1000);
            addControlsToUI();
            setupCharacterCounter();

            // Iniciar autoguardado si está configurado
            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 buttonContainer = document.querySelector(SELECTORS.CONTROLS_AREA);
        if (textarea && hasContent && buttonContainer) {
            console.log('✅ Página lista, inicializando funciones...');
            return true;
        }
        return false;
    }

    function startInitialization() {
        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.');
            if (!document.querySelector(SELECTORS.CONTROLS_AREA)) {
                console.log('Forzando inicialización de controles flotantes.');
                createFloatingControls();
            }
            initializeFeatures();
            return;
        }

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

    // Manejo de mensajes entre ventanas
    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;
            }
        }
    });

    // =========================================================
    // INICIALIZACIÓN Y OBSERVADORES
    // =========================================================

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

    const observer = new MutationObserver((mutations) => {
        if (!featuresInitialized || !document.querySelector(SELECTORS.CONTROLS_AREA + ' [data-perplexity-controls]')) {
            console.log('Detectado cambio en el DOM, verificando estado de inicialización...');
            startInitialization();
        }
    });

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

    window.addEventListener('beforeunload', () => {
        // Limpiar recursos antes de cerrar
        stopAutoSave();

        // Limpiar ventanas de autoguardado
        if (window.autoSaveWindows) {
            window.autoSaveWindows.forEach(win => {
                if (!win.closed) {
                    try {
                        win.close();
                    } catch (e) {
                        console.warn('⚠️ Error cerrando ventana:', e);
                    }
                }
            });
        }

        document.querySelectorAll('[data-perplexity-sidepanel]').forEach(el => {
            if (el.__escapeListener) {
                document.removeEventListener('keydown', el.__escapeListener);
            }
            el.remove();
        });

        observer.disconnect();
    });

    // =========================================================
    // FUNCIONES DE DEBUGGING Y UTILIDADES
    // =========================================================

    function testChatExtraction() {
        console.log('🧪 === TESTING EXTRACCIÓN DE CHAT ===');
        const chatContent = getCurrentChatContent();
        console.log('📊 Resultado de extracción:', chatContent);
        if (chatContent.length === 0) {
            alert('❌ No se encontraron mensajes en el chat actual.\n\n🔍 Abre la consola (F12) para ver los detalles del debugging.');
        } else {
            alert(`✅ Extracción exitosa: ${chatContent.length} mensajes encontrados.\n\n📝 Primeros 2 mensajes:\n\n1. [${chatContent.type}]: ${chatContent.text.substring(0, Math.min(chatContent.text.length, 100))}...\n\n${chatContent[1] ? `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', []);
                alert('✅ Todas las conversaciones han sido eliminadas del almacenamiento local.');
                console.log('🧹 localStorage limpiado de "perplexity_playground_chats".');
            } catch (e) {
                console.error('❌ Error limpiando localStorage:', e);
                alert('❌ Error al limpiar el almacenamiento: ' + e.message);
            }
        }
    }

    function clearAutoSavedChats() {
        if (confirm('⚠️ ¿Eliminar TODOS los chats autoguardados?\n\nEsta acción es PERMANENTE.')) {
            try {
                RobustStorage.setItem('perplexity_auto_saves', []);
                alert('✅ Todos los autoguardados han sido eliminados.');
                console.log('🧹 Autoguardados limpiados.');
            } catch (e) {
                console.error('❌ Error limpiando autoguardados:', e);
                alert('❌ Error: ' + e.message);
            }
        }
    }

    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', [])?.timestamp || 'Nunca'
        };
    }

    console.log('📋 Perplexity Playground Advanced Pro v3.0 cargado');

    // =========================================================
    // EXPONER FUNCIONES GLOBALES PARA DEBUGGING Y CONTROL
    // =========================================================

    // Funciones existentes
    window.testChatExtraction = testChatExtraction;
    window.clearAllSavedChats = clearAllSavedChats;
    window.loadSavedChatsMain = loadSavedChatsMain;
    window.openChatsManagerWindow = openChatsManagerWindow;

    // Nuevas funciones
    window.openJSExecutorWindow = openJSExecutorWindow;
    window.openAutoSaveWindow = openAutoSaveWindow;
    window.startAutoSave = startAutoSave;
    window.stopAutoSave = stopAutoSave;
    window.clearAutoSavedChats = clearAutoSavedChats;
    window.getAutoSaveStatus = getAutoSaveStatus;
    window.getCurrentChatContent = getCurrentChatContent;
    window.RobustStorage = RobustStorage;

    // Mostrar status inicial
    console.log('🔧 Funciones disponibles en consola:');
    console.log('- window.testChatExtraction() - Probar extracción de chats');
    console.log('- window.openJSExecutorWindow() - Abrir ejecutor de JavaScript');
    console.log('- window.openAutoSaveWindow() - Abrir ventana de autoguardado');
    console.log('- window.startAutoSave() - Iniciar autoguardado');
    console.log('- window.stopAutoSave() - Detener autoguardado');
    console.log('- window.getAutoSaveStatus() - Ver estado del autoguardado');
    console.log('- window.clearAllSavedChats() - Limpiar chats guardados');
    console.log('- window.clearAutoSavedChats() - Limpiar autoguardados');

    console.log('✨ ¡Perplexity Playground Advanced Pro completamente cargado!');
    console.log('🎯 Nuevas funcionalidades: Ejecutor JS + Autoguardado robusto');

})();