Hide Web Elements Pro

Stealth element hider, Shadow DOM UI, persistent freeze, link extractor, time skipper, enhanced reveal, dock button visibility, stable Reveal & Unblock Engine, plus media downloader with preview. Automatic Protection. Now with Anti-Paywall, Auto-Close Modals, Cookie Bypass, and Bulk Filter Lists.

Pada tanggal 20 Agustus 2026. Lihat %(latest_version_link).

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

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

(I already have a user script manager, let me install it!)

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

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

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

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

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

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

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Hide Web Elements Pro
// @version      12.3
// @description  Stealth element hider, Shadow DOM UI, persistent freeze, link extractor, time skipper, enhanced reveal, dock button visibility, stable Reveal & Unblock Engine, plus media downloader with preview. Automatic Protection. Now with Anti-Paywall, Auto-Close Modals, Cookie Bypass, and Bulk Filter Lists.
// @author       KTZ
// @match        *://*/*
// @icon         https://cdn.corenexis.com/f/v9leABxGUbJ.png
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addValueChangeListener
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @grant        unsafeWindow
// @connect      *
// @run-at       document-start
// @license      MIT
// @namespace    https://greasyfork.org/users/1620673
// ==/UserScript==

(function() {
    'use strict';

    // ---------- Safe Storage ----------
    const gv = (key, def) => {
        try {
            if (typeof GM_getValue !== 'undefined') return GM_getValue(key, def);
            const item = localStorage.getItem(key);
            return item !== null ? JSON.parse(item) : def;
        } catch {
            return def;
        }
    };

    let isSyncingStorage = false;
    const sv = (key, val) => {
        try {
            if (typeof GM_setValue !== 'undefined') {
                GM_setValue(key, val);
            } else {
                localStorage.setItem(key, JSON.stringify(val));
            }
        } catch {}

        if (!isSyncingStorage) {
            isSyncingStorage = true;
            try {
                if (typeof syncCache === 'function') syncCache();
                if (typeof requestUpdateStyles === 'function') requestUpdateStyles();
                if (isTop && typeof broadcastState === 'function') broadcastState();
            } finally {
                isSyncingStorage = false;
            }
        }
    };

    const doc = document, win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
    const UI_HOST_ID = 'hider-ui-root', STEPPER_BAR_ID = 'hider-stepper-bar';
    
    let isTop = false;
    try { isTop = (window.self === window.top); } catch { isTop = false; }

    let shadowRoot = null;
    const shadowBy = id => shadowRoot ? shadowRoot.getElementById(id) : null;

    // ---------- Persistent Settings ----------
    let initialMem = gv('hider_freeze_memory', null) || (gv('hider_autono_global', false) ? 'block_all' : 'ask');
    const CACHE = { 
        blockedDomainsList: [], blockedDomainsSet: new Set(), 
        allowedDomainsList: [], allowedDomainsSet: new Set(),
        customRules: [], isFrozen: gv('hider_freeze_global', false), 
        freezeMemory: initialMem, logs: null,
        autoTimeSkipper: gv('hider_auto_time_skipper', false),
        autoScroll: gv('hider_auto_scroll', true),
        enableContextMenu: gv('hider_enable_contextmenu', true),
        autoRemoveBlur: gv('hider_auto_remove_blur', false),
        universalProtect: true,
        // Rule-breaker features
        antiPaywall: gv('hider_anti_paywall', false),
        autoCloseModals: gv('hider_auto_close_modals', false),
        cookieConsentMode: gv('hider_cookie_consent_mode', 'ask'), // 'accept', 'reject', 'ask'
        filterLists: gv('hider_filter_lists', []) // array of {name, selectors: []}
    };

    // ---------- Dock Button Visibility ----------
    const DOCK_BUTTONS = [
        { id: 'btn-select', label: '🎯 Hide' },
        { id: 'btn-scope', label: '🌐 Scope' },
        { id: 'btn-reveal-quick', label: '👁️ Reveal' },
        { id: 'btn-links', label: '🔗 Links' },
        { id: 'btn-skip-30', label: '⏩ +30s' },
        { id: 'btn-freeze', label: '❄️ Freeze' }
    ];

    function getHiddenDockButtons() {
        return gv('hider_hidden_dock_buttons', []);
    }
    function setHiddenDockButtons(arr) {
        sv('hider_hidden_dock_buttons', arr);
    }
    function applyDockButtonVisibility() {
        if (!shadowRoot) return;
        const hidden = new Set(getHiddenDockButtons());
        DOCK_BUTTONS.forEach(btn => {
            const el = shadowRoot.getElementById(btn.id);
            if (el) {
                el.style.setProperty('display', hidden.has(btn.id) ? 'none' : 'flex', 'important');
            }
        });
        const menuBtn = shadowRoot.getElementById('btn-manage');
        if (menuBtn) menuBtn.style.setProperty('display', 'flex', 'important');
    }
    function renderDockButtonOptions() {
        if (!shadowRoot) return;
        const container = shadowRoot.getElementById('dock-buttons-list');
        if (!container) return;
        const hidden = new Set(getHiddenDockButtons());
        container.innerHTML = '';
        DOCK_BUTTONS.forEach(btn => {
            const label = document.createElement('label');
            label.style.cssText = 'font-size:10px!important;color:#cbd5e1!important;display:flex!important;align-items:center!important;gap:6px;cursor:pointer;user-select:none;';
            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.dataset.btnId = btn.id;
            checkbox.checked = !hidden.has(btn.id);
            checkbox.style.cssText = 'accent-color:#38bdf8;cursor:pointer;';
            checkbox.addEventListener('change', function() {
                const id = this.dataset.btnId;
                let hiddenArr = getHiddenDockButtons();
                if (this.checked) {
                    hiddenArr = hiddenArr.filter(h => h !== id);
                } else {
                    if (!hiddenArr.includes(id)) hiddenArr.push(id);
                }
                setHiddenDockButtons(hiddenArr);
                applyDockButtonVisibility();
            });
            label.appendChild(checkbox);
            const span = document.createElement('span');
            span.textContent = btn.label;
            label.appendChild(span);
            container.appendChild(label);
        });
    }

    // ---------- Core Variables ----------
    let isSelecting = false, isFrozen = CACHE.isFrozen, currentScope = 'site', previewElement = null;
    let stepperStack = [], userApprovedNavigation = false, cachedCssString = null, lastUrl = location.href;
    let stepperPos = { x: null, y: null }, isDraggingStepper = false, isDraggingDock = false, logSaveTimer = null;
    let collapseTimer = null, editingRuleId = null, scrollAnimationFrame = null, styleUpdateRAF = null;
    let linkPanelEl = null;
    let linkDisplayMode = 'text';
    let isProtected = false;
    let featuresEnabled = true;
    let CURRENT_DOMAIN = '', CURRENT_URL = '';
    let previewOutsideListener = null;
    let lastHiddenSelector = null; // for undo
    let globalScopeTemp = false;

    // ---------- Cleanup (Memory Leak Prevention) ----------
    const timers = {
        scrollInterval: null,
        blurInterval: null,
        protectionPoller: null,
        logSaveTimer: null,
        collapseTimer: null,
        paywallObserver: null,
        modalObserver: null,
        cookieObserver: null
    };
    const observers = {
        protectionObserver: null,
        blurObserver: null,
        urlChangeObserver: null,
        paywallObserver: null,
        modalObserver: null,
        cookieObserver: null
    };
    const styleElements = {
        scrollStyleEl: null,
        contextMenuStyleEl: null,
        blurGlobalStyle: null
    };

    function dispose() {
        // Clear intervals
        Object.keys(timers).forEach(key => {
            if (timers[key]) {
                clearInterval(timers[key]);
                clearTimeout(timers[key]);
                timers[key] = null;
            }
        });
        // Disconnect observers
        Object.keys(observers).forEach(key => {
            if (observers[key]) {
                observers[key].disconnect();
                observers[key] = null;
            }
        });
        // Remove injected styles
        Object.values(styleElements).forEach(el => {
            if (el && el.parentNode) el.remove();
        });
        // Remove any leftover UI elements
        const host = doc.getElementById(UI_HOST_ID);
        if (host) host.remove();
        // Remove stepper if present
        const stepper = shadowBy(STEPPER_BAR_ID);
        if (stepper) stepper.remove();
        // Remove link panel
        if (linkPanelEl && linkPanelEl.parentNode) linkPanelEl.remove();
        // Remove prompt modals
        const prompt = shadowBy('hider-freeze-prompt');
        if (prompt) prompt.remove();
        // Remove toast
        const toast = doc.getElementById('hider-toast');
        if (toast) toast.remove();
        // Remove dynamic styles
        const dyn = doc.getElementById('hider-dynamic-styles');
        if (dyn) dyn.remove();
    }

    window.addEventListener('beforeunload', dispose);

    // ---------- Context Menu Override (Safe) ----------
    const contextMenuHandler = function(e) {
        if (!CACHE.enableContextMenu) return;
        const path = e.composedPath ? e.composedPath() : [];
        if (path.some(el => el.id === UI_HOST_ID || (el.closest && el.closest('#' + UI_HOST_ID)))) {
            e.stopPropagation();
            return;
        }
    };
    document.addEventListener('contextmenu', contextMenuHandler, true);

    // ---------- Freeze Mode ----------
    const FREEZE_LABELS = {
        'ask': '❓ Ask Every Time', 'block_all': '⛔ Auto-Block All Navigations',
        'allow_same': '🔗 Allow Same Domain Only', 'allow_all': '🟢 Allow All Navigations'
    };

    const resolveUrl = u => {
        if (!u || typeof u !== 'string') return '';
        const trimmed = u.trim();
        if (trimmed === '*') return '*';
        if (!/^[a-zA-Z][a-zA-Z0-9+-.]*:\/\//.test(trimmed)) {
            if (trimmed.startsWith('//')) return 'http:' + trimmed;
            if (!trimmed.startsWith('/') && !trimmed.startsWith('./') && !trimmed.startsWith('../')) {
                return 'http://' + trimmed;
            }
        }
        try { return new URL(trimmed, win.location.href).href; } catch { return trimmed; }
    };

    const cleanUrl = () => CURRENT_URL || (CURRENT_URL = location.origin + location.pathname);
    const cleanDomain = url => {
        try { 
            if (!url) return '';
            if (url === '*') return '*';
            const abs = resolveUrl(url);
            return new URL(abs).hostname.replace(/^www\./, '').toLowerCase(); 
        } catch { 
            return String(url).trim().toLowerCase(); 
        }
    };

    const updateCurrentLocCache = () => {
        CURRENT_URL = location.origin + location.pathname;
        CURRENT_DOMAIN = cleanDomain(location.href);
        updateProtectionFlag();
        applyAllSettings();
    };

    function getParentDomain(url) {
        if (!url) return '';
        try {
            const host = cleanDomain(url);
            if (!host || host === '*') return host;
            const parts = host.split('.');
            if (parts.length <= 2) return host;
            const multiPartTlds = ['co.uk', 'com.au', 'org.uk', 'gov.uk', 'co.jp', 'com.br', 'co.id', 'or.id', 'ac.uk', 'net.au', 'com.tw', 'co.nz', 'com.sg', 'com.mx', 'co.kr', 'com.tr'];
            const lastTwo = parts.slice(-2).join('.');
            return (multiPartTlds.includes(lastTwo) && parts.length > 2) ? parts.slice(-3).join('.') : lastTwo;
        } catch {
            return cleanDomain(url) || '';
        }
    }

    const FEATURE_BLACKLIST = ['facebook.com', 'fb.com', 'facebook'];
    let blacklistToastShown = false;

    function isFeatureBlacklisted() {
        if (!CURRENT_DOMAIN) return false;
        return FEATURE_BLACKLIST.some(domain => 
            CURRENT_DOMAIN.includes(domain) || CURRENT_DOMAIN.endsWith('.' + domain)
        );
    }

    // ============ REVEAL & UNBLOCK ENGINE ============
    function isProtectedPage() {
        try {
            if (win.__cf_chl_opt || win.__cfRLUnblockHandlers || win._cf) return true;
            if (win.turnstile) {
                if (doc.querySelector('.cf-turnstile, #turnstile-wrapper, .turnstile-container, #cf-challenge')) return true;
            }
            const challengeSelectors = [
                '#challenge-running', '#cf-please-wait', '.cf-browser-verification',
                '#cf-content', '#cf-stage', '#cf-challenge', '.cf-challenge',
                '#cf-error-details', '#cf-waiting', '.cf-please-wait',
                '#cf-content-wrapper', '#challenge-form', '.challenge-form', '#cf-intercept'
            ];
            for (const sel of challengeSelectors) {
                if (doc.querySelector(sel)) return true;
            }
            if (doc.querySelector('.ray-id, [data-ray-id], [data-cf-ray]')) return true;
            const title = doc.title || '';
            if (title.includes('Just a moment...') || title.includes('Attention Required!') ||
                title.includes('Security Check') || title.includes('Verify you are human') ||
                title.includes('Checking your browser')) {
                return true;
            }
            const forms = doc.querySelectorAll('form[action*="__cf_chl"], form[action*="cf-challenge"]');
            if (forms.length > 0) return true;
            const scripts = doc.querySelectorAll('script[src*="challenges.cloudflare.com"], script[src*="/cdn-cgi/challenge-platform/"]');
            if (scripts.length > 0) return true;
            if (doc.querySelector('meta[name="cf-options"]')) return true;
        } catch (e) { /* ignore */ }
        return false;
    }

    function updateProtectionFlag() {
        const was = isProtected;
        isProtected = isProtectedPage();
        featuresEnabled = isProtected ? !CACHE.universalProtect : true;
        if (was !== isProtected) {
            applyAllSettings();
            requestUpdateStyles();
        }
    }

    function setupProtectionObserver() {
        if (observers.protectionObserver) return;
        observers.protectionObserver = new MutationObserver(() => {
            const was = isProtected;
            updateProtectionFlag();
            if (was !== isProtected) {
                applyAllSettings();
                requestUpdateStyles();
            }
        });
        observers.protectionObserver.observe(doc.documentElement, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeOldValue: false
        });

        let checks = 0;
        const rapidInterval = setInterval(() => {
            checks++;
            const was = isProtected;
            updateProtectionFlag();
            if (was !== isProtected) {
                applyAllSettings();
                requestUpdateStyles();
            }
            if (checks >= 10) clearInterval(rapidInterval);
        }, 1000);
        timers.protectionPoller = rapidInterval;

        if (!window.__hider_protection_poller) {
            window.__hider_protection_poller = setInterval(() => {
                const was = isProtected;
                updateProtectionFlag();
                if (was !== isProtected) {
                    applyAllSettings();
                    requestUpdateStyles();
                }
            }, 5000);
        }
    }

    // ---------- Scroll Defeater ----------
    function forceEnableScroll() {
        if (!CACHE.autoScroll) return;
        if (isFeatureBlacklisted() || !featuresEnabled) return;
        const html = doc.documentElement, body = doc.body;
        if (!html && !body) return;
        if (!styleElements.scrollStyleEl) {
            styleElements.scrollStyleEl = doc.createElement('style');
            styleElements.scrollStyleEl.id = 'hider-force-scroll-style';
            (doc.head || doc.documentElement)?.appendChild(styleElements.scrollStyleEl);
        }
        styleElements.scrollStyleEl.textContent = `
            html, body {
                overflow: auto !important;
                overflow-x: auto !important;
                overflow-y: auto !important;
                position: static !important;
                height: auto !important;
                max-height: none !important;
                touch-action: auto !important;
                -webkit-overflow-scrolling: touch !important;
            }
        `;
    }

    function checkAndAutoUnblockScroll() {
        if (!CACHE.autoScroll || isFeatureBlacklisted() || !featuresEnabled) {
            stopScrollDefeater();
            return;
        }
        const html = doc.documentElement, body = doc.body;
        if (!html || !body) return;
        try {
            const hStyle = win.getComputedStyle(html), bStyle = win.getComputedStyle(body);
            if (
                hStyle.overflow === 'hidden' || hStyle.overflowY === 'hidden' ||
                bStyle.overflow === 'hidden' || bStyle.overflowY === 'hidden' ||
                bStyle.position === 'fixed' || hStyle.position === 'fixed'
            ) {
                forceEnableScroll();
            }
        } catch {}
    }

    function startScrollDefeater() {
        if (isFeatureBlacklisted() || !featuresEnabled) {
            stopScrollDefeater();
            return;
        }
        if (timers.scrollInterval) clearInterval(timers.scrollInterval);
        if (CACHE.autoScroll) {
            forceEnableScroll();
            timers.scrollInterval = setInterval(checkAndAutoUnblockScroll, 2000);
        }
    }

    function stopScrollDefeater() {
        if (timers.scrollInterval) {
            clearInterval(timers.scrollInterval);
            timers.scrollInterval = null;
        }
        if (styleElements.scrollStyleEl) {
            styleElements.scrollStyleEl.remove();
            styleElements.scrollStyleEl = null;
        }
    }

    // ---------- Context Menu Styles (Safe) ----------
    function updateContextMenuStyles() {
        if (isFeatureBlacklisted() || !featuresEnabled) {
            if (styleElements.contextMenuStyleEl) {
                styleElements.contextMenuStyleEl.remove();
                styleElements.contextMenuStyleEl = null;
            }
            return;
        }
        if (!CACHE.enableContextMenu) {
            if (styleElements.contextMenuStyleEl) {
                styleElements.contextMenuStyleEl.remove();
                styleElements.contextMenuStyleEl = null;
            }
            return;
        }
        if (!styleElements.contextMenuStyleEl) {
            styleElements.contextMenuStyleEl = doc.createElement('style');
            styleElements.contextMenuStyleEl.id = 'hider-contextmenu-style';
            (doc.head || doc.documentElement)?.appendChild(styleElements.contextMenuStyleEl);
        }
        styleElements.contextMenuStyleEl.textContent = `
            * {
                -webkit-touch-callout: default !important;
                -webkit-user-select: text !important;
                user-select: text !important;
            }
        `;
    }

    // ---------- Blur Removal ----------
    function removeBlurFromElements() {
        if (!CACHE.autoRemoveBlur || isFeatureBlacklisted() || !featuresEnabled) {
            stopBlurRemoval();
            return;
        }
        const all = doc.querySelectorAll('*');
        const uiHost = doc.getElementById(UI_HOST_ID);
        for (const el of all) {
            if (el === uiHost || (el.closest && el.closest('#' + UI_HOST_ID))) continue;
            if (el.classList && el.classList.contains('hider-stealth-target')) continue;
            try {
                const style = win.getComputedStyle(el);
                if (style.filter && style.filter.includes('blur')) {
                    el.style.setProperty('filter', 'none', 'important');
                    el.style.setProperty('backdrop-filter', 'none', 'important');
                    el.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
                }
                if (el.style.filter && el.style.filter.includes('blur')) {
                    el.style.setProperty('filter', 'none', 'important');
                }
                if (el.style.backdropFilter && el.style.backdropFilter.includes('blur')) {
                    el.style.setProperty('backdrop-filter', 'none', 'important');
                    el.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
                }
            } catch {}
        }
    }

    function scheduleBlurRemoval() {
        if (isFeatureBlacklisted() || !featuresEnabled) {
            stopBlurRemoval();
            return;
        }
        if (CACHE.autoRemoveBlur && !styleElements.blurGlobalStyle) {
            styleElements.blurGlobalStyle = doc.createElement('style');
            styleElements.blurGlobalStyle.id = 'hider-blur-global-style';
            styleElements.blurGlobalStyle.textContent = `
                *:not(#hider-ui-root):not(#hider-ui-root *) {
                    filter: none !important;
                    backdrop-filter: none !important;
                    -webkit-backdrop-filter: none !important;
                }
            `;
            (doc.head || doc.documentElement)?.appendChild(styleElements.blurGlobalStyle);
        } else if (!CACHE.autoRemoveBlur && styleElements.blurGlobalStyle) {
            styleElements.blurGlobalStyle.remove();
            styleElements.blurGlobalStyle = null;
        }

        if (timers.blurInterval) clearInterval(timers.blurInterval);
        if (CACHE.autoRemoveBlur) {
            removeBlurFromElements();
            timers.blurInterval = setInterval(removeBlurFromElements, 2000);
            if (!observers.blurObserver) {
                observers.blurObserver = new MutationObserver(() => {
                    if (CACHE.autoRemoveBlur) {
                        removeBlurFromElements();
                    }
                });
                observers.blurObserver.observe(doc.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
            }
        } else {
            if (observers.blurObserver) {
                observers.blurObserver.disconnect();
                observers.blurObserver = null;
            }
        }
    }

    function stopBlurRemoval() {
        if (timers.blurInterval) {
            clearInterval(timers.blurInterval);
            timers.blurInterval = null;
        }
        if (observers.blurObserver) {
            observers.blurObserver.disconnect();
            observers.blurObserver = null;
        }
        if (styleElements.blurGlobalStyle) {
            styleElements.blurGlobalStyle.remove();
            styleElements.blurGlobalStyle = null;
        }
    }

    // ---------- SAFE HELPER: Check if element is main content ----------
    function isMainContentElement(el) {
        if (!el) return false;
        // Never hide html or body
        if (el === doc.documentElement || el === doc.body) return true;
        // If element is our UI host, never hide
        if (el.id === UI_HOST_ID || el.closest && el.closest('#' + UI_HOST_ID)) return true;
        // If element contains a lot of text (> 500 characters) and is not an overlay, consider it main content
        const text = el.textContent || '';
        if (text.length > 500) {
            // Check if it's positioned fixed/absolute with high z-index – could be overlay
            const style = win.getComputedStyle(el);
            if (style.position === 'fixed' || style.position === 'absolute') {
                const z = parseInt(style.zIndex, 10);
                if (z > 1000) return false; // high z-index overlay
            }
            return true; // likely main content
        }
        // If it's a structural element (article, main, section) with substantial text
        if (el.matches && el.matches('article, main, section, div[role="main"]')) {
            if (text.length > 100) return true;
        }
        return false;
    }

    // ---------- Rule-Breaker Engines (with safety) ----------
    function setupPaywallBypass() {
        if (observers.paywallObserver) {
            observers.paywallObserver.disconnect();
            observers.paywallObserver = null;
        }
        if (!CACHE.antiPaywall || !featuresEnabled || isFeatureBlacklisted()) return;

        const paywallKeywords = ['adblock', 'paywall', 'premium', 'subscribe', 'whitelist', 'disable adblock', 'ad blocker'];
        const paywallSelectors = [
            '[class*="paywall"]', '[id*="paywall"]', '[class*="adblock"]', '[id*="adblock"]',
            '[class*="premium"]', '[id*="premium"]', '[class*="subscribe"]', '[id*="subscribe"]',
            '[class*="overlay"]', '[id*="overlay"]', '[class*="modal"]', '[id*="modal"]'
        ];

        function removePaywallElement(el) {
            if (!el || el === doc.documentElement || el === doc.body) return;
            if (el.closest && el.closest('#' + UI_HOST_ID)) return;
            // Skip if it's main content
            if (isMainContentElement(el)) return;

            const text = el.textContent.toLowerCase();
            // Check if it matches paywall criteria
            let isPaywall = false;
            if (el.matches && el.matches(paywallSelectors.join(','))) isPaywall = true;
            if (paywallKeywords.some(kw => text.includes(kw))) isPaywall = true;

            if (isPaywall) {
                // Additional check: element should be either fixed/absolute or have high z-index
                const style = win.getComputedStyle(el);
                const pos = style.position;
                const z = parseInt(style.zIndex, 10);
                if (pos === 'fixed' || pos === 'absolute' || z > 100) {
                    try {
                        el.style.setProperty('display', 'none', 'important');
                        el.style.setProperty('visibility', 'hidden', 'important');
                        // Also remove overflow hiding on body/html
                        forceEnableScroll();
                    } catch {}
                }
            }
        }

        function scanAndRemove(node) {
            if (node.nodeType === Node.ELEMENT_NODE) {
                removePaywallElement(node);
                node.querySelectorAll('*').forEach(child => removePaywallElement(child));
            }
        }

        observers.paywallObserver = new MutationObserver(mutations => {
            for (const mutation of mutations) {
                if (mutation.type === 'childList') {
                    mutation.addedNodes.forEach(node => {
                        scanAndRemove(node);
                    });
                }
            }
        });
        observers.paywallObserver.observe(doc.documentElement, { childList: true, subtree: true });

        // Initial scan
        doc.querySelectorAll('*').forEach(removePaywallElement);
        forceEnableScroll();
    }

    function setupModalAutoClose() {
        if (observers.modalObserver) {
            observers.modalObserver.disconnect();
            observers.modalObserver = null;
        }
        if (!CACHE.autoCloseModals || !featuresEnabled || isFeatureBlacklisted()) return;

        const closeKeywords = ['accept', 'close', 'dismiss', 'continue', 'agree', 'ok', 'got it', 'i understand'];
        const modalSelectors = [
            '[role="dialog"]', '[role="alertdialog"]', '.modal', '.overlay', '.popup', '.lightbox',
            '[class*="modal"]', '[id*="modal"]', '[class*="overlay"]', '[id*="overlay"]'
        ];

        function tryCloseModal() {
            const modals = doc.querySelectorAll(modalSelectors.join(','));
            for (const modal of modals) {
                if (modal === doc.body || modal === doc.documentElement) continue;
                if (modal.closest && modal.closest('#' + UI_HOST_ID)) continue;
                const style = win.getComputedStyle(modal);
                if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') continue;
                // Skip if it's main content
                if (isMainContentElement(modal)) continue;

                // Look for buttons inside
                const buttons = modal.querySelectorAll('button, a[role="button"], input[type="button"], input[type="submit"]');
                for (const btn of buttons) {
                    const text = btn.textContent.trim().toLowerCase();
                    if (closeKeywords.some(kw => text.includes(kw))) {
                        if (btn.offsetParent !== null) {
                            try { btn.click(); } catch {}
                            // After click, try to hide modal if still visible
                            setTimeout(() => {
                                if (modal.parentNode && !isMainContentElement(modal)) {
                                    modal.style.setProperty('display', 'none', 'important');
                                }
                            }, 200);
                            return;
                        }
                    }
                }
                // If no button, hide if it's a backdrop/overlay
                if (modal.matches('.overlay, .modal-backdrop, .modal-overlay')) {
                    if (!isMainContentElement(modal)) {
                        modal.style.setProperty('display', 'none', 'important');
                    }
                }
            }
        }

        observers.modalObserver = new MutationObserver(() => {
            tryCloseModal();
        });
        observers.modalObserver.observe(doc.documentElement, { childList: true, subtree: true });

        setTimeout(tryCloseModal, 500);
        setTimeout(tryCloseModal, 1500);
    }

    function setupCookieConsent() {
        if (observers.cookieObserver) {
            observers.cookieObserver.disconnect();
            observers.cookieObserver = null;
        }
        if (CACHE.cookieConsentMode === 'ask' || !featuresEnabled || isFeatureBlacklisted()) return;

        const cookieSelectors = [
            '#cookie-consent', '#cookie-banner', '.cookie-consent', '.cookie-banner',
            '[class*="cookie"]', '[id*="cookie"]', '[aria-label*="cookie"]'
        ];
        const acceptKeywords = ['accept', 'agree', 'allow', 'yes', 'ok', 'got it'];
        const rejectKeywords = ['reject', 'decline', 'no', 'deny'];

        function handleCookieBanner() {
            const banners = doc.querySelectorAll(cookieSelectors.join(','));
            for (const banner of banners) {
                if (banner === doc.body || banner === doc.documentElement) continue;
                if (banner.closest && banner.closest('#' + UI_HOST_ID)) continue;
                const style = win.getComputedStyle(banner);
                if (style.display === 'none' || style.visibility === 'hidden') continue;
                if (isMainContentElement(banner)) continue;

                const buttons = banner.querySelectorAll('button, a[role="button"], input[type="button"]');
                const mode = CACHE.cookieConsentMode;
                let targetTexts = mode === 'accept' ? acceptKeywords : rejectKeywords;
                for (const btn of buttons) {
                    const text = btn.textContent.trim().toLowerCase();
                    if (targetTexts.some(kw => text.includes(kw))) {
                        try { btn.click(); } catch {}
                        return;
                    }
                }
                // Try close button
                const closeBtn = banner.querySelector('[aria-label*="close"], [aria-label*="Close"], .close, .dismiss');
                if (closeBtn) {
                    try { closeBtn.click(); } catch {}
                }
            }
        }

        observers.cookieObserver = new MutationObserver(() => {
            handleCookieBanner();
        });
        observers.cookieObserver.observe(doc.documentElement, { childList: true, subtree: true });

        setTimeout(handleCookieBanner, 500);
        setTimeout(handleCookieBanner, 2000);
    }

    // ---------- Apply all settings ----------
    function applyAllSettings() {
        if (isFeatureBlacklisted() && !blacklistToastShown) {
            showToast('⚠️ Some Reveal features disabled on this domain');
            blacklistToastShown = true;
        }

        if (CACHE.autoScroll) startScrollDefeater();
        else stopScrollDefeater();

        updateContextMenuStyles();

        if (CACHE.autoRemoveBlur) scheduleBlurRemoval();
        else stopBlurRemoval();

        updateProtectionFlag();

        setupPaywallBypass();
        setupModalAutoClose();
        setupCookieConsent();
    }

    // ---------- Sync Cache ----------
    function syncCache() {
        CACHE.blockedDomainsList = gv('hider_blocked_domains', []);
        CACHE.blockedDomainsSet = new Set(CACHE.blockedDomainsList.map(cleanDomain).filter(Boolean));
        CACHE.allowedDomainsList = gv('hider_allowed_domains', []);
        CACHE.allowedDomainsSet = new Set(CACHE.allowedDomainsList.map(cleanDomain).filter(Boolean));
        CACHE.customRules = gv('hider_custom_rules_v4', []);
        CACHE.isFrozen = gv('hider_freeze_global', false);
        isFrozen = CACHE.isFrozen;
        CACHE.freezeMemory = gv('hider_freeze_memory', CACHE.freezeMemory);
        CACHE.autoTimeSkipper = gv('hider_auto_time_skipper', false);
        CACHE.autoScroll = gv('hider_auto_scroll', true);
        CACHE.enableContextMenu = gv('hider_enable_contextmenu', true);
        CACHE.autoRemoveBlur = gv('hider_auto_remove_blur', false);
        CACHE.universalProtect = true;
        CACHE.antiPaywall = gv('hider_anti_paywall', false);
        CACHE.autoCloseModals = gv('hider_auto_close_modals', false);
        CACHE.cookieConsentMode = gv('hider_cookie_consent_mode', 'ask');
        CACHE.filterLists = gv('hider_filter_lists', []);
        if (gv('hider_last_log_clear_day', '') !== new Date().toDateString()) {
            CACHE.logs = []; sv('hider_global_logs', []); sv('hider_last_log_clear_day', new Date().toDateString());
        }
        applyAllSettings();
    }
    syncCache();

    function disableFreezeMode() {
        isFrozen = false; CACHE.isFrozen = false;
        sv('hider_freeze_global', false);
        shadowBy('btn-freeze')?.classList.remove('is-frozen');
        broadcastState();
    }

    // ---------- Stealth Engine (unchanged) ----------
    const styleProxyCache = new WeakMap();
    try {
        const origGetComputedStyle = win.getComputedStyle;
        win.getComputedStyle = function(el, pseudo) {
            const style = origGetComputedStyle.apply(this, arguments);
            if (el && el instanceof Element && el.classList?.contains('hider-stealth-target')) {
                let cachedProxy = styleProxyCache.get(style);
                if (!cachedProxy) {
                    cachedProxy = new Proxy(style, {
                        get(target, prop) {
                            switch(prop) {
                                case 'display': return 'block';
                                case 'visibility': return 'visible';
                                case 'opacity': return '1';
                                case 'pointerEvents': return 'auto';
                                default: 
                                    const val = target[prop];
                                    return typeof val === 'function' ? val.bind(target) : val;
                            }
                        }
                    });
                    styleProxyCache.set(style, cachedProxy);
                }
                return cachedProxy;
            }
            return style;
        };
    } catch {}

    const isSameDomain = u => cleanDomain(u) && cleanDomain(u) === CURRENT_DOMAIN;
    
    const isDomainBlocked = u => {
        if (!u || !CACHE.blockedDomainsSet.size) return false;
        const d = cleanDomain(u), lower = String(u).toLowerCase();
        return d && (CACHE.blockedDomainsSet.has(d) || [...CACHE.blockedDomainsSet].some(b => b !== '*' && (d.endsWith('.' + b) || lower.includes(b))));
    };

    const isDomainAllowed = u => {
        if (!u || !CACHE.allowedDomainsSet.size) return false;
        const d = cleanDomain(u), lower = String(u).toLowerCase();
        return d && (CACHE.allowedDomainsSet.has('*') || CACHE.allowedDomainsSet.has(d) || [...CACHE.allowedDomainsSet].some(a => a !== '*' && (d.endsWith('.' + a) || lower.includes(a))));
    };

    function convertToWildcardSelector(sel) {
        if (!sel || typeof sel !== 'string') return '';
        return sel.replace(/(#|\.)([a-zA-Z0-9_-]+)/g, (m, p, name) => {
            if (name.startsWith('hider-')) return '';
            const base = (name.match(/^([a-zA-Z_-]+?)[0-9a-fA-F_-]{3,}$/)?.[1] || name.replace(/[0-9a-fA-F]{4,}$/, '')).replace(/[-_]+$/, '');
            return base ? (p === '#' ? `[id*="${base}"]` : `[class*="${base}"]`) : '';
        }).replace(/\s*>\s*/g, ' ');
    }

    function logBlockedAttempt(url, triggerType) {
        if (!CACHE.logs) CACHE.logs = gv('hider_global_logs', []);
        CACHE.logs.unshift({ url: url || 'about:blank', time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }), type: triggerType || 'Popup' });
        if (CACHE.logs.length > 50) CACHE.logs.pop();
        if (!timers.logSaveTimer) timers.logSaveTimer = setTimeout(() => { timers.logSaveTimer = null; sv('hider_global_logs', CACHE.logs); }, 1000);
    }

    // ---------- Freeze FX ----------
    function triggerFreezeFx() {
        const fx = doc.createElement('div');
        fx.className = 'hider-freeze-snow-overlay';
        const frag = doc.createDocumentFragment();
        const flakeChars = ['❄', '❅', '❆', '✨', '⚡'];
        for (let i = 0; i < 22; i++) {
            const flake = doc.createElement('div');
            flake.className = 'hider-snow-flake';
            flake.textContent = flakeChars[Math.floor(Math.random() * flakeChars.length)];
            flake.style.cssText = `left:${Math.random() * 98}vw; top:${Math.random() * 60}vh; animation-delay:${Math.random() * 0.35}s; font-size:${14 + Math.random() * 18}px;`;
            frag.appendChild(flake);
        }
        fx.appendChild(frag);
        (doc.body || doc.documentElement)?.appendChild(fx);
        setTimeout(() => fx.remove(), 1450);
    }

    function forceExposeAndPlayVideos() {
        doc.querySelectorAll('video').forEach(v => {
            ['display', 'visibility', 'opacity', 'pointer-events'].forEach(p => v.style.setProperty(p, p === 'display' ? 'block' : p === 'pointer-events' ? 'auto' : '1', 'important'));
            v.play()?.catch?.(() => {});
        });
    }

    function triggerVideoResumeChain() {
        forceExposeAndPlayVideos(); 
        [150, 400, 800].forEach(t => setTimeout(forceExposeAndPlayVideos, t));
        broadcastToFrames(window, { type: 'HIDER_RESUME_VIDEOS' });
    }

    function simulateAdWindowSuccess() {
        try {
            win.dispatchEvent(new Event('blur')); doc.dispatchEvent(new Event('visibilitychange'));
            win.onblur?.();
            setTimeout(() => { win.dispatchEvent(new Event('focus')); win.onfocus?.(); }, 60);
            triggerVideoResumeChain();
        } catch {}
    }

    function createDummyWindow() {
        const dummy = {
            closed: false, focus(){}, blur(){}, close(){ this.closed = true; }, postMessage(){},
            location: { href: 'about:blank', replace(u){ if(isDomainBlocked(u)) logBlockedAttempt(u, 'Blocked Dummy Replace'); }, assign(u){ if(isDomainBlocked(u)) logBlockedAttempt(u, 'Blocked Dummy Assign'); } },
            document: { write(){}, close(){}, body:{} }, opener: win
        };
        return new Proxy(dummy, {
            get: (t, p) => p in t ? t[p] : () => {},
            set: (t, p, v) => { if (p === 'location' && isDomainBlocked(v)) logBlockedAttempt(v, 'Blocked Dummy Location Set'); else t[p] = v; return true; }
        });
    }

    function handleFreezeNavigation(url, triggerType, onConfirm, onDeny) {
        if (isDomainBlocked(url)) {
            logBlockedAttempt(url, triggerType + ' (Auto-Block Domain)');
            onDeny?.(); simulateAdWindowSuccess(); return;
        }
        if (isDomainAllowed(url)) {
            userApprovedNavigation = true; onConfirm?.();
            setTimeout(() => userApprovedNavigation = false, 300); return;
        }
        const mem = CACHE.freezeMemory || 'ask';
        if (mem === 'allow_all') {
            disableFreezeMode(); userApprovedNavigation = true; onConfirm?.();
            setTimeout(() => userApprovedNavigation = false, 300); return;
        }
        if (mem === 'block_all') {
            logBlockedAttempt(url, triggerType + ' (Auto-Block)');
            onDeny?.(); simulateAdWindowSuccess(); return;
        }
        if (mem === 'allow_same' && isSameDomain(url)) {
            const domain = getParentDomain(url) || cleanDomain(url);
            if (domain) executeAddAllowedDomain(domain);
            userApprovedNavigation = true; onConfirm?.();
            setTimeout(() => userApprovedNavigation = false, 300); return;
        }
        showFreezePrompt(url, triggerType, onConfirm, onDeny);
    }

    // ---------- Interceptors ----------
    let interceptorsInstalled = false;

    function installInterceptors() {
        if (interceptorsInstalled) return;
        interceptorsInstalled = true;

        try {
            const lp = win.Location ? win.Location.prototype : Object.getPrototypeOf(win.location);
            if (lp) {
                const origA = lp.assign, origR = lp.replace, hrefDesc = Object.getOwnPropertyDescriptor(lp, 'href');

                const checkAndInterceptNav = (u, origFn, contextThis, triggerName) => {
                    if (!featuresEnabled) {
                        return origFn.call(contextThis, u);
                    }
                    if (isDomainBlocked(u)) {
                        logBlockedAttempt(u, `Blocked ${triggerName}`);
                        showToast(`⛔ Blocked ${triggerName}`); simulateAdWindowSuccess(); return;
                    }
                    if (isFrozen && !userApprovedNavigation) {
                        if (isDomainAllowed(u)) {
                            userApprovedNavigation = true; const res = origFn.call(contextThis, u);
                            setTimeout(() => userApprovedNavigation = false, 300); return res;
                        }
                        handleFreezeNavigation(u, triggerName, () => {
                            userApprovedNavigation = true; origFn.call(contextThis, u);
                            setTimeout(() => userApprovedNavigation = false, 300);
                        }, simulateAdWindowSuccess);
                        return;
                    }
                    return origFn.call(contextThis, u);
                };

                if (origA) lp.assign = function(u) { return checkAndInterceptNav(u, origA, this, 'Redirect (assign)'); };
                if (origR) lp.replace = function(u) { return checkAndInterceptNav(u, origR, this, 'Redirect (replace)'); };
                if (hrefDesc?.set) {
                    try {
                        Object.defineProperty(lp, 'href', {
                            set(u) { checkAndInterceptNav(u, hrefDesc.set, this, 'Redirect (href)'); },
                            get() { return hrefDesc.get.call(this); }
                        });
                    } catch {}
                }
            }

            const origClick = HTMLAnchorElement.prototype.click;
            HTMLAnchorElement.prototype.click = function() {
                if (!featuresEnabled) return origClick.apply(this, arguments);
                if (isDomainBlocked(this.href)) { logBlockedAttempt(this.href, 'Blocked Click'); showToast('⛔ Blocked link click'); simulateAdWindowSuccess(); return; }
                if (isFrozen && !userApprovedNavigation) {
                    if (isDomainAllowed(this.href)) {
                        userApprovedNavigation = true; const res = origClick.apply(this, arguments);
                        setTimeout(() => userApprovedNavigation = false, 300); return res;
                    }
                    handleFreezeNavigation(this.href, 'Anchor Click', () => {
                        userApprovedNavigation = true; origClick.apply(this, arguments);
                        setTimeout(() => userApprovedNavigation = false, 300);
                    }, simulateAdWindowSuccess);
                    return;
                }
                return origClick.apply(this, arguments);
            };

            const origOpen = win.open;
            win.open = function(url, target, features) {
                if (!featuresEnabled) return origOpen.apply(win, arguments);
                if (isDomainBlocked(url)) { logBlockedAttempt(url || 'about:blank', 'Blocked Popup'); simulateAdWindowSuccess(); showToast('⛔ Blocked Popup'); return createDummyWindow(); }
                if (!url || url === 'about:blank') {
                    const realWin = origOpen.apply(win, arguments);
                    return realWin ? new Proxy(realWin, {
                        get: (t, p) => p === 'location' ? new Proxy(t.location, { set: (l, lp, lv) => (lp==='href'||lp==='assign') && isDomainBlocked(lv) ? (logBlockedAttempt(lv, 'Blocked Popup Nav'), showToast('⛔ Blocked popup nav'), t.close(), true) : (l[lp]=lv, true) }) : (typeof t[p]==='function'?t[p].bind(t):t[p]),
                        set: (t, p, v) => p === 'location' && isDomainBlocked(v) ? (logBlockedAttempt(v, 'Blocked Popup Location'), showToast('⛔ Blocked popup nav'), t.close(), true) : (t[p]=v, true)
                    }) : createDummyWindow();
                }
                if (isFrozen && !userApprovedNavigation) { 
                    if (isDomainAllowed(url)) {
                        userApprovedNavigation = true; const res = origOpen.apply(win, arguments);
                        setTimeout(() => userApprovedNavigation = false, 300); return res;
                    }
                    handleFreezeNavigation(url, 'win.open()', () => {
                        userApprovedNavigation = true; origOpen.call(win, url, target, features);
                        setTimeout(() => userApprovedNavigation = false, 300);
                    }, () => {}); 
                    return createDummyWindow(); 
                }
                return origOpen.apply(win, arguments);
            };
        } catch {}
    }

    // ---------- Broadcast / Sync ----------
    function broadcastToFrames(w, msg) { try { for (let i = 0; i < w.frames.length; i++) { w.frames[i].postMessage(msg, '*'); broadcastToFrames(w.frames[i], msg); } } catch {} }
    function broadcastState() { if (isTop) broadcastToFrames(window, { type: 'HIDER_SYNC_STATE', isSelecting, currentScope, isFrozen }); }

    window.addEventListener('message', e => {
        if (!e.data) return;
        if (e.data.type === 'HIDER_REQUEST_STATE' && isTop) broadcastState();
        if (e.data.type === 'HIDER_SYNC_STATE') {
            ({ isSelecting, currentScope, isFrozen } = e.data);
            CACHE.isFrozen = isFrozen;
            syncCache(); requestUpdateStyles();
            shadowBy('btn-select')?.classList.toggle('active', isSelecting);
            shadowBy('btn-scope')?.classList.toggle('active', currentScope === 'link');
            shadowBy('btn-freeze')?.classList.toggle('is-frozen', isFrozen);
            if (!isSelecting) clearSelectionState();
            applyDockButtonVisibility();
        }
        if (e.data.type === 'HIDER_RESUME_VIDEOS') triggerVideoResumeChain();
        if (e.data.type === 'HIDER_SKIP_30') skip30Seconds();
    });

    window.addEventListener('storage', e => {
        if (e.key && e.key.startsWith('hider_')) {
            syncCache(); requestUpdateStyles();
            if (isTop) broadcastState();
            applyDockButtonVisibility();
        }
    });

    if (typeof GM_addValueChangeListener !== 'undefined') {
        ['hider_freeze_global', 'hider_freeze_memory', 'hider_blocked_domains', 'hider_allowed_domains', 'hider_custom_rules_v4', 'hider_auto_time_skipper',
         'hider_auto_scroll', 'hider_enable_contextmenu', 'hider_auto_remove_blur', 'hider_hidden_dock_buttons',
         'hider_anti_paywall', 'hider_auto_close_modals', 'hider_cookie_consent_mode', 'hider_filter_lists'
        ].forEach(key => {
            try { GM_addValueChangeListener(key, () => { syncCache(); requestUpdateStyles(); if (isTop) broadcastState(); applyDockButtonVisibility(); }); } catch {}
        });
    }

    if (!isTop) try { window.top.postMessage({ type: 'HIDER_REQUEST_STATE' }, '*'); } catch {}

    // ---------- Style Update ----------
    function requestUpdateStyles() {
        if (styleUpdateRAF) return;
        styleUpdateRAF = requestAnimationFrame(() => {
            styleUpdateRAF = null;
            updateStyles();
        });
    }

    function updateStyles() {
        let el = doc.getElementById('hider-dynamic-styles');
        if (!el) { el = doc.createElement('style'); el.id = 'hider-dynamic-styles'; (doc.head || doc.documentElement)?.appendChild(el); }
        
        const host = location.hostname;
        const siteRules = gv('hider_site_' + host, []);
        const linkRules = gv('hider_link_' + cleanUrl(), []);
        
        const customActiveRules = (CACHE.customRules || []).filter(r => {
            if (!r?.selector) return false;
            const t = cleanDomain(r.target);
            return t === '*' || t === host || (t && host.endsWith('.' + t));
        }).map(r => r.selector);

        const combined = [...new Set([...siteRules, ...linkRules, ...customActiveRules])].filter(Boolean);
        // Safety: never hide html or body
        const safeCombined = combined.filter(sel => !sel.match(/^(html|body|document)/i));
        const hideCss = (featuresEnabled && safeCombined.length) ? `${safeCombined.join(',')}{opacity:0!important;pointer-events:none!important;position:absolute!important;top:-99999px!important;left:-99999px!important;width:0!important;height:0!important;max-width:0!important;max-height:0!important;overflow:hidden!important;visibility:hidden!important;clip:rect(0,0,0,0)!important}` : '';
        
        const baseAnimationCss = `
        .hider-preview-highlight { outline: none !important; border: 2px solid #38bdf8 !important; background: rgba(56, 189, 248, 0.15) !important; box-shadow: 0 0 24px rgba(56, 189, 248, 0.6), inset 0 0 12px rgba(56, 189, 248, 0.3) !important; transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1) !important; position: relative !important; z-index: 2147483640 !important; cursor: crosshair !important; border-radius: 6px !important; }
        .hider-freeze-snow-overlay { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; pointer-events: none !important; z-index: 2147483647 !important; overflow: hidden !important; background: radial-gradient(circle at center, rgba(56, 189, 248, 0.18) 0%, transparent 70%) !important; animation: hiderSnowOverlayFade 1.4s cubic-bezier(0.16, 1, 0.3, 1) forwards !important; }
        @keyframes hiderSnowOverlayFade { 0% { opacity: 0; backdrop-filter: blur(0px); } 30% { opacity: 1; backdrop-filter: blur(3px); } 80% { opacity: 1; backdrop-filter: blur(3px); } 100% { opacity: 0; backdrop-filter: blur(0px); } }
        .hider-snow-flake { position: absolute !important; color: #e0f2fe !important; user-select: none !important; pointer-events: none !important; opacity: 0.95 !important; animation: hiderSnowFall 1.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards !important; filter: drop-shadow(0 0 8px rgba(56, 189, 248, 0.9)) !important; }
        @keyframes hiderSnowFall { 0% { transform: translateY(-25px) scale(0.5) rotate(0deg); opacity: 0; } 20% { opacity: 1; } 100% { transform: translateY(140px) scale(1.15) rotate(180deg); opacity: 0; } }`;

        const css = baseAnimationCss + '\n' + hideCss;

        if (cachedCssString !== css) { 
            cachedCssString = css; el.textContent = css; 
            if (featuresEnabled) {
                safeCombined.forEach(s => {
                    try { doc.querySelectorAll(s).forEach(targetEl => targetEl.classList.add('hider-stealth-target')); } catch {}
                });
            }
        }

        if (CACHE.autoScroll && featuresEnabled) checkAndAutoUnblockScroll();
    }
    updateStyles();

    // ---------- Selector Helpers ----------
    function safeCSSEscape(str) { return (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') ? CSS.escape(str) : str.replace(/([!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~])/g, '\\$1'); }

    function getExactSelector(el) {
        if (!el || el.nodeType !== 1) return '';
        const path = []; let curr = el;
        while (curr && curr.nodeType === 1 && curr.tagName.toLowerCase() !== 'html') {
            let tag = curr.tagName.toLowerCase();
            if (tag === 'body') { path.unshift('body'); break; }
            if (curr.id && !curr.id.startsWith('hider-') && !/^\d+$/.test(curr.id) && curr.id.length < 18) { path.unshift(`#${safeCSSEscape(curr.id)}`); break; }
            const rawC = typeof curr.className === 'string' ? curr.className : curr.getAttribute('class') || '';
            const classes = rawC.trim().split(/\s+/).filter(c => c.length > 1 && !c.startsWith('hider-') && !/^[a-zA-Z0-9]{10,}$/.test(c) && !/^hover:/i.test(c));
            if (classes.length) { tag += `.${safeCSSEscape(classes[0])}` + (classes[1] ? `.${safeCSSEscape(classes[1])}` : ''); }
            else {
                let idx = 1, sib = curr.previousElementSibling;
                while (sib) { if (sib.tagName === curr.tagName) idx++; sib = sib.previousElementSibling; }
                tag += `:nth-of-type(${idx})`;
            }
            path.unshift(tag); curr = curr.parentElement;
        }
        return path.join(' > ');
    }

    // ---------- Drag Listeners ----------
    function attachDragListeners(barEl, handleEl) {
        if (!handleEl) return;
        let startX, startY, initialX, initialY;

        const onMove = e => {
            if (!isDraggingStepper) return;
            if (e.cancelable) e.preventDefault();
            const p = e.touches ? e.touches[0] : e, maxX = win.innerWidth - barEl.offsetWidth, maxY = win.innerHeight - barEl.offsetHeight;
            stepperPos = { x: Math.max(0, Math.min(maxX, initialX + (p.clientX - startX))), y: Math.max(0, Math.min(maxY, initialY + (p.clientY - startY))) };
            barEl.style.setProperty('left', `${stepperPos.x}px`, 'important'); barEl.style.setProperty('top', `${stepperPos.y}px`, 'important');
            barEl.style.setProperty('right', 'auto', 'important'); barEl.style.setProperty('bottom', 'auto', 'important'); barEl.style.setProperty('transform', 'none', 'important');
        };

        const onEnd = () => {
            if (isDraggingStepper) { isDraggingStepper = false; }
            win.removeEventListener('mousemove', onMove); win.removeEventListener('mouseup', onEnd);
            win.removeEventListener('touchmove', onMove); win.removeEventListener('touchend', onEnd); win.removeEventListener('touchcancel', onEnd);
        };

        const onStart = e => {
            if (e.target.tagName === 'BUTTON') return;
            if (e.cancelable) e.preventDefault();
            isDraggingStepper = true;
            const p = e.touches ? e.touches[0] : e, r = barEl.getBoundingClientRect();
            startX = p.clientX; startY = p.clientY; initialX = r.left; initialY = r.top;
            barEl.style.setProperty('right', 'auto', 'important');
            barEl.style.setProperty('bottom', 'auto', 'important');
            barEl.style.setProperty('transform', 'none', 'important');
            barEl.style.setProperty('margin', '0', 'important');
            barEl.style.setProperty('left', `${initialX}px`, 'important');
            barEl.style.setProperty('top', `${initialY}px`, 'important');
            win.addEventListener('mousemove', onMove, { passive: false }); win.addEventListener('mouseup', onEnd);
            win.addEventListener('touchmove', onMove, { passive: false }); win.addEventListener('touchend', onEnd); win.addEventListener('touchcancel', onEnd);
        };
        handleEl.addEventListener('mousedown', onStart, { passive: false });
        handleEl.addEventListener('touchstart', onStart, { passive: false });
    }

    function clearSelectionState() {
        previewElement?.classList.remove('hider-preview-highlight'); previewElement = null; stepperStack = [];
        const stepper = shadowBy(STEPPER_BAR_ID);
        if (stepper) {
            stepper.remove();
        }
        globalScopeTemp = false;
    }

    function turnOffHideMode() {
        if (isSelecting) {
            isSelecting = false; shadowBy('btn-select')?.classList.remove('active');
            clearSelectionState(); broadcastState();
            showToast('🎯 Selection mode OFF');
        }
        globalScopeTemp = false;
    }

    function closeAllMenus(e, force = false) {
        if (!shadowRoot) return false;
        if (!force) {
            if (isSelecting || isDraggingDock || isDraggingStepper) return false; 
            const active = shadowRoot.activeElement || doc.activeElement;
            if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA')) return false;
            const path = e?.composedPath?.() || [];
            if (path.length > 0 && path.some(el => el.id === UI_HOST_ID || el.id === STEPPER_BAR_ID)) return false;
            if (shadowBy('hider-panel')?.querySelector('.is-editing')) return false;
        }

        const panel = shadowBy('hider-panel'), menu = shadowBy('hider-dock-menu'), mainBtn = shadowBy('btn-toggle-dock'), dockEl = shadowBy('hider-main-dock');
        let closed = false;
        shadowRoot.querySelectorAll('.h-custom-select').forEach(c => c.classList.remove('is-open'));

        if (linkPanelEl && linkPanelEl.classList.contains('is-visible')) {
            linkPanelEl.classList.remove('is-visible');
            setTimeout(() => linkPanelEl.style.display = 'none', 300);
            closed = true;
        }

        if (panel && panel.classList.contains('is-visible')) { 
            panel.classList.remove('is-visible'); 
            setTimeout(()=> { if(!panel.classList.contains('is-visible')) panel.style.display='none'; }, 300); 
            shadowBy('btn-manage')?.classList.remove('active'); 
            closed = true; 
        }
        if (menu && menu.classList.contains('is-open')) {
            menu.classList.remove('is-open'); mainBtn?.classList.remove('expanded'); dockEl?.classList.remove('expanded'); dockEl?.classList.add('manual-hidden');
            if (timers.collapseTimer) clearTimeout(timers.collapseTimer);
            timers.collapseTimer = setTimeout(() => { dockEl?.classList.add('is-collapsed'); timers.collapseTimer = null; }, 1000);
            closed = true;
        }
        return closed;
    }

    // ---------- Stepper UI ----------
    function renderTouchStepperUI() {
        if (!shadowRoot) return;
        let stepper = shadowBy(STEPPER_BAR_ID);
        if (!previewElement) { stepper?.remove(); return; }
        if (!stepper) { 
            stepper = doc.createElement('div'); stepper.id = STEPPER_BAR_ID; 
            shadowRoot.appendChild(stepper); 
        }

        stepper.className = 'h-glass h-stepper-pill';
        if (stepperPos.x !== null && stepperPos.y !== null) {
            stepper.style.setProperty('left', `${stepperPos.x}px`, 'important'); 
            stepper.style.setProperty('top', `${stepperPos.y}px`, 'important');
            stepper.style.setProperty('bottom', 'auto', 'important'); 
            stepper.style.setProperty('right', 'auto', 'important');
            stepper.style.setProperty('transform', 'none', 'important'); 
            stepper.style.setProperty('margin', '0', 'important');
        } else {
            stepper.style.setProperty('left', '50%', 'important');
            stepper.style.setProperty('top', 'auto', 'important');
            stepper.style.setProperty('bottom', '24px', 'important');
            stepper.style.setProperty('right', 'auto', 'important');
            stepper.style.setProperty('transform', 'translateX(-50%)', 'important');
            stepper.style.setProperty('margin', '0', 'important');
        }

        const tag = previewElement.tagName.toLowerCase(), c = typeof previewElement.className === 'string' ? previewElement.className.trim().split(/\s+/)[0] : '';
        const classStr = c && !c.startsWith('hider-') ? `.${c}` : '', idStr = previewElement.id && !previewElement.id.startsWith('hider-') ? `#${previewElement.id}` : '';
        const fullText = `${tag}${idStr}${classStr}`;
        const isLongText = fullText.length > 14;

        stepper.innerHTML = `
            <div id="hider-drag-handle" class="h-drag-dots" title="Drag Selector Bar">⠿</div>
            <div class="h-stepper-row">
                <button id="hider-step-up" class="h-btn-icon" title="Select Parent Element">▲</button>
                <button id="hider-step-down" class="h-btn-icon" title="Select Child Element">▼</button>
            </div>
            <div class="h-tag-badge-box" title="${fullText}">
                <span class="h-tag-badge-text ${isLongText ? 'is-animating' : ''}">${fullText}</span>
            </div>
            <button id="hider-step-confirm" class="h-btn-pill btn-blue">🙈 Hide</button>
            <button id="hider-step-confirm-global" class="h-btn-pill btn-purple" style="background:linear-gradient(135deg,#a855f7,#7e22ce)!important;">🌐 Global</button>
            <button id="hider-step-cancel" class="h-btn-pill btn-gray">✖ Cancel</button>
        `;

        attachDragListeners(stepper, stepper.querySelector('#hider-drag-handle'));

        stepper.querySelector('#hider-step-up').onclick = e => {
            e.stopPropagation(); const p = previewElement.parentElement;
            if (p && p !== doc.body && p !== doc.documentElement && p.id !== UI_HOST_ID) {
                previewElement.classList.remove('hider-preview-highlight'); stepperStack.push(previewElement);
                previewElement = p; previewElement.classList.add('hider-preview-highlight'); renderTouchStepperUI();
            } else showToast('⛰️ Top parent reached');
        };
        stepper.querySelector('#hider-step-down').onclick = e => {
            e.stopPropagation();
            if (stepperStack.length || previewElement.firstElementChild) {
                previewElement.classList.remove('hider-preview-highlight');
                previewElement = stepperStack.length ? stepperStack.pop() : previewElement.firstElementChild;
                previewElement.classList.add('hider-preview-highlight'); renderTouchStepperUI();
            }
        };
        stepper.querySelector('#hider-step-confirm').onclick = e => { e.stopPropagation(); confirmHideSelectedElement(false); };
        stepper.querySelector('#hider-step-confirm-global').onclick = e => { e.stopPropagation(); confirmHideSelectedElement(true); };
        stepper.querySelector('#hider-step-cancel').onclick = e => { 
            e.stopPropagation(); 
            clearSelectionState(); 
            showToast('❌ Selection cancelled');
        };
    }

    function confirmHideSelectedElement(global = false) {
        if (!previewElement) return;
        const el = previewElement;
        el.classList.remove('hider-preview-highlight'); el.classList.add('hider-stealth-target');
        const sel = getExactSelector(el);
        if (sel) {
            // Prevent hiding body or html
            if (sel.match(/^(html|body)/i)) {
                showToast('⚠️ Cannot hide body or html');
                return;
            }
            lastHiddenSelector = sel;
            if (global) {
                const rule = { id: 'rule_' + Date.now(), selector: sel, target: '*' };
                CACHE.customRules.push(rule);
                sv('hider_custom_rules_v4', CACHE.customRules);
                showToast('🌐 Global hide rule added!');
            } else {
                const key = currentScope === 'site' ? 'hider_site_' + location.hostname : 'hider_link_' + cleanUrl();
                const s = gv(key, []); if (!s.includes(sel)) { s.push(sel); sv(key, s); }
                showToast('🙈 Element Hidden!');
            }
        }
        requestUpdateStyles(); clearSelectionState();
    }

    // ---------- Undo Last Hide ----------
    function undoLastHide() {
        if (!lastHiddenSelector) {
            showToast('⚠️ No hidden element to undo');
            return;
        }
        let found = false;
        for (let i = 0; i < CACHE.customRules.length; i++) {
            if (CACHE.customRules[i].selector === lastHiddenSelector) {
                CACHE.customRules.splice(i, 1);
                sv('hider_custom_rules_v4', CACHE.customRules);
                found = true;
                break;
            }
        }
        if (!found) {
            const key = currentScope === 'site' ? 'hider_site_' + location.hostname : 'hider_link_' + cleanUrl();
            let rules = gv(key, []);
            const idx = rules.indexOf(lastHiddenSelector);
            if (idx !== -1) {
                rules.splice(idx, 1);
                sv(key, rules);
                found = true;
            }
        }
        if (found) {
            try {
                doc.querySelectorAll(lastHiddenSelector).forEach(el => el.classList.remove('hider-stealth-target'));
            } catch {}
            requestUpdateStyles();
            showToast('↩️ Undone last hide');
            lastHiddenSelector = null;
        } else {
            showToast('⚠️ Selector not found in rules');
        }
    }

    // ---------- Toast ----------
    function showToast(msg) {
        let targetRoot = shadowRoot;
        if (!targetRoot) targetRoot = doc.body;
        if (!targetRoot) return;

        const existing = targetRoot.querySelector('#hider-toast');
        if (existing) existing.remove();

        const toast = doc.createElement('div');
        toast.id = 'hider-toast';
        toast.className = 'h-glass h-toast';
        toast.textContent = msg;

        Object.assign(toast.style, {
            position: 'fixed',
            bottom: '70px',
            left: '50%',
            transform: 'translateX(-50%) translateY(16px)',
            opacity: '0',
            padding: '6px 16px',
            fontSize: '11px',
            fontWeight: '700',
            zIndex: '2147483647',
            pointerEvents: 'none',
            transition: 'all .3s ease',
            textAlign: 'center',
            borderRadius: '20px',
            border: '1px solid rgba(56,189,248,.5)',
            color: '#e0f2fe',
            background: 'rgba(13,18,30,0.95)',
            backdropFilter: 'blur(12px)',
            WebkitBackdropFilter: 'blur(12px)',
            boxShadow: '0 12px 30px rgba(0,0,0,0.6)',
            fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, sans-serif',
            lineHeight: '1.3',
            maxWidth: '90vw',
            whiteSpace: 'nowrap'
        });

        targetRoot.appendChild(toast);
        requestAnimationFrame(() => {
            toast.style.opacity = '1';
            toast.style.transform = 'translateX(-50%) translateY(0)';
        });

        setTimeout(() => {
            toast.style.opacity = '0';
            toast.style.transform = 'translateX(-50%) translateY(12px)';
            setTimeout(() => {
                if (toast.parentNode) toast.remove();
            }, 400);
        }, 2500);
    }

    // ---------- Clipboard ----------
    function copyToClipboard(text) {
        if (!text) return;
        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(text).then(() => {
                showToast('📋 Copied!');
            }).catch(() => {
                fallbackCopy(text);
            });
        } else {
            fallbackCopy(text);
        }
    }

    function fallbackCopy(text) {
        const textarea = document.createElement('textarea');
        textarea.value = text;
        textarea.style.position = 'fixed';
        textarea.style.opacity = '0';
        textarea.style.left = '-9999px';
        textarea.style.top = '-9999px';
        textarea.style.width = '1px';
        textarea.style.height = '1px';
        document.body.appendChild(textarea);
        textarea.select();
        try {
            document.execCommand('copy');
            showToast('📋 Copied!');
        } catch (err) {
            showToast('❌ Copy failed');
        }
        document.body.removeChild(textarea);
    }

    // ---------- Custom Dropdown ----------
    function setupCustomDropdown(container, initialValue, onChangeCallback) {
        if (!container) return;
        const trigger = container.querySelector('.h-custom-trigger'), textSpan = container.querySelector('.h-custom-value-text'), options = container.querySelectorAll('.h-custom-opt');
        let currentVal = initialValue || 'ask'; textSpan.textContent = FREEZE_LABELS[currentVal] || FREEZE_LABELS['ask'];

        options.forEach(opt => {
            opt.classList.toggle('is-selected', opt.getAttribute('data-val') === currentVal);
            opt.onclick = e => {
                e.stopPropagation(); currentVal = opt.getAttribute('data-val');
                textSpan.textContent = FREEZE_LABELS[currentVal] || opt.textContent.trim();
                options.forEach(o => o.classList.toggle('is-selected', o === opt)); container.classList.remove('is-open'); onChangeCallback?.(currentVal);
            };
        });
        trigger.onclick = e => {
            e.stopPropagation(); const isOpen = container.classList.contains('is-open');
            shadowRoot.querySelectorAll('.h-custom-select').forEach(c => c.classList.remove('is-open'));
            if (!isOpen) container.classList.add('is-open');
        };
    }

    // ---------- Domain Management ----------
    function executeAddBlockDomain(parentDomain, triggerType, onDeny, promptEl) {
        if (parentDomain && !CACHE.blockedDomainsSet.has(parentDomain)) {
            CACHE.blockedDomainsList.push(parentDomain); CACHE.blockedDomainsSet.add(parentDomain);
            sv('hider_blocked_domains', CACHE.blockedDomainsList);
        }
        logBlockedAttempt(parentDomain, triggerType + ' (User Domain Block)'); promptEl?.remove();
        showToast(`🚫 Blocked ${parentDomain}! Managed in Control Panel.`); onDeny?.(); simulateAdWindowSuccess();
    }

    function executeAddAllowedDomain(parentDomain) {
        if (parentDomain && !CACHE.allowedDomainsSet.has(parentDomain)) {
            CACHE.allowedDomainsList.push(parentDomain); CACHE.allowedDomainsSet.add(parentDomain);
            sv('hider_allowed_domains', CACHE.allowedDomainsList);
            if (shadowBy('hider-panel')?.classList.contains('is-visible')) renderList();
        }
    }

    function showFreezePrompt(url, triggerType, onConfirm, onDeny) {
        if (!shadowRoot) return;
        shadowBy('hider-freeze-prompt')?.remove();
        const promptEl = Object.assign(doc.createElement('div'), { id: 'hider-freeze-prompt', className: 'h-glass h-prompt' });
        const displayUrl = url ? (url.length > 38 ? url.substring(0, 35) + '...' : url) : 'another page';
        const parentDomain = getParentDomain(url) || 'unknown domain';

        promptEl.innerHTML = `
            <div style="font-weight:800;color:#38bdf8;font-size:11px!important;text-transform:uppercase!important;letter-spacing:0.5px">❄️ Navigation Intercepted</div>
            <div style="font-size:11px!important;color:#f8fafc!important;font-weight:600">Proceed to page?</div>
            <div class="h-url-box">${displayUrl}</div>
            <div class="h-custom-select" id="hider-modal-custom-dropdown">
                <div class="h-custom-trigger"><span class="h-custom-value-text">${FREEZE_LABELS[CACHE.freezeMemory] || FREEZE_LABELS['ask']}</span><span class="h-custom-arrow">▼</span></div>
                <div class="h-custom-options"><div class="h-custom-opt" data-val="ask">❓ Ask Every Time</div><div class="h-custom-opt" data-val="block_all">⛔ Auto-Block All Navigations</div><div class="h-custom-opt" data-val="allow_same">🔗 Allow Same Domain Only</div><div class="h-custom-opt" data-val="allow_all">🟢 Allow All Navigations</div></div>
            </div>
            <div style="display:flex;gap:6px;width:100%;margin-top:4px"><button id="hider-freeze-yes" class="h-btn-pill btn-green" style="flex:1">Allow Once</button><button id="hider-freeze-no" class="h-btn-pill btn-red" style="flex:1">Deny</button></div>
            <button id="hider-freeze-allow-btn" class="h-btn-pill" style="width:100%;margin-top:4px;background:rgba(16,185,129,0.15)!important;border:1px solid rgba(16,185,129,0.4)!important;color:#34d399!important;">🟢 Always Allow (${parentDomain})</button>
            <button id="hider-freeze-block-btn" class="h-btn-pill" style="width:100%;margin-top:4px;background:rgba(239,68,68,0.15)!important;border:1px solid rgba(239,68,68,0.4)!important;color:#fca5a5!important;">🚫 Always Block (${parentDomain})</button>
        `;

        shadowRoot.appendChild(promptEl); let selectedMem = CACHE.freezeMemory || 'ask';
        setupCustomDropdown(promptEl.querySelector('#hider-modal-custom-dropdown'), selectedMem, v => { selectedMem = v; });

        setTimeout(() => { promptEl.style.opacity = '1'; promptEl.style.transform = 'translateX(-50%) translateY(0)'; }, 10);

        const saveMem = () => { if (selectedMem !== CACHE.freezeMemory) { CACHE.freezeMemory = selectedMem; sv('hider_freeze_memory', selectedMem); } };

        promptEl.querySelector('#hider-freeze-yes').onclick = () => { 
            saveMem(); if (selectedMem === 'allow_all') disableFreezeMode(); else if (selectedMem === 'allow_same' && parentDomain !== 'unknown domain') executeAddAllowedDomain(parentDomain);
            promptEl.remove(); onConfirm?.(); 
        };
        promptEl.querySelector('#hider-freeze-no').onclick = () => { 
            saveMem(); if (selectedMem === 'allow_all') disableFreezeMode();
            logBlockedAttempt(url, triggerType + ' (User)'); promptEl.remove(); onDeny?.(); simulateAdWindowSuccess(); 
        };
        promptEl.querySelector('#hider-freeze-allow-btn').onclick = () => {
            saveMem(); if (parentDomain !== 'unknown domain') executeAddAllowedDomain(parentDomain);
            if (selectedMem === 'allow_all') disableFreezeMode();
            promptEl.remove(); showToast(`🟢 Allowed ${parentDomain}!`); onConfirm?.();
        };
        promptEl.querySelector('#hider-freeze-block-btn').onclick = () => {
            saveMem(); const skipConfirm = gv('hider_skip_block_confirm', false);
            if (skipConfirm) { executeAddBlockDomain(parentDomain, triggerType, onDeny, promptEl); return; }

            promptEl.innerHTML = `
                <div style="font-weight:800;color:#ef4444;font-size:11px!important;text-transform:uppercase!important;">🚫 Confirm Domain Block</div>
                <div style="font-size:11px!important;color:#f8fafc!important;text-align:center;margin:2px 0">Block all future requests to:<br><strong style="color:#38bdf8;font-size:12px!important">${parentDomain}</strong>?</div>
                <label style="font-size:10px!important;color:#cbd5e1!important;display:flex;align-items:center;gap:4px;cursor:pointer;margin:4px 0;user-select:none"><input type="checkbox" id="hider-dont-ask-block" style="cursor:pointer;accent-color:#38bdf8;width:12px!important;height:12px!important"> Don't ask confirmation again</label>
                <div style="display:flex;gap:6px;width:100%;margin-top:4px"><button id="hider-confirm-block-yes" class="h-btn-pill btn-red" style="flex:1">Yes, Block</button><button id="hider-confirm-block-no" class="h-btn-pill" style="flex:1;background:rgba(255,255,255,0.1)!important;color:#f1f5f9!important;border:1px solid rgba(255,255,255,0.15)!important;">Cancel</button></div>
            `;
            promptEl.querySelector('#hider-confirm-block-yes').onclick = () => {
                if (promptEl.querySelector('#hider-dont-ask-block')?.checked) sv('hider_skip_block_confirm', true);
                executeAddBlockDomain(parentDomain, triggerType, onDeny, promptEl);
            };
            promptEl.querySelector('#hider-confirm-block-no').onclick = () => { showFreezePrompt(url, triggerType, onConfirm, onDeny); };
        };
    }

    // ---------- Enhanced Reveal (Quick) ----------
    function revealHiddenElements() {
        if (!doc.body) return;

        const isHiddenByUs = el => 
            el.id === UI_HOST_ID || 
            el.closest('#' + UI_HOST_ID) || 
            el.classList.contains('hider-stealth-target');

        const targets = new Set();

        const inlineHidden = doc.querySelectorAll([
            '[style*="display:none"]',
            '[style*="display: none"]',
            '[style*="visibility:hidden"]',
            '[style*="visibility: hidden"]',
            '[style*="opacity:0"]',
            '[style*="opacity: 0"]',
            '[style*="filter:blur"]',
            '[style*="filter: blur"]',
            '[style*="backdrop-filter:blur"]',
            '[style*="backdrop-filter: blur"]'
        ].join(','));
        inlineHidden.forEach(el => targets.add(el));

        const overlaySelector = [
            'div[style*="position:fixed"]',
            'div[style*="position: fixed"]',
            'div[style*="position:absolute"]',
            'div[style*="position: absolute"]',
            'div[style*="z-index: 999"]',
            'div[style*="z-index:999"]',
            'div[style*="z-index: 9999"]',
            'div[style*="z-index:9999"]',
            'div[style*="z-index: 99999"]',
            'div[style*="z-index:99999"]'
        ].join(',');
        const overlayCandidates = doc.querySelectorAll(overlaySelector);
        overlayCandidates.forEach(el => {
            const rect = el.getBoundingClientRect();
            if (rect.width < 100 || rect.height < 100) return;
            if (el.innerText.length > 200) return;
            if (el.querySelector('article, main, p, h1, h2, h3, h4, h5, h6')) return;
            targets.add(el);
        });

        doc.querySelectorAll([
            '.modal', '.overlay', '.popup', '.lightbox', '.blocker', 
            '.paywall', '.gate', '.wall', '.restricted', '.locked',
            '[data-overlay]', '[data-modal]', '[data-popup]', '[data-paywall]'
        ].join(',')).forEach(el => {
            if (!isHiddenByUs(el)) targets.add(el);
        });

        doc.querySelectorAll('*').forEach(el => {
            if (isHiddenByUs(el)) return;
            const style = win.getComputedStyle(el);
            if (style.filter && style.filter.includes('blur')) {
                targets.add(el);
            }
            if (style.backdropFilter && style.backdropFilter.includes('blur')) {
                targets.add(el);
            }
            if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
                targets.add(el);
            }
        });

        let count = 0;
        let blurCount = 0, hiddenCount = 0, overlayCount = 0;

        const processBatch = (arr, start) => {
            const end = Math.min(start + 50, arr.length);
            for (let i = start; i < end; i++) {
                const el = arr[i];
                if (isHiddenByUs(el)) continue;

                const style = win.getComputedStyle(el);
                let changed = false;

                if (style.filter && style.filter.includes('blur')) {
                    el.style.setProperty('filter', 'none', 'important');
                    el.style.setProperty('backdrop-filter', 'none', 'important');
                    el.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
                    blurCount++;
                    changed = true;
                }

                if (style.display === 'none') {
                    el.style.setProperty('display', 'block', 'important');
                    hiddenCount++;
                    changed = true;
                }
                if (style.visibility === 'hidden') {
                    el.style.setProperty('visibility', 'visible', 'important');
                    hiddenCount++;
                    changed = true;
                }
                if (style.opacity === '0') {
                    el.style.setProperty('opacity', '1', 'important');
                    hiddenCount++;
                    changed = true;
                }

                if (style.pointerEvents === 'none') {
                    el.style.setProperty('pointer-events', 'auto', 'important');
                }
                if (style.userSelect === 'none') {
                    el.style.setProperty('user-select', 'text', 'important');
                    el.style.setProperty('-webkit-user-select', 'text', 'important');
                }

                if (style.position === 'fixed' || style.position === 'absolute') {
                    const z = parseInt(style.zIndex, 10);
                    if (z > 900) {
                        el.style.setProperty('position', 'static', 'important');
                        el.style.setProperty('z-index', 'auto', 'important');
                        overlayCount++;
                        changed = true;
                    }
                }

                if (changed) count++;
            }

            if (end < arr.length) {
                requestAnimationFrame(() => processBatch(arr, end));
            } else {
                const parts = [];
                if (hiddenCount) parts.push(`${hiddenCount} hidden`);
                if (blurCount) parts.push(`${blurCount} blurred`);
                if (overlayCount) parts.push(`${overlayCount} overlays`);
                const summary = parts.length ? `👁️ Revealed: ${parts.join(', ')}` : '👁️ No hidden/blurred elements found.';
                showToast(summary);
                if (CACHE.autoScroll && featuresEnabled) forceEnableScroll();
            }
        };

        const targetArray = Array.from(targets);
        if (targetArray.length === 0) {
            showToast('👁️ No hidden/blurred elements found.');
            return;
        }
        requestAnimationFrame(() => processBatch(targetArray, 0));
    }

    // ---------- Time Skipper ----------
    function skip30Seconds() {
        let mediaCount = 0;
        doc.querySelectorAll('video, audio').forEach(el => {
            try {
                if (!isNaN(el.duration) && isFinite(el.duration)) {
                    el.currentTime = Math.min(el.duration, el.currentTime + 30);
                } else {
                    el.currentTime += 30;
                }
                mediaCount++;
            } catch {}
        });

        let timerCount = 0;
        const timerElements = doc.querySelectorAll(
            '[class*="timer"], [class*="countdown"], [id*="timer"], [id*="countdown"], ' +
            '[class*="time"], [id*="time"], [class*="remaining"], [id*="remaining"]'
        );
        timerElements.forEach(el => {
            const text = el.textContent.trim();
            if (/^\d{1,2}:\d{2}$/.test(text) || /^\d+\s*(s|sec|seconds?)$/i.test(text) || /^\d{1,2}:\d{2}\s*$/.test(text)) {
                el.textContent = '0';
                el.dispatchEvent(new Event('input', { bubbles: true }));
                timerCount++;
            }
        });

        doc.querySelectorAll('*:not([class*="timer"]):not([id*="timer"]):not([class*="countdown"]):not([id*="countdown"])')
            .forEach(el => {
                const text = el.textContent.trim();
                if (/^(?:[0-9]{1,2}:[0-5][0-9]|[1-9][0-9]?s?)$/i.test(text)) {
                    el.textContent = '0';
                    el.dispatchEvent(new Event('input', { bubbles: true }));
                    timerCount++;
                }
            });

        let clickCount = 0;
        const skipBtns = doc.querySelectorAll('button, a[role="button"], [role="button"]');
        skipBtns.forEach(btn => {
            const text = btn.textContent.trim().toLowerCase();
            if (text && (text.includes('skip') || text.includes('close') || text.includes('dismiss'))) {
                const rect = btn.getBoundingClientRect();
                if (rect.width > 0 && rect.height > 0) {
                    try { btn.click(); clickCount++; } catch {}
                }
            }
        });

        broadcastToFrames(window, { type: 'HIDER_SKIP_30' });

        const msgParts = [];
        if (mediaCount) msgParts.push(`${mediaCount} media`);
        if (timerCount) msgParts.push(`${timerCount} timers`);
        if (clickCount) msgParts.push(`${clickCount} buttons`);
        const summary = msgParts.length ? `⏩ Skipped: ${msgParts.join(', ')}` : '⏩ Skipped +30s';
        showToast(summary);
    }

    function autoSkipTimers() {
        if (!CACHE.autoTimeSkipper) return;
        if (!featuresEnabled) return;
        let timerCount = 0, clickCount = 0;

        const timerSelectors = [
            '[class*="timer"]', '[class*="countdown"]', '[id*="timer"]', '[id*="countdown"]',
            '[class*="time"]', '[id*="time"]', '[class*="remaining"]', '[id*="remaining"]'
        ];
        timerSelectors.forEach(sel => {
            doc.querySelectorAll(sel).forEach(el => {
                const text = el.textContent.trim();
                if (/^\d{1,2}:\d{2}$/.test(text) || /^\d+\s*(s|sec|seconds?)$/i.test(text) || /^\d{1,2}:\d{2}\s*$/.test(text)) {
                    el.textContent = '0';
                    el.dispatchEvent(new Event('input', { bubbles: true }));
                    timerCount++;
                }
            });
        });

        doc.querySelectorAll('*:not([class*="timer"]):not([id*="timer"]):not([class*="countdown"]):not([id*="countdown"])')
            .forEach(el => {
                const text = el.textContent.trim();
                if (/^(?:[0-9]{1,2}:[0-5][0-9]|[1-9][0-9]?s?)$/i.test(text)) {
                    el.textContent = '0';
                    el.dispatchEvent(new Event('input', { bubbles: true }));
                    timerCount++;
                }
            });

        const skipBtns = doc.querySelectorAll('button, a[role="button"], [role="button"]');
        skipBtns.forEach(btn => {
            const text = btn.textContent.trim().toLowerCase();
            if (text && (text.includes('skip') || text.includes('close') || text.includes('dismiss'))) {
                const rect = btn.getBoundingClientRect();
                if (rect.width > 0 && rect.height > 0) {
                    try { btn.click(); clickCount++; } catch {}
                }
            }
        });

        if (timerCount || clickCount) {
            showToast(`⏩ Auto-skipped: ${timerCount} timers, ${clickCount} buttons`);
        }
    }

    // ========== AGGRESSIVE PAUSE ==========
    function pauseAllVideos() {
        function pauseMedia(el) {
            try {
                if (el.tagName === 'VIDEO' || el.tagName === 'AUDIO') {
                    el.pause();
                    el.currentTime = 0;
                    el.loop = false;
                }
            } catch(e) {}
        }

        function traverse(node) {
            if (!node) return;
            if (node.nodeType === Node.ELEMENT_NODE) {
                pauseMedia(node);
                if (node.shadowRoot) {
                    traverse(node.shadowRoot);
                }
                if (node.tagName === 'IFRAME' || node.tagName === 'FRAME') {
                    try {
                        if (node.contentDocument) {
                            traverse(node.contentDocument);
                        }
                    } catch(e) {}
                }
                if (node.childNodes) {
                    node.childNodes.forEach(child => traverse(child));
                }
            } else if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType === Node.DOCUMENT_NODE) {
                if (node.childNodes) {
                    node.childNodes.forEach(child => traverse(child));
                }
            }
        }

        traverse(document);
        document.querySelectorAll('video, audio').forEach(pauseMedia);
    }

    // ========== LINK EXTRACTOR ==========
    function isDirectMedia(url) {
        if (!url) return false;
        const lower = url.toLowerCase();
        if (lower.startsWith('blob:')) return true;
        const mediaExts = [
            '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp', '.ico', '.tiff', '.tif', '.avif', '.heic', '.heif',
            '.mp4', '.webm', '.ogg', '.ogv', '.mov', '.avi', '.mkv', '.ts', '.m4v', '.wmv', '.flv', '.m3u8',
            '.mp3', '.wav', '.flac', '.m4a', '.aac', '.ogg', '.wma'
        ];
        return mediaExts.some(ext => lower.includes(ext));
    }

    function getMediaType(url) {
        if (!url) return null;
        const lower = url.toLowerCase();
        const imgExts = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp', '.ico', '.tiff', '.tif', '.avif', '.heic', '.heif'];
        if (imgExts.some(ext => lower.includes(ext))) return 'image';
        const vidExts = ['.mp4', '.webm', '.ogg', '.ogv', '.mov', '.avi', '.mkv', '.ts', '.m4v', '.wmv', '.flv', '.m3u8'];
        if (vidExts.some(ext => lower.includes(ext))) return 'video';
        const audExts = ['.mp3', '.wav', '.flac', '.m4a', '.aac', '.ogg', '.wma'];
        if (audExts.some(ext => lower.includes(ext))) return 'audio';
        if (lower.startsWith('blob:')) return 'image';
        return null;
    }

    function isMediaUrl(url) {
        return getMediaType(url) !== null;
    }

    function getAllLinks() {
        const linkMap = new Map();

        function addLink(url, text, type = 'link') {
            if (!url) return;
            try {
                const abs = new URL(url, location.href).href;
                if (abs.startsWith('javascript:') || abs.startsWith('mailto:') || abs.startsWith('tel:') || abs === '#') return;
                let finalType = type;
                const mediaType = getMediaType(abs);
                if (mediaType) finalType = 'media';
                if (!linkMap.has(abs)) {
                    linkMap.set(abs, { url: abs, text: text || abs, type: finalType, mediaSubtype: mediaType });
                } else {
                    const existing = linkMap.get(abs);
                    if (finalType === 'media' && existing.type === 'link') {
                        existing.type = 'media';
                        existing.mediaSubtype = mediaType;
                    }
                    if (text && text !== abs && (existing.text === existing.url || !existing.text)) {
                        existing.text = text;
                    }
                }
            } catch (e) { /* ignore */ }
        }

        function traverse(node) {
            if (!node) return;
            if (node.nodeType === Node.ELEMENT_NODE) {
                const el = node;

                if (el.tagName === 'VIDEO' || el.tagName === 'AUDIO') {
                    const src = el.getAttribute('src') || el.currentSrc;
                    if (src) {
                        const text = el.getAttribute('title') || el.getAttribute('aria-label') || el.getAttribute('alt') || el.textContent.trim() || src;
                        addLink(src, text, 'media');
                    }
                    el.querySelectorAll('source').forEach(source => {
                        const s = source.getAttribute('src');
                        if (s) {
                            const label = source.getAttribute('label') || source.getAttribute('title') || s;
                            addLink(s, label, 'media');
                        }
                    });
                    const poster = el.getAttribute('poster');
                    if (poster && isMediaUrl(poster)) {
                        addLink(poster, 'Poster image', 'media');
                    }
                }

                if (el.tagName === 'IMG') {
                    const src = el.getAttribute('src') || el.currentSrc;
                    if (src) {
                        const text = el.alt || el.title || el.getAttribute('aria-label') || src;
                        addLink(src, text, 'media');
                    }
                    const srcset = el.getAttribute('srcset');
                    if (srcset) {
                        const urls = srcset.split(',').map(s => s.trim().split(/\s+/)[0]).filter(Boolean);
                        urls.forEach(u => {
                            if (u) addLink(u, el.alt || el.title || u, 'media');
                        });
                    }
                    const lazyAttrs = ['data-src', 'data-original', 'data-lazy-src', 'data-srcset'];
                    lazyAttrs.forEach(attr => {
                        const val = el.getAttribute(attr);
                        if (val) {
                            if (attr === 'data-srcset') {
                                const urls = val.split(',').map(s => s.trim().split(/\s+/)[0]).filter(Boolean);
                                urls.forEach(u => addLink(u, el.alt || el.title || u, 'media'));
                            } else {
                                addLink(val, el.alt || el.title || val, 'media');
                            }
                        }
                    });
                }

                if (el.tagName === 'SOURCE' && el.closest('picture')) {
                    const s = el.getAttribute('src');
                    if (s) {
                        const label = el.getAttribute('label') || el.getAttribute('title') || s;
                        addLink(s, label, 'media');
                    }
                    const srcset = el.getAttribute('srcset');
                    if (srcset) {
                        const urls = srcset.split(',').map(s => s.trim().split(/\s+/)[0]).filter(Boolean);
                        urls.forEach(u => addLink(u, el.getAttribute('label') || u, 'media'));
                    }
                }

                const dataAttrs = ['src', 'url', 'link', 'video-src', 'audio-src', 'media-url', 'file', 'image', 'img', 'photo'];
                for (const attr of dataAttrs) {
                    const val = el.getAttribute('data-' + attr);
                    if (val && isMediaUrl(val)) {
                        const text = el.textContent.trim() || el.title || el.getAttribute('aria-label') || val;
                        addLink(val, text, 'media');
                    }
                }

                if (el.matches('a[href], area[href]')) {
                    const href = el.getAttribute('href');
                    if (href && isMediaUrl(href)) {
                        const text = el.textContent.trim() || el.title || el.getAttribute('aria-label') || href;
                        addLink(href, text, 'media');
                    } else if (href) {
                        const text = el.textContent.trim() || el.title || el.getAttribute('aria-label') || href;
                        addLink(href, text, 'link');
                    }
                }

                const onclick = el.getAttribute('onclick');
                if (onclick) {
                    const matches = onclick.match(/(?:location\.href|window\.open)\s*\(\s*['"]([^'"]+)['"]/gi);
                    if (matches) {
                        matches.forEach(m => {
                            const urlMatch = m.match(/['"]([^'"]+)['"]/);
                            if (urlMatch) {
                                const url = urlMatch[1];
                                if (isMediaUrl(url)) {
                                    const text = el.textContent.trim() || el.title || el.getAttribute('aria-label') || url;
                                    addLink(url, text, 'media');
                                }
                            }
                        });
                    }
                }

                if (el.matches('form[action]')) {
                    const action = el.getAttribute('action');
                    if (action && isMediaUrl(action)) {
                        const text = el.getAttribute('name') || el.id || 'Form action';
                        addLink(action, text, 'media');
                    }
                }

                if (el.tagName === 'IFRAME') {
                    const iframeSrc = el.getAttribute('src');
                    if (iframeSrc) {
                        const text = el.getAttribute('title') || el.getAttribute('aria-label') || 'iframe';
                        addLink(iframeSrc, text, 'link');
                    }
                }

                if (el.shadowRoot) {
                    traverseShadow(el.shadowRoot);
                }
            }

            if (node.childNodes) {
                for (const child of node.childNodes) {
                    traverse(child);
                }
            }
        }

        function traverseShadow(root) {
            if (root.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
                for (const child of root.children) {
                    traverse(child);
                }
            }
        }

        traverse(document);
        return Array.from(linkMap.values());
    }

    // ---------- Preview Modal ----------
    function closePreviewModal(modalEl) {
        const modal = modalEl || shadowBy('hider-link-preview-modal');
        if (modal && modal.parentNode) {
            modal.remove();
        }
        if (previewOutsideListener) {
            document.removeEventListener('click', previewOutsideListener);
            previewOutsideListener = null;
        }
    }

    function showLinkPreview(url) {
        const existing = shadowBy('hider-link-preview-modal');
        if (existing) {
            closePreviewModal(existing);
        }

        const mediaType = getMediaType(url);
        const isDirect = isDirectMedia(url);

        const modal = doc.createElement('div');
        modal.id = 'hider-link-preview-modal';
        modal.className = 'h-glass';
        modal.style.cssText = `
            position: fixed !important;
            top: 50% !important;
            left: 50% !important;
            transform: translate(-50%, -50%) !important;
            z-index: 2147483647 !important;
            padding: 16px !important;
            border-radius: 16px !important;
            background: rgba(13, 18, 30, 0.96) !important;
            backdrop-filter: blur(16px) !important;
            border: 1px solid rgba(255,255,255,0.15) !important;
            box-shadow: 0 24px 48px rgba(0,0,0,0.8) !important;
            min-width: 280px !important;
            max-width: 90vw !important;
            max-height: 90vh !important;
            pointer-events: auto !important;
            display: flex !important;
            flex-direction: column !important;
            gap: 10px !important;
            color: #f8fafc !important;
            overflow-y: auto !important;
        `;

        let typeIcon = '🔗';
        if (mediaType === 'image') typeIcon = '🖼️';
        else if (mediaType === 'video') typeIcon = '🎬';
        else if (mediaType === 'audio') typeIcon = '🔊';

        const title = doc.createElement('div');
        title.style.cssText = 'font-weight:800; font-size:12px; color:#38bdf8; text-transform:uppercase; letter-spacing:0.5px;';
        title.textContent = `${typeIcon} ${mediaType ? mediaType.toUpperCase() : 'Link'} Preview`;
        modal.appendChild(title);

        if (mediaType) {
            const mediaWrapper = doc.createElement('div');
            mediaWrapper.style.cssText = `
                display:flex; justify-content:center; align-items:center; 
                background: rgba(0,0,0,0.4); border-radius:8px; padding:4px;
                min-height: 80px; max-height: 55vh; overflow:hidden;
            `;

            if (mediaType === 'image') {
                const img = doc.createElement('img');
                img.src = url;
                img.style.cssText = 'max-width:100%; max-height:55vh; object-fit:contain; border-radius:4px;';
                img.onerror = () => { 
                    img.alt = '❌ Failed to load image';
                    img.style.cssText += 'height:60px; width:auto;';
                };
                mediaWrapper.appendChild(img);
            } else if (mediaType === 'video') {
                if (isDirect) {
                    const video = doc.createElement('video');
                    video.src = url;
                    video.controls = true;
                    video.preload = 'metadata';
                    video.style.cssText = 'max-width:100%; max-height:55vh; border-radius:4px; background:#000;';
                    video.onerror = () => {
                        video.innerHTML = '<div style="padding:20px;color:#f87171;font-size:12px;">❌ Failed to load video</div>';
                    };
                    mediaWrapper.appendChild(video);
                } else {
                    mediaWrapper.textContent = '🎬 Video – click "Open" to watch in new tab.';
                    mediaWrapper.style.cssText += 'padding:20px;color:#94a3b8;font-size:12px;';
                }
            } else if (mediaType === 'audio') {
                const audio = doc.createElement('audio');
                audio.src = url;
                audio.controls = true;
                audio.preload = 'metadata';
                audio.style.cssText = 'width:100%;';
                audio.onerror = () => {
                    audio.innerHTML = '<div style="padding:20px;color:#f87171;font-size:12px;">❌ Failed to load audio</div>';
                };
                mediaWrapper.appendChild(audio);
            } else {
                mediaWrapper.textContent = 'Media preview not available';
                mediaWrapper.style.cssText += 'padding:20px;color:#94a3b8;font-size:12px;';
            }
            modal.appendChild(mediaWrapper);
        } else {
            const linkPreview = doc.createElement('div');
            linkPreview.textContent = '🔗 Link Preview';
            linkPreview.style.cssText = 'font-size:12px;color:#94a3b8;padding:10px;';
            modal.appendChild(linkPreview);
        }

        const urlDisplay = doc.createElement('div');
        urlDisplay.style.cssText = 'font-size:10px; word-break:break-all; background:rgba(0,0,0,0.3); padding:6px 8px; border-radius:6px; border:1px solid rgba(255,255,255,0.1); font-family:monospace; max-height:80px; overflow-y:auto;';
        urlDisplay.textContent = url;
        modal.appendChild(urlDisplay);

        const btnGroup = doc.createElement('div');
        btnGroup.style.cssText = 'display:flex; gap:6px; justify-content:flex-end; flex-wrap:wrap;';

        const copyBtn = doc.createElement('button');
        copyBtn.className = 'hider-btn-small btn-blue';
        copyBtn.textContent = '📋 Copy';
        copyBtn.onclick = () => {
            copyToClipboard(url);
            showToast('📋 URL copied!');
        };
        btnGroup.appendChild(copyBtn);

        if (isDirect && (mediaType === 'image' || mediaType === 'video' || mediaType === 'audio')) {
            const downloadBtn = doc.createElement('button');
            downloadBtn.className = 'hider-btn-small btn-green';
            downloadBtn.textContent = '⬇️ Download';
            downloadBtn.onclick = function(e) {
                e.stopPropagation();
                let filename = url.split('/').pop().split(/[?#]/)[0] || 'media_file';
                if (!filename.includes('.')) {
                    if (mediaType === 'image') filename += '.jpg';
                    else if (mediaType === 'video') filename += '.mp4';
                    else if (mediaType === 'audio') filename += '.mp3';
                    else filename += '.bin';
                }
                try {
                    GM_download({
                        url: url,
                        name: filename,
                        onerror: function(err) {
                            console.error('GM_download failed, trying fetch fallback', err);
                            fetch(url).then(res => {
                                if (!res.ok) throw new Error('Network error');
                                return res.blob();
                            }).then(blob => {
                                const a = document.createElement('a');
                                const objectUrl = URL.createObjectURL(blob);
                                a.href = objectUrl;
                                a.download = filename;
                                document.body.appendChild(a);
                                a.click();
                                document.body.removeChild(a);
                                URL.revokeObjectURL(objectUrl);
                                showToast('⬇️ Downloaded using fallback');
                            }).catch(() => {
                                showToast('❌ Download failed – opening in new tab');
                                window.open(url, '_blank');
                            });
                        }
                    });
                    showToast(`⬇️ Downloading: ${filename}`);
                } catch (err) {
                    console.error('GM_download error:', err);
                    showToast('❌ Download error – opening in new tab');
                    window.open(url, '_blank');
                }
            };
            btnGroup.appendChild(downloadBtn);
        }

        const openBtn = doc.createElement('button');
        openBtn.className = 'hider-btn-small btn-purple';
        openBtn.textContent = '↗ Open';
        openBtn.onclick = () => {
            win.open(url, '_blank');
        };
        btnGroup.appendChild(openBtn);

        const closeBtn = doc.createElement('button');
        closeBtn.className = 'hider-btn-small btn-gray';
        closeBtn.textContent = '✖ Close';
        closeBtn.onclick = () => closePreviewModal(modal);
        btnGroup.appendChild(closeBtn);

        modal.appendChild(btnGroup);
        shadowRoot.appendChild(modal);

        const closeModalHandler = (e) => {
            if (!modal.parentNode) {
                document.removeEventListener('click', closeModalHandler);
                return;
            }
            const path = e.composedPath ? e.composedPath() : [];
            if (path.some(el => el === modal || (el && el.contains && el.contains(modal)))) {
                return;
            }
            if (path.some(el => el.id === UI_HOST_ID || el.id === STEPPER_BAR_ID)) {
                return;
            }
            closePreviewModal(modal);
        };
        if (previewOutsideListener) {
            document.removeEventListener('click', previewOutsideListener);
        }
        previewOutsideListener = closeModalHandler;
        setTimeout(() => {
            document.addEventListener('click', previewOutsideListener);
        }, 10);
    }

    // ----- Grid item for Media Mode -----
    function buildGridItem(link) {
        const div = doc.createElement('div');
        div.className = 'hider-grid-item';
        div.style.cssText = `
            position: relative;
            background: rgba(255,255,255,0.04);
            border-radius: 8px;
            overflow: hidden;
            aspect-ratio: 1 / 1;
            cursor: pointer;
            border: 1px solid rgba(255,255,255,0.08);
            transition: transform 0.2s ease, box-shadow 0.2s ease;
        `;
        div.onmouseover = () => { div.style.transform = 'scale(1.03)'; div.style.boxShadow = '0 4px 12px rgba(0,0,0,0.6)'; };
        div.onmouseout = () => { div.style.transform = 'scale(1)'; div.style.boxShadow = 'none'; };

        const mediaType = link.mediaSubtype || getMediaType(link.url);
        const isDirect = isDirectMedia(link.url);
        let icon = '📎';
        if (mediaType === 'image') icon = '🖼️';
        else if (mediaType === 'video') icon = '🎬';
        else if (mediaType === 'audio') icon = '🔊';

        let thumbnail = '';
        if (mediaType === 'image') {
            thumbnail = `<img src="${link.url}" style="width:100%;height:100%;object-fit:cover;" onerror="this.style.display='none';">`;
        } else if (mediaType === 'video' && isDirect) {
            thumbnail = `<video src="${link.url}" muted preload="metadata" style="width:100%;height:100%;object-fit:cover;" onerror="this.style.display='none';"></video>`;
        } else {
            thumbnail = `<div style="display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:48px;color:#94a3b8;background:rgba(0,0,0,0.3);">${icon}</div>`;
        }

        div.innerHTML = thumbnail;

        const overlay = doc.createElement('div');
        overlay.style.cssText = `
            position: absolute;
            bottom: 4px;
            left: 4px;
            background: rgba(0,0,0,0.7);
            padding: 2px 6px;
            border-radius: 4px;
            font-size: 8px;
            color: #e0f2fe;
            backdrop-filter: blur(4px);
            pointer-events: none;
            font-weight: 600;
            letter-spacing: 0.3px;
            text-transform: uppercase;
        `;
        overlay.textContent = mediaType || 'media';
        div.appendChild(overlay);

        if (isDirect && (mediaType === 'image' || mediaType === 'video' || mediaType === 'audio')) {
            const downloadBtn = doc.createElement('button');
            downloadBtn.className = 'hider-btn-small';
            downloadBtn.textContent = '⬇️';
            downloadBtn.title = 'Download this media';
            downloadBtn.style.cssText = `
                position: absolute;
                bottom: 4px;
                right: 4px;
                background: rgba(0,0,0,0.7) !important;
                backdrop-filter: blur(4px);
                border: none;
                border-radius: 4px;
                color: #fff;
                padding: 2px 6px;
                font-size: 10px;
                cursor: pointer;
                z-index: 2;
                pointer-events: auto;
                transition: background 0.2s;
            `;
            downloadBtn.onmouseover = () => { downloadBtn.style.background = 'rgba(56,189,248,0.8) !important'; };
            downloadBtn.onmouseout = () => { downloadBtn.style.background = 'rgba(0,0,0,0.7) !important'; };

            downloadBtn.addEventListener('click', function(e) {
                e.stopPropagation();
                const url = link.url;
                if (!url) {
                    showToast('❌ No media URL');
                    return;
                }
                let filename = url.split('/').pop().split(/[?#]/)[0] || 'media_file';
                if (!filename.includes('.')) {
                    if (mediaType === 'image') filename += '.jpg';
                    else if (mediaType === 'video') filename += '.mp4';
                    else if (mediaType === 'audio') filename += '.mp3';
                    else filename += '.bin';
                }
                try {
                    GM_download({
                        url: url,
                        name: filename,
                        onerror: function(err) {
                            console.error('GM_download failed, trying fetch fallback', err);
                            fetch(url).then(res => {
                                if (!res.ok) throw new Error('Network error');
                                return res.blob();
                            }).then(blob => {
                                const a = document.createElement('a');
                                const objectUrl = URL.createObjectURL(blob);
                                a.href = objectUrl;
                                a.download = filename;
                                document.body.appendChild(a);
                                a.click();
                                document.body.removeChild(a);
                                URL.revokeObjectURL(objectUrl);
                                showToast('⬇️ Downloaded using fallback');
                            }).catch(() => {
                                showToast('❌ Download failed – opening in new tab');
                                window.open(url, '_blank');
                            });
                        }
                    });
                    showToast(`⬇️ Downloading: ${filename}`);
                } catch (err) {
                    console.error('GM_download error:', err);
                    showToast('❌ Download error – opening in new tab');
                    window.open(url, '_blank');
                }
            });

            div.appendChild(downloadBtn);
        }

        div.addEventListener('click', (e) => {
            if (e.target.closest('button')) return;
            showLinkPreview(link.url);
        });

        return div;
    }

    // ----- List item for normal mode -----
    function buildListItem(link, filterText, hideInternal, mediaOnly) {
        const currentHost = location.hostname;
        if (hideInternal) {
            try {
                const urlObj = new URL(link.url);
                if (urlObj.hostname === currentHost) return null;
            } catch { /* ignore */ }
        }
        if (mediaOnly && link.type !== 'media') return null;

        if (filterText) {
            const lower = filterText.toLowerCase();
            if (!link.text.toLowerCase().includes(lower) && !link.url.toLowerCase().includes(lower)) {
                return null;
            }
        }

        const div = doc.createElement('div');
        div.className = 'list-item';
        div.style.cssText = 'display:flex; justify-content:space-between; align-items:center; gap:4px;';
        
        let icon = '🔗';
        if (link.type === 'media') {
            const subtype = link.mediaSubtype || getMediaType(link.url);
            if (subtype === 'image') icon = '🖼️';
            else if (subtype === 'video') icon = '🎬';
            else if (subtype === 'audio') icon = '🔊';
            else icon = '🎬';
        }

        let displayText = link.text;
        if (link.type === 'media') {
            displayText = icon + ' ' + displayText;
        }
        if (linkDisplayMode === 'url') {
            displayText = link.url + (link.type === 'media' ? ' ' + icon : '');
        }

        const textSpan = doc.createElement('span');
        textSpan.className = 'rule-text';
        textSpan.textContent = displayText;
        textSpan.title = link.url;
        textSpan.style.cssText = 'flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;';
        
        const btnGroup = doc.createElement('div');
        btnGroup.style.cssText = 'display:flex; gap:2px; flex-shrink:0;';

        const previewBtn = doc.createElement('button');
        previewBtn.className = 'hider-btn-small btn-purple';
        previewBtn.textContent = '🔍';
        previewBtn.title = 'Preview full link (media preview if applicable)';
        previewBtn.onclick = (e) => {
            e.stopPropagation();
            showLinkPreview(link.url);
        };
        btnGroup.appendChild(previewBtn);

        const copyBtn = doc.createElement('button');
        copyBtn.className = 'hider-btn-small btn-blue';
        copyBtn.textContent = '📋';
        copyBtn.title = 'Copy URL';
        copyBtn.onclick = (e) => {
            e.stopPropagation();
            copyToClipboard(link.url);
            showToast('📋 Copied!');
        };
        btnGroup.appendChild(copyBtn);

        const openBtn = doc.createElement('button');
        openBtn.className = 'hider-btn-small btn-green';
        openBtn.textContent = '↗';
        openBtn.title = 'Open in new tab';
        openBtn.onclick = (e) => {
            e.stopPropagation();
            win.open(link.url, '_blank');
        };
        btnGroup.appendChild(openBtn);

        div.appendChild(textSpan);
        div.appendChild(btnGroup);
        return div;
    }

    function populateLinkList() {
        const listContainer = shadowBy('hider-link-list');
        if (!listContainer) return;
        const searchInput = shadowBy('hider-link-search');
        const hideInternalCheck = shadowBy('hider-link-hide-internal');
        const mediaModeCheck = shadowBy('hider-link-media-mode');
        const filterText = searchInput ? searchInput.value.toLowerCase() : '';
        const hideInternal = hideInternalCheck ? hideInternalCheck.checked : false;
        const mediaMode = mediaModeCheck ? mediaModeCheck.checked : false;

        const links = getAllLinks();
        const title = shadowBy('link-panel-title');
        if (title) title.textContent = `🔗 Extracted Links (${links.length})`;

        listContainer.innerHTML = '';
        let displayed = 0;
        const frag = doc.createDocumentFragment();

        if (mediaMode) {
            const grid = doc.createElement('div');
            grid.style.cssText = 'display:grid;grid-template-columns:repeat(3,1fr);gap:6px;';
            links.forEach(link => {
                if (link.type !== 'media') return;
                if (filterText) {
                    const lower = filterText;
                    if (!link.text.toLowerCase().includes(lower) && !link.url.toLowerCase().includes(lower)) return;
                }
                if (hideInternal) {
                    try {
                        const urlObj = new URL(link.url);
                        if (urlObj.hostname === location.hostname) return;
                    } catch {}
                }
                const item = buildGridItem(link);
                grid.appendChild(item);
                displayed++;
            });
            if (displayed === 0) {
                const empty = doc.createElement('div');
                empty.style.cssText = 'font-size:9px!important;color:#94a3b8!important;padding:8px!important;text-align:center!important;border:1px dashed rgba(255,255,255,0.12)!important;border-radius:6px!important;grid-column:1/4;';
                empty.textContent = 'No media items.';
                grid.appendChild(empty);
            }
            frag.appendChild(grid);
        } else {
            links.forEach(link => {
                const item = buildListItem(link, filterText, hideInternal, false);
                if (item) {
                    frag.appendChild(item);
                    displayed++;
                }
            });
            if (displayed === 0) {
                const empty = doc.createElement('div');
                empty.style.cssText = 'font-size:9px!important;color:#94a3b8!important;padding:8px!important;text-align:center!important;border:1px dashed rgba(255,255,255,0.12)!important;border-radius:6px!important;';
                empty.textContent = 'No matching links.';
                frag.appendChild(empty);
            }
        }

        listContainer.appendChild(frag);
        if (title) title.textContent = `🔗 Extracted Links (${displayed} shown)`;
    }

    // --- Link panel with Refresh button ---
    function createLinkPanel() {
        if (linkPanelEl) return linkPanelEl;

        const panel = doc.createElement('div');
        panel.id = 'hider-link-panel';
        panel.className = 'h-glass';
        panel.style.cssText = `
            position: fixed !important;
            right: 14px !important;
            top: 55px !important;
            z-index: 2147483645 !important;
            width: min(310px, 90vw) !important;
            max-height: min(580px, 82vh) !important;
            border-radius: 16px !important;
            padding: 10px !important;
            display: none;
            flex-direction: column !important;
            overflow-y: auto !important;
            overscroll-behavior: contain !important;
            touch-action: pan-y !important;
            pointer-events: auto !important;
            gap: 6px !important;
            opacity: 0;
            transform: scale(0.96) translateY(-8px);
            transition: opacity 0.2s ease, transform 0.2s ease !important;
        `;

        const header = doc.createElement('div');
        header.className = 'panel-header';
        header.style.cssText = 'display:flex; justify-content:space-between; align-items:center;';
        const title = doc.createElement('span');
        title.id = 'link-panel-title';
        title.textContent = '🔗 Extracted Links';
        const headerRight = doc.createElement('div');
        headerRight.style.cssText = 'display:flex; gap:4px;';

        const modeBtn = doc.createElement('button');
        modeBtn.className = 'hider-btn-small btn-gray';
        modeBtn.textContent = '📝';
        modeBtn.title = 'Toggle display: text / URL';
        modeBtn.onclick = (e) => {
            e.stopPropagation();
            linkDisplayMode = linkDisplayMode === 'text' ? 'url' : 'text';
            modeBtn.textContent = linkDisplayMode === 'text' ? '📝' : '🔗';
            populateLinkList();
        };
        headerRight.appendChild(modeBtn);

        const refreshBtn = doc.createElement('button');
        refreshBtn.className = 'hider-btn-small btn-purple';
        refreshBtn.textContent = '🔄';
        refreshBtn.title = 'Refresh links & pause media';
        refreshBtn.onclick = (e) => {
            e.stopPropagation();
            pauseAllVideos();
            populateLinkList();
            showToast('🔄 Links refreshed');
        };
        headerRight.appendChild(refreshBtn);

        const closeBtn = doc.createElement('button');
        closeBtn.className = 'hider-btn-small';
        closeBtn.style.cssText = 'background:rgba(255,255,255,0.12)!important; padding:2px 6px!important;';
        closeBtn.textContent = '✖';
        closeBtn.onclick = () => { toggleLinkPanel(); };
        headerRight.appendChild(closeBtn);

        header.appendChild(title);
        header.appendChild(headerRight);
        panel.appendChild(header);

        const searchWrapper = doc.createElement('div');
        searchWrapper.style.cssText = 'display:flex; gap:4px; align-items:center; margin-bottom:2px; flex-wrap:wrap;';
        const searchInput = doc.createElement('input');
        searchInput.id = 'hider-link-search';
        searchInput.className = 'h-select';
        searchInput.placeholder = '🔍 Filter links...';
        searchInput.style.cssText = 'flex:1; height:26px; font-size:10px; min-width:80px;';
        searchInput.oninput = () => populateLinkList();
        searchWrapper.appendChild(searchInput);

        const hideCheck = doc.createElement('label');
        hideCheck.style.cssText = 'font-size:9px; color:#cbd5e1; display:flex; align-items:center; gap:4px; cursor:pointer; user-select:none; white-space:nowrap;';
        const checkBox = doc.createElement('input');
        checkBox.id = 'hider-link-hide-internal';
        checkBox.type = 'checkbox';
        checkBox.style.cssText = 'accent-color:#38bdf8; width:12px; height:12px; cursor:pointer;';
        checkBox.onchange = () => populateLinkList();
        hideCheck.appendChild(checkBox);
        hideCheck.appendChild(doc.createTextNode('Hide internal'));
        searchWrapper.appendChild(hideCheck);

        const mediaCheck = doc.createElement('label');
        mediaCheck.style.cssText = 'font-size:9px; color:#cbd5e1; display:flex; align-items:center; gap:4px; cursor:pointer; user-select:none; white-space:nowrap;';
        const mediaBox = doc.createElement('input');
        mediaBox.id = 'hider-link-media-mode';
        mediaBox.type = 'checkbox';
        mediaBox.style.cssText = 'accent-color:#f59e0b; width:12px; height:12px; cursor:pointer;';
        mediaBox.onchange = () => populateLinkList();
        mediaCheck.appendChild(mediaBox);
        mediaCheck.appendChild(doc.createTextNode('📺 Media mode'));
        searchWrapper.appendChild(mediaCheck);

        panel.appendChild(searchWrapper);

        const listContainer = doc.createElement('div');
        listContainer.id = 'hider-link-list';
        listContainer.style.cssText = 'display:flex; flex-direction:column; gap:4px; overflow-y:auto; flex:1; overscroll-behavior:contain;';
        panel.appendChild(listContainer);

        shadowRoot.appendChild(panel);
        linkPanelEl = panel;

        return panel;
    }

    function toggleLinkPanel() {
        if (!shadowRoot) return;
        if (!linkPanelEl || !linkPanelEl.parentNode) {
            linkPanelEl = createLinkPanel();
        }

        const isVisible = linkPanelEl.classList.contains('is-visible');
        if (isVisible) {
            linkPanelEl.classList.remove('is-visible');
            setTimeout(() => linkPanelEl.style.display = 'none', 300);
        } else {
            pauseAllVideos();
            populateLinkList();
            linkPanelEl.style.display = 'flex';
            void linkPanelEl.offsetWidth;
            linkPanelEl.classList.add('is-visible');
        }
    }

    // ---------- UI Creation ----------
    function createShadowUI() {
        if (!isTop) return;
        const parentEl = doc.documentElement || doc.body;
        if (!parentEl) return;

        let hostEl = doc.getElementById(UI_HOST_ID);
        if (!hostEl) {
            hostEl = doc.createElement('div'); hostEl.id = UI_HOST_ID;
            hostEl.style.cssText = 'position:fixed!important;top:0!important;left:0!important;width:0!important;height:0!important;z-index:2147483647!important;pointer-events:none!important;display:block!important;visibility:visible!important;opacity:1!important;overflow:visible!important;';
            parentEl.appendChild(hostEl);
        }

        shadowRoot = hostEl.shadowRoot || hostEl.attachShadow({ mode: 'open' });
        const style = doc.createElement('style');
        
        style.textContent = `
        * { box-sizing: border-box !important; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, sans-serif !important; line-height: 1.3 !important; }
        
        .h-glass { 
            background: rgba(13, 18, 30, 0.92) !important; 
            backdrop-filter: blur(12px) !important; 
            -webkit-backdrop-filter: blur(12px) !important; 
            border: 1px solid rgba(255, 255, 255, 0.12) !important; 
            color: #f8fafc !important; 
            border-radius: 14px !important; 
            box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6) !important; 
        }

        ::-webkit-scrollbar { width: 4px !important; height: 4px !important; }
        ::-webkit-scrollbar-track { background: transparent !important; }
        ::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2) !important; border-radius: 8px !important; }

        #hider-panel { 
            position: fixed !important; 
            right: 14px !important; 
            top: 55px !important; 
            z-index: 2147483645 !important; 
            width: min(480px, 92vw) !important; 
            max-height: min(700px, 85vh) !important;
            border-radius: 16px !important; 
            padding: 0 !important; 
            display: none; 
            flex-direction: column !important; 
            overflow: hidden !important; 
            pointer-events: auto !important; 
            opacity: 0; 
            transform: scale(0.96) translateY(-8px); 
            transition: opacity 0.2s ease, transform 0.2s ease !important; 
        }
        #hider-panel.is-visible { 
            opacity: 1 !important; 
            transform: scale(1) translateY(0) !important; 
            display: flex !important; 
        }

        #hider-link-panel.is-visible {
            opacity: 1 !important;
            transform: scale(1) translateY(0) !important;
            display: flex !important;
        }

        .panel-header {
            padding: 8px 12px;
            border-bottom: 1px solid rgba(255,255,255,0.08);
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-shrink: 0;
        }
        .panel-header .title {
            font-weight: 800;
            font-size: 12px;
            color: #f8fafc;
        }
        .panel-header .close-btn {
            background: rgba(255,255,255,0.08);
            border: none;
            border-radius: 6px;
            color: #cbd5e1;
            padding: 2px 8px;
            cursor: pointer;
            font-size: 11px;
        }
        .panel-header .close-btn:hover { background: rgba(255,255,255,0.16); }

        .panel-body {
            display: flex;
            flex: 1;
            overflow: hidden;
        }

        .panel-sidebar {
            flex: 0 0 110px;
            background: rgba(0,0,0,0.2);
            padding: 6px 4px;
            overflow-y: auto;
            border-right: 1px solid rgba(255,255,255,0.06);
        }

        .panel-sidebar .tab-btn {
            display: block;
            width: 100%;
            text-align: left;
            background: transparent;
            border: none;
            border-radius: 6px;
            padding: 5px 8px;
            color: #94a3b8;
            font-size: 10px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.15s ease;
            margin-bottom: 2px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .panel-sidebar .tab-btn:hover {
            background: rgba(255,255,255,0.08);
            color: #e2e8f0;
        }
        .panel-sidebar .tab-btn.active {
            background: rgba(56,189,248,0.15);
            color: #38bdf8;
            border-left: 2px solid #38bdf8;
        }

        .panel-content {
            flex: 1;
            padding: 8px 10px;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            gap: 6px;
        }

        .panel-content .tab-content {
            display: none;
            flex-direction: column;
            gap: 6px;
        }
        .panel-content .tab-content.active {
            display: flex;
        }

        .h-dock { 
            position: fixed !important; right: 10px !important; top: 35%; z-index: 2147483643 !important; 
            display: flex !important; flex-direction: column !important; align-items: center !important; gap: 5px !important; 
            padding: 5px !important; pointer-events: auto !important; transition: transform 0.3s ease, opacity 0.3s ease !important; 
            user-select: none !important; border-radius: 20px !important;
        }
        .h-dock.is-collapsed { transform: translateX(65%) !important; opacity: 0.5 !important; } 
        .h-dock.manual-hidden { transform: translateX(65%) !important; opacity: 0.5 !important; } 
        .h-dock.is-collapsed:not(.manual-hidden):hover, .h-dock.expanded { transform: translateX(0) !important; opacity: 1 !important; }
        
        .h-dock-main { 
            width: 34px !important; height: 34px !important; font-size: 16px !important; 
            background: linear-gradient(135deg, rgba(56, 189, 248, 0.3), rgba(37, 99, 235, 0.4)) !important; 
            border: 1px solid rgba(56, 189, 248, 0.4) !important; cursor: grab !important; border-radius: 50% !important;
            flex-shrink: 0 !important; min-height: 34px !important; min-width: 34px !important; display: flex !important; align-items: center !important; justify-content: center !important;
        } 
        .h-dock-main.expanded { 
            background: linear-gradient(135deg, #0ea5e9, #2563eb) !important; color: #fff !important; 
            box-shadow: 0 0 12px rgba(14, 165, 233, 0.5) !important; border-color: transparent !important;
        }
        
        .h-dock-menu { display: flex; flex-direction: column !important; gap: 5px !important; overflow: hidden !important; max-height: 0; opacity: 0; transition: max-height 0.3s ease, opacity 0.2s ease !important; }
        .h-dock-menu.is-open { max-height: 450px; opacity: 1; }
        
        .h-dock-btn { 
            width: 32px !important; height: 32px !important; border-radius: 10px !important; 
            border: 1px solid rgba(255, 255, 255, 0.1) !important; background: rgba(255, 255, 255, 0.06) !important; 
            color: #cbd5e1 !important; font-size: 11px !important; font-weight: 700 !important; display: flex !important; 
            flex-direction: column !important; align-items: center !important; justify-content: center !important; 
            cursor: pointer !important; transition: all 0.2s ease !important; margin: 0 !important; padding: 0 !important; 
            flex-shrink: 0 !important; min-height: 32px !important; min-width: 32px !important;
        }
        .h-dock-btn:hover { background: rgba(255, 255, 255, 0.18) !important; color: #fff !important; transform: scale(1.05) !important; } 
        .h-dock-btn.active { background: linear-gradient(135deg, #0ea5e9, #2563eb) !important; color: #fff !important; border-color: transparent !important; } 
        .h-dock-btn.scope-link { background: linear-gradient(135deg, #10b981, #059669) !important; color: #fff !important; border-color: transparent !important; } 
        .h-dock-btn.is-frozen { background: linear-gradient(135deg, #8b5cf6, #6d28d9) !important; color: #fff !important; border-color: transparent !important; } 
        .h-dock-btn span { font-size: 7px !important; font-weight: 800 !important; margin-top: 1px !important; letter-spacing: 0.3px !important; text-transform: uppercase !important; }
        
        .btn-blue { background: linear-gradient(135deg, #0ea5e9, #0284c7) !important; color: #fff !important; border: 1px solid rgba(255,255,255,0.2) !important; }
        .btn-green { background: linear-gradient(135deg, #10b981, #059669) !important; color: #fff !important; border: 1px solid rgba(255,255,255,0.2) !important; }
        .btn-red { background: linear-gradient(135deg, #f43f5e, #e11d48) !important; color: #fff !important; border: 1px solid rgba(255,255,255,0.2) !important; }
        .btn-purple { background: linear-gradient(135deg, #a855f7, #7e22ce) !important; color: #fff !important; border: 1px solid rgba(255,255,255,0.2) !important; }
        .btn-gray { background: linear-gradient(135deg, #475569, #334155) !important; color: #fff !important; border: 1px solid rgba(255,255,255,0.15) !important; }

        .h-stepper-pill { 
            position: fixed !important; bottom: 20px !important; left: 50% !important; transform: translateX(-50%) !important; 
            z-index: 2147483644 !important; padding: 6px 8px !important; display: flex !important; flex-direction: column !important; 
            align-items: center !important; gap: 4px !important; pointer-events: auto !important; width: 130px !important; 
            user-select: none !important; border-radius: 12px !important; 
        }
        .h-stepper-row { display: flex !important; gap: 4px !important; width: 100% !important; justify-content: center !important; }
        .h-stepper-row .h-btn-icon { flex: 1 !important; }
        .h-drag-dots { cursor: grab !important; color: #64748b !important; font-size: 11px !important; width: 100% !important; text-align: center !important; line-height: 1 !important; letter-spacing: 2px !important; } 
        .h-btn-icon { width: 100% !important; height: 22px !important; border-radius: 6px !important; border: 1px solid rgba(255,255,255,.12) !important; background: rgba(255,255,255,.08) !important; color: #f1f5f9 !important; font-size: 9px !important; font-weight: 700 !important; cursor: pointer !important; display: flex !important; align-items: center !important; justify-content: center !important; } 
        .h-btn-icon:hover { background: rgba(255,255,255,.2) !important; } 
        
        .h-tag-badge-box { width: 100% !important; height: 22px !important; overflow: hidden !important; position: relative !important; background: rgba(0, 0, 0, 0.5) !important; border: 1px solid rgba(56, 189, 248, 0.3) !important; border-radius: 6px !important; display: flex !important; align-items: center !important; flex-shrink: 0 !important; }
        .h-tag-badge-text { color: #38bdf8 !important; font-size: 9px !important; font-family: monospace !important; font-weight: 700 !important; display: block !important; width: 100% !important; text-align: center !important; overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; line-height: 22px !important; }
        .h-tag-badge-text.is-animating { position: absolute !important; left: 0 !important; width: auto !important; padding-left: 100% !important; text-align: left !important; animation: hiderMarqueeR2L 8s linear infinite !important; }
        @keyframes hiderMarqueeR2L { 0% { transform: translate3d(0,0,0); } 100% { transform: translate3d(-100%,0,0); } }

        .h-btn-pill { height: 22px !important; min-height: 22px !important; width: 100% !important; padding: 0 6px !important; border-radius: 6px !important; font-size: 9px !important; font-weight: 800 !important; border: none !important; cursor: pointer !important; display: flex !important; align-items: center !important; justify-content: center !important; } 
        .h-btn-pill:hover { filter: brightness(1.15) !important; } 

        .h-toast { /* overridden by inline styles */ }
        .h-prompt { position: fixed !important; top: 25px !important; left: 50% !important; transform: translateX(-50%) translateY(-15px) !important; opacity: 0; padding: 12px 14px !important; z-index: 2147483646 !important; display: flex !important; flex-direction: column !important; align-items: center !important; gap: 6px !important; pointer-events: auto !important; width: min(290px, 88vw) !important; max-height: 85vh !important; transition: all 0.3s ease !important; } 
        .h-url-box { font-size: 10px !important; color: #94a3b8 !important; word-break: break-all !important; max-height: 32px !important; overflow: hidden !important; background: rgba(0,0,0,.4) !important; padding: 4px 8px !important; border-radius: 6px !important; width: 100% !important; border: 1px solid rgba(255,255,255,.1) !important; font-family: monospace !important; } 
        .h-select { width: 100% !important; background: rgba(255,255,255,.06) !important; border: 1px solid rgba(255,255,255,.14) !important; border-radius: 6px !important; color: #fff !important; padding: 4px 8px !important; font-size: 10px !important; outline: 0 !important; height: 28px !important; } 
        
        .h-custom-select { position: relative !important; width: 100% !important; user-select: none !important; margin-top: 2px !important; z-index: 10 !important; } 
        .h-custom-trigger { background: rgba(30,41,59,.85) !important; border: 1px solid rgba(96,165,250,.4) !important; border-radius: 8px !important; color: #f1f5f9 !important; padding: 6px 10px !important; font-size: 10px !important; font-weight: 700 !important; cursor: pointer !important; display: flex !important; justify-content: space-between !important; align-items: center !important; height: 30px !important; } 
        .h-custom-arrow { font-size: 9px !important; color: #38bdf8 !important; transition: transform .2s ease !important; } 
        .h-custom-select.is-open .h-custom-arrow { transform: rotate(-180deg) !important; } 
        .h-custom-options { display: none; position: relative !important; z-index: 100 !important; flex-direction: column !important; background: rgba(15,23,42,0.98) !important; border: 1px solid rgba(255,255,255,.2) !important; border-radius: 8px !important; max-height: 160px !important; overflow-y: auto !important; margin-top: 4px !important; } 
        .h-custom-select.is-open .h-custom-options { display: flex !important; } 
        .h-custom-opt { padding: 6px 10px !important; color: #cbd5e1 !important; font-size: 10px !important; cursor: pointer !important; border-bottom: 1px solid rgba(255,255,255,.05) !important; } 
        .h-custom-opt:hover, .h-custom-opt.is-selected { background: rgba(56,189,248,.2) !important; color: #38bdf8 !important; font-weight: 700 !important; }
        
        .panel-header { font-weight: 800 !important; font-size: 11px !important; border-bottom: 1px solid rgba(255,255,255,.12) !important; padding-bottom: 6px !important; display: flex !important; justify-content: space-between !important; align-items: center !important; margin-bottom: 2px !important; color: #f8fafc !important; }
        .list-item { font-size: 10px !important; background: rgba(255,255,255,.04) !important; border: 1px solid rgba(255,255,255,.08) !important; border-radius: 6px !important; padding: 4px 6px !important; display: flex !important; justify-content: space-between !important; align-items: center !important; gap: 6px !important; } 
        .list-item span.rule-text { word-break: break-all !important; color: #e2e8f0 !important; font-family: monospace !important; font-size: 9px !important; flex: 1 !important; overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; } 
        .hider-btn-small { cursor: pointer !important; border: none !important; border-radius: 4px !important; padding: 2px 6px !important; color: #fff !important; font-weight: 700 !important; font-size: 9px !important; height: 20px !important; display: flex; align-items: center; justify-content: center; } 
        `;
        const container = doc.createElement('div');
        container.innerHTML = `
        <div class="h-glass h-dock is-collapsed manual-hidden" id="hider-main-dock">
            <button class="h-dock-btn h-dock-main" id="btn-toggle-dock" title="Toggle Control Dock">🛡️</button>
            <div class="h-dock-menu" id="hider-dock-menu">
                <button class="h-dock-btn" id="btn-select" title="Target Element to Hide">🎯<span>Hide</span></button>
                <button class="h-dock-btn" id="btn-scope" title="Toggle Scope (Site/Page)">🌐<span>SITE</span></button>
                <button class="h-dock-btn" id="btn-reveal-quick" title="Reveal hidden/blurred elements">👁️<span>Reveal</span></button>
                <button class="h-dock-btn" id="btn-links" title="Extract all links from the page">🔗<span>Links</span></button>
                <button class="h-dock-btn" id="btn-skip-30" title="Skip 30 seconds forward">⏩<span>+30s</span></button>
                <button class="h-dock-btn ${isFrozen?'is-frozen':''}" id="btn-freeze" title="Toggle Navigation Freeze">❄️<span>Freeze</span></button>
                <button class="h-dock-btn" id="btn-manage" title="Open Control Panel">⚙️<span>Menu</span></button>
            </div>
        </div>

        <!-- Control Panel (two-column layout) -->
        <div id="hider-panel" class="h-glass">
            <div class="panel-header">
                <span class="title">🛡️ Hide Web Elements Pro</span>
                <button class="close-btn" id="close-p">✖</button>
            </div>
            <div class="panel-body">
                <div class="panel-sidebar" id="panel-sidebar"></div>
                <div class="panel-content" id="panel-content"></div>
            </div>
        </div>`;

        shadowRoot.innerHTML = ''; shadowRoot.appendChild(style); shadowRoot.appendChild(container);
        buildPanelTabs();
        setupShadowUIEvents();
        applyDockButtonVisibility();
        renderDockButtonOptions();

        // ---- ISOLATE PANEL EVENTS FROM MAIN PAGE ----
        const panel = shadowRoot.getElementById('hider-panel');
        if (panel) {
            const stopProp = (e) => e.stopPropagation();
            panel.addEventListener('wheel', stopProp, { passive: true, capture: true });
            panel.addEventListener('touchmove', stopProp, { passive: true, capture: true });
            panel.addEventListener('scroll', stopProp, { passive: true, capture: true });
            panel.addEventListener('pointerdown', stopProp, { capture: true });
            panel.addEventListener('mousedown', stopProp, { capture: true });
        }
        const linkPanel = shadowRoot.getElementById('hider-link-panel');
        if (linkPanel) {
            const stopProp = (e) => e.stopPropagation();
            linkPanel.addEventListener('wheel', stopProp, { passive: true, capture: true });
            linkPanel.addEventListener('touchmove', stopProp, { passive: true, capture: true });
            linkPanel.addEventListener('scroll', stopProp, { passive: true, capture: true });
            linkPanel.addEventListener('pointerdown', stopProp, { capture: true });
            linkPanel.addEventListener('mousedown', stopProp, { capture: true });
        }
        const stepper = shadowRoot.getElementById(STEPPER_BAR_ID);
        if (stepper) {
            const stopProp = (e) => e.stopPropagation();
            stepper.addEventListener('wheel', stopProp, { passive: true, capture: true });
            stepper.addEventListener('touchmove', stopProp, { passive: true, capture: true });
            stepper.addEventListener('pointerdown', stopProp, { capture: true });
        }
    }

    // ---------- Build Panel Tabs ----------
    function buildPanelTabs() {
        const sidebar = shadowBy('panel-sidebar');
        const content = shadowBy('panel-content');
        if (!sidebar || !content) return;

        const tabs = [
            { id: 'tab-tools', label: '🛠️ Tools', html: `
                <div style="display:flex;flex-direction:column;gap:4px;">
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;">
                        <input type="checkbox" id="chk-auto-scroll" ${CACHE.autoScroll?'checked':''} style="accent-color:#38bdf8;"> Auto Anti‑Scroll Lock
                    </label>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;">
                        <input type="checkbox" id="chk-enable-contextmenu" ${CACHE.enableContextMenu?'checked':''} style="accent-color:#38bdf8;"> Auto Right‑Click / Long‑Press
                    </label>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;">
                        <input type="checkbox" id="chk-auto-remove-blur" ${CACHE.autoRemoveBlur?'checked':''} style="accent-color:#38bdf8;"> Auto Remove Blur
                    </label>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;margin-top:4px;">
                        <input type="checkbox" id="chk-auto-time-skipper" ${CACHE.autoTimeSkipper?'checked':''} style="accent-color:#f59e0b;"> Auto Time Skipper
                    </label>
                    <!-- Rule-breaker toggles -->
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;margin-top:4px;border-top:1px solid rgba(255,255,255,0.06);padding-top:4px;">
                        <input type="checkbox" id="chk-anti-paywall" ${CACHE.antiPaywall?'checked':''} style="accent-color:#f59e0b;"> Anti‑Paywall / Anti‑Adblock
                    </label>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;">
                        <input type="checkbox" id="chk-auto-close-modals" ${CACHE.autoCloseModals?'checked':''} style="accent-color:#f59e0b;"> Auto‑Close Modals & Overlays
                    </label>
                    <div style="display:flex;align-items:center;gap:6px;margin-top:2px;">
                        <span style="font-size:10px;color:#94a3b8;">🍪 Cookie Consent:</span>
                        <select id="cookie-consent-mode" style="background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.14);border-radius:6px;color:#fff;padding:2px 6px;font-size:9px;height:22px;flex:1;">
                            <option value="ask" ${CACHE.cookieConsentMode === 'ask' ? 'selected' : ''}>Ask</option>
                            <option value="accept" ${CACHE.cookieConsentMode === 'accept' ? 'selected' : ''}>Accept</option>
                            <option value="reject" ${CACHE.cookieConsentMode === 'reject' ? 'selected' : ''}>Reject</option>
                        </select>
                    </div>
                    <div style="margin-top:4px;border-top:1px solid rgba(255,255,255,0.06);padding-top:4px;">
                        <div style="font-size:10px;color:#94a3b8;margin-bottom:2px;">❄️ Freeze Behaviour</div>
                        <div class="h-custom-select" id="freeze-custom-panel-dropdown">
                            <div class="h-custom-trigger"><span class="h-custom-value-text">${FREEZE_LABELS[CACHE.freezeMemory] || FREEZE_LABELS['ask']}</span><span class="h-custom-arrow">▼</span></div>
                            <div class="h-custom-options">
                                <div class="h-custom-opt" data-val="ask">❓ Ask Every Time</div>
                                <div class="h-custom-opt" data-val="block_all">⛔ Auto‑Block All</div>
                                <div class="h-custom-opt" data-val="allow_same">🔗 Allow Same Domain Only</div>
                                <div class="h-custom-opt" data-val="allow_all">🟢 Allow All</div>
                            </div>
                        </div>
                        <button id="btn-reset-block-confirm" class="hider-btn-small" style="background:rgba(255,255,255,0.06);color:#cbd5e1;margin-top:4px;width:100%;padding:4px;height:auto;font-size:9px;">Reset "Don't Ask Block" Prompt</button>
                        <button id="btn-undo-hide" class="hider-btn-small" style="background:rgba(255,255,255,0.06);color:#cbd5e1;margin-top:4px;width:100%;padding:4px;height:auto;font-size:9px;">↩️ Undo Last Hide</button>
                    </div>
                    <div style="margin-top:4px;border-top:1px solid rgba(255,255,255,0.06);padding-top:4px;">
                        <div style="font-size:10px;color:#94a3b8;margin-bottom:2px;">🔘 Dock Button Visibility</div>
                        <div id="dock-buttons-list" style="display:flex;flex-direction:column;gap:4px;"></div>
                    </div>
                </div>
            ` },
            { id: 'tab-rules', label: '✏️ Rules', html: `
                <div style="display:flex;flex-direction:column;gap:4px;">
                    <div style="display:flex;gap:4px;">
                        <input type="text" id="manual-rule-input" placeholder="CSS Selector (e.g. .ad-banner)" class="h-select" style="flex:1;">
                        <input type="text" id="manual-target-input" placeholder="Target Domain (* Global)" class="h-select" style="flex:1;">
                        <button class="hider-btn-small btn-blue" id="save-rule-btn" style="height:28px;padding:0 8px;">Save</button>
                    </div>
                    <!-- Bulk Add -->
                    <div style="display:flex;gap:4px;margin-top:2px;">
                        <textarea id="bulk-rules-input" placeholder="Paste multiple selectors (one per line)" style="flex:1;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);border-radius:6px;color:#fff;padding:4px 6px;font-size:9px;height:40px;resize:vertical;"></textarea>
                        <button class="hider-btn-small btn-purple" id="bulk-add-rules" style="height:40px;padding:0 8px;">➕ Bulk Add</button>
                    </div>
                    <div style="display:flex;flex-direction:column;gap:4px;">
                        <div style="display:flex;justify-content:space-between;font-size:10px;color:#94a3b8;">
                            <span>Custom Rules (<span id="cnt-custom">0</span>)</span>
                            <button class="hider-btn-small btn-red" id="clear-custom-rules" style="font-size:8px;padding:1px 5px;height:18px;">Clear All</button>
                        </div>
                        <div id="list-custom-rules" style="display:flex;flex-direction:column;gap:3px;"></div>
                    </div>
                    <div style="border-top:1px solid rgba(255,255,255,0.06);padding-top:4px;">
                        <div style="display:flex;justify-content:space-between;font-size:10px;color:#94a3b8;">
                            <span>🌐 Site‑Wide (<span id="cnt-site">0</span>)</span>
                            <button class="hider-btn-small btn-red" id="clear-site-rules" style="font-size:8px;padding:1px 5px;height:18px;">Clear All</button>
                        </div>
                        <div id="list-site" style="display:flex;flex-direction:column;gap:3px;"></div>
                    </div>
                    <div style="border-top:1px solid rgba(255,255,255,0.06);padding-top:4px;">
                        <div style="display:flex;justify-content:space-between;font-size:10px;color:#94a3b8;">
                            <span>📄 Page‑Only (<span id="cnt-link">0</span>)</span>
                            <button class="hider-btn-small btn-red" id="clear-page-rules" style="font-size:8px;padding:1px 5px;height:18px;">Clear All</button>
                        </div>
                        <div id="list-link" style="display:flex;flex-direction:column;gap:3px;"></div>
                    </div>
                </div>
            ` },
            { id: 'tab-domains', label: '🌐 Domains', html: `
                <div style="display:flex;flex-direction:column;gap:6px;">
                    <div style="display:flex;gap:4px;">
                        <input type="text" id="manual-domain-input" placeholder="Block domain (e.g. bad.com)" class="h-select" style="flex:1;">
                        <button class="hider-btn-small btn-red" id="add-domain-btn" style="height:28px;padding:0 8px;">Block</button>
                    </div>
                    <div>
                        <div style="font-size:10px;color:#f87171;font-weight:700;margin-bottom:2px;">🚫 Blocked Domains</div>
                        <div id="list-blocked-domains" style="display:flex;flex-direction:column;gap:3px;"></div>
                    </div>
                    <div style="border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">
                        <div style="display:flex;gap:4px;">
                            <input type="text" id="manual-allowed-domain-input" placeholder="Allow domain (e.g. trusted.com)" class="h-select" style="flex:1;">
                            <button class="hider-btn-small btn-green" id="add-allowed-domain-btn" style="height:28px;padding:0 8px;">Allow</button>
                        </div>
                        <div>
                            <div style="font-size:10px;color:#34d399;font-weight:700;margin-top:4px;margin-bottom:2px;">🟢 Allowed Domains</div>
                            <div id="list-allowed-domains" style="display:flex;flex-direction:column;gap:3px;"></div>
                        </div>
                    </div>
                </div>
            ` },
            { id: 'tab-logs', label: '📋 Logs', html: `
                <div style="display:flex;justify-content:space-between;align-items:center;">
                    <span style="font-size:10px;color:#94a3b8;">Blocked (<span id="cnt-logs">0</span>)</span>
                    <button class="hider-btn-small btn-gray" id="clear-log-btn" style="font-size:8px;padding:1px 5px;height:18px;">Clear</button>
                </div>
                <div id="list-blocked-log" style="display:flex;flex-direction:column;gap:3px;margin-top:4px;"></div>
            ` },
            { id: 'tab-export', label: '💾 Export', html: `
                <div style="display:flex;gap:4px;flex-wrap:wrap;align-items:center;">
                    <button class="hider-btn-small btn-blue" id="btn-export-settings" style="flex:1;min-width:70px;height:26px;">📤 Export All</button>
                    <button class="hider-btn-small btn-green" id="btn-import-settings" style="flex:1;min-width:70px;height:26px;">📥 Import All</button>
                    <input type="file" id="import-file-input" accept=".json" style="display:none;">
                </div>
                <div style="font-size:9px;color:#94a3b8;margin-top:4px;">Export/Import all settings (rules, domains, toggles, logs).</div>
                <div style="margin-top:8px;border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">
                    <div style="font-size:10px;color:#94a3b8;margin-bottom:4px;">🍪 Cookie Manager</div>
                    <div style="display:flex;gap:4px;margin-bottom:4px;">
                        <button class="hider-btn-small btn-blue" id="cookie-refresh" style="flex:1;height:24px;">🔄 Refresh</button>
                        <button class="hider-btn-small btn-green" id="cookie-export" style="flex:1;height:24px;">📤 Export</button>
                        <button class="hider-btn-small btn-purple" id="cookie-import" style="flex:1;height:24px;">📥 Import</button>
                        <input type="file" id="cookie-import-file" accept=".json" style="display:none;">
                    </div>
                    <div style="display:flex;gap:4px;margin-bottom:4px;">
                        <input type="text" id="cookie-new-name" placeholder="name" style="flex:1;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);border-radius:6px;color:#fff;padding:2px 6px;font-size:9px;height:22px;">
                        <input type="text" id="cookie-new-value" placeholder="value" style="flex:1;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);border-radius:6px;color:#fff;padding:2px 6px;font-size:9px;height:22px;">
                        <button class="hider-btn-small btn-green" id="cookie-add" style="height:22px;padding:0 8px;">Add</button>
                    </div>
                    <div id="cookie-list" style="display:flex;flex-direction:column;gap:3px;max-height:180px;overflow-y:auto;"></div>
                </div>
            ` },
            { id: 'tab-about', label: 'ℹ️ About', html: `
                <div style="font-size:10px;color:#cbd5e1;line-height:1.6;padding:4px 0;">
                    <h3 style="font-size:11px;font-weight:800;color:#f8fafc;margin:0 0 6px 0;">🛡️ Hide Web Elements Pro</h3>
                    <p> A powerful element hider with advanced navigation control, media extraction, and automatic challenge protection.</p>
                    
                    <h4 style="font-size:10px;font-weight:700;color:#94a3b8;margin:8px 0 4px 0;">✨ Core Features</h4>
                    <ul style="margin:0;padding-left:16px;">
                        <li><strong>🎯 Hide</strong> – Click any element to hide it (site‑wide, page‑only, or global).</li>
                        <li><strong>❄️ Freeze</strong> – Block or allow navigation popups/redirects with fine‑grained rules.</li>
                        <li><strong>🔗 Link Extractor</strong> – Scan the page for all links, with media preview and download.</li>
                        <li><strong>⏩ Time Skipper</strong> – Jump forward 30 seconds on videos/audio and skip timers.</li>
                        <li><strong>👁️ Reveal</strong> – Unhide hidden/blurred elements (overlays, modals, etc.).</li>
                        <li><strong>📥 Media Downloader</strong> – Direct download of images, videos, and audio from extracted links.</li>
                        <li><strong>🛡️ Automatic Protection</strong> – Detects Cloudflare/challenge pages and temporarily disables features to avoid interference.</li>
                        <li><strong>🚫 Anti‑Paywall</strong> – Removes paywall and adblock overlays automatically.</li>
                        <li><strong>🗑️ Auto‑Close Modals</strong> – Dismisses cookie banners, newsletters, and popups.</li>
                        <li><strong>🍪 Cookie Bypass</strong> – Accepts or rejects cookies automatically based on your choice.</li>
                    </ul>

                    <h4 style="font-size:10px;font-weight:700;color:#94a3b8;margin:8px 0 4px 0;">🔒 Protection Logic</h4>
                    <p>The script automatically pauses all hiding/freezing/scroll‑override features when it detects a Cloudflare challenge, "Just a moment..." page, or other anti‑bot screens. This ensures that the script never interferes with the challenge process. Once the page loads normally, features resume instantly.</p>

                    <h4 style="font-size:10px;font-weight:700;color:#94a3b8;margin:8px 0 4px 0;">💾 Persistent Storage</h4>
                    <p>All rules, domains, freeze settings, and logs are saved locally (via GM_setValue or localStorage). Your customisations persist across browser restarts and site visits.</p>

                    <h4 style="font-size:10px;font-weight:700;color:#94a3b8;margin:8px 0 4px 0;">⌨️ Keyboard Shortcuts</h4>
                    <ul style="margin:0;padding-left:16px;">
                        <li><kbd>Esc</kbd> – Cancel selection mode / close panels.</li>
                        <li><kbd>Ctrl+Click</kbd> / <kbd>Middle‑click</kbd> – Bypass freeze for that link.</li>
                    </ul>

                    <p style="margin-top:8px;font-size:9px;color:#64748b;">Made with ❤️ by KTZ • Open Source under MIT</p>
                </div>
            ` }
        ];

        tabs.forEach((tab, index) => {
            const btn = document.createElement('button');
            btn.className = 'tab-btn' + (index === 0 ? ' active' : '');
            btn.dataset.tab = tab.id;
            btn.textContent = tab.label;
            btn.title = tab.label;
            sidebar.appendChild(btn);

            const contentDiv = document.createElement('div');
            contentDiv.className = 'tab-content' + (index === 0 ? ' active' : '');
            contentDiv.id = tab.id;
            contentDiv.innerHTML = tab.html;
            content.appendChild(contentDiv);
        });

        sidebar.addEventListener('click', (e) => {
            const btn = e.target.closest('.tab-btn');
            if (!btn) return;
            const tabId = btn.dataset.tab;
            sidebar.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
            content.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
            btn.classList.add('active');
            const contentDiv = content.querySelector('#' + tabId);
            if (contentDiv) contentDiv.classList.add('active');
        });
    }

    // ---------- Shadow UI Events ----------
    function setupShadowUIEvents() {
        shadowBy('close-p').onclick = e => { if (e) { e.stopPropagation(); e.preventDefault(); } turnOffHideMode(); closeAllMenus(e, true); };

        setupCustomDropdown(shadowBy('freeze-custom-panel-dropdown'), CACHE.freezeMemory, val => {
            CACHE.freezeMemory = val; sv('hider_freeze_memory', val);
            const label = FREEZE_LABELS[val] || val;
            if (val === 'allow_all') { disableFreezeMode(); showToast(`🟢 Freeze Mode Disabled (Allow All)`); } 
            else showToast(`❄️ Memory updated: ${label}`);
        });

        shadowBy('btn-reset-block-confirm').onclick = () => { sv('hider_skip_block_confirm', false); showToast('🔄 Reset Block Domain confirmation!'); };
        shadowBy('btn-undo-hide').onclick = undoLastHide;

        // Rule-breaker toggles
        const chkPaywall = shadowBy('chk-anti-paywall');
        if (chkPaywall) {
            chkPaywall.onchange = e => {
                CACHE.antiPaywall = e.target.checked;
                sv('hider_anti_paywall', CACHE.antiPaywall);
                applyAllSettings();
                showToast(`🚫 Anti-Paywall: ${CACHE.antiPaywall ? 'ON' : 'OFF'}`);
            };
        }

        const chkModal = shadowBy('chk-auto-close-modals');
        if (chkModal) {
            chkModal.onchange = e => {
                CACHE.autoCloseModals = e.target.checked;
                sv('hider_auto_close_modals', CACHE.autoCloseModals);
                applyAllSettings();
                showToast(`🗑️ Auto-Close Modals: ${CACHE.autoCloseModals ? 'ON' : 'OFF'}`);
            };
        }

        const cookieMode = shadowBy('cookie-consent-mode');
        if (cookieMode) {
            cookieMode.onchange = e => {
                CACHE.cookieConsentMode = e.target.value;
                sv('hider_cookie_consent_mode', CACHE.cookieConsentMode);
                applyAllSettings();
                showToast(`🍪 Cookie mode: ${CACHE.cookieConsentMode === 'accept' ? 'Accept' : CACHE.cookieConsentMode === 'reject' ? 'Reject' : 'Ask'}`);
            };
        }

        const chkScroll = shadowBy('chk-auto-scroll');
        if (chkScroll) {
            chkScroll.onchange = e => {
                CACHE.autoScroll = e.target.checked;
                sv('hider_auto_scroll', CACHE.autoScroll);
                if (CACHE.autoScroll) {
                    startScrollDefeater();
                    showToast('🔓 Auto Anti-Scroll Lock enabled');
                } else {
                    stopScrollDefeater();
                    showToast('🔒 Auto Anti-Scroll Lock disabled');
                }
            };
        }

        const chkContext = shadowBy('chk-enable-contextmenu');
        if (chkContext) {
            chkContext.onchange = e => {
                CACHE.enableContextMenu = e.target.checked;
                sv('hider_enable_contextmenu', CACHE.enableContextMenu);
                updateContextMenuStyles();
                showToast(`🖱️ Auto Right-Click/Long-Press: ${CACHE.enableContextMenu ? 'ON' : 'OFF'}`);
            };
        }

        const chkBlur = shadowBy('chk-auto-remove-blur');
        if (chkBlur) {
            chkBlur.onchange = e => {
                CACHE.autoRemoveBlur = e.target.checked;
                sv('hider_auto_remove_blur', CACHE.autoRemoveBlur);
                if (CACHE.autoRemoveBlur) {
                    scheduleBlurRemoval();
                    showToast('👁️ Auto Remove Blur enabled (aggressive)');
                } else {
                    stopBlurRemoval();
                    showToast('👁️ Auto Remove Blur disabled');
                }
            };
        }

        const autoSkipChk = shadowBy('chk-auto-time-skipper');
        if (autoSkipChk) {
            autoSkipChk.onchange = e => {
                CACHE.autoTimeSkipper = e.target.checked;
                sv('hider_auto_time_skipper', CACHE.autoTimeSkipper);
                if (CACHE.autoTimeSkipper) {
                    autoSkipTimers();
                    showToast('⏩ Auto Time Skipper enabled');
                } else {
                    showToast('⏩ Auto Time Skipper disabled');
                }
            };
        }

        const dockEl = shadowBy('hider-main-dock'), mainBtn = shadowBy('btn-toggle-dock');
        const savedY = gv('hider_dock_y', null); if (savedY) dockEl.style.top = savedY;
        dockEl.addEventListener('mouseleave', () => dockEl.classList.remove('manual-hidden'));

        let dockStartX, dockStartY, dockInitY, dockMoved = false;
        const onDockMove = e => {
            if (!isDraggingDock) return;
            const p = e.touches ? e.touches[0] : e, dy = p.clientY - dockStartY;
            if (Math.hypot(p.clientX - dockStartX, dy) > 8) {
                dockMoved = true; if (e.cancelable) e.preventDefault();
                dockEl.style.top = `${Math.max(0, Math.min(dockInitY + dy, win.innerHeight - dockEl.offsetHeight))}px`;
            }
        };

        const onDockEnd = () => {
            if (isDraggingDock) { isDraggingDock = false; dockEl.style.transition = ''; if (dockMoved) sv('hider_dock_y', dockEl.style.top); }
            win.removeEventListener('mousemove', onDockMove); win.removeEventListener('mouseup', onDockEnd);
            win.removeEventListener('touchmove', onDockMove); win.removeEventListener('touchend', onDockEnd); win.removeEventListener('touchcancel', onDockEnd);
        };

        const onDockStart = e => {
            if (e.target.tagName === 'BUTTON' && e.target.id !== 'btn-toggle-dock') return;
            const p = e.touches ? e.touches[0] : e;
            dockStartX = p.clientX; dockStartY = p.clientY; dockInitY = dockEl.getBoundingClientRect().top;
            isDraggingDock = true; dockMoved = false; dockEl.style.transition = 'none';
            win.addEventListener('mousemove', onDockMove, { passive: false }); win.addEventListener('mouseup', onDockEnd);
            win.addEventListener('touchmove', onDockMove, { passive: false }); win.addEventListener('touchend', onDockEnd); win.addEventListener('touchcancel', onDockEnd);
        };
        mainBtn.addEventListener('mousedown', onDockStart, { passive: false });
        mainBtn.addEventListener('touchstart', onDockStart, { passive: false });

        mainBtn.onclick = e => {
            e.stopPropagation(); if (dockMoved) { dockMoved = false; return; }
            if (timers.collapseTimer) { clearTimeout(timers.collapseTimer); timers.collapseTimer = null; }
            const menu = shadowBy('hider-dock-menu'), isOpening = !menu.classList.contains('is-open');
            
            menu.classList.toggle('is-open', isOpening); 
            mainBtn.classList.toggle('expanded', isOpening); 
            dockEl.classList.toggle('expanded', isOpening); 
            dockEl.classList.toggle('is-collapsed', !isOpening);

            if (!isOpening) {
                turnOffHideMode(); 
                const panel = shadowBy('hider-panel');
                if (panel.classList.contains('is-visible')) { panel.classList.remove('is-visible'); setTimeout(()=> panel.style.display='none', 300); }
                shadowBy('btn-manage')?.classList.remove('active'); 
                dockEl.classList.add('manual-hidden');
                timers.collapseTimer = setTimeout(() => { dockEl.classList.add('is-collapsed'); timers.collapseTimer = null; }, 1000);
            } else dockEl.classList.remove('manual-hidden');
        };

        shadowBy('btn-reveal-quick').onclick = (e) => {
            e.stopPropagation();
            revealHiddenElements();
        };

        shadowBy('btn-links').onclick = (e) => {
            e.stopPropagation();
            toggleLinkPanel();
        };

        shadowBy('btn-skip-30').onclick = (e) => {
            e.stopPropagation();
            skip30Seconds();
        };

        // Bulk add rules
        shadowBy('bulk-add-rules').onclick = () => {
            const textarea = shadowBy('bulk-rules-input');
            if (!textarea) return;
            const selectors = textarea.value.split('\n').map(s => s.trim()).filter(s => s.length > 0);
            if (selectors.length === 0) { showToast('⚠️ Enter at least one selector'); return; }
            let added = 0;
            selectors.forEach(sel => {
                // Ensure selector doesn't target body/html
                if (sel.match(/^(html|body)/i)) {
                    showToast('⚠️ Skipping selector targeting body/html');
                    return;
                }
                const rule = { id: 'rule_' + Date.now() + '_' + Math.random().toString(36).substr(2, 4), selector: sel, target: '*' };
                CACHE.customRules.push(rule);
                added++;
            });
            sv('hider_custom_rules_v4', CACHE.customRules);
            textarea.value = '';
            requestUpdateStyles();
            renderList();
            showToast(`➕ Added ${added} global rules`);
        };

        shadowBy('save-rule-btn').onclick = () => {
            const ruleInput = shadowBy('manual-rule-input'), targetInput = shadowBy('manual-target-input'), sel = (ruleInput.value || '').trim(), target = cleanDomain(targetInput.value) || '*';
            if (!sel) { showToast('⚠️ Enter a selector'); return; }
            if (sel.match(/^(html|body)/i)) { showToast('⚠️ Cannot hide body or html'); return; }
            if (editingRuleId) {
                const idx = CACHE.customRules.findIndex(r => r.id === editingRuleId);
                if (idx !== -1) { CACHE.customRules[idx] = { id: editingRuleId, selector: sel, target: target }; showToast('✏️ Rule updated'); }
                editingRuleId = null; shadowBy('save-rule-btn').textContent = 'Save';
            } else { CACHE.customRules.push({ id: 'rule_' + Date.now(), selector: sel, target: target }); showToast('✨ Custom Rule Added!'); }
            sv('hider_custom_rules_v4', CACHE.customRules); ruleInput.value = ''; targetInput.value = ''; requestUpdateStyles(); renderList();
        };

        const addAllowedDomain = () => {
            const input = shadowBy('manual-allowed-domain-input'), d = cleanDomain(input.value);
            if (d && !CACHE.allowedDomainsSet.has(d)) { CACHE.allowedDomainsList.push(d); CACHE.allowedDomainsSet.add(d); sv('hider_allowed_domains', CACHE.allowedDomainsList); showToast(`🟢 Allowed: ${d}`); }
            input.value = ''; renderList();
        };
        shadowBy('add-allowed-domain-btn').onclick = addAllowedDomain; shadowBy('manual-allowed-domain-input').onkeypress = e => e.key === 'Enter' && addAllowedDomain();

        const addDomain = () => {
            const input = shadowBy('manual-domain-input'), d = cleanDomain(input.value);
            if (d && !CACHE.blockedDomainsSet.has(d)) { CACHE.blockedDomainsList.push(d); CACHE.blockedDomainsSet.add(d); sv('hider_blocked_domains', CACHE.blockedDomainsList); showToast(`🚫 Blocked: ${d}`); }
            input.value = ''; renderList();
        };
        shadowBy('add-domain-btn').onclick = addDomain; shadowBy('manual-domain-input').onkeypress = e => e.key === 'Enter' && addDomain();

        shadowBy('btn-select').onclick = e => {
            e.stopPropagation(); isSelecting = !isSelecting; e.currentTarget.classList.toggle('active', isSelecting);
            const p = shadowBy('hider-panel');
            if (isSelecting) { 
                if(p.classList.contains('is-visible')) { p.classList.remove('is-visible'); setTimeout(()=> p.style.display='none', 300); } shadowBy('btn-manage').classList.remove('active'); 
                showToast('🎯 Selection mode ON – Click element to hide (or use Global)');
            } else {
                clearSelectionState();
                showToast('🎯 Selection mode OFF');
            }
            broadcastState();
        };

        const btnScope = shadowBy('btn-scope');
        btnScope.onclick = e => {
            e.stopPropagation(); currentScope = currentScope === 'site' ? 'link' : 'site'; btnScope.querySelector('span').textContent = currentScope.toUpperCase();
            btnScope.classList.toggle('scope-link', currentScope === 'link'); 
            const label = currentScope === 'site' ? '🌐 Site-wide' : '📄 Page-only';
            showToast(`Scope: ${label}`); broadcastState();
        };

        const btnFreeze = shadowBy('btn-freeze');
        btnFreeze.onclick = e => {
            e.stopPropagation(); isFrozen = !isFrozen; CACHE.isFrozen = isFrozen; sv('hider_freeze_global', isFrozen);
            if (isFrozen && CACHE.freezeMemory === 'allow_all') { CACHE.freezeMemory = 'ask'; sv('hider_freeze_memory', 'ask'); }
            btnFreeze.classList.toggle('is-frozen', isFrozen); if (isFrozen) triggerFreezeFx(); 
            showToast(isFrozen ? '🥶 Freeze ON' : '🔥 Freeze OFF'); broadcastState();
        };

        shadowBy('btn-manage').onclick = e => {
            e.stopPropagation(); const p = shadowBy('hider-panel'), isHidden = p.style.display === 'none' || p.style.display === '';
            
            if (isHidden) {
                p.style.display = 'flex';
                void p.offsetWidth;
                p.classList.add('is-visible');
                e.currentTarget.classList.add('active');
                turnOffHideMode(); renderList();
            } else {
                p.classList.remove('is-visible');
                setTimeout(() => p.style.display = 'none', 300);
                e.currentTarget.classList.remove('active');
            }
        };

        shadowBy('clear-log-btn').onclick = e => { if (e) e.stopPropagation(); CACHE.logs = []; sv('hider_global_logs', []); renderList(); showToast('🧹 Logs cleared'); };

        // Clear All Rules
        shadowBy('clear-custom-rules').onclick = () => {
            if (confirm('Delete all custom rules?')) {
                CACHE.customRules = [];
                sv('hider_custom_rules_v4', CACHE.customRules);
                renderList(); requestUpdateStyles();
                showToast('🧹 Custom rules cleared');
            }
        };
        shadowBy('clear-site-rules').onclick = () => {
            const key = 'hider_site_' + location.hostname;
            if (confirm('Delete all site-wide rules?')) {
                sv(key, []);
                renderList(); requestUpdateStyles();
                showToast('🧹 Site rules cleared');
            }
        };
        shadowBy('clear-page-rules').onclick = () => {
            const key = 'hider_link_' + cleanUrl();
            if (confirm('Delete all page-only rules?')) {
                sv(key, []);
                renderList(); requestUpdateStyles();
                showToast('🧹 Page rules cleared');
            }
        };

        // Export/Import
        const exportBtn = shadowBy('btn-export-settings');
        const importBtn = shadowBy('btn-import-settings');
        const fileInput = shadowBy('import-file-input');
        if (exportBtn) exportBtn.onclick = () => {
            const data = getAllSettings();
            const json = JSON.stringify(data, null, 2);
            const blob = new Blob([json], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `hider_backup_${new Date().toISOString().slice(0,10)}.json`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            showToast('📤 Settings exported');
        };
        if (importBtn) importBtn.onclick = () => fileInput?.click();
        if (fileInput) {
            fileInput.onchange = function() {
                if (this.files && this.files[0]) {
                    const reader = new FileReader();
                    reader.onload = function(e) {
                        try {
                            const data = JSON.parse(e.target.result);
                            let count = 0;
                            for (const [key, val] of Object.entries(data)) {
                                if (key.startsWith('hider_')) {
                                    sv(key, val);
                                    count++;
                                }
                            }
                            syncCache();
                            requestUpdateStyles();
                            renderList();
                            applyDockButtonVisibility();
                            showToast(`📥 Imported ${count} settings`);
                        } catch (err) {
                            showToast('❌ Invalid JSON file');
                        }
                    };
                    reader.readAsText(this.files[0]);
                    this.value = '';
                }
            };
        }

        // Cookie Manager
        const cookieRefresh = shadowBy('cookie-refresh');
        const cookieExport = shadowBy('cookie-export');
        const cookieImport = shadowBy('cookie-import');
        const cookieFileInput = shadowBy('cookie-import-file');
        const cookieAdd = shadowBy('cookie-add');
        const cookieName = shadowBy('cookie-new-name');
        const cookieValue = shadowBy('cookie-new-value');

        function getCookies() {
            return document.cookie.split(';').map(c => c.trim()).filter(Boolean).map(c => {
                const eq = c.indexOf('=');
                return { name: c.slice(0, eq), value: c.slice(eq + 1) };
            });
        }

        function renderCookies() {
            const list = shadowBy('cookie-list');
            if (!list) return;
            const cookies = getCookies();
            if (cookies.length === 0) {
                list.innerHTML = '<div style="font-size:9px;color:#94a3b8;text-align:center;padding:4px;">No cookies for this domain.</div>';
                return;
            }
            list.innerHTML = '';
            cookies.forEach((c, idx) => {
                const row = document.createElement('div');
                row.style.cssText = 'display:flex;align-items:center;gap:4px;font-size:9px;padding:2px 4px;background:rgba(255,255,255,.04);border-radius:4px;';
                const nameSpan = document.createElement('span');
                nameSpan.textContent = c.name;
                nameSpan.style.cssText = 'font-weight:700;color:#38bdf8;min-width:60px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
                const valSpan = document.createElement('span');
                valSpan.textContent = c.value;
                valSpan.style.cssText = 'flex:1;color:#e2e8f0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
                const btnGroup = document.createElement('div');
                btnGroup.style.cssText = 'display:flex;gap:2px;flex-shrink:0;';
                const editBtn = document.createElement('button');
                editBtn.className = 'hider-btn-small btn-blue';
                editBtn.textContent = '✏️';
                editBtn.style.cssText = 'padding:0 4px;height:16px;font-size:7px;';
                editBtn.onclick = function(e) {
                    e.stopPropagation();
                    const newVal = prompt(`Edit value for "${c.name}":`, c.value);
                    if (newVal !== null) {
                        document.cookie = `${c.name}=${newVal}; path=/; domain=${location.hostname}`;
                        renderCookies();
                        showToast(`🍪 Updated cookie: ${c.name}`);
                    }
                };
                const delBtn = document.createElement('button');
                delBtn.className = 'hider-btn-small btn-red';
                delBtn.textContent = '✖';
                delBtn.style.cssText = 'padding:0 4px;height:16px;font-size:7px;';
                delBtn.onclick = function(e) {
                    e.stopPropagation();
                    if (confirm(`Delete cookie "${c.name}"?`)) {
                        document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${location.hostname}`;
                        renderCookies();
                        showToast(`🍪 Deleted cookie: ${c.name}`);
                    }
                };
                btnGroup.appendChild(editBtn);
                btnGroup.appendChild(delBtn);
                row.appendChild(nameSpan);
                row.appendChild(valSpan);
                row.appendChild(btnGroup);
                list.appendChild(row);
            });
        }

        if (cookieAdd) {
            cookieAdd.onclick = function() {
                const name = cookieName ? cookieName.value.trim() : '';
                const value = cookieValue ? cookieValue.value.trim() : '';
                if (!name) { showToast('⚠️ Enter cookie name'); return; }
                document.cookie = `${name}=${value}; path=/; domain=${location.hostname}`;
                renderCookies();
                if (cookieName) cookieName.value = '';
                if (cookieValue) cookieValue.value = '';
                showToast(`🍪 Added cookie: ${name}`);
            };
        }
        if (cookieName) cookieName.onkeypress = e => e.key === 'Enter' && cookieAdd?.click();
        if (cookieValue) cookieValue.onkeypress = e => e.key === 'Enter' && cookieAdd?.click();
        if (cookieRefresh) cookieRefresh.onclick = renderCookies;
        if (cookieExport) {
            cookieExport.onclick = function() {
                const cookies = getCookies();
                const json = JSON.stringify(cookies, null, 2);
                const blob = new Blob([json], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `cookies_${location.hostname}_${new Date().toISOString().slice(0,10)}.json`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
                showToast('🍪 Cookies exported');
            };
        }
        if (cookieImport) cookieImport.onclick = () => cookieFileInput?.click();
        if (cookieFileInput) {
            cookieFileInput.onchange = function() {
                if (this.files && this.files[0]) {
                    const reader = new FileReader();
                    reader.onload = function(e) {
                        try {
                            const cookies = JSON.parse(e.target.result);
                            if (!Array.isArray(cookies)) throw new Error('Not an array');
                            cookies.forEach(c => {
                                if (c.name && c.value !== undefined) {
                                    document.cookie = `${c.name}=${c.value}; path=/; domain=${location.hostname}`;
                                }
                            });
                            renderCookies();
                            showToast(`🍪 Imported ${cookies.length} cookies`);
                        } catch (err) {
                            showToast('❌ Invalid cookie JSON');
                        }
                    };
                    reader.readAsText(this.files[0]);
                    this.value = '';
                }
            };
        }

        function getAllSettings() {
            const settings = {};
            const knownKeys = [
                'hider_freeze_memory', 'hider_freeze_global', 'hider_blocked_domains',
                'hider_allowed_domains', 'hider_custom_rules_v4', 'hider_auto_time_skipper',
                'hider_auto_scroll', 'hider_enable_contextmenu', 'hider_auto_remove_blur',
                'hider_hidden_dock_buttons', 'hider_global_logs',
                'hider_last_log_clear_day', 'hider_skip_block_confirm', 'hider_dock_y',
                'hider_anti_paywall', 'hider_auto_close_modals', 'hider_cookie_consent_mode'
            ];
            knownKeys.forEach(k => {
                const val = gv(k, undefined);
                if (val !== undefined) settings[k] = val;
            });
            try {
                for (let i = 0; i < localStorage.length; i++) {
                    const key = localStorage.key(i);
                    if (key && (key.startsWith('hider_site_') || key.startsWith('hider_link_'))) {
                        const val = localStorage.getItem(key);
                        try { settings[key] = JSON.parse(val); } catch { settings[key] = val; }
                    }
                }
            } catch {}
            return settings;
        }
    }

    // ---------- Render List ----------
    function renderList() {
        if (!shadowRoot) return;
        if (!CACHE.logs) CACHE.logs = gv('hider_global_logs', []);
        const siteKey = 'hider_site_' + location.hostname, linkKey = 'hider_link_' + cleanUrl();
        const siteData = gv(siteKey, []), linkData = gv(linkKey, []);

        const cCustom = shadowBy('list-custom-rules'), cAllowed = shadowBy('list-allowed-domains'), cDomains = shadowBy('list-blocked-domains'), cSite = shadowBy('list-site'), cLink = shadowBy('list-link'), cLog = shadowBy('list-blocked-log');
        if (!cSite || !cLink) return;

        ['cnt-custom', 'cnt-allowed', 'cnt-domains', 'cnt-logs', 'cnt-site', 'cnt-link'].forEach((id, i) => {
            const el = shadowBy(id); 
            if(el) el.textContent = [CACHE.customRules.length, CACHE.allowedDomainsList.length, CACHE.blockedDomainsList.length, CACHE.logs.length, siteData.length, linkData.length][i];
        });

        const buildFrag = (arr, emptyMsg, renderItem) => {
            const frag = doc.createDocumentFragment();
            if (!arr.length) { const d = doc.createElement('div'); d.style.cssText = 'font-size:9px!important;color:#94a3b8!important;padding:4px!important;text-align:center!important;border:1px dashed rgba(255,255,255,0.12)!important;border-radius:6px!important;'; d.textContent = emptyMsg; frag.appendChild(d); return frag; }
            arr.forEach((item, i) => frag.appendChild(renderItem(item, i))); return frag;
        };

        if (cCustom) {
            cCustom.innerHTML = '';
            cCustom.appendChild(buildFrag(CACHE.customRules, 'No custom rules', rule => {
                const div = doc.createElement('div'); div.className = 'list-item';
                div.innerHTML = `<span class="rule-text" title="${rule.selector}">${rule.selector} <span style="color:${rule.target === '*' ? '#38bdf8' : '#34d399'}!important; font-weight:bold!important;">[${rule.target}]</span></span><div style="display:flex;gap:2px"><button class="hider-btn-small btn-blue btn-edit">✏️</button><button class="hider-btn-small btn-red btn-del">✖</button></div>`;
                div.querySelector('.btn-edit').onclick = () => {
                    editingRuleId = rule.id; shadowBy('manual-rule-input').value = rule.selector; shadowBy('manual-target-input').value = rule.target; shadowBy('save-rule-btn').textContent = 'Update';
                    const sidebar = shadowBy('panel-sidebar');
                    const content = shadowBy('panel-content');
                    if (sidebar && content) {
                        const tabBtn = sidebar.querySelector('[data-tab="tab-rules"]');
                        if (tabBtn) tabBtn.click();
                    }
                };
                div.querySelector('.btn-del').onclick = () => { 
                    CACHE.customRules = CACHE.customRules.filter(r => r.id !== rule.id); 
                    sv('hider_custom_rules_v4', CACHE.customRules); 
                    requestUpdateStyles(); renderList(); 
                    showToast('🗑️ Rule removed');
                };
                return div;
            }));
        }

        if (cAllowed) {
            cAllowed.innerHTML = '';
            cAllowed.appendChild(buildFrag(CACHE.allowedDomainsList, 'No allowed domains', (d, i) => {
                const div = doc.createElement('div'); div.className = 'list-item'; div.innerHTML = `<span class="rule-text" title="${d}">${d}</span><button class="hider-btn-small btn-red">✖</button>`;
                div.querySelector('button').onclick = () => { 
                    CACHE.allowedDomainsList.splice(i, 1); 
                    CACHE.allowedDomainsSet.delete(cleanDomain(d)); 
                    sv('hider_allowed_domains', CACHE.allowedDomainsList); 
                    renderList(); 
                    showToast('🟢 Allowed domain removed');
                };
                return div;
            }));
        }

        if (cDomains) {
            cDomains.innerHTML = '';
            cDomains.appendChild(buildFrag(CACHE.blockedDomainsList, 'No blocked domains', (d, i) => {
                const div = doc.createElement('div'); div.className = 'list-item'; div.innerHTML = `<span class="rule-text" title="${d}">${d}</span><button class="hider-btn-small btn-red">✖</button>`;
                div.querySelector('button').onclick = () => { 
                    CACHE.blockedDomainsList.splice(i, 1); 
                    CACHE.blockedDomainsSet.delete(cleanDomain(d)); 
                    sv('hider_blocked_domains', CACHE.blockedDomainsList); 
                    renderList(); 
                    showToast('🚫 Blocked domain removed');
                };
                return div;
            }));
        }

        if (cLog) {
            cLog.innerHTML = '';
            cLog.appendChild(buildFrag(CACHE.logs, 'No logs today', item => {
                const row = doc.createElement('div'); row.style.cssText = 'font-size:9px!important;border-bottom:1px solid rgba(255,255,255,0.08)!important;padding:2px 0!important;';
                row.innerHTML = `<div style="display:flex;justify-content:space-between;color:#6ee7b7!important;font-weight:700!important;"><span>${item.type}</span><span style="color:#94a3b8!important;font-weight:normal!important;">${item.time}</span></div><div style="color:#cbd5e1!important;word-break:break-all!important;font-family:monospace!important;opacity:0.8;">${item.url}</div>`; return row;
            }));
        }

        const renderEditableHiddenItems = (data, key, container) => {
            container.innerHTML = '';
            container.appendChild(buildFrag(data, 'None', (sel, i) => {
                const div = doc.createElement('div'); div.className = 'list-item';
                div.innerHTML = `<span class="rule-text" title="${sel}">${sel}</span><div style="display:flex;gap:2px;align-items:center"><button class="hider-btn-small btn-blue btn-edit" title="Edit Rule Inline">✏️</button><button class="hider-btn-small btn-purple btn-wild" title="Convert Wildcard">🪄</button><button class="hider-btn-small btn-red btn-del" title="Delete Rule">✖</button></div>`;
                const textSpan = div.querySelector('.rule-text'), editBtn = div.querySelector('.btn-edit');

                editBtn.onclick = () => {
                    if (div.classList.contains('is-editing')) return;
                    div.classList.add('is-editing');
                    const input = doc.createElement('input'); input.type = 'text'; input.value = data[i]; input.className = 'h-select'; input.style.cssText = 'font-size:9px!important;padding:2px 4px!important;height:20px!important;flex:1!important;margin-right:4px!important;';
                    const saveBtn = doc.createElement('button'); saveBtn.className = 'hider-btn-small btn-green'; saveBtn.textContent = '✓';
                    textSpan.replaceWith(input); editBtn.replaceWith(saveBtn); input.focus();

                    const saveHandler = () => {
                        const newVal = input.value.trim();
                        if (newVal) { data[i] = newVal; sv(key, data); requestUpdateStyles(); showToast('✏️ Hidden rule updated'); }
                        renderList();
                    };
                    saveBtn.onclick = saveHandler; input.onkeypress = e => e.key === 'Enter' && saveHandler();
                };

                div.querySelector('.btn-wild').onclick = () => { 
                    data[i] = convertToWildcardSelector(data[i]); 
                    sv(key, data); requestUpdateStyles(); renderList(); 
                    showToast(`🪄 Wildcard applied`);
                };
                div.querySelector('.btn-del').onclick = () => {
                    const removed = data.splice(i, 1)[0]; sv(key, data);
                    try { doc.querySelectorAll(removed).forEach(el => el.classList.remove('hider-stealth-target')); } catch {}
                    requestUpdateStyles(); renderList();
                    showToast('🗑️ Hidden rule removed');
                };
                return div;
            }));
        };

        renderEditableHiddenItems(siteData, siteKey, cSite); renderEditableHiddenItems(linkData, linkKey, cLink);

        renderDockButtonOptions();
        applyDockButtonVisibility();
    }

    // ---------- Navigation Click Handler ----------
    function handleNavigationClick(e) {
        const path = e.composedPath?.() || [];
        if (isSelecting || path.some(el => el.id === UI_HOST_ID || el.id === STEPPER_BAR_ID)) return;
        const link = e.target.closest('a[href], area[href]');
        if (link?.href) {
            const rawHref = link.getAttribute('href') || '';
            if (rawHref.startsWith('#') || rawHref.toLowerCase().startsWith('javascript:')) return;
            const targetUrl = link.href;
            if (isDomainBlocked(targetUrl)) {
                e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
                logBlockedAttempt(targetUrl, 'Blocked Link Click'); simulateAdWindowSuccess(); showToast('⛔ Force Blocked'); return;
            }
            if (!isFrozen || isDomainAllowed(targetUrl)) return;

            e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
            const isNewTab = link.target === '_blank' || e.ctrlKey || e.metaKey || e.button === 1;
            handleFreezeNavigation(targetUrl, 'Link Click', () => {
                userApprovedNavigation = true; if (isNewTab) win.open(targetUrl, '_blank'); else win.location.href = targetUrl;
                setTimeout(() => userApprovedNavigation = false, 300);
            }, simulateAdWindowSuccess);
        }
    }

    // ---------- Scroll auto-close ----------
    function setupScrollAutoClose() {
        win.addEventListener('scroll', () => {
            if (scrollAnimationFrame) return;
            scrollAnimationFrame = win.requestAnimationFrame(() => {
                scrollAnimationFrame = null;
                closeAllMenus(null);
                closePreviewModal();
            });
        }, { passive: true, capture: true });
    }

    // ---------- Keyboard shortcuts ----------
    window.addEventListener('keydown', e => { if (e.key === 'Escape') { if (isSelecting) { turnOffHideMode(); showToast('🎯 Selection mode cancelled'); } else { closeAllMenus(null, true); closePreviewModal(); } } }, true);

    // ---------- Selection mode blockers ----------
    ['mousedown', 'pointerdown', 'mouseup'].forEach(evtType => {
        window.addEventListener(evtType, e => {
            if (!isSelecting) return;
            if (e.composedPath?.().some(el => el.id === UI_HOST_ID || el.id === STEPPER_BAR_ID)) return;
            e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
        }, true);
    });

    // ---------- Click handling for selection ----------
    window.addEventListener('click', e => {
        const path = e.composedPath?.() || [];
        const isUI = path.some(el => el.id === UI_HOST_ID || el.id === STEPPER_BAR_ID);
        
        if (!isUI) { closeAllMenus(e); shadowRoot?.querySelectorAll('.h-custom-select').forEach(c => c.classList.remove('is-open')); }
        if (isUI) return;
        
        handleNavigationClick(e); 
        if (!isSelecting) return;
        
        e.preventDefault(); e.stopPropagation();
        if (previewElement === e.target) confirmHideSelectedElement(false);
        else {
            previewElement?.classList.remove('hider-preview-highlight'); stepperStack = [];
            previewElement = e.target; previewElement.classList.add('hider-preview-highlight'); renderTouchStepperUI();
        }
    }, true);

    window.addEventListener('auxclick', handleNavigationClick, true);

    window.addEventListener('submit', e => {
        const path = e.composedPath?.() || [];
        if (path.some(el => el.id === UI_HOST_ID || el.id === STEPPER_BAR_ID)) return;
        const form = e.target, action = form.action || location.href;
        if (isDomainBlocked(action)) {
            e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
            logBlockedAttempt(action, 'Blocked Form Submit'); simulateAdWindowSuccess(); showToast('⛔ Blocked Form'); return;
        }
        if (!isFrozen || isDomainAllowed(action)) return;
        e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
        handleFreezeNavigation(action, 'Form Submit', () => { userApprovedNavigation = true; form.submit(); setTimeout(() => userApprovedNavigation = false, 300); }, simulateAdWindowSuccess);
    }, true);

    window.addEventListener('touchstart', e => {
        if (!e.touches?.[0]) return;
        const x = e.touches[0].clientX;
        if (x <= 40 || x >= (win.innerWidth - 40)) { userApprovedNavigation = true; setTimeout(() => { userApprovedNavigation = false; }, 1500); }
    }, { passive: true, capture: true });

    // ---------- History navigation ----------
    ['back', 'forward', 'go'].forEach(method => {
        const orig = history[method];
        if (orig) { history[method] = function() { userApprovedNavigation = true; setTimeout(() => { userApprovedNavigation = false; }, 1000); return orig.apply(this, arguments); }; }
    });

    try { win.navigation?.addEventListener('navigate', e => { if (e.navigationType === 'traverse' || e.navigationType === 'reload') { userApprovedNavigation = true; setTimeout(() => { userApprovedNavigation = false; }, 1000); } }); } catch {}

    win.addEventListener('beforeunload', e => {
        if (userApprovedNavigation) return;
        if (isFrozen && !isDomainAllowed(location.href) && (CACHE.freezeMemory === 'ask' || CACHE.freezeMemory === 'block_all')) { e.preventDefault(); return (e.returnValue = 'Page navigation is currently frozen site-wide.'); }
    }, true);

    // ---------- URL change detection ----------
    const checkUrlChange = () => {
        if (location.href !== lastUrl) { 
            lastUrl = location.href; 
            updateCurrentLocCache();
            requestUpdateStyles(); 
            if (shadowBy('hider-panel')?.classList.contains('is-visible')) renderList(); 
        }
    };

    ['pushState', 'replaceState'].forEach(fn => { const orig = history[fn]; if (orig) history[fn] = function() { orig.apply(this, arguments); checkUrlChange(); }; });
    window.addEventListener('popstate', () => { userApprovedNavigation = true; checkUrlChange(); setTimeout(() => { userApprovedNavigation = false; }, 500); }, { passive: true });
    window.addEventListener('hashchange', checkUrlChange, { passive: true });
    window.addEventListener('pageshow', () => { userApprovedNavigation = false; checkUrlChange(); }, { passive: true });

    // ---------- Low-power heartbeat ----------
    function setupLowPowerHeartbeat() {
        const scheduleIdle = fn => (win.requestIdleCallback ? win.requestIdleCallback(fn, { timeout: 2000 }) : setTimeout(fn, 1000));
        const performHealthCheck = () => {
            if (isTop && !doc.getElementById(UI_HOST_ID)) createShadowUI();
            if (!doc.getElementById('hider-dynamic-styles')) requestUpdateStyles();
            if (!isTop) try { window.top.postMessage({ type: 'HIDER_REQUEST_STATE' }, '*'); } catch {}
            scheduleIdle(performHealthCheck);
        };
        scheduleIdle(performHealthCheck);
    }

    // ---------- Init ----------
    function init() {
        updateCurrentLocCache();
        installInterceptors();
        createShadowUI();
        requestUpdateStyles();
        setupScrollAutoClose();
        setupLowPowerHeartbeat();
        setupProtectionObserver();

        applyAllSettings();

        if (CACHE.autoTimeSkipper && featuresEnabled) {
            setTimeout(autoSkipTimers, 500);
        }
    }

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