Greasy Fork is available in English.

Safety Shield Pro v1

Production-grade privacy shield. Split-phase init, dynamic reconfig, extensible rules.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

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

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

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

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

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

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

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

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

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

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

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         Safety Shield Pro v1
// @namespace    https://greasyfork.org/fr/scripts/565749-safety-shield-pro/code
// @version      1.0.1
// @license      MIT
// @description  Production-grade privacy shield. Split-phase init, dynamic reconfig, extensible rules.
// @match        *://*/*
// @run-at       document-start
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
    'use strict';

    const VERSION = '6.0';
    const host = location.host;
    const EventBus = {
        listeners: {},

        on(event, callback) {
            if (!this.listeners[event]) this.listeners[event] = [];
            this.listeners[event].push(callback);
        },

        emit(event, data) {
            if (!this.listeners[event]) return;
            this.listeners[event].forEach(cb => {
                try {
                    cb(data);
                } catch (err) {
                    console.error(`[EventBus] Error in ${event}:`, err);
                }
            });
        },

        off(event, callback) {
            if (!this.listeners[event]) return;
            this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
        }
    };
    const SafetyShield = {
        version: VERSION,
        host: host,
        profile: 'balanced',
        initialized: {
            core: false,
            ui: false
        },
        state: {
            blockedLog: [],
            stats: {}
        },
        settings: {},
        modules: {},
        ui: {},
        observers: [],
        rules: {
            trackers: [],
            ads: []
        },
        debug: {
            enabled: false,
            log: []
        }
    };
    const BUILTIN_RULES = {
        trackers: [
            { domain: 'google-analytics.com' },
            { domain: 'analytics.google.com' },
            { domain: 'facebook.com' },
            { domain: 'fbcdn.net' },
            { domain: 'doubleclick.net' },
            { domain: 'googlesyndication.com' },
            { domain: 'amazon-adsystem.com' },
            { domain: 'hotjar.com' },
            { domain: 'mixpanel.com' },
            { domain: 'segment.com' },
            { domain: 'amplitude.com' },
            { domain: 'intercom.io' },
            { domain: 'drift.com' },
            { domain: 'optimizely.com' }
        ],
        ads: [
            { domain: 'doubleclick.net' },
            { domain: 'googlesyndication.com' },
            { domain: 'amazon-adsystem.com' },
            { regex: /adserver|adnetwork|adexchange|ads\./ }
        ]
    };
    const Debug = {
        enable() {
            SafetyShield.debug.enabled = true;
            console.log('[SAFETY SHIELD] Debug mode enabled');
        },

        disable() {
            SafetyShield.debug.enabled = false;
            console.log('[SAFETY SHIELD] Debug mode disabled');
        },

        log(msg) {
            if (!SafetyShield.debug.enabled) return;
            SafetyShield.debug.log.push({
                msg,
                time: new Date().toLocaleTimeString()
            });
            console.log(`[DEBUG] ${msg}`);
        },

        inspect() {
            return {
                profile: SafetyShield.profile,
                settings: SafetyShield.settings,
                observersActive: SafetyShield.observers.length,
                trackerRules: SafetyShield.rules.trackers.length,
                adRules: SafetyShield.rules.ads.length,
                stats: SafetyShield.state.stats,
                recentBlocks: SafetyShield.state.blockedLog.slice(-20)
            };
        }
    };
    const PROFILES = {
        relaxed: {
            exeBlockEnabled: true,
            trackerBlockEnabled: false,
            adBlockEnabled: false,
            redirectBlockEnabled: false,
            dnsPrefetchBlock: false,
            fingerprintProtect: 'off',
            scriptInjectionBlock: 'off'
        },
        balanced: {
            exeBlockEnabled: true,
            trackerBlockEnabled: true,
            adBlockEnabled: true,
            redirectBlockEnabled: false,
            dnsPrefetchBlock: true,
            fingerprintProtect: 'light',
            scriptInjectionBlock: 'external'
        },
        paranoid: {
            exeBlockEnabled: true,
            trackerBlockEnabled: true,
            adBlockEnabled: true,
            redirectBlockEnabled: true,
            dnsPrefetchBlock: true,
            fingerprintProtect: 'aggressive',
            scriptInjectionBlock: 'external'
        }
    };

    const SettingsManager = {
        defaults: PROFILES.balanced,

        init() {
            const savedProfile = GM_getValue('profile');
            if (savedProfile && PROFILES[savedProfile]) {
                SafetyShield.profile = savedProfile;
                const profile = PROFILES[savedProfile];
                for (const [key, value] of Object.entries(profile)) {
                    SafetyShield.settings[key] = value;
                }
            } else {
                for (const [key, value] of Object.entries(this.defaults)) {
                    const stored = GM_getValue(key);
                    SafetyShield.settings[key] = stored !== undefined ? stored : value;
                }
            }
            Debug.log('Settings initialized');
        },

        get(key) {
            return SafetyShield.settings[key] ?? this.defaults[key];
        },

        set(key, value) {
            const oldValue = SafetyShield.settings[key];
            SafetyShield.settings[key] = value;
            GM_setValue(key, value);
            GM_setValue('profile', null);
            Debug.log(`Setting ${key}: ${oldValue} → ${value}`);
            EventBus.emit('setting-changed', { key, oldValue, newValue: value });
        },

        setProfile(profileName) {
            if (!PROFILES[profileName]) return false;
            SafetyShield.profile = profileName;
            GM_setValue('profile', profileName);
            const profile = PROFILES[profileName];
            for (const [key, value] of Object.entries(profile)) {
                SafetyShield.settings[key] = value;
                GM_setValue(key, value);
            }
            Debug.log(`Profile switched to: ${profileName}`);
            EventBus.emit('profile-changed', { profile: profileName });
            return true;
        }
    };
    const RulesManager = {
        init() {
            SafetyShield.rules.trackers = [...BUILTIN_RULES.trackers];
            SafetyShield.rules.ads = [...BUILTIN_RULES.ads];
        },

        addTrackerRule(rule) {
            SafetyShield.rules.trackers.push(rule);
            Debug.log(`Added tracker rule: ${rule.domain || rule.regex}`);
        },

        addAdRule(rule) {
            SafetyShield.rules.ads.push(rule);
            Debug.log(`Added ad rule: ${rule.domain || rule.regex}`);
        },

        matchesTracker(url) {
            return this._matchRules(url, SafetyShield.rules.trackers);
        },

        matchesAd(url) {
            return this._matchRules(url, SafetyShield.rules.ads);
        },

        _matchRules(url, rules) {
            try {
                const hostname = new URL(url, location.href).hostname;
                return rules.some(rule => {
                    if (rule.domain) {
                        return hostname === rule.domain || hostname.endsWith('.' + rule.domain);
                    }
                    if (rule.regex && rule.regex instanceof RegExp) {
                        return rule.regex.test(hostname);
                    }
                    return false;
                });
            } catch {
                return false;
            }
        }
    };
    const Logger = {
        MAX_ENTRIES: 150,

        log(url, type) {
            const entry = {
                url: String(url || '').substring(0, 120),
                type,
                time: new Date().toLocaleTimeString()
            };

            SafetyShield.state.blockedLog.push(entry);
            if (SafetyShield.state.blockedLog.length > this.MAX_ENTRIES) {
                SafetyShield.state.blockedLog.shift();
            }

            SafetyShield.state.stats[type] = (SafetyShield.state.stats[type] || 0) + 1;

            Debug.log(`Blocked ${type}: ${url}`);
            EventBus.emit('block', { url, type, total: SafetyShield.state.blockedLog.length });
        },

        clear() {
            SafetyShield.state.blockedLog = [];
            SafetyShield.state.stats = {};
            Debug.log('Log cleared');
            EventBus.emit('log-cleared', {});
        },

        getTotal() {
            return SafetyShield.state.blockedLog.length;
        }
    };
    const Detectors = {
        getHostname(url) {
            try {
                if (!url || typeof url !== 'string') return '';
                return new URL(url, location.href).hostname;
            } catch {
                return '';
            }
        },

        isExternal(url) {
            try {
                if (!url || typeof url !== 'string') return false;
                const urlObj = new URL(url, location.href);
                return urlObj.host !== host;
            } catch {
                return false;
            }
        },

        isExe(url) {
            return SettingsManager.get('exeBlockEnabled') &&
                typeof url === 'string' &&
                /\.exe(\?|#|$)/i.test(url);
        },

        isTracker(url) {
            if (!SettingsManager.get('trackerBlockEnabled') || !url || typeof url !== 'string') {
                return false;
            }
            return RulesManager.matchesTracker(url);
        },

        isAd(url) {
            if (!SettingsManager.get('adBlockEnabled') || !url || typeof url !== 'string') {
                return false;
            }
            return RulesManager.matchesAd(url);
        }
    };
    SafetyShield.modules.redirect = {
        name: 'redirect',
        enabled: false,
        originalAssign: location.assign,
        originalReplace: location.replace,
        originalOpen: window.open,
        originalHrefDescriptor: null,

        shouldBlock(url) {
            if (!url || typeof url !== 'string') return false;

            if (Detectors.isExe(url)) {
                Logger.log(url, 'exe');
                return true;
            }
            if (Detectors.isTracker(url)) {
                Logger.log(url, 'tracker');
                return true;
            }
            if (Detectors.isAd(url)) {
                Logger.log(url, 'ad');
                return true;
            }
            if (SettingsManager.get('redirectBlockEnabled') && Detectors.isExternal(url)) {
                Logger.log(url, 'redirect');
                return true;
            }
            return false;
        },
        initCore() {
            if (this.enabled) return;

            const self = this;
            const guard = (fn, originalFn) => {
                const wrapper = function (url, ...args) {
                    if (self.shouldBlock(url)) return undefined;
                    return fn.call(this, url, ...args);
                };
                wrapper.toString = () => originalFn.toString();
                return wrapper;
            };
            location.assign = guard(this.originalAssign, this.originalAssign);
            location.replace = guard(this.originalReplace, this.originalReplace);
            window.open = guard(this.originalOpen, this.originalOpen);
            this.patchLocationHref();

            this.enabled = true;
            Debug.log('Redirect module: Core phase initialized');
        },
        initUI() {
            if (!this.enabled) {
                this.initCore();
            }
            this.setupLinkProtection();
            Debug.log('Redirect module: UI phase initialized');
        },

        patchLocationHref() {
            const self = this;
            try {
                const locationProto = Location.prototype;
                const hrefDescriptor = Object.getOwnPropertyDescriptor(locationProto, 'href');

                if (!hrefDescriptor) {
                    Debug.log('Could not get href descriptor (unsupported browser)');
                    return;
                }

                this.originalHrefDescriptor = hrefDescriptor;

                Object.defineProperty(locationProto, 'href', {
                    get: hrefDescriptor.get,
                    set(url) {
                        if (self.shouldBlock(url)) {
                            return;
                        }
                        hrefDescriptor.set.call(this, url);
                    },
                    configurable: true
                });

                Debug.log('location.href patched');
            } catch (err) {
                Debug.log(`Could not patch location.href: ${err.message}`);
            }
        },

        setupLinkProtection() {
            const self = this;
            document.addEventListener("click", (e) => {
                const a = e.target.closest("a[href]");
                if (!a || !a.href || typeof a.href !== 'string') return;

                if (self.shouldBlock(a.href)) {
                    e.preventDefault();
                    e.stopPropagation();
                    e.stopImmediatePropagation();
                }
            }, true);
        },

        enable() {
            if (this.enabled) return;
            this.initCore();
            this.initUI();
        },

        disable() {
            if (!this.enabled) return;
            location.assign = this.originalAssign;
            location.replace = this.originalReplace;
            window.open = this.originalOpen;
            if (this.originalHrefDescriptor) {
                Object.defineProperty(Location.prototype, 'href', this.originalHrefDescriptor);
            }
            this.enabled = false;
            Debug.log('Redirect module disabled');
        }
    };
    SafetyShield.modules.tracker = {
        name: 'tracker',
        enabled: false,
        observer: null,
        timeout: null,

        initCore() {
            if (!SettingsManager.get('trackerBlockEnabled')) return;
            this.removeDnsPrefetch();
            this.cleanTrackers();
        },

        initUI() {
            if (!SettingsManager.get('trackerBlockEnabled')) return;
            if (!this.enabled) {
                this.startObserver();
                this.enabled = true;
                Debug.log('Tracker module initialized');
            }
        },

        removeDnsPrefetch() {
            if (!SettingsManager.get('dnsPrefetchBlock')) return;

            try {
                document.querySelectorAll('link[rel="dns-prefetch"]').forEach(link => {
                    Logger.log(link.href, 'dns-prefetch');
                    link.remove();
                });
            } catch (err) {}
        },

        cleanTrackers() {
            const selectors = [
                'img[src*="analytics"]',
                'img[src*="track"]',
                'img[src*="pixel"]',
                'img[src*="beacon"]'
            ];

            selectors.forEach(sel => {
                try {
                    document.querySelectorAll(sel).forEach(el => {
                        if (el.src && Detectors.isTracker(el.src)) {
                            Logger.log(el.src, 'tracking-pixel');
                            el.remove();
                        }
                    });
                } catch (err) {}
            });
        },

        startObserver() {
            if (this.observer) return;

            const self = this;
            this.observer = new MutationObserver(() => {
                clearTimeout(self.timeout);
                self.timeout = setTimeout(() => self.cleanTrackers(), 100);
            });

            try {
                this.observer.observe(document.documentElement, {
                    childList: true,
                    subtree: true
                });
                SafetyShield.observers.push(this.observer);
            } catch (err) {}
        },

        enable() {
            if (this.enabled) return;
            SettingsManager.set('trackerBlockEnabled', true);
            this.initUI();
        },

        disable() {
            if (!this.enabled) return;
            if (this.observer) {
                this.observer.disconnect();
                SafetyShield.observers = SafetyShield.observers.filter(o => o !== this.observer);
                this.observer = null;
            }
            clearTimeout(this.timeout);
            this.enabled = false;
            Debug.log('Tracker module disabled');
        }
    };
    SafetyShield.modules.ads = {
        name: 'ads',
        enabled: false,
        observer: null,
        timeout: null,

        initCore() {
            if (!SettingsManager.get('adBlockEnabled')) return;
            this.cleanAds();
        },

        initUI() {
            if (!SettingsManager.get('adBlockEnabled')) return;
            if (!this.enabled) {
                this.startObserver();
                this.enabled = true;
                Debug.log('Ad blocking module initialized');
            }
        },

        cleanAds() {
            const adSelectors = [
                '[id*="ad-"]',
                '[id*="-ad"]',
                '[class*=" ad-"]',
                '[class*="-ad-"]',
                '[class*="advert"]',
                '[data-ad-slot]',
                '[data-ad-format]'
            ];

            adSelectors.forEach(sel => {
                try {
                    document.querySelectorAll(sel).forEach(el => {
                        try {
                            const identifier = el.src || el.id || el.className || '';
                            if (Detectors.isAd(identifier)) {
                                Logger.log(identifier, 'ad');
                                el.remove();
                            }
                        } catch (e) {}
                    });
                } catch (err) {}
            });

            try {
                document.querySelectorAll("iframe").forEach(f => {
                    try {
                        if (f.src && (Detectors.isTracker(f.src) || Detectors.isAd(f.src))) {
                            Logger.log(f.src, 'external-iframe');
                            f.remove();
                        }
                    } catch (e) {}
                });
            } catch (err) {}

            try {
                document.querySelectorAll('meta[http-equiv="refresh"]').forEach(m => {
                    Logger.log(m.content, 'meta-refresh');
                    m.remove();
                });
            } catch (err) {}
        },

        startObserver() {
            if (this.observer) return;

            const self = this;
            this.observer = new MutationObserver(() => {
                clearTimeout(self.timeout);
                self.timeout = setTimeout(() => self.cleanAds(), 150);
            });

            try {
                this.observer.observe(document.documentElement, {
                    childList: true,
                    subtree: true
                });
                SafetyShield.observers.push(this.observer);
            } catch (err) {}
        },

        enable() {
            if (this.enabled) return;
            SettingsManager.set('adBlockEnabled', true);
            this.initUI();
        },

        disable() {
            if (!this.enabled) return;
            if (this.observer) {
                this.observer.disconnect();
                SafetyShield.observers = SafetyShield.observers.filter(o => o !== this.observer);
                this.observer = null;
            }
            clearTimeout(this.timeout);
            this.enabled = false;
            Debug.log('Ad blocking module disabled');
        }
    };
    SafetyShield.modules.scriptInjection = {
        name: 'scriptInjection',
        enabled: false,
        observer: null,

        initCore() {
        },

        initUI() {
            const mode = SettingsManager.get('scriptInjectionBlock');
            if (mode === 'off' || this.enabled) return;

            this.startObserver();
            this.enabled = true;
            Debug.log('Script injection module initialized');
        },

        blockScript(node) {
            const src = node.src || '';

            if (src && (Detectors.isTracker(src) || Detectors.isAd(src))) {
                Logger.log(src, 'external-script');
                return true;
            }

            return false;
        },

        startObserver() {
            if (this.observer) return;

            const self = this;
            this.observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    mutation.addedNodes.forEach((node) => {
                        try {
                            if (node.tagName === 'SCRIPT' && self.blockScript(node)) {
                                node.remove();
                            }
                        } catch (e) {}
                    });
                });
            });

            try {
                this.observer.observe(document.documentElement, {
                    childList: true,
                    subtree: true
                });
                SafetyShield.observers.push(this.observer);
            } catch (err) {}
        },

        enable() {
            if (this.enabled) return;
            SettingsManager.set('scriptInjectionBlock', 'external');
            this.initUI();
        },

        disable() {
            if (!this.enabled) return;
            if (this.observer) {
                this.observer.disconnect();
                SafetyShield.observers = SafetyShield.observers.filter(o => o !== this.observer);
                this.observer = null;
            }
            this.enabled = false;
            Debug.log('Script injection module disabled');
        }
    };
    SafetyShield.modules.fingerprint = {
        name: 'fingerprint',
        enabled: false,
        originalCanvasToDataURL: null,
        originalWebGLGetParameter: null,

        initCore() {
            const mode = SettingsManager.get('fingerprintProtect');
            if (mode === 'off') return;

            this.spoof();

            if (mode === 'light') {
                this.protectCanvas();
            } else if (mode === 'aggressive') {
                this.protectCanvas();
                this.protectWebGL();
            }

            this.enabled = true;
            Debug.log('Fingerprint protection initialized');
        },

        initUI() {
        },

        spoof() {
            try {
                Object.defineProperty(navigator, 'language', {
                    get: () => 'en-US',
                    configurable: true
                });

                Object.defineProperty(navigator, 'languages', {
                    get: () => ['en-US', 'en'],
                    configurable: true
                });

                Object.defineProperty(navigator, 'platform', {
                    get: () => 'Linux x86_64',
                    configurable: true
                });
            } catch (err) {}
        },

        protectCanvas() {
            try {
                this.originalCanvasToDataURL = HTMLCanvasElement.prototype.toDataURL;
                const originalFn = this.originalCanvasToDataURL;

                HTMLCanvasElement.prototype.toDataURL = function (...args) {
                    Logger.log('canvas.toDataURL', 'fingerprint-attempt');
                    return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
                };
                HTMLCanvasElement.prototype.toDataURL.toString = () => originalFn.toString();
            } catch (err) {}
        },

        protectWebGL() {
            try {
                this.originalWebGLGetParameter = WebGLRenderingContext.prototype.getParameter;
                const originalFn = this.originalWebGLGetParameter;

                WebGLRenderingContext.prototype.getParameter = function (parameter) {
                    if (parameter === 37445 || parameter === 37446) {
                        Logger.log(`WebGL.parameter(${parameter})`, 'fingerprint-attempt');
                        return 'Generic GPU';
                    }
                    return originalFn.call(this, parameter);
                };

                WebGLRenderingContext.prototype.getParameter.toString = () => originalFn.toString();
            } catch (err) {}

            try {
                const originalFn2 = WebGL2RenderingContext.prototype.getParameter;
                WebGL2RenderingContext.prototype.getParameter = function (parameter) {
                    if (parameter === 37445 || parameter === 37446) {
                        return 'Generic GPU';
                    }
                    return originalFn2.call(this, parameter);
                };
            } catch (err) {}
        },

        enable() {
            if (this.enabled) return;
            SettingsManager.set('fingerprintProtect', 'light');
            this.initCore();
        },

        disable() {
            if (!this.enabled) return;
            if (this.originalCanvasToDataURL) {
                HTMLCanvasElement.prototype.toDataURL = this.originalCanvasToDataURL;
            }
            if (this.originalWebGLGetParameter) {
                WebGLRenderingContext.prototype.getParameter = this.originalWebGLGetParameter;
            }
            this.enabled = false;
            Debug.log('Fingerprint protection disabled');
        }
    };
    SafetyShield.ui.statusButton = null;

    SafetyShield.ui.createButton = () => {
        const btn = document.createElement("div");
        btn.id = "safety-shield-status";
        btn.style.cssText = `
            position: fixed;
            bottom: 12px;
            right: 12px;
            z-index: 999999;
            padding: 6px 10px;
            font-size: 11px;
            font-family: monospace;
            cursor: pointer;
            border-radius: 4px;
            background: rgba(15, 23, 42, 0.9);
            color: #22c55e;
            opacity: 0.7;
            border: 1px solid #16a34a;
            transition: all 0.2s;
            user-select: none;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
        `;

        btn.onmouseover = () => {
            btn.style.opacity = "1";
            btn.style.boxShadow = "0 4px 12px rgba(34, 197, 94, 0.4)";
        };

        btn.onmouseout = () => {
            btn.style.opacity = "0.7";
            btn.style.boxShadow = "0 2px 8px rgba(0, 0, 0, 0.3)";
        };

        document.documentElement.appendChild(btn);
        return btn;
    };

    SafetyShield.ui.updateButton = () => {
        if (!SafetyShield.ui.statusButton) return;

        const total = Logger.getTotal();
        const status = [
            SettingsManager.get('exeBlockEnabled') ? 'E' : '',
            SettingsManager.get('trackerBlockEnabled') ? 'T' : '',
            SettingsManager.get('adBlockEnabled') ? 'A' : '',
            SettingsManager.get('redirectBlockEnabled') ? 'R' : ''
        ].filter(Boolean).join('');

        const display = status ? `${status} (${total})` : `○ (${total})`;
        SafetyShield.ui.statusButton.textContent = display;
        SafetyShield.ui.statusButton.title =
            `Safety Shield v${VERSION}\nProfile: ${SafetyShield.profile}\nBlocked: ${total}\nPress ? for help | D for debug`;
    };

    SafetyShield.ui.showHelp = () => {
        const existing = document.getElementById('safety-shield-help');
        if (existing) {
            existing.remove();
            return;
        }

        const helpDiv = document.createElement('div');
        helpDiv.id = 'safety-shield-help';
        helpDiv.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 99999999;
            background: rgba(15, 23, 42, 0.98);
            color: #22c55e;
            padding: 24px;
            border-radius: 8px;
            border: 2px solid #16a34a;
            font-family: 'Courier New', monospace;
            font-size: 12px;
            max-width: 540px;
            max-height: 720px;
            overflow-y: auto;
            line-height: 1.7;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
        `;

        helpDiv.innerHTML = `
            <div style="margin-bottom: 16px;">
                <strong style="color: #60a5fa; font-size: 14px;">Safety Shield v${VERSION}</strong>
                <div style="font-size: 10px; color: #888; margin-top: 4px;">Profile: <strong>${SafetyShield.profile}</strong></div>
            </div>

            <div style="margin-bottom: 12px; border-bottom: 1px solid #16a34a; padding-bottom: 8px;">
                <strong style="color: #60a5fa;">⌨️  KEYBOARD SHORTCUTS:</strong>
            </div>

            <div style="margin-bottom: 16px; font-size: 11px;">
                <strong style="color: #4ade80;">L</strong> - Toggle EXE blocking<br>
                <strong style="color: #4ade80;">T</strong> - Toggle tracker blocking<br>
                <strong style="color: #4ade80;">A</strong> - Toggle ad blocking<br>
                <strong style="color: #4ade80;">R</strong> - Toggle redirect blocking<br>
                <strong style="color: #4ade80;">C</strong> - Clear blocked log<br>
                <strong style="color: #4ade80;">1/2/3</strong> - Profiles (relaxed/balanced/paranoid)<br>
                <strong style="color: #4ade80;">D</strong> - Toggle debug mode (F12)<br>
                <strong style="color: #4ade80;">?</strong> - Toggle this help<br>
            </div>

            <div style="margin-bottom: 12px; border-bottom: 1px solid #16a34a; padding-bottom: 8px;">
                <strong style="color: #60a5fa;">PROFILES:</strong>
            </div>

            <div style="font-size: 10px; margin-bottom: 16px; background: rgba(34, 197, 94, 0.1); padding: 8px; border-radius: 4px;">
                <strong>1 - Relaxed:</strong> EXE only<br>
                <strong>2 - Balanced:</strong> Standard (recommended)<br>
                <strong>3 - Paranoid:</strong> Maximum protection<br>
            </div>

            <div style="font-size: 10px; color: #888;">
                <strong>⚠️  HONEST ASSESSMENT:</strong><br>
                This script provides <strong>low false positives</strong>, not zero. Some sites require adjustments:
                <ul style="margin: 4px 0; padding-left: 16px;">
                    <li>OAuth logins (Google, GitHub)</li>
                    <li>Payment processors (Stripe, PayPal)</li>
                    <li>CAPTCHA services</li>
                </ul>
                Use profile <strong>1</strong> or <strong>2</strong> if issues occur.
            </div>

            <div style="margin-top: 12px; background: rgba(34, 197, 94, 0.1); padding: 8px; border-radius: 4px; font-size: 10px;">
                <strong>TECHNICAL:</strong><br>
                Race condition fixed: Split-phase init (core at document-start, UI at DOMContentLoaded).<br>
                Extensible rules system. Dynamic module enable/disable. Debug mode available.
            </div>

            <div style="text-align: center; cursor: pointer; padding: 10px; background: rgba(34, 197, 94, 0.2); border-radius: 4px; user-select: none; border: 1px solid rgba(34, 197, 94, 0.4); margin-top: 12px;">
                <strong>Press ? to close</strong>
            </div>
        `;

        document.documentElement.appendChild(helpDiv);
        helpDiv.addEventListener('click', SafetyShield.ui.showHelp);
    };
    EventBus.on('block', () => {
        SafetyShield.ui.updateButton();
    });

    EventBus.on('log-cleared', () => {
        SafetyShield.ui.updateButton();
    });

    EventBus.on('setting-changed', (data) => {
        SafetyShield.ui.updateButton();
    });

    EventBus.on('profile-changed', () => {
        SafetyShield.ui.updateButton();
    });
    document.addEventListener("keydown", (e) => {
        if (e.target.tagName.match(/INPUT|TEXTAREA|SELECT/)) return;

        const key = e.key.toLowerCase();
        const hasModifier = e.ctrlKey || e.metaKey || e.altKey;

        if (!hasModifier) {
            if (key === 'l') {
                SettingsManager.set('exeBlockEnabled', !SettingsManager.get('exeBlockEnabled'));
            }

            if (key === 't') {
                if (SettingsManager.get('trackerBlockEnabled')) {
                    SafetyShield.modules.tracker.disable();
                } else {
                    SafetyShield.modules.tracker.enable();
                }
            }

            if (key === 'a') {
                if (SettingsManager.get('adBlockEnabled')) {
                    SafetyShield.modules.ads.disable();
                } else {
                    SafetyShield.modules.ads.enable();
                }
            }

            if (key === 'r') {
                SettingsManager.set('redirectBlockEnabled', !SettingsManager.get('redirectBlockEnabled'));
            }

            if (key === 'c') {
                Logger.clear();
            }

            if (key === 'd') {
                SafetyShield.debug.enabled ? Debug.disable() : Debug.enable();
            }

            if (key === '1') {
                SettingsManager.setProfile('relaxed');
            }

            if (key === '2') {
                SettingsManager.setProfile('balanced');
            }

            if (key === '3') {
                SettingsManager.setProfile('paranoid');
            }
        }

        if (key === '?') {
            e.preventDefault();
            SafetyShield.ui.showHelp();
        }
    });
    window.addEventListener('beforeunload', () => {
        SafetyShield.observers.forEach(obs => {
            try {
                obs.disconnect();
            } catch (err) {}
        });
        SafetyShield.modules.tracker.disable();
        SafetyShield.modules.ads.disable();
        SafetyShield.modules.scriptInjection.disable();
    });
    const initCore = () => {
        SettingsManager.init();
        RulesManager.init();
        SafetyShield.modules.redirect.initCore();
        SafetyShield.modules.tracker.initCore();
        SafetyShield.modules.ads.initCore();
        SafetyShield.modules.fingerprint.initCore();

        SafetyShield.initialized.core = true;
        Debug.log('Core initialization complete (document-start)');
    };
    const initUI = () => {
        SafetyShield.modules.redirect.initUI();
        SafetyShield.modules.tracker.initUI();
        SafetyShield.modules.ads.initUI();
        SafetyShield.modules.scriptInjection.initUI();

        SafetyShield.ui.statusButton = SafetyShield.ui.createButton();
        SafetyShield.ui.updateButton();

        SafetyShield.initialized.ui = true;

        console.log(
            `%c[SAFETY SHIELD] v${VERSION}\n` +
            `Split-phase init • Extensible rules • Dynamic reconfiguration\n` +
            `Press ? for help | D for debug | 1/2/3 for profiles`,
            'color: #22c55e; font-weight: bold; font-size: 13px'
        );
    };
    initCore();
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initUI);
    } else {
        initUI();
    }
    window.SafetyShield = {
        version: VERSION,
        debug: Debug,
        rules: RulesManager,
        modules: SafetyShield.modules,
        settings: SettingsManager,
        getState: () => Debug.inspect()
    };

})();