Focused YouTube

Remove ads, shorts, and algorithmic suggestions on YouTube (EN/NL/DE/FR)

当前为 2025-06-29 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Focused YouTube
// @version      2025-06-29.4
// @author       Richard B
// @namespace    https://www.365devnet.eu/focusedyoutube
// @description  Remove ads, shorts, and algorithmic suggestions on YouTube (EN/NL/DE/FR)
// @match        *://*.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @run-at       document-start
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT
// ==/UserScript==

// Credits: 
// Originally based on Focused YouTube by Kervyn
// https://github.com/KervynH/Focused-YouTube
// 
// Additional credits: https://github.com/lawrencehook/remove-youtube-suggestions
//
// MIT License
// 
// Copyright (c) 2025 Richard B
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

'use strict';

// Config custom settings here - now with user preferences support
const DEFAULT_SETTINGS = {
  /// homepage redirect ///
  redirectHomepage: false, // Options: 'wl', 'subs', 'lib', false
  hideHomepageButton: false,

  /// homepage suggestions ///
  hideAllSuggestions: false,
  hideAllButOneRow: true,
  hideInfiniteScroll: false,

  /// video player ///
  skipAds: true,
  hideLiveChat: true,
  hideRelatedVideos: true,
  hideMiniPlayerButton: true,
  hidePlayNextButton: true,
  forceCinemaMode: true,

  /// shorts ///
  hideShorts: true,
  redirectShortsPlayer: true,

  /// misc ///
  hideSearchButton: false,
  cleanSearchResults: true,
  hideSponsoredContent: true,
};

// Load user settings with fallback to defaults
const SETTINGS = {};
Object.keys(DEFAULT_SETTINGS).forEach(key => {
  SETTINGS[key] = GM_getValue(key, DEFAULT_SETTINGS[key]);
});

// Performance optimizations
let styleElement = null;
let lastUrl = '';
let observer = null;
const processingQueue = new Set();

// Mark settings in HTML
const HTML = document.documentElement;
Object.keys(SETTINGS).forEach(key => {
  HTML.setAttribute(key, SETTINGS[key]);
});

// Improved CSS selectors with better specificity and modern features
const DESKTOP_BLOCK_LIST = [
  // Ads - More comprehensive coverage
  '#masthead-ad',
  'ytd-mealbar-promo-renderer',
  'ytd-carousel-ad-renderer',
  'ytd-display-ad-renderer',
  'ytd-ad-slot-renderer',
  'ytd-promoted-sparkles-text-search-renderer',
  'div.ytp-ad-overlay-image',
  '.iv-branding.annotation-type-custom.annotation',
  '[class*="ad-showing"]',
  '.ytp-ad-module',

  // Sponsored Content - Enhanced detection
  'html[hideSponsoredContent="true"] ytd-rich-item-renderer:has(ytd-ad-slot-renderer)',
  'html[hideSponsoredContent="true"] ytd-ad-slot-renderer',
  'html[hideSponsoredContent="true"] ytd-in-feed-ad-layout-renderer',
  'html[hideSponsoredContent="true"] ytd-video-display-full-buttoned-and-button-group-renderer',
  'html[hideSponsoredContent="true"] ytd-ad-inline-playback-meta-block',
  'html[hideSponsoredContent="true"] top-landscape-image-layout-view-model',
  'html[hideSponsoredContent="true"] feed-ad-metadata-view-model',
  'html[hideSponsoredContent="true"] ad-badge-view-model',
  'html[hideSponsoredContent="true"] [class*="ytwAdBadgeViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="ytwFeedAdMetadataViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="badge-style-type-ad"]',

  // Shorts - Enhanced selectors based on HTML structure
  'html[hideShorts="true"] ytd-rich-section-renderer:has(ytd-rich-shelf-renderer[is-shorts])',
  'html[hideShorts="true"] ytd-rich-shelf-renderer[is-shorts]',
  'html[hideShorts="true"] ytd-rich-shelf-renderer:has(#title:contains("Shorts"))',
  'html[hideShorts="true"] ytd-reel-shelf-renderer',
  'html[hideShorts="true"] ytd-shelf-renderer:has([href*="/shorts/"])',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model-v2',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model',
  'html[hideShorts="true"] [aria-label*="Shorts"]',
  'html[hideShorts="true"] [class*="shortsLockupViewModelHost"]',
  'html[hideShorts="true"] .reel-item-endpoint',

  // Left Bar Navigation 
  'a[href="/feed/trending"]',
  'a[href="/feed/explore"]',
  'html[hideShorts="true"] ytd-guide-section-renderer a[title="Shorts"]',
  'html[hideShorts="true"] ytd-mini-guide-entry-renderer[aria-label="Shorts"]',
  'ytd-guide-section-renderer.ytd-guide-renderer.style-scope:nth-of-type(4)',
  'ytd-guide-section-renderer.ytd-guide-renderer.style-scope:nth-of-type(3)',

  // Homepage - Better targeting
  'html[hideHomepageButton="true"] a:not(#logo)[href="/"]',
  'html[hideAllSuggestions="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer',
  'html[hideAllButOneRow="true"] ytd-browse[page-subtype="home"] #header',
  'html[hideAllButOneRow="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer > #contents > ytd-rich-grid-row:nth-child(n+2)',
  'html[hideInfiniteScroll="true"] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer > #contents > ytd-continuation-item-renderer',

  // Video Player - Enhanced
  'html[hideRelatedVideos="true"] #secondary',
  'html[hideRelatedVideos="true"] #related',
  'html[hideRelatedVideos="true"] .html5-endscreen',
  'html[hideRelatedVideos="true"] .ytp-endscreen-content',
  'html[hidePlayNextButton="true"] .ytp-next-button',
  'html[hidePlayNextButton="true"] .ytp-prev-button',
  'html[hideLiveChat="true"] #chat',
  'html[hideLiveChat="true"] ytd-live-chat-frame',
  'html[hideMiniPlayerButton="true"] .ytp-miniplayer-button',
  '.ytd-download-button-renderer',

  // Search - Improved
  'div.sbdd_a',
  '#container.ytd-search ytd-search-pyv-renderer',
  'html[hideSearchButton="true"] ytd-searchbox',
  'html[hideSearchButton="true"] #voice-search-button',
];

const MOBILE_BLOCK_LIST = [
  // Ads 
  'ytm-companion-ad-renderer',
  'ytm-promoted-sparkles-web-renderer',
  '[class*="ad-showing"]',

  // Sponsored Content (Mobile) - Enhanced
  'html[hideSponsoredContent="true"] ytm-rich-item-renderer:has([class*="ad"])',
  'html[hideSponsoredContent="true"] ytm-ad-slot-renderer',
  'html[hideSponsoredContent="true"] [class*="ytwAdBadgeViewModelHost"]',
  'html[hideSponsoredContent="true"] [class*="sponsored"]',
  'html[hideSponsoredContent="true"] [class*="badge-style-type-ad"]',

  // Shorts - Enhanced mobile targeting
  'html[hideShorts="true"] ytm-reel-shelf-renderer',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model-v2',
  'html[hideShorts="true"] ytm-shorts-lockup-view-model',
  'html[hideShorts="true"] [aria-label*="Shorts"]',
  'html[hideShorts="true"] [class*="shortsLockupViewModelHost"]',
  'html[hideShorts="true"] .reel-item-endpoint',

  // Homepage 
  'html[hideHomepageButton="true"] div[tab-identifier="FEwhat_to_watch"]',
  'html[hideSearchButton="true"] #header-bar > header > div > button',
  'html[hideSearchButton="true"] #center.style-scope.ytd-masthead',

  // Video Player 
  'html[hideRelatedVideos="true"] ytm-item-section-renderer[section-identifier="related-items"]',
  'html[hidePlayNextButton="true"] .player-controls-middle-core-buttons > div:nth-child(1)',
  'html[hidePlayNextButton="true"] .player-controls-middle-core-buttons > div:nth-child(5)',
  'html[hideLiveChat="true"] ytm-live-chat-frame',

  // Navigation Bar 
  'html[hideHomepageButton="true"] ytm-pivot-bar-item-renderer:nth-child(1)',
  'html[hideShorts="true"] ytm-pivot-bar-item-renderer:nth-child(2)',
  'ytm-chip-cloud-chip-renderer[chip-style="STYLE_EXPLORE_LAUNCHER_CHIP"]',
];

// Improved style injection with error handling
function addStyle(css) {
  try {
    if (!styleElement) {
      styleElement = document.createElement('style');
      styleElement.id = 'focused-youtube-styles';
      document.head.appendChild(styleElement);
    }
    styleElement.textContent = css;
  } catch (error) {
    console.warn('Focused YouTube: Failed to inject styles:', error);
  }
}

// Apply styles based on platform
function applyStyles() {
  const isDesktop = location.hostname.startsWith('www.');
  const isMobile = location.hostname.startsWith('m.');
  
  if (isDesktop) {
    const styles = DESKTOP_BLOCK_LIST.map(e => `${e} { display: none !important; }`).join('\n');
    addStyle(styles);
  } else if (isMobile) {
    const styles = MOBILE_BLOCK_LIST.map(e => `${e} { display: none !important; }`).join('\n');
    addStyle(styles);
  }
}

// Improved URL change detection
function detectUrlChange() {
  const currentUrl = location.href;
  if (currentUrl !== lastUrl) {
    lastUrl = currentUrl;
    handleUrlChange();
  }
}

function handleUrlChange() {
  // Re-apply settings when navigating
  setTimeout(() => {
    runDynamicSettings();
  }, 100);
}

// Enhanced MutationObserver for better performance
function setupObserver() {
  if (observer) observer.disconnect();
  
  observer = new MutationObserver((mutations) => {
    let shouldProcess = false;
    
    for (const mutation of mutations) {
      if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
        for (const node of mutation.addedNodes) {
          if (node.nodeType === Node.ELEMENT_NODE) {
            const tagName = node.tagName?.toLowerCase();
            if (tagName?.includes('ytd-') || tagName?.includes('ytm-')) {
              shouldProcess = true;
              break;
            }
          }
        }
      }
      if (shouldProcess) break;
    }
    
    if (shouldProcess) {
      // Debounce processing
      clearTimeout(window.focusedYTTimeout);
      window.focusedYTTimeout = setTimeout(runDynamicSettings, 100);
    }
  });
  
  observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false
  });
}

// Start initialization
function initialize() {
  applyStyles();
  setupObserver();
  
  // URL change detection
  setInterval(detectUrlChange, 250);
  
  // Initial run
  setTimeout(runDynamicSettings, 500);
}

// Wait for DOM to be ready
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initialize);
} else {
  initialize();
}

/***** Core Functions *****/

function runDynamicSettings() {
  try {
    if (SETTINGS.redirectHomepage && SETTINGS.redirectHomepage !== 'false') redirectHomepage();
    if (SETTINGS.redirectShortsPlayer) redirectShortsPlayer();
    if (SETTINGS.hideShorts) hideShortsVideos();
    if (SETTINGS.cleanSearchResults) cleanSearchResults();
    if (SETTINGS.skipAds) skipVideoAds();
    if (SETTINGS.hideRelatedVideos) disableRelatedAutoPlay();
    if (SETTINGS.forceCinemaMode) enableCinemaMode();
    if (SETTINGS.hideSponsoredContent) hideSponsoredContent();
  } catch (error) {
    console.warn('Focused YouTube: Error in runDynamicSettings:', error);
  }
}

function redirectHomepage() {
  if (location.pathname === '/' && !location.search) {
    const redirectMap = {
      'wl': '/playlist?list=WL',
      'subs': '/feed/subscriptions',
      'lib': '/feed/library'
    };
    
    const redirect = redirectMap[SETTINGS.redirectHomepage];
    if (redirect) {
      location.replace(redirect);
    }
  }
}

function redirectShortsPlayer() {
  if (location.pathname.startsWith('/shorts/')) {
    const videoId = location.pathname.replace('/shorts/', '');
    const newUrl = `/watch?v=${videoId}${location.search ? '&' + location.search.slice(1) : ''}`;
    location.replace(newUrl);
  }
}

function disableRelatedAutoPlay() {
  // Desktop autoplay
  const autoplayButtons = document.querySelectorAll('.ytp-autonav-toggle-button[aria-checked="true"]');
  autoplayButtons.forEach(button => {
    if (button.offsetParent && !processingQueue.has(button)) {
      processingQueue.add(button);
      button.click();
      setTimeout(() => processingQueue.delete(button), 1000);
    }
  });
  
  // Mobile autoplay
  const mobileAutoplayButtons = document.querySelectorAll('.ytm-autonav-toggle-button-container[aria-pressed="true"]');
  mobileAutoplayButtons.forEach(button => {
    if (button.offsetParent && !processingQueue.has(button)) {
      processingQueue.add(button);
      button.click();
      setTimeout(() => processingQueue.delete(button), 1000);
    }
  });
}

function hideShortsVideos() {
  // Remove shorts containers - Enhanced detection
  const shortsContainers = document.querySelectorAll(
    'ytd-rich-section-renderer:has(ytd-rich-shelf-renderer[is-shorts]), ' +
    'ytd-rich-section-renderer:has([id="title"]:is([innerText*="Shorts"], [textContent*="Shorts"]))'
  );
  shortsContainers.forEach(container => {
    if (!processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove shorts shelf renderers
  const shortsShelves = document.querySelectorAll('ytd-rich-shelf-renderer[is-shorts]');
  shortsShelves.forEach(shelf => {
    if (!processingQueue.has(shelf)) {
      processingQueue.add(shelf);
      shelf.remove();
    }
  });

  // Remove by title detection
  const shortsHeaders = document.querySelectorAll('#title');
  shortsHeaders.forEach(title => {
    const text = title.innerText || title.textContent;
    if (text && text.toLowerCase().includes('shorts')) {
      const container = title.closest('ytd-rich-section-renderer, ytd-rich-shelf-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });

  // Remove shorts lockup components
  const shortsLockups = document.querySelectorAll(
    'ytm-shorts-lockup-view-model-v2, ytm-shorts-lockup-view-model, ' +
    '[class*="shortsLockupViewModelHost"], .reel-item-endpoint'
  );
  shortsLockups.forEach(lockup => {
    const parent = lockup.closest('ytd-rich-item-renderer, ytd-rich-section-renderer');
    if (parent && !processingQueue.has(parent)) {
      processingQueue.add(parent);
      parent.remove();
    }
  });

  // Fallback: Remove by shorts links
  const shortsLinks = document.querySelectorAll('a[href*="/shorts/"]');
  shortsLinks.forEach(link => {
    const containers = [
      link.closest('ytd-rich-item-renderer'),
      link.closest('ytd-rich-section-renderer'),
      link.closest('ytm-item-section-renderer'),
      link.closest('ytd-video-renderer'),
      link.closest('ytm-video-with-context-renderer')
    ].filter(Boolean);
    
    containers.forEach(container => {
      if (!processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    });
  });

  // Remove shorts tabs on channel pages
  if (location.pathname.startsWith('/@') || location.pathname.startsWith('/c/') || location.pathname.startsWith('/channel/')) {
    const shortsTabs = document.querySelectorAll('[role="tab"], div.tab-content');
    shortsTabs.forEach(tab => {
      const text = tab.innerText?.toUpperCase();
      const shortsTerms = ['SHORTS', 'COURTS', 'KURZ', 'KORT']; // EN, FR, DE, NL
      
      if (shortsTerms.some(term => text?.includes(term)) && !processingQueue.has(tab)) {
        processingQueue.add(tab);
        (tab.parentElement || tab).remove();
      }
    });
  }
}

function skipVideoAds() {
  if (!location.pathname.startsWith('/watch')) return;
  
  // Skip ad buttons
  const skipButtons = document.querySelectorAll('.ytp-ad-skip-button-slot button, .ytp-ad-overlay-close-button, .ytp-ad-skip-button');
  skipButtons.forEach(button => {
    if (button.offsetParent && !processingQueue.has(button)) {
      processingQueue.add(button);
      button.click();
      setTimeout(() => processingQueue.delete(button), 500);
    }
  });

  // Fast-forward through ads
  const adVideo = document.querySelector('.ad-showing');
  if (adVideo) {
    const video = document.querySelector('.html5-main-video');
    if (video && video.duration && !isNaN(video.duration) && video.duration > 0) {
      video.currentTime = video.duration - 0.1;
    }
  }
}

function cleanSearchResults() {
  if (!location.pathname.startsWith('/results')) return;
  
  const relatedTerms = [
    // English
    'Related', 'People also watched', 'For you', 'Recommended', 'You might also like',
    'Similar videos', 'More like this', 'Suggested', 'Because you watched',
    
    // Dutch
    'Gerelateerd', 'Anderen bekeken ook', 'Voor jou', 'Aanbevolen', 'Misschien vind je dit ook leuk',
    'Vergelijkbare video\'s', 'Meer zoals dit', 'Voorgesteld', 'Omdat je keek naar',
    
    // German  
    'Ähnlich', 'Andere sahen auch', 'Für dich', 'Empfohlen', 'Das könnte dir auch gefallen',
    'Ähnliche Videos', 'Mehr davon', 'Vorgeschlagen', 'Weil du dir angesehen hast',
    
    // French
    'Connexe', 'D\'autres ont aussi regardé', 'Pour vous', 'Recommandé', 'Vous aimerez peut-être aussi',
    'Vidéos similaires', 'Plus comme ça', 'Suggéré', 'Parce que vous avez regardé'
  ];
  
  const badges = document.querySelectorAll('ytm-badge, .badge-style-type-simple');
  
  badges.forEach(badge => {
    const text = badge.innerText || badge.textContent;
    if (relatedTerms.some(term => text?.includes(term))) {
      const container = badge.closest('ytm-video-with-context-renderer, ytd-video-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });
}

function enableCinemaMode() {
  if (!location.pathname.startsWith('/watch')) return;
  
  // Check if we're in fullscreen mode
  const isFullscreen = document.fullscreenElement || 
                      document.webkitFullscreenElement || 
                      document.mozFullScreenElement || 
                      document.msFullscreenElement;
  
  if (isFullscreen) return; // Don't force cinema mode if already in fullscreen
  
  // Find the cinema mode button
  const cinemaButton = document.querySelector('.ytp-size-button');
  
  if (cinemaButton && !processingQueue.has(cinemaButton)) {
    // Check if cinema mode is already active by looking for the expanded state
    const player = document.querySelector('#movie_player');
    const isAlreadyCinema = player?.classList.contains('ytp-big-mode') || 
                           document.querySelector('ytd-watch-flexy[theater]');
    
    if (!isAlreadyCinema) {
      processingQueue.add(cinemaButton);
      cinemaButton.click();
      setTimeout(() => processingQueue.delete(cinemaButton), 1000);
    }
  }
}

function hideSponsoredContent() {
  // Remove sponsored/ad containers - Enhanced detection based on new HTML structure
  const sponsoredContainers = document.querySelectorAll(
    'ytd-rich-item-renderer:has(ytd-ad-slot-renderer), ' +
    'ytd-rich-item-renderer:has(ytd-in-feed-ad-layout-renderer), ' +
    'ytd-rich-item-renderer:has(ytd-video-display-full-buttoned-and-button-group-renderer)'
  );
  sponsoredContainers.forEach(container => {
    if (!processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove ad slot renderers directly
  const adSlots = document.querySelectorAll('ytd-ad-slot-renderer');
  adSlots.forEach(slot => {
    const container = slot.closest('ytd-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove in-feed ad layout renderers
  const adLayouts = document.querySelectorAll(
    'ytd-in-feed-ad-layout-renderer, ' +
    'ytd-video-display-full-buttoned-and-button-group-renderer, ' +
    'ytd-ad-inline-playback-meta-block, ' +
    'top-landscape-image-layout-view-model'
  );
  adLayouts.forEach(layout => {
    const container = layout.closest('ytd-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove elements with sponsored badges - Enhanced detection
  const sponsoredBadges = document.querySelectorAll(
    'ad-badge-view-model, ' +
    '[class*="ytwAdBadgeViewModelHost"], ' +
    '[class*="badge-style-type-ad"], ' +
    '.badge-style-type-ad'
  );
  sponsoredBadges.forEach(badge => {
    const container = badge.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });

  // Remove by sponsored text content - Enhanced with more variations
  const sponsoredTerms = [
    // English
    'Sponsored', 'Ad', 'Promoted', 'Advertisement',
    
    // Dutch
    'Gesponsord', 'Advertentie', 'Gepromoot', 'Reclame',
    
    // German
    'Gesponsert', 'Anzeige', 'Werbung', 'Gesponsort',
    
    // French
    'Sponsorisé', 'Publicité', 'Annonce', 'Promo'
  ];

  // Check badge elements
  const badges = document.querySelectorAll(
    'badge-shape, .badge-shape-wiz, [class*="badge"], ' +
    'ytd-badge-supported-renderer, .badge-style-type-ad, ' +
    '[aria-label*="Sponsored"], [title*="Sponsored"]'
  );
  badges.forEach(badge => {
    const text = badge.innerText || badge.textContent || badge.getAttribute('aria-label') || badge.getAttribute('title');
    if (text && sponsoredTerms.some(term => text.toLowerCase().includes(term.toLowerCase()))) {
      const container = badge.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
      if (container && !processingQueue.has(container)) {
        processingQueue.add(container);
        container.remove();
      }
    }
  });

  // Check for googleadservices links (ad links)
  const adLinks = document.querySelectorAll('a[href*="googleadservices.com"]');
  adLinks.forEach(link => {
    const container = link.closest('ytd-rich-item-renderer, ytm-rich-item-renderer');
    if (container && !processingQueue.has(container)) {
      processingQueue.add(container);
      container.remove();
    }
  });
}

// Settings management (for future UI)
function updateSetting(key, value) {
  SETTINGS[key] = value;
  GM_setValue(key, value);
  HTML.setAttribute(key, value);
  applyStyles();
  runDynamicSettings();
}

// Export for potential external use
window.FocusedYouTube = {
  settings: SETTINGS,
  updateSetting,
  runDynamicSettings
};