Greasy Fork is available in English.

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 (smart skip for essential UI incl. side menus), Auto-Accept Age Verification, Auto-Close Logins, Cookie Bypass, Bulk Filter Lists, and improved UI.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

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

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Hide Web Elements Pro
// @version      14.1
// @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 (smart skip for essential UI incl. side menus), Auto-Accept Age Verification, Auto-Close Logins, Cookie Bypass, Bulk Filter Lists, and improved UI.
// @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,
        antiPaywall: gv('hider_anti_paywall', false),
        autoCloseModals: gv('hider_auto_close_modals', false),
        cookieConsentMode: gv('hider_cookie_consent_mode', 'ask'),
        autoAcceptAge: gv('hider_auto_accept_age', false),
        autoCloseLogins: gv('hider_auto_close_logins', false),
        filterLists: gv('hider_filter_lists', [])
    };

    // ---------- 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 = '';
        container.style.cssText = 'display:grid!important;grid-template-columns:repeat(auto-fill,minmax(80px,1fr))!important;gap:4px!important;';
        DOCK_BUTTONS.forEach(btn => {
            const label = document.createElement('label');
            label.style.cssText = 'font-size:9px!important;color:#cbd5e1!important;display:flex!important;align-items:center!important;gap:4px!important;cursor:pointer!important;user-select:none!important;background:rgba(255,255,255,0.05)!important;padding:2px 6px!important;border-radius:4px!important;border:1px solid rgba(255,255,255,0.06)!important;';
            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;width:12px!important;height:12px!important;flex-shrink:0!important;';
            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;
            span.style.cssText = 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis;';
            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;
    let globalScopeTemp = false;

    // === SMART IMPROVEMENT: Cache for rule signature ===
    let lastRuleSignature = '';
    let activeHiddenSelector = '';    // Combined selector for the proxy

    // ---------- Auto Time Skipper State ----------
    let autoSkipInterval = null;
    let autoSkipEmptyCount = 0;
    const AUTO_SKIP_INTERVAL_MS = 1000;
    const AUTO_SKIP_MAX_EMPTY = 4;

    // ---------- Cleanup ----------
    const timers = {
        scrollInterval: null,
        blurInterval: null,
        protectionPoller: null,
        logSaveTimer: null,
        collapseTimer: null,
        paywallObserverTimer: null,
        modalObserverTimer: null,
        cookieObserverTimer: null
    };
    const observers = {
        protectionObserver: null,
        blurObserver: null,
        urlChangeObserver: null,
        paywallObserver: null,
        modalObserver: null,
        cookieObserver: null,
        adSkipObserver: null,
        headMutationObserver: null
    };
    const styleElements = {
        scrollStyleEl: null,
        contextMenuStyleEl: null,
        blurGlobalStyle: null
    };

    function dispose() {
        Object.keys(timers).forEach(key => {
            if (timers[key]) {
                clearInterval(timers[key]);
                clearTimeout(timers[key]);
                timers[key] = null;
            }
        });
        Object.keys(observers).forEach(key => {
            if (observers[key]) {
                observers[key].disconnect();
                observers[key] = null;
            }
        });
        Object.values(styleElements).forEach(el => {
            if (el && el.parentNode) el.remove();
        });
        const host = doc.getElementById(UI_HOST_ID);
        if (host) host.remove();
        const stepper = shadowBy(STEPPER_BAR_ID);
        if (stepper) stepper.remove();
        if (linkPanelEl && linkPanelEl.parentNode) linkPanelEl.remove();
        const prompt = shadowBy('hider-freeze-prompt');
        if (prompt) prompt.remove();
        const toast = doc.getElementById('hider-toast');
        if (toast) toast.remove();
        const dyn = doc.getElementById('hider-dynamic-styles');
        if (dyn) dyn.remove();
        stopAutoSkipMonitoring();
    }

    window.addEventListener('beforeunload', dispose);

    // ---------- Context Menu Override ----------
    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 ----------
    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;
            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;
        if (el === doc.documentElement || el === doc.body) return true;
        if (el.id === UI_HOST_ID || el.closest && el.closest('#' + UI_HOST_ID)) return true;
        const text = el.textContent || '';
        if (text.length > 500) {
            const style = win.getComputedStyle(el);
            if (style.position === 'fixed' || style.position === 'absolute') {
                const z = parseInt(style.zIndex, 10);
                if (z > 1000) return false;
            }
            return true;
        }
        if (el.matches && el.matches('article, main, section, div[role="main"]')) {
            if (text.length > 100) return true;
        }
        return false;
    }

    // ================================================================
    //  NEW HELPER: Detect side panels (smart)
    // ================================================================
    function isSidePanel(el) {
        if (!el || el === doc.documentElement || el === doc.body) return false;
        if (el.closest && el.closest('#' + UI_HOST_ID)) return false;

        const rect = el.getBoundingClientRect();
        const vw = win.innerWidth, vh = win.innerHeight;
        const widthRatio = rect.width / vw;
        const heightRatio = rect.height / vh;
        const isLeft = rect.left < 10;
        const isRight = (vw - rect.right) < 10;

        // 1. Position & size
        if ((isLeft || isRight) && widthRatio < 0.4 && heightRatio > 0.3) return true;

        // 2. Class/id/role keywords
        const classId = (el.className + ' ' + el.id).toLowerCase();
        const role = el.getAttribute('role') || '';
        const combined = classId + ' ' + role;
        const sideKeywords = ['sidebar', 'drawer', 'menu', 'navigation', 'nav', 'sidepanel', 'offcanvas', 'slide', 'panel', 'sidenav'];
        if (sideKeywords.some(kw => combined.includes(kw))) return true;

        // 3. ARIA roles that are typical for menus/navigation
        const menuRoles = ['navigation', 'menu', 'menubar', 'listbox', 'tree', 'tablist'];
        if (menuRoles.includes(role)) return true;

        // 4. Many links and not full‑screen → likely a menu
        const links = el.querySelectorAll('a');
        if (links.length > 5 && widthRatio < 0.5 && heightRatio < 0.9) return true;

        // 5. Contains a search input or hamburger‑like button
        const hasSearch = el.querySelector('input[type="search"], input[placeholder*="search"], .search-input');
        if (hasSearch && widthRatio < 0.5) return true;

        // 6. Check for transform/transition that suggests sliding panel
        const style = win.getComputedStyle(el);
        if (style.transform && style.transform !== 'none' && (style.transform.includes('translateX') || style.transform.includes('translateY'))) {
            return true;
        }

        return false;
    }

    // ================================================================
    //  REWRITTEN ANTI-PAYWALL / ANTI-ADBLOCK ENGINE (SMARTER)
    // ================================================================
    function setupPaywallBypass() {
        if (observers.paywallObserver) {
            observers.paywallObserver.disconnect();
            observers.paywallObserver = null;
        }
        if (!CACHE.antiPaywall || !featuresEnabled || isFeatureBlacklisted()) return;

        const overlaySelectors = [
            '.paywall', '.adblock-overlay', '.premium-overlay', '.subscribe-overlay',
            '.gate', '.wall', '.restricted', '.locked',
            '[class*="paywall"]', '[id*="paywall"]', '[class*="adblock"]', '[id*="adblock"]',
            '[class*="premium"]', '[id*="premium"]', '[class*="subscribe"]', '[id*="subscribe"]',
            '[class*="overlay"]', '[id*="overlay"]', '[class*="modal"]', '[id*="modal"]'
        ];

        const paywallKeywords = ['adblock', 'paywall', 'premium', 'subscribe', 'whitelist',
                                 'disable adblock', 'ad blocker', 'subscription', 'unlock',
                                 'membership', 'register', 'sign up', 'log in'];

        function isPaywallElement(el) {
            if (!el || el === doc.documentElement || el === doc.body) return false;
            if (el.closest && el.closest('#' + UI_HOST_ID)) return false;
            if (isMainContentElement(el)) return false;
            if (isSidePanel(el)) return false;

            const style = win.getComputedStyle(el);
            const pos = style.position;
            if (pos !== 'fixed' && pos !== 'absolute') return false;

            const rect = el.getBoundingClientRect();
            const vw = win.innerWidth, vh = win.innerHeight;
            const area = rect.width * rect.height;
            const vpArea = vw * vh;
            const coverage = area / vpArea;
            if (coverage < 0.05) return false;

            let score = 0;
            let z = parseInt(style.zIndex, 10) || 0;
            if (z >= 100) score += 1;
            const bg = style.backgroundColor || style.background;
            const hasDarkBg = bg && (bg.includes('rgba(0,0,0') || bg.includes('#000') || bg.includes('black'));
            if (hasDarkBg) score += 2;
            const hasBlur = style.backdropFilter && style.backdropFilter.includes('blur');
            if (hasBlur) score += 2;
            const text = el.textContent.toLowerCase();
            let keywordCount = 0;
            paywallKeywords.forEach(kw => { if (text.includes(kw)) keywordCount++; });
            if (keywordCount >= 2) score += 3;
            else if (keywordCount === 1) score += 1;
            const buttons = el.querySelectorAll('button, a[role="button"], input[type="button"], input[type="submit"]');
            let actionBtn = false;
            for (const btn of buttons) {
                const btnText = btn.textContent.toLowerCase();
                if (btnText.includes('accept') || btnText.includes('agree') || btnText.includes('continue') ||
                    btnText.includes('subscribe') || btnText.includes('unlock')) {
                    actionBtn = true;
                    break;
                }
            }
            if (actionBtn) score += 2;
            if (coverage > 0.6) score += 2;
            const hasCloseBtn = el.querySelector('[aria-label*="close"], .close, .dismiss, [class*="close"]');
            if (hasCloseBtn) score -= 1;
            return score >= 5;
        }

        function removePaywallElement(el) {
            if (!el || el === doc.documentElement || el === doc.body) return;
            if (el.closest && el.closest('#' + UI_HOST_ID)) return;
            if (isMainContentElement(el)) return;
            try {
                el.style.setProperty('display', 'none', 'important');
                el.style.setProperty('visibility', 'hidden', 'important');
                forceEnableScroll();
            } catch (e) { /* ignore */ }
        }

        function scanForPaywalls(node) {
            if (node.nodeType === Node.ELEMENT_NODE) {
                if (isPaywallElement(node)) {
                    removePaywallElement(node);
                    return;
                }
                const children = node.querySelectorAll ? node.querySelectorAll('*') : [];
                for (const child of children) {
                    if (isPaywallElement(child)) {
                        removePaywallElement(child);
                    }
                }
            }
        }

        let paywallTimeout = null;
        const paywallObserverCallback = (mutations) => {
            if (paywallTimeout) return;
            paywallTimeout = setTimeout(() => {
                paywallTimeout = null;
                for (const mutation of mutations) {
                    if (mutation.type === 'childList') {
                        mutation.addedNodes.forEach(node => scanForPaywalls(node));
                    }
                }
            }, 200);
        };

        observers.paywallObserver = new MutationObserver(paywallObserverCallback);
        observers.paywallObserver.observe(doc.documentElement, { childList: true, subtree: true });

        const allElements = doc.querySelectorAll('*');
        for (const el of allElements) {
            if (isPaywallElement(el)) {
                removePaywallElement(el);
            }
        }
        forceEnableScroll();

        setTimeout(() => {
            const allElements2 = doc.querySelectorAll('*');
            for (const el of allElements2) {
                if (isPaywallElement(el)) {
                    removePaywallElement(el);
                }
            }
            forceEnableScroll();
        }, 2000);
    }

    // ================================================================
    //  UPGRADED AGE VERIFICATION DETECTION & AUTO-FILL
    // ================================================================
    function isAgeVerificationOrLogin(modal) {
        if (!modal) return false;
        const text = (modal.textContent || '').toLowerCase();
        
        // Keywords specific to age verification
        const ageKeywords = [
            'age', 'verify', 'verification', '18', 'over 18', 'adult',
            'are you 18', 'confirm age', 'age gate', 'age check',
            'you must be 18', 'adult content', 'age restricted',
            'birthday', 'date of birth', 'dob'
        ];
        const aria = (modal.getAttribute('aria-label') || '').toLowerCase();
        const title = (modal.getAttribute('title') || '').toLowerCase();
        const role = modal.getAttribute('role') || '';
        const classId = (modal.className + ' ' + modal.id).toLowerCase();
        const combined = text + ' ' + aria + ' ' + title + ' ' + classId + ' ' + role;

        // Check for specific class names
        const ageClassPatterns = [
            'age-gate', 'age-verification', 'age-check', 'age-verify',
            'adult-verification', 'age-modal', 'age-overlay',
            'birthday-verification', 'dob-verification'
        ];
        for (const pattern of ageClassPatterns) {
            if (combined.includes(pattern)) return true;
        }

        // Check for date input fields (day/month/year selects or date input)
        const hasDateFields = modal.querySelector('select.day, select.month, select.year, input[type="date"]');
        if (hasDateFields) {
            // If there are date fields and age-related keywords, it's age verification
            if (ageKeywords.some(kw => combined.includes(kw))) return true;
        }

        // Check for "Enter" / "Confirm" button with age keywords
        const buttons = modal.querySelectorAll('button, a[role="button"], input[type="button"], input[type="submit"]');
        let hasAgeButton = false;
        for (const btn of buttons) {
            const btnText = btn.textContent.toLowerCase();
            const btnAria = (btn.getAttribute('aria-label') || '').toLowerCase();
            const btnCombined = btnText + ' ' + btnAria;
            if (btnCombined.includes('enter') || btnCombined.includes('confirm') || 
                btnCombined.includes('verify') || btnCombined.includes('i am') ||
                btnCombined.includes('proceed') || btnCombined.includes('continue')) {
                if (ageKeywords.some(kw => combined.includes(kw))) {
                    hasAgeButton = true;
                    break;
                }
            }
        }

        if (hasAgeButton) return true;

        // Fallback: if it looks like a centered modal with a dark backdrop and age keywords
        const style = win.getComputedStyle(modal);
        const pos = style.position;
        if (pos === 'fixed' || pos === 'absolute') {
            const rect = modal.getBoundingClientRect();
            const vw = win.innerWidth, vh = win.innerHeight;
            const widthRatio = rect.width / vw;
            const heightRatio = rect.height / vh;
            // Centered modal (between 30% and 80% width, 20% to 80% height)
            if (widthRatio > 0.2 && widthRatio < 0.8 && heightRatio > 0.1 && heightRatio < 0.9) {
                const bg = style.backgroundColor || style.background;
                const hasDarkBg = bg && (bg.includes('rgba(0,0,0') || bg.includes('#000') || bg.includes('black'));
                if (hasDarkBg && ageKeywords.some(kw => combined.includes(kw))) {
                    return true;
                }
            }
        }

        return false;
    }

    function fillAgeFields(container) {
        if (!container) return false;
        let filled = false;

        // 1. Input[type="date"]
        const dateInputs = container.querySelectorAll('input[type="date"]');
        for (const input of dateInputs) {
            if (!input.value) {
                input.value = '2001-01-01';
                input.dispatchEvent(new Event('input', { bubbles: true }));
                input.dispatchEvent(new Event('change', { bubbles: true }));
                filled = true;
            }
        }

        // 2. Select dropdowns for day/month/year
        const selects = container.querySelectorAll('select');
        let daySelect = null, monthSelect = null, yearSelect = null;
        for (const sel of selects) {
            const name = (sel.name || '').toLowerCase();
            const id = (sel.id || '').toLowerCase();
            const combined = name + ' ' + id;
            if (combined.includes('day') || combined.includes('dd') || combined.includes('date')) {
                daySelect = sel;
            } else if (combined.includes('month') || combined.includes('mm')) {
                monthSelect = sel;
            } else if (combined.includes('year') || combined.includes('yyyy') || combined.includes('yy')) {
                yearSelect = sel;
            }
        }

        // Try to find selects by label/placeholder/aria-label
        if (!daySelect || !monthSelect || !yearSelect) {
            for (const sel of selects) {
                const label = sel.getAttribute('aria-label') || sel.getAttribute('placeholder') || '';
                const lower = label.toLowerCase();
                if (!daySelect && (lower.includes('day') || lower.includes('date'))) daySelect = sel;
                else if (!monthSelect && lower.includes('month')) monthSelect = sel;
                else if (!yearSelect && (lower.includes('year') || lower.includes('yyyy'))) yearSelect = sel;
            }
        }

        // Set day → 1
        if (daySelect && daySelect.options.length > 1) {
            let found = false;
            for (let opt of daySelect.options) {
                if (opt.value === '1' || opt.value === '01' || opt.text.trim() === '1' || opt.text.trim() === '01') {
                    daySelect.selectedIndex = opt.index;
                    found = true;
                    break;
                }
            }
            if (!found) daySelect.selectedIndex = 1;
            daySelect.dispatchEvent(new Event('change', { bubbles: true }));
            filled = true;
        }

        // Set month → January (1)
        if (monthSelect && monthSelect.options.length > 1) {
            for (let opt of monthSelect.options) {
                if (opt.value === '1' || opt.value === '01' || opt.text.toLowerCase().includes('jan')) {
                    monthSelect.selectedIndex = opt.index;
                    break;
                }
            }
            monthSelect.dispatchEvent(new Event('change', { bubbles: true }));
            filled = true;
        }

        // Set year → 2001 (or the earliest available if 2001 not present)
        if (yearSelect && yearSelect.options.length > 1) {
            let yearSet = false;
            for (let opt of yearSelect.options) {
                if (opt.value === '2001') {
                    yearSelect.selectedIndex = opt.index;
                    yearSet = true;
                    break;
                }
            }
            if (!yearSet && yearSelect.options.length > 0) {
                // Pick the first option that looks like a year (e.g., 1990-2010)
                const years = [];
                for (let opt of yearSelect.options) {
                    const val = parseInt(opt.value, 10);
                    if (!isNaN(val) && val > 1900 && val < 2030) {
                        years.push({ value: val, index: opt.index });
                    }
                }
                if (years.length > 0) {
                    // Pick the median year or the earliest that is at least 18 years ago
                    const now = new Date().getFullYear();
                    const minYear = now - 100; // allow up to 100 years ago
                    const maxYear = now - 18; // must be at least 18
                    let best = years[0];
                    for (const y of years) {
                        if (y.value >= maxYear && y.value <= now) {
                            best = y;
                            break;
                        }
                    }
                    yearSelect.selectedIndex = best.index;
                } else {
                    yearSelect.selectedIndex = 1; // fallback
                }
            }
            yearSelect.dispatchEvent(new Event('change', { bubbles: true }));
            filled = true;
        }

        // 3. Text/number inputs for age
        const ageInputs = container.querySelectorAll('input[type="text"], input[type="number"]');
        for (const input of ageInputs) {
            const name = (input.name || '').toLowerCase();
            const placeholder = (input.placeholder || '').toLowerCase();
            const combined = name + ' ' + placeholder;
            if (combined.includes('age') || combined.includes('birth') || combined.includes('dob') || combined.includes('birthday')) {
                if (!input.value) {
                    input.value = '18'; // or '2001-01-01' if they expect a date
                    input.dispatchEvent(new Event('input', { bubbles: true }));
                    input.dispatchEvent(new Event('change', { bubbles: true }));
                    filled = true;
                }
            }
        }

        return filled;
    }

    function findAcceptButton(modal) {
        const buttons = modal.querySelectorAll('button, a[role="button"], input[type="button"], input[type="submit"]');
        const acceptKeywords = ['accept', 'enter', 'yes', 'i am over 18', 'over 18', 'continue', 'proceed', 'verify', 'confirm', 'i am 18', 'enter site', 'go to site'];
        for (const btn of buttons) {
            const text = btn.textContent.trim().toLowerCase();
            const aria = (btn.getAttribute('aria-label') || '').toLowerCase();
            const combined = text + ' ' + aria;
            if (acceptKeywords.some(kw => combined.includes(kw))) {
                return btn;
            }
        }
        // Look for any button that is not "close" or "cancel"
        for (const btn of buttons) {
            const text = btn.textContent.trim().toLowerCase();
            if (text && !text.includes('close') && !text.includes('cancel') && !text.includes('dismiss')) {
                return btn;
            }
        }
        return null;
    }

    // ================================================================
    //  AUTO-CLOSE MODALS & OVERLAYS ENGINE (SMART & SITE‑AWARE)
    // ================================================================
    function setupModalAutoClose() {
        if (observers.modalObserver) {
            observers.modalObserver.disconnect();
            observers.modalObserver = null;
        }
        if (!CACHE.autoCloseModals || !featuresEnabled || isFeatureBlacklisted()) return;

        const modalSelectors = [
            '[role="dialog"]', '[role="alertdialog"]', '.modal', '.popup', '.lightbox',
            '[class*="modal"]', '[id*="modal"]', '[class*="popup"]', '[id*="popup"]',
            '[class*="overlay"]', '[id*="overlay"]', '.modal-overlay', '.modal-backdrop'
        ];

        const closeKeywords = ['close', 'dismiss', 'cancel', '×', 'x', 'got it', 'ok', 'continue'];

        function isNavigationOrMenu(modal) {
            const role = modal.getAttribute('role');
            if (role && ['navigation', 'menu', 'listbox', 'tree', 'menubar', 'tablist'].includes(role)) {
                return true;
            }
            const label = (modal.getAttribute('aria-label') || '').toLowerCase();
            if (label.includes('navigation') || label.includes('menu') || label.includes('sidebar') || label.includes('drawer')) {
                return true;
            }
            const classId = (modal.className + ' ' + modal.id).toLowerCase();
            if (/(menu|sidebar|drawer|nav|navigation|sidepanel|offcanvas|slide[-_]in|slide[-_]out)/i.test(classId)) {
                return true;
            }
            const links = modal.querySelectorAll('a');
            if (links.length > 3) {
                const style = win.getComputedStyle(modal);
                const pos = style.position;
                if (pos === 'fixed' || pos === 'absolute') {
                    const rect = modal.getBoundingClientRect();
                    const vw = window.innerWidth;
                    const vh = window.innerHeight;
                    if ((rect.left < 50 || (vw - rect.right) < 50) && rect.width < vw * 0.5) {
                        return true;
                    }
                }
            }
            const parent = modal.parentElement;
            if (parent && parent.matches && parent.matches('.sidebar, .menu, .nav, .drawer, .offcanvas, [role="navigation"]')) {
                return true;
            }
            return false;
        }

        function isEssentialUI(modal) {
            if (isSidePanel(modal)) return true;
            if (isNavigationOrMenu(modal)) return true;
            const rect = modal.getBoundingClientRect();
            const vw = window.innerWidth;
            const vh = window.innerHeight;
            const widthRatio = rect.width / vw;
            const heightRatio = rect.height / vh;
            const isLeft = rect.left < 10;
            const isRight = (vw - rect.right) < 10;
            if ((isLeft || isRight) && widthRatio < 0.5 && heightRatio > 0.3) return true;
            if (modal.querySelector('input, textarea, select')) {
                const text = (modal.textContent || '').toLowerCase();
                if (text.includes('subscribe') || text.includes('paywall') || text.includes('unlock') || text.includes('membership')) {
                    return false;
                }
                if (CACHE.autoCloseLogins) return false;
                return true;
            }
            if (widthRatio < 0.3 || heightRatio < 0.3) return true;
            if (modal.matches && modal.matches('.menu, .dropdown, .panel, .sidebar, .drawer, [role="menu"], [role="listbox"], [role="navigation"]')) return true;
            if (modal.querySelector('input[type="search"], input[placeholder*="search"], .search-input')) return true;
            return false;
        }

        function findCloseButton(modal) {
            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();
                const aria = (btn.getAttribute('aria-label') || '').toLowerCase();
                if (closeKeywords.some(kw => text.includes(kw) || aria.includes(kw))) {
                    return btn;
                }
            }
            const closeEl = modal.querySelector('.close, .dismiss, [aria-label*="close"], [aria-label*="Close"]');
            return closeEl || null;
        }

        function tryCloseModal(modal) {
            if (!modal || modal === doc.documentElement || modal === doc.body) return false;
            if (modal.closest && modal.closest('#' + UI_HOST_ID)) return false;
            if (isMainContentElement(modal)) return false;

            if (isSidePanel(modal)) return false;

            // ---- AGE VERIFICATION HANDLING ----
            if (isAgeVerificationOrLogin(modal)) {
                if (CACHE.autoAcceptAge) {
                    // Fill date fields
                    fillAgeFields(modal);
                    const acceptBtn = findAcceptButton(modal);
                    if (acceptBtn) {
                        try { acceptBtn.click(); return true; } catch {}
                    }
                }
                return false; // don't close automatically unless we clicked
            }

            // ---- LOGIN HANDLING ----
            if (CACHE.autoCloseLogins) {
                // If it's a login modal, try to close it
                const text = (modal.textContent || '').toLowerCase();
                if (text.includes('login') || text.includes('sign in') || text.includes('log in') || text.includes('register')) {
                    const closeBtn = findCloseButton(modal);
                    if (closeBtn) {
                        try { closeBtn.click(); return true; } catch {}
                    }
                }
            }

            // ---- REGULAR MODAL CLOSE ----
            if (isNavigationOrMenu(modal) || isEssentialUI(modal)) return false;

            if (modal.querySelector('input[type="text"], input[type="search"], textarea, select')) {
                const text = modal.textContent.toLowerCase();
                if (!text.includes('subscribe') && !text.includes('paywall') && !text.includes('unlock')) {
                    return false;
                }
            }

            const rect = modal.getBoundingClientRect();
            const vw = window.innerWidth, vh = window.innerHeight;
            const areaRatio = (rect.width * rect.height) / (vw * vh);
            if (areaRatio < 0.3) {
                const style = win.getComputedStyle(modal);
                const bg = style.backgroundColor || style.background;
                const hasDarkBg = bg && (bg.includes('rgba(0,0,0') || bg.includes('#000') || bg.includes('black'));
                const text = (modal.textContent || '').toLowerCase();
                const isAdOrPaywall = text.includes('ad') || text.includes('subscribe') || text.includes('unlock');
                if (!hasDarkBg && !isAdOrPaywall) return false;
            }

            const closeBtn = findCloseButton(modal);
            if (closeBtn) {
                try { closeBtn.click(); return true; } catch {}
            }
            if (modal.matches('.modal-backdrop, .modal-overlay, .overlay')) {
                try { modal.style.setProperty('display', 'none', 'important'); return true; } catch {}
            }
            const parent = modal.parentElement;
            if (parent && parent.matches && parent.matches('.modal-backdrop, .modal-overlay, .overlay')) {
                try { parent.style.setProperty('display', 'none', 'important'); return true; } catch {}
            }
            return false;
        }

        function scanForModals() {
            const modals = doc.querySelectorAll(modalSelectors.join(','));
            for (const modal of modals) {
                tryCloseModal(modal);
            }
        }

        let modalTimeout = null;
        const modalObserverCallback = () => {
            if (modalTimeout) return;
            modalTimeout = setTimeout(() => {
                modalTimeout = null;
                scanForModals();
            }, 250);
        };

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

        setTimeout(scanForModals, 500);
        setTimeout(scanForModals, 1500);
        setTimeout(scanForModals, 3000);
    }

    // ---------- Cookie Consent ----------
    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;
                    }
                }
                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();

        if (CACHE.autoTimeSkipper && featuresEnabled) {
            startAutoSkipMonitoring();
        } else {
            stopAutoSkipMonitoring();
        }
    }

    // ---------- 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.autoAcceptAge = gv('hider_auto_accept_age', false);
        CACHE.autoCloseLogins = gv('hider_auto_close_logins', false);
        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 (SMART: no class, just proxy) ----------
    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.matches && activeHiddenSelector && el.matches(activeHiddenSelector)) {
                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))));
    };

    // ---------- WILDCARD CONVERSION ----------
    function getBaseName(name) {
        let base = name.replace(/[-_][0-9a-fA-F]+$/, '');
        base = base.replace(/[0-9]+$/, '');
        base = base.replace(/[-_]+$/, '');
        return base || name;
    }

    function convertToWildcardSelector(sel) {
        if (!sel || typeof sel !== 'string') return '';
        return sel.replace(/(?<![#.])(#|\.)([a-zA-Z0-9_-]+)/g, (match, p, name) => {
            if (name.startsWith('hider-')) return match;
            const base = getBaseName(name);
            if (!base) return match;
            return p === '#' ? `[id*="${base}"]` : `[class*="${base}"]`;
        });
    }

    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-scope')?.classList.toggle('scope-global', currentScope === 'global');
            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_auto_accept_age', 'hider_auto_close_logins', '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 (SMART: signature-based) ----------
    function getRuleSignature() {
        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);
        return combined.sort().join('|');
    }

    function requestUpdateStyles(force = false) {
        if (styleUpdateRAF) {
            cancelAnimationFrame(styleUpdateRAF);
            styleUpdateRAF = null;
        }
        styleUpdateRAF = requestAnimationFrame(() => {
            styleUpdateRAF = null;
            updateStyles(force);
        });
    }

    function updateStyles(force = false) {
        const currentSignature = getRuleSignature();
        if (!force && lastRuleSignature === currentSignature) {
            if (CACHE.autoScroll && featuresEnabled) checkAndAutoUnblockScroll();
            return;
        }

        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);
        const safeCombined = combined.filter(sel => !sel.match(/^document$/i));
        activeHiddenSelector = safeCombined.join(',');
        
        const hideCss = (featuresEnabled && safeCombined.length) 
            ? `${activeHiddenSelector}{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) {
            el.textContent = css;
            cachedCssString = css;
        }

        lastRuleSignature = currentSignature;
        if (CACHE.autoScroll && featuresEnabled) checkAndAutoUnblockScroll();
    }
    updateStyles(true);

    // === MOBILE-FRIENDLY PERSISTENCE: Reapply on visibility/focus ===
    function reapplyHiddenStyles() {
        requestUpdateStyles(true);
    }

    document.addEventListener('visibilitychange', () => {
        if (document.visibilityState === 'visible') {
            reapplyHiddenStyles();
        }
    });

    window.addEventListener('focus', reapplyHiddenStyles, { passive: true });

    if (doc.head) {
        observers.headMutationObserver = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                for (const node of mutation.removedNodes) {
                    if (node.id === 'hider-dynamic-styles') {
                        requestUpdateStyles(true);
                        return;
                    }
                }
            }
        });
        observers.headMutationObserver.observe(doc.head, { childList: true });
    }

    // ---------- 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>
            <div class="h-stepper-row" style="display:flex;flex-direction:column;gap:4px;width:100%;">
                <button id="hider-step-confirm" class="h-btn-pill btn-blue" style="width:100%;">🙈 Hide</button>
                <button id="hider-step-undo" class="h-btn-pill btn-gray" style="width:100%;">↩️ Undo</button>
                <button id="hider-step-cancel" class="h-btn-pill btn-red" style="width:100%;">✖ Cancel</button>
            </div>
        `;

        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(); };
        stepper.querySelector('#hider-step-undo').onclick = e => { e.stopPropagation(); undoLastHide(); };
        stepper.querySelector('#hider-step-cancel').onclick = e => { 
            e.stopPropagation(); 
            clearSelectionState(); 
            showToast('❌ Selection cancelled');
        };
    }

    function confirmHideSelectedElement() {
        if (!previewElement) return;
        const el = previewElement;
        el.classList.remove('hider-preview-highlight');
        const sel = getExactSelector(el);
        if (sel) {
            if (/^(html|body)$/i.test(sel)) {
                if (!confirm('⚠️ Warning: You are about to hide the entire page (html/body). Are you sure?')) {
                    clearSelectionState();
                    showToast('❌ Cancelled hiding entire page');
                    return;
                }
            }
            lastHiddenSelector = sel;
            if (currentScope === '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 if (currentScope === 'site') {
                const key = 'hider_site_' + location.hostname;
                const s = gv(key, []); if (!s.includes(sel)) { s.push(sel); sv(key, s); }
                showToast('🌐 Site-wide hide rule added!');
            } else { // link
                const key = 'hider_link_' + cleanUrl();
                const s = gv(key, []); if (!s.includes(sel)) { s.push(sel); sv(key, s); }
                showToast('📄 Page-only hide rule added!');
            }
        }
        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 = 'hider_site_' + location.hostname;
            let rules = gv(key, []);
            let idx = rules.indexOf(lastHiddenSelector);
            if (idx !== -1) {
                rules.splice(idx, 1);
                sv(key, rules);
                found = true;
            } else {
                const linkKey = 'hider_link_' + cleanUrl();
                rules = gv(linkKey, []);
                idx = rules.indexOf(lastHiddenSelector);
                if (idx !== -1) {
                    rules.splice(idx, 1);
                    sv(linkKey, rules);
                    found = true;
                }
            }
        }
        if (found) {
            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 ----------
    function revealHiddenElements() {
        if (!doc.body) return;

        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 => targets.add(el));

        doc.querySelectorAll('*').forEach(el => {
            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];
                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 (Manual 30s) ----------
    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);
    }

    // ================================================================
    //  SMART AUTO TIME SKIPPER + VIDEO AD SKIPPER
    // ================================================================
    function isInsideMedia(el) {
        let node = el;
        while (node && node !== doc) {
            if (node.tagName === 'VIDEO' || node.tagName === 'AUDIO') return true;
            node = node.parentElement;
        }
        return false;
    }

    function checkAndSkipTimers() {
        if (!CACHE.autoTimeSkipper || !featuresEnabled) return false;
        let found = false;

        const timerSelectors = [
            '[class*="timer"]', '[class*="countdown"]', '[id*="timer"]', '[id*="countdown"]',
            '[class*="time"]', '[id*="time"]', '[class*="remaining"]', '[id*="remaining"]',
            '[data-timer]', '[data-countdown]', '[aria-label*="time"]', '[aria-label*="countdown"]'
        ];
        const timerElements = doc.querySelectorAll(timerSelectors.join(','));
        for (const el of timerElements) {
            if (isInsideMedia(el)) continue;
            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) ||
                /^\d+\s*second/i.test(text)) {
                el.textContent = '0';
                el.dispatchEvent(new Event('input', { bubbles: true }));
                found = true;
            }
        }

        const allElements = doc.querySelectorAll('*');
        for (const el of allElements) {
            if (isInsideMedia(el)) continue;
            if (el.matches && el.matches(timerSelectors.join(','))) continue;
            const text = el.textContent.trim();
            if (/^\d{1,2}:\d{2}$/.test(text) || /^\d+\s*(s|sec|seconds?)$/i.test(text)) {
                const parent = el.parentElement;
                if (parent && (parent.matches && parent.matches('[class*="timer"], [class*="countdown"], [id*="timer"], [id*="countdown"]'))) {
                    el.textContent = '0';
                    el.dispatchEvent(new Event('input', { bubbles: true }));
                    found = true;
                }
            }
        }

        return found;
    }

    function skipVideoAds() {
        if (!CACHE.autoTimeSkipper || !featuresEnabled) return false;
        let skipped = false;

        const adContainers = doc.querySelectorAll([
            '.ad-container', '.video-ads', '.ad-player', '.ad-overlay',
            '[id*="ad"]', '[id*="video-ad"]', '[id*="ad-container"]',
            '.ytp-ad-overlay', '.ytp-ad-player-overlay', '.ytp-ad-image-overlay',
            '.ytp-ad-text-overlay', '.ytp-ad-skip-button-container',
            '.vjs-ad-overlay', '.vjs-ad-container',
            '.jwplayer-ads', '.jwplayer-ads-container',
            '.preroll-ads', '.ad-iframe', '.ad-banner'
        ].join(','));
        
        for (const ad of adContainers) {
            const skipBtns = ad.querySelectorAll('button, a[role="button"], [role="button"]');
            for (const btn of skipBtns) {
                const text = btn.textContent.trim().toLowerCase();
                if (text && (text.includes('skip') || text.includes('close') || text.includes('dismiss') || text.includes('×'))) {
                    const rect = btn.getBoundingClientRect();
                    if (rect.width > 0 && rect.height > 0) {
                        try { btn.click(); skipped = true; } catch {}
                    }
                }
            }
            const skipTexts = ad.querySelectorAll('*');
            for (const el of skipTexts) {
                const txt = el.textContent.trim().toLowerCase();
                if (txt && (txt.includes('skip ad') || txt.includes('skip video') || txt.includes('skip in'))) {
                    const parentBtn = el.closest('button, a[role="button"], [role="button"]');
                    if (parentBtn) {
                        try { parentBtn.click(); skipped = true; } catch {}
                    }
                }
            }
        }

        const genericSkipBtns = doc.querySelectorAll('button, a[role="button"], [role="button"]');
        for (const btn of genericSkipBtns) {
            const text = btn.textContent.trim().toLowerCase();
            if (text && (text.includes('skip ad') || text.includes('skip video') || text.includes('skip this ad'))) {
                const rect = btn.getBoundingClientRect();
                if (rect.width > 0 && rect.height > 0) {
                    try { btn.click(); skipped = true; } catch {}
                }
            }
        }

        return skipped;
    }

    function autoSkipLoop() {
        let found = false;
        if (checkAndSkipTimers()) found = true;
        if (skipVideoAds()) found = true;

        if (found) {
            autoSkipEmptyCount = 0;
        } else {
            autoSkipEmptyCount++;
            if (autoSkipEmptyCount >= AUTO_SKIP_MAX_EMPTY) {
                stopAutoSkipMonitoring();
            }
        }
    }

    function startAutoSkipMonitoring() {
        if (autoSkipInterval) {
            clearInterval(autoSkipInterval);
            autoSkipInterval = null;
        }
        autoSkipEmptyCount = 0;
        autoSkipLoop();
        autoSkipInterval = setInterval(autoSkipLoop, AUTO_SKIP_INTERVAL_MS);
    }

    function stopAutoSkipMonitoring() {
        if (autoSkipInterval) {
            clearInterval(autoSkipInterval);
            autoSkipInterval = null;
        }
        autoSkipEmptyCount = 0;
        if (observers.adSkipObserver) {
            observers.adSkipObserver.disconnect();
            observers.adSkipObserver = null;
        }
    }

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

    // ================================================================
    //  RULE OVERLAY (ADD / EDIT) – ENLARGED HEIGHT, TARGET FIELD
    // ================================================================
    let currentRuleOverlayMode = 'add';
    let currentRuleEditInfo = null;

    function showRuleOverlay(options) {
        const existing = shadowRoot?.getElementById('hider-rule-overlay');
        if (existing) existing.remove();

        const mode = options.mode || 'add';
        const initialSelector = options.selector || '';
        const initialScope = options.scope || 'global';
        const initialTarget = options.target || '';

        currentRuleOverlayMode = mode;
        currentRuleEditInfo = options.editInfo || null;

        const overlay = doc.createElement('div');
        overlay.id = 'hider-rule-overlay';
        overlay.className = 'h-glass';
        overlay.style.cssText = `
            position: fixed !important;
            top: 50% !important;
            left: 50% !important;
            transform: translate(-50%, -50%) !important;
            z-index: 2147483647 !important;
            padding: 22px !important;
            border-radius: 16px !important;
            min-width: 360px !important;
            max-width: 92vw !important;
            width: 420px !important;
            min-height: 280px !important;
            display: flex !important;
            flex-direction: column !important;
            gap: 14px !important;
            pointer-events: auto !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;
        `;

        const title = doc.createElement('div');
        title.style.cssText = 'font-weight:800;font-size:14px;color:#38bdf8;margin-bottom:4px;';
        title.textContent = mode === 'add' ? '➕ Add Rule' : '✏️ Edit Rule';
        overlay.appendChild(title);

        const scopeContainer = doc.createElement('div');
        scopeContainer.className = 'h-custom-select';
        scopeContainer.id = 'rule-scope-select';
        scopeContainer.innerHTML = `
            <div class="h-custom-trigger"><span class="h-custom-value-text">Global</span><span class="h-custom-arrow">▼</span></div>
            <div class="h-custom-options">
                <div class="h-custom-opt" data-val="global">🌍 Global</div>
                <div class="h-custom-opt" data-val="site">🌐 Site‑Wide</div>
                <div class="h-custom-opt" data-val="link">📄 Page‑Only</div>
            </div>
        `;
        overlay.appendChild(scopeContainer);

        const targetContainer = doc.createElement('div');
        targetContainer.id = 'rule-target-container';
        targetContainer.style.cssText = 'display:none; flex-direction:column; gap:4px;';
        const targetLabel = doc.createElement('div');
        targetLabel.style.cssText = 'font-size:10px;color:#94a3b8;font-weight:600;text-transform:uppercase;letter-spacing:0.3px;';
        targetLabel.textContent = '🎯 Target (domain or URL)';
        targetContainer.appendChild(targetLabel);
        const targetInput = doc.createElement('input');
        targetInput.id = 'rule-target-input';
        targetInput.className = 'h-select';
        targetInput.placeholder = 'example.com or /path';
        targetInput.value = initialTarget || '';
        targetInput.style.cssText = 'width:100%;height:34px;font-size:11px;padding:4px 10px;';
        targetContainer.appendChild(targetInput);
        overlay.appendChild(targetContainer);

        const input = doc.createElement('input');
        input.id = 'rule-selector-input';
        input.className = 'h-select';
        input.placeholder = 'CSS Selector (e.g. .ad, #banner)';
        input.value = initialSelector;
        input.style.cssText = 'width:100%;height:34px;font-size:11px;padding:4px 10px;';
        overlay.appendChild(input);

        const btnGroup = doc.createElement('div');
        btnGroup.style.cssText = 'display:flex;gap:8px;justify-content:flex-end;margin-top:6px;';
        const saveBtn = doc.createElement('button');
        saveBtn.className = 'hider-btn-small btn-green';
        saveBtn.textContent = '💾 Save';
        saveBtn.style.cssText = 'height:32px;padding:0 16px;font-size:11px;';
        const cancelBtn = doc.createElement('button');
        cancelBtn.className = 'hider-btn-small btn-gray';
        cancelBtn.textContent = '✖ Cancel';
        cancelBtn.style.cssText = 'height:32px;padding:0 16px;font-size:11px;';
        btnGroup.appendChild(saveBtn);
        btnGroup.appendChild(cancelBtn);
        overlay.appendChild(btnGroup);

        shadowRoot.appendChild(overlay);

        let selectedScope = initialScope;
        const trigger = scopeContainer.querySelector('.h-custom-trigger');
        const valueSpan = trigger.querySelector('.h-custom-value-text');
        const optionsList = scopeContainer.querySelectorAll('.h-custom-opt');
        const updateScopeLabel = (val) => {
            const labels = { global: '🌍 Global', site: '🌐 Site‑Wide', link: '📄 Page‑Only' };
            valueSpan.textContent = labels[val] || 'Global';
            optionsList.forEach(opt => opt.classList.toggle('is-selected', opt.dataset.val === val));
            selectedScope = val;
            if (val === 'global') {
                targetContainer.style.display = 'none';
            } else {
                targetContainer.style.display = 'flex';
                if (!targetInput.value) {
                    if (val === 'site') targetInput.value = location.hostname;
                    else if (val === 'link') targetInput.value = cleanUrl();
                }
            }
        };
        optionsList.forEach(opt => {
            opt.addEventListener('click', (e) => {
                e.stopPropagation();
                updateScopeLabel(opt.dataset.val);
                scopeContainer.classList.remove('is-open');
            });
        });
        trigger.addEventListener('click', (e) => {
            e.stopPropagation();
            const isOpen = scopeContainer.classList.contains('is-open');
            shadowRoot.querySelectorAll('.h-custom-select').forEach(c => c.classList.remove('is-open'));
            if (!isOpen) scopeContainer.classList.add('is-open');
        });
        document.addEventListener('click', function closeDropdown(e) {
            if (scopeContainer && !scopeContainer.contains(e.target)) {
                scopeContainer.classList.remove('is-open');
                document.removeEventListener('click', closeDropdown);
            }
        });

        updateScopeLabel(initialScope);

        const saveRule = () => {
            const selector = input.value.trim();
            if (!selector) {
                showToast('⚠️ Please enter a CSS selector');
                return;
            }

            let newScope = selectedScope;
            let targetValue = targetInput.value.trim();

            if (newScope === 'global') {
                targetValue = '*';
            } else {
                if (!targetValue) {
                    showToast(`⚠️ Please enter a target ${newScope === 'site' ? 'domain' : 'URL'}`);
                    return;
                }
                if (newScope === 'site') {
                    targetValue = cleanDomain(targetValue);
                    if (!targetValue) {
                        showToast('⚠️ Invalid domain');
                        return;
                    }
                } else if (newScope === 'link') {
                    try {
                        const abs = resolveUrl(targetValue);
                        if (!abs) throw new Error();
                        targetValue = abs;
                    } catch {
                        showToast('⚠️ Invalid URL');
                        return;
                    }
                }
            }

            if (mode === 'edit' && currentRuleEditInfo) {
                const info = currentRuleEditInfo;
                if (info.listType === 'custom') {
                    CACHE.customRules = CACHE.customRules.filter(r => r.id !== info.id);
                    sv('hider_custom_rules_v4', CACHE.customRules);
                } else if (info.listType === 'site') {
                    const key = 'hider_site_' + location.hostname;
                    let rules = gv(key, []);
                    if (info.index >= 0 && info.index < rules.length) {
                        rules.splice(info.index, 1);
                        sv(key, rules);
                    }
                } else if (info.listType === 'link') {
                    const key = 'hider_link_' + cleanUrl();
                    let rules = gv(key, []);
                    if (info.index >= 0 && info.index < rules.length) {
                        rules.splice(info.index, 1);
                        sv(key, rules);
                    }
                }
            }

            if (newScope === 'global') {
                const newRule = { id: 'rule_' + Date.now() + '_' + Math.random().toString(36).substr(2,4), selector: selector, target: '*' };
                CACHE.customRules.push(newRule);
                sv('hider_custom_rules_v4', CACHE.customRules);
                showToast(`🌍 Added global rule: ${selector}`);
            } else if (newScope === 'site') {
                const key = 'hider_site_' + targetValue;
                let rules = gv(key, []);
                if (!rules.includes(selector)) {
                    rules.push(selector);
                    sv(key, rules);
                    showToast(`🌐 Added site-wide rule for ${targetValue}: ${selector}`);
                } else {
                    showToast('⚠️ Rule already exists for this site');
                }
            } else if (newScope === 'link') {
                const key = 'hider_link_' + targetValue;
                let rules = gv(key, []);
                if (!rules.includes(selector)) {
                    rules.push(selector);
                    sv(key, rules);
                    showToast(`📄 Added page-only rule for ${targetValue}: ${selector}`);
                } else {
                    showToast('⚠️ Rule already exists for this page');
                }
            }

            overlay.remove();
            requestUpdateStyles();
            renderList();
            currentRuleEditInfo = null;
        };

        const cancel = () => {
            overlay.remove();
            currentRuleEditInfo = null;
        };

        saveBtn.addEventListener('click', saveRule);
        cancelBtn.addEventListener('click', cancel);
    }

    // ---------- 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.scope-global { background: linear-gradient(135deg, #a855f7, #7e22ce) !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">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%" style="display:block;">
                    <defs>
                        <radialGradient id="bgGradient" cx="50%" cy="50%" r="50%">
                            <stop offset="0%" stop-color="#1e293b" />
                            <stop offset="60%" stop-color="#0d121e" />
                            <stop offset="100%" stop-color="#050816" />
                        </radialGradient>
                        <linearGradient id="neonCyan" x1="0%" y1="0%" x2="100%" y2="100%">
                            <stop offset="0%" stop-color="#7dd3fc" />
                            <stop offset="50%" stop-color="#38bdf8" />
                            <stop offset="100%" stop-color="#0284c7" />
                        </linearGradient>
                        <linearGradient id="proGradient" x1="0%" y1="0%" x2="100%" y2="100%">
                            <stop offset="0%" stop-color="#fbbf24" />
                            <stop offset="100%" stop-color="#f59e0b" />
                        </linearGradient>
                        <linearGradient id="glassBorder" x1="0%" y1="0%" x2="100%" y2="100%">
                            <stop offset="0%" stop-color="#38bdf8" stop-opacity="0.9"/>
                            <stop offset="50%" stop-color="#1e293b" stop-opacity="0.3"/>
                            <stop offset="100%" stop-color="#38bdf8" stop-opacity="0.7"/>
                        </linearGradient>
                        <filter id="neonGlow" x="-20%" y="-20%" width="140%" height="140%">
                            <feGaussianBlur stdDeviation="8" result="blur" />
                            <feMerge>
                                <feMergeNode in="blur" />
                                <feMergeNode in="SourceGraphic" />
                            </feMerge>
                        </filter>
                        <filter id="proGlow" x="-20%" y="-20%" width="140%" height="140%">
                            <feGaussianBlur stdDeviation="4" result="blur" />
                            <feMerge>
                                <feMergeNode in="blur" />
                                <feMergeNode in="SourceGraphic" />
                            </feMerge>
                        </filter>
                    </defs>
                    <circle cx="256" cy="256" r="230" fill="url(#bgGradient)" stroke="url(#glassBorder)" stroke-width="6" filter="url(#neonGlow)"/>
                    <g stroke="#38bdf8" stroke-opacity="0.12" stroke-width="2">
                        <line x1="126" y1="180" x2="386" y2="180"/>
                        <line x1="126" y1="256" x2="386" y2="256"/>
                        <line x1="126" y1="332" x2="386" y2="332"/>
                        <line x1="180" y1="126" x2="180" y2="386"/>
                        <line x1="256" y1="126" x2="256" y2="386"/>
                        <line x1="332" y1="126" x2="332" y2="386"/>
                    </g>
                    <circle cx="256" cy="256" r="145" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="8 8" opacity="0.45" />
                    <g filter="url(#neonGlow)">
                        <path d="M 136 256 C 180 176, 332 176, 376 256 C 332 336, 180 336, 136 256 Z" 
                              fill="none" stroke="url(#neonCyan)" stroke-width="12" stroke-linejoin="round" stroke-linecap="round"/>
                        <circle cx="256" cy="256" r="46" fill="#0d121e" stroke="url(#neonCyan)" stroke-width="8"/>
                        <circle cx="256" cy="256" r="18" fill="#e0f2fe"/>
                        <line x1="150" y1="362" x2="362" y2="150" stroke="#f8fafc" stroke-width="12" stroke-linecap="round"/>
                        <line x1="150" y1="362" x2="362" y2="150" stroke="#38bdf8" stroke-width="6" stroke-linecap="round"/>
                    </g>
                    <g stroke="#e0f2fe" stroke-width="2.5" opacity="0.8">
                        <path d="M 360 130 L 360 154 M 348 142 L 372 142 M 351 133 L 369 151 M 351 151 L 369 133" />
                    </g>
                    <g transform="translate(85, 335)" filter="url(#proGlow)">
                        <rect x="0" y="0" width="112" height="50" rx="14" fill="#0d121e" stroke="url(#proGradient)" stroke-width="3.5"/>
                        <text x="56" y="34" font-family="system-ui, -apple-system, sans-serif" font-weight="900" font-size="25" fill="url(#proGradient)" text-anchor="middle" letter-spacing="3.5">PRO</text>
                    </g>
                </svg>
            </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/Link/Global)">🌐<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>

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

        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:6px;">
                    <div style="font-size:9px;color:#94a3b8;text-transform:uppercase;letter-spacing:0.5px;font-weight:700;">Basic</div>
                    <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:2px;">
                        <input type="checkbox" id="chk-auto-time-skipper" ${CACHE.autoTimeSkipper?'checked':''} style="accent-color:#f59e0b;"> Auto Time Skipper (Smart)
                    </label>

                    <div style="font-size:9px;color:#94a3b8;text-transform:uppercase;letter-spacing:0.5px;font-weight:700;margin-top:6px;border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">Overlays & Paywalls</div>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;">
                        <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>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;padding-left:16px;border-left:2px solid rgba(56,189,248,0.3);">
                        <input type="checkbox" id="chk-auto-accept-age" ${CACHE.autoAcceptAge?'checked':''} style="accent-color:#f59e0b;"> Auto‑Accept Age Verification
                    </label>
                    <label style="font-size:10px;color:#cbd5e1;display:flex;align-items:center;gap:6px;cursor:pointer;user-select:none;padding-left:16px;border-left:2px solid rgba(56,189,248,0.3);">
                        <input type="checkbox" id="chk-auto-close-logins" ${CACHE.autoCloseLogins?'checked':''} style="accent-color:#f59e0b;"> Auto‑Close Logins
                    </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="font-size:9px;color:#94a3b8;text-transform:uppercase;letter-spacing:0.5px;font-weight:700;margin-top:6px;border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">Dock Buttons</div>
                    <div id="dock-buttons-list" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:4px;"></div>
                </div>
            ` },
            { id: 'tab-rules', label: '✏️ Rules', html: `
                <div style="display:flex;flex-direction:column;gap:4px;">
                    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:2px;">
                        <span style="font-size:10px;color:#94a3b8;font-weight:700;">Custom Rules (<span id="cnt-custom">0</span>)</span>
                        <button class="hider-btn-small btn-blue" id="add-rule-btn" style="height:24px;padding:0 8px;">➕ Add Rule</button>
                    </div>
                    <div id="list-custom-rules" style="display:flex;flex-direction:column;gap:3px;"></div>
                    <div style="border-top:1px solid rgba(255,255,255,0.06);padding-top:4px;margin-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 style="margin-top:4px;text-align:right;">
                        <button class="hider-btn-small btn-red" id="clear-custom-rules" style="font-size:8px;padding:1px 5px;height:18px;">Clear All Custom Rules</button>
                    </div>
                </div>
            ` },
            { id: 'tab-freeze', label: '❄️ Freeze', html: `
                <div style="display:flex;flex-direction:column;gap:6px;">
                    <div style="font-size:9px;color:#94a3b8;text-transform:uppercase;letter-spacing:0.5px;font-weight:700;">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;width:100%;padding:4px;height:auto;font-size:9px;">Reset "Don't Ask Block" Prompt</button>
                    <div style="font-size:9px;color:#94a3b8;text-transform:uppercase;letter-spacing:0.5px;font-weight:700;margin-top:8px;border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">🚫 Blocked Domains</div>
                    <div style="display:flex;gap:4px;margin-bottom: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 id="list-blocked-domains" style="display:flex;flex-direction:column;gap:3px;"></div>
                    <div style="font-size:9px;color:#94a3b8;text-transform:uppercase;letter-spacing:0.5px;font-weight:700;margin-top:8px;border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">🟢 Allowed Domains</div>
                    <div style="display:flex;gap:4px;margin-bottom: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 id="list-allowed-domains" style="display:flex;flex-direction:column;gap:3px;"></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;margin-bottom:8px;">
                    <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-bottom:8px;">Export/Import all settings (rules, domains, toggles, logs).</div>

                <!-- ========== COOKIE MANAGER (without edit) ========== -->
                <div style="border-top:1px solid rgba(255,255,255,0.06);padding-top:8px;margin-top:4px;">
                    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;">
                        <span style="font-size:11px;font-weight:700;color:#f8fafc;">🍪 Cookies (<span id="cookie-count">0</span>)</span>
                        <input type="text" id="cookie-search" placeholder="🔍 Filter by name..." 
                               style="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;width:140px;">
                    </div>
                    <div id="cookie-list" style="display:flex;flex-direction:column;gap:3px;max-height:160px;overflow-y:auto;margin-bottom:6px;"></div>

                    <!-- Add cookie row -->
                    <div style="display:flex;gap:4px;flex-wrap:wrap;align-items:center;background:rgba(255,255,255,0.04);padding:4px;border-radius:6px;border:1px solid rgba(255,255,255,0.08);">
                        <input type="text" id="cookie-new-name" placeholder="name" style="flex:1;min-width:60px;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:24px;">
                        <input type="text" id="cookie-new-value" placeholder="value" style="flex:2;min-width:80px;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:24px;">
                        <input type="number" id="cookie-new-expiry" placeholder="days (opt)" min="0" step="1" style="width:60px;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:24px;">
                        <button class="hider-btn-small btn-green" id="cookie-add" style="height:24px;padding:0 10px;">➕ Add</button>
                    </div>

                    <!-- Action buttons -->
                    <div style="display:flex;gap:4px;margin-top:4px;flex-wrap:wrap;">
                        <button class="hider-btn-small btn-red" id="cookie-clear-all" style="height:24px;padding:0 10px;">🗑️ Clear All</button>
                        <button class="hider-btn-small btn-blue" id="cookie-export" style="height:24px;padding:0 10px;">📤 Export</button>
                        <button class="hider-btn-small btn-purple" id="cookie-import" style="height:24px;padding:0 10px;">📥 Import</button>
                        <input type="file" id="cookie-import-file" accept=".json" style="display:none;">
                    </div>
                </div>
            ` },
            { id: 'tab-about', label: 'ℹ️ About', html: `
                <div style="font-size:10px;color:#cbd5e1;line-height:1.6;padding:4px 0;">
                    <div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">
                        <div style="width:48px;height:48px;flex-shrink:0;">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="48" height="48">
                                <defs>
                                    <radialGradient id="aboutBg" cx="50%" cy="50%" r="50%">
                                        <stop offset="0%" stop-color="#1e293b" />
                                        <stop offset="100%" stop-color="#0d121e" />
                                    </radialGradient>
                                    <linearGradient id="aboutNeon" x1="0%" y1="0%" x2="100%" y2="100%">
                                        <stop offset="0%" stop-color="#7dd3fc" />
                                        <stop offset="100%" stop-color="#0284c7" />
                                    </linearGradient>
                                    <linearGradient id="aboutPro" x1="0%" y1="0%" x2="100%" y2="100%">
                                        <stop offset="0%" stop-color="#fbbf24" />
                                        <stop offset="100%" stop-color="#f59e0b" />
                                    </linearGradient>
                                </defs>
                                <circle cx="256" cy="256" r="220" fill="url(#aboutBg)" stroke="url(#aboutNeon)" stroke-width="4"/>
                                <path d="M 136 256 C 180 176, 332 176, 376 256 C 332 336, 180 336, 136 256 Z" 
                                      fill="none" stroke="url(#aboutNeon)" stroke-width="10"/>
                                <circle cx="256" cy="256" r="40" fill="#0d121e" stroke="url(#aboutNeon)" stroke-width="6"/>
                                <circle cx="256" cy="256" r="14" fill="#e0f2fe"/>
                                <line x1="150" y1="362" x2="362" y2="150" stroke="#f8fafc" stroke-width="10"/>
                                <line x1="150" y1="362" x2="362" y2="150" stroke="#38bdf8" stroke-width="4"/>
                                <text x="256" y="425" font-family="system-ui, -apple-system, sans-serif" font-weight="900" font-size="28" fill="url(#aboutPro)" text-anchor="middle" letter-spacing="4">PRO</text>
                            </svg>
                        </div>
                        <div>
                            <h3 style="font-size:14px;font-weight:800;color:#f8fafc;margin:0;">Hide Web Elements</h3>
                            <p style="font-size:10px;color:#94a3b8;margin:2px 0 0;"><strong style="color:gold;">Pro</strong> version • by KTZ</p>
                        </div>
                    </div>
                    <p style="font-size:10px;color:#94a3b8;margin:0 0 8px;">A powerful element hider with advanced navigation control, media extraction, and automatic challenge protection.</p>

                    <div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:8px 0;">
                        <div style="background:rgba(255,255,255,0.04);border-radius:6px;padding:6px 8px;border:1px solid rgba(255,255,255,0.06);">
                            <div style="font-size:11px;font-weight:700;color:#38bdf8;">🎯 Hide</div>
                            <div style="font-size:9px;color:#94a3b8;">Site, page, or global hiding</div>
                        </div>
                        <div style="background:rgba(255,255,255,0.04);border-radius:6px;padding:6px 8px;border:1px solid rgba(255,255,255,0.06);">
                            <div style="font-size:11px;font-weight:700;color:#34d399;">❄️ Freeze</div>
                            <div style="font-size:9px;color:#94a3b8;">Block/allow navigation</div>
                        </div>
                        <div style="background:rgba(255,255,255,0.04);border-radius:6px;padding:6px 8px;border:1px solid rgba(255,255,255,0.06);">
                            <div style="font-size:11px;font-weight:700;color:#a855f7;">🔗 Links</div>
                            <div style="font-size:9px;color:#94a3b8;">Extract & download media</div>
                        </div>
                        <div style="background:rgba(255,255,255,0.04);border-radius:6px;padding:6px 8px;border:1px solid rgba(255,255,255,0.06);">
                            <div style="font-size:11px;font-weight:700;color:#f59e0b;">⏩ Time Skipper</div>
                            <div style="font-size:9px;color:#94a3b8;">Jump forward 30s</div>
                        </div>
                        <div style="background:rgba(255,255,255,0.04);border-radius:6px;padding:6px 8px;border:1px solid rgba(255,255,255,0.06);">
                            <div style="font-size:11px;font-weight:700;color:#f43f5e;">👁️ Reveal</div>
                            <div style="font-size:9px;color:#94a3b8;">Unhide overlays & blur</div>
                        </div>
                        <div style="background:rgba(255,255,255,0.04);border-radius:6px;padding:6px 8px;border:1px solid rgba(255,255,255,0.06);">
                            <div style="font-size:11px;font-weight:700;color:#8b5cf6;">🛡️ Protection</div>
                            <div style="font-size:9px;color:#94a3b8;">Cloudflare/anti‑bot</div>
                        </div>
                    </div>

                    <div style="margin:8px 0;border-top:1px solid rgba(255,255,255,0.06);padding-top:8px;">
                        <div style="display:flex;gap:12px;flex-wrap:wrap;">
                            <div><span style="font-weight:700;color:#38bdf8;">Anti‑Paywall</span> <span style="color:#94a3b8;">•</span> <span style="color:#94a3b8;">Removes overlays</span></div>
                            <div><span style="font-weight:700;color:#38bdf8;">Auto‑Close Modals</span> <span style="color:#94a3b8;">•</span> <span style="color:#94a3b8;">Smart skip</span></div>
                            <div><span style="font-weight:700;color:#38bdf8;">Cookie Bypass</span> <span style="color:#94a3b8;">•</span> <span style="color:#94a3b8;">Accept/Reject</span></div>
                            <div><span style="font-weight:700;color:#38bdf8;">Media Downloader</span> <span style="color:#94a3b8;">•</span> <span style="color:#94a3b8;">Preview & save</span></div>
                        </div>
                    </div>

                    <div style="margin:8px 0;border-top:1px solid rgba(255,255,255,0.06);padding-top:8px;">
                        <div style="font-size:9px;color:#94a3b8;">
                            <span style="font-weight:700;color:#e2e8f0;">🔒 Protection:</span> Pauses features on Cloudflare challenges, resumes automatically.
                        </div>
                        <div style="font-size:9px;color:#94a3b8;margin-top:2px;">
                            <span style="font-weight:700;color:#e2e8f0;">💾 Storage:</span> All settings persist across restarts (GM_setValue/localStorage).
                        </div>
                        <div style="font-size:9px;color:#94a3b8;margin-top:2px;">
                            <span style="font-weight:700;color:#e2e8f0;">⌨️ Shortcuts:</span> <kbd style="background:rgba(255,255,255,0.08);padding:0 4px;border-radius:3px;">Esc</kbd> cancel selection/close panels • <kbd style="background:rgba(255,255,255,0.08);padding:0 4px;border-radius:3px;">Ctrl+Click</kbd> bypass freeze
                        </div>
                    </div>

                    <div style="margin-top:8px;font-size:8px;color:#64748b;text-align:center;border-top:1px solid rgba(255,255,255,0.06);padding-top:6px;">
                        Open source under MIT • Made with ❤️
                    </div>
                </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!'); };

        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 chkAutoAcceptAge = shadowBy('chk-auto-accept-age');
        if (chkAutoAcceptAge) {
            chkAutoAcceptAge.onchange = e => {
                CACHE.autoAcceptAge = e.target.checked;
                sv('hider_auto_accept_age', CACHE.autoAcceptAge);
                applyAllSettings();
                showToast(`✅ Auto-Accept Age: ${CACHE.autoAcceptAge ? 'ON' : 'OFF'}`);
            };
        }

        const chkAutoCloseLogins = shadowBy('chk-auto-close-logins');
        if (chkAutoCloseLogins) {
            chkAutoCloseLogins.onchange = e => {
                CACHE.autoCloseLogins = e.target.checked;
                sv('hider_auto_close_logins', CACHE.autoCloseLogins);
                applyAllSettings();
                showToast(`🔓 Auto-Close Logins: ${CACHE.autoCloseLogins ? '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) {
                    startAutoSkipMonitoring();
                    showToast('⏩ Auto Time Skipper enabled (smart)');
                } else {
                    stopAutoSkipMonitoring();
                    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');
        };

        const btnScope = shadowBy('btn-scope');
        btnScope.onclick = e => {
            e.stopPropagation();
            const scopes = ['site', 'link', 'global'];
            let idx = scopes.indexOf(currentScope);
            idx = (idx + 1) % scopes.length;
            currentScope = scopes[idx];
            btnScope.querySelector('span').textContent = currentScope.toUpperCase();
            btnScope.classList.toggle('scope-link', currentScope === 'link');
            btnScope.classList.toggle('scope-global', currentScope === 'global');
            const label = currentScope === 'site' ? '🌐 Site-wide' : currentScope === 'link' ? '📄 Page-only' : '🌍 Global';
            showToast(`Scope: ${label}`);
            broadcastState();
        };

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

        const addRuleBtn = shadowBy('add-rule-btn');
        if (addRuleBtn) {
            addRuleBtn.onclick = () => {
                showRuleOverlay({ mode: 'add', scope: 'global' });
            };
        }

        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');
            } else {
                clearSelectionState();
                showToast('🎯 Selection mode OFF');
            }
            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'); };

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

        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 (without edit) ----------
        const cookieListEl = shadowBy('cookie-list');
        const cookieCountEl = shadowBy('cookie-count');
        const cookieSearch = shadowBy('cookie-search');
        const cookieAddBtn = shadowBy('cookie-add');
        const cookieNameInput = shadowBy('cookie-new-name');
        const cookieValueInput = shadowBy('cookie-new-value');
        const cookieExpiryInput = shadowBy('cookie-new-expiry');
        const cookieClearAll = shadowBy('cookie-clear-all');
        const cookieExportBtn = shadowBy('cookie-export');
        const cookieImportBtn = shadowBy('cookie-import');
        const cookieImportFile = shadowBy('cookie-import-file');

        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(filter = '') {
            if (!cookieListEl) return;
            const cookies = getCookies();
            const filtered = filter ? cookies.filter(c => c.name.toLowerCase().includes(filter.toLowerCase())) : cookies;
            cookieCountEl.textContent = filtered.length;

            if (filtered.length === 0) {
                cookieListEl.innerHTML = `<div style="font-size:9px;color:#94a3b8;text-align:center;padding:4px;">${cookies.length ? 'No matching cookies' : 'No cookies for this domain.'}</div>`;
                return;
            }

            cookieListEl.innerHTML = '';
            filtered.forEach(c => {
                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;border:1px solid rgba(255,255,255,0.06);';
                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;';

                // Delete button only (no edit)
                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 = (e) => {
                    e.stopPropagation();
                    if (confirm(`Delete cookie "${c.name}"?`)) {
                        // Try multiple deletion variants
                        document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${location.hostname}`;
                        document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
                        document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
                        renderCookies(cookieSearch ? cookieSearch.value : '');
                        showToast(`🍪 Deleted cookie: ${c.name}`);
                    }
                };
                btnGroup.appendChild(delBtn);
                row.appendChild(nameSpan);
                row.appendChild(valSpan);
                row.appendChild(btnGroup);
                cookieListEl.appendChild(row);
            });
        }

        // Add cookie
        function addCookie() {
            const name = cookieNameInput ? cookieNameInput.value.trim() : '';
            const value = cookieValueInput ? cookieValueInput.value.trim() : '';
            const days = cookieExpiryInput ? parseInt(cookieExpiryInput.value, 10) : 0;
            if (!name) { showToast('⚠️ Enter cookie name'); return; }
            let cookieStr = `${name}=${value}; path=/; domain=${location.hostname}`;
            if (days > 0) {
                const exp = new Date(Date.now() + days * 24 * 60 * 60 * 1000);
                cookieStr += `; expires=${exp.toUTCString()}`;
            }
            document.cookie = cookieStr;
            if (cookieNameInput) cookieNameInput.value = '';
            if (cookieValueInput) cookieValueInput.value = '';
            if (cookieExpiryInput) cookieExpiryInput.value = '';
            renderCookies(cookieSearch ? cookieSearch.value : '');
            showToast(`🍪 Added cookie: ${name}`);
        }

        // Clear all cookies for current domain
        function clearAllCookies() {
            if (!confirm('Delete ALL cookies for this domain?')) return;
            const cookies = getCookies();
            cookies.forEach(c => {
                document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${location.hostname}`;
                document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
                document.cookie = `${c.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
            });
            renderCookies(cookieSearch ? cookieSearch.value : '');
            showToast(`🗑️ Cleared ${cookies.length} cookies`);
        }

        // Export cookies
        function exportCookies() {
            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');
        }

        // Import cookies
        function importCookies(file) {
            const reader = new FileReader();
            reader.onload = function(e) {
                try {
                    const data = JSON.parse(e.target.result);
                    if (!Array.isArray(data)) throw new Error('Not an array');
                    data.forEach(c => {
                        if (c.name && c.value !== undefined) {
                            document.cookie = `${c.name}=${c.value}; path=/; domain=${location.hostname}`;
                        }
                    });
                    renderCookies(cookieSearch ? cookieSearch.value : '');
                    showToast(`🍪 Imported ${data.length} cookies`);
                } catch (err) {
                    showToast('❌ Invalid cookie JSON');
                }
            };
            reader.readAsText(file);
        }

        // Event listeners
        if (cookieAddBtn) cookieAddBtn.onclick = addCookie;
        if (cookieNameInput) cookieNameInput.onkeypress = e => e.key === 'Enter' && addCookie();
        if (cookieValueInput) cookieValueInput.onkeypress = e => e.key === 'Enter' && addCookie();
        if (cookieExpiryInput) cookieExpiryInput.onkeypress = e => e.key === 'Enter' && addCookie();
        if (cookieClearAll) cookieClearAll.onclick = clearAllCookies;
        if (cookieExportBtn) cookieExportBtn.onclick = exportCookies;
        if (cookieImportBtn) cookieImportBtn.onclick = () => cookieImportFile?.click();
        if (cookieImportFile) {
            cookieImportFile.onchange = function() {
                if (this.files && this.files[0]) {
                    importCookies(this.files[0]);
                    this.value = '';
                }
            };
        }
        if (cookieSearch) {
            cookieSearch.oninput = function() {
                renderCookies(this.value);
            };
        }

        // Initial render
        renderCookies();

        // ---------- End of Cookie Manager ----------

        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',
                'hider_auto_accept_age', 'hider_auto_close_logins'
            ];
            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, idx) => {
                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 = () => {
                    showRuleOverlay({
                        mode: 'edit',
                        selector: rule.selector,
                        scope: 'global',
                        target: rule.target,
                        editInfo: { listType: 'custom', id: rule.id, index: idx }
                    });
                };
                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 = () => {
                    let scope = 'site';
                    let target = location.hostname;
                    if (key === linkKey) {
                        scope = 'link';
                        target = cleanUrl();
                    }
                    const listType = (key === siteKey) ? 'site' : 'link';
                    showRuleOverlay({
                        mode: 'edit',
                        selector: sel,
                        scope: scope,
                        target: target,
                        editInfo: { listType: listType, index: i }
                    });
                };

                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);
                    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();
        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 (SMART) ----------
    const checkUrlChange = () => {
        if (location.href !== lastUrl) { 
            lastUrl = location.href; 
            updateCurrentLocCache();
            requestUpdateStyles(false);
            if (shadowBy('hider-panel')?.classList.contains('is-visible')) renderList(); 
        }
    };

    window.addEventListener('pageshow', (e) => {
        if (e.persisted || e.type === 'pageshow') {
            requestUpdateStyles(true);
        }
    }, { passive: true });

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

    // ---------- 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(true);
        setupScrollAutoClose();
        setupLowPowerHeartbeat();
        setupProtectionObserver();
        applyAllSettings();
        if (CACHE.autoTimeSkipper && featuresEnabled) {
            startAutoSkipMonitoring();
        }
    }

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