WebMultitool

Adaptive compact panel with buttons and widgets

// ==UserScript==
// @name         WebMultitool
// @namespace    http://tampermonkey.net/
// @version      6.3.2
// @description  Adaptive compact panel with buttons and widgets
// @author       allu_b 
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // ========== CONFIGURATION ========== //
    const favoritesConfig = [
        { text: '4pda', url: 'https://examle.com', icon: 'https://www.google.com/s2/favicons?domain=examle.com&sz=64' },
        { text: 'Speed', url: 'https://fast.com', icon: 'https://www.google.com/s2/favicons?domain=fast.com&sz=64' },
        
    ];

    const aiConfig = [
        { text: 'Mistral', url: 'https://chat.mistral.ai/chat', icon: 'https://www.google.com/s2/favicons?domain=mistral.ai&sz=64' },
        { text: 'DeepSeek', url: 'https://chat.deepseek.com', icon: 'https://www.google.com/s2/favicons?domain=deepseek.com&sz=64' },
        { text: 'Perplexity', url: 'https://www.perplexity.ai/', icon: 'https://www.google.com/s2/favicons?domain=perplexity.com&sz=64' },
        { text: 'ChatGPT', url: 'https://chatgpt.com/', icon: 'https://www.google.com/s2/favicons?domain=openai.com&sz=64' },
        { text: 'Gemini', url: 'https://gemini.google.com/app', icon: 'https://www.google.com/s2/favicons?domain=google.com&sz=64' },
        { text: 'Claude', url: 'https://claude.ai', icon: 'https://www.google.com/s2/favicons?domain=claude.ai&sz=64' },
        { text: 'Grok', url: 'https://grok.com/', icon: 'https://www.google.com/s2/favicons?domain=x.ai&sz=64' },
        { text: 'Polybuzz', url: 'https://www.polybuzz.ai/ru/virtual-assistant', icon: 'https://www.google.com/s2/favicons?domain=polybuzz.ai&sz=64' }
    ];

    const proxyConfig = [
        { text: 'CroxyProxy', url: 'https://www.croxyproxy.com/', icon: 'https://www.google.com/s2/favicons?domain=croxyproxy.com&sz=64' },
        { text: 'Lablancer', url: 'https://www.lablancer.com/?C=D;O=A', icon: 'https://www.google.com/s2/favicons?domain=lablancer.com&sz=64' },
        { text: 'Proxyium', url: 'https://proxyium.com/', icon: 'https://www.google.com/s2/favicons?domain=proxyium.com&sz=64' },
        { text: 'ProxyPal', url: 'https://proxypal.net/', icon: 'https://www.google.com/s2/favicons?domain=proxypal.net&sz=64' },
        { text: 'ProxyOrb', url: 'https://proxyorb.com/ru', icon: 'https://www.google.com/s2/favicons?domain=proxyorb.com&sz=64' },
        { text: 'VPNBook', url: 'https://www.vpnbook.com/webproxy', icon: 'https://www.google.com/s2/favicons?domain=vpnbook.com&sz=64' }
    ];

    const networkTools = [
        { text: 'Ping', url: 'https://ping.eu/ping/', icon: 'https://www.google.com/s2/favicons?domain=ping.eu&sz=64' },
        { text: 'Whois', url: 'https://whois.com/', icon: 'https://www.google.com/s2/favicons?domain=whois.com&sz=64' },
        { text: 'DNS Lookup', url: 'https://www.nslookup.io/', icon: 'https://www.google.com/s2/favicons?domain=nslookup.io&sz=64' },
        { text: 'SSL Check', url: 'https://www.sslshopper.com/ssl-checker.html', icon: 'https://www.google.com/s2/favicons?domain=sslshopper.com&sz=64' },
        { text: 'IP Info', url: 'https://ipinfo.io/', icon: 'https://www.google.com/s2/favicons?domain=ipinfo.io&sz=64' },
        { text: 'BrowserLeaks', url: 'https://browserleaks.com/', icon: 'https://www.google.com/s2/favicons?domain=browserleaks.com&sz=64' },
        { text: 'IP Leak', url: 'https://ipleak.net/', icon: 'https://www.google.com/s2/favicons?domain=ipleak.net&sz=64' },
        { text: 'SpeedTest', url: 'https://speedsmart.net/', icon: 'https://www.google.com/s2/favicons?domain=speedsmart.net&sz=64' },
        { text: 'CheckAdBlock', url: 'https://checkadblock.ru/', icon: 'https://www.google.com/s2/favicons?domain=checkadblock.ru&sz=64' }
    ];

    const utilities = [
        { text: 'QR Generator', url: 'https://qr-code-generator.com/', icon: 'https://www.google.com/s2/favicons?domain=qr-code-generator.com&sz=64' },
        { text: 'URL Shortener', url: 'https://tinyurl.com/app', icon: 'https://www.google.com/s2/favicons?domain=tinyurl.com&sz=64' },
        { text: 'Base64 Encode', url: 'https://www.base64encode.org/ru/', icon: 'https://www.google.com/s2/favicons?domain=base64encode.org&sz=64' },
        { text: 'RegEx Tester', url: 'https://regex101.com/', icon: 'https://www.google.com/s2/favicons?domain=regex101.com&sz=64' }
    ];

    const webrtcChats = [
        { text: 'Jitsi Meet', url: 'https://meet.jit.si/', icon: 'https://www.google.com/s2/favicons?domain=meet.jit.si&sz=64' },
        { text: 'PeerCalls', url: 'https://peercalls.com/', icon: 'https://www.google.com/s2/favicons?domain=peercalls.com&sz=64' },
        { text: 'Talky', url: 'https://talky.io/', icon: 'https://www.google.com/s2/favicons?domain=talky.io&sz=64' }
    ];

    const devToolsConfig = [
        { text: 'Viewport Info', action: 'viewportInfo' },
        { text: 'Outline All', action: 'outlineAll' },
        { text: 'Flexbox Debug', action: 'flexboxDebug' },
        { text: 'Grid Debug', action: 'gridDebug' },
        { text: 'Performance', action: 'performanceMonitor' },
        { text: 'LocalStorage', action: 'localStorageManager' },
        { text: 'Color Picker', action: 'colorPicker' },
        { text: 'Page Analyzer', action: 'pageAnalyzer' },
        { text: 'IcoGrabber', action: 'icoGrabber' },
        { text: 'Encoding', action: 'encoding' }
    ];

    const amoledConfig = [
        { text: 'Grayscale', action: 'grayscale' },
        { text: 'MobFriendly', action: 'mobFriendly' }
    ];
    
    const translateEngines = [
        { text: 'Google Translate', url: 'https://translate.google.com/translate?hl=ru&sl=auto&tl=ru&u=', icon: 'https://www.google.com/s2/favicons?domain=google.com&sz=64' },
        { text: 'Yandex Translate', url: 'https://translate.yandex.com/translate?url=', icon: 'https://www.google.com/s2/favicons?domain=yandex.ru&sz=64' }
     ];

    // ========== SETTINGS ========== //
    const panelWidth = '18vw';
    const buttonHeight = '4vmax';
    const buttonWidth = '15vw';
    const gapSize = '1.7vh';
    const topMargin = '1.5vh';
    const bottomMargin = '1.5vh';
    let searchWidget = null;
    let searchWidgetVisible = false;
    let currentWidget = null;
    let isNetMonitorActive = false;
    let netMonitorWidget = null;
    let originalPageContent = null;
    let ftpWidget = null;
    let isGrayscaleActive = false;
    let grayscaleObserver = null;
    let isMobFriendlyActive = false;
    const SWIPE_THRESHOLD = 20;
    const HIGHLIGHT_DURATION = 500;
    let isAdBlockActive = false;
    let adBlockStartX = 0, adBlockStartY = 0;

    // ========== COLORS ========== //
    const panelBackground = '#2c3e50';
    const buttonBackground = '#34495e';
    const buttonHoverBackground = '#3d566e';
    const textColor = '#ffffff';

    // ========== PAGE ANALYZER FUNCTION ========== //
    function showPageAnalyzer() {
        const analyzer = document.createElement('div');
        analyzer.id = 'page-analyzer';
        analyzer.style.cssText = `
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); 
            background: white; padding: 20px; border-radius: 10px; z-index: 10000; 
            box-shadow: 0 0 25px rgba(0,0,0,0.3); font-family: Arial, sans-serif;
            max-width: 90vw; max-height: 80vh; overflow-y: auto; text-align: center;
        `;
        
        // Collect page information
        const pageInfo = {
            title: document.title || 'No title',
            url: window.location.href,
            description: document.querySelector('meta[name="description"]')?.content || 'No description',
            viewport: document.querySelector('meta[name="viewport"]')?.content || 'Not specified',
            images: document.images.length,
            links: document.links.length,
            scripts: document.scripts.length,
            pageSize: new Blob([document.documentElement.outerHTML]).size,
            doctype: document.doctype ? document.doctype.name : 'Not specified',
            language: document.documentElement.lang || 'Not specified',
            encoding: document.characterSet || 'Not specified'
        };

        analyzer.innerHTML = `
            <div style="position: relative;">
                <button onclick="this.parentElement.parentElement.remove()" 
                        style="position: absolute; top: -10px; right: -10px; background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center;">
                    ×
                </button>
                
                <div style="margin-bottom: 20px; font-weight: bold; color: #2c3e50; font-size: 18px;">🔍 Page Analysis</div>
            </div>
            
            <div style="text-align: left; margin-bottom: 15px;">
                <div style="margin-bottom: 8px;"><strong>📄 Title:</strong> ${pageInfo.title}</div>
                <div style="margin-bottom: 8px;"><strong>🌐 URL:</strong> <span style="font-size: 12px; word-break: break-all;">${pageInfo.url}</span></div>
                <div style="margin-bottom: 8px;"><strong>📝 Description:</strong> ${pageInfo.description}</div>
                <div style="margin-bottom: 8px;"><strong>🔤 Language:</strong> ${pageInfo.language}</div>
                <div style="margin-bottom: 8px;"><strong>💾 Encoding:</strong> ${pageInfo.encoding}</div>
            </div>

            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 20px;">
                <div style="background: #e8f4fd; padding: 10px; border-radius: 5px;">
                    <div style="font-size: 24px; color: #3498db;">${pageInfo.images}</div>
                    <div style="font-size: 12px;">Images</div>
                </div>
                <div style="background: #e8f6f3; padding: 10px; border-radius: 5px;">
                    <div style="font-size: 24px; color: #27ae60;">${pageInfo.links}</div>
                    <div style="font-size: 12px;">Links</div>
                </div>
                <div style="background: #fef9e7; padding: 10px; border-radius: 5px;">
                    <div style="font-size: 24px; color: #f39c12;">${pageInfo.scripts}</div>
                    <div style="font-size: 12px;">Scripts</div>
                </div>
                <div style="background: #fbeeee; padding: 10px; border-radius: 5px;">
                    <div style="font-size: 24px; color: #e74c3c;">${Math.round(pageInfo.pageSize / 1024)} KB</div>
                    <div style="font-size: 12px;">Page Size</div>
                </div>
            </div>

            <div style="margin-bottom: 15px;">
                <button onclick="showSEOAnalysis()" style="padding: 10px 15px; background: #9b59b6; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 5px; font-size: 12px;">SEO Analysis</button>
                <button onclick="showPerformanceInfo()" style="padding: 10px 15px; background: #e67e22; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 5px; font-size: 12px;">Performance</button>
            </div>
        `;

        // SEO analysis function
        window.showSEOAnalysis = function() {
            const seoIssues = [];
            
            // Check title
            if (!document.title || document.title.length < 10) {
                seoIssues.push('❌ Page title is too short');
            }
            if (document.title.length > 60) {
                seoIssues.push('⚠️ Page title is too long');
            }
            
            // Check description
            const metaDesc = document.querySelector('meta[name="description"]');
            if (!metaDesc) {
                seoIssues.push('❌ Missing meta description');
            } else if (metaDesc.content.length < 50) {
                seoIssues.push('❌ Meta description is too short');
            }
            
            // Check h1 headers
            const h1s = document.querySelectorAll('h1');
            if (h1s.length === 0) {
                seoIssues.push('❌ Missing H1 header');
            } else if (h1s.length > 1) {
                seoIssues.push('⚠️ Too many H1 headers');
            }
            
            // Check images without alt
            const imagesWithoutAlt = Array.from(document.images).filter(img => !img.alt).length;
            if (imagesWithoutAlt > 0) {
                seoIssues.push(`⚠️ ${imagesWithoutAlt} images without alt text`);
            }
            
            alert('SEO Analysis:\n\n' + (seoIssues.length > 0 ? seoIssues.join('\n') : '✅ All basic SEO parameters are good!'));
        };

        // Performance info function
        window.showPerformanceInfo = function() {
            const perfInfo = [
                `🕒 Load time: ${Math.round(performance.timing.loadEventEnd - performance.timing.navigationStart)} ms`,
                `📊 Memory usage: ${performance.memory ? Math.round(performance.memory.usedJSHeapSize / 1048576) + ' MB' : 'N/A'}`,
                `🖼️ Images: ${document.images.length}`,
                `📜 Scripts: ${document.scripts.length}`,
                `🎨 Styles: ${document.styleSheets.length}`
            ];
            
            alert('Performance Information:\n\n' + perfInfo.join('\n'));
        };

        document.body.appendChild(analyzer);
        closeCurrentWidget();
    }

    // ========== MOBFRIENDLY FUNCTION ========== //
    function toggleMobFriendly() {
        isMobFriendlyActive = !isMobFriendlyActive;
        if (isMobFriendlyActive) activateMobFriendly();
        else deactivateMobFriendly();
        closeCurrentWidget();
    }

    function activateMobFriendly() {
        const style = document.createElement('style');
        style.id = 'mobfriendly-styles';
        style.textContent = `
            body {
                font-size: 18px !important;
                line-height: 1.6 !important;
                width: 100% !important;
                margin: 0 !important;
                padding: 5px !important;
                background: white !important;
            }

            * {
                background-image: none !important;
                background-color: white !important;
            }

            table {
                width: 100% !important;
                max-width: 100% !important;
                border-collapse: collapse !important;
                font-size: 18px !important;
            }

            td, th {
                padding: 12px !important;
                word-break: break-word !important;
                white-space: normal !important;
                border: 1px solid #ddd !important;
            }

            td *, th * {
                word-break: break-word !important;
                white-space: normal !important;
                font-size: inherit !important;
            }

            button, input[type="button"] {
                min-height: 44px !important;
                padding: 10px !important;
                font-size: 18px !important;
            }
        `;
        document.head.appendChild(style);
        
        // Additional fix for nested tables
        document.querySelectorAll('table table').forEach(table => {
            table.style.width = '100% !important';
        });
    }

    function deactivateMobFriendly() {
        const style = document.getElementById('mobfriendly-styles');
        if (style) style.remove();
    }

    // ========== ICOGRABBER FUNCTION ========== //
    function showIcoGrabber() {
        const faviconUrl = findFavicon();
        if (faviconUrl) {
            createFaviconBox(faviconUrl);
        }
        closeCurrentWidget();
    }

    function findFavicon() {
        const domain = window.location.origin;
        let faviconUrl = null;

        const links = document.querySelectorAll('link[rel*="icon"]');
        if (links.length > 0) {
            faviconUrl = links[0].href;
            if (!faviconUrl.startsWith('http')) {
                faviconUrl = domain + (faviconUrl.startsWith('/') ? faviconUrl : '/' + faviconUrl);
            }
        } else {
            faviconUrl = domain + '/favicon.ico';
        }

        return faviconUrl;
    }

    function createFaviconBox(faviconUrl) {
        const box = document.createElement('div');
        box.id = 'favicon-box';
        box.style.cssText = `
            position: fixed !important; top: 50% !important; left: 50% !important;
            transform: translate(-50%, -50%) !important; background: rgba(255,255,255,0.95) !important;
            padding: 20px !important; border-radius: 10px !important; z-index: 10002 !important;
            box-shadow: 0 0 20px rgba(0,0,0,0.3) !important; font-family: Arial, sans-serif !important;
            text-align: center !important; backdrop-filter: blur(10px) !important;
            border: 1px solid #ddd !important; min-width: 200px !important;
        `;

        const closeBtn = document.createElement('button');
        closeBtn.textContent = '×';
        closeBtn.style.cssText = `
            position: absolute !important; top: 5px !important; right: 5px !important;
            background: #e74c3c !important; color: white !important; border: none !important;
            border-radius: 50% !important; width: 30px !important; height: 30px !important;
            font-size: 18px !important; cursor: pointer !important;
            display: flex !important; align-items: center !important; justify-content: center !important;
        `;
        closeBtn.onclick = () => box.remove();

        box.innerHTML = `
            <h3 style="margin-top: 0; margin-bottom: 15px; font-size: 16px; color: #333;">Website Favicon</h3>
            <img id="faviconImg" src="${faviconUrl}" style="max-width: 64px; max-height: 64px; display: block; margin: 0 auto 15px; cursor: pointer;">
            <div style="font-size: 12px; color: #666;">To save:<br>long tap or right click</div>
        `;

        box.appendChild(closeBtn);
        document.body.appendChild(box);

        const img = box.querySelector('#faviconImg');
        img.addEventListener('mouseenter', function() {
            this.style.transform = 'scale(1.1)';
            this.style.transition = 'transform 0.2s';
        });
        img.addEventListener('mouseleave', function() {
            this.style.transform = 'scale(1)';
        });
    }

    // ========== ENCODING FUNCTION ========== //
    function showEncoding() {
        createEncodingSelector();
        closeCurrentWidget();
    }

    function createEncodingSelector() {
        const container = document.createElement('div');
        container.id = 'encoding-selector';
        container.style.cssText = `
            position: fixed !important; top: 0 !important; left: 0 !important;
            right: 0 !important; background: white !important; z-index: 10002 !important;
            padding: 10px !important; box-shadow: 0 2px 10px rgba(0,0,0,0.1) !important;
            display: flex !important; align-items: center !important; justify-content: center !important;
        `;

        const select = document.createElement('select');
        select.style.cssText = `
            margin-right: 10px !important; padding: 8px 12px !important;
            border: 1px solid #ccc !important; border-radius: 4px !important;
            font-size: 14px !important;
        `;
        
        const encodings = ['UTF-8', 'windows-1251', 'KOI8-R', 'ISO-8859-5', 'macintosh'];
        encodings.forEach(encoding => {
            const option = document.createElement('option');
            option.value = encoding;
            option.textContent = encoding;
            select.appendChild(option);
        });

        const okButton = document.createElement('button');
        okButton.textContent = 'OK';
        okButton.style.cssText = `
            padding: 8px 16px !important; background: #4285f4 !important;
            color: white !important; border: none !important; border-radius: 4px !important;
            cursor: pointer !important; font-size: 14px !important; margin-right: 5px !important;
        `;
        okButton.addEventListener('click', () => {
            const selectedEncoding = select.value;
            if (selectedEncoding) {
                applyEncoding(selectedEncoding);
            }
        });

        const hideButton = document.createElement('button');
        hideButton.textContent = 'Cancel';
        hideButton.style.cssText = `
            padding: 8px 16px !important; background: #95a5a6 !important;
            color: white !important; border: none !important; border-radius: 4px !important;
            cursor: pointer !important; font-size: 14px !important;
        `;
        hideButton.addEventListener('click', () => {
            container.remove();
        });

        container.appendChild(select);
        container.appendChild(okButton);
        container.appendChild(hideButton);
        document.body.appendChild(container);
    }

    async function applyEncoding(encoding) {
        try {
            const response = await fetch(window.location.href);
            const reader = response.body.getReader();
            const decoder = new TextDecoder(encoding);
            let { value: chunk, done: readerDone } = await reader.read();
            chunk = chunk ? decoder.decode(chunk, { stream: true }) : '';

            while (!readerDone) {
                const { value, done } = await reader.read();
                chunk += value ? decoder.decode(value, { stream: true }) : '';
                readerDone = done;
            }

            document.body.innerHTML = `<pre>${chunk}</pre>`;
        } catch (error) {
            console.error('Error applying encoding:', error);
            alert('Error applying encoding');
        }
    }

    // ========== APK DOWNLOADER FUNCTIONALITY ========== //
    function initApkDownloader() {
        if (!window.location.href.includes('play.google.com/store/apps/details')) return;
        
        function createDropdown() {
            if (document.getElementById('redirect-dropdown')) return;

            const container = document.createElement('div');
            container.id = 'redirect-dropdown-container';
            container.style.cssText = `
                position: fixed !important; top: 10px !important; left: 50% !important;
                transform: translateX(-50%) !important; z-index: 10000 !important;
                background: rgba(255, 255, 255, 0.9) !important; padding: 10px !important;
                border-radius: 5px !important; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2) !important;
            `;

            const dropdown = document.createElement('select');
            dropdown.id = 'redirect-dropdown';
            dropdown.style.cssText = `
                padding: 6px 12px !important; border-radius: 4px !important;
                border: 1px solid #ccc !important; font-size: 12px !important;
            `;

            const headerOption = document.createElement('option');
            headerOption.textContent = 'Download APK';
            headerOption.disabled = true;
            headerOption.selected = true;
            dropdown.appendChild(headerOption);

            const options = [
                { value: 'apkmirror', text: 'APKMirror' },
                { value: 'apkpure', text: 'APKPure' },
                { value: 'aptoide', text: 'Aptoide' },
                { value: 'fdroid', text: 'F-Droid' },
                { value: 'apkdownloader', text: 'APK Downloader' }
            ];

            options.forEach(option => {
                const optionElement = document.createElement('option');
                optionElement.value = option.value;
                optionElement.textContent = option.text;
                dropdown.appendChild(optionElement);
            });

            dropdown.addEventListener('change', async () => {
                const url = new URL(window.location.href);
                const idValue = url.searchParams.get('id');
                if (!idValue) return;

                const selectedOption = dropdown.value;
                let redirectUrl;

                switch (selectedOption) {
                    case 'apkdownloader':
                        try {
                            await navigator.clipboard.writeText(idValue);
                            showModalBeforeRedirect();
                        } catch (err) {
                            console.error('Error copying ID:', err);
                        }
                        return;
                    case 'apkpure':
                        redirectUrl = `https://apkpure.com/apk/${idValue}`;
                        break;
                    case 'apkmirror':
                        redirectUrl = `https://www.apkmirror.com/?s=${idValue}`;
                        break;
                    case 'aptoide':
                        redirectUrl = `https://en.aptoide.com/search?query=${idValue}&type=apps`;
                        break;
                    case 'fdroid':
                        redirectUrl = `https://f-droid.org/packages/${idValue}/`;
                        break;
                }

                window.open(redirectUrl, '_blank');
            });

            container.appendChild(dropdown);
            document.body.appendChild(container);
        }

        function showModalBeforeRedirect() {
            const modal = document.createElement('div');
            modal.style.cssText = `
                position: fixed !important; top: 50% !important; left: 50% !important;
                transform: translate(-50%, -50%) !important; z-index: 10001 !important;
                background: #fff !important; padding: 20px !important; border-radius: 8px !important;
                box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2) !important; text-align: center !important;
                max-width: 300px !important;
            `;

            modal.innerHTML = `
                <p style="margin-bottom: 15px; font-weight: bold;">Package name copied!</p>
                <p style="margin-bottom: 20px;">Click "Got it" to go to APK Downloader.</p>
                <button id="confirm-btn" style="
                    padding: 8px 16px;
                    background: #4285f4;
                    color: white;
                    border: none;
                    border-radius: 4px;
                    cursor: pointer;
                    font-size: 14px;
                ">Got it</button>
            `;

            document.body.appendChild(modal);

            const confirmBtn = modal.querySelector('#confirm-btn');
            confirmBtn.addEventListener('click', () => {
                modal.remove();
                window.open('https://apkgk.com/APK-Downloader', '_blank');
            });
        }

        createDropdown();
        const observer = new MutationObserver(createDropdown);
        observer.observe(document.body, { childList: true, subtree: true });
    }

    // ========== ANTI COPY BLOCK FUNCTIONALITY ========== //
    function initAntiCopyBlock() {
        const blockedEvents = ["contextmenu", "selectstart", "mousedown"];

        function isAllowedElement(el) {
            return (el instanceof HTMLInputElement ||
                    el instanceof HTMLTextAreaElement ||
                    el instanceof HTMLSelectElement ||
                    el.isContentEditable);
        }

        const originalAddEventListener = EventTarget.prototype.addEventListener;
        EventTarget.prototype.addEventListener = function(type, listener, options) {
            if (blockedEvents.includes(type) && !isAllowedElement(this)) {
                return;
            }
            return originalAddEventListener.call(this, type, listener, options);
        };

        function injectCSS() {
            const style = document.createElement('style');
            style.innerHTML = `
                * {
                    -webkit-user-select: text !important;
                    -moz-user-select: text !important;
                    -ms-user-select: text !important;
                    user-select: text !important;
                    touch-action: auto !important;
                }
            `;
            document.documentElement.appendChild(style);
        }

        function removeInlineHandlers() {
            document.querySelectorAll('*').forEach(el => {
                if (isAllowedElement(el)) return;
                el.oncontextmenu = null;
                el.onselectstart = null;
                el.onmousedown = null;
            });
        }

        function observeMutations() {
            const observer = new MutationObserver(removeInlineHandlers);
            observer.observe(document.documentElement, { childList: true, subtree: true });
        }

        function init() {
            injectCSS();
            removeInlineHandlers();
            observeMutations();
        }

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

    // ========== GRAYSCALE TURBO ========== //
    function toggleGrayscale() {
        isGrayscaleActive = !isGrayscaleActive;
        if (isGrayscaleActive) activateGrayscale();
        else deactivateGrayscale();
        closeCurrentWidget();
    }

    function activateGrayscale() {
        const style = document.createElement('style');
        style.id = 'grayscale-styles';
        style.textContent = `
            html { filter: grayscale(100%) !important; -webkit-filter: grayscale(100%) !important; }
            img, video, iframe, canvas, svg { filter: grayscale(100%) !important; -webkit-filter: grayscale(100%) !important; }
        `;
        document.head.appendChild(style);
        grayscaleObserver = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.addedNodes.length) {
                    mutation.addedNodes.forEach((node) => {
                        if (node.nodeType === 1) {
                            if (node.matches('img, video, iframe, canvas, svg')) {
                                node.style.filter = 'grayscale(100%)';
                                node.style.webkitFilter = 'grayscale(100%)';
                            }
                            if (node.hasAttribute('style')) {
                                const style = node.getAttribute('style');
                                if (style && /color|background|border/.test(style)) {
                                    node.style.filter = 'grayscale(100%)';
                                }
                            }
                        }
                    });
                }
            });
        });
        setTimeout(() => {
            document.querySelectorAll('img, video, iframe, canvas, svg').forEach(el => {
                el.style.filter = 'grayscale(100%)';
                el.style.webkitFilter = 'grayscale(100%)';
            });
            grayscaleObserver.observe(document.documentElement, {
                childList: true,
                subtree: true,
                attributes: false,
                characterData: false
            });
        }, 50);
    }

    function deactivateGrayscale() {
        const style = document.getElementById('grayscale-styles');
        if (style) style.remove();
        if (grayscaleObserver) {
            grayscaleObserver.disconnect();
            grayscaleObserver = null;
        }
        document.querySelectorAll('img, video, iframe, canvas, svg').forEach(el => {
            el.style.filter = '';
            el.style.webkitFilter = '';
        });
        document.documentElement.style.filter = '';
        document.documentElement.style.webkitFilter = '';
    }

    // ========== AMOLED WIDGET ========== //
    function toggleAmoledWidget() {
        createWidget(amoledConfig, 2, 'Amoled Tools');
    }

    function executeAmoledTool(action) {
        switch(action) {
            case 'grayscale': toggleGrayscale(); break;
            case 'mobFriendly': toggleMobFriendly(); break;
        }
    }

    // ========== TRANSLATE FUNCTION ========== //
    function showTranslateWidget() {
        createWidget(translateEngines, 2, 'Select Translator');
    }

    function translatePage(engineUrl) {
        const currentUrl = window.location.href;
        let translateUrl;
        
        if (engineUrl.includes('yandex.com')) {
            // Fixed URL for Yandex Translate according to UniTranslator
            translateUrl = `https://translate.yandex.com/translate?url=${encodeURIComponent(currentUrl)}&lang=auto-ru`;
        } else {
            // Google Translate
            translateUrl = engineUrl + encodeURIComponent(currentUrl);
        }
        
        window.open(translateUrl, '_blank');
        closeCurrentWidget();
    }

    // ========== DEV TOOLS FUNCTIONS ========== //
    function toggleDevTools() {
        createWidget(devToolsConfig, 2, 'Dev Tools');
    }

    function executeDevTool(action) {
        switch(action) {
            case 'viewportInfo': showViewportInfo(); break;
            case 'outlineAll': outlineAllElements(); break;
            case 'flexboxDebug': debugFlexbox(); break;
            case 'gridDebug': debugGrid(); break;
            case 'performanceMonitor': showPerformanceMonitor(); break;
            case 'localStorageManager': showLocalStorageManager(); break;
            case 'colorPicker': showColorPicker(); break;
            case 'pageAnalyzer': showPageAnalyzer(); break;
            case 'icoGrabber': showIcoGrabber(); break;
            case 'encoding': showEncoding(); break;
        }
    }

    function showViewportInfo() {
        const info = document.createElement('div');
        info.id = 'viewport-info';
        info.style.cssText = `
            position: fixed; top: 10px; right: 10px; background: rgba(0,0,0,0.9); color: white; padding: 15px;
            border-radius: 8px; font-family: monospace; font-size: 12px; z-index: 10000;
            backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.2);
        `;
        function updateInfo() {
            info.innerHTML = `
                <div style="margin-bottom: 5px; font-weight: bold; color: #3498db;">📐 Viewport Info</div>
                <div>Window: ${window.innerWidth} × ${window.innerHeight}</div>
                <div>Screen: ${window.screen.width} × ${window.screen.height}</div>
                <div>Pixel Ratio: ${window.devicePixelRatio}</div>
                <div>Orientation: ${window.screen.orientation?.type || 'unknown'}</div>
                <button onclick="this.parentElement.remove()" style="margin-top: 8px; padding: 4px 8px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer;">Close</button>
            `;
        }
        window.addEventListener('resize', updateInfo);
        updateInfo();
        document.body.appendChild(info);
        closeCurrentWidget();
    }

    function outlineAllElements() {
        document.querySelectorAll('*').forEach(el => {
            const currentOutline = el.style.outline;
            if (!currentOutline || currentOutline === 'none') el.style.outline = '1px solid #ff0000';
            else el.style.outline = '';
        });
        closeCurrentWidget();
    }

    function debugFlexbox() {
        document.querySelectorAll('*').forEach(el => {
            const display = getComputedStyle(el).display;
            if (display === 'flex') el.style.outline = '2px dashed #3498db';
        });
        closeCurrentWidget();
    }

    function debugGrid() {
        document.querySelectorAll('*').forEach(el => {
            const display = getComputedStyle(el).display;
            if (display === 'grid') el.style.outline = '2px dotted #2ecc71';
        });
        closeCurrentWidget();
    }

    function showPerformanceMonitor() {
        const perf = document.createElement('div');
        perf.id = 'performance-monitor';
        perf.style.cssText = `
            position: fixed; bottom: 10px; right: 10px; background: rgba(0,0,0,0.9); color: #2ecc71; padding: 15px;
            border-radius: 8px; font-family: monospace; font-size: 12px; z-index: 10000;
            backdrop-filter: blur(10px); border: 1px solid rgba(46, 204, 113, 0.3);
        `;
        let frameCount = 0;
        let lastTime = performance.now();
        function updatePerf() {
            frameCount++;
            const currentTime = performance.now();
            if (currentTime - lastTime >= 1000) {
                const fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
                const memory = performance.memory ? `Memory: ${Math.round(performance.memory.usedJSHeapSize / 1048576)}MB` : 'Memory: N/A';
                perf.innerHTML = `
                    <div style="margin-bottom: 5px; font-weight: bold; color: #3498db;">📊 Performance</div>
                    <div>FPS: ${fps}</div>
                    <div>${memory}</div>
                    <button onclick="this.parentElement.remove()" style="margin-top: 8px; padding: 4px 8px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer;">Close</button>
                `;
                frameCount = 0;
                lastTime = currentTime;
            }
            requestAnimationFrame(updatePerf);
        }
        updatePerf();
        document.body.appendChild(perf);
        closeCurrentWidget();
    }

    function showLocalStorageManager() {
        const manager = document.createElement('div');
        manager.id = 'localstorage-manager';
        manager.style.cssText = `
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px;
            border-radius: 10px; z-index: 10000; max-width: 500px; max-height: 400px; overflow-y: auto;
            box-shadow: 0 0 20px rgba(0,0,0,0.3); font-family: Arial, sans-serif;
        `;
        function refreshItems() {
            let html = `
                <div style="margin-bottom: 15px; font-weight: bold; font-size: 16px; color: #2c3e50;">💾 LocalStorage Manager</div>
                <div style="margin-bottom: 10px;">
                    <input type="text" id="newKey" placeholder="Key" style="margin-right: 5px; padding: 5px;">
                    <input type="text" id="newValue" placeholder="Value" style="margin-right: 5px; padding: 5px;">
                    <button onclick="addNewItem()" style="padding: 5px 10px; background: #27ae60; color: white; border: none; border-radius: 4px; cursor: pointer;">Add</button>
                </div>
                <div id="lsItems" style="margin-bottom: 15px;"></div>
                <button onclick="clearAllItems()" style="padding: 8px 15px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer;">Clear All</button>
                <button onclick="this.parentElement.remove()" style="padding: 8px 15px; background: #95a5a6; color: white; border: none; border-radius: 4px; cursor: pointer; margin-left: 10px;">Close</button>
            `;
            manager.innerHTML = html;
            const itemsDiv = manager.querySelector('#lsItems');
            itemsDiv.innerHTML = '';
            if (localStorage.length === 0) {
                itemsDiv.innerHTML = '<div style="color: #7f8c8d; text-align: center;">No items in localStorage</div>';
                return;
            }
            for (let i = 0; i < localStorage.length; i++) {
                const key = localStorage.key(i);
                const value = localStorage.getItem(key);
                const item = document.createElement('div');
                item.style.cssText = 'margin: 5px 0; padding: 8px; background: #f8f9fa; border-radius: 4px;';
                item.innerHTML = `
                    <strong>${key}:</strong>
                    <input value="${value}" style="width: 200px; margin: 0 5px; padding: 3px;">
                    <button onclick="updateItem('${key}')" style="padding: 3px 8px; background: #3498db; color: white; border: none; border-radius: 3px; cursor: pointer;">Update</button>
                    <button onclick="deleteItem('${key}')" style="padding: 3px 8px; background: #e74c3c; color: white; border: none; border-radius: 3px; cursor: pointer;">Delete</button>
                `;
                itemsDiv.appendChild(item);
            }
        }
        window.addNewItem = function() {
            const key = document.getElementById('newKey').value;
            const value = document.getElementById('newValue').value;
            if (key && value) {
                localStorage.setItem(key, value);
                refreshItems();
            }
        };
        window.updateItem = function(key) {
            const newValue = document.querySelector(`input[value="${localStorage.getItem(key)}"]`).value;
            localStorage.setItem(key, newValue);
            refreshItems();
        };
        window.deleteItem = function(key) {
            localStorage.removeItem(key);
            refreshItems();
        };
        window.clearAllItems = function() {
            if (confirm('Clear all localStorage items?')) {
                localStorage.clear();
                refreshItems();
            }
        };
        refreshItems();
        document.body.appendChild(manager);
        closeCurrentWidget();
    }

    function showColorPicker() {
        const picker = document.createElement('div');
        picker.id = 'color-picker';
        picker.style.cssText = `
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px;
            border-radius: 10px; z-index: 10000; box-shadow: 0 0 20px rgba(0,0,0,0.3); font-family: Arial, sans-serif;
        `;
        picker.innerHTML = `
            <div style="margin-bottom: 15px; font-weight: bold; font-size: 16px; color: #2c3e50;">🎨 Color Picker</div>
            <input type="color" id="colorInput" style="width: 100px; height: 100px; margin-bottom: 10px;">
            <div id="colorInfo" style="margin: 10px 0; padding: 10px; background: #f8f9fa; border-radius: 5px; font-family: monospace;"></div>
            <button onclick="this.parentElement.remove()" style="padding: 8px 15px; background: #95a5a6; color: white; border: none; border-radius: 4px; cursor: pointer;">Close</button>
        `;
        const colorInput = picker.querySelector('#colorInput');
        const colorInfo = picker.querySelector('#colorInfo');
        colorInput.addEventListener('input', function() {
            const color = this.value;
            colorInfo.innerHTML = `
                HEX: ${color}<br>
                RGB: ${hexToRgb(color)}<br>
                HSL: ${hexToHsl(color)}
            `;
        });
        colorInput.value = '#3498db';
        colorInput.dispatchEvent(new Event('input'));
        document.body.appendChild(picker);
        closeCurrentWidget();
    }

    function hexToRgb(hex) {
        const r = parseInt(hex.slice(1, 3), 16);
        const g = parseInt(hex.slice(3, 5), 16);
        const b = parseInt(hex.slice(5, 7), 16);
        return `rgb(${r}, ${g}, ${b})`;
    }

    function hexToHsl(hex) {
        const r = parseInt(hex.slice(1, 3), 16) / 255;
        const g = parseInt(hex.slice(3, 5), 16) / 255;
        const b = parseInt(hex.slice(5, 7), 16) / 255;
        const max = Math.max(r, g, b);
        const min = Math.min(r, g, b);
        let h, s, l = (max + min) / 2;
        if (max === min) {
            h = s = 0;
        } else {
            const d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
    }

    // ========== RESPONSIVE TESTER (SIMPLIFIED VERSION) ========== //
    function showResponsiveTester() {
        const devices = [
            { name: 'Phone', width: 375, height: 667 },
            { name: 'Tablet', width: 768, height: 1024 },
            { name: 'Laptop', width: 1024, height: 768 },
            { name: 'Desktop', width: 1440, height: 900 }
        ];

        const tester = document.createElement('div');
        tester.id = 'responsive-tester';
        tester.style.cssText = `
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); 
            background: white; padding: 15px; border-radius: 8px; z-index: 10000; 
            box-shadow: 0 0 20px rgba(0,0,0,0.3); font-family: Arial, sans-serif;
            text-align: center; max-width: 90vw;
        `;
        
        tester.innerHTML = `
            <div style="margin-bottom: 15px; font-weight: bold; color: #2c3e50;">📱 Size Test</div>
            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 15px;">
                ${devices.map(device =>
                    `<button onclick="setViewportSize(${device.width}, ${device.height})" 
                      style="padding: 10px 5px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;">
                      ${device.name}<br><small>${device.width}×${device.height}</small>
                    </button>`
                ).join('')}
            </div>
            <div style="font-size: 11px; color: #666; margin-bottom: 10px;">
                Current: ${window.innerWidth} × ${window.innerHeight}
            </div>
            <button onclick="resetViewport()" style="padding: 8px 15px; background: #27ae60; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 5px;">Reset</button>
            <button onclick="this.parentElement.remove()" style="padding: 8px 15px; background: #95a5a6; color: white; border: none; border-radius: 4px; cursor: pointer;">Close</button>
        `;

        window.setViewportSize = function(width, height) {
            // Simply resize window
            window.resizeTo(width, height);
            // Update current size display
            const sizeInfo = tester.querySelector('div:last-child');
            if (sizeInfo) {
                sizeInfo.textContent = `Current: ${width} × ${height}`;
            }
        };

        window.resetViewport = function() {
            window.resizeTo(1200, 800);
            const sizeInfo = tester.querySelector('div:last-child');
            if (sizeInfo) {
                sizeInfo.textContent = `Current: 1200 × 800`;
            }
        };

        document.body.appendChild(tester);
        closeCurrentWidget();
    }

    // ========== FTP/WEBDAV WIDGET ========== //
    function initFTPWidget() {
        if (ftpWidget) {
            ftpWidget.style.display = 'block';
            return;
        }
        const defaultConfig = {
            protocols: {
                'ftp': { port: 21, prefix: 'ftp://' },
                'sftp': { port: 22, prefix: 'sftp://' },
                'ftps': { port: 21, prefix: 'ftps://' },
                'webdav': { port: 80, prefix: 'http://' },
                'webdavs': { port: 443, prefix: 'https://' }
            }
        };
        let selectedConnection = null;
        ftpWidget = document.createElement('div');
        ftpWidget.id = 'ftp-connection-widget';
        ftpWidget.innerHTML = `
            <div class="ftp-widget-container">
                <div class="ftp-widget-header">
                    <h3>📁 FTP/WebDAV Connector</h3>
                    <button class="ftp-widget-close">×</button>
                </div>
                <div class="ftp-widget-tabs">
                    <button class="tab-btn active" data-tab="quick-connect">Quick Connect</button>
                    <button class="tab-btn" data-tab="saved-connections">Saved</button>
                </div>
                <div class="ftp-widget-body">
                    <div id="quick-connect" class="tab-content active">
                        <div class="form-group">
                            <label for="ftp-protocol">Server Type:</label>
                            <select id="ftp-protocol">
                                <option value="ftp">FTP</option>
                                <option value="sftp">SFTP</option>
                                <option value="ftps">FTPS</option>
                                <option value="webdav">WebDAV</option>
                                <option value="webdavs">WebDAV Secure</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <label for="ftp-server">Server/IP:</label>
                            <input type="text" id="ftp-server" placeholder="example.com or 192.168.1.1">
                        </div>
                        <div class="form-group">
                            <label for="ftp-port">Port:</label>
                            <input type="number" id="ftp-port" placeholder="Auto">
                        </div>
                        <div class="form-group">
                            <label for="ftp-username">Username:</label>
                            <input type="text" id="ftp-username" placeholder="username">
                        </div>
                        <div class="form-group">
                            <label for="ftp-password">Password:</label>
                            <input type="password" id="ftp-password" placeholder="password">
                        </div>
                        <div class="form-group">
                            <label for="ftp-path">Path:</label>
                            <input type="text" id="ftp-path" placeholder="/optional/path">
                        </div>
                        <div class="form-group">
                            <label for="connection-name">Name (for saving):</label>
                            <input type="text" id="connection-name" placeholder="My Server">
                        </div>
                        <div class="form-group">
                            <label>
                                <input type="checkbox" id="ftp-passive" checked>
                                Passive Mode (FTP)
                            </label>
                        </div>
                        <div class="form-buttons">
                            <button id="ftp-connect" class="connect-btn">Connect</button>
                            <button id="ftp-save" class="save-btn">Save</button>
                            <button id="ftp-reset" class="reset-btn">Reset</button>
                        </div>
                    </div>
                    <div id="saved-connections" class="tab-content">
                        <div class="saved-list" id="saved-connections-list">
                            <div style="text-align: center; color: #666;">No saved connections</div>
                        </div>
                        <div class="selected-connection-info" id="selected-connection-info" style="display: none;">
                            <div class="connection-details">
                                <strong>Selected:</strong> <span id="selected-connection-name"></span>
                                <div class="connection-params" id="selected-connection-params"></div>
                            </div>
                        </div>
                        <div class="form-buttons">
                            <button id="saved-connect" class="connect-btn" disabled>Connect to Selected</button>
                            <button id="saved-load" class="save-btn" disabled>Load to Form</button>
                            <button id="clear-saved" class="reset-btn">Clear All</button>
                        </div>
                    </div>
                    <div class="connection-url">
                        <label>Connection URL:</label>
                        <div id="generated-url" class="url-display">Fill fields to generate URL</div>
                    </div>
                </div>
            </div>
        `;
        const styles = `
            <style>
                #ftp-connection-widget {
                    position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #34495e;
                    border-radius: 1vh; z-index: 10001; max-width: 90vw; max-height: 90vh; overflow-y: auto; box-shadow: 0 0 20px rgba(0,0,0,0.5);
                    font-family: Arial, sans-serif;
                }
                .ftp-widget-container { width: 350px; background: #f5f5f5; border: 2px solid #333; border-radius: 8px; max-height: 80vh; overflow-y: auto; }
                .ftp-widget-header { background: #333; color: white; padding: 10px; display: flex; justify-content: space-between; align-items: center; border-radius: 6px 6px 0 0; }
                .ftp-widget-tabs { display: flex; background: #ddd; }
                .tab-btn { flex: 1; padding: 8px; border: none; background: #ccc; cursor: pointer; font-size: 11px; }
                .tab-btn.active { background: #f5f5f5; font-weight: bold; }
                .tab-content { display: none; padding: 15px; }
                .tab-content.active { display: block; }
                .saved-list { max-height: 200px; overflow-y: auto; margin-bottom: 10px; }
                .saved-item { padding: 8px; margin: 5px 0; background: white; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; }
                .saved-item:hover { background: #e9e9e9; }
                .saved-item.selected { background: #d4edda; border-color: #c3e6cb; }
                .saved-item .delete-btn { color: #dc3545; cursor: pointer; padding: 2px 6px; font-weight: bold; }
                .selected-connection-info { background: #e9f7ef; border: 1px solid #c3e6cb; border-radius: 4px; padding: 10px; margin: 10px 0; }
                .connection-details { font-size: 12px; }
                .connection-params { margin-top: 5px; color: #666; }
                .form-group { margin-bottom: 10px; }
                .form-group label { display: block; margin-bottom: 3px; font-weight: bold; font-size: 12px; }
                .form-group input, .form-group select { width: 100%; padding: 6px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
                .form-buttons { display: flex; gap: 8px; margin: 15px 0; }
                .connect-btn { flex: 2; background: #4CAF50; color: white; border: none; padding: 8px; border-radius: 4px; cursor: pointer; }
                .connect-btn:disabled { background: #cccccc; cursor: not-allowed; }
                .save-btn { flex: 1; background: #2196F3; color: white; border: none; padding: 8px; border-radius: 4px; cursor: pointer; }
                .save-btn:disabled { background: #cccccc; cursor: not-allowed; }
                .reset-btn { flex: 1; background: #ff9800; color: white; border: none; padding: 8px; border-radius: 4px; cursor: pointer; }
                .connection-url { margin-top: 10px; padding: 10px; background: #e9e9e9; border-radius: 4px; }
                .url-display { word-break: break-all; font-family: monospace; font-size: 11px; background: white; padding: 5px; border: 1px solid #ddd; margin-top: 5px; }
            </style>
        `;
        document.head.insertAdjacentHTML('beforeend', styles);
        document.body.appendChild(ftpWidget);
        setupFTPWidgetEvents(defaultConfig, selectedConnection);
    }

    function setupFTPWidgetEvents(defaultConfig, selectedConnection) {
        function getSavedConnections() {
            try { return JSON.parse(localStorage.getItem('ftpSavedConnections') || '[]'); }
            catch { return []; }
        }
        function saveConnection(connection) {
            try {
                let saved = getSavedConnections();
                saved = saved.filter(c => c.name !== connection.name);
                saved.unshift(connection);
                saved = saved.slice(0, 20);
                localStorage.setItem('ftpSavedConnections', JSON.stringify(saved));
                return true;
            } catch { return false; }
        }
        function deleteConnection(name) {
            try {
                let saved = getSavedConnections();
                saved = saved.filter(c => c.name !== name);
                localStorage.setItem('ftpSavedConnections', JSON.stringify(saved));
                return true;
            } catch { return false; }
        }
        function generateURL() {
            const protocol = document.getElementById('ftp-protocol').value;
            const server = document.getElementById('ftp-server').value;
            const port = document.getElementById('ftp-port').value;
            const username = document.getElementById('ftp-username').value;
            const password = document.getElementById('ftp-password').value;
            const path = document.getElementById('ftp-path').value;
            if (!server) return '';
            const config = defaultConfig.protocols[protocol];
            let url = config.prefix;
            if (username) {
                url += encodeURIComponent(username);
                if (password) url += ':' + encodeURIComponent(password);
                url += '@';
            }
            url += server;
            if (port && port != config.port) url += ':' + port;
            if (path) url += path.startsWith('/') ? path : '/' + path;
            return url;
        }
        function updateGeneratedURL() {
            const urlDisplay = document.getElementById('generated-url');
            const url = generateURL();
            urlDisplay.textContent = url || 'Fill fields to generate URL';
        }
        function connect() {
            const url = generateURL();
            if (url) {
                window.open(url, '_blank');
                closeFTPWidget();
            } else alert('Please specify at least server for connection');
        }
        function saveConnectionToStorage() {
            const name = document.getElementById('connection-name').value.trim();
            if (!name) { alert('Enter name for saving connection'); return; }
            const connection = {
                name: name,
                protocol: document.getElementById('ftp-protocol').value,
                server: document.getElementById('ftp-server').value,
                port: document.getElementById('ftp-port').value || '',
                username: document.getElementById('ftp-username').value,
                password: document.getElementById('ftp-password').value,
                path: document.getElementById('ftp-path').value
            };
            if (saveConnection(connection)) {
                alert(`Connection "${name}" saved!`);
                loadSavedConnections();
            } else alert('Error saving connection');
        }
        function loadSavedConnections() {
            const saved = getSavedConnections();
            const container = document.getElementById('saved-connections-list');
            if (saved.length === 0) {
                container.innerHTML = '<div style="text-align: center; color: #666;">No saved connections</div>';
                document.getElementById('selected-connection-info').style.display = 'none';
                updateSavedButtonsState(false);
                return;
            }
            container.innerHTML = saved.map(conn => `
                <div class="saved-item" data-config='${JSON.stringify(conn)}'>
                    <div>
                        <strong>${conn.name}</strong><br>
                        <small>${conn.protocol}://${conn.server}${conn.port ? ':' + conn.port : ''}</small>
                    </div>
                    <div class="delete-btn" data-name="${conn.name}">×</div>
                </div>
            `).join('');
            container.querySelectorAll('.saved-item').forEach(item => {
                item.addEventListener('click', function(e) {
                    if (!e.target.classList.contains('delete-btn')) {
                        container.querySelectorAll('.saved-item').forEach(i => i.classList.remove('selected'));
                        this.classList.add('selected');
                        selectedConnection = JSON.parse(this.getAttribute('data-config'));
                        showSelectedConnectionInfo(selectedConnection);
                        updateSavedButtonsState(true);
                    }
                });
            });
            container.querySelectorAll('.delete-btn').forEach(btn => {
                btn.addEventListener('click', function(e) {
                    e.stopPropagation();
                    const name = this.getAttribute('data-name');
                    if (confirm(`Delete connection "${name}"?`)) {
                        deleteConnection(name);
                        loadSavedConnections();
                        selectedConnection = null;
                        updateSavedButtonsState(false);
                    }
                });
            });
            selectedConnection = null;
            updateSavedButtonsState(false);
        }
        function showSelectedConnectionInfo(connection) {
            const infoDiv = document.getElementById('selected-connection-info');
            const nameSpan = document.getElementById('selected-connection-name');
            const paramsDiv = document.getElementById('selected-connection-params');
            nameSpan.textContent = connection.name;
            const params = [];
            if (connection.username) params.push(`Username: ${connection.username}`);
            if (connection.port) params.push(`Port: ${connection.port}`);
            if (connection.path) params.push(`Path: ${connection.path}`);
            paramsDiv.innerHTML = params.join(' | ') || 'No additional parameters';
            infoDiv.style.display = 'block';
        }
        function updateSavedButtonsState(enabled) {
            document.getElementById('saved-connect').disabled = !enabled;
            document.getElementById('saved-load').disabled = !enabled;
        }
        function connectToSelected() {
            if (selectedConnection) {
                const url = generateURLFromConfig(selectedConnection);
                if (url) {
                    window.open(url, '_blank');
                    closeFTPWidget();
                }
            }
        }
        function generateURLFromConfig(config) {
            if (!config.server) return '';
            const protocolConfig = defaultConfig.protocols[config.protocol];
            let url = protocolConfig.prefix;
            if (config.username) {
                url += encodeURIComponent(config.username);
                if (config.password) url += ':' + encodeURIComponent(config.password);
                url += '@';
            }
            url += config.server;
            if (config.port && config.port != protocolConfig.port) url += ':' + config.port;
            if (config.path) url += config.path.startsWith('/') ? config.path : '/' + config.path;
            return url;
        }
        function loadSelectedToForm() {
            if (selectedConnection) {
                loadConnection(selectedConnection);
                switchTab('quick-connect');
            }
        }
        function loadConnection(config) {
            document.getElementById('ftp-protocol').value = config.protocol;
            document.getElementById('ftp-server').value = config.server;
            document.getElementById('ftp-port').value = config.port || '';
            document.getElementById('ftp-username').value = config.username || '';
            document.getElementById('ftp-password').value = config.password || '';
            document.getElementById('ftp-path').value = config.path || '';
            document.getElementById('connection-name').value = config.name || '';
            updateGeneratedURL();
        }
        function switchTab(tabName) {
            document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
            document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
            document.querySelector(`[data-tab="${tabName}"]`).classList.add('active');
            document.getElementById(tabName).classList.add('active');
            if (tabName === 'saved-connections') loadSavedConnections();
        }
        function resetForm() {
            document.getElementById('ftp-protocol').value = 'ftp';
            document.getElementById('ftp-server').value = '';
            document.getElementById('ftp-port').value = '';
            document.getElementById('ftp-username').value = '';
            document.getElementById('ftp-password').value = '';
            document.getElementById('ftp-path').value = '';
            document.getElementById('connection-name').value = '';
            updateGeneratedURL();
        }
        function setupProtocolChange() {
            const protocolSelect = document.getElementById('ftp-protocol');
            const portInput = document.getElementById('ftp-port');
            protocolSelect.addEventListener('change', function() {
                const protocol = this.value;
                const defaultPort = defaultConfig.protocols[protocol].port;
                if (!portInput.value) portInput.placeholder = `Auto (${defaultPort})`;
                updateGeneratedURL();
            });
        }
        document.getElementById('ftp-connect').addEventListener('click', connect);
        document.getElementById('ftp-save').addEventListener('click', saveConnectionToStorage);
        document.getElementById('ftp-reset').addEventListener('click', resetForm);
        document.getElementById('saved-connect').addEventListener('click', connectToSelected);
        document.getElementById('saved-load').addEventListener('click', loadSelectedToForm);
        document.getElementById('clear-saved').addEventListener('click', function() {
            if (confirm('Clear all saved connections?')) {
                localStorage.setItem('ftpSavedConnections', '[]');
                loadSavedConnections();
            }
        });
        document.querySelector('.ftp-widget-close').addEventListener('click', closeFTPWidget);
        const inputs = ['ftp-protocol', 'ftp-server', 'ftp-port', 'ftp-username', 'ftp-password', 'ftp-path'];
        inputs.forEach(id => document.getElementById(id).addEventListener('input', updateGeneratedURL));
        setupTabs();
        setupProtocolChange();
        updateGeneratedURL();
        loadSavedConnections();
    }

    function closeFTPWidget() {
        if (ftpWidget) ftpWidget.style.display = 'none';
        closePanel();
    }

    function toggleFTPWidget() {
        initFTPWidget();
        closePanel();
    }

    // ========== NETWORK MONITOR ========== //
    function toggleNetMonitor() {
        isNetMonitorActive = !isNetMonitorActive;
        if (isNetMonitorActive) initNetMonitor();
        else deactivateNetMonitor();
        updateNetMonitorButton();
        closePanel();
    }

    function initNetMonitor() {
        if (!isNetMonitorActive) {
            deactivateNetMonitor();
            return;
        }
        if (netMonitorWidget) {
            netMonitorWidget.style.display = 'block';
            return;
        }
        let totalDownload = 0;
        let totalUpload = 0;
        let downloadSpeed = 0;
        let uploadSpeed = 0;
        let lastDownload = 0;
        let lastUpload = 0;
        let lastTime = Date.now();
        let trackerRequests = 0;
        const trackerDomains = [
            'google-analytics', 'googlesyndication', 'doubleclick', 'facebook.com/tr',
            'connect.facebook.net', 'analytics', 'metrics', 'tracking', 'telemetry',
            'beacon', 'tagmanager', 'gtm', 'amplitude', 'mixpanel', 'hotjar',
            'piwik', 'matomo', 'yandex.metrika', 'mc.yandex.ru', 'vk.com/rtrg',
            'ads', 'adservice', 'trc.taboola.com'
        ];
        const trackerPaths = [
            '/collect', '/tr', '/track', '/log', '/beacon', '/analytics',
            '/metrics', '/telemetry'
        ];
        netMonitorWidget = document.createElement('div');
        netMonitorWidget.id = 'network-monitor';
        netMonitorWidget.innerHTML = `
            <div style="
                position: fixed; top: 0; left: 0; background: rgba(0, 0, 0, 0.9); color: white; padding: 6px;
                font-family: Arial, sans-serif; font-size: 10px; border-radius: 0 0 6px 0; z-index: 9998;
                backdrop-filter: blur(5px); border-right: 1px solid rgba(255, 255, 255, 0.3);
                border-bottom: 1px solid rgba(255, 255, 255, 0.3); min-width: 130px; user-select: none; line-height: 1.2;
            ">
                <div style="margin-bottom: 3px; font-weight: bold; font-size: 9px; color: #3498db;">NETWORK MONITOR</div>
                <div style="margin-bottom: 2px;">↓: <span id="dl-speed">0 Kb/s</span></div>
                <div style="margin-bottom: 2px;">↑: <span id="ul-speed">0 Kb/s</span></div>
                <div style="margin-bottom: 2px;">Dw: <span id="dl-total">0 Kb</span></div>
                <div style="margin-bottom: 2px;">Up: <span id="ul-total">0 Kb</span></div>
                <div style="color: #ff6b6b; font-weight: bold;">🎯 Trackers: <span id="tracker-count">0</span></div>
            </div>
        `;
        document.body.appendChild(netMonitorWidget);
        function isTrackerRequest(url) {
            if (!url) return false;
            const urlStr = url.toString().toLowerCase();
            for (const domain of trackerDomains) if (urlStr.includes(domain)) return true;
            for (const path of trackerPaths) if (urlStr.includes(path)) return true;
            if (urlStr.includes('google') && (urlStr.includes('/gtm/') || urlStr.includes('/ga/'))) return true;
            return false;
        }
        function getDataSize(data) {
            if (!data) return 0;
            if (typeof data === 'string') return new Blob([data]).size;
            if (data instanceof FormData) return 1024;
            if (data instanceof Blob) return data.size;
            if (data instanceof ArrayBuffer) return data.byteLength;
            return 0;
        }
        const originalFetch = window.fetch;
        window.fetch = function(...args) {
            if (!isNetMonitorActive) return originalFetch.apply(this, args);
            const url = args[0];
            const request = args[1] || {};
            if (isTrackerRequest(url)) {
                trackerRequests++;
                updateTrackerDisplay();
            }
            if (request.body) {
                const size = getDataSize(request.body);
                if (size > 0) totalUpload += size;
            }
            return originalFetch.apply(this, args).then(response => {
                if (isNetMonitorActive) {
                    const contentLength = response.headers.get('content-length');
                    if (contentLength && response.ok) totalDownload += parseInt(contentLength);
                }
                return response;
            });
        };
        const originalOpen = XMLHttpRequest.prototype.open;
        const originalSend = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.open = function(method, url, ...rest) {
            this._url = url;
            return originalOpen.apply(this, [method, url, ...rest]);
        };
        XMLHttpRequest.prototype.send = function(data) {
            if (!isNetMonitorActive) return originalSend.call(this, data);
            if (this._url && isTrackerRequest(this._url)) {
                trackerRequests++;
                updateTrackerDisplay();
            }
            if (data) {
                const size = getDataSize(data);
                if (size > 0) totalUpload += size;
            }
            const originalOnLoad = this.onload;
            this.addEventListener('load', function() {
                if (isNetMonitorActive && this.status >= 200 && this.status < 300) {
                    const contentLength = this.getResponseHeader('content-length');
                    if (contentLength) totalDownload += parseInt(contentLength);
                }
                if (originalOnLoad) originalOnLoad.call(this);
            });
            return originalSend.call(this, data);
        };
        function updateStats() {
            if (!isNetMonitorActive) return;
            const currentTime = Date.now();
            const timeDiff = (currentTime - lastTime) / 1000;
            if (timeDiff > 0) {
                downloadSpeed = Math.round(((totalDownload - lastDownload) / timeDiff) / 1024 * 8);
                uploadSpeed = Math.round(((totalUpload - lastUpload) / timeDiff) / 1024 * 8);
                lastDownload = totalDownload;
                lastUpload = totalUpload;
                lastTime = currentTime;
                updateDisplay();
            }
        }
        function updateDisplay() {
            const dlSpeedElem = document.getElementById('dl-speed');
            const ulSpeedElem = document.getElementById('ul-speed');
            const dlTotalElem = document.getElementById('dl-total');
            const ulTotalElem = document.getElementById('ul-total');
            if (dlSpeedElem && isNetMonitorActive) {
                dlSpeedElem.textContent = `${downloadSpeed} Kb/s`;
                ulSpeedElem.textContent = `${uploadSpeed} Kb/s`;
                dlTotalElem.textContent = `${Math.round(totalDownload / 1024)} Kb`;
                ulTotalElem.textContent = `${Math.round(totalUpload / 1024)} Kb`;
            }
        }
        function updateTrackerDisplay() {
            const trackerElem = document.getElementById('tracker-count');
            if (trackerElem && isNetMonitorActive) trackerElem.textContent = trackerRequests;
        }
        const statsInterval = setInterval(() => {
            if (isNetMonitorActive) updateStats();
            else clearInterval(statsInterval);
        }, 1000);
    }

    function deactivateNetMonitor() {
        if (netMonitorWidget) netMonitorWidget.style.display = 'none';
        isNetMonitorActive = false;
        updateNetMonitorButton();
    }

    function updateNetMonitorButton() {
        const netmonitorBtn = document.querySelector('[data-button="netmonitor"]');
        if (netmonitorBtn) netmonitorBtn.style.background = isNetMonitorActive ? '#27ae60' : buttonBackground;
    }

    // ========== ADBLOCKER FUNCTIONS ========== //
    function toggleAdBlockMode() {
        isAdBlockActive = !isAdBlockActive;
        const adblockIndicator = document.getElementById('adblock-indicator');
        if (adblockIndicator) {
            adblockIndicator.style.background = isAdBlockActive ? '#f44336' : 'transparent';
            adblockIndicator.style.opacity = isAdBlockActive ? '1' : '0';
        }
        if (!isAdBlockActive) removeHighlight();
        closePanel();
    }

    function handleAdBlockSelection(e) {
        const element = document.elementFromPoint(e.touches[0].clientX, e.touches[0].clientY);
        if (!element) return;
        highlightElement(element);
        copyToClipboard(`##${getCssSelector(element)}`);
        
        // FIXED LOGIC: auto disable after selection (like in Ninja AdBlocker)
        setTimeout(() => {
            removeHighlight();
            toggleAdBlockMode(); // Auto reset mode
        }, HIGHLIGHT_DURATION);
    }

    function highlightElement(el) {
        const rect = el.getBoundingClientRect();
        const highlight = document.createElement('div');
        highlight.style.cssText = `
            position: absolute !important; left: ${rect.left + window.scrollX}px !important;
            top: ${rect.top + window.scrollY}px !important; width: ${rect.width}px !important;
            height: ${rect.height}px !important; background: rgba(255,0,0,0.2) !important;
            border: 1px dashed red !important; z-index: 2147483646 !important; pointer-events: none !important;
        `;
        highlight.dataset.adblockHighlight = 'true';
        document.body.appendChild(highlight);
    }

    function getCssSelector(el) {
        const path = [];
        while (el && el !== document.body) {
            let selector = el.tagName.toLowerCase();
            if (el.id) {
                selector += `#${el.id}`;
                path.unshift(selector);
                break;
            } else {
                if (el.className) selector += `.${el.className.toString().trim().replace(/\s+/g, '.')}`;
                path.unshift(selector);
                el = el.parentNode;
            }
        }
        return path.join(' > ');
    }

    function copyToClipboard(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);
    }

    function removeHighlight() {
        document.querySelectorAll('[data-adblock-highlight="true"]').forEach(el => el.remove());
    }

    // ========== ADBLOCKER HANDLERS ========== //
    document.addEventListener('touchstart', (e) => {
        if (isAdBlockActive) {
            adBlockStartX = e.touches[0].clientX;
            adBlockStartY = e.touches[0].clientY;
        }
    }, {passive: true});

    document.addEventListener('touchmove', (e) => {
        if (!isAdBlockActive || !adBlockStartX) return;
        const diffX = Math.abs(e.touches[0].clientX - adBlockStartX);
        if (diffX > SWIPE_THRESHOLD) handleAdBlockSelection(e);
    }, {passive: true});

    // ========== WIDGET FUNCTIONS ========== //
    function createWidget(config, columns, title) {
        closeCurrentWidget();
        const rows = Math.ceil(config.length / columns);
        const widget = document.createElement('div');
        widget.className = 'custom-widget';
        widget.style.cssText = `
            position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
            background: ${panelBackground}; padding: 2vh; border-radius: 1vh; z-index: 10001;
            display: grid; grid-template-columns: repeat(${columns}, 1fr); grid-template-rows: repeat(${rows}, auto);
            gap: 1vh; max-width: 90vw; max-height: 90vh; overflow-y: auto; box-shadow: 0 0 20px rgba(0,0,0,0.5);
        `;
        config.forEach(item => {
            const btn = document.createElement('button');
            btn.style.cssText = `
                display: flex; flex-direction: column; align-items: center; justify-content: center;
                padding: 1.5vh 0.5vw; background: ${buttonBackground}; color: ${textColor}; text-decoration: none;
                border-radius: 0.5vh; font-size: 1.6vmax; text-align: center; cursor: pointer;
                border: none; min-height: 8vh; gap: 0.5vh;
                transition: background 0.3s;
            `;
            
            btn.addEventListener('mouseenter', () => {
                btn.style.background = buttonHoverBackground;
            });
            btn.addEventListener('mouseleave', () => {
                btn.style.background = buttonBackground;
            });

            if (item.icon) {
                const icon = document.createElement('img');
                icon.src = item.icon;
                icon.style.cssText = `width: 3vmax; height: 3vmax; min-width: 3vmax; min-height: 3vmax;`;
                icon.onerror = () => { icon.style.display = 'none'; };
                btn.appendChild(icon);
            }
            const text = document.createElement('span');
            text.textContent = item.text;
            text.style.cssText = `
                font-size: 1.4vmax; white-space: nowrap; overflow: hidden;
                text-overflow: ellipsis; max-width: 100%; color: ${textColor};
            `;
            btn.appendChild(text);
            if (item.url) {
                btn.onclick = () => {
                    if (title === 'Select Translator') translatePage(item.url);
                    else window.open(item.url, '_blank');
                    closeCurrentWidget();
                };
            } else if (item.action) {
                if (title === 'Amoled Tools') btn.onclick = () => executeAmoledTool(item.action);
                else btn.onclick = () => executeDevTool(item.action);
            }
            widget.appendChild(btn);
        });
        const closeBtn = document.createElement('button');
        closeBtn.textContent = '×';
        closeBtn.style.cssText = `
            position: absolute; top: 1vh; right: 1vh; background: #e74c3c; color: white;
            border: none; border-radius: 50%; width: 4vh; height: 4vh; font-size: 2.5vmax;
            cursor: pointer; display: flex; align-items: center; justify-content: center;
        `;
        closeBtn.onclick = closeCurrentWidget;
        widget.appendChild(closeBtn);
        document.body.appendChild(widget);
        currentWidget = widget;
    }

    function closeCurrentWidget() {
        if (currentWidget) {
            currentWidget.remove();
            currentWidget = null;
        }
    }

    // ========== MAIN BUTTONS ========== //
    function createMainButton(config) {
        const btn = document.createElement('div');
        btn.style.cssText = `
            display: flex; flex-direction: column; align-items: center; text-decoration: none;
            color: ${textColor}; width: ${buttonWidth}; height: ${buttonHeight}; min-height: ${buttonHeight};
            border-radius: 12px; background: ${config.background || buttonBackground}; justify-content: center;
            transition: transform 0.2s, background 0.3s; cursor: pointer; flex-shrink: 0; padding: 0 1vw;
        `;
        
        btn.addEventListener('mouseenter', () => { 
            btn.style.transform = 'scale(1.05)'; 
            btn.style.background = buttonHoverBackground;
        });
        btn.addEventListener('mouseout', () => { 
            btn.style.transform = 'scale(1)'; 
            btn.style.background = config.background || buttonBackground;
        });

        const text = document.createElement('span');
        text.textContent = config.text;
        text.style.cssText = `
            font-size: 1.4vmax; white-space: nowrap; overflow: hidden;
            text-overflow: ellipsis; max-width: 100%; text-align: center; color: ${textColor};
        `;
        btn.appendChild(text);

        // Assign handlers for all buttons
        if (config.text === 'Search') {
            btn.onclick = toggleSearchWidget;
        } else if (config.text === 'Translate') {
            btn.onclick = showTranslateWidget;
        } else if (config.text === 'AdBlock+') {
            btn.onclick = toggleAdBlockMode;
        } else if (config.text === 'Netmonitor') {
            btn.onclick = toggleNetMonitor;
        } else if (config.text === 'Amoled') {
            btn.onclick = toggleAmoledWidget;
        } else if (config.text === 'Favorites') {
            btn.onclick = () => createWidget(favoritesConfig, 3, 'Favorites');
        } else if (config.text === 'AI') {
            btn.onclick = () => createWidget(aiConfig, 2, 'AI');
        } else if (config.text === 'Proxy') {
            btn.onclick = () => createWidget(proxyConfig, 2, 'Proxy');
        } else if (config.text === 'Network') {
            btn.onclick = () => createWidget(networkTools, 3, 'Network Tools');
        } else if (config.text === 'Utilities') {
            btn.onclick = () => createWidget(utilities, 2, 'Utilities');
        } else if (config.text === 'WebRTC p2p Chats') {
            btn.onclick = () => createWidget(webrtcChats, 2, 'WebRTC p2p Chats');
        } else if (config.text === 'FTP/Webdav') {
            btn.onclick = toggleFTPWidget;
        } else if (config.text === 'Files') {
            btn.onclick = openFileDialog;
        } else if (config.text === 'Dev Tools') {
            btn.onclick = toggleDevTools;
        }
        return btn;
    }

    // ========== SEARCH WIDGET ========== //
    function toggleSearchWidget() {
        if (!searchWidget) createSearchWidget();
        if (searchWidgetVisible) {
            searchWidget.style.transform = 'translateY(100%)';
            searchWidgetVisible = false;
        } else {
            searchWidget.style.transform = 'translateY(0)';
            searchWidgetVisible = true;
            // Focus input after opening
            setTimeout(() => {
                const iframe = searchWidget.querySelector('iframe');
                if (iframe && iframe.contentWindow) {
                    try {
                        iframe.contentWindow.document.getElementById('searchInput')?.focus();
                    } catch (e) {
                        console.log('Cannot focus search input:', e);
                    }
                }
            }, 300);
        }
        closePanel();
    }

    function createSearchWidget() {
        if (searchWidget) return;
        
        const widgetHTML = `
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; background: transparent; font-family: Arial, sans-serif; }
        .widget-container { padding: 15px; background: white; border-top: 1px solid #ccc; box-shadow: 0 -2px 10px rgba(0,0,0,0.1); width: 100%; box-sizing: border-box; height: 100%; overflow-y: auto; }
        .engine-selector { display: flex; margin-bottom: 15px; flex-wrap: wrap; gap: 12px; justify-content: center; }
        .engine-option { display: flex; flex-direction: column; align-items: center; cursor: pointer; padding: 8px; border-radius: 8px; transition: background 0.2s; min-width: 60px; }
        .engine-option:hover { background: #f0f0f0; }
        .engine-option input { display: none; }
        .engine-icon { width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: bold; color: white; margin-bottom: 6px; }
        .engine-name { font-size: 11px; color: #666; text-align: center; }
        .engine-option input:checked + .engine-content .engine-icon { box-shadow: 0 0 0 2px #007BFF; }
        
        .search-row { display: flex; flex-direction: column; gap: 10px; width: 100%; }
        #searchInput { padding: 12px; border: 1px solid #ccc; border-radius: 8px; font-size: 16px; width: 100%; box-sizing: border-box; }
        .buttons-row { display: flex; gap: 8px; width: 100%; }
        #searchButton { padding: 12px; background: #007BFF; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; flex: 2; }
        #queryGeneratorButton { padding: 12px; background: #28a745; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px; flex: 1; }
        .close-button { position: absolute; top: 10px; right: 10px; background: #e74c3c; color: white; border: none; border-radius: 50%; width: 30px; height: 30px; font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center; }
        
        .query-generator { margin-top: 15px; padding: 15px; background: #f8f9fa; border-radius: 8px; border: 1px solid #dee2e6; display: none; }
        .query-generator.active { display: block; }
        .generator-row { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
        .form-group { flex: 1; min-width: 200px; }
        .form-group label { display: block; margin-bottom: 5px; font-weight: bold; font-size: 14px; color: #333; }
        .form-group select, .form-group input { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 14px; box-sizing: border-box; }
        .checkbox-group { display: flex; align-items: center; gap: 5px; margin-bottom: 5px; }
        .checkbox-group input { width: auto; }
        .checkbox-group label { margin: 0; font-size: 14px; }
        .generator-result { margin-top: 15px; padding: 10px; background: #e9ecef; border-radius: 4px; border: 1px dashed #6c757d; }
        .generator-buttons { display: flex; gap: 8px; margin-top: 10px; }
        #generateQueryButton { padding: 8px 12px; background: #17a2b8; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; flex: 1; }
        #copyQueryButton { padding: 8px 12px; background: #6f42c1; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; flex: 1; display: none; }
        #applyQueryButton { padding: 8px 12px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; flex: 1; display: none; }
    </style>
</head>
<body>
    <div class="widget-container">
        <button class="close-button" id="closeButton" title="Close">×</button>
        <div class="engine-selector">
            <label class="engine-option" title="Google">
                <input type="radio" name="engine" value="google" checked>
                <div class="engine-content">
                    <div class="engine-icon" style="background: #4285F4;">G</div>
                    <div class="engine-name">Google</div>
                </div>
            </label>
            <label class="engine-option" title="Yandex">
                <input type="radio" name="engine" value="yandex">
                <div class="engine-content">
                    <div class="engine-icon" style="background: #FF0000;">Y</div>
                    <div class="engine-name">Yandex</div>
                </div>
            </label>
            <label class="engine-option" title="DuckDuckGo">
                <input type="radio" name="engine" value="duckduckgo">
                <div class="engine-content">
                    <div class="engine-icon" style="background: #DE5833;">D</div>
                    <div class="engine-name">DDG</div>
                </div>
            </label>
            <label class="engine-option" title="Perplexity">
                <input type="radio" name="engine" value="perplexity">
                <div class="engine-content">
                    <div class="engine-icon" style="background: #6B7280;">P</div>
                    <div class="engine-name">Perplexity</div>
                </div>
            </label>
        </div>
        <div class="search-row">
            <input type="text" id="searchInput" placeholder="Enter query or URL">
            <div class="buttons-row">
                <button id="searchButton">Search</button>
                <button id="queryGeneratorButton">⚙️</button>
            </div>
        </div>
        
        <div class="query-generator" id="queryGenerator">
            <h3 style="margin: 0 0 10px 0; font-size: 16px; color: #333;">Search Query Generator</h3>
            
            <div class="generator-row">
                <div class="form-group">
                    <label for="generatorEngine">Search Engine:</label>
                    <select id="generatorEngine">
                        <option value="google">Google</option>
                        <option value="yandex">Yandex</option>
                        <option value="duckduckgo">DuckDuckGo</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="searchRegion">Search Region:</label>
                    <select id="searchRegion">
                        <option value="">Any region</option>
                        <option value="ru">Russia</option>
                        <option value="ua">Ukraine</option>
                        <option value="by">Belarus</option>
                        <option value="kz">Kazakhstan</option>
                        <option value="us">USA</option>
                        <option value="de">Germany</option>
                        <option value="fr">France</option>
                        <option value="gb">UK</option>
                    </select>
                </div>
            </div>
            
            <div class="form-group">
                <label>Result Language:</label>
                <div class="checkbox-group">
                    <input type="checkbox" id="langRu" value="ru" checked>
                    <label for="langRu">Russian</label>
                </div>
                <div class="checkbox-group">
                    <input type="checkbox" id="langEn" value="en">
                    <label for="langEn">English</label>
                </div>
                <div class="checkbox-group">
                    <input type="checkbox" id="langUa" value="uk">
                    <label for="langUa">Ukrainian</label>
                </div>
            </div>
            
            <div class="form-group">
                <label for="whiteList">Whitelist sites:</label>
                <input type="text" id="whiteList" placeholder="example.com, example.org">
                <small style="font-size: 12px; color: #666;">Comma separated, without http://</small>
            </div>
            
            <div class="generator-row">
                <div class="checkbox-group">
                    <input type="checkbox" id="exactMatch">
                    <label for="exactMatch">Exact match (add "")</label>
                </div>
                <div class="checkbox-group">
                    <input type="checkbox" id="excludeDuplicates">
                    <label for="excludeDuplicates">Exclude duplicates</label>
                </div>
            </div>
            
            <div class="generator-result" id="generatorResult" style="display: none;">
                <strong>Generated URL:</strong>
                <div id="generatedUrl" style="word-break: break-all; font-size: 12px; margin-top: 5px; font-family: monospace;"></div>
            </div>
            
            <div class="generator-buttons">
                <button id="generateQueryButton">Generate</button>
                <button id="copyQueryButton">Copy URL</button>
                <button id="applyQueryButton">Apply to Search</button>
            </div>
        </div>
    </div>
    <script>
        const searchInput = document.getElementById('searchInput');
        const searchButton = document.getElementById('searchButton');
        const closeButton = document.getElementById('closeButton');
        const queryGeneratorButton = document.getElementById('queryGeneratorButton');
        const queryGenerator = document.getElementById('queryGenerator');
        
        const generatorEngine = document.getElementById('generatorEngine');
        const searchRegion = document.getElementById('searchRegion');
        const whiteList = document.getElementById('whiteList');
        const exactMatch = document.getElementById('exactMatch');
        const excludeDuplicates = document.getElementById('excludeDuplicates');
        const generateQueryButton = document.getElementById('generateQueryButton');
        const copyQueryButton = document.getElementById('copyQueryButton');
        const applyQueryButton = document.getElementById('applyQueryButton');
        const generatorResult = document.getElementById('generatorResult');
        const generatedUrl = document.getElementById('generatedUrl');
        
        let currentGeneratedUrl = '';
        
        function isDomain(input) { 
            return /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(input); 
        }
        
        function performSearch() {
            const query = searchInput.value.trim();
            if (!query) return;
            
            const engine = document.querySelector('input[name="engine"]:checked').value;
            if (isDomain(query)) {
                window.parent.location.href = query.startsWith('http') ? query : 'https://' + query;
            } else {
                const urls = {
                    google: 'https://www.google.com/search?q=' + encodeURIComponent(query),
                    yandex: 'https://yandex.ru/search/?text=' + encodeURIComponent(query),
                    duckduckgo: 'https://duckduckgo.com/?q=' + encodeURIComponent(query),
                    perplexity: 'https://www.perplexity.ai/search?q=' + encodeURIComponent(query)
                };
                window.parent.location.href = urls[engine];
            }
        }
        
        function toggleQueryGenerator() {
            const selectedEngine = document.querySelector('input[name="engine"]:checked').value;
            
            if (selectedEngine === 'perplexity') {
                alert('Query generator not supported for Perplexity');
                return;
            }
            
            queryGenerator.classList.toggle('active');
            generatorEngine.value = selectedEngine;
        }
        
        function generateSearchQuery() {
            const baseQuery = searchInput.value.trim();
            if (!baseQuery) {
                alert('Enter search query');
                return;
            }
            
            let finalQuery = baseQuery;
            
            if (exactMatch.checked) {
                finalQuery = '"' + finalQuery + '"';
            }
            
            if (whiteList.value.trim()) {
                const sites = whiteList.value.split(',').map(site => site.trim()).filter(site => site);
                if (sites.length > 0) {
                    const siteQuery = sites.map(site => 'site:' + site).join(' OR ');
                    finalQuery = finalQuery + ' (' + siteQuery + ')';
                }
            }
            
            if (excludeDuplicates.checked && generatorEngine.value === 'google') {
                finalQuery += ' -inurl:(dup|duplicate)';
            }
            
            let searchUrl = '';
            const encodedQuery = encodeURIComponent(finalQuery);
            
            switch(generatorEngine.value) {
                case 'google':
                    searchUrl = 'https://www.google.com/search?q=' + encodedQuery;
                    if (searchRegion.value) {
                        searchUrl += '&gl=' + searchRegion.value;
                    }
                    const languages = [];
                    if (document.getElementById('langRu').checked) languages.push('lang_ru');
                    if (document.getElementById('langEn').checked) languages.push('lang_en');
                    if (document.getElementById('langUa').checked) languages.push('lang_uk');
                    if (languages.length > 0) {
                        searchUrl += '&lr=' + languages.join(',');
                    }
                    break;
                    
                case 'yandex':
                    searchUrl = 'https://yandex.ru/search/?text=' + encodedQuery;
                    if (searchRegion.value) {
                        const regions = { ru: 225, ua: 187, by: 149, kz: 159 };
                        if (regions[searchRegion.value]) {
                            searchUrl += '&lr=' + regions[searchRegion.value];
                        }
                    }
                    break;
                    
                case 'duckduckgo':
                    searchUrl = 'https://duckduckgo.com/?q=' + encodedQuery;
                    break;
            }
            
            currentGeneratedUrl = searchUrl;
            generatedUrl.textContent = searchUrl;
            generatorResult.style.display = 'block';
            copyQueryButton.style.display = 'block';
            applyQueryButton.style.display = 'block';
        }
        
        function copyGeneratedUrl() {
            if (!currentGeneratedUrl) return;
            
            navigator.clipboard.writeText(currentGeneratedUrl).then(() => {
                alert('URL copied to clipboard!');
            }).catch(() => {
                const textarea = document.createElement('textarea');
                textarea.value = currentGeneratedUrl;
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);
                alert('URL copied to clipboard!');
            });
        }
        
        function applyGeneratedUrl() {
            if (!currentGeneratedUrl) return;
            window.parent.location.href = currentGeneratedUrl;
        }
        
        searchButton.addEventListener('click', performSearch);
        searchInput.addEventListener('keypress', (e) => { 
            if (e.key === 'Enter') performSearch(); 
        });
        
        queryGeneratorButton.addEventListener('click', toggleQueryGenerator);
        generateQueryButton.addEventListener('click', generateSearchQuery);
        copyQueryButton.addEventListener('click', copyGeneratedUrl);
        applyQueryButton.addEventListener('click', applyGeneratedUrl);
        
        document.querySelectorAll('input[name="engine"]').forEach(radio => {
            radio.addEventListener('change', function() {
                generatorEngine.value = this.value;
                if (this.value === 'perplexity' && queryGenerator.classList.contains('active')) {
                    queryGenerator.classList.remove('active');
                }
            });
        });
        
        generatorEngine.addEventListener('change', function() {
            document.querySelector('input[name="engine"][value="' + this.value + '"]').checked = true;
        });
        
        closeButton.addEventListener('click', () => { 
            window.parent.postMessage({type: 'CLOSE_SEARCH_WIDGET'}, '*'); 
        });
        
        document.addEventListener('DOMContentLoaded', () => { 
            searchInput.focus(); 
        });
        
        document.addEventListener('keydown', (e) => { 
            if (e.key === 'Escape') window.parent.postMessage({type: 'CLOSE_SEARCH_WIDGET'}, '*'); 
        });
    </script>
</body>
</html>`;
        
        searchWidget = document.createElement('div');
        searchWidget.id = 'search-widget-panel';
        searchWidget.style.cssText = `
            position: fixed; 
            bottom: 0; 
            left: 0; 
            width: 100%; 
            background: white;
            border-top: 1px solid #ccc; 
            z-index: 10000; 
            transform: translateY(100%);
            transition: transform 0.3s ease; 
            box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
            max-height: 70vh; 
            overflow: hidden;
        `;
        
        const iframe = document.createElement('iframe');
        iframe.style.cssText = `
            border: none; 
            background: transparent; 
            width: 100%; 
            height: 70vh; 
            min-height: 400px;
        `;
        iframe.srcdoc = widgetHTML;
        
        searchWidget.appendChild(iframe);
        document.body.appendChild(searchWidget);
        
        window.addEventListener('message', (e) => {
            if (e.data.type === 'CLOSE_SEARCH_WIDGET') {
                toggleSearchWidget();
            }
        });
    }

    // ========== FILE DIALOG ========== //
    function openFileDialog() {
        isNetMonitorActive = false;
        deactivateNetMonitor();
        updateNetMonitorButton();
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.onchange = async (e) => {
            const file = e.target.files[0];
            if (!file) return;
            try {
                originalPageContent = document.documentElement.outerHTML;
                const ext = file.name.toLowerCase().split('.').pop();
                if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'].includes(ext)) {
                    const url = await readFileAsDataURL(file);
                    showImage(url);
                }
                else if (['mp3', 'wav', 'ogg'].includes(ext)) {
                    const url = await readFileAsDataURL(file);
                    showAudio(url, file.name);
                }
                else if (['mp4', 'webm'].includes(ext)) {
                    const url = await readFileAsDataURL(file);
                    showVideo(url);
                }
                else if (ext === 'pdf') {
                    const url = await readFileAsDataURL(file);
                    showPDF(url);
                }
                else if (['html', 'htm'].includes(ext)) {
                    const content = await readFileAsText(file);
                    showHTML(content);
                }
                else if (['url', 'webloc'].includes(ext)) {
                    const content = await readFileAsText(file);
                    handleShortcut(content, ext);
                }
                else {
                    const content = await readFileAsText(file);
                    showText(content);
                }
            } catch {}
        };
        fileInput.click();
        closePanel();
    }

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

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

    function createBackButton() {
        const backBtn = document.createElement('button');
        backBtn.textContent = '×';
        backBtn.title = 'Go back';
        backBtn.style.cssText = `
            position: fixed; top: 10px; right: 10px; background: #e74c3c; color: white;
            border: none; border-radius: 50%; width: 40px; height: 40px; font-size: 20px;
            cursor: pointer; z-index: 10000; display: flex; align-items: center; justify-content: center;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
        `;
        backBtn.addEventListener('click', restoreOriginalPage);
        return backBtn;
    }

    function restoreOriginalPage() {
        if (originalPageContent) {
            document.documentElement.innerHTML = originalPageContent;
            setTimeout(init, 100);
        } else window.location.reload();
    }

    function showImage(url) {
        document.body.innerHTML = '';
        document.body.style.cssText = 'margin:0; padding:2vh; background:#f0f0f0; display:flex; justify-content:center; align-items:center; min-height:100vh;';
        const img = document.createElement('img');
        img.src = url;
        img.style.cssText = 'max-width:100%; max-height:100vh;';
        document.body.appendChild(img);
        document.body.appendChild(createBackButton());
    }

    function showAudio(url, name) {
        document.body.innerHTML = '';
        document.body.style.cssText = 'margin:0; background:#2c3e50; min-height:100vh; display:flex; flex-direction:column; justify-content:center; align-items:center;';
        const container = document.createElement('div');
        container.style.cssText = 'text-align:center; color:white; padding:4vh 2vh;';
        const title = document.createElement('h2');
        title.textContent = name;
        title.style.cssText = 'font-size:2.5vmax; margin-bottom:2vh;';
        const audio = document.createElement('audio');
        audio.src = url;
        audio.controls = true;
        audio.autoplay = true;
        audio.style.cssText = 'width:100%; max-width:80vw; margin:2vh 0;';
        container.appendChild(title);
        container.appendChild(audio);
        document.body.appendChild(container);
        document.body.appendChild(createBackButton());
    }

    function showVideo(url) {
        document.body.innerHTML = '';
        document.body.style.cssText = 'margin:0; padding:2vh; background:black; display:flex; justify-content:center; align-items:center; min-height:100vh;';
        const video = document.createElement('video');
        video.src = url;
        video.controls = true;
        video.autoplay = true;
        video.style.cssText = 'max-width:100%; max-height:100vh;';
        document.body.appendChild(video);
        document.body.appendChild(createBackButton());
    }

    function showPDF(url) {
        document.body.innerHTML = '';
        document.body.style.cssText = 'margin:0; background:#f0f0f0;';
        const embed = document.createElement('embed');
        embed.src = url;
        embed.type = 'application/pdf';
        embed.style.cssText = 'width:100%; height:100vh; border:none;';
        document.body.appendChild(embed);
        document.body.appendChild(createBackButton());
    }

    function showHTML(content) {
        document.open();
        document.write(content);
        document.close();
        setTimeout(() => {
            const backBtn = createBackButton();
            document.body.appendChild(backBtn);
        }, 100);
    }

    function showText(content) {
        document.body.innerHTML = '';
        document.body.style.cssText = 'margin:0; background:white; min-height:100vh;';
        const pre = document.createElement('pre');
        pre.textContent = content;
        pre.style.cssText = 'font-size:2vmax; line-height:1.4; white-space:pre-wrap; padding:2vh; margin:0; color:black;';
        document.body.appendChild(pre);
        document.body.appendChild(createBackButton());
    }

    function handleShortcut(content, ext) {
        let url = '';
        if (ext === 'url') {
            const match = content.match(/URL=(.+)/i);
            url = match ? match[1] : '';
        }
        else if (ext === 'webloc') {
            const match = content.match(/<string>(.+?)<\/string>/i);
            url = match ? match[1] : '';
        }
        if (url) window.location.href = url;
    }

    // ========== PANEL MANAGEMENT ========== //
    function togglePanel() {
        const panel = document.getElementById('custom-side-panel');
        if (panel) {
            if (panel.style.left === '0px') closePanel();
            else openPanel();
        }
    }

    function openPanel() {
        const panel = document.getElementById('custom-side-panel');
        if (panel) panel.style.left = '0';
    }

    function closePanel() {
        const panel = document.getElementById('custom-side-panel');
        if (panel) panel.style.left = `-${panelWidth}`;
        closeCurrentWidget();
    }

    document.addEventListener('click', function(e) {
        const panel = document.getElementById('custom-side-panel');
        const toggleButton = document.getElementById('panel-toggle-button');
        if (panel && toggleButton) {
            if (!panel.contains(e.target) && e.target !== toggleButton && !toggleButton.contains(e.target)) closePanel();
        }
    });

    // ========== MAIN INITIALIZATION ========== //
    function init() {
        const oldToggle = document.getElementById('panel-toggle-button');
        if (oldToggle) oldToggle.remove();
        const oldPanel = document.getElementById('custom-side-panel');
        if (oldPanel) oldPanel.remove();
        const oldAdblockIndicator = document.getElementById('adblock-indicator');
        if (oldAdblockIndicator) oldAdblockIndicator.remove();
        const adblockIndicator = document.createElement('div');
        adblockIndicator.id = 'adblock-indicator';
        adblockIndicator.style.cssText = `
            position: fixed !important; bottom: 12px !important; left: 12px !important;
            width: 12px !important; height: 12px !important; border-radius: 50% !important;
            background: transparent !important; z-index: 2147483647 !important;
            border: 1px solid rgba(255,255,255,0.9) !important; pointer-events: none !important;
            opacity: 0 !important; transition: opacity 0.3s !important;
        `;
        document.body.appendChild(adblockIndicator);
        const toggleButton = document.createElement('div');
        toggleButton.id = 'panel-toggle-button';
        toggleButton.style.cssText = `
            position: fixed !important; bottom: 0 !important; left: 0 !important;
            width: 65px !important; height: 65px !important; background: transparent !important;
            border: 2px solid rgba(0,0,0,0.9) !important; z-index: 10000 !important;
            cursor: pointer !important; min-width: 65px !important; min-height: 65px !important;
        `;
        toggleButton.addEventListener('click', togglePanel);
        document.body.appendChild(toggleButton);
        const panel = document.createElement('div');
        panel.id = 'custom-side-panel';
        panel.style.cssText = `
            position: fixed !important; left: -${panelWidth} !important; top: 0 !important;
            width: ${panelWidth} !important; height: 100vh !important; background: ${panelBackground} !important;
            transition: left 0.3s ease !important; z-index: 9999 !important; overflow-y: auto !important;
            box-shadow: 2px 0 10px rgba(0,0,0,0.2) !important;
        `;
        const buttonsContainer = document.createElement('div');
        buttonsContainer.style.cssText = `
            display: flex; flex-direction: column; align-items: center; gap: ${gapSize};
            position: absolute; top: ${topMargin}; bottom: ${bottomMargin}; left: 0.5vw; right: 0.5vw;
            padding: 1vh 0; overflow-y: auto; justify-content: flex-start;
        `;
        const mainButtonsConfig = [
            { text: 'Search' },
            { text: 'Translate' },
            { text: 'AdBlock+' },
            { text: 'Netmonitor' },
            { text: 'Amoled' },
            { type: 'separator' },
            { text: 'Favorites' },
            { text: 'AI' },
            { text: 'Proxy' },
            { text: 'Network' },
            { text: 'Utilities' },
            { text: 'WebRTC p2p Chats' },
            { type: 'separator' },
            { text: 'FTP/Webdav' },
            { text: 'Files' },
            { text: 'Dev Tools' }
        ];
        mainButtonsConfig.forEach(button => {
            if (button.type === 'separator') {
                const separator = document.createElement('div');
                separator.style.cssText = `
                    width: 80%; height: 1px; background: rgba(255,255,255,0.3);
                    margin: 0.5vh 0;
                `;
                buttonsContainer.appendChild(separator);
            } else {
                const btn = createMainButton(button);
                if (button.text === 'Netmonitor') btn.setAttribute('data-button', 'netmonitor');
                buttonsContainer.appendChild(btn);
            }
        });
        panel.appendChild(buttonsContainer);
        document.body.appendChild(panel);

        // Launch background scripts
        initApkDownloader();
        initAntiCopyBlock();
    }

    // ========== SCRIPT LAUNCH ========== //
    init();
})();