/**
 * Grax content engine v3
 *
 * Isolated-world responsibilities:
 * - Load and apply compiled cosmetic selectors.
 * - Observe only added DOM subtrees with strict idle-time budgets.
 * - Neutralize high-confidence click-jacking overlays and hostile links.
 * - Synchronize protection state with the early MAIN-world Page Guard.
 * - Restore every Grax-authored DOM/style mutation when protection is paused.
 */
(async () => {
  'use strict';

  const INSTANCE_KEY = '__graxContentEngineInstalled';
  if (globalThis[INSTANCE_KEY]) return;
  if (!await readInitialMasterState()) return;
  try {
    Object.defineProperty(globalThis, INSTANCE_KEY, {
      value: true,
      configurable: true,
      enumerable: false,
      writable: false
    });
  } catch {
    globalThis[INSTANCE_KEY] = true;
  }

  const CONFIG = Object.freeze({
    marker: 'data-grax-cosmetic-style',
    collapsed: 'data-grax-collapsed',
    neutralized: 'data-grax-neutralized',
    stateEvent: '__grax_guard_state_v1__',
    riskEvent: '__grax_guard_risk_v1__',
    shards: 64,
    cssChunk: 300,
    selectorLimit: 42_000,
    queueDelay: 42,
    nodeBudget: 950,
    shadowBudget: 700,
    linkBudget: 550,
    parentDepth: 2,
    initialSweepMs: 12_000
  });

  const HIGH_CONFIDENCE_SELECTORS = [
    'ins.adsbygoogle',
    '[data-ad-slot][data-ad-client]',
    '[data-ad-unit]',
    '[data-ad-container]',
    '[data-ad-placement]',
    '[data-ad-format]',
    '[aria-label="advertisement" i]',
    '[aria-label="sponsored advertisement" i]',
    '[id^="google_ads_"]',
    '[id^="div-gpt-ad-"]',
    '[id^="ad_iframe_"]',
    '[class~="ad-slot"]',
    '[class~="adsbox"]',
    '[class~="advertisement"]',
    'iframe[src*="doubleclick.net"]',
    'iframe[src*="googlesyndication.com"]',
    'iframe[src*="adnxs.com"]',
    'iframe[src*="amazon-adsystem.com"]',
    'ytd-ad-slot-renderer',
    'ytd-display-ad-renderer',
    'ytd-promoted-video-renderer',
    'ytd-promoted-sparkles-web-renderer',
    'ytd-in-feed-ad-layout-renderer',
    'ytd-banner-promo-renderer',
    'shreddit-post[promoted]',
    '[data-testid="post-container"][data-promoted="true"]'
  ].join(',');

  const OPTIONAL_HAS_SELECTORS = [
    'article:has([data-testid="placementTracking"])',
    '[role="article"]:has([aria-label="Sponsored" i])'
  ];

  const ANTI_ADBLOCK_TEXT = /\b(?:disable|turn off|whitelist|allow)\b.{0,45}\b(?:ad\s*block|adblocker|advertising blocker)\b|\b(?:ad\s*block|adblocker)\b.{0,45}\b(?:detected|enabled|active)\b/i;
  const PROTECTED_HOSTS = Object.freeze([
    'checkout.stripe.com',
    'stripe.com',
    'paypal.com',
    'paypalobjects.com',
    'accounts.google.com',
    'oauth2.googleapis.com',
    'appleid.apple.com',
    'login.microsoftonline.com',
    'login.live.com',
    'github.com',
    'facebook.com',
    'hcaptcha.com',
    'recaptcha.net'
  ]);

  const POPUNDER_HOST_PATTERN = /(?:^|\.)(?:popads|popcash|propellerads|onclicka|onclickads|onclickperformance|adsterra|admaven|ad-maven|exoclick|exosrv|clickadu|clickaine|clickadilla|hilltopads|evadav|richads|trafficstars|trafficjunky|juicyads|plugrush|adsession|supertracker200|dogsprotectedfeed|eagamerz|affforce)\./i;
  const SUSPICIOUS_LINK_PATTERN = /(?:[?&#](?:zoneid|campaignid|clickid|subid|pubid|siteid)=|\/(?:popunder|pop-up|popads|onclicka|propellerads|exoclick)(?:[/?#._-]|$))/i;
  const INLINE_POPUP_PATTERN = /(?:window\s*\.\s*open|(?:self|top|parent)\s*\.\s*open|popunder|onclicka|propeller|exoclick|adsterra|clickadu)/i;
  const OVERLAY_NAME_PATTERN = /(?:^|[-_\s])(popunder|popup|clickunder|interstitial|ad[-_\s]?overlay|underlay|click[-_\s]?layer)(?:[-_\s]|$)/i;
  const INTERACTIVE_SELECTOR = 'a[href],button,input,select,textarea,summary,[role="button"],[role="link"],[contenteditable="true"],video,audio';

  const state = {
    hostname: getHostname(),
    protectionActive: false,
    cosmeticActive: false,
    startingCosmetic: null,
    destroyedCosmetic: false,
    aggressive: true,
    selectors: [],
    styles: new Map(),
    observers: new Map(),
    collapsed: new Map(),
    neutralized: new Map(),
    queue: new Set(),
    timer: null,
    idleHandle: null,
    initialTimer: null,
    captureInstalled: false
  };

  let refreshGeneration = 0;
  let shuttingDown = false;

  chrome.runtime.onMessage.addListener(handleRuntimeMessage);
  chrome.storage.onChanged.addListener(handleStorageChanged);

  await refresh();

  async function readInitialMasterState() {
    try {
      const data = await chrome.storage.local.get('settings');
      return data?.settings?.enabled !== false;
    } catch {
      try {
        const response = await chrome.runtime.sendMessage({
          type: 'GRAX_GET_STATE',
          hostname: getHostname()
        });
        return response?.ok && response.result?.settings?.enabled !== false;
      } catch {
        return false;
      }
    }
  }

  function handleRuntimeMessage(message) {
    if (
      message &&
      ['GRAX_PROTECTION_STATE_CHANGED', 'GRAX_SITE_STATE_CHANGED', 'GRAX_SETTINGS_CHANGED']
        .includes(message.type)
    ) {
      void refresh();
    }
  }

  function handleStorageChanged(changes, areaName) {
    if (areaName !== 'local') return;
    if (Object.hasOwn(changes, 'settings') || Object.hasOwn(changes, 'allowlist')) {
      void refresh();
    }
  }

  async function readRuntimeSnapshot() {
    try {
      const data = await chrome.storage.local.get(['settings', 'allowlist']);
      const settings = data?.settings && typeof data.settings === 'object'
        ? data.settings
        : { enabled: true, cosmeticFiltering: true };
      const allowlist = Array.isArray(data?.allowlist) ? data.allowlist : [];
      const siteDisabled = state.hostname
        ? allowlist.some(domain => state.hostname === domain || state.hostname.endsWith(`.${domain}`))
        : false;
      return {
        settings,
        site: state.hostname ? { hostname: state.hostname, enabled: !siteDisabled } : null
      };
    } catch {
      const response = await chrome.runtime.sendMessage({
        type: 'GRAX_GET_STATE',
        hostname: state.hostname
      });
      if (!response?.ok) throw new Error(response?.error?.message || 'State unavailable');
      return response.result;
    }
  }

  async function refresh() {
    if (shuttingDown) return;
    const generation = ++refreshGeneration;
    try {
      const snapshot = await readRuntimeSnapshot();
      if (generation !== refreshGeneration || shuttingDown) return;

      const masterEnabled = snapshot?.settings?.enabled !== false;
      if (!masterEnabled) {
        shutdownContentEngine();
        return;
      }

      const protectionActive = Boolean(snapshot?.site?.enabled !== false);
      const cosmeticActive = Boolean(
        protectionActive && snapshot?.settings?.cosmeticFiltering !== false
      );

      setPageGuardState(protectionActive);

      if (protectionActive) {
        await startNavigationDefense();
      } else {
        stopNavigationDefense();
      }

      if (generation !== refreshGeneration || shuttingDown) return;
      if (cosmeticActive) {
        await startCosmeticEngine();
      } else {
        stopCosmeticEngine();
      }
    } catch (error) {
      setPageGuardState(false);
      stopNavigationDefense();
      stopCosmeticEngine();
    }
  }

  function shutdownContentEngine() {
    if (shuttingDown) return;
    shuttingDown = true;
    refreshGeneration += 1;
    setPageGuardState(false);
    stopNavigationDefense();
    stopCosmeticEngine();
    try { chrome.runtime.onMessage.removeListener(handleRuntimeMessage); } catch {}
    try { chrome.storage.onChanged.removeListener(handleStorageChanged); } catch {}
    try { delete globalThis[INSTANCE_KEY]; } catch {}
  }

  function setPageGuardState(enabled) {
    try {
      document.dispatchEvent(new CustomEvent(CONFIG.stateEvent, {
        detail: { enabled: Boolean(enabled) }
      }));
    } catch {}
  }

  function elevatePageRisk() {
    try {
      document.dispatchEvent(new CustomEvent(CONFIG.riskEvent));
    } catch {}
  }

  async function startNavigationDefense() {
    if (state.protectionActive) return;
    await waitForRoot();
    state.protectionActive = true;
    state.aggressive = !isProtectedOrigin(state.hostname);
    installCaptureHandlers();
    ensureObservedRoot(document);
    enqueue(document.documentElement);
  }

  function stopNavigationDefense() {
    if (!state.protectionActive && !state.captureInstalled) return;
    state.protectionActive = false;
    removeCaptureHandlers();
    restoreNeutralizedElements();
    if (!state.cosmeticActive) {
      disconnectObserversAndQueue();
    }
  }

  async function startCosmeticEngine() {
    if (state.cosmeticActive) return;
    if (state.startingCosmetic) return state.startingCosmetic;

    state.startingCosmetic = (async () => {
      state.destroyedCosmetic = false;
      state.aggressive = !isProtectedOrigin(state.hostname);
      state.selectors = (await loadSelectors(state.hostname)).slice(0, CONFIG.selectorLimit);
      if (state.destroyedCosmetic) return;
      await waitForRoot();
      if (state.destroyedCosmetic) return;

      state.cosmeticActive = true;
      installCosmeticStyles(document);
      ensureObservedRoot(document);
      enqueue(document.documentElement);
      clearTimeout(state.initialTimer);
      state.initialTimer = setTimeout(() => {
        if (state.cosmeticActive) enqueue(document.documentElement);
      }, CONFIG.initialSweepMs);
    })().finally(() => {
      state.startingCosmetic = null;
    });

    return state.startingCosmetic;
  }

  function stopCosmeticEngine() {
    state.destroyedCosmetic = true;
    state.cosmeticActive = false;
    state.selectors = [];
    clearTimeout(state.initialTimer);
    state.initialTimer = null;

    for (const styles of state.styles.values()) {
      for (const style of styles) style.remove();
    }
    state.styles.clear();

    for (const [element, original] of state.collapsed) {
      if (!element.isConnected) continue;
      if (original === null) element.removeAttribute('style');
      else element.setAttribute('style', original);
      element.removeAttribute(CONFIG.collapsed);
    }
    state.collapsed.clear();

    if (!state.protectionActive) {
      disconnectObserversAndQueue();
    }
  }

  function disconnectObserversAndQueue() {
    clearTimeout(state.timer);
    cancelIdle();
    state.timer = null;
    state.queue.clear();
    for (const observer of state.observers.values()) observer.disconnect();
    state.observers.clear();
  }

  function installCaptureHandlers() {
    if (state.captureInstalled) return;
    state.captureInstalled = true;
    document.addEventListener('pointerdown', capturePotentialHijack, true);
    document.addEventListener('pointerup', capturePotentialHijack, true);
    document.addEventListener('mousedown', capturePotentialHijack, true);
    document.addEventListener('mouseup', capturePotentialHijack, true);
    document.addEventListener('touchstart', capturePotentialHijack, { capture: true, passive: false });
    document.addEventListener('touchend', capturePotentialHijack, { capture: true, passive: false });
    document.addEventListener('click', capturePotentialHijack, true);
    document.addEventListener('auxclick', capturePotentialHijack, true);
  }

  function removeCaptureHandlers() {
    if (!state.captureInstalled) return;
    state.captureInstalled = false;
    document.removeEventListener('pointerdown', capturePotentialHijack, true);
    document.removeEventListener('pointerup', capturePotentialHijack, true);
    document.removeEventListener('mousedown', capturePotentialHijack, true);
    document.removeEventListener('mouseup', capturePotentialHijack, true);
    document.removeEventListener('touchstart', capturePotentialHijack, true);
    document.removeEventListener('touchend', capturePotentialHijack, true);
    document.removeEventListener('click', capturePotentialHijack, true);
    document.removeEventListener('auxclick', capturePotentialHijack, true);
  }

  function capturePotentialHijack(event) {
    try {
      if (!state.protectionActive || !event.isTrusted) return;
      const path = safeEventPath(event);
      const anchor = path.find(node => node instanceof HTMLAnchorElement) || null;

      if (anchor) {
        sanitizeAnchor(anchor);
        if (isHostileAnchor(anchor)) {
          blockEvent(event);
          neutralizeElement(anchor, 'hostile-link');
          elevatePageRisk();
          return;
        }
      }

      const candidate = path.find(node => node instanceof HTMLElement && isSuspiciousOverlay(node));
      if (candidate) {
        blockEvent(event);
        neutralizeElement(candidate, 'click-overlay');
        elevatePageRisk();
      }
    } catch {}
  }

  function blockEvent(event) {
    try { event.preventDefault(); } catch {}
    try { event.stopImmediatePropagation(); } catch {}
    try { event.stopPropagation(); } catch {}
  }

  function sanitizeAnchor(anchor) {
    if (!(anchor instanceof HTMLAnchorElement)) return;
    if (anchor.target === '_blank') {
      let destination = null;
      try {
        destination = new URL(anchor.href, location.href);
      } catch {}

      const sameOrigin = destination?.origin === location.origin;
      const protectedDestination = destination && isProtectedHostname(destination.hostname);
      const suspiciousDestination = destination && (
        POPUNDER_HOST_PATTERN.test(destination.hostname) ||
        SUSPICIOUS_LINK_PATTERN.test(destination.href)
      );

      if (!sameOrigin && !protectedDestination) {
        const tokens = new Set((anchor.rel || '').split(/\s+/).filter(Boolean));
        tokens.add('noopener');
        if (suspiciousDestination) tokens.add('noreferrer');
        anchor.rel = [...tokens].join(' ');
      }
    }

    const inlineHandler = anchor.getAttribute('onclick') || '';
    if (INLINE_POPUP_PATTERN.test(inlineHandler) && isSuspiciousOverlay(anchor)) {
      rememberNeutralized(anchor);
      anchor.removeAttribute('onclick');
    }
  }

  function isHostileAnchor(anchor) {
    if (anchor.hasAttribute('download')) return false;
    const rawHref = (anchor.getAttribute('href') || '').trim();
    const inlineHandler = anchor.getAttribute('onclick') || '';

    if (/^javascript:/i.test(rawHref)) {
      return INLINE_POPUP_PATTERN.test(rawHref) || INLINE_POPUP_PATTERN.test(inlineHandler);
    }
    if (/^(?:data|blob):text\/html/i.test(rawHref)) return true;

    let url;
    try {
      url = new URL(anchor.href, location.href);
    } catch {
      return false;
    }

    if (isProtectedHostname(url.hostname)) return false;
    const thirdParty = url.hostname && state.hostname &&
      url.hostname !== state.hostname && !url.hostname.endsWith(`.${state.hostname}`);

    return Boolean(
      thirdParty &&
      (POPUNDER_HOST_PATTERN.test(url.hostname) || SUSPICIOUS_LINK_PATTERN.test(url.href))
    );
  }

  async function loadSelectors(host) {
    const generic = await getJson('rules/cosmetic/generic.json');
    const suffixes = hostSuffixes(host);
    const count = generic.shardCount || CONFIG.shards;
    const ids = [...new Set(suffixes.map(domain => fnv(domain) % count))];
    const shards = await Promise.all(ids.map(id =>
      getJson(`rules/cosmetic/shard-${String(id).padStart(2, '0')}.json`)
    ));
    const hide = new Set(Array.isArray(generic.selectors) ? generic.selectors : []);
    const unhide = new Set(Array.isArray(generic.globalExceptions) ? generic.globalExceptions : []);

    for (const group of Array.isArray(generic.conditional) ? generic.conditional : []) {
      if (!excluded(group.excludeDomains, host)) {
        for (const selector of Array.isArray(group.selectors) ? group.selectors : []) {
          hide.add(selector);
        }
      }
    }

    for (const shard of shards) {
      const domains = shard?.domains && typeof shard.domains === 'object'
        ? shard.domains
        : {};
      for (const domain of suffixes) {
        const bucket = domains[domain];
        if (!bucket) continue;
        for (const entry of Array.isArray(bucket.hide) ? bucket.hide : []) {
          if (typeof entry === 'string') hide.add(entry);
          else if (
            Array.isArray(entry) &&
            typeof entry[0] === 'string' &&
            !excluded(entry[1], host)
          ) {
            hide.add(entry[0]);
          }
        }
        for (const selector of Array.isArray(bucket.unhide) ? bucket.unhide : []) {
          unhide.add(selector);
        }
      }
    }

    for (const selector of unhide) hide.delete(selector);
    return [...hide].filter(validSelector);
  }

  async function getJson(file) {
    const response = await fetch(chrome.runtime.getURL(file), {
      cache: 'force-cache',
      credentials: 'omit'
    });
    if (!response.ok) throw new Error(`Could not load ${file}`);
    return response.json();
  }

  function installCosmeticStyles(root) {
    if (!state.cosmeticActive || state.styles.has(root)) return;
    const target = root === document ? document.documentElement : root;
    if (!target) return;

    const styles = [];
    for (let index = 0; index < state.selectors.length; index += CONFIG.cssChunk) {
      const selectors = state.selectors.slice(index, index + CONFIG.cssChunk);
      if (!selectors.length) continue;
      const style = document.createElement('style');
      style.setAttribute(CONFIG.marker, String(index / CONFIG.cssChunk));
      style.textContent = `${selectors.join(',\n')}{display:none!important;visibility:hidden!important;min-height:0!important;max-height:0!important;margin:0!important;padding:0!important;border:0!important;}`;
      target.append(style);
      styles.push(style);
    }

    const heuristic = document.createElement('style');
    heuristic.setAttribute(CONFIG.marker, 'heuristic');
    const extra = OPTIONAL_HAS_SELECTORS.filter(validSelector);
    heuristic.textContent = `${[HIGH_CONFIDENCE_SELECTORS, ...extra].filter(Boolean).join(',\n')}{display:none!important;visibility:hidden!important;min-height:0!important;max-height:0!important;margin:0!important;padding:0!important;border:0!important;}`;
    target.append(heuristic);
    styles.push(heuristic);
    state.styles.set(root, styles);
  }

  function ensureObservedRoot(root) {
    if (state.observers.has(root)) return;
    const target = root === document ? document.documentElement : root;
    if (!target) return;

    const observer = new MutationObserver(records => {
      try {
        for (const record of records) {
          for (const node of record.addedNodes) {
            if (node.nodeType === Node.ELEMENT_NODE) enqueue(node);
          }
        }
      } catch {}
    });
    observer.observe(target, { childList: true, subtree: true });
    state.observers.set(root, observer);
  }

  function enqueue(node) {
    if ((!state.protectionActive && !state.cosmeticActive) || !(node instanceof Element)) return;
    state.queue.add(node);
    clearTimeout(state.timer);
    state.timer = setTimeout(() => {
      try { scheduleFlush(); } catch {}
    }, CONFIG.queueDelay);
  }

  function scheduleFlush() {
    state.timer = null;
    cancelIdle();
    if (typeof requestIdleCallback === 'function') {
      state.idleHandle = requestIdleCallback(deadline => {
        try { flush(deadline); } catch {}
      }, { timeout: 160 });
    } else {
      state.idleHandle = setTimeout(() => {
        try {
          flush({
            timeRemaining: () => 8,
            didTimeout: true
          });
        } catch {}
      }, 0);
    }
  }

  function cancelIdle() {
    if (state.idleHandle === null) return;
    if (typeof cancelIdleCallback === 'function') cancelIdleCallback(state.idleHandle);
    else clearTimeout(state.idleHandle);
    state.idleHandle = null;
  }

  function flush(deadline) {
    state.idleHandle = null;
    if (!state.protectionActive && !state.cosmeticActive) return;

    const pending = [...state.queue];
    state.queue.clear();
    let visited = 0;

    for (const root of pending) {
      if (!root.isConnected) continue;
      processSubtree(root, () =>
        visited++ < CONFIG.nodeBudget && (deadline.didTimeout || deadline.timeRemaining() > 1)
      );
      if (visited >= CONFIG.nodeBudget) break;
    }

    if (state.queue.size) scheduleFlush();
  }

  function processSubtree(root, hasBudget) {
    discoverShadowRoots(root, hasBudget);
    if (state.protectionActive) {
      sanitizeNavigationSubtree(root, hasBudget);
      neutralizeSuspiciousOverlays(root, hasBudget);
    }
    if (state.cosmeticActive) {
      collapseCandidates(root);
      if (state.aggressive) removeAntiAdblockOverlay(root);
    }
  }

  function discoverShadowRoots(root, hasBudget) {
    let visited = 0;
    const inspect = element => {
      if (!hasBudget() || visited++ >= CONFIG.shadowBudget) return false;
      if (element.shadowRoot && !state.observers.has(element.shadowRoot)) {
        if (state.cosmeticActive) installCosmeticStyles(element.shadowRoot);
        ensureObservedRoot(element.shadowRoot);
        for (const child of element.shadowRoot.children || []) enqueue(child);
      }
      return true;
    };

    if (!inspect(root)) return;
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
    let current;
    while ((current = walker.nextNode())) {
      if (!inspect(current)) break;
    }
  }

  function sanitizeNavigationSubtree(root, hasBudget) {
    let inspected = 0;
    const inspect = element => {
      if (!hasBudget() || inspected++ >= CONFIG.linkBudget) return false;
      if (element instanceof HTMLAnchorElement) sanitizeAnchor(element);
      if (
        element instanceof HTMLElement &&
        element.hasAttribute('onclick') &&
        INLINE_POPUP_PATTERN.test(element.getAttribute('onclick') || '') &&
        isSuspiciousOverlay(element)
      ) {
        neutralizeElement(element, 'inline-popup-handler');
        elevatePageRisk();
      }
      return true;
    };

    if (!inspect(root)) return;
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
    let current;
    while ((current = walker.nextNode())) {
      if (!inspect(current)) break;
    }
  }

  function neutralizeSuspiciousOverlays(root, hasBudget) {
    const candidates = [];
    if (root instanceof HTMLElement) candidates.push(root);
    try {
      candidates.push(...root.querySelectorAll?.(
        '[onclick],[class*="popunder" i],[id*="popunder" i],[class*="clickunder" i],[id*="clickunder" i],[class*="interstitial" i],[id*="interstitial" i],[class*="ad-overlay" i],[id*="ad-overlay" i]'
      ) || []);
    } catch {}

    let count = 0;
    for (const element of candidates) {
      if (!hasBudget() || count++ >= 80) break;
      if (isSuspiciousOverlay(element)) {
        neutralizeElement(element, 'overlay');
        elevatePageRisk();
      }
    }
  }

  function isSuspiciousOverlay(element) {
    if (!(element instanceof HTMLElement) || !element.isConnected || isProtectedOrigin(state.hostname)) return false;
    if (element.closest('form,input,button,select,textarea,[contenteditable="true"]')) return false;
    if (element.matches(INTERACTIVE_SELECTOR) && !element.hasAttribute('onclick')) return false;
    if (element.querySelector('input:not([type="hidden"]),button,select,textarea,video,audio,[contenteditable="true"]')) return false;

    const style = getComputedStyle(element);
    if (style.pointerEvents === 'none' || style.display === 'none' || style.visibility === 'hidden') return false;
    const rect = element.getBoundingClientRect();
    if (rect.width < 40 || rect.height < 40) return false;

    const viewportArea = Math.max(1, innerWidth * innerHeight);
    const areaRatio = Math.max(0, rect.width) * Math.max(0, rect.height) / viewportArea;
    const positioned = ['fixed', 'absolute', 'sticky'].includes(style.position);
    const opacity = Number.parseFloat(style.opacity || '1');
    const transparent = opacity <= 0.16 || style.backgroundColor === 'rgba(0, 0, 0, 0)';
    const highZ = Number.parseInt(style.zIndex || '0', 10) >= 100;
    const name = `${element.id} ${element.className}`.toLowerCase();
    const handler = element.getAttribute('onclick') || '';
    const text = (element.innerText || element.textContent || '').replace(/\s+/g, ' ').trim();
    const named = OVERLAY_NAME_PATTERN.test(name);
    const scripted = INLINE_POPUP_PATTERN.test(handler);

    return Boolean(
      (positioned && areaRatio >= 0.55 && (transparent || highZ) && text.length < 120) ||
      (named && areaRatio >= 0.18 && text.length < 160) ||
      (scripted && areaRatio >= 0.08 && text.length < 180)
    );
  }

  function rememberNeutralized(element) {
    if (state.neutralized.has(element)) return;
    state.neutralized.set(element, {
      style: element.getAttribute('style'),
      onclick: element.getAttribute('onclick'),
      href: element instanceof HTMLAnchorElement ? element.getAttribute('href') : undefined,
      target: element instanceof HTMLAnchorElement ? element.getAttribute('target') : undefined,
      rel: element instanceof HTMLAnchorElement ? element.getAttribute('rel') : undefined
    });
  }

  function neutralizeElement(element, reason) {
    if (!(element instanceof HTMLElement) || !element.isConnected) return;
    rememberNeutralized(element);
    element.setAttribute(CONFIG.neutralized, reason);
    element.removeAttribute('onclick');
    element.style.setProperty('pointer-events', 'none', 'important');
    element.style.setProperty('cursor', 'default', 'important');

    if (element instanceof HTMLAnchorElement && isHostileAnchor(element)) {
      element.removeAttribute('href');
      element.removeAttribute('target');
    }

    if (state.cosmeticActive && safeToCollapse(element)) {
      collapse(element, reason);
    }
  }

  function restoreNeutralizedElements() {
    for (const [element, original] of state.neutralized) {
      if (!element.isConnected) continue;
      if (original.style === null) element.removeAttribute('style');
      else element.setAttribute('style', original.style);
      restoreAttribute(element, 'onclick', original.onclick);
      if (element instanceof HTMLAnchorElement) {
        restoreAttribute(element, 'href', original.href);
        restoreAttribute(element, 'target', original.target);
        restoreAttribute(element, 'rel', original.rel);
      }
      element.removeAttribute(CONFIG.neutralized);
    }
    state.neutralized.clear();
  }

  function restoreAttribute(element, name, value) {
    if (value === null || value === undefined) element.removeAttribute(name);
    else element.setAttribute(name, value);
  }

  function collapseCandidates(scope) {
    const candidates = [];
    if (scope.matches?.(HIGH_CONFIDENCE_SELECTORS)) candidates.push(scope);
    try {
      candidates.push(...(scope.querySelectorAll?.(HIGH_CONFIDENCE_SELECTORS) || []));
    } catch {}

    for (const element of candidates) collapse(element, 'candidate');

    const frames = [];
    if (scope.matches?.('iframe')) frames.push(scope);
    frames.push(...(scope.querySelectorAll?.('iframe') || []));
    for (const frame of frames) {
      frame.addEventListener('load', () => {
        try { inspectFrame(frame); } catch {}
      }, { once: true, passive: true });
      try { inspectFrame(frame); } catch {}
    }
  }

  function inspectFrame(frame) {
    if (!state.cosmeticActive || !(frame instanceof HTMLIFrameElement) || !frame.isConnected) return;
    const src = (frame.getAttribute('src') || '').trim();
    const name = `${frame.id} ${frame.className} ${frame.title}`.toLowerCase();
    const known = /\b(?:ad|ads|advert|sponsor|promo|banner|gpt|dfp)\b/.test(name) ||
      /(?:doubleclick|googlesyndication|adnxs|amazon-adsystem)/i.test(src);
    let empty = !src || src === 'about:blank' || src.startsWith('javascript:');
    try {
      const doc = frame.contentDocument;
      if (doc) empty = empty || !doc.body || (!doc.body.children.length && !doc.body.textContent?.trim());
    } catch {}
    if (known && empty) collapse(frame, 'empty-frame');
  }

  function removeAntiAdblockOverlay(scope) {
    const elements = [];
    if (scope instanceof HTMLElement) elements.push(scope);
    try {
      elements.push(...scope.querySelectorAll?.(
        '[class*="adblock" i],[id*="adblock" i],[class*="ad-block" i],[id*="ad-block" i],[role="dialog"],[aria-modal="true"]'
      ) || []);
    } catch {}

    for (const element of elements) {
      if (!(element instanceof HTMLElement) || state.collapsed.has(element) || !element.isConnected) continue;
      const text = (element.innerText || element.textContent || '').replace(/\s+/g, ' ').trim();
      if (
        !ANTI_ADBLOCK_TEXT.test(text) ||
        text.length > 1600 ||
        element.querySelector('input[type="password"],input[type="email"],form[action*="login" i],form[action*="checkout" i]')
      ) {
        continue;
      }
      const style = getComputedStyle(element);
      const rect = element.getBoundingClientRect();
      const overlay = ['fixed', 'sticky', 'absolute'].includes(style.position) &&
        rect.width > innerWidth * 0.35 && rect.height > 80;
      if (overlay) collapse(element, 'anti-adblock');
    }
  }

  function collapse(element, reason) {
    if (
      !(element instanceof HTMLElement) ||
      !element.isConnected ||
      state.collapsed.has(element) ||
      !safeToCollapse(element)
    ) {
      return;
    }

    state.collapsed.set(element, element.getAttribute('style'));
    element.setAttribute(CONFIG.collapsed, reason);
    for (const [property, value] of [
      ['display', 'none'],
      ['visibility', 'hidden'],
      ['min-height', '0'],
      ['max-height', '0'],
      ['height', '0'],
      ['margin', '0'],
      ['padding', '0'],
      ['border', '0']
    ]) {
      element.style.setProperty(property, value, 'important');
    }
    collapseEmptyParents(element);
  }

  function collapseEmptyParents(element) {
    let parent = element.parentElement;
    for (let depth = 0; parent && depth < CONFIG.parentDepth; depth += 1, parent = parent.parentElement) {
      if (!safeToCollapse(parent) || state.collapsed.has(parent)) continue;
      const visible = [...parent.children].filter(child => child !== element && isVisible(child));
      const text = (parent.textContent || '').replace(/\s+/g, ' ').trim();
      const name = `${parent.id} ${parent.className}`.toLowerCase();
      if (
        !visible.length &&
        text.length < 24 &&
        /(?:^|[-_\s])(ad|ads|advert|sponsor|promo|banner)(?:[-_\s]|$)/.test(name)
      ) {
        collapse(parent, 'empty-wrapper');
      } else {
        break;
      }
    }
  }

  function safeToCollapse(element) {
    if (element.matches('html,body,main,header,footer,nav,form,dialog,[role="main"],[role="navigation"]')) return false;
    if (element.querySelector('input:not([type="hidden"]),button,select,textarea,video,audio,[contenteditable="true"]')) return false;
    const rect = element.getBoundingClientRect();
    if (rect.width > innerWidth * 0.98 && rect.height > innerHeight * 0.72) return false;
    const text = (element.innerText || element.textContent || '').trim();
    return text.length <= 240 || /advertisement|sponsored|promoted|adblock/i.test(text);
  }

  function isVisible(element) {
    if (!(element instanceof HTMLElement)) return false;
    const style = getComputedStyle(element);
    return style.display !== 'none' && style.visibility !== 'hidden' && element.getClientRects().length > 0;
  }

  function safeEventPath(event) {
    try {
      return event.composedPath?.() || [event.target];
    } catch {
      return [event.target];
    }
  }

  function validSelector(selector) {
    if (typeof selector !== 'string' || !selector || selector.length > 2048) return false;
    try {
      return typeof CSS?.supports !== 'function' || CSS.supports(`selector(${selector})`);
    } catch {
      return false;
    }
  }

  function excluded(domains, host) {
    return Array.isArray(domains) && host && domains.some(domain =>
      host === domain || host.endsWith(`.${domain}`)
    );
  }

  function hostSuffixes(host) {
    if (!host) return [];
    const parts = host.toLowerCase().split('.').filter(Boolean);
    if (parts.length < 2) return [host];
    const output = [];
    for (let index = 0; index <= parts.length - 2; index += 1) {
      output.push(parts.slice(index).join('.'));
    }
    return output;
  }

  function getHostname() {
    try {
      if (location.hostname) return location.hostname.toLowerCase();
      if (window.parent !== window && document.referrer) {
        return new URL(document.referrer).hostname.toLowerCase();
      }
    } catch {}
    return null;
  }

  function isProtectedHostname(hostname) {
    return Boolean(hostname && PROTECTED_HOSTS.some(domain =>
      hostname === domain || hostname.endsWith(`.${domain}`)
    ));
  }

  function isProtectedOrigin(host) {
    return isProtectedHostname(host);
  }

  function waitForRoot() {
    if (document.documentElement) return Promise.resolve();
    return new Promise(resolve => {
      const observer = new MutationObserver(() => {
        try {
          if (document.documentElement) {
            observer.disconnect();
            resolve();
          }
        } catch {}
      });
      observer.observe(document, { childList: true });
    });
  }

  function fnv(value) {
    let hash = 0x811c9dc5;
    for (let index = 0; index < value.length; index += 1) {
      hash ^= value.charCodeAt(index);
      hash = Math.imul(hash, 0x01000193);
    }
    return hash >>> 0;
  }
})().catch(() => undefined);
