New:Socket for Asana Is Now Available.Learn more
Get Started

Vidsieve - Clean YouTube, Hide Shorts

Package Overview
Versions
1
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ytfeed@vidsieve.com - firefox Package Compare versions

Comparing version
1.7.0
to
1.8.2
+1
shared/device.js
const YtcDevice=(()=>{const t="https://vidsieve.com/uninstall";function e(e){try{if("function"!=typeof chrome.runtime.setUninstallURL)return;if(!e?.key||!e?.instanceId)return void chrome.runtime.setUninstallURL(t);const n=new URL(t),a=btoa(JSON.stringify({k:e.key,i:e.instanceId}));n.searchParams.set("d",a),chrome.runtime.setUninstallURL(n.toString())}catch{}}function n(t){return"number"==typeof t&&t>0&&t<=Date.now()?t:0}const a=Object.freeze({hideDiscoveryShelf:!1,hideSubscriptionsAlgo:!1,keywords:Object.freeze([]),minDuration:0,maxDuration:0,minViews:0,maxViews:0,dailyChannelLimit:0,mutedChannels:Object.freeze({})});let i=null;function r(t){try{return btoa(JSON.stringify(t))}catch{return null}}async function s(){const{device:t}=await chrome.storage.local.get(["device"]);return function(t){if(t&&"object"==typeof t)return t;if("string"==typeof t)try{const e=JSON.parse(atob(t));return e&&"object"==typeof e?e:void 0}catch{return}}(t)||{key:null,instanceId:null,status:"inactive"}}async function o(t,e){const n={Accept:"application/json","Content-Type":"application/json"};let a;chrome.runtime?.id&&(n["X-Extension-Id"]=chrome.runtime.id);try{a=await fetch(`https://api.vidsieve.com/${t}`,{method:"POST",headers:n,body:JSON.stringify(e),signal:AbortSignal.timeout(1e4)})}catch(e){return console.error("[Vidsieve] license API unreachable:",t,e),{ok:!1,kind:"network"}}try{const t=await a.json();return{ok:!0,status:a.status,data:t}}catch(e){return console.error("[Vidsieve] license API returned a non-JSON response:",t,a.status,e),{ok:!1,kind:"server",status:a.status}}}function c(t){const e=t?.message;return Array.isArray(e)&&e.length?e.join(" "):"string"==typeof e&&e?e:t?.error||"invalid"}function l(t,e){return{key:t.key,instanceId:t.instance?.id??e??null,status:t.status,expiresAt:t.expires_at,activationLimit:t.activation_limit,activationUsage:t.activation,lastValidatedAt:Date.now(),lastError:null}}let u=null;let d=null;let y=null;return Object.freeze({getState:s,isPro:async function(){const t=await s();if("active"!==t.status)return!1;if(!t.key||!t.instanceId)return!1;const e=n(t.lastValidatedAt);return!(Date.now()-e>6048e5)},activate:async function(t){return u||(u=(async()=>{const n=(t||"").trim();if(!n)return{ok:!1,error:"empty"};const a=await async function(){const{installId:t}=await chrome.storage.local.get(["installId"]);return t||(i||(i=(async()=>{const t=crypto.randomUUID();return await chrome.storage.local.set({installId:t}),t})().finally(()=>{i=null})),i)}(),s=await o("activate",{key:n,instance_name:`vidsieve-${a}`});if(!s.ok)return{ok:!1,error:"network"};const{status:u,data:d}=s;if(200!==u||"active"!==d.status)return{ok:!1,error:c(d)};const y=l(d);return await chrome.storage.local.set({device:r(y)}),e(y),{ok:!0,license:y}})().finally(()=>{u=null}),u)},validateIfStale:async function(){const t=await s();if(!t.key||!t.instanceId)return{ok:!1,error:"not-activated"};const e=n(t.lastValidatedAt);return Date.now()-e<864e5?{ok:!0,license:t}:async function(){return d||(d=(async()=>{const t=await s();if(!t.key||!t.instanceId)return{ok:!1,error:"not-activated"};const e=await o("validate",{key:t.key,instance_id:t.instanceId});if(!e.ok)return{ok:!0,license:t,stale:!0};const{status:n,data:a}=e;if(200!==n||"active"!==a.status){const e={...t,status:a.status||"invalid",lastValidatedAt:Date.now(),lastError:c(a)};return await chrome.storage.local.set({device:r(e)}),{ok:!0,license:e,valid:!1}}const i=l(a,t.instanceId);return await chrome.storage.local.set({device:r(i)}),{ok:!0,license:i,valid:!0}})().finally(()=>{d=null}),d)}()},deactivate:async function(){return y||(y=(async()=>{const t=await s();if(t.key&&t.instanceId){if(!(await o("deactivate",{key:t.key,instance_id:t.instanceId})).ok)return{ok:!1,error:"network"}}return await chrome.storage.local.remove("device"),e(null),{ok:!0}})().finally(()=>{y=null}),y)},gate:function(t,e){if(e)return t;for(const[e,n]of Object.entries(a))e in t&&(t[e]=n);return"dryrun"===t.watchedMode&&(t.watchedMode="dim"),t},syncUninstallUrl:e,GATED_KEYS:a})})();
+1
-1

@@ -1,1 +0,1 @@

"function"==typeof importScripts&&importScripts("../shared/i18n.js","../shared/storage.js","../shared/license.js","../shared/profiles.js","../shared/scheduler.js","../shared/schedule.js");const LICENSE_ALARM="ytc-license-validate",DEFAULTS={enabled:!0,hideSeen:!1,watchedMode:"hide",watchedThreshold:.5,hideShorts:!0,hideLive:!1,hideUpcoming:!1,hidePremieres:!1,hideMembers:!1,hideFilterBar:!1,hideMixes:!1,hideDiscoveryShelf:!1,hidePlayablesShelf:!1,hideSubscriptionsAlgo:!1,keywords:[],blockedChannels:[],whitelistedChannels:[],mutedChannels:{},muteDefaultDays:14,minDuration:0,maxDuration:0,minAgeDays:0,maxAgeDays:0,minViews:0,maxViews:0,dailyChannelLimit:0,homeFeedMode:"show",videosPerRow:"3",disableInfiniteScroll:!1,disableAutoplay:!1,hideRelated:!1,hideEndCards:!1,hideEndScreenFeed:!1,hideLiveChat:!1,hidePlaylistPanel:!1,hideChannelInfo:!1,hideDescription:!1,hideMerchShelf:!1,hideComments:!1,hideVideoActions:!1,hideAskButton:!1,hideSaveButton:!1,hideMoreActionsButton:!1,hideExploreSidebar:!1,hideSubscriptions:!1,hideShortsSidebar:!1,hideMoreFromYoutube:!1,hideNotifications:!1,hideVoiceSearch:!1,blurThumbnails:!1,hideProfilePhotos:!1,favoriteFilters:["hideShorts","hideSeen","hideMembers"],channelDayCounts:{},watchedVideos:{},hiddenCounts:{},hiddenByReason:{},totalHidden:0,reviewPrompt:{rated:!1,dismissedAt:null,lastShownAt:null,decisions:0},schedules:{items:{},prevProfileId:null,engagedProfileId:null,snoozeUntil:0}},ICON_SIZES=[16,32],ICON_PATHS_ON=Object.fromEntries(ICON_SIZES.map(e=>[e,`icons/icon${e}.png`])),ICON_PATHS_OFF=Object.fromEntries(ICON_SIZES.map(e=>[e,`icons/icon${e}-gray.png`]));async function loadIconImageData(e,a){const t=await fetch(chrome.runtime.getURL(e)),n=await t.blob(),o=await createImageBitmap(n),c=new OffscreenCanvas(a,a).getContext("2d");return c.drawImage(o,0,0,a,a),c.getImageData(0,0,a,a)}async function loadIconImageDataSet(e){const a=await Promise.all(ICON_SIZES.map(async a=>[a,await loadIconImageData(e[a],a)]));return Object.fromEntries(a)}let _iconImageDataPromise=null;function getIconImageDataSets(){return _iconImageDataPromise||(_iconImageDataPromise=Promise.all([loadIconImageDataSet(ICON_PATHS_ON),loadIconImageDataSet(ICON_PATHS_OFF)]).then(([e,a])=>({on:e,off:a})).catch(e=>{throw _iconImageDataPromise=null,e})),_iconImageDataPromise}async function syncToolbarIcon(){const{enabled:e=!0}=await chrome.storage.local.get(["enabled"]),a=await getIconImageDataSets();await chrome.action.setIcon({imageData:e?a.on:a.off})}async function syncUninstallUrl(){YtcLicense.syncUninstallUrl(await YtcLicense.getState())}async function syncHideShortsSidebar(){const{hideShortsSidebar:e}=await chrome.storage.local.get(["hideShortsSidebar"]);e||await chrome.storage.local.set({hideShortsSidebar:!0})}chrome.storage.onChanged.addListener((e,a)=>{"local"===a&&("license"in e&&(syncUninstallUrl().catch(()=>{}),YtcSchedule.syncAlarm().catch(()=>{})),"enabled"in e&&syncToolbarIcon().catch(()=>{}),!0===e.hideShorts?.newValue&&syncHideShortsSidebar().catch(()=>{}))}),chrome.runtime.onInstalled.addListener(async e=>{const a=await chrome.storage.local.get(Object.keys(DEFAULTS)),t={};for(const[e,n]of Object.entries(DEFAULTS))void 0===a[e]&&(t[e]=n);Object.keys(t).length>0&&await chrome.storage.local.set(t),ensureLicenseAlarm(),YtcSchedule.syncAlarm().catch(()=>{}),syncUninstallUrl().catch(()=>{}),syncToolbarIcon().catch(()=>{}),YtcLicense.validateIfStale().catch(()=>{});try{const{welcomeShown:e}=await chrome.storage.local.get(["welcomeShown"]);e||(await chrome.storage.local.set({welcomeShown:!0}),chrome.tabs.create({url:chrome.runtime.getURL("welcome/welcome.html")}))}catch{}});let _togglePauseInFlight=Promise.resolve();function ensureLicenseAlarm(){chrome.alarms.create(LICENSE_ALARM,{periodInMinutes:1440})}chrome.commands?.onCommand.addListener(e=>{"toggle-pause"===e&&(_togglePauseInFlight=_togglePauseInFlight.catch(()=>{}).then(async()=>{const{enabled:e=!0}=await chrome.storage.local.get(["enabled"]);await chrome.storage.local.set({enabled:!e})}))}),chrome.runtime.onStartup?.addListener?.(()=>{ensureLicenseAlarm(),YtcSchedule.syncAlarm().catch(()=>{}),syncUninstallUrl().catch(()=>{}),syncToolbarIcon().catch(()=>{}),YtcLicense.validateIfStale().catch(()=>{}),YtcSchedule.checkAndApply().catch(()=>{})}),chrome.alarms.onAlarm.addListener(e=>{e.name!==YtcSchedule.ALARM_NAME?e.name===LICENSE_ALARM&&YtcLicense.validateIfStale().catch(()=>{}):YtcSchedule.checkAndApply().catch(()=>{})}),chrome.runtime.onMessage.addListener(e=>{"openOptionsPage"===e?.type&&(e.hash?chrome.tabs.create({url:chrome.runtime.getURL(`options/options.html#${e.hash}`)}):chrome.runtime.openOptionsPage())});
"function"==typeof importScripts&&importScripts("../shared/i18n.js","../shared/storage.js","../shared/device.js","../shared/profiles.js","../shared/scheduler.js","../shared/schedule.js");const LICENSE_ALARM="ytc-license-validate",DEFAULTS={enabled:!0,hideSeen:!1,watchedMode:"hide",watchedThreshold:.5,hideShorts:!0,hideLive:!1,hideUpcoming:!1,hidePremieres:!1,hideMembers:!1,hideFilterBar:!1,hideMixes:!1,hideDiscoveryShelf:!1,hidePlayablesShelf:!1,hideSubscriptionsAlgo:!1,keywords:[],blockedChannels:[],whitelistedChannels:[],mutedChannels:{},muteDefaultDays:14,minDuration:0,maxDuration:0,minAgeDays:0,maxAgeDays:0,minViews:0,maxViews:0,dailyChannelLimit:0,homeFeedMode:"show",videosPerRow:"3",disableInfiniteScroll:!1,disableAutoplay:!1,hideRelated:!1,hideEndCards:!1,hideEndScreenFeed:!1,hideLiveChat:!1,hidePlaylistPanel:!1,hideChannelInfo:!1,hideDescription:!1,hideMerchShelf:!1,hideComments:!1,hideVideoActions:!1,hideAskButton:!1,hideSaveButton:!1,hideMoreActionsButton:!1,hideExploreSidebar:!1,hideSubscriptions:!1,hideShortsSidebar:!1,hideMoreFromYoutube:!1,hideNotifications:!1,hideVoiceSearch:!1,blurThumbnails:!1,hideProfilePhotos:!1,favoriteFilters:["hideShorts","hideSeen","hideMembers"],channelDayCounts:{},watchedVideos:{},hiddenCounts:{},hiddenByReason:{},totalHidden:0,reviewPrompt:{rated:!1,dismissedAt:null,lastShownAt:null,decisions:0},schedules:{items:{},prevProfileId:null,engagedProfileId:null,snoozeUntil:0}},ICON_SIZES=[16,32],ICON_PATHS_ON=Object.fromEntries(ICON_SIZES.map(e=>[e,`icons/icon${e}.png`])),ICON_PATHS_OFF=Object.fromEntries(ICON_SIZES.map(e=>[e,`icons/icon${e}-gray.png`]));async function loadIconImageData(e,a){const t=await fetch(chrome.runtime.getURL(e)),n=await t.blob(),o=await createImageBitmap(n),c=new OffscreenCanvas(a,a).getContext("2d");return c.drawImage(o,0,0,a,a),c.getImageData(0,0,a,a)}async function loadIconImageDataSet(e){const a=await Promise.all(ICON_SIZES.map(async a=>[a,await loadIconImageData(e[a],a)]));return Object.fromEntries(a)}let _iconImageDataPromise=null;function getIconImageDataSets(){return _iconImageDataPromise||(_iconImageDataPromise=Promise.all([loadIconImageDataSet(ICON_PATHS_ON),loadIconImageDataSet(ICON_PATHS_OFF)]).then(([e,a])=>({on:e,off:a})).catch(e=>{throw _iconImageDataPromise=null,e})),_iconImageDataPromise}async function syncToolbarIcon(){const{enabled:e=!0}=await chrome.storage.local.get(["enabled"]),a=await getIconImageDataSets();await chrome.action.setIcon({imageData:e?a.on:a.off})}async function syncUninstallUrl(){YtcDevice.syncUninstallUrl(await YtcDevice.getState())}async function syncHideShortsSidebar(){const{hideShortsSidebar:e}=await chrome.storage.local.get(["hideShortsSidebar"]);e||await chrome.storage.local.set({hideShortsSidebar:!0})}chrome.storage.onChanged.addListener((e,a)=>{"local"===a&&("device"in e&&(syncUninstallUrl().catch(()=>{}),YtcSchedule.syncAlarm().catch(()=>{})),"enabled"in e&&syncToolbarIcon().catch(()=>{}),!0===e.hideShorts?.newValue&&syncHideShortsSidebar().catch(()=>{}))}),chrome.runtime.onInstalled.addListener(async e=>{const a=await chrome.storage.local.get(Object.keys(DEFAULTS)),t={};for(const[e,n]of Object.entries(DEFAULTS))void 0===a[e]&&(t[e]=n);Object.keys(t).length>0&&await chrome.storage.local.set(t),ensureLicenseAlarm(),YtcSchedule.syncAlarm().catch(()=>{}),syncUninstallUrl().catch(()=>{}),syncToolbarIcon().catch(()=>{}),YtcDevice.validateIfStale().catch(()=>{});try{const{welcomeShown:e}=await chrome.storage.local.get(["welcomeShown"]);e||(await chrome.storage.local.set({welcomeShown:!0}),chrome.tabs.create({url:chrome.runtime.getURL("welcome/welcome.html")}))}catch{}});let _togglePauseInFlight=Promise.resolve();function ensureLicenseAlarm(){chrome.alarms.create(LICENSE_ALARM,{periodInMinutes:1440})}chrome.commands?.onCommand.addListener(e=>{"toggle-pause"===e&&(_togglePauseInFlight=_togglePauseInFlight.catch(()=>{}).then(async()=>{const{enabled:e=!0}=await chrome.storage.local.get(["enabled"]);await chrome.storage.local.set({enabled:!e})}))}),chrome.runtime.onStartup?.addListener?.(()=>{ensureLicenseAlarm(),YtcSchedule.syncAlarm().catch(()=>{}),syncUninstallUrl().catch(()=>{}),syncToolbarIcon().catch(()=>{}),YtcDevice.validateIfStale().catch(()=>{}),YtcSchedule.checkAndApply().catch(()=>{})}),chrome.alarms.onAlarm.addListener(e=>{e.name!==YtcSchedule.ALARM_NAME?e.name===LICENSE_ALARM&&YtcDevice.validateIfStale().catch(()=>{}):YtcSchedule.checkAndApply().catch(()=>{})}),chrome.runtime.onMessage.addListener(e=>{"openOptionsPage"===e?.type&&(e.hash?chrome.tabs.create({url:chrome.runtime.getURL(`options/options.html#${e.hash}`)}):chrome.runtime.openOptionsPage())});

@@ -1,1 +0,1 @@

let _observerStarted=!1,isProCached=!1;const PREF_KEYS=["enabled","hideSeen","watchedMode","watchedThreshold","hideShorts","hideLive","hideUpcoming","hidePremieres","hideMembers","hideFilterBar","hideMixes","hideDiscoveryShelf","hidePlayablesShelf","hideSubscriptionsAlgo","keywords","blockedChannels","whitelistedChannels","mutedChannels","minDuration","maxDuration","minAgeDays","maxAgeDays","minViews","maxViews","dailyChannelLimit","homeFeedMode","videosPerRow","disableInfiniteScroll","disableAutoplay","hideRelated","hideEndCards","hideEndScreenFeed","hideLiveChat","hidePlaylistPanel","hideChannelInfo","hideDescription","hideMerchShelf","hideComments","hideVideoActions","hideAskButton","hideSaveButton","hideMoreActionsButton","hideExploreSidebar","hideSubscriptions","hideShortsSidebar","hideMoreFromYoutube","hideNotifications","hideVoiceSearch","blurThumbnails","hideProfilePhotos","hiddenCounts","hiddenByReason","totalHidden"],SILENT_KEYS=new Set(["channelDayCounts","hiddenCounts","hiddenByReason","totalHidden"]);async function init(){const[e,t]=await Promise.all([YtcStorage.get(PREF_KEYS),YtcLicense.isPro()]);isProCached=t,prefs={...prefs,...e},YtcLicense.gate(prefs,isProCached),prefs.enabled&&activate(),YtcLicense.validateIfStale().catch(()=>{}),chrome.storage.onChanged.addListener(e=>{let t=!1;for(const n of Object.keys(e))SILENT_KEYS.has(n)?prefs[n]=e[n].newValue:PREF_KEYS.includes(n)&&(prefs[n]=e[n].newValue,t=!0);const n=()=>{t&&YtcLicense.gate(prefs,isProCached),"enabled"in e&&prefs.enabled&&activate(),"disableAutoplay"in e&&e.disableAutoplay.newValue&&enforceAutoplayOff(),("homeFeedMode"in e||"enabled"in e)&&enforceHomeRedirect(),t?(applyUiCleanupFlags(),resetProcessedCards(),schedulecleanFeed()):"watchedVideos"in e&&(resetProcessedCards(),schedulecleanFeed())};if("license"in e)return t=!0,void YtcLicense.isPro().then(e=>{isProCached=e,n()});n()}),injectHoverStyles(),applyUiCleanupFlags(),trackMenuTriggers()}function activate(){_observerStarted?schedulecleanFeed():(_observerStarted=!0,trackCurrentVideoFallback(),enforceAutoplayOff(),startObserver(),watchNavigation())}const HOME_REDIRECT_PATHS={subscriptions:"/feed/subscriptions",watchLater:"/playlist?list=WL",library:"/feed/library"};function enforceHomeRedirect(){const e=document.documentElement;if(!prefs.enabled||"/"!==location.pathname)return void e.removeAttribute("data-ytc-home-state");const t=HOME_REDIRECT_PATHS[prefs.homeFeedMode];t?(e.setAttribute("data-ytc-home-state","show"),location.replace(`https://www.youtube.com${t}`)):e.setAttribute("data-ytc-home-state",prefs.homeFeedMode)}function enforceAutoplayOff(e=0){if(!prefs.enabled||!prefs.disableAutoplay)return;const t=document.querySelector(".ytp-autonav-toggle-button");t?"true"===t.getAttribute("aria-checked")&&t.click():e<10&&setTimeout(()=>enforceAutoplayOff(e+1),500)}function startObserver(){cleanFeed();const e=document.querySelector("ytd-app")??document.body,t=new MutationObserver(e=>{if(YtcStorage.alive()){for(const t of e)queueMutatedNodes(t.addedNodes);document.hidden||schedulecleanFeed()}else t.disconnect()});t.observe(e,{childList:!0,subtree:!0}),document.addEventListener("visibilitychange",()=>{document.hidden||schedulecleanFeed()})}function watchNavigation(){document.addEventListener("yt-navigate-finish",()=>{resetProcessedCards(),trackCurrentVideoFallback(),enforceAutoplayOff(),enforceHomeRedirect(),schedulecleanFeed()})}function resetProcessedCards(){document.querySelectorAll("[data-ytc-done], [data-ytc-counted], [data-ytc-hidden], [data-ytc-dim]").forEach(e=>{e.removeAttribute("data-ytc-done"),e.removeAttribute("data-ytc-counted"),e.removeAttribute("data-ytc-reason"),e.removeAttribute("data-ytc-hidden"),e.removeAttribute("data-ytc-dim")}),forceFullRescan()}function injectHoverStyles(){if(document.getElementById("ytc-style"))return;const e=document.createElement("style");e.id="ytc-style",e.textContent='\n ytd-rich-grid-renderer ytd-rich-grid-row,\n ytd-rich-grid-renderer ytd-rich-grid-row > #contents {\n display: contents !important;\n }\n [data-ytc-hidden] { display: none !important; }\n [data-ytc-dim] { opacity: 0.35 !important; filter: grayscale(1) !important; }\n\n /* watchedMode="dryrun": applyAction() grava data-ytc-dim="preview" em\n vez de "1" pra estilizar diferente (borda+etiqueta em vez de\n opacity/grayscale) sem precisar de outro atributo no <html>.\n box-sizing: border-box faz a borda "comer" o conteúdo interno em vez\n de desalinhar a grade. */\n [data-ytc-dim="preview"] {\n opacity: 1 !important;\n filter: none !important;\n position: relative;\n }\n [data-ytc-dim="preview"]::before {\n content: "";\n position: absolute;\n /* -12px (igual ao hover nativo) sobrepunha o card vizinho numa grade\n cheia; -7px cabe até a metade do gutter. */\n inset: -7px;\n z-index: 5;\n background: rgba(180, 83, 9, 0.35);\n border-radius: 14px;\n pointer-events: none;\n }\n [data-ytc-dim="preview"]::after {\n content: attr(data-ytc-reason);\n position: absolute;\n top: 10px;\n left: 8px;\n z-index: 10;\n background: #b45309 url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'white\' stroke-width=\'2.75\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3E%3Cpath d=\'M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24\'/%3E%3Cline x1=\'1\' y1=\'1\' x2=\'23\' y2=\'23\'/%3E%3C/svg%3E") no-repeat 10px center;\n background-size: 14px 14px;\n color: #fff;\n font: 700 12px/16px Roboto, Arial, sans-serif;\n padding: 4px 10px 4px 30px;\n border-radius: 4px;\n pointer-events: none;\n }\n\n html[data-ytc-hide-related] ytd-watch-next-secondary-results-renderer,\n html[data-ytc-hide-related] #related.ytd-watch-flexy { display: none !important; }\n\n html[data-ytc-hide-endcards] .ytp-ce-element,\n html[data-ytc-hide-endcards] .ytp-cards-teaser { display: none !important; }\n\n /* .html5-endscreen (não só .ytp-endscreen-content) leva junto as setas\n anterior/próximo, que são irmãs do content, não filhas.\n .ytp-fullscreen-grid é a reformulação 2025 da mesma tela, estrutura\n nova e independente. */\n html[data-ytc-hide-endscreen-feed] .html5-endscreen,\n html[data-ytc-hide-endscreen-feed] .ytp-fullscreen-grid { display: none !important; }\n\n html[data-ytc-hide-live-chat] ytd-live-chat-frame#chat,\n html[data-ytc-hide-live-chat] #chat.ytd-watch-flexy,\n /* Card "Reprodução do chat" no carrossel abaixo da descrição — mesmo\n painel, atalho separado. Casa pelo path do ícone (idioma-independente);\n escopado no #teaser-carousel inteiro, não só no item, senão o título\n ficava visível com o conteúdo vazio. */\n html[data-ytc-hide-live-chat] div#teaser-carousel:has(path[d="M16 2H4a3 3 0 00-3 3v8a3 3 0 003 3h1v2.14a.8.8 0 001.188.7L11.3 16H16a3 3 0 003-3V5a3 3 0 00-3-3ZM4 4h12a1 1 0 011 1v8a1 1 0 01-1 1h-5.218l-.452.252L7 16.1V14H4a1 1 0 01-1-1V5a1 1 0 011-1Zm17 2.174A3 3 0 0123 9v8a3 3 0 01-2.846 2.996L20 20v2.14a.8.8 0 01-1.189.7L13.701 20H8.216l3.6-2h2.402l.453.252L18 20.101V18.05l1.95-.05.113-.003A1 1 0 0021 17V6.174Z"]) { display: none !important; }\n\n html[data-ytc-hide-playlist-panel] ytd-playlist-panel-renderer#playlist,\n html[data-ytc-hide-playlist-panel] #playlist.ytd-watch-flexy { display: none !important; }\n\n html[data-ytc-hide-channel-info] ytd-watch-metadata #owner,\n html[data-ytc-hide-channel-info] ytd-video-owner-renderer { display: none !important; }\n\n html[data-ytc-hide-description] ytd-watch-metadata #description,\n html[data-ytc-hide-description] #description-inline-expander.ytd-watch-metadata { display: none !important; }\n\n html[data-ytc-hide-merch] ytd-merch-shelf-renderer,\n html[data-ytc-hide-merch] ytd-ticket-shelf-renderer,\n html[data-ytc-hide-merch] ytd-product-shelf-renderer { display: none !important; }\n\n html[data-ytc-hide-notifications] ytd-notification-topbar-button-renderer { display: none !important; }\n\n html[data-ytc-hide-voice-search] #voice-search-button { display: none !important; }\n\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/premium"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/feed/storefront"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/gaming"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/kids"]),\n html[data-ytc-hide-more-from-youtube] ytd-mini-guide-entry-renderer:has(a[href="/premium"]),\n html[data-ytc-hide-more-from-youtube] ytd-mini-guide-entry-renderer:has(a[href="/gaming"]),\n /* Layouts novos agrupam Premium/Music/Kids numa ytd-guide-section-renderer\n titulada — casa a seção pelo href de um filho (idioma-independente)\n em vez do título. */\n html[data-ytc-hide-more-from-youtube] ytd-guide-section-renderer:has(a[href="/premium"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-section-renderer:has(a[href^="https://music.youtube.com"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-section-renderer:has(a[href^="https://www.youtubekids.com"]) { display: none !important; }\n\n /* visibility (não display) de propósito — o avatar ancora a indentação\n das respostas encadeadas; display:none desalinharia a thread. */\n html[data-ytc-hide-profile-photos] ytd-comment-view-model #author-thumbnail { visibility: hidden !important; }\n\n html[data-ytc-hide-profile-photos] ytd-video-owner-renderer #avatar,\n html[data-ytc-hide-profile-photos] ytd-channel-renderer #avatar,\n html[data-ytc-hide-profile-photos] #avatar yt-img-shadow,\n html[data-ytc-hide-profile-photos] yt-img-shadow#avatar,\n /* Resultado de busca usa #channel-thumbnail pro link+thumbnail do canal\n (#avatar deles fica vazio, só decorativo). */\n html[data-ytc-hide-profile-photos] #channel-thumbnail,\n /* Layout "lockup" (feed/sidebar novos) não tem #avatar — casa pela\n classe estável do wrapper. display:none aqui (não visibility) pro\n título ocupar o espaço liberado. */\n html[data-ytc-hide-profile-photos] .ytLockupMetadataViewModelAvatar { display: none !important; }\n\n html[data-ytc-hide-comments] ytd-comments#comments,\n html[data-ytc-hide-comments] #comments.ytd-watch-flexy { display: none !important; }\n\n html[data-ytc-hide-video-actions] segmented-like-dislike-button-view-model,\n html[data-ytc-hide-video-actions] like-button-view-model,\n html[data-ytc-hide-video-actions] dislike-button-view-model,\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-toggle-button-renderer,\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Share" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Compartilhar" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Compartir" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-button-renderer:has(button[aria-label="Share" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-button-renderer:has(button[aria-label="Compartilhar" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-button-renderer:has(button[aria-label="Compartir" i]),\n /* Share não tem classe própria — casa pelo path do ícone. */\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(path[d="M10 3.158V7.51c-5.428.223-8.27 3.75-8.875 11.199-.04.487-.07.975-.09 1.464l-.014.395c-.014.473.578.684.88.32.302-.368.61-.73.925-1.086l.244-.273c1.79-1.967 3-2.677 4.93-2.917a18.011 18.011 0 012-.112v4.346a1 1 0 001.646.763l9.805-8.297 1.55-1.31-1.55-1.31-9.805-8.297A1 1 0 0010 3.158Zm2 6.27v.002-4.116l7.904 6.688L12 18.689v-4.212l-2.023.024c-1.935.022-3.587.17-5.197 1.024a9 9 0 00-1.348.893c.355-1.947.916-3.39 1.63-4.425 1.062-1.541 2.607-2.385 5.02-2.485L12 9.428Z"]),\n /* Super Thanks — mesmo wrapper genérico, casa pelo ícone de coração. */\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(path[d="M16.25 2A6.7 6.7 0 0012 3.509 6.75 6.75 0 001 8.75c0 4.497 2.784 7.818 5.207 9.87a23.498 23.498 0 004.839 3.143l.096.044.03.013.01.005.003.002.002.001c.273-.609.544-1.218.813-1.828 0 0-9-4-9-11.25a4.75 4.75 0 018.932-2.247A1 1 0 0011 7.5v.638c-.357.1-.689.26-.979.49A2.35 2.35 0 009.13 10.5c-.007.424.112.84.342 1.197.21.31.497.563.831.734.546.29 1.23.411 1.693.502.557.109.899.19 1.117.315.086.048.109.082.114.09.004.006.028.045.028.162 0 .024-.008.118-.165.235-.162.122-.5.27-1.09.27-.721 0-1.049-.21-1.181-.323a.6.6 0 01-.142-.168l.005.013.006.014.002.009a.996.996 0 00-1.884.64l.947-.316-.003.001c-.875.292-.939.314-.943.317l.001.003.003.006.004.015.012.032c.045.111.1.218.162.321.146.236.324.444.535.624.357.306.841.566 1.476.702v.605a1 1 0 002 0v-.614c1.29-.289 2.245-1.144 2.245-2.386 0-.44-.103-.852-.327-1.212-.22-.355-.52-.6-.82-.77-.555-.316-1.244-.445-1.719-.539-.567-.111-.915-.185-1.143-.305a.5.5 0 01-.1-.07l-.004-.003-.003-.009a.4.4 0 01-.009-.092c0-.158.053-.244.14-.314.109-.086.341-.19.74-.19.373-.001.73.144.997.404a.996.996 0 001.518-1.286l-.699.58.698-.582v-.001l-.002-.001-.002-.003-.006-.006-.016-.018a2.984 2.984 0 00-.178-.182A3.45 3.45 0 0013 8.154V7.5a1 1 0 00-.933-.997A4.75 4.75 0 0121 8.75C21 16 12 20 12 20l.813 1.827.002-.001.003-.001.01-.005.029-.013.097-.045c.081-.037.191-.09.33-.16a23.5 23.5 0 004.509-2.982C20.216 16.568 23 13.248 23 8.75A6.75 6.75 0 0016.25 2Zm-3.437 19.827L12 20l-.813 1.828.813.36.813-.361Z"]) { display: none !important; }\n\n html[data-ytc-hide-ask-button] ytd-menu-renderer .you-chat-entrypoint-button,\n html[data-ytc-hide-ask-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Ask" i]),\n html[data-ytc-hide-ask-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Perguntar" i]),\n html[data-ytc-hide-ask-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Preguntar" i]),\n /* Segunda entrada da mesma feature Ask/YouChat: card promocional na\n descrição, tag própria e estável. */\n html[data-ytc-hide-ask-button] yt-video-description-youchat-section-view-model { display: none !important; }\n\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label*="Save" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label*="Salvar" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label*="Guardar" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer ytd-button-renderer:has(button[aria-label*="Save" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer ytd-button-renderer:has(button[aria-label*="Salvar" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer ytd-button-renderer:has(button[aria-label*="Guardar" i]),\n /* Save também não tem classe própria — mesmo raciocínio do Share. */\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(path[d="M19 2H5a2 2 0 00-2 2v16.887c0 1.266 1.382 2.048 2.469 1.399L12 18.366l6.531 3.919c1.087.652 2.469-.131 2.469-1.397V4a2 2 0 00-2-2ZM5 20.233V4h14v16.233l-6.485-3.89-.515-.309-.515.309L5 20.233Z"]) { display: none !important; }\n\n html[data-ytc-hide-more-actions-button] ytd-menu-renderer yt-icon-button.dropdown-trigger,\n html[data-ytc-hide-more-actions-button] ytd-menu-renderer #button.dropdown-trigger,\n /* YouTube migrou o "..." pro componente novo yt-button-shape (mesma\n família do Ask/Save/Share); id estável como filho direto do menu. */\n html[data-ytc-hide-more-actions-button] ytd-menu-renderer > yt-button-shape#button-shape { display: none !important; }\n\n /* Não mira ytd-guide-section-renderer inteiro: Home/Shorts/Subscriptions\n viram irmãos dentro da MESMA section, então isso escondia os três\n juntos (bug real, já corrigido). Só a entry + mini-guide-entry. */\n html[data-ytc-hide-subscriptions] ytd-mini-guide-entry-renderer:has(a[href="/feed/subscriptions"]),\n html[data-ytc-hide-subscriptions] ytd-guide-entry-renderer:has(a[href="/feed/subscriptions"]) { display: none !important; }\n html[data-ytc-hide-subscriptions] ytd-guide-section-renderer:has(ytd-guide-collapsible-section-entry-renderer a[href="/feed/subscriptions"]) { display: none !important; }\n\n html[data-ytc-hide-explore] ytd-guide-entry-renderer a[href="/feed/trending"],\n html[data-ytc-hide-explore] ytd-guide-entry-renderer a[href="/feed/explore"],\n html[data-ytc-hide-explore] ytd-mini-guide-entry-renderer:has(a[href="/feed/trending"]),\n html[data-ytc-hide-explore] ytd-mini-guide-entry-renderer:has(a[href="/feed/explore"]) { display: none !important; }\n html[data-ytc-hide-explore] ytd-guide-entry-renderer:has(a[href="/feed/trending"]),\n html[data-ytc-hide-explore] ytd-guide-entry-renderer:has(a[href="/feed/explore"]) { display: none !important; }\n /* Layouts novos agrupam Explore numa section titulada sem href estável\n nos filhos, exceto "Filmes" (sempre /feed/storefront) — casa a\n section pai por esse único filho confiável. */\n html[data-ytc-hide-explore] ytd-guide-section-renderer:has(a[href^="/feed/storefront"]) { display: none !important; }\n\n /* Shelf "YouTube Playables" (mini-games) misturado no feed. */\n html[data-ytc-hide-playables-shelf] ytd-rich-section-renderer:has(ytd-mini-game-card-view-model) { display: none !important; }\n\n html[data-ytc-hide-mixes] ytd-radio-renderer { display: none !important; }\n\n /* "Descubra mais temas" e o shelf promocional "YouTube featured" —\n ambos dentro de um ytd-rich-section-renderer, identificados pela tag\n do componente interno (idioma-independente). Vídeos individuais do\n shelf de marca continuam filtrados por Rules.evaluate() normalmente;\n isto só esconde a moldura/cabeçalho do shelf. */\n html[data-ytc-hide-discovery-shelf] ytd-rich-section-renderer:has(ytd-chips-shelf-with-video-shelf-renderer),\n html[data-ytc-hide-discovery-shelf] ytd-rich-section-renderer:has(ytd-brand-video-shelf-renderer) { display: none !important; }\n\n /* Shelves algorítmicas que o YouTube injeta em /feed/subscriptions: o\n feed cronológico normal dessa página nunca agrupa vídeos numa shelf\n titulada, então qualquer ytd-rich-shelf-renderer ali já é a inserção\n algorítmica. Escopado por page-subtype pra não pegar shelves da Home. */\n html[data-ytc-hide-subscriptions-algo] ytd-browse[page-subtype="subscriptions"] ytd-rich-section-renderer:has(ytd-rich-shelf-renderer) { display: none !important; }\n \n html[data-ytc-hide-filter-bar] ytd-rich-grid-renderer > #header {\n display: none !important;\n }\n html[data-ytc-hide-filter-bar] #frosted-glass.with-chipbar {\n height: 68px !important;\n }\n\n /* ytd-rich-section-renderer é o mesmo wrapper genérico do shelf\n "discovery" — só conta como Shorts se tiver um card de Shorts real\n dentro (:has()). */\n html[data-ytc-hide-shorts] ytd-rich-shelf-renderer[is-shorts],\n html[data-ytc-hide-shorts] ytd-reel-shelf-renderer,\n html[data-ytc-hide-shorts] grid-shelf-view-model,\n html[data-ytc-hide-shorts] ytd-rich-section-renderer:has(\n ytd-reel-item-renderer,\n ytm-shorts-lockup-view-model,\n ytd-rich-shelf-renderer[is-shorts],\n ytd-reel-shelf-renderer,\n grid-shelf-view-model\n ) { display: none !important; }\n\n /* Ícone do raio (Shorts) é o mesmo em qualquer idioma; href="/shorts/"\n reforça o caso da sidebar recolhida. */\n html[data-ytc-hide-shorts-sidebar] ytd-mini-guide-entry-renderer:has(a[href="/shorts/"]),\n html[data-ytc-hide-shorts-sidebar] ytd-mini-guide-entry-renderer:has(path[d="m13.467 1.19-8 4.7a5 5 0 00-.255 8.46 5 5 0 005.32 8.462l8-4.7a5 5 0 00.258-8.462 5 5 0 001.641-6.464l-.12-.217a5 5 0 00-6.844-1.78m5.12 2.79a2.999 2.999 0 01-1.067 4.107l-1.327.78a1 1 0 00.096 1.775l.943.423a3 3 0 01.288 5.323l-8 4.7a3 3 0 01-3.039-5.173l1.327-.78a1 1 0 00-.097-1.775l-.942-.423a3 3 0 01-.288-5.323l8-4.7a3 3 0 014.106 1.066ZM15 12l-5-3v6l5-3Z"]),\n html[data-ytc-hide-shorts-sidebar] ytd-guide-entry-renderer:has(path[d="m13.467 1.19-8 4.7a5 5 0 00-.255 8.46 5 5 0 005.32 8.462l8-4.7a5 5 0 00.258-8.462 5 5 0 001.641-6.464l-.12-.217a5 5 0 00-6.844-1.78m5.12 2.79a2.999 2.999 0 01-1.067 4.107l-1.327.78a1 1 0 00.096 1.775l.943.423a3 3 0 01.288 5.323l-8 4.7a3 3 0 01-3.039-5.173l1.327-.78a1 1 0 00-.097-1.775l-.942-.423a3 3 0 01-.288-5.323l8-4.7a3 3 0 014.106 1.066ZM15 12l-5-3v6l5-3Z"]) { display: none !important; }\n\n html[data-ytc-blur-thumbs] ytd-thumbnail img,\n html[data-ytc-blur-thumbs] yt-image img,\n html[data-ytc-blur-thumbs] yt-thumbnail-view-model img {\n filter: blur(14px) saturate(0.85) !important;\n transition: filter .2s ease;\n }\n /* --ytd-rich-grid-items-per-row é a custom property que o próprio\n YouTube já usa pra decidir a grade responsiva do feed — sobrescrever\n ela em vez de reimplementar grid/flex na mão evita brigar com o\n layout nativo. Escopo igual ao hide-subscriptions-algo acima:\n page-subtype casa Home e Subscriptions, os dois lugares onde essa\n grade aparece. */\n html[data-ytc-videos-per-row] ytd-browse[page-subtype="home"] ytd-rich-item-renderer[rendered-from-rich-grid]:not([is-shorts-grid]),\n html[data-ytc-videos-per-row] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer[rendered-from-rich-grid]:not([is-shorts-grid]) {\n --ytd-rich-grid-items-per-row: var(--ytc-videos-per-row) !important;\n }\n\n /* videosPerRow=1: com só 1 card por linha, uma thumbnail 16:9 em cima do\n título (layout vertical padrão) desperdiça a largura toda disponível\n ao lado — vira lista horizontal (thumbnail à esquerda, texto ocupando\n o resto), mesma ideia do "list view" do youtube-enhancer\n (temp/youtube-enhancer/css/youtube.css). .ytLockupViewModelVertical é\n o wrapper do card no layout "lockup" novo (Home/Subscriptions atuais);\n card antigo (ytd-rich-grid-media, layouts A/B mais raros) não tem esse\n wrapper e continua vertical — sem fallback aqui de propósito, mesmo\n espírito de simplicidade do resto desta feature. */\n html[data-ytc-list-view] ytd-browse[page-subtype="home"] ytd-rich-item-renderer .ytLockupViewModelVertical,\n html[data-ytc-list-view] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer .ytLockupViewModelVertical {\n flex-direction: row !important;\n }\n html[data-ytc-list-view] ytd-browse[page-subtype="home"] ytd-rich-item-renderer .ytLockupViewModelContentImage,\n html[data-ytc-list-view] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer .ytLockupViewModelContentImage {\n flex: 0 0 220px !important;\n width: 220px !important;\n margin-inline-end: 16px !important;\n }\n html[data-ytc-list-view] ytd-browse[page-subtype="home"] ytd-rich-item-renderer .ytLockupMetadataViewModelHost,\n html[data-ytc-list-view] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer .ytLockupMetadataViewModelHost {\n flex: 1 1 auto !important;\n min-width: 0 !important;\n }\n\n /* ytd-continuation-item-renderer é o placeholder que o próprio YouTube\n observa (IntersectionObserver interno) pra saber quando buscar mais\n uma leva de vídeos — escondê-lo faz o carregamento parar depois da\n primeira leva, sem mexer em scroll/wheel nem em rede. Mesma técnica\n do untrap-for-youtube (shared/options/options.json:1591-1593 em\n temp/untrap-for-youtube), aplicada no mesmo escopo Home+Subscriptions\n de videosPerRow acima. */\n html[data-ytc-disable-infinite-scroll] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer > #contents > ytd-continuation-item-renderer,\n html[data-ytc-disable-infinite-scroll] ytd-browse[page-subtype="subscriptions"] ytd-rich-grid-renderer > #contents > ytd-continuation-item-renderer {\n display: none !important;\n }\n\n html[data-ytc-blur-thumbs] ytd-rich-item-renderer:hover img,\n html[data-ytc-blur-thumbs] ytd-video-renderer:hover img,\n html[data-ytc-blur-thumbs] ytd-compact-video-renderer:hover img,\n html[data-ytc-blur-thumbs] yt-lockup-view-model:hover img,\n html[data-ytc-blur-thumbs] ytm-shorts-lockup-view-model:hover img {\n filter: none !important;\n }\n ',document.head.appendChild(e)}function applyUiCleanupFlags(){const e=document.documentElement,t=prefs.enabled,n={"data-ytc-hide-related":t&&prefs.hideRelated,"data-ytc-hide-endcards":t&&prefs.hideEndCards,"data-ytc-hide-endscreen-feed":t&&prefs.hideEndScreenFeed,"data-ytc-hide-live-chat":t&&prefs.hideLiveChat,"data-ytc-hide-playlist-panel":t&&prefs.hidePlaylistPanel,"data-ytc-hide-channel-info":t&&prefs.hideChannelInfo,"data-ytc-hide-description":t&&prefs.hideDescription,"data-ytc-hide-merch":t&&prefs.hideMerchShelf,"data-ytc-hide-comments":t&&prefs.hideComments,"data-ytc-hide-video-actions":t&&prefs.hideVideoActions,"data-ytc-hide-ask-button":t&&prefs.hideAskButton,"data-ytc-hide-save-button":t&&prefs.hideSaveButton,"data-ytc-hide-more-actions-button":t&&prefs.hideMoreActionsButton,"data-ytc-hide-explore":t&&prefs.hideExploreSidebar,"data-ytc-hide-subscriptions":t&&prefs.hideSubscriptions,"data-ytc-hide-shorts-sidebar":t&&prefs.hideShortsSidebar,"data-ytc-hide-more-from-youtube":t&&prefs.hideMoreFromYoutube,"data-ytc-hide-playables-shelf":t&&prefs.hidePlayablesShelf,"data-ytc-hide-mixes":t&&prefs.hideMixes,"data-ytc-hide-discovery-shelf":t&&prefs.hideDiscoveryShelf,"data-ytc-hide-subscriptions-algo":t&&prefs.hideSubscriptionsAlgo,"data-ytc-hide-filter-bar":t&&prefs.hideFilterBar,"data-ytc-hide-shorts":t&&prefs.hideShorts,"data-ytc-hide-notifications":t&&prefs.hideNotifications,"data-ytc-hide-voice-search":t&&prefs.hideVoiceSearch,"data-ytc-blur-thumbs":t&&prefs.blurThumbnails,"data-ytc-hide-profile-photos":t&&prefs.hideProfilePhotos,"data-ytc-disable-infinite-scroll":t&&prefs.disableInfiniteScroll};for(const[t,a]of Object.entries(n))a?e.setAttribute(t,"1"):e.removeAttribute(t);t&&prefs.videosPerRow?(e.setAttribute("data-ytc-videos-per-row","1"),e.style.setProperty("--ytc-videos-per-row",prefs.videosPerRow)):(e.removeAttribute("data-ytc-videos-per-row"),e.style.removeProperty("--ytc-videos-per-row")),t&&"1"===prefs.videosPerRow?e.setAttribute("data-ytc-list-view","1"):e.removeAttribute("data-ytc-list-view")}const CARD_SEL="ytd-rich-item-renderer, ytd-video-renderer, ytd-compact-video-renderer, ytd-grid-video-renderer, ytd-reel-item-renderer, ytd-rich-grid-media, yt-lockup-view-model, ytm-shorts-lockup-view-model, ytd-playlist-panel-video-renderer",WATCH_ACTIONS_SEL="ytd-watch-metadata #actions ytd-menu-renderer",LEGACY_TRIGGER_SEL="yt-button-shape#button-shape, yt-icon-button.dropdown-trigger",V2_TRIGGER_SEL=".ytLockupMetadataViewModelMenuButton button",MENU_POPUP_SEL="ytd-menu-popup-renderer, yt-list-view-model",MENU_ARM_MS=3e3,ICON_BLOCK="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11 11-4.925 11-11S18.075 1 12 1Zm0 2a9 9 0 018.246 12.605L4.755 6.661A8.99 8.99 0 0112 3ZM3.754 8.393l15.491 8.944A9 9 0 013.754 8.393Z",ICON_WATCHED="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z",ICON_MUTE="M4.34 2.93L2.93 4.34 7.29 8.7 7 9H3v6h4l5 5v-6.59l4.18 4.18c-.65.49-1.38.88-2.18 1.11v2.06c1.34-.3 2.57-.92 3.61-1.75l2.05 2.05 1.41-1.41L4.34 2.93zM10 15.17L7.83 13H5v-2h2.83l.88-.88L10 11.41v3.76zM19 12c0 .82-.15 1.61-.41 2.34l1.53 1.53c.56-1.17.88-2.48.88-3.87 0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zm-7-8l-1.88 1.88L12 7.76zm4.5 8c0-1.77-1.02-3.29-2.5-4.03v1.79l2.48 2.48c.01-.08.02-.16.02-.24z";let _menuObserver=null;function trackMenuTriggers(){document.__ytcMenuTriggerAbort?.abort();const e=new AbortController;document.__ytcMenuTriggerAbort=e,document.addEventListener("click",e=>{if(!prefs.enabled)return;if(!(e.target instanceof Element))return;const t=e.target.closest(LEGACY_TRIGGER_SEL);if(t){const e=t.closest("ytd-menu-renderer");if(!e)return;const n=e.closest(CARD_SEL);if(!n&&!e.closest(WATCH_ACTIONS_SEL))return;return void armMenuInjector(n)}const n=e.target.closest(V2_TRIGGER_SEL);if(!n)return;const a=n.closest(CARD_SEL);a&&armMenuInjector(a)},{capture:!0,signal:e.signal})}function armMenuInjector(e){_menuObserver?.disconnect();const t=Date.now(),n=new MutationObserver(a=>{for(const t of a)for(const n of t.addedNodes){if(!(n instanceof Element))continue;if(n.hasAttribute?.("data-ytc-custom-item")||n.closest?.("[data-ytc-custom-item]"))continue;const t=n.closest?.(MENU_POPUP_SEL)??(n.matches?.(MENU_POPUP_SEL)?n:n.querySelector?.(MENU_POPUP_SEL));t&&injectCustomMenuItems(t,e)}Date.now()-t>3e3&&n.disconnect()});_menuObserver=n,n.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>n.disconnect(),3e3),document.querySelectorAll(MENU_POPUP_SEL).forEach(t=>injectCustomMenuItems(t,e))}function injectCustomMenuItems(e,t){const n="YT-LIST-VIEW-MODEL"===e.tagName,a=n?e:e.querySelector("tp-yt-paper-listbox#items");if(!a)return;a.querySelectorAll("[data-ytc-custom-item]").forEach(e=>e.remove());const r=t?Parsers.getCardMeta(t,{needsTitle:!1,needsDuration:!1,needsType:!1,needsProgress:!1,needsViewsAge:!1}):Parsers.getCurrentVideoChannelMeta(),o=t?r.videoId:getVideoIdFromUrl(location.href),i=n?buildMenuItemV2:buildMenuItemLegacy,d=i(a,ICON_BLOCK,Ytci18n.t("ctxBlockChannel"),async()=>{const e=await blockChannelFromMeta(r);e&&(resetProcessedCards(),schedulecleanFeed(),showToast(e.label,e.undo))});d&&a.appendChild(d);const s=i(a,ICON_MUTE,Ytci18n.t("ctxSilenceChannel"),async()=>{if(!isProCached)return void chrome.runtime.sendMessage({type:"openOptionsPage",hash:"mutedChannelsSection"});const e=await muteChannelFromMeta(r);e&&(resetProcessedCards(),schedulecleanFeed(),showToast(e.label,e.undo))});if(s&&a.appendChild(s),o){const e=i(a,ICON_WATCHED,Ytci18n.t("ctxMarkWatched"),async()=>{await markWatched(o),resetProcessedCards(),schedulecleanFeed(),showToast(Ytci18n.t("toastWatched"))});e&&a.appendChild(e)}}function buildMenuItemLegacy(e,t,n,a){const r=e.querySelector("ytd-menu-service-item-renderer")||e.querySelector("ytd-menu-navigation-item-renderer");if(!r)return null;let o=r.cloneNode(!0);o.querySelector("ytd-badge-supported-renderer")?.remove(),o=deCustomize(o),o.removeAttribute("aria-selected"),o.classList.remove("iron-selected"),o.setAttribute("data-ytc-custom-item","1");const i=o.querySelector("a.yt-simple-endpoint");if(i){for(;i.firstChild;)i.parentNode.insertBefore(i.firstChild,i);i.remove()}const d=o.querySelector("svg path");d&&d.setAttribute("d",t);const s=o.querySelector(".text-wrapper"),c=s?.querySelector(".title")??o.querySelector(".title");c&&(c.textContent=n,c.style.cssText="font-size:14px;line-height:20px;font-family:Roboto,Arial,sans-serif;");const l=s?.parentElement??o;l.style.cssText="display:flex;align-items:center;padding:0 12px 0 16px;height:36px;box-sizing:border-box;cursor:pointer;user-select:none;";const h=s?.previousElementSibling;return h&&(h.style.cssText="width:24px;height:24px;flex-shrink:0;margin-right:12px;display:flex;align-items:center;justify-content:center;"),s&&(s.style.cssText="flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"),wireMenuItemInteractivity(l,a,"8px"),o}function buildMenuItemV2(e,t,n,a){const r=e.querySelector("yt-list-item-view-model");if(!r)return null;let o=deCustomize(r.cloneNode(!0));o.setAttribute("data-ytc-custom-item","1");const i=o.querySelector(".ytButtonOrAnchorButton, .ytButtonOrAnchorAnchor, a, button");if(i){for(;i.firstChild;)i.parentNode.insertBefore(i.firstChild,i);i.remove()}const d=o.querySelector("svg path");d&&d.setAttribute("d",t);const s=o.querySelector(".ytListItemViewModelTitle");s&&(s.textContent=n);const c=o.querySelector(".ytListItemViewModelLayoutWrapper")??o;c.style.cssText="display:flex;padding:2px 16px;box-sizing:border-box;cursor:pointer;user-select:none;";const l=o.querySelector(".ytListItemViewModelMainContainer");l&&(l.style.cssText="display:flex;align-items:center;height:36px;width:100%;");const h=o.querySelector(".ytListItemViewModelImageContainer");h&&(h.style.cssText="width:24px;height:36px;flex-shrink:0;margin-right:12px;display:flex;align-items:center;justify-content:center;");const m=o.querySelector(".ytListItemViewModelTitleWrapper");return m&&(m.style.cssText="display:flex;align-items:center;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"),wireMenuItemInteractivity(c,a,"0px"),o}function nativeHoverColor(){return document.documentElement.hasAttribute("dark")?"rgba(255,255,255,.1)":"rgba(0,0,0,.05)"}function wireMenuItemInteractivity(e,t,n){e.style.borderRadius=n,e.addEventListener("mouseenter",()=>{e.style.backgroundColor=nativeHoverColor()}),e.addEventListener("mouseleave",()=>{e.style.backgroundColor=""}),e.addEventListener("click",n=>{n.preventDefault(),n.stopPropagation(),closeMenuPopup(e),t()},!0)}function deCustomize(e){const t=[...e.querySelectorAll("*")].filter(e=>e.tagName.includes("-"));for(const e of t){const t=document.createElement("div");for(const n of e.attributes)t.setAttribute(n.name,n.value);for(;e.firstChild;)t.appendChild(e.firstChild);e.replaceWith(t)}if(e.tagName.includes("-")){const t=document.createElement("div");for(const n of e.attributes)t.setAttribute(n.name,n.value);for(;e.firstChild;)t.appendChild(e.firstChild);return t}return e}function closeMenuPopup(e){const t=e.closest("tp-yt-iron-dropdown");t&&"function"==typeof t.close?t.close():document.body.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:!0}))}async function blockChannelFromMeta(e){const t=e.channelHandle||e.channelName;if(!t)return null;let n=!1;return await YtcStorage.mutate("blockedChannels",(e=[])=>e.includes(t)?(n=!0,e):[...e,t]),n?null:{label:`${Ytci18n.t("toastBlocked")}: ${e.channelName||t}`,undo:async()=>{await YtcStorage.mutate("blockedChannels",(e=[])=>e.filter(e=>e!==t))}}}const FALLBACK_MUTE_DAYS=14;async function muteChannelFromMeta(e){const t=e.channelHandle||e.channelName;if(!t)return null;const{muteDefaultDays:n=FALLBACK_MUTE_DAYS}=await YtcStorage.get(["muteDefaultDays"]);let a=!1;return await YtcStorage.mutate("mutedChannels",(e={})=>e[t]&&e[t]>Date.now()?(a=!0,e):(e[t]=Date.now()+24*n*60*60*1e3,e)),a?null:{label:`${Ytci18n.t("toastMuted")}: ${e.channelName||t}`,undo:async()=>{await YtcStorage.mutate("mutedChannels",(e={})=>(delete e[t],e))}}}let _toastTimer=null;function showToast(e,t){let n=document.getElementById("ytc-toast-host");n||(n=document.createElement("div"),n.id="ytc-toast-host",n.style.cssText="position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:99999;pointer-events:none;",document.body.appendChild(n)),n.replaceChildren();const a=document.createElement("div");a.style.cssText="display:inline-flex;align-items:center;gap:16px;background:#0f172a;color:#f1f5f9;padding:12px 18px;border-radius:10px;box-shadow:0 8px 32px rgba(0,0,0,.3);font:500 14px/1.4 'Roboto','Segoe UI',sans-serif;pointer-events:auto;animation:ytc-toast-in .2s ease-out;";const r=document.createElement("span");if(r.textContent=e,a.appendChild(r),t){const e=document.createElement("button");e.textContent=Ytci18n.t("undo"),e.style.cssText="background:none;border:none;color:#67e8f9;font:600 14px 'Roboto','Segoe UI',sans-serif;cursor:pointer;padding:4px 8px;border-radius:6px;text-transform:uppercase;letter-spacing:.5px;",e.addEventListener("mouseenter",()=>e.style.background="rgba(103,232,249,.12)"),e.addEventListener("mouseleave",()=>e.style.background="none"),e.addEventListener("click",async()=>{await t(),resetProcessedCards(),schedulecleanFeed(),n.replaceChildren()}),a.appendChild(e)}if(n.appendChild(a),!document.getElementById("ytc-toast-style")){const e=document.createElement("style");e.id="ytc-toast-style",e.textContent="@keyframes ytc-toast-in{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}",document.head.appendChild(e)}clearTimeout(_toastTimer),_toastTimer=setTimeout(()=>n.replaceChildren(),5e3)}init();
let _observerStarted=!1,isProCached=!1;const PREF_KEYS=["enabled","hideSeen","watchedMode","watchedThreshold","hideShorts","hideLive","hideUpcoming","hidePremieres","hideMembers","hideFilterBar","hideMixes","hideDiscoveryShelf","hidePlayablesShelf","hideSubscriptionsAlgo","keywords","blockedChannels","whitelistedChannels","mutedChannels","minDuration","maxDuration","minAgeDays","maxAgeDays","minViews","maxViews","dailyChannelLimit","homeFeedMode","videosPerRow","disableInfiniteScroll","disableAutoplay","hideRelated","hideEndCards","hideEndScreenFeed","hideLiveChat","hidePlaylistPanel","hideChannelInfo","hideDescription","hideMerchShelf","hideComments","hideVideoActions","hideAskButton","hideSaveButton","hideMoreActionsButton","hideExploreSidebar","hideSubscriptions","hideShortsSidebar","hideMoreFromYoutube","hideNotifications","hideVoiceSearch","blurThumbnails","hideProfilePhotos","hiddenCounts","hiddenByReason","totalHidden"],SILENT_KEYS=new Set(["channelDayCounts","hiddenCounts","hiddenByReason","totalHidden"]);async function init(){const[e,t]=await Promise.all([YtcStorage.get(PREF_KEYS),YtcDevice.isPro()]);isProCached=t,prefs={...prefs,...e},YtcDevice.gate(prefs,isProCached),prefs.enabled&&activate(),YtcDevice.validateIfStale().catch(()=>{}),chrome.storage.onChanged.addListener(e=>{let t=!1;for(const n of Object.keys(e))SILENT_KEYS.has(n)?prefs[n]=e[n].newValue:PREF_KEYS.includes(n)&&(prefs[n]=e[n].newValue,t=!0);const n=()=>{t&&YtcDevice.gate(prefs,isProCached),"enabled"in e&&prefs.enabled&&activate(),"disableAutoplay"in e&&e.disableAutoplay.newValue&&enforceAutoplayOff(),("homeFeedMode"in e||"enabled"in e)&&enforceHomeRedirect(),t?(applyUiCleanupFlags(),resetProcessedCards(),schedulecleanFeed()):"watchedVideos"in e&&(resetProcessedCards(),schedulecleanFeed())};if("device"in e)return t=!0,void YtcDevice.isPro().then(e=>{isProCached=e,n()});n()}),injectHoverStyles(),applyUiCleanupFlags(),trackMenuTriggers()}function activate(){_observerStarted?schedulecleanFeed():(_observerStarted=!0,trackCurrentVideoFallback(),enforceAutoplayOff(),startObserver(),watchNavigation())}const HOME_REDIRECT_PATHS={subscriptions:"/feed/subscriptions",watchLater:"/playlist?list=WL",library:"/feed/library"};function enforceHomeRedirect(){const e=document.documentElement;if(!prefs.enabled||"/"!==location.pathname)return void e.removeAttribute("data-ytc-home-state");const t=HOME_REDIRECT_PATHS[prefs.homeFeedMode];t?(e.setAttribute("data-ytc-home-state","show"),location.replace(`https://www.youtube.com${t}`)):e.setAttribute("data-ytc-home-state",prefs.homeFeedMode)}function enforceAutoplayOff(e=0){if(!prefs.enabled||!prefs.disableAutoplay)return;const t=document.querySelector(".ytp-autonav-toggle-button");t?"true"===t.getAttribute("aria-checked")&&t.click():e<10&&setTimeout(()=>enforceAutoplayOff(e+1),500)}function startObserver(){cleanFeed();const e=document.querySelector("ytd-app")??document.body,t=new MutationObserver(e=>{if(YtcStorage.alive()){for(const t of e)queueMutatedNodes(t.addedNodes);document.hidden||schedulecleanFeed()}else t.disconnect()});t.observe(e,{childList:!0,subtree:!0}),document.addEventListener("visibilitychange",()=>{document.hidden||schedulecleanFeed()})}function watchNavigation(){document.addEventListener("yt-navigate-finish",()=>{resetProcessedCards(),trackCurrentVideoFallback(),enforceAutoplayOff(),enforceHomeRedirect(),schedulecleanFeed()})}function resetProcessedCards(){document.querySelectorAll("[data-ytc-done], [data-ytc-counted], [data-ytc-hidden], [data-ytc-dim]").forEach(e=>{e.removeAttribute("data-ytc-done"),e.removeAttribute("data-ytc-counted"),e.removeAttribute("data-ytc-reason"),e.removeAttribute("data-ytc-hidden"),e.removeAttribute("data-ytc-dim")}),forceFullRescan()}function injectHoverStyles(){if(document.getElementById("ytc-style"))return;const e=document.createElement("style");e.id="ytc-style",e.textContent='\n ytd-rich-grid-renderer ytd-rich-grid-row,\n ytd-rich-grid-renderer ytd-rich-grid-row > #contents {\n display: contents !important;\n }\n [data-ytc-hidden] { display: none !important; }\n [data-ytc-dim] { opacity: 0.35 !important; filter: grayscale(1) !important; }\n\n /* watchedMode="dryrun": applyAction() grava data-ytc-dim="preview" em\n vez de "1" pra estilizar diferente (borda+etiqueta em vez de\n opacity/grayscale) sem precisar de outro atributo no <html>.\n box-sizing: border-box faz a borda "comer" o conteúdo interno em vez\n de desalinhar a grade. */\n [data-ytc-dim="preview"] {\n opacity: 1 !important;\n filter: none !important;\n position: relative;\n }\n [data-ytc-dim="preview"]::before {\n content: "";\n position: absolute;\n /* -12px (igual ao hover nativo) sobrepunha o card vizinho numa grade\n cheia; -7px cabe até a metade do gutter. */\n inset: -7px;\n z-index: 5;\n background: rgba(180, 83, 9, 0.35);\n border-radius: 14px;\n pointer-events: none;\n }\n [data-ytc-dim="preview"]::after {\n content: attr(data-ytc-reason);\n position: absolute;\n top: 10px;\n left: 8px;\n z-index: 10;\n background: #b45309 url("data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 24 24\' fill=\'none\' stroke=\'white\' stroke-width=\'2.75\' stroke-linecap=\'round\' stroke-linejoin=\'round\'%3E%3Cpath d=\'M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24\'/%3E%3Cline x1=\'1\' y1=\'1\' x2=\'23\' y2=\'23\'/%3E%3C/svg%3E") no-repeat 10px center;\n background-size: 14px 14px;\n color: #fff;\n font: 700 12px/16px Roboto, Arial, sans-serif;\n padding: 4px 10px 4px 30px;\n border-radius: 4px;\n pointer-events: none;\n }\n\n html[data-ytc-hide-related] ytd-watch-next-secondary-results-renderer,\n html[data-ytc-hide-related] #related.ytd-watch-flexy { display: none !important; }\n\n html[data-ytc-hide-endcards] .ytp-ce-element,\n html[data-ytc-hide-endcards] .ytp-cards-teaser { display: none !important; }\n\n /* .html5-endscreen (não só .ytp-endscreen-content) leva junto as setas\n anterior/próximo, que são irmãs do content, não filhas.\n .ytp-fullscreen-grid é a reformulação 2025 da mesma tela, estrutura\n nova e independente. */\n html[data-ytc-hide-endscreen-feed] .html5-endscreen,\n html[data-ytc-hide-endscreen-feed] .ytp-fullscreen-grid { display: none !important; }\n\n html[data-ytc-hide-live-chat] ytd-live-chat-frame#chat,\n html[data-ytc-hide-live-chat] #chat.ytd-watch-flexy,\n /* Card "Reprodução do chat" no carrossel abaixo da descrição — mesmo\n painel, atalho separado. Casa pelo path do ícone (idioma-independente);\n escopado no #teaser-carousel inteiro, não só no item, senão o título\n ficava visível com o conteúdo vazio. */\n html[data-ytc-hide-live-chat] div#teaser-carousel:has(path[d="M16 2H4a3 3 0 00-3 3v8a3 3 0 003 3h1v2.14a.8.8 0 001.188.7L11.3 16H16a3 3 0 003-3V5a3 3 0 00-3-3ZM4 4h12a1 1 0 011 1v8a1 1 0 01-1 1h-5.218l-.452.252L7 16.1V14H4a1 1 0 01-1-1V5a1 1 0 011-1Zm17 2.174A3 3 0 0123 9v8a3 3 0 01-2.846 2.996L20 20v2.14a.8.8 0 01-1.189.7L13.701 20H8.216l3.6-2h2.402l.453.252L18 20.101V18.05l1.95-.05.113-.003A1 1 0 0021 17V6.174Z"]) { display: none !important; }\n\n html[data-ytc-hide-playlist-panel] ytd-playlist-panel-renderer#playlist,\n html[data-ytc-hide-playlist-panel] #playlist.ytd-watch-flexy { display: none !important; }\n\n html[data-ytc-hide-channel-info] ytd-watch-metadata #owner,\n html[data-ytc-hide-channel-info] ytd-video-owner-renderer { display: none !important; }\n\n html[data-ytc-hide-description] ytd-watch-metadata #description,\n html[data-ytc-hide-description] #description-inline-expander.ytd-watch-metadata { display: none !important; }\n\n html[data-ytc-hide-merch] ytd-merch-shelf-renderer,\n html[data-ytc-hide-merch] ytd-ticket-shelf-renderer,\n html[data-ytc-hide-merch] ytd-product-shelf-renderer { display: none !important; }\n\n html[data-ytc-hide-notifications] ytd-notification-topbar-button-renderer { display: none !important; }\n\n html[data-ytc-hide-voice-search] #voice-search-button { display: none !important; }\n\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/premium"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/feed/storefront"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/gaming"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-entry-renderer:has(a[href="/kids"]),\n html[data-ytc-hide-more-from-youtube] ytd-mini-guide-entry-renderer:has(a[href="/premium"]),\n html[data-ytc-hide-more-from-youtube] ytd-mini-guide-entry-renderer:has(a[href="/gaming"]),\n /* Layouts novos agrupam Premium/Music/Kids numa ytd-guide-section-renderer\n titulada — casa a seção pelo href de um filho (idioma-independente)\n em vez do título. */\n html[data-ytc-hide-more-from-youtube] ytd-guide-section-renderer:has(a[href="/premium"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-section-renderer:has(a[href^="https://music.youtube.com"]),\n html[data-ytc-hide-more-from-youtube] ytd-guide-section-renderer:has(a[href^="https://www.youtubekids.com"]) { display: none !important; }\n\n /* visibility (não display) de propósito — o avatar ancora a indentação\n das respostas encadeadas; display:none desalinharia a thread. */\n html[data-ytc-hide-profile-photos] ytd-comment-view-model #author-thumbnail { visibility: hidden !important; }\n\n html[data-ytc-hide-profile-photos] ytd-video-owner-renderer #avatar,\n html[data-ytc-hide-profile-photos] ytd-channel-renderer #avatar,\n html[data-ytc-hide-profile-photos] #avatar yt-img-shadow,\n html[data-ytc-hide-profile-photos] yt-img-shadow#avatar,\n /* Resultado de busca usa #channel-thumbnail pro link+thumbnail do canal\n (#avatar deles fica vazio, só decorativo). */\n html[data-ytc-hide-profile-photos] #channel-thumbnail,\n /* Layout "lockup" (feed/sidebar novos) não tem #avatar — casa pela\n classe estável do wrapper. display:none aqui (não visibility) pro\n título ocupar o espaço liberado. */\n html[data-ytc-hide-profile-photos] .ytLockupMetadataViewModelAvatar { display: none !important; }\n\n html[data-ytc-hide-comments] ytd-comments#comments,\n html[data-ytc-hide-comments] #comments.ytd-watch-flexy { display: none !important; }\n\n html[data-ytc-hide-video-actions] segmented-like-dislike-button-view-model,\n html[data-ytc-hide-video-actions] like-button-view-model,\n html[data-ytc-hide-video-actions] dislike-button-view-model,\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-toggle-button-renderer,\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Share" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Compartilhar" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Compartir" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-button-renderer:has(button[aria-label="Share" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-button-renderer:has(button[aria-label="Compartilhar" i]),\n html[data-ytc-hide-video-actions] ytd-menu-renderer ytd-button-renderer:has(button[aria-label="Compartir" i]),\n /* Share não tem classe própria — casa pelo path do ícone. */\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(path[d="M10 3.158V7.51c-5.428.223-8.27 3.75-8.875 11.199-.04.487-.07.975-.09 1.464l-.014.395c-.014.473.578.684.88.32.302-.368.61-.73.925-1.086l.244-.273c1.79-1.967 3-2.677 4.93-2.917a18.011 18.011 0 012-.112v4.346a1 1 0 001.646.763l9.805-8.297 1.55-1.31-1.55-1.31-9.805-8.297A1 1 0 0010 3.158Zm2 6.27v.002-4.116l7.904 6.688L12 18.689v-4.212l-2.023.024c-1.935.022-3.587.17-5.197 1.024a9 9 0 00-1.348.893c.355-1.947.916-3.39 1.63-4.425 1.062-1.541 2.607-2.385 5.02-2.485L12 9.428Z"]),\n /* Super Thanks — mesmo wrapper genérico, casa pelo ícone de coração. */\n html[data-ytc-hide-video-actions] ytd-menu-renderer yt-button-view-model:has(path[d="M16.25 2A6.7 6.7 0 0012 3.509 6.75 6.75 0 001 8.75c0 4.497 2.784 7.818 5.207 9.87a23.498 23.498 0 004.839 3.143l.096.044.03.013.01.005.003.002.002.001c.273-.609.544-1.218.813-1.828 0 0-9-4-9-11.25a4.75 4.75 0 018.932-2.247A1 1 0 0011 7.5v.638c-.357.1-.689.26-.979.49A2.35 2.35 0 009.13 10.5c-.007.424.112.84.342 1.197.21.31.497.563.831.734.546.29 1.23.411 1.693.502.557.109.899.19 1.117.315.086.048.109.082.114.09.004.006.028.045.028.162 0 .024-.008.118-.165.235-.162.122-.5.27-1.09.27-.721 0-1.049-.21-1.181-.323a.6.6 0 01-.142-.168l.005.013.006.014.002.009a.996.996 0 00-1.884.64l.947-.316-.003.001c-.875.292-.939.314-.943.317l.001.003.003.006.004.015.012.032c.045.111.1.218.162.321.146.236.324.444.535.624.357.306.841.566 1.476.702v.605a1 1 0 002 0v-.614c1.29-.289 2.245-1.144 2.245-2.386 0-.44-.103-.852-.327-1.212-.22-.355-.52-.6-.82-.77-.555-.316-1.244-.445-1.719-.539-.567-.111-.915-.185-1.143-.305a.5.5 0 01-.1-.07l-.004-.003-.003-.009a.4.4 0 01-.009-.092c0-.158.053-.244.14-.314.109-.086.341-.19.74-.19.373-.001.73.144.997.404a.996.996 0 001.518-1.286l-.699.58.698-.582v-.001l-.002-.001-.002-.003-.006-.006-.016-.018a2.984 2.984 0 00-.178-.182A3.45 3.45 0 0013 8.154V7.5a1 1 0 00-.933-.997A4.75 4.75 0 0121 8.75C21 16 12 20 12 20l.813 1.827.002-.001.003-.001.01-.005.029-.013.097-.045c.081-.037.191-.09.33-.16a23.5 23.5 0 004.509-2.982C20.216 16.568 23 13.248 23 8.75A6.75 6.75 0 0016.25 2Zm-3.437 19.827L12 20l-.813 1.828.813.36.813-.361Z"]) { display: none !important; }\n\n html[data-ytc-hide-ask-button] ytd-menu-renderer .you-chat-entrypoint-button,\n html[data-ytc-hide-ask-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Ask" i]),\n html[data-ytc-hide-ask-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Perguntar" i]),\n html[data-ytc-hide-ask-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label="Preguntar" i]),\n /* Segunda entrada da mesma feature Ask/YouChat: card promocional na\n descrição, tag própria e estável. */\n html[data-ytc-hide-ask-button] yt-video-description-youchat-section-view-model { display: none !important; }\n\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label*="Save" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label*="Salvar" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(button[aria-label*="Guardar" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer ytd-button-renderer:has(button[aria-label*="Save" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer ytd-button-renderer:has(button[aria-label*="Salvar" i]),\n html[data-ytc-hide-save-button] ytd-menu-renderer ytd-button-renderer:has(button[aria-label*="Guardar" i]),\n /* Save também não tem classe própria — mesmo raciocínio do Share. */\n html[data-ytc-hide-save-button] ytd-menu-renderer yt-button-view-model:has(path[d="M19 2H5a2 2 0 00-2 2v16.887c0 1.266 1.382 2.048 2.469 1.399L12 18.366l6.531 3.919c1.087.652 2.469-.131 2.469-1.397V4a2 2 0 00-2-2ZM5 20.233V4h14v16.233l-6.485-3.89-.515-.309-.515.309L5 20.233Z"]) { display: none !important; }\n\n html[data-ytc-hide-more-actions-button] ytd-menu-renderer yt-icon-button.dropdown-trigger,\n html[data-ytc-hide-more-actions-button] ytd-menu-renderer #button.dropdown-trigger,\n /* YouTube migrou o "..." pro componente novo yt-button-shape (mesma\n família do Ask/Save/Share); id estável como filho direto do menu. */\n html[data-ytc-hide-more-actions-button] ytd-menu-renderer > yt-button-shape#button-shape { display: none !important; }\n\n /* Não mira ytd-guide-section-renderer inteiro: Home/Shorts/Subscriptions\n viram irmãos dentro da MESMA section, então isso escondia os três\n juntos (bug real, já corrigido). Só a entry + mini-guide-entry. */\n html[data-ytc-hide-subscriptions] ytd-mini-guide-entry-renderer:has(a[href="/feed/subscriptions"]),\n html[data-ytc-hide-subscriptions] ytd-guide-entry-renderer:has(a[href="/feed/subscriptions"]) { display: none !important; }\n html[data-ytc-hide-subscriptions] ytd-guide-section-renderer:has(ytd-guide-collapsible-section-entry-renderer a[href="/feed/subscriptions"]) { display: none !important; }\n\n html[data-ytc-hide-explore] ytd-guide-entry-renderer a[href="/feed/trending"],\n html[data-ytc-hide-explore] ytd-guide-entry-renderer a[href="/feed/explore"],\n html[data-ytc-hide-explore] ytd-mini-guide-entry-renderer:has(a[href="/feed/trending"]),\n html[data-ytc-hide-explore] ytd-mini-guide-entry-renderer:has(a[href="/feed/explore"]) { display: none !important; }\n html[data-ytc-hide-explore] ytd-guide-entry-renderer:has(a[href="/feed/trending"]),\n html[data-ytc-hide-explore] ytd-guide-entry-renderer:has(a[href="/feed/explore"]) { display: none !important; }\n /* Layouts novos agrupam Explore numa section titulada sem href estável\n nos filhos, exceto "Filmes" (sempre /feed/storefront) — casa a\n section pai por esse único filho confiável. */\n html[data-ytc-hide-explore] ytd-guide-section-renderer:has(a[href^="/feed/storefront"]) { display: none !important; }\n\n /* Shelf "YouTube Playables" (mini-games) misturado no feed. */\n html[data-ytc-hide-playables-shelf] ytd-rich-section-renderer:has(ytd-mini-game-card-view-model) { display: none !important; }\n\n html[data-ytc-hide-mixes] ytd-radio-renderer { display: none !important; }\n\n /* "Descubra mais temas" e o shelf promocional "YouTube featured" —\n ambos dentro de um ytd-rich-section-renderer, identificados pela tag\n do componente interno (idioma-independente). Vídeos individuais do\n shelf de marca continuam filtrados por Rules.evaluate() normalmente;\n isto só esconde a moldura/cabeçalho do shelf. */\n html[data-ytc-hide-discovery-shelf] ytd-rich-section-renderer:has(ytd-chips-shelf-with-video-shelf-renderer),\n html[data-ytc-hide-discovery-shelf] ytd-rich-section-renderer:has(ytd-brand-video-shelf-renderer) { display: none !important; }\n\n /* Shelves algorítmicas que o YouTube injeta em /feed/subscriptions: o\n feed cronológico normal dessa página nunca agrupa vídeos numa shelf\n titulada, então qualquer ytd-rich-shelf-renderer ali já é a inserção\n algorítmica. Escopado por page-subtype pra não pegar shelves da Home. */\n html[data-ytc-hide-subscriptions-algo] ytd-browse[page-subtype="subscriptions"] ytd-rich-section-renderer:has(ytd-rich-shelf-renderer) { display: none !important; }\n \n html[data-ytc-hide-filter-bar] ytd-rich-grid-renderer > #header {\n display: none !important;\n }\n html[data-ytc-hide-filter-bar] #frosted-glass.with-chipbar {\n height: 68px !important;\n }\n\n /* ytd-rich-section-renderer é o mesmo wrapper genérico do shelf\n "discovery" — só conta como Shorts se tiver um card de Shorts real\n dentro (:has()). */\n html[data-ytc-hide-shorts] ytd-rich-shelf-renderer[is-shorts],\n html[data-ytc-hide-shorts] ytd-reel-shelf-renderer,\n html[data-ytc-hide-shorts] grid-shelf-view-model,\n html[data-ytc-hide-shorts] ytd-rich-section-renderer:has(\n ytd-reel-item-renderer,\n ytm-shorts-lockup-view-model,\n ytd-rich-shelf-renderer[is-shorts],\n ytd-reel-shelf-renderer,\n grid-shelf-view-model\n ) { display: none !important; }\n\n /* Ícone do raio (Shorts) é o mesmo em qualquer idioma; href="/shorts/"\n reforça o caso da sidebar recolhida. */\n html[data-ytc-hide-shorts-sidebar] ytd-mini-guide-entry-renderer:has(a[href="/shorts/"]),\n html[data-ytc-hide-shorts-sidebar] ytd-mini-guide-entry-renderer:has(path[d="m13.467 1.19-8 4.7a5 5 0 00-.255 8.46 5 5 0 005.32 8.462l8-4.7a5 5 0 00.258-8.462 5 5 0 001.641-6.464l-.12-.217a5 5 0 00-6.844-1.78m5.12 2.79a2.999 2.999 0 01-1.067 4.107l-1.327.78a1 1 0 00.096 1.775l.943.423a3 3 0 01.288 5.323l-8 4.7a3 3 0 01-3.039-5.173l1.327-.78a1 1 0 00-.097-1.775l-.942-.423a3 3 0 01-.288-5.323l8-4.7a3 3 0 014.106 1.066ZM15 12l-5-3v6l5-3Z"]),\n html[data-ytc-hide-shorts-sidebar] ytd-guide-entry-renderer:has(path[d="m13.467 1.19-8 4.7a5 5 0 00-.255 8.46 5 5 0 005.32 8.462l8-4.7a5 5 0 00.258-8.462 5 5 0 001.641-6.464l-.12-.217a5 5 0 00-6.844-1.78m5.12 2.79a2.999 2.999 0 01-1.067 4.107l-1.327.78a1 1 0 00.096 1.775l.943.423a3 3 0 01.288 5.323l-8 4.7a3 3 0 01-3.039-5.173l1.327-.78a1 1 0 00-.097-1.775l-.942-.423a3 3 0 01-.288-5.323l8-4.7a3 3 0 014.106 1.066ZM15 12l-5-3v6l5-3Z"]) { display: none !important; }\n\n html[data-ytc-blur-thumbs] ytd-thumbnail img,\n html[data-ytc-blur-thumbs] yt-image img,\n html[data-ytc-blur-thumbs] yt-thumbnail-view-model img {\n filter: blur(14px) saturate(0.85) !important;\n transition: filter .2s ease;\n }\n /* --ytd-rich-grid-items-per-row é a custom property que o próprio\n YouTube já usa pra decidir a grade responsiva do feed — sobrescrever\n ela em vez de reimplementar grid/flex na mão evita brigar com o\n layout nativo. Escopo igual ao hide-subscriptions-algo acima:\n page-subtype casa Home e Subscriptions, os dois lugares onde essa\n grade aparece. */\n html[data-ytc-videos-per-row] ytd-browse[page-subtype="home"] ytd-rich-item-renderer[rendered-from-rich-grid]:not([is-shorts-grid]),\n html[data-ytc-videos-per-row] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer[rendered-from-rich-grid]:not([is-shorts-grid]) {\n --ytd-rich-grid-items-per-row: var(--ytc-videos-per-row) !important;\n }\n\n /* videosPerRow=1: com só 1 card por linha, uma thumbnail 16:9 em cima do\n título (layout vertical padrão) desperdiça a largura toda disponível\n ao lado — vira lista horizontal (thumbnail à esquerda, texto ocupando\n o resto), mesma ideia do "list view" do youtube-enhancer\n (temp/youtube-enhancer/css/youtube.css). .ytLockupViewModelVertical é\n o wrapper do card no layout "lockup" novo (Home/Subscriptions atuais);\n card antigo (ytd-rich-grid-media, layouts A/B mais raros) não tem esse\n wrapper e continua vertical — sem fallback aqui de propósito, mesmo\n espírito de simplicidade do resto desta feature. */\n html[data-ytc-list-view] ytd-browse[page-subtype="home"] ytd-rich-item-renderer .ytLockupViewModelVertical,\n html[data-ytc-list-view] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer .ytLockupViewModelVertical {\n flex-direction: row !important;\n }\n html[data-ytc-list-view] ytd-browse[page-subtype="home"] ytd-rich-item-renderer .ytLockupViewModelContentImage,\n html[data-ytc-list-view] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer .ytLockupViewModelContentImage {\n flex: 0 0 220px !important;\n width: 220px !important;\n margin-inline-end: 16px !important;\n }\n html[data-ytc-list-view] ytd-browse[page-subtype="home"] ytd-rich-item-renderer .ytLockupMetadataViewModelHost,\n html[data-ytc-list-view] ytd-browse[page-subtype="subscriptions"] ytd-rich-item-renderer .ytLockupMetadataViewModelHost {\n flex: 1 1 auto !important;\n min-width: 0 !important;\n }\n\n /* ytd-continuation-item-renderer é o placeholder que o próprio YouTube\n observa (IntersectionObserver interno) pra saber quando buscar mais\n uma leva de vídeos — escondê-lo faz o carregamento parar depois da\n primeira leva, sem mexer em scroll/wheel nem em rede. Mesma técnica\n do untrap-for-youtube (shared/options/options.json:1591-1593 em\n temp/untrap-for-youtube), aplicada no mesmo escopo Home+Subscriptions\n de videosPerRow acima. */\n html[data-ytc-disable-infinite-scroll] ytd-browse[page-subtype="home"] ytd-rich-grid-renderer > #contents > ytd-continuation-item-renderer,\n html[data-ytc-disable-infinite-scroll] ytd-browse[page-subtype="subscriptions"] ytd-rich-grid-renderer > #contents > ytd-continuation-item-renderer {\n display: none !important;\n }\n\n html[data-ytc-blur-thumbs] ytd-rich-item-renderer:hover img,\n html[data-ytc-blur-thumbs] ytd-video-renderer:hover img,\n html[data-ytc-blur-thumbs] ytd-compact-video-renderer:hover img,\n html[data-ytc-blur-thumbs] yt-lockup-view-model:hover img,\n html[data-ytc-blur-thumbs] ytm-shorts-lockup-view-model:hover img {\n filter: none !important;\n }\n ',document.head.appendChild(e)}function applyUiCleanupFlags(){const e=document.documentElement,t=prefs.enabled,n={"data-ytc-hide-related":t&&prefs.hideRelated,"data-ytc-hide-endcards":t&&prefs.hideEndCards,"data-ytc-hide-endscreen-feed":t&&prefs.hideEndScreenFeed,"data-ytc-hide-live-chat":t&&prefs.hideLiveChat,"data-ytc-hide-playlist-panel":t&&prefs.hidePlaylistPanel,"data-ytc-hide-channel-info":t&&prefs.hideChannelInfo,"data-ytc-hide-description":t&&prefs.hideDescription,"data-ytc-hide-merch":t&&prefs.hideMerchShelf,"data-ytc-hide-comments":t&&prefs.hideComments,"data-ytc-hide-video-actions":t&&prefs.hideVideoActions,"data-ytc-hide-ask-button":t&&prefs.hideAskButton,"data-ytc-hide-save-button":t&&prefs.hideSaveButton,"data-ytc-hide-more-actions-button":t&&prefs.hideMoreActionsButton,"data-ytc-hide-explore":t&&prefs.hideExploreSidebar,"data-ytc-hide-subscriptions":t&&prefs.hideSubscriptions,"data-ytc-hide-shorts-sidebar":t&&prefs.hideShortsSidebar,"data-ytc-hide-more-from-youtube":t&&prefs.hideMoreFromYoutube,"data-ytc-hide-playables-shelf":t&&prefs.hidePlayablesShelf,"data-ytc-hide-mixes":t&&prefs.hideMixes,"data-ytc-hide-discovery-shelf":t&&prefs.hideDiscoveryShelf,"data-ytc-hide-subscriptions-algo":t&&prefs.hideSubscriptionsAlgo,"data-ytc-hide-filter-bar":t&&prefs.hideFilterBar,"data-ytc-hide-shorts":t&&prefs.hideShorts,"data-ytc-hide-notifications":t&&prefs.hideNotifications,"data-ytc-hide-voice-search":t&&prefs.hideVoiceSearch,"data-ytc-blur-thumbs":t&&prefs.blurThumbnails,"data-ytc-hide-profile-photos":t&&prefs.hideProfilePhotos,"data-ytc-disable-infinite-scroll":t&&prefs.disableInfiniteScroll};for(const[t,a]of Object.entries(n))a?e.setAttribute(t,"1"):e.removeAttribute(t);t&&prefs.videosPerRow?(e.setAttribute("data-ytc-videos-per-row","1"),e.style.setProperty("--ytc-videos-per-row",prefs.videosPerRow)):(e.removeAttribute("data-ytc-videos-per-row"),e.style.removeProperty("--ytc-videos-per-row")),t&&"1"===prefs.videosPerRow?e.setAttribute("data-ytc-list-view","1"):e.removeAttribute("data-ytc-list-view")}const CARD_SEL="ytd-rich-item-renderer, ytd-video-renderer, ytd-compact-video-renderer, ytd-grid-video-renderer, ytd-reel-item-renderer, ytd-rich-grid-media, yt-lockup-view-model, ytm-shorts-lockup-view-model, ytd-playlist-panel-video-renderer",WATCH_ACTIONS_SEL="ytd-watch-metadata #actions ytd-menu-renderer",LEGACY_TRIGGER_SEL="yt-button-shape#button-shape, yt-icon-button.dropdown-trigger",V2_TRIGGER_SEL=".ytLockupMetadataViewModelMenuButton button",MENU_POPUP_SEL="ytd-menu-popup-renderer, yt-list-view-model",MENU_ARM_MS=3e3,ICON_BLOCK="M12 1C5.925 1 1 5.925 1 12s4.925 11 11 11 11-4.925 11-11S18.075 1 12 1Zm0 2a9 9 0 018.246 12.605L4.755 6.661A8.99 8.99 0 0112 3ZM3.754 8.393l15.491 8.944A9 9 0 013.754 8.393Z",ICON_WATCHED="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z",ICON_MUTE="M4.34 2.93L2.93 4.34 7.29 8.7 7 9H3v6h4l5 5v-6.59l4.18 4.18c-.65.49-1.38.88-2.18 1.11v2.06c1.34-.3 2.57-.92 3.61-1.75l2.05 2.05 1.41-1.41L4.34 2.93zM10 15.17L7.83 13H5v-2h2.83l.88-.88L10 11.41v3.76zM19 12c0 .82-.15 1.61-.41 2.34l1.53 1.53c.56-1.17.88-2.48.88-3.87 0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zm-7-8l-1.88 1.88L12 7.76zm4.5 8c0-1.77-1.02-3.29-2.5-4.03v1.79l2.48 2.48c.01-.08.02-.16.02-.24z";let _menuObserver=null;function trackMenuTriggers(){document.__ytcMenuTriggerAbort?.abort();const e=new AbortController;document.__ytcMenuTriggerAbort=e,document.addEventListener("click",e=>{if(!prefs.enabled)return;if(!(e.target instanceof Element))return;const t=e.target.closest(LEGACY_TRIGGER_SEL);if(t){const e=t.closest("ytd-menu-renderer");if(!e)return;const n=e.closest(CARD_SEL);if(!n&&!e.closest(WATCH_ACTIONS_SEL))return;return void armMenuInjector(n)}const n=e.target.closest(V2_TRIGGER_SEL);if(!n)return;const a=n.closest(CARD_SEL);a&&armMenuInjector(a)},{capture:!0,signal:e.signal})}function armMenuInjector(e){_menuObserver?.disconnect();const t=Date.now(),n=new MutationObserver(a=>{for(const t of a)for(const n of t.addedNodes){if(!(n instanceof Element))continue;if(n.hasAttribute?.("data-ytc-custom-item")||n.closest?.("[data-ytc-custom-item]"))continue;const t=n.closest?.(MENU_POPUP_SEL)??(n.matches?.(MENU_POPUP_SEL)?n:n.querySelector?.(MENU_POPUP_SEL));t&&injectCustomMenuItems(t,e)}Date.now()-t>3e3&&n.disconnect()});_menuObserver=n,n.observe(document.body,{childList:!0,subtree:!0}),setTimeout(()=>n.disconnect(),3e3),document.querySelectorAll(MENU_POPUP_SEL).forEach(t=>injectCustomMenuItems(t,e))}function injectCustomMenuItems(e,t){const n="YT-LIST-VIEW-MODEL"===e.tagName,a=n?e:e.querySelector("tp-yt-paper-listbox#items");if(!a)return;a.querySelectorAll("[data-ytc-custom-item]").forEach(e=>e.remove());const r=t?Parsers.getCardMeta(t,{needsTitle:!1,needsDuration:!1,needsType:!1,needsProgress:!1,needsViewsAge:!1}):Parsers.getCurrentVideoChannelMeta(),o=t?r.videoId:getVideoIdFromUrl(location.href),i=n?buildMenuItemV2:buildMenuItemLegacy,d=i(a,ICON_BLOCK,Ytci18n.t("ctxBlockChannel"),async()=>{const e=await blockChannelFromMeta(r);e&&(resetProcessedCards(),schedulecleanFeed(),showToast(e.label,e.undo))});d&&a.appendChild(d);const s=i(a,ICON_MUTE,Ytci18n.t("ctxSilenceChannel"),async()=>{if(!await YtcDevice.isPro())return void chrome.runtime.sendMessage({type:"openOptionsPage",hash:"mutedChannelsSection"});const e=await muteChannelFromMeta(r);e&&(resetProcessedCards(),schedulecleanFeed(),showToast(e.label,e.undo))});if(s&&a.appendChild(s),o){const e=i(a,ICON_WATCHED,Ytci18n.t("ctxMarkWatched"),async()=>{await markWatched(o),resetProcessedCards(),schedulecleanFeed(),showToast(Ytci18n.t("toastWatched"))});e&&a.appendChild(e)}}function buildMenuItemLegacy(e,t,n,a){const r=e.querySelector("ytd-menu-service-item-renderer")||e.querySelector("ytd-menu-navigation-item-renderer");if(!r)return null;let o=r.cloneNode(!0);o.querySelector("ytd-badge-supported-renderer")?.remove(),o=deCustomize(o),o.removeAttribute("aria-selected"),o.classList.remove("iron-selected"),o.setAttribute("data-ytc-custom-item","1");const i=o.querySelector("a.yt-simple-endpoint");if(i){for(;i.firstChild;)i.parentNode.insertBefore(i.firstChild,i);i.remove()}const d=o.querySelector("svg path");d&&d.setAttribute("d",t);const s=o.querySelector(".text-wrapper"),c=s?.querySelector(".title")??o.querySelector(".title");c&&(c.textContent=n,c.style.cssText="font-size:14px;line-height:20px;font-family:Roboto,Arial,sans-serif;");const l=s?.parentElement??o;l.style.cssText="display:flex;align-items:center;padding:0 12px 0 16px;height:36px;box-sizing:border-box;cursor:pointer;user-select:none;";const h=s?.previousElementSibling;return h&&(h.style.cssText="width:24px;height:24px;flex-shrink:0;margin-right:12px;display:flex;align-items:center;justify-content:center;"),s&&(s.style.cssText="flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"),wireMenuItemInteractivity(l,a,"8px"),o}function buildMenuItemV2(e,t,n,a){const r=e.querySelector("yt-list-item-view-model");if(!r)return null;let o=deCustomize(r.cloneNode(!0));o.setAttribute("data-ytc-custom-item","1");const i=o.querySelector(".ytButtonOrAnchorButton, .ytButtonOrAnchorAnchor, a, button");if(i){for(;i.firstChild;)i.parentNode.insertBefore(i.firstChild,i);i.remove()}const d=o.querySelector("svg path");d&&d.setAttribute("d",t);const s=o.querySelector(".ytListItemViewModelTitle");s&&(s.textContent=n);const c=o.querySelector(".ytListItemViewModelLayoutWrapper")??o;c.style.cssText="display:flex;padding:2px 16px;box-sizing:border-box;cursor:pointer;user-select:none;";const l=o.querySelector(".ytListItemViewModelMainContainer");l&&(l.style.cssText="display:flex;align-items:center;height:36px;width:100%;");const h=o.querySelector(".ytListItemViewModelImageContainer");h&&(h.style.cssText="width:24px;height:36px;flex-shrink:0;margin-right:12px;display:flex;align-items:center;justify-content:center;");const m=o.querySelector(".ytListItemViewModelTitleWrapper");return m&&(m.style.cssText="display:flex;align-items:center;flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"),wireMenuItemInteractivity(c,a,"0px"),o}function nativeHoverColor(){return document.documentElement.hasAttribute("dark")?"rgba(255,255,255,.1)":"rgba(0,0,0,.05)"}function wireMenuItemInteractivity(e,t,n){e.style.borderRadius=n,e.addEventListener("mouseenter",()=>{e.style.backgroundColor=nativeHoverColor()}),e.addEventListener("mouseleave",()=>{e.style.backgroundColor=""}),e.addEventListener("click",n=>{n.preventDefault(),n.stopPropagation(),closeMenuPopup(e),t()},!0)}function deCustomize(e){const t=[...e.querySelectorAll("*")].filter(e=>e.tagName.includes("-"));for(const e of t){const t=document.createElement("div");for(const n of e.attributes)t.setAttribute(n.name,n.value);for(;e.firstChild;)t.appendChild(e.firstChild);e.replaceWith(t)}if(e.tagName.includes("-")){const t=document.createElement("div");for(const n of e.attributes)t.setAttribute(n.name,n.value);for(;e.firstChild;)t.appendChild(e.firstChild);return t}return e}function closeMenuPopup(e){const t=e.closest("tp-yt-iron-dropdown");t&&"function"==typeof t.close?t.close():document.body.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:!0}))}async function blockChannelFromMeta(e){const t=e.channelHandle||e.channelName;if(!t)return null;let n=!1;return await YtcStorage.mutate("blockedChannels",(e=[])=>e.includes(t)?(n=!0,e):[...e,t]),n?null:{label:`${Ytci18n.t("toastBlocked")}: ${e.channelName||t}`,undo:async()=>{await YtcStorage.mutate("blockedChannels",(e=[])=>e.filter(e=>e!==t))}}}const FALLBACK_MUTE_DAYS=14;async function muteChannelFromMeta(e){const t=e.channelHandle||e.channelName;if(!t)return null;const{muteDefaultDays:n=FALLBACK_MUTE_DAYS}=await YtcStorage.get(["muteDefaultDays"]);let a=!1;return await YtcStorage.mutate("mutedChannels",(e={})=>e[t]&&e[t]>Date.now()?(a=!0,e):(e[t]=Date.now()+24*n*60*60*1e3,e)),a?null:{label:`${Ytci18n.t("toastMuted")}: ${e.channelName||t}`,undo:async()=>{await YtcStorage.mutate("mutedChannels",(e={})=>(delete e[t],e))}}}let _toastTimer=null;function showToast(e,t){let n=document.getElementById("ytc-toast-host");n||(n=document.createElement("div"),n.id="ytc-toast-host",n.style.cssText="position:fixed;bottom:24px;left:50%;transform:translateX(-50%);z-index:99999;pointer-events:none;",document.body.appendChild(n)),n.replaceChildren();const a=document.createElement("div");a.style.cssText="display:inline-flex;align-items:center;gap:16px;background:#0f172a;color:#f1f5f9;padding:12px 18px;border-radius:10px;box-shadow:0 8px 32px rgba(0,0,0,.3);font:500 14px/1.4 'Roboto','Segoe UI',sans-serif;pointer-events:auto;animation:ytc-toast-in .2s ease-out;";const r=document.createElement("span");if(r.textContent=e,a.appendChild(r),t){const e=document.createElement("button");e.textContent=Ytci18n.t("undo"),e.style.cssText="background:none;border:none;color:#67e8f9;font:600 14px 'Roboto','Segoe UI',sans-serif;cursor:pointer;padding:4px 8px;border-radius:6px;text-transform:uppercase;letter-spacing:.5px;",e.addEventListener("mouseenter",()=>e.style.background="rgba(103,232,249,.12)"),e.addEventListener("mouseleave",()=>e.style.background="none"),e.addEventListener("click",async()=>{await t(),resetProcessedCards(),schedulecleanFeed(),n.replaceChildren()}),a.appendChild(e)}if(n.appendChild(a),!document.getElementById("ytc-toast-style")){const e=document.createElement("style");e.id="ytc-toast-style",e.textContent="@keyframes ytc-toast-in{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}",document.head.appendChild(e)}clearTimeout(_toastTimer),_toastTimer=setTimeout(()=>n.replaceChildren(),5e3)}init();

@@ -6,3 +6,3 @@ {

"short_name": "__MSG_appShortName__",
"version": "1.7.0",
"version": "1.8.2",
"author": "Vidsieve",

@@ -26,3 +26,3 @@ "homepage_url": "https://vidsieve.com",

"shared/storage.js",
"shared/license.js",
"shared/device.js",
"shared/profiles.js",

@@ -68,3 +68,3 @@ "shared/scheduler.js",

"shared/storage.js",
"shared/license.js",
"shared/device.js",
"shared/history.js",

@@ -71,0 +71,0 @@ "shared/parsers.js",

@@ -1,1 +0,1 @@

<!doctype html><html><head><meta charset="UTF-8"><title data-i18n="pageTitle">YouTube Cleanup - Settings</title><link rel="icon" href="../icons/icon48.png" type="image/png"><script src="../shared/theme-init.js"></script><link rel="stylesheet" href="../shared/tokens.css"><link rel="stylesheet" href="options.css"></head><body><div class="page-header"><div class="page-header-brand"><img class="logo" src="../icons/icon.svg" width="28" height="28" alt=""> <span class="page-title" data-i18n="appShortName">Vidsieve</span></div><div class="page-header-actions"><a class="btn header-theme-btn" id="headerCoffeeLink" href="https://www.creem.io/payment/prod_96aLhruFN5CFXbaKQrmn5" target="_blank" rel="noopener noreferrer" hidden data-i18n-title="proCoffee" data-i18n-aria-label="proCoffeeAriaLabel" title="Enjoying the extension? Buy me a coffee ☕" aria-label="Enjoying the extension? Buy me a coffee"><svg class="section-header-btn-icon" viewBox="0 0 24 24" aria-hidden="true"><use href="../shared/icons.svg#ic-coffee"/></svg> </a><button type="button" class="btn header-theme-btn" id="themeBtn" data-i18n-title="cycleTheme" data-i18n-aria-label="cycleTheme" title="Cycle theme" aria-label="Cycle theme"><svg class="header-theme-btn-icon theme-icon" data-theme-icon="auto" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 18V4a8 8 0 0 1 0 16Z"/></svg> <svg class="header-theme-btn-icon theme-icon" data-theme-icon="light" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4" fill="currentColor"/><path stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg> <svg class="header-theme-btn-icon theme-icon" data-theme-icon="dark" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79Z"/></svg></button></div></div><div class="search-bar"><svg class="search-bar-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" stroke-width="2"/><path d="M21 21l-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg> <input id="filterSearchInput" class="search-bar-input" autocomplete="off" data-i18n-placeholder="filterSearchPlaceholder" placeholder="Search filters…"> <kbd class="search-bar-shortcut" id="filterSearchShortcut">Ctrl + K</kbd> <button type="button" class="search-bar-clear" id="filterSearchClear" hidden data-i18n-aria-label="filterSearchClear" aria-label="Clear search">×</button> <button type="button" class="search-bar-active-toggle" id="filterActiveOnlyBtn" aria-pressed="false" data-i18n="filterActiveOnlyBtn" data-i18n-title="filterActiveOnlyBtnTitle" title="Show only active filters">Active only</button></div><p class="search-bar-empty" id="filterSearchEmpty" hidden data-i18n="filterSearchEmpty">No filters match your search.</p><section class="topic" id="profilesSection"><div class="section-header-row"><p class="section-label" data-i18n="secProfiles">Profiles</p><button type="button" class="section-header-btn" id="scheduleOverviewOpenBtn"><svg class="section-header-btn-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M17 12h-5v5h5v-5ZM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2Zm3 18H5V8h14v11Z"/></svg> <span data-i18n="scheduleOverviewBtn">Schedule overview</span></button></div><p class="surface-hint" data-i18n="secProfilesHint">Switch your whole set of filters at once. Free includes 3 ready-made profiles. Pro adds renaming, editing, saving your own, and auto-switching by schedule.</p><div class="branches"><div class="branch"><div class="profiles-grid" id="profilesCard"></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secFeed">Feed &amp; grid</p><p class="surface-hint" data-i18n="secFeedHint">Everything that decides whether a card shows up on Home, Subscriptions or a channel page</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="homeFeedMode">Home feed</span></div><div class="row-desc" data-i18n="homeFeedModeDesc">Controls what happens to the YouTube home page</div></div><select id="homeFeedMode"><option value="show" data-i18n="homeFeedModeShow">Default</option><option value="blank" data-i18n="homeFeedModeBlank">Blank</option><option value="subscriptions" data-i18n="homeFeedModeSubscriptions">Redirect to Subscriptions</option><option value="watchLater" data-i18n="homeFeedModeWatchLater">Redirect to Watch Later</option><option value="library" data-i18n="homeFeedModeLibrary">Redirect to Library</option></select></div><div class="card-row"><div><div class="row-label"><span data-i18n="videosPerRow">Videos per row</span></div><div class="row-desc" data-i18n="videosPerRowDesc">How many video cards fit side by side in the grid</div></div><select id="videosPerRow"><option value="1">1</option><option value="2">2</option><option value="3" data-i18n="videosPerRowDefault">Default</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideShorts">Hide Shorts</span></div><div class="row-desc" data-i18n="hideShortsDesc">Short videos and Shorts shelves</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideShorts" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideShorts"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMixes">Hide Mixes</span></div><div class="row-desc" data-i18n="hideMixesDesc">Playlists generated by YouTube</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMixes" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMixes"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideLive">Hide Lives</span></div><div class="row-desc" data-i18n="hideLiveDesc">Hides streams that are currently live</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideLive" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideLive"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideUpcoming">Hide Upcoming</span></div><div class="row-desc" data-i18n="hideUpcomingDesc">Hides scheduled live streams and premieres</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideUpcoming" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideUpcoming"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hidePremieres">Hide Premieres</span></div><div class="row-desc" data-i18n="hidePremieresDesc">Hides videos marked as premiere</div></div><div class="row-actions"><button class="fav-btn" data-fav="hidePremieres" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hidePremieres"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMembers">Hide Members-only</span></div><div class="row-desc" data-i18n="hideMembersDesc">Hides videos exclusive to paying channel members</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMembers" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMembers"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideFilterBar">Hide topic filter bar</span></div><div class="row-desc" data-i18n="hideFilterBarDesc">Removes the row of topic pills (All, Music, Gaming...) above the feed</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideFilterBar" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideFilterBar"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hidePlayablesShelf">Hide Playables</span></div><div class="row-desc" data-i18n="hidePlayablesShelfDesc">The "YouTube Playables" mini-games shelf mixed into the feed</div></div><div class="row-actions"><button class="fav-btn" data-fav="hidePlayablesShelf" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hidePlayablesShelf"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="blurThumbnails">Blur thumbnails</span></div><div class="row-desc" data-i18n="blurThumbnailsDesc">Blurs video thumbnails until you hover.</div></div><div class="row-actions"><button class="fav-btn" data-fav="blurThumbnails" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="blurThumbnails"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideProfilePhotos">Hide profile photos</span></div><div class="row-desc" data-i18n="hideProfilePhotosDesc">Hides channel avatars in comments, the feed and the sidebar</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideProfilePhotos" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideProfilePhotos"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="disableInfiniteScroll">Disable infinite scroll</span></div><div class="row-desc" data-i18n="disableInfiniteScrollDesc">Stops loading more videos after the first batch on Home and Subscriptions</div></div><div class="row-actions"><button class="fav-btn" data-fav="disableInfiniteScroll" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="disableInfiniteScroll"><span class="track"></span></label></div></div></div></div><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideSeen">Hide watched</span></div><div class="row-desc" data-i18n="hideSeenDesc">Expires after 90 days</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSeen" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSeen"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="watchedThreshold">Threshold to mark as watched</span></div><div class="row-desc"><span id="thresholdValue">50</span><span data-i18n="watchedThresholdDesc">% of video watched</span></div></div><input type="range" id="watchedThreshold" min="0" max="100" step="5"></div><div class="card-row"><div><div class="row-label"><span data-i18n="filterMode">Filter mode</span></div><div class="row-desc" data-i18n="filterModeDesc">Controls how every filter behaves: Hide removes the video, Dim grays it out, Preview shows why without hiding it</div></div><select id="watchedMode"><option value="hide" data-i18n="modeHide">Hide</option><option value="dim" data-i18n="modeDim">Dim</option><option value="dryrun" id="modeDryRunOption" data-i18n="modeDryRun">Preview</option></select></div></div></div><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="minAge">Minimum age (days)</span></div><div class="row-desc" data-i18n="minAgeDesc">Hides videos newer than this (0 = no limit)</div></div><input type="number" id="minAgeDays" min="0" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="maxAge">Maximum age (days)</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="maxAgeDays" min="0" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="minDuration">Minimum duration (minutes)</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="minDurationDesc">Hides videos shorter than this (0 = no limit)</div></div><input type="number" id="minDuration" min="0" step="0.5" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="maxDuration">Maximum duration (minutes)</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="maxDuration" min="0" step="0.5" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="minViews">Minimum views</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="minViews" min="0" style="width:120px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="maxViews">Maximum views</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="maxViews" min="0" style="width:120px"></div></div></div><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideDiscoveryShelf">Hide Topic Discovery</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="hideDiscoveryShelfDesc">The "Discover more topics" shelf with topic chips</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideDiscoveryShelf" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideDiscoveryShelf"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideSubscriptionsAlgo">Hide algorithmic shelves in Subscriptions</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="hideSubscriptionsAlgoDesc">Removes "Most relevant"/"For you" shelves from the Subscriptions feed. Only your chronological subscriptions remain</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSubscriptionsAlgo" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSubscriptionsAlgo"><span class="track"></span></label></div></div></div></div><div class="branch"><div class="card"><div class="card-row column"><div class="row-label"><span data-i18n="keywordsLabel">Blocked words / regex</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="keywordsDesc">One per line. Plain text works, or use <code>/regex/i</code> for advanced patterns.</div><textarea id="keywords" rows="4" data-i18n-placeholder="keywordsPlaceholder" placeholder="you won't believe&#10;gone wrong&#10;/reacts? to/i"></textarea></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secChannels">Channels</p><p class="surface-hint" data-i18n="secChannelsHint">Rules applied per channel, regardless of where the video shows up</p><div class="branches"><div class="branch"><div class="card"><div class="card-row column"><div class="row-label"><span data-i18n="blockedChannels">Blocked channels</span></div><div class="row-desc" data-i18n="blockedChannelsDesc">Type a @handle and press Enter. Also use the "..." menu on any video card.</div><div class="tag-input" id="blockedChannelsTags"><div class="tag-list"></div><input class="tag-input-field" data-i18n-placeholder="channelHandlePlaceholder" placeholder="@SomeChannel"></div></div><div class="card-row column" id="mutedChannelsSection"><div class="row-label"><span data-i18n="mutedChannelsLabel">Muted channels</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="mutedChannelsDesc">Hides a channel for a set number of days, then unblocks it automatically. Also available from YouTube's "..." menu.</div><div class="mute-panel" id="mutedChannelsTags"><div class="mute-table" id="mutedChannelsTable"><div class="mute-head" id="mutedChannelsHead" hidden><span class="mute-col-channel" data-i18n="mutedChannelsColChannel">Channel</span> <span class="mute-col-expires" data-i18n="mutedChannelsColExpires">Expires</span> <button type="button" class="mute-unmute" id="mutedChannelsUnmuteAllBtn" data-i18n-aria-label="mutedChannelsUnmuteAll" data-i18n-title="mutedChannelsUnmuteAll" aria-label="Unmute all" title="Unmute all">×</button></div><div class="mute-rows-scroll" id="mutedChannelsRowsScroll"><div class="mute-list" id="mutedChannelsList"></div></div></div><div class="mute-add"><input class="mute-add-input" id="mutedChannelsInput" data-i18n-placeholder="channelHandlePlaceholder" placeholder="@SomeChannel"><div class="duration-row"><button type="button" class="duration-chip" data-days="7">7d</button> <button type="button" class="duration-chip is-on" data-days="14">14d</button> <button type="button" class="duration-chip" data-days="30">30d</button></div></div></div></div><div class="card-row column"><div class="row-label"><span data-i18n="whitelist">Whitelist (always pass)</span></div><div class="row-desc" data-i18n="whitelistDesc">Channels that ignore all filter rules</div><div class="tag-input" id="whitelistedChannelsTags"><div class="tag-list"></div><input class="tag-input-field" data-i18n-placeholder="channelHandlePlaceholder" placeholder="@SomeChannel"></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="dailyLimit">Daily limit per channel</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="dailyLimitDesc">Hides after N videos from the same channel per day (0 = off)</div></div><input type="number" id="dailyChannelLimit" min="0" max="50" style="width:72px"></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secVideoPage">Video page</p><p class="surface-hint" data-i18n="secVideoPageHint">Elements below the player while you're watching</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideVideoActions">Hide like/dislike/share/thanks buttons</span></div><div class="row-desc" data-i18n="hideVideoActionsDesc">Removes the like, dislike, share and Super Thanks buttons below videos</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideVideoActions" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideVideoActions"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideAskButton">Hide "Ask" button</span></div><div class="row-desc" data-i18n="hideAskButtonDesc">Removes the AI "Ask" button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideAskButton" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideAskButton"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideSaveButton">Hide "Save" button</span></div><div class="row-desc" data-i18n="hideSaveButtonDesc">Removes the "Save to playlist" button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSaveButton" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSaveButton"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMoreActionsButton">Hide "..." (more actions) button</span></div><div class="row-desc" data-i18n="hideMoreActionsButtonDesc">Removes the "..." overflow menu button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMoreActionsButton" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMoreActionsButton"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideChannelInfo">Hide channel info</span></div><div class="row-desc" data-i18n="hideChannelInfoDesc">Hides the channel name, avatar and subscribe button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideChannelInfo" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideChannelInfo"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideDescription">Hide description</span></div><div class="row-desc" data-i18n="hideDescriptionDesc">Hides the video description box</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideDescription" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideDescription"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMerchShelf">Hide merch, tickets &amp; offers</span></div><div class="row-desc" data-i18n="hideMerchShelfDesc">Hides merchandise, concert ticket and product shelves below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMerchShelf" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMerchShelf"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideComments">Hide comments</span></div><div class="row-desc" data-i18n="hideCommentsDesc">Removes the comments section below videos</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideComments" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideComments"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideRelated">Hide recommendations (video sidebar)</span></div><div class="row-desc" data-i18n="hideRelatedDesc">Right column on the video page</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideRelated" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideRelated"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hidePlaylistPanel">Hide playlist panel</span></div><div class="row-desc" data-i18n="hidePlaylistPanelDesc">Hides the up-next playlist sidebar when watching a video that's part of one</div></div><div class="row-actions"><button class="fav-btn" data-fav="hidePlaylistPanel" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hidePlaylistPanel"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideLiveChat">Hide live chat</span></div><div class="row-desc" data-i18n="hideLiveChatDesc">Hides the chat panel next to live streams</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideLiveChat" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideLiveChat"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideEndCards">Hide end screen cards</span></div><div class="row-desc" data-i18n="hideEndCardsDesc">Small suggestion cards popping up during playback</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideEndCards" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideEndCards"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideEndScreenFeed">Hide end screen feed</span></div><div class="row-desc" data-i18n="hideEndScreenFeedDesc">The full suggestion grid shown when the video finishes</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideEndScreenFeed" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideEndScreenFeed"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="disableAutoplay">Disable autoplay</span></div><div class="row-desc" data-i18n="disableAutoplayDesc">Turns off "autoplay next video" every time you open a video</div></div><div class="row-actions"><button class="fav-btn" data-fav="disableAutoplay" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="disableAutoplay"><span class="track"></span></label></div></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secSideMenu">Side menu</p><p class="surface-hint" data-i18n="secSideMenuHint">Shortcuts in the left navigation, kept separate from the feed filters above</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideShortsSidebar">Hide Shorts in side menu</span></div><div class="row-desc" data-i18n="hideShortsSidebarDesc">Removes the Shorts shortcut from the side menu (the feed toggle above only hides Shorts from the feed)</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideShortsSidebar" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideShortsSidebar"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideSubscriptions">Hide Subscriptions in side menu</span></div><div class="row-desc" data-i18n="hideSubscriptionsDesc">Removes the list of subscribed channels from the side menu</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSubscriptions" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSubscriptions"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMoreFromYoutube">Hide "More from YouTube" in side menu</span></div><div class="row-desc" data-i18n="hideMoreFromYoutubeDesc">Removes Premium, Movies &amp; TV, Gaming and Kids shortcuts from the side menu</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMoreFromYoutube" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMoreFromYoutube"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideExploreSidebar">Hide Trending / Explore in side menu</span></div><div class="row-desc" data-i18n="hideExploreSidebarDesc">Removes the Trending and Explore shortcuts from the side menu</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideExploreSidebar" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideExploreSidebar"><span class="track"></span></label></div></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secTopHeader">Top header</p><p class="surface-hint" data-i18n="secTopHeaderHint">The bar with search and account controls above everything else</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideVoiceSearch">Hide voice search</span></div><div class="row-desc" data-i18n="hideVoiceSearchDesc">Removes the microphone button next to the search bar</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideVoiceSearch" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideVoiceSearch"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideNotifications">Hide notifications</span></div><div class="row-desc" data-i18n="hideNotificationsDesc">Removes the notification bell from the top header</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideNotifications" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideNotifications"><span class="track"></span></label></div></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secData">Data</p><p class="surface-hint" data-i18n="secDataHint">Backup, restore and clear what's saved in your browser</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="exportSettings">Export settings</span></div><div class="row-desc" data-i18n="exportDesc">Backup as JSON</div></div><button class="btn" id="exportBtn" data-i18n="exportBtn">Export</button></div><div class="card-row"><div><div class="row-label"><span data-i18n="importSettings">Import settings</span></div><div class="row-desc" data-i18n="importDesc">Restore settings from a previously exported JSON file</div></div><button class="btn" id="importBtn" data-i18n="importBtn">Import</button> <input type="file" id="importFile" accept="application/json" hidden></div><div class="card-row"><div><div class="row-label"><span data-i18n="clearHistory">Clear watched history</span></div><div class="row-desc" data-i18n="clearHistoryDesc">Erases the internal list of videos already marked as watched</div></div><button class="btn" id="clearHistory" data-i18n="clearBtn">Clear</button></div></div></div></div></section><section class="topic" id="proSection"><p class="section-label" data-i18n="secPro">Pro</p><p class="surface-hint" data-i18n="secProHint">One-time purchase that unlocks every advanced filter.</p><div id="pro"><div class="pro-banner" id="proPitch"><span class="pro-badge" data-i18n="proBadge">PRO</span><h3 class="pro-banner-title" data-i18n="proBannerTitle">Get every advanced feature.</h3><p class="pro-banner-subtitle" data-i18n="proBannerSubtitle">Pay once. Keep it forever.</p><ul class="pro-banner-checklist"><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletNoSub">No subscription</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletFilters">Advanced filters unlocked</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletEditAny">Rename &amp; edit any profile</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletProfiles">+3 custom profiles</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletSchedule">Auto-switch on schedule</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletUpdates">Lifetime updates</span></li></ul><p class="pro-banner-why" data-i18n="proWhyPaid">Vidsieve is independently built: no VC, no ads, no data collection. Your one-time purchase is what keeps it alive.</p><a class="pro-cta-btn" href="https://www.creem.io/payment/prod_4LMzW908SRyYJezTph13gl" id="proUpgradeBtn" target="_blank" rel="noopener noreferrer"><span data-i18n="proCtaUpgradePrice">Buy Pro ($9.99)</span> <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17L17 7"></path><path d="M8 7h9v9"></path></svg></a></div><div class="pro-thanks" id="proThanks" hidden><span class="pro-badge" data-i18n="proBadge">PRO</span><p class="pro-thanks-text" data-i18n="proThanksText">You're Pro. Thanks for supporting Vidsieve!</p><button type="button" class="pro-manage-link" id="licenseDeactivateBtn" data-i18n="licenseDeactivateBtn">Deactivate on this device</button></div></div></section><section class="topic" id="licenseSection"><p class="section-label" data-i18n="licenseSectionTitle">License Key</p><p class="surface-hint" data-i18n="secLicenseHint">Paste the key from your purchase confirmation email to activate Pro on this device.</p><div class="license-box"><div class="license-row" id="licenseFormRow"><input id="licenseKeyInput" class="license-input" data-i18n-placeholder="licenseInputPlaceholder" placeholder="Paste your license key" autocomplete="off" spellcheck="false"> <button class="btn-primary" id="licenseActivateBtn" data-i18n="licenseActivateBtn">Activate</button></div><p class="license-status" id="licenseStatus"></p></div></section><p class="pro-coffee-link"><a href="https://www.creem.io/payment/prod_96aLhruFN5CFXbaKQrmn5" id="proCoffeeLink" data-i18n="proCoffee" target="_blank" rel="noopener noreferrer">Enjoying the extension? Support development ☕</a></p><hr class="page-footer-divider"><p class="page-footer-note" id="footerYtNote" data-i18n="footerYtNote">Vidsieve is actively maintained to keep up with YouTube's changes. If a filter ever needs an update, the fix itself is usually ready within days, but it takes about a week to actually reach you because of the Chrome Web Store's review.</p><p class="page-footer-note page-footer-contact"><a href="https://vidsieve.com/privacy" target="_blank" rel="noopener noreferrer" data-i18n="footerPrivacyLink">Privacy</a> · <a href="https://vidsieve.com/terms" target="_blank" rel="noopener noreferrer" data-i18n="footerTermsLink">Terms</a> · <a href="mailto:contact@vidsieve.com?subject=Vidsieve%20Support%3A%20%5Badd%20a%20short%20summary%5D&body=Describe%20your%20question%20or%20issue%20below%3A%0A%0A%0AFor%20faster%20support%2C%20please%20also%20include%20%28if%20relevant%29%3A%0A-%20Order%20ID%20%28for%20purchase%20or%20license%20issues%29%0A-%20Browser%20name%20and%20version%0A-%20Vidsieve%20version%20%28see%20chrome%3A%2F%2Fextensions%29%0A-%20Which%20filter%20is%20affected%20and%20where%20%28e.g.%20Home%20feed%2C%20Shorts%2C%20Watch%20page%29%0A-%20YouTube%27s%20display%20language%20%28Settings%20%3E%20Language%20on%20youtube.com%29" data-i18n="footerContactLink">Contact</a></p><span class="status" id="status"></span><div class="modal-overlay" id="modalOverlay" hidden><div class="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle"><h3 class="modal-title" id="modalTitle"></h3><p class="modal-desc" id="modalDesc"></p><input class="modal-input" id="modalInput" maxlength="40"><div class="modal-actions"><button class="btn" id="modalCancel" data-i18n="modalCancel">Cancel</button> <button class="btn-primary" id="modalConfirm"></button></div></div></div><div class="modal-overlay" id="scheduleModalOverlay" hidden><div class="modal modal-schedule" role="dialog" aria-modal="true" aria-labelledby="scheduleModalTitle"><div class="modal-header"><label class="switch"><input type="checkbox" id="scheduleEnabledToggle"><span class="track"></span></label><h3 class="modal-title" id="scheduleModalTitle" data-i18n="scheduleModalTitle">Auto-schedule</h3><button type="button" class="modal-close-btn" id="scheduleModalClose" aria-label="Close">×</button></div><p class="modal-desc" id="scheduleModalDesc"></p><div class="schedule-section"><span class="schedule-section-label" data-i18n="scheduleActiveOnLabel">Active on</span><div class="day-chip-row" id="scheduleDayChips"></div></div><div class="schedule-section"><div class="schedule-section-head"><span class="schedule-section-label" data-i18n="scheduleActiveHoursLabel">Active hours</span> <span class="toggle-switch-sm"><span data-i18n="scheduleAllDayLabel">All day</span><label class="switch"><input type="checkbox" id="scheduleAllDayToggle"><span class="track"></span></label></span></div><div class="schedule-ranges" id="scheduleRanges"></div><button type="button" class="link-btn" id="scheduleAddRange" data-i18n="scheduleAddRangeBtn">+ Add another range</button></div><p class="schedule-hint" data-i18n="scheduleRestoreHint">Outside these hours, your previous profile is restored.</p><p class="schedule-validation-error" id="scheduleValidationError" hidden></p><p class="schedule-conflict-warning" id="scheduleConflictWarning" hidden></p><div class="modal-actions"><button class="btn" id="scheduleModalCancel" data-i18n="modalCancel">Cancel</button> <button class="btn-primary" id="scheduleModalSave" data-i18n="modalSave">Save</button></div></div></div><div class="modal-overlay" id="scheduleOverviewModalOverlay" hidden><div class="modal modal-schedule-overview" role="dialog" aria-modal="true" aria-labelledby="scheduleOverviewModalTitle"><div class="modal-header"><h3 class="modal-title" id="scheduleOverviewModalTitle" data-i18n="scheduleOverviewTitle">Schedule overview</h3><button type="button" class="modal-close-btn" id="scheduleOverviewModalClose" aria-label="Close">×</button></div><div id="scheduleOverviewBody"></div></div></div><script src="../shared/i18n.js"></script><script src="../shared/storage.js"></script><script src="../shared/license.js"></script><script src="../shared/profiles.js"></script><script src="../shared/scheduler.js"></script><script src="../shared/schedule.js"></script><script src="options.js"></script></body></html>
<!doctype html><html><head><meta charset="UTF-8"><title data-i18n="pageTitle">YouTube Cleanup - Settings</title><link rel="icon" href="../icons/icon48.png" type="image/png"><script src="../shared/theme-init.js"></script><link rel="stylesheet" href="../shared/tokens.css"><link rel="stylesheet" href="options.css"></head><body><div class="page-header"><div class="page-header-brand"><img class="logo" src="../icons/icon.svg" width="28" height="28" alt=""> <span class="page-title" data-i18n="appShortName">Vidsieve</span></div><div class="page-header-actions"><a class="btn header-theme-btn" id="headerCoffeeLink" href="https://www.creem.io/payment/prod_96aLhruFN5CFXbaKQrmn5" target="_blank" rel="noopener noreferrer" hidden data-i18n-title="proCoffee" data-i18n-aria-label="proCoffeeAriaLabel" title="Enjoying the extension? Buy me a coffee ☕" aria-label="Enjoying the extension? Buy me a coffee"><svg class="section-header-btn-icon" viewBox="0 0 24 24" aria-hidden="true"><use href="../shared/icons.svg#ic-coffee"/></svg> </a><button type="button" class="btn header-theme-btn" id="themeBtn" data-i18n-title="cycleTheme" data-i18n-aria-label="cycleTheme" title="Cycle theme" aria-label="Cycle theme"><svg class="header-theme-btn-icon theme-icon" data-theme-icon="auto" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 18V4a8 8 0 0 1 0 16Z"/></svg> <svg class="header-theme-btn-icon theme-icon" data-theme-icon="light" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4" fill="currentColor"/><path stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg> <svg class="header-theme-btn-icon theme-icon" data-theme-icon="dark" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79Z"/></svg></button></div></div><div class="search-bar"><svg class="search-bar-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" stroke-width="2"/><path d="M21 21l-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg> <input id="filterSearchInput" class="search-bar-input" autocomplete="off" data-i18n-placeholder="filterSearchPlaceholder" placeholder="Search filters…"> <kbd class="search-bar-shortcut" id="filterSearchShortcut">Ctrl + K</kbd> <button type="button" class="search-bar-clear" id="filterSearchClear" hidden data-i18n-aria-label="filterSearchClear" aria-label="Clear search">×</button> <button type="button" class="search-bar-active-toggle" id="filterActiveOnlyBtn" aria-pressed="false" data-i18n="filterActiveOnlyBtn" data-i18n-title="filterActiveOnlyBtnTitle" title="Show only active filters">Active only</button></div><p class="search-bar-empty" id="filterSearchEmpty" hidden data-i18n="filterSearchEmpty">No filters match your search.</p><section class="topic" id="profilesSection"><div class="section-header-row"><p class="section-label" data-i18n="secProfiles">Profiles</p><button type="button" class="section-header-btn" id="scheduleOverviewOpenBtn"><svg class="section-header-btn-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M17 12h-5v5h5v-5ZM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2Zm3 18H5V8h14v11Z"/></svg> <span data-i18n="scheduleOverviewBtn">Schedule overview</span></button></div><p class="surface-hint" data-i18n="secProfilesHint">Switch your whole set of filters at once. Free includes 3 ready-made profiles. Pro adds renaming, editing, saving your own, and auto-switching by schedule.</p><div class="branches"><div class="branch"><div class="profiles-grid" id="profilesCard"></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secFeed">Feed &amp; grid</p><p class="surface-hint" data-i18n="secFeedHint">Everything that decides whether a card shows up on Home, Subscriptions or a channel page</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="homeFeedMode">Home feed</span></div><div class="row-desc" data-i18n="homeFeedModeDesc">Controls what happens to the YouTube home page</div></div><select id="homeFeedMode"><option value="show" data-i18n="homeFeedModeShow">Default</option><option value="blank" data-i18n="homeFeedModeBlank">Blank</option><option value="subscriptions" data-i18n="homeFeedModeSubscriptions">Redirect to Subscriptions</option><option value="watchLater" data-i18n="homeFeedModeWatchLater">Redirect to Watch Later</option><option value="library" data-i18n="homeFeedModeLibrary">Redirect to Library</option></select></div><div class="card-row"><div><div class="row-label"><span data-i18n="videosPerRow">Videos per row</span></div><div class="row-desc" data-i18n="videosPerRowDesc">How many video cards fit side by side in the grid</div></div><select id="videosPerRow"><option value="1">1</option><option value="2">2</option><option value="3" data-i18n="videosPerRowDefault">Default</option><option value="4">4</option><option value="5">5</option><option value="6">6</option></select></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideShorts">Hide Shorts</span></div><div class="row-desc" data-i18n="hideShortsDesc">Short videos and Shorts shelves</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideShorts" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideShorts"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMixes">Hide Mixes</span></div><div class="row-desc" data-i18n="hideMixesDesc">Playlists generated by YouTube</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMixes" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMixes"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideLive">Hide Lives</span></div><div class="row-desc" data-i18n="hideLiveDesc">Hides streams that are currently live</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideLive" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideLive"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideUpcoming">Hide Upcoming</span></div><div class="row-desc" data-i18n="hideUpcomingDesc">Hides scheduled live streams and premieres</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideUpcoming" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideUpcoming"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hidePremieres">Hide Premieres</span></div><div class="row-desc" data-i18n="hidePremieresDesc">Hides videos marked as premiere</div></div><div class="row-actions"><button class="fav-btn" data-fav="hidePremieres" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hidePremieres"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMembers">Hide Members-only</span></div><div class="row-desc" data-i18n="hideMembersDesc">Hides videos exclusive to paying channel members</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMembers" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMembers"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideFilterBar">Hide topic filter bar</span></div><div class="row-desc" data-i18n="hideFilterBarDesc">Removes the row of topic pills (All, Music, Gaming...) above the feed</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideFilterBar" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideFilterBar"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hidePlayablesShelf">Hide Playables</span></div><div class="row-desc" data-i18n="hidePlayablesShelfDesc">The "YouTube Playables" mini-games shelf mixed into the feed</div></div><div class="row-actions"><button class="fav-btn" data-fav="hidePlayablesShelf" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hidePlayablesShelf"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="blurThumbnails">Blur thumbnails</span></div><div class="row-desc" data-i18n="blurThumbnailsDesc">Blurs video thumbnails until you hover.</div></div><div class="row-actions"><button class="fav-btn" data-fav="blurThumbnails" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="blurThumbnails"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideProfilePhotos">Hide profile photos</span></div><div class="row-desc" data-i18n="hideProfilePhotosDesc">Hides channel avatars in comments, the feed and the sidebar</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideProfilePhotos" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideProfilePhotos"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="disableInfiniteScroll">Disable infinite scroll</span></div><div class="row-desc" data-i18n="disableInfiniteScrollDesc">Stops loading more videos after the first batch on Home and Subscriptions</div></div><div class="row-actions"><button class="fav-btn" data-fav="disableInfiniteScroll" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="disableInfiniteScroll"><span class="track"></span></label></div></div></div></div><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideSeen">Hide watched</span></div><div class="row-desc" data-i18n="hideSeenDesc">Expires after 90 days</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSeen" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSeen"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="watchedThreshold">Threshold to mark as watched</span></div><div class="row-desc"><span id="thresholdValue">50</span><span data-i18n="watchedThresholdDesc">% of video watched</span></div></div><input type="range" id="watchedThreshold" min="0" max="100" step="5"></div><div class="card-row"><div><div class="row-label"><span data-i18n="filterMode">Filter mode</span></div><div class="row-desc" data-i18n="filterModeDesc">Controls how every filter behaves: Hide removes the video, Dim grays it out, Preview shows why without hiding it</div></div><select id="watchedMode"><option value="hide" data-i18n="modeHide">Hide</option><option value="dim" data-i18n="modeDim">Dim</option><option value="dryrun" id="modeDryRunOption" data-i18n="modeDryRun">Preview</option></select></div></div></div><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="minAge">Minimum age (days)</span></div><div class="row-desc" data-i18n="minAgeDesc">Hides videos newer than this (0 = no limit)</div></div><input type="number" id="minAgeDays" min="0" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="maxAge">Maximum age (days)</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="maxAgeDays" min="0" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="minDuration">Minimum duration (minutes)</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="minDurationDesc">Hides videos shorter than this (0 = no limit)</div></div><input type="number" id="minDuration" min="0" step="0.5" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="maxDuration">Maximum duration (minutes)</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="maxDuration" min="0" step="0.5" style="width:96px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="minViews">Minimum views</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="minViews" min="0" style="width:120px"></div><div class="card-row"><div><div class="row-label"><span data-i18n="maxViews">Maximum views</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="noLimit">0 = no limit</div></div><input type="number" id="maxViews" min="0" style="width:120px"></div></div></div><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideDiscoveryShelf">Hide Topic Discovery</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="hideDiscoveryShelfDesc">The "Discover more topics" shelf with topic chips</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideDiscoveryShelf" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideDiscoveryShelf"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideSubscriptionsAlgo">Hide algorithmic shelves in Subscriptions</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="hideSubscriptionsAlgoDesc">Removes "Most relevant"/"For you" shelves from the Subscriptions feed. Only your chronological subscriptions remain</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSubscriptionsAlgo" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSubscriptionsAlgo"><span class="track"></span></label></div></div></div></div><div class="branch"><div class="card"><div class="card-row column"><div class="row-label"><span data-i18n="keywordsLabel">Blocked words / regex</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="keywordsDesc">One per line. Plain text works, or use <code>/regex/i</code> for advanced patterns.</div><textarea id="keywords" rows="4" data-i18n-placeholder="keywordsPlaceholder" placeholder="you won't believe&#10;gone wrong&#10;/reacts? to/i"></textarea></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secChannels">Channels</p><p class="surface-hint" data-i18n="secChannelsHint">Rules applied per channel, regardless of where the video shows up</p><div class="branches"><div class="branch"><div class="card"><div class="card-row column"><div class="row-label"><span data-i18n="blockedChannels">Blocked channels</span></div><div class="row-desc" data-i18n="blockedChannelsDesc">Type a @handle and press Enter. Also use the "..." menu on any video card.</div><div class="tag-input" id="blockedChannelsTags"><div class="tag-list"></div><input class="tag-input-field" data-i18n-placeholder="channelHandlePlaceholder" placeholder="@SomeChannel"></div></div><div class="card-row column" id="mutedChannelsSection"><div class="row-label"><span data-i18n="mutedChannelsLabel">Muted channels</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="mutedChannelsDesc">Hides a channel for a set number of days, then unblocks it automatically. Also available from YouTube's "..." menu.</div><div class="mute-panel" id="mutedChannelsTags"><div class="mute-table" id="mutedChannelsTable"><div class="mute-head" id="mutedChannelsHead" hidden><span class="mute-col-channel" data-i18n="mutedChannelsColChannel">Channel</span> <span class="mute-col-expires" data-i18n="mutedChannelsColExpires">Expires</span> <button type="button" class="mute-unmute" id="mutedChannelsUnmuteAllBtn" data-i18n-aria-label="mutedChannelsUnmuteAll" data-i18n-title="mutedChannelsUnmuteAll" aria-label="Unmute all" title="Unmute all">×</button></div><div class="mute-rows-scroll" id="mutedChannelsRowsScroll"><div class="mute-list" id="mutedChannelsList"></div></div></div><div class="mute-add"><input class="mute-add-input" id="mutedChannelsInput" data-i18n-placeholder="channelHandlePlaceholder" placeholder="@SomeChannel"><div class="duration-row"><button type="button" class="duration-chip" data-days="7">7d</button> <button type="button" class="duration-chip is-on" data-days="14">14d</button> <button type="button" class="duration-chip" data-days="30">30d</button></div></div></div></div><div class="card-row column"><div class="row-label"><span data-i18n="whitelist">Whitelist (always pass)</span></div><div class="row-desc" data-i18n="whitelistDesc">Channels that ignore all filter rules</div><div class="tag-input" id="whitelistedChannelsTags"><div class="tag-list"></div><input class="tag-input-field" data-i18n-placeholder="channelHandlePlaceholder" placeholder="@SomeChannel"></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="dailyLimit">Daily limit per channel</span> <span class="pro-badge" data-i18n="proBadge">PRO</span></div><div class="row-desc" data-i18n="dailyLimitDesc">Hides after N videos from the same channel per day (0 = off)</div></div><input type="number" id="dailyChannelLimit" min="0" max="50" style="width:72px"></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secVideoPage">Video page</p><p class="surface-hint" data-i18n="secVideoPageHint">Elements below the player while you're watching</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideVideoActions">Hide like/dislike/share/thanks buttons</span></div><div class="row-desc" data-i18n="hideVideoActionsDesc">Removes the like, dislike, share and Super Thanks buttons below videos</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideVideoActions" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideVideoActions"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideAskButton">Hide "Ask" button</span></div><div class="row-desc" data-i18n="hideAskButtonDesc">Removes the AI "Ask" button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideAskButton" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideAskButton"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideSaveButton">Hide "Save" button</span></div><div class="row-desc" data-i18n="hideSaveButtonDesc">Removes the "Save to playlist" button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSaveButton" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSaveButton"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMoreActionsButton">Hide "..." (more actions) button</span></div><div class="row-desc" data-i18n="hideMoreActionsButtonDesc">Removes the "..." overflow menu button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMoreActionsButton" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMoreActionsButton"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideChannelInfo">Hide channel info</span></div><div class="row-desc" data-i18n="hideChannelInfoDesc">Hides the channel name, avatar and subscribe button below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideChannelInfo" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideChannelInfo"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideDescription">Hide description</span></div><div class="row-desc" data-i18n="hideDescriptionDesc">Hides the video description box</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideDescription" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideDescription"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMerchShelf">Hide merch, tickets &amp; offers</span></div><div class="row-desc" data-i18n="hideMerchShelfDesc">Hides merchandise, concert ticket and product shelves below the video</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMerchShelf" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMerchShelf"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideComments">Hide comments</span></div><div class="row-desc" data-i18n="hideCommentsDesc">Removes the comments section below videos</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideComments" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideComments"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideRelated">Hide recommendations (video sidebar)</span></div><div class="row-desc" data-i18n="hideRelatedDesc">Right column on the video page</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideRelated" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideRelated"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hidePlaylistPanel">Hide playlist panel</span></div><div class="row-desc" data-i18n="hidePlaylistPanelDesc">Hides the up-next playlist sidebar when watching a video that's part of one</div></div><div class="row-actions"><button class="fav-btn" data-fav="hidePlaylistPanel" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hidePlaylistPanel"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideLiveChat">Hide live chat</span></div><div class="row-desc" data-i18n="hideLiveChatDesc">Hides the chat panel next to live streams</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideLiveChat" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideLiveChat"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideEndCards">Hide end screen cards</span></div><div class="row-desc" data-i18n="hideEndCardsDesc">Small suggestion cards popping up during playback</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideEndCards" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideEndCards"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideEndScreenFeed">Hide end screen feed</span></div><div class="row-desc" data-i18n="hideEndScreenFeedDesc">The full suggestion grid shown when the video finishes</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideEndScreenFeed" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideEndScreenFeed"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="disableAutoplay">Disable autoplay</span></div><div class="row-desc" data-i18n="disableAutoplayDesc">Turns off "autoplay next video" every time you open a video</div></div><div class="row-actions"><button class="fav-btn" data-fav="disableAutoplay" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="disableAutoplay"><span class="track"></span></label></div></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secSideMenu">Side menu</p><p class="surface-hint" data-i18n="secSideMenuHint">Shortcuts in the left navigation, kept separate from the feed filters above</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideShortsSidebar">Hide Shorts in side menu</span></div><div class="row-desc" data-i18n="hideShortsSidebarDesc">Removes the Shorts shortcut from the side menu (the feed toggle above only hides Shorts from the feed)</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideShortsSidebar" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideShortsSidebar"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideSubscriptions">Hide Subscriptions in side menu</span></div><div class="row-desc" data-i18n="hideSubscriptionsDesc">Removes the list of subscribed channels from the side menu</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideSubscriptions" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideSubscriptions"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideMoreFromYoutube">Hide "More from YouTube" in side menu</span></div><div class="row-desc" data-i18n="hideMoreFromYoutubeDesc">Removes Premium, Movies &amp; TV, Gaming and Kids shortcuts from the side menu</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideMoreFromYoutube" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideMoreFromYoutube"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideExploreSidebar">Hide Trending / Explore in side menu</span></div><div class="row-desc" data-i18n="hideExploreSidebarDesc">Removes the Trending and Explore shortcuts from the side menu</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideExploreSidebar" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideExploreSidebar"><span class="track"></span></label></div></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secTopHeader">Top header</p><p class="surface-hint" data-i18n="secTopHeaderHint">The bar with search and account controls above everything else</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="hideVoiceSearch">Hide voice search</span></div><div class="row-desc" data-i18n="hideVoiceSearchDesc">Removes the microphone button next to the search bar</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideVoiceSearch" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideVoiceSearch"><span class="track"></span></label></div></div><div class="card-row"><div><div class="row-label"><span data-i18n="hideNotifications">Hide notifications</span></div><div class="row-desc" data-i18n="hideNotificationsDesc">Removes the notification bell from the top header</div></div><div class="row-actions"><button class="fav-btn" data-fav="hideNotifications" type="button" data-i18n-title="addToQuickFilters" data-i18n-aria-label="addToQuickFilters" title="Add to quick filters" aria-label="Add to quick filters"><svg class="fav-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z"/></svg></button> <label class="switch"><input type="checkbox" id="hideNotifications"><span class="track"></span></label></div></div></div></div></div></section><section class="topic"><p class="section-label" data-i18n="secData">Data</p><p class="surface-hint" data-i18n="secDataHint">Backup, restore and clear what's saved in your browser</p><div class="branches"><div class="branch"><div class="card"><div class="card-row"><div><div class="row-label"><span data-i18n="exportSettings">Export settings</span></div><div class="row-desc" data-i18n="exportDesc">Backup as JSON</div></div><button class="btn" id="exportBtn" data-i18n="exportBtn">Export</button></div><div class="card-row"><div><div class="row-label"><span data-i18n="importSettings">Import settings</span></div><div class="row-desc" data-i18n="importDesc">Restore settings from a previously exported JSON file</div></div><button class="btn" id="importBtn" data-i18n="importBtn">Import</button> <input type="file" id="importFile" accept="application/json" hidden></div><div class="card-row"><div><div class="row-label"><span data-i18n="clearHistory">Clear watched history</span></div><div class="row-desc" data-i18n="clearHistoryDesc">Erases the internal list of videos already marked as watched</div></div><button class="btn" id="clearHistory" data-i18n="clearBtn">Clear</button></div></div></div></div></section><section class="topic" id="proSection"><p class="section-label" data-i18n="secPro">Pro</p><p class="surface-hint" data-i18n="secProHint">One-time purchase that unlocks every advanced filter.</p><div id="pro"><div class="pro-banner" id="proPitch"><span class="pro-badge" data-i18n="proBadge">PRO</span><h3 class="pro-banner-title" data-i18n="proBannerTitle">Get every advanced feature.</h3><p class="pro-banner-subtitle" data-i18n="proBannerSubtitle">Pay once. Keep it forever.</p><ul class="pro-banner-checklist"><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletNoSub">No subscription</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletFilters">Advanced filters unlocked</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletEditAny">Rename &amp; edit any profile</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletProfiles">+3 custom profiles</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletSchedule">Auto-switch on schedule</span></li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"></path></svg> <span data-i18n="proBannerBulletUpdates">Lifetime updates</span></li></ul><p class="pro-banner-why" data-i18n="proWhyPaid">Vidsieve is independently built: no VC, no ads, no data collection. Your one-time purchase is what keeps it alive.</p><a class="pro-cta-btn" href="https://www.creem.io/payment/prod_4LMzW908SRyYJezTph13gl" id="proUpgradeBtn" target="_blank" rel="noopener noreferrer"><span data-i18n="proCtaUpgradePrice">Buy Pro ($9.99)</span> <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 17L17 7"></path><path d="M8 7h9v9"></path></svg></a></div><div class="pro-thanks" id="proThanks" hidden><span class="pro-badge" data-i18n="proBadge">PRO</span><p class="pro-thanks-text" data-i18n="proThanksText">You're Pro. Thanks for supporting Vidsieve!</p><button type="button" class="pro-manage-link" id="licenseDeactivateBtn" data-i18n="licenseDeactivateBtn">Deactivate on this device</button></div></div></section><section class="topic" id="licenseSection"><p class="section-label" data-i18n="licenseSectionTitle">License Key</p><p class="surface-hint" data-i18n="secLicenseHint">Paste the key from your purchase confirmation email to activate Pro on this device.</p><div class="license-box"><div class="license-row" id="licenseFormRow"><input id="licenseKeyInput" class="license-input" data-i18n-placeholder="licenseInputPlaceholder" placeholder="Paste your license key" autocomplete="off" spellcheck="false"> <button class="btn-primary" id="licenseActivateBtn" data-i18n="licenseActivateBtn">Activate</button></div><p class="license-status" id="licenseStatus"></p></div></section><p class="pro-coffee-link"><a href="https://www.creem.io/payment/prod_96aLhruFN5CFXbaKQrmn5" id="proCoffeeLink" data-i18n="proCoffee" target="_blank" rel="noopener noreferrer">Enjoying the extension? Support development ☕</a></p><hr class="page-footer-divider"><p class="page-footer-note" id="footerYtNote" data-i18n="footerYtNote">Vidsieve is actively maintained to keep up with YouTube's changes. If a filter ever needs an update, the fix itself is usually ready within days, but it takes about a week to actually reach you because of the Chrome Web Store's review.</p><p class="page-footer-note page-footer-contact"><a href="https://vidsieve.com/privacy" target="_blank" rel="noopener noreferrer" data-i18n="footerPrivacyLink">Privacy</a> · <a href="https://vidsieve.com/terms" target="_blank" rel="noopener noreferrer" data-i18n="footerTermsLink">Terms</a> · <a href="mailto:contact@vidsieve.com?subject=Vidsieve%20Support%3A%20%5Badd%20a%20short%20summary%5D&body=Describe%20your%20question%20or%20issue%20below%3A%0A%0A%0AFor%20faster%20support%2C%20please%20also%20include%20%28if%20relevant%29%3A%0A-%20Order%20ID%20%28for%20purchase%20or%20license%20issues%29%0A-%20Browser%20name%20and%20version%0A-%20Vidsieve%20version%20%28see%20chrome%3A%2F%2Fextensions%29%0A-%20Which%20filter%20is%20affected%20and%20where%20%28e.g.%20Home%20feed%2C%20Shorts%2C%20Watch%20page%29%0A-%20YouTube%27s%20display%20language%20%28Settings%20%3E%20Language%20on%20youtube.com%29" data-i18n="footerContactLink">Contact</a></p><span class="status" id="status"></span><div class="modal-overlay" id="modalOverlay" hidden><div class="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle"><h3 class="modal-title" id="modalTitle"></h3><p class="modal-desc" id="modalDesc"></p><input class="modal-input" id="modalInput" maxlength="40"><div class="modal-actions"><button class="btn" id="modalCancel" data-i18n="modalCancel">Cancel</button> <button class="btn-primary" id="modalConfirm"></button></div></div></div><div class="modal-overlay" id="scheduleModalOverlay" hidden><div class="modal modal-schedule" role="dialog" aria-modal="true" aria-labelledby="scheduleModalTitle"><div class="modal-header"><label class="switch"><input type="checkbox" id="scheduleEnabledToggle"><span class="track"></span></label><h3 class="modal-title" id="scheduleModalTitle" data-i18n="scheduleModalTitle">Auto-schedule</h3><button type="button" class="modal-close-btn" id="scheduleModalClose" aria-label="Close">×</button></div><p class="modal-desc" id="scheduleModalDesc"></p><div class="schedule-section"><span class="schedule-section-label" data-i18n="scheduleActiveOnLabel">Active on</span><div class="day-chip-row" id="scheduleDayChips"></div></div><div class="schedule-section"><div class="schedule-section-head"><span class="schedule-section-label" data-i18n="scheduleActiveHoursLabel">Active hours</span> <span class="toggle-switch-sm"><span data-i18n="scheduleAllDayLabel">All day</span><label class="switch"><input type="checkbox" id="scheduleAllDayToggle"><span class="track"></span></label></span></div><div class="schedule-ranges" id="scheduleRanges"></div><button type="button" class="link-btn" id="scheduleAddRange" data-i18n="scheduleAddRangeBtn">+ Add another range</button></div><p class="schedule-hint" data-i18n="scheduleRestoreHint">Outside these hours, your previous profile is restored.</p><p class="schedule-validation-error" id="scheduleValidationError" hidden></p><p class="schedule-conflict-warning" id="scheduleConflictWarning" hidden></p><div class="modal-actions"><button class="btn" id="scheduleModalCancel" data-i18n="modalCancel">Cancel</button> <button class="btn-primary" id="scheduleModalSave" data-i18n="modalSave">Save</button></div></div></div><div class="modal-overlay" id="scheduleOverviewModalOverlay" hidden><div class="modal modal-schedule-overview" role="dialog" aria-modal="true" aria-labelledby="scheduleOverviewModalTitle"><div class="modal-header"><h3 class="modal-title" id="scheduleOverviewModalTitle" data-i18n="scheduleOverviewTitle">Schedule overview</h3><button type="button" class="modal-close-btn" id="scheduleOverviewModalClose" aria-label="Close">×</button></div><div id="scheduleOverviewBody"></div></div></div><script src="../shared/i18n.js"></script><script src="../shared/storage.js"></script><script src="../shared/device.js"></script><script src="../shared/profiles.js"></script><script src="../shared/scheduler.js"></script><script src="../shared/schedule.js"></script><script src="options.js"></script></body></html>

@@ -1,1 +0,1 @@

const status=document.getElementById("status"),THEMES=["auto","light","dark"],THEME_TITLE_KEY={auto:"themeAutoTitle",light:"themeLightTitle",dark:"themeDarkTitle"},THEME_LABEL_KEY={auto:"themeAuto",light:"themeLight",dark:"themeDark"};function applyTheme(e){"auto"===e?(document.documentElement.removeAttribute("data-theme"),localStorage.removeItem("theme")):(document.documentElement.setAttribute("data-theme",e),localStorage.setItem("theme",e));const t=document.getElementById("themeBtn");t&&(t.dataset.theme=e,t.title=Ytci18n.t(THEME_TITLE_KEY[e]));const n=document.getElementById("themeLabel");n&&(n.textContent=Ytci18n.t(THEME_LABEL_KEY[e]))}chrome.storage.local.get(["theme"],({theme:e="auto"})=>{applyTheme(THEMES.includes(e)?e:"auto")}),document.getElementById("themeBtn")?.addEventListener("click",async()=>{const{theme:e="auto"}=await chrome.storage.local.get(["theme"]),t=THEMES[(THEMES.indexOf(e)+1)%THEMES.length];await chrome.storage.local.set({theme:t}),applyTheme(t)}),chrome.storage.onChanged.addListener(e=>{"theme"in e&&applyTheme(e.theme.newValue||"auto")});let isReloadPending=!1;const MUTE_DEFAULT_DURATION_DAYS=14,MUTE_DAY_MS=864e5,BOOL_KEYS=["hideShorts","hideLive","hideUpcoming","hidePremieres","hideMembers","hideFilterBar","hideMixes","hideDiscoveryShelf","hidePlayablesShelf","hideSubscriptionsAlgo","hideSeen","disableAutoplay","hideRelated","hideEndCards","hideEndScreenFeed","hideLiveChat","hidePlaylistPanel","hideChannelInfo","hideDescription","hideMerchShelf","hideComments","hideVideoActions","hideAskButton","hideSaveButton","hideMoreActionsButton","hideExploreSidebar","hideSubscriptions","hideShortsSidebar","hideMoreFromYoutube","hideNotifications","hideVoiceSearch","blurThumbnails","hideProfilePhotos","disableInfiniteScroll"],NUM_KEYS=["minAgeDays","maxAgeDays","minViews","maxViews","dailyChannelLimit"],TEXTAREA_KEYS=["keywords"],TAG_KEYS=["blockedChannels","whitelistedChannels"],SELECT_KEYS=["watchedMode","homeFeedMode","videosPerRow"],DEFAULTS={hideSeen:!1,hideShorts:!0,hideMixes:!0,hideDiscoveryShelf:!1,hidePlayablesShelf:!0,hideSubscriptionsAlgo:!1,hideLive:!1,hideUpcoming:!1,hidePremieres:!1,hideMembers:!1,hideFilterBar:!1,homeFeedMode:"show",videosPerRow:"3",disableInfiniteScroll:!1,disableAutoplay:!1,hideRelated:!1,hideEndCards:!1,hideEndScreenFeed:!1,hideLiveChat:!1,hidePlaylistPanel:!1,hideChannelInfo:!1,hideDescription:!1,hideMerchShelf:!1,hideComments:!1,hideVideoActions:!1,hideAskButton:!1,hideSaveButton:!1,hideMoreActionsButton:!1,hideExploreSidebar:!1,hideSubscriptions:!1,hideShortsSidebar:!1,hideMoreFromYoutube:!1,hideNotifications:!1,hideVoiceSearch:!1,blurThumbnails:!1,hideProfilePhotos:!1,minDuration:0,maxDuration:0,minAgeDays:0,maxAgeDays:0,minViews:0,maxViews:0,dailyChannelLimit:0,watchedMode:"hide",watchedThreshold:.5,keywords:[],blockedChannels:[],whitelistedChannels:[],mutedChannels:{},muteDefaultDays:14},ALL_KEYS=[...BOOL_KEYS,...NUM_KEYS,...TEXTAREA_KEYS,...TAG_KEYS,...SELECT_KEYS,"watchedThreshold","minDuration","maxDuration","mutedChannels","muteDefaultDays"];let flashHideTimer=null,flashClearTimer=null;function flash(e){clearTimeout(flashHideTimer),clearTimeout(flashClearTimer),status.textContent=e,status.classList.add("is-visible");const t=Math.min(5e3,Math.max(1500,50*e.length));flashHideTimer=setTimeout(()=>{status.classList.remove("is-visible"),flashClearTimer=setTimeout(()=>status.textContent="",150)},t)}function renderPrefsForm(e){BOOL_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.checked=e[t]??DEFAULTS[t])}),NUM_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.value=e[t]??DEFAULTS[t])}),TEXTAREA_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.value=(e[t]??DEFAULTS[t]).join("\n"))}),TAG_KEYS.forEach(t=>{initTagInput(t,e[t]??DEFAULTS[t])}),initMutePanel(e.mutedChannels??DEFAULTS.mutedChannels,e.muteDefaultDays??DEFAULTS.muteDefaultDays),SELECT_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.value=e[t]??DEFAULTS[t])});const t=100*(e.watchedThreshold??.5);document.getElementById("watchedThreshold").value=t,document.getElementById("thresholdValue").textContent=Math.round(t);const n=document.getElementById("minDuration");n&&(n.value=(e.minDuration??DEFAULTS.minDuration)/60);const l=document.getElementById("maxDuration");l&&(l.value=(e.maxDuration??DEFAULTS.maxDuration)/60)}chrome.storage.local.get(ALL_KEYS,renderPrefsForm),BOOL_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>chrome.storage.local.set({[e]:t.checked}))});const favButtons=[...document.querySelectorAll(".fav-btn")];function renderFavButtons(e){favButtons.forEach(t=>{t.classList.toggle("is-active",e.includes(t.dataset.fav))})}function clampToInputRange(e,t){const n=e.hasAttribute("min")?Number(e.min):-1/0,l=e.hasAttribute("max")?Number(e.max):1/0;return Math.min(Math.max(t,n),l)}chrome.storage.local.get(["favoriteFilters"],({favoriteFilters:e=[]})=>{renderFavButtons(e)}),favButtons.forEach(e=>{e.addEventListener("click",async()=>{const{favoriteFilters:t=[]}=await chrome.storage.local.get(["favoriteFilters"]),n=e.dataset.fav,l=t.includes(n)?t.filter(e=>e!==n):[...t,n];await chrome.storage.local.set({favoriteFilters:l}),renderFavButtons(l)})}),chrome.storage.onChanged.addListener(e=>{isReloadPending||e.favoriteFilters&&renderFavButtons(e.favoriteFilters.newValue??[])}),NUM_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>{const n=parseInt(t.value,10),l=clampToInputRange(t,isNaN(n)?0:n);t.value=l,chrome.storage.local.set({[e]:l})})}),["minDuration","maxDuration"].forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>{const n=parseFloat(t.value),l=clampToInputRange(t,isNaN(n)?0:n);t.value=l,chrome.storage.local.set({[e]:Math.round(60*l)})})});const CHANNEL_HANDLE_RX=/^@[A-Za-z0-9._-]{2,}$/;function initTagInput(e,t){const n=document.getElementById(`${e}Tags`);if(!n)return;if(n.__ytcTagInput)return void n.__ytcTagInput.setEntries(t);const l=n.querySelector(".tag-list"),o=n.querySelector(".tag-input-field");let a=[...t];function i(){chrome.storage.local.set({[e]:a})}function d(){const e=n.classList.contains("is-locked");l.replaceChildren();for(const t of a){const n=document.createElement("span");n.className="tag-chip";const o=document.createElement("span");o.className="tag-chip-label",o.textContent=t;const c=document.createElement("button");c.type="button",c.className="tag-chip-remove",c.disabled=e,c.setAttribute("aria-label",Ytci18n.t("removeChannelTag",{name:t})),c.textContent="×",c.addEventListener("click",()=>{a=a.filter(e=>e!==t),i(),d()}),n.append(o,c),l.appendChild(n)}}o.addEventListener("keydown",e=>{if("Enter"!==e.key)return;e.preventDefault();const t=o.value.trim();t&&(CHANNEL_HANDLE_RX.test(t)?(a.includes(t)||(a=[...a,t],i(),d()),o.value=""):flash(Ytci18n.t("invalidChannelHandle")))}),n.__ytcTagInput={setEntries(e){a=[...e],d()}},d()}function initMutePanel(e,t){const n=document.getElementById("mutedChannelsTags");if(!n)return;if(n.__ytcMutePanel)return n.__ytcMutePanel.setEntries(e),void n.__ytcMutePanel.setDurationDays(t);const l=document.getElementById("mutedChannelsTable"),o=document.getElementById("mutedChannelsRowsScroll"),a=document.getElementById("mutedChannelsList"),i=document.getElementById("mutedChannelsHead"),d=document.getElementById("mutedChannelsInput"),c=document.getElementById("mutedChannelsUnmuteAllBtn"),r=[...n.querySelectorAll(".duration-chip")];let s={...e},u=t??14;function h(){chrome.storage.local.set({mutedChannels:s})}function m(e,t){const n=Math.ceil((e-t)/864e5);return n<=1?{text:Ytci18n.t("mutedChannelsExpiresToday"),soon:!0}:{text:Ytci18n.t("mutedChannelsDaysLeft",{days:String(n)}),soon:!1}}function f(){const e=n.classList.contains("is-locked"),t=Date.now(),d=Object.entries(s).filter(([,e])=>e>t).sort((e,t)=>e[1]-t[1]);a.replaceChildren(),i.hidden=0===d.length,o.hidden=0===d.length,l.hidden=0===d.length,c.disabled=e;for(const[n,l]of d){const o=document.createElement("div");o.className="mute-row";const i=document.createElement("div");i.className="mute-name",i.textContent=n;const{text:d,soon:c}=m(l,t),r=document.createElement("span");r.className=c?"mute-countdown is-soon":"mute-countdown",r.textContent=d;const u=document.createElement("button");u.type="button",u.className="mute-unmute",u.textContent="×";const p=Ytci18n.t("mutedChannelsUnmute");u.setAttribute("aria-label",p),u.title=p,u.disabled=e,u.addEventListener("click",()=>{delete s[n],h(),f()}),o.append(i,r,u),a.appendChild(o)}}function p(e){u=e,r.forEach(t=>t.classList.toggle("is-on",Number(t.dataset.days)===e))}n.style.setProperty("--mute-scrollbar-w",o.offsetWidth-o.clientWidth+"px"),p(u),r.forEach(e=>{e.addEventListener("click",()=>{n.classList.contains("is-locked")||(p(Number(e.dataset.days)),chrome.storage.local.set({muteDefaultDays:u}))})}),d.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),function(){if(n.classList.contains("is-locked"))return;const e=d.value.trim();e&&(CHANNEL_HANDLE_RX.test(e)?(s={...s,[e]:Date.now()+864e5*u},h(),f(),d.value=""):flash(Ytci18n.t("invalidChannelHandle")))}())}),c.addEventListener("click",async()=>{if(n.classList.contains("is-locked"))return;await showModal({title:Ytci18n.t("mutedChannelsUnmuteAllConfirmTitle"),desc:Ytci18n.t("mutedChannelsUnmuteAllConfirmDesc"),showInput:!1,confirmLabel:Ytci18n.t("mutedChannelsUnmuteAll"),danger:!0})&&(s={},h(),f())}),n.__ytcMutePanel={setEntries(e){s={...e},f()},setDurationDays(e){"number"==typeof e&&p(e)}},f()}SELECT_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",async()=>{if("watchedMode"===e&&"dryrun"===t.value&&!await YtcLicense.isPro()){const{watchedMode:e}=await chrome.storage.local.get(["watchedMode"]);return t.value=e??DEFAULTS.watchedMode,void goToProSection()}chrome.storage.local.set({[e]:t.value})})}),TEXTAREA_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>{const n=t.value.split("\n").map(e=>e.trim()).filter(Boolean);chrome.storage.local.set({[e]:n})})});const thresholdEl=document.getElementById("watchedThreshold"),thresholdValueEl=document.getElementById("thresholdValue");thresholdEl.addEventListener("input",()=>{thresholdValueEl.textContent=thresholdEl.value}),thresholdEl.addEventListener("change",()=>{chrome.storage.local.set({watchedThreshold:parseInt(thresholdEl.value,10)/100})}),document.getElementById("clearHistory").addEventListener("click",async()=>{await showModal({title:Ytci18n.t("clearHistoryConfirmTitle"),desc:Ytci18n.t("clearHistoryConfirmDesc"),showInput:!1,confirmLabel:Ytci18n.t("clearBtn"),danger:!0})&&chrome.storage.local.set({watchedVideos:{}},()=>flash(Ytci18n.t("historyCleared")))}),document.getElementById("exportBtn").addEventListener("click",async()=>{const e=await chrome.storage.local.get(null);delete e.license;const t=new Blob([JSON.stringify(e,null,2)],{type:"application/json"}),n=URL.createObjectURL(t),l=document.createElement("a");l.href=n,l.download=`vidsieve-${(new Date).toISOString().slice(0,10)}.json`,l.click(),URL.revokeObjectURL(n),flash(Ytci18n.t("exported"))});const fileInput=document.getElementById("importFile");document.getElementById("importBtn").addEventListener("click",()=>fileInput.click());const IMPORT_SCHEMA={enabled:"boolean",hideSeen:"boolean",watchedMode:"string",watchedThreshold:"number",hideShorts:"boolean",hideLive:"boolean",hideUpcoming:"boolean",hidePremieres:"boolean",hideMembers:"boolean",hideFilterBar:"boolean",hideMixes:"boolean",hideDiscoveryShelf:"boolean",hidePlayablesShelf:"boolean",hideSubscriptionsAlgo:"boolean",homeFeedMode:"string",videosPerRow:"string",disableInfiniteScroll:"boolean",disableAutoplay:"boolean",hideRelated:"boolean",hideEndCards:"boolean",hideEndScreenFeed:"boolean",hideLiveChat:"boolean",hidePlaylistPanel:"boolean",hideChannelInfo:"boolean",hideDescription:"boolean",hideMerchShelf:"boolean",hideComments:"boolean",hideVideoActions:"boolean",hideAskButton:"boolean",hideSaveButton:"boolean",hideMoreActionsButton:"boolean",hideExploreSidebar:"boolean",hideSubscriptions:"boolean",hideShortsSidebar:"boolean",hideMoreFromYoutube:"boolean",hideNotifications:"boolean",hideVoiceSearch:"boolean",blurThumbnails:"boolean",hideProfilePhotos:"boolean",minDuration:"integer",maxDuration:"integer",minAgeDays:"integer",maxAgeDays:"integer",minViews:"integer",maxViews:"integer",dailyChannelLimit:"integer",keywords:"stringArray",blockedChannels:"stringArray",whitelistedChannels:"stringArray",favoriteFilters:"stringArray",watchedVideos:"stringNumberMap",hiddenCounts:"stringNumberMap",mutedChannels:"stringNumberMap",muteDefaultDays:"integer",profiles:"profileState"};function coerceProfileSettings(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t={};for(const n of YtcProfiles.KEYS){if(!(n in e))continue;const l=e[n];"keywords"!==n?"watchedMode"!==n?"homeFeedMode"!==n?"boolean"!=typeof l?"number"==typeof l&&Number.isFinite(l)&&(t[n]=l):t[n]=l:"show"!==l&&"blank"!==l&&"subscriptions"!==l&&"watchLater"!==l&&"library"!==l||(t[n]=l):"hide"!==l&&"dim"!==l&&"dryrun"!==l||(t[n]=l):Array.isArray(l)&&(t[n]=l.filter(e=>"string"==typeof e).slice(0,5e3))}return t}function coerceProfilesState(e){if(!e||"object"!=typeof e||Array.isArray(e))return;if(!e.items||"object"!=typeof e.items||Array.isArray(e.items))return;const t={};for(const[n,l]of Object.entries(e.items)){if("__proto__"===n||"constructor"===n||"prototype"===n)continue;if(!l||"object"!=typeof l)continue;const e=coerceProfileSettings(l.settings);e&&(t[n]={name:"string"==typeof l.name?l.name.slice(0,40):n,builtin:!!l.builtin,createdAt:Number.isFinite(l.createdAt)?l.createdAt:Date.now(),updatedAt:Number.isFinite(l.updatedAt)?l.updatedAt:Date.now(),settings:e})}return{schemaVersion:1,activeProfileId:"string"==typeof e.activeProfileId?e.activeProfileId:null,items:t}}const IMPORT_NUMBER_RANGES={dailyChannelLimit:[0,50],watchedThreshold:[0,1],muteDefaultDays:[1,365]};function coerce(e,t,n){switch(t){case"boolean":return"boolean"==typeof e?e:void 0;case"string":return"string"==typeof e?e:void 0;case"number":{const t=Number(e);if(!Number.isFinite(t))return;const l=IMPORT_NUMBER_RANGES[n];return l?Math.min(Math.max(t,l[0]),l[1]):t}case"integer":{const t=Number(e);if(!Number.isFinite(t))return;const l=Math.trunc(t),o=IMPORT_NUMBER_RANGES[n];return o?Math.min(Math.max(l,o[0]),o[1]):Math.max(l,0)}case"stringArray":return Array.isArray(e)?e.filter(e=>"string"==typeof e).slice(0,5e3):void 0;case"stringNumberMap":{if(!e||"object"!=typeof e||Array.isArray(e))return;const t=Object.create(null);let n=0;for(const[l,o]of Object.entries(e)){if(n>=2e4)break;if("string"!=typeof l)continue;if("__proto__"===l||"constructor"===l||"prototype"===l)continue;const e=Number(o);Number.isFinite(e)&&(t[l]=e,n++)}return t}case"profileState":return coerceProfilesState(e);default:return}}function sanitizeImport(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t={};for(const[n,l]of Object.entries(IMPORT_SCHEMA)){if(!(n in e))continue;const o=coerce(e[n],l,n);void 0!==o&&(t[n]=o)}return t}fileInput.addEventListener("change",async()=>{const e=fileInput.files?.[0];if(e)try{if(e.size>2097152)throw new Error("too large");const t=await e.text(),n=sanitizeImport(JSON.parse(t));if(!n||0===Object.keys(n).length)throw new Error("no keys");isReloadPending=!0,await chrome.storage.local.set(n),flash(Ytci18n.t("imported")),setTimeout(()=>location.reload(),600)}catch{flash(Ytci18n.t("invalidJson"))}});const modalOverlay=document.getElementById("modalOverlay"),modalTitleEl=document.getElementById("modalTitle"),modalDescEl=document.getElementById("modalDesc"),modalInputEl=document.getElementById("modalInput"),modalCancelBtn=document.getElementById("modalCancel"),modalConfirmBtn=document.getElementById("modalConfirm");let modalResolve=null;function closeModal(e){modalOverlay.hidden=!0,document.removeEventListener("keydown",onModalKeydown);const t=modalResolve;modalResolve=null,t?.(e)}function onModalKeydown(e){const t=!modalInputEl.hidden;"Escape"===e.key&&closeModal(!!t&&null),"Enter"===e.key&&t&&(e.preventDefault(),modalConfirmBtn.click())}function showModal({title:e,desc:t,showInput:n,inputValue:l,confirmLabel:o,danger:a}){return modalTitleEl.textContent=e,modalDescEl.textContent=t||"",modalInputEl.hidden=!n,modalInputEl.value=n?l??"":"",modalConfirmBtn.textContent=o,modalConfirmBtn.className=a?"btn-danger":"btn-primary",modalOverlay.hidden=!1,n?(modalInputEl.focus(),modalInputEl.select()):modalConfirmBtn.focus(),document.addEventListener("keydown",onModalKeydown),new Promise(e=>{modalResolve=e})}modalCancelBtn.addEventListener("click",()=>closeModal(!modalInputEl.hidden&&null)),modalConfirmBtn.addEventListener("click",()=>{modalInputEl.hidden?closeModal(!0):closeModal(modalInputEl.value)}),modalOverlay.addEventListener("click",e=>{e.target===modalOverlay&&closeModal(!modalInputEl.hidden&&null)});const profilesCard=document.getElementById("profilesCard"),BUILTIN_DESC_KEY={"preset-deep":"presetDeepDesc","preset-learning":"presetLearningDesc","preset-minimal":"presetMinimalDesc"},BUILTIN_DEFAULT_NAME_KEY={"preset-deep":"profileFocus","preset-learning":"profileStudy","preset-minimal":"profileLight"};function profileFilterCount(e){let t=0;for(const n of YtcProfiles.KEYS){const l=e[n];"boolean"!=typeof l?"number"!=typeof l?Array.isArray(l)&&l.length>0&&t++:l>0&&t++:l&&t++}return t}function closeAllProfileMenus(){document.querySelectorAll(".profile-menu-dropdown").forEach(e=>e.hidden=!0)}function goToProSection(){document.getElementById("pro")?.scrollIntoView({behavior:"smooth",block:"center"})}function buildEmptyProfileCard(e,t){const n=document.createElement("div");n.className="profile-card is-empty"+(t?"":" is-pro-locked"),n.dataset.id=e,n.setAttribute("role","button"),n.tabIndex=0;const l=document.createElement("span");l.className="profile-radio",l.setAttribute("aria-hidden","true"),n.appendChild(l);const o=document.createElement("div");o.className="profile-body";const a=document.createElement("div");a.className="profile-name-row";const i=document.createElement("div");if(i.className="profile-name",i.textContent=Ytci18n.t("profileEmptySlot"),a.appendChild(i),!t){const e=document.createElement("span");e.className="pro-badge",e.textContent=Ytci18n.t("proBadge"),a.appendChild(e)}o.appendChild(a);const d=document.createElement("div");async function c(){if(!t)return void goToProSection();const n=await showModal({title:Ytci18n.t("profileCreateTitle"),desc:Ytci18n.t("profileCreatePrompt"),showInput:!0,inputValue:"",confirmLabel:Ytci18n.t("modalSave")});if(null===n)return;(await YtcProfiles.saveCurrentToSlot(e,n)).error?flash(Ytci18n.t("profileNameRequired")):(flash(Ytci18n.t("profileCreated")),renderProfiles())}return d.className="profile-desc",d.textContent=Ytci18n.t("profileEmptySlotDesc"),o.appendChild(d),n.appendChild(o),n.addEventListener("click",c),n.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),c())}),n}function buildCustomProfilesHintCard(){const e=document.createElement("div");e.className="profile-card is-pro-locked is-hint",e.setAttribute("role","button"),e.tabIndex=0;const t=document.createElement("span");t.className="profile-radio",t.setAttribute("aria-hidden","true"),e.appendChild(t);const n=document.createElement("div");n.className="profile-body";const l=document.createElement("div");l.className="profile-name-row";const o=document.createElement("span");o.className="pro-badge",o.textContent=Ytci18n.t("proBadge"),l.appendChild(o);const a=document.createElement("span");a.className="profile-name",a.textContent=Ytci18n.t("profileLockedPillText"),l.appendChild(a),n.appendChild(l);const i=document.createElement("div");return i.className="profile-desc",i.textContent=Ytci18n.t("profileCustomHintDesc"),n.appendChild(i),e.appendChild(n),e.addEventListener("click",goToProSection),e.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),goToProSection())}),e}document.addEventListener("click",closeAllProfileMenus),document.addEventListener("click",e=>{e.target.closest(".card-row.is-pro-locked")&&goToProSection()});const MENU_ICON_PATHS={rename:"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25ZM20.71 7.04a1.003 1.003 0 0 0 0-1.42l-2.34-2.34a1.003 1.003 0 0 0-1.42 0l-1.83 1.83 3.75 3.75 1.84-1.82Z",schedule:"M17 12h-5v5h5v-5ZM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2Zm3 18H5V8h14v11Z",update:"M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35Z",delete:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12ZM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4Z",check:"M9 16.17L4.83 12l-1.41 1.41L9 19 21 7l-1.41-1.41z",lock:"M12 17a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2 2 2 0 0 0 2 2m6-9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2h1V6a5 5 0 0 1 5-5 5 5 0 0 1 5 5v2h-2V6a3 3 0 0 0-3-3 3 3 0 0 0-3 3v2z"},SVG_NS="http://www.w3.org/2000/svg";function buildIconSvg(e,t){const n=document.createElementNS(SVG_NS,"svg");n.setAttribute("class",t),n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("aria-hidden","true");const l=document.createElementNS(SVG_NS,"path");return l.setAttribute("d",MENU_ICON_PATHS[e]),n.appendChild(l),n}function buildMenuItem(e,t,n="profile-menu-item",l=!1){const o=document.createElement("button");o.type="button",o.className=n,o.appendChild(buildIconSvg(e,"profile-menu-item-icon"));const a=document.createElement("span");return a.className="profile-menu-item-label",a.textContent=t,o.appendChild(a),l&&o.appendChild(buildIconSvg("lock","profile-menu-item-lock")),o}function buildProfileCard(e,t,n,l,o){const a=!t.builtin&&!l,i=document.createElement("div");i.className="profile-card"+(n?" is-active":"")+(a?" is-pro-locked":""),i.dataset.id=e,i.setAttribute("role","radio"),i.setAttribute("aria-checked",n?"true":"false"),i.tabIndex=0;const d=document.createElement("span");d.className="profile-radio",d.setAttribute("aria-hidden","true"),n&&d.appendChild(buildIconSvg("check","profile-radio-check")),i.appendChild(d);const c=document.createElement("div");c.className="profile-body";const r=document.createElement("div");r.className="profile-name-row";const s=document.createElement("div");if(s.className="profile-name",s.textContent=t.name,s.title=t.name,r.appendChild(s),a){const e=document.createElement("span");e.className="pro-badge",e.textContent=Ytci18n.t("proBadge"),r.appendChild(e)}if(l&&o){const e=document.createElement("span");e.className="profile-schedule-badge",e.appendChild(buildIconSvg("schedule","profile-schedule-badge-icon"));const t=document.createElement("span");t.textContent=Ytci18n.t("scheduleBadge"),e.appendChild(t),r.appendChild(e)}c.appendChild(r);const u=BUILTIN_DESC_KEY[e]&&t.name===Ytci18n.t(BUILTIN_DEFAULT_NAME_KEY[e]),h=document.createElement("div");h.className="profile-desc",h.textContent=u?Ytci18n.t(BUILTIN_DESC_KEY[e]):`${profileFilterCount(t.settings)} ${Ytci18n.t("profileFilterCountSuffix")}`,h.title=h.textContent,c.appendChild(h),i.appendChild(c);const m=document.createElement("div");m.className="profile-menu";const f=document.createElement("button");f.type="button",f.className="kebab-btn",f.setAttribute("aria-label",Ytci18n.t("profileMenuLabel")),f.textContent="⋮",m.appendChild(f);const p=document.createElement("div");p.className="profile-menu-dropdown",p.hidden=!0;const E=!l,v=buildMenuItem("rename",Ytci18n.t("profileRenameBtn"),"profile-menu-item",E);v.addEventListener("click",async n=>{if(n.stopPropagation(),p.hidden=!0,!l)return void goToProSection();const o=await showModal({title:Ytci18n.t("profileRenameTitle"),desc:Ytci18n.t("profileRenamePrompt"),showInput:!0,inputValue:t.name,confirmLabel:Ytci18n.t("modalSave")});if(null===o)return;await YtcProfiles.rename(e,o)?(flash(Ytci18n.t("profileRenamed")),renderProfiles()):flash(Ytci18n.t("profileNameRequired"))}),p.appendChild(v);const g=buildMenuItem("schedule",Ytci18n.t("scheduleMenuItem"),"profile-menu-item",E);g.addEventListener("click",async n=>{n.stopPropagation(),p.hidden=!0,l?await openScheduleModal(e,t.name):goToProSection()}),p.appendChild(g);const y=buildMenuItem("update",Ytci18n.t("profileUpdateBtn"),"profile-menu-item",E);if(y.title=Ytci18n.t("profileUpdateHint"),y.addEventListener("click",async t=>{t.stopPropagation(),p.hidden=!0,l?(await YtcProfiles.updateFromCurrent(e),flash(Ytci18n.t("profileUpdated")),renderProfiles()):goToProSection()}),p.appendChild(y),!t.builtin){const t=document.createElement("hr");t.className="profile-menu-divider",p.appendChild(t);const n=buildMenuItem("delete",Ytci18n.t("profileDeleteBtn"),"profile-menu-item profile-menu-item-danger",E);n.addEventListener("click",async t=>{if(t.stopPropagation(),p.hidden=!0,!l)return void goToProSection();if(!await showModal({title:Ytci18n.t("profileDeleteTitle"),desc:Ytci18n.t("profileDeleteConfirm"),showInput:!1,confirmLabel:Ytci18n.t("profileDeleteBtn"),danger:!0}))return;await YtcProfiles.remove(e)?(await YtcSchedule.disableAndClear(e),flash(Ytci18n.t("profileDeleted")),renderProfiles()):renderProfiles()}),p.appendChild(n)}async function S(){a?goToProSection():n||await YtcProfiles.applyProfile(e)}return f.addEventListener("click",e=>{e.stopPropagation();const t=!p.hidden;closeAllProfileMenus(),p.hidden=t}),m.appendChild(p),i.appendChild(m),i.addEventListener("click",S),i.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||!a&&n||(e.preventDefault(),S())}),i}async function renderProfiles(){if(!profilesCard)return;const[e,t,n,l]=await Promise.all([YtcProfiles.getState(),YtcProfiles.currentSnapshot(),YtcLicense.isPro(),YtcSchedule.getState()]),o=YtcProfiles.findMatchingProfile(e,t);profilesCard.innerHTML="",YtcProfiles.BUILTIN_ORDER.forEach(t=>{const a=e.items[t];profilesCard.appendChild(buildProfileCard(t,a,t===o,n,l.items[t]?.enabled))}),n?YtcProfiles.CUSTOM_ORDER.forEach(t=>{const a=e.items[t];profilesCard.appendChild(a.empty?buildEmptyProfileCard(t,n):buildProfileCard(t,a,t===o,n,l.items[t]?.enabled))}):profilesCard.appendChild(buildCustomProfilesHintCard())}function profileColorVar(e){return"--profile-color-"+(YtcProfiles.orderedIds().indexOf(e)%6+1)}renderProfiles(),chrome.storage.onChanged.addListener(e=>{isReloadPending||(("profiles"in e||"license"in e||"schedules"in e||YtcProfiles.KEYS.some(t=>t in e))&&renderProfiles(),"license"in e&&renderLicense(),ALL_KEYS.some(t=>t in e)&&chrome.storage.local.get(ALL_KEYS,renderPrefsForm),!scheduleOverviewModalOverlay.hidden&&("schedules"in e||"profiles"in e||"license"in e)&&renderScheduleOverview())});const TIME_OPTIONS=(()=>{const e=[];for(let t=0;t<24;t++)for(const n of[0,30])e.push(`${String(t).padStart(2,"0")}:${String(n).padStart(2,"0")}`);return e})();function dayShortLabels(){const e=new Intl.DateTimeFormat(chrome.i18n.getUILanguage()||void 0,{weekday:"short"}),t=[];for(let n=0;n<7;n++)t.push(e.format(new Date(2024,0,1+n)));return t}const DAY_DISPLAY_ORDER=[6,0,1,2,3,4,5],scheduleModalOverlay=document.getElementById("scheduleModalOverlay"),scheduleModalDescEl=document.getElementById("scheduleModalDesc"),scheduleEnabledToggle=document.getElementById("scheduleEnabledToggle"),scheduleDayChipsEl=document.getElementById("scheduleDayChips"),scheduleAllDayToggle=document.getElementById("scheduleAllDayToggle"),scheduleRangesEl=document.getElementById("scheduleRanges"),scheduleAddRangeBtn=document.getElementById("scheduleAddRange"),scheduleValidationErrorEl=document.getElementById("scheduleValidationError"),scheduleConflictWarningEl=document.getElementById("scheduleConflictWarning"),scheduleModalCancelBtn=document.getElementById("scheduleModalCancel"),scheduleModalSaveBtn=document.getElementById("scheduleModalSave"),scheduleModalCloseBtn=document.getElementById("scheduleModalClose");let scheduleModalProfileId=null,scheduleDraft=null;function buildTimeSelect(e){const t=document.createElement("select");for(const n of TIME_OPTIONS){const l=document.createElement("option");l.value=n,l.textContent=n,n===e&&(l.selected=!0),t.appendChild(l)}return t}function renderScheduleDayChips(){const e=dayShortLabels();scheduleDayChipsEl.innerHTML="",DAY_DISPLAY_ORDER.forEach(t=>{const n=e[t],l=document.createElement("button");l.type="button",l.className="day-chip"+(scheduleDraft.days[t]?" is-on":""),l.textContent=n.slice(0,1).toUpperCase(),l.title=n,l.addEventListener("click",()=>{scheduleDraft.days[t]=!scheduleDraft.days[t],l.classList.toggle("is-on",scheduleDraft.days[t]),renderScheduleConflicts()}),scheduleDayChipsEl.appendChild(l)})}function renderScheduleRanges(){scheduleRangesEl.innerHTML="",scheduleRangesEl.hidden=scheduleDraft.allDay,scheduleAddRangeBtn.hidden=scheduleDraft.allDay,scheduleDraft.ranges.forEach((e,t)=>{const n=document.createElement("div");n.className="schedule-range-row";const l=buildTimeSelect(e.start);l.addEventListener("change",()=>{scheduleDraft.ranges[t].start=l.value,renderScheduleConflicts()});const o=document.createElement("span");o.className="schedule-range-sep",o.textContent=Ytci18n.t("scheduleRangeTo");const a=buildTimeSelect(e.end);if(a.addEventListener("change",()=>{scheduleDraft.ranges[t].end=a.value,renderScheduleConflicts()}),n.appendChild(l),n.appendChild(o),n.appendChild(a),scheduleDraft.ranges.length>1){const e=document.createElement("button");e.type="button",e.className="schedule-range-remove",e.setAttribute("aria-label",Ytci18n.t("scheduleRemoveRangeLabel")),e.textContent="×",e.addEventListener("click",()=>{scheduleDraft.ranges.splice(t,1),renderScheduleRanges(),renderScheduleConflicts()}),n.appendChild(e)}scheduleRangesEl.appendChild(n)})}function validateScheduleDraft(){const e=[];return scheduleDraft.enabled?(scheduleDraft.days.some(Boolean)||e.push(Ytci18n.t("scheduleErrorNoDays")),!scheduleDraft.allDay&&scheduleDraft.ranges.some(e=>e.start>=e.end)&&e.push(Ytci18n.t("scheduleErrorInvalidRange")),e):e}function renderScheduleValidation(){const e=validateScheduleDraft();scheduleValidationErrorEl.textContent=e.join(" "),scheduleValidationErrorEl.hidden=0===e.length,scheduleModalSaveBtn.disabled=e.length>0}let _scheduleConflictsToken=0;async function renderScheduleConflicts(){if(!scheduleModalProfileId)return;renderScheduleValidation();const e=++_scheduleConflictsToken,t=await YtcSchedule.getState();if(e!==_scheduleConflictsToken||!scheduleDraft)return;const n={...t,items:{...t.items,[scheduleModalProfileId]:scheduleDraft}},l=YtcProfiles.orderedIds(),o=YtcScheduler.findOverlaps(n,l).filter(e=>e.a===scheduleModalProfileId||e.b===scheduleModalProfileId);if(!scheduleDraft.enabled||0===o.length)return scheduleConflictWarningEl.hidden=!0,void(scheduleConflictWarningEl.textContent="");const a=await YtcProfiles.getState();if(e!==_scheduleConflictsToken||!scheduleDraft)return;const i=dayShortLabels(),d=o.map(e=>{const t=e.a===scheduleModalProfileId?e.b:e.a,n=e.a===scheduleModalProfileId?e.bRange:e.aRange,l=a.items[t]?.name||t;return Ytci18n.t("scheduleConflictWarning",{profile:l,day:i[e.day],range:`${n.start}–${n.end}`})});scheduleConflictWarningEl.textContent=d.join(" "),scheduleConflictWarningEl.hidden=!1}function renderScheduleModalDesc(e){const t=chrome.i18n.getMessage("scheduleModalDesc")||"Turn on {profile} automatically on a schedule.",[n,l=""]=t.split("{profile}");scheduleModalDescEl.textContent="",scheduleModalDescEl.appendChild(document.createTextNode(n));const o=document.createElement("span");o.className="schedule-modal-desc-profile",o.textContent=e,scheduleModalDescEl.appendChild(o),scheduleModalDescEl.appendChild(document.createTextNode(l))}async function openScheduleModal(e,t){scheduleModalProfileId=e;const n=(await YtcSchedule.getState()).items[e];scheduleDraft={enabled:n.enabled,days:[...n.days],allDay:n.allDay,ranges:n.ranges.map(e=>({...e}))},renderScheduleModalDesc(t),scheduleEnabledToggle.checked=scheduleDraft.enabled,scheduleAllDayToggle.checked=scheduleDraft.allDay,renderScheduleDayChips(),renderScheduleRanges(),await renderScheduleConflicts(),scheduleModalOverlay.hidden=!1,document.addEventListener("keydown",onScheduleModalKeydown)}function closeScheduleModal(){scheduleModalOverlay.hidden=!0,scheduleModalProfileId=null,scheduleDraft=null,document.removeEventListener("keydown",onScheduleModalKeydown)}function onScheduleModalKeydown(e){"Escape"===e.key&&closeScheduleModal()}scheduleEnabledToggle.addEventListener("change",()=>{scheduleDraft.enabled=scheduleEnabledToggle.checked,renderScheduleConflicts()}),scheduleAllDayToggle.addEventListener("change",()=>{scheduleDraft.allDay=scheduleAllDayToggle.checked,renderScheduleRanges(),renderScheduleConflicts()}),scheduleAddRangeBtn.addEventListener("click",()=>{scheduleDraft.ranges.push({start:"09:00",end:"17:00"}),renderScheduleRanges(),renderScheduleConflicts()}),scheduleModalCancelBtn.addEventListener("click",closeScheduleModal),scheduleModalCloseBtn.addEventListener("click",closeScheduleModal),scheduleModalOverlay.addEventListener("click",e=>{e.target===scheduleModalOverlay&&closeScheduleModal()}),scheduleModalSaveBtn.addEventListener("click",async()=>{if(!scheduleModalProfileId)return;if(validateScheduleDraft().length>0)return;if(!await YtcSchedule.save(scheduleModalProfileId,{enabled:scheduleDraft.enabled,days:scheduleDraft.days,allDay:scheduleDraft.allDay,ranges:scheduleDraft.ranges}))return closeScheduleModal(),void flash(Ytci18n.t("scheduleSaveFailed"));closeScheduleModal(),flash(Ytci18n.t("scheduleSaved")),await YtcSchedule.checkAndApply(),renderProfiles()});const scheduleOverviewOpenBtn=document.getElementById("scheduleOverviewOpenBtn"),scheduleOverviewModalOverlay=document.getElementById("scheduleOverviewModalOverlay"),scheduleOverviewModalCloseBtn=document.getElementById("scheduleOverviewModalClose"),scheduleOverviewBody=document.getElementById("scheduleOverviewBody");async function openScheduleOverviewModal(){scheduleOverviewModalOverlay.hidden=!1,document.addEventListener("keydown",onScheduleOverviewModalKeydown),await renderScheduleOverview()}function closeScheduleOverviewModal(){scheduleOverviewModalOverlay.hidden=!0,document.removeEventListener("keydown",onScheduleOverviewModalKeydown)}function onScheduleOverviewModalKeydown(e){"Escape"===e.key&&closeScheduleOverviewModal()}function buildScheduleOverviewUpsell(){const e={items:{"preset-deep":{name:Ytci18n.t("profileFocus")},"preset-learning":{name:Ytci18n.t("profileStudy")}}},t=new Date,n=document.createElement("div");n.className="schedule-overview-preview";const l=document.createElement("div");l.className="schedule-overview-preview-chart",l.setAttribute("aria-hidden","true"),l.appendChild(buildScheduleChart({enabledIds:["preset-deep","preset-learning"],schedulesState:{items:{"preset-deep":{days:{1:!0,2:!0,3:!0,4:!0,5:!0},allDay:!1,ranges:[{start:"09:00",end:"18:00"}]},"preset-learning":{days:{0:!0,6:!0},allDay:!1,ranges:[{start:"10:00",end:"14:00"}]}}},profilesState:e,todayIdx:YtcScheduler.dayIndex(t),nowPct:(60*t.getHours()+t.getMinutes())/1440*100,conflicts:[]})),n.appendChild(l);const o=document.createElement("div");o.className="schedule-overview-preview-overlay";const a=document.createElement("span");a.className="pro-badge",a.textContent=Ytci18n.t("proBadge"),o.appendChild(a);const i=document.createElement("p");i.className="schedule-overview-preview-msg",i.textContent=Ytci18n.t("scheduleOverviewPreviewMsg"),o.appendChild(i);const d=document.createElement("button");return d.type="button",d.className="btn-primary",d.textContent=Ytci18n.t("proCtaUpgrade"),d.addEventListener("click",()=>{closeScheduleOverviewModal(),goToProSection()}),o.appendChild(d),n.appendChild(o),n}function buildScheduleOverviewHourAxis(){const e=document.createElement("div");e.className="schedule-overview-axis";const t=document.createElement("span");t.className="schedule-overview-day-label",e.appendChild(t);const n=document.createElement("div");return n.className="schedule-overview-axis-track",[0,6,12,18,24].forEach(e=>{const t=document.createElement("span");t.textContent=String(e).padStart(2,"0")+"h",n.appendChild(t)}),e.appendChild(n),e}function buildScheduleChart({enabledIds:e,schedulesState:t,profilesState:n,todayIdx:l,nowPct:o,conflicts:a}){const i=document.createDocumentFragment(),d=dayShortLabels();i.appendChild(buildScheduleOverviewHourAxis());const c=document.createElement("div");c.className="schedule-overview-grid",DAY_DISPLAY_ORDER.forEach(i=>{const r=i===l,s=document.createElement("div");s.className="schedule-overview-row"+(r?" is-today":"");const u=document.createElement("span");u.className="schedule-overview-day-label",u.textContent=d[i],s.appendChild(u);const h=document.createElement("div");if(h.className="schedule-overview-track",[...e].reverse().forEach(e=>{const l=t.items[e];if(!l.days[i])return;const o=l.allDay?[{start:"00:00",end:"24:00"}]:l.ranges,d=a.some(t=>t.day===i&&(t.a===e||t.b===e));o.forEach(t=>{const[l,o]=t.start.split(":").map(Number),[a,i]=t.end.split(":").map(Number),c=(60*l+o)/1440*100,r=(60*a+i-(60*l+o))/1440*100,s=document.createElement("div");s.className="schedule-overview-segment"+(d?" has-conflict":""),s.style.left=`${c}%`,s.style.width=`${r}%`,s.style.background=`var(${profileColorVar(e)})`,s.title=`${n.items[e]?.name||e} — ${u.textContent} ${t.start}–${t.end}`,h.appendChild(s)})}),r){const e=document.createElement("div");e.className="schedule-overview-now-line",e.style.left=`${o}%`,h.appendChild(e)}s.appendChild(h),c.appendChild(s)}),i.appendChild(c);const r=document.createElement("div");if(r.className="schedule-overview-legend",e.forEach(e=>{const t=document.createElement("div");t.className="schedule-overview-legend-item";const l=document.createElement("span");l.className="schedule-overview-swatch",l.style.background=`var(${profileColorVar(e)})`,t.appendChild(l);const o=document.createElement("span");o.textContent=n.items[e]?.name||e,t.appendChild(o),r.appendChild(t)}),i.appendChild(r),a.length>0){const e=document.createElement("p");e.className="schedule-conflict-warning",e.textContent=Ytci18n.t("scheduleOverviewConflictHint"),i.appendChild(e)}return i}async function renderScheduleOverview(){if(!scheduleOverviewBody)return;const[e,t,n]=await Promise.all([YtcLicense.isPro(),YtcSchedule.getState(),YtcProfiles.getState()]);if(scheduleOverviewBody.innerHTML="",!e)return void scheduleOverviewBody.appendChild(buildScheduleOverviewUpsell());const l=YtcProfiles.orderedIds(),o=l.filter(e=>t.items[e]?.enabled);if(0===o.length){const e=document.createElement("div");return e.className="schedule-overview-empty",e.textContent=Ytci18n.t("scheduleOverviewEmpty"),void scheduleOverviewBody.appendChild(e)}const a=YtcScheduler.findOverlaps(t,l),i=new Date,d=YtcScheduler.dayIndex(i),c=(60*i.getHours()+i.getMinutes())/1440*100;scheduleOverviewBody.appendChild(buildScheduleChart({enabledIds:o,schedulesState:t,profilesState:n,todayIdx:d,nowPct:c,conflicts:a}))}scheduleOverviewOpenBtn.addEventListener("click",openScheduleOverviewModal),scheduleOverviewModalCloseBtn.addEventListener("click",closeScheduleOverviewModal),scheduleOverviewModalOverlay.addEventListener("click",e=>{e.target===scheduleOverviewModalOverlay&&closeScheduleOverviewModal()});const licenseSectionEl=document.getElementById("licenseSection"),licenseKeyInput=document.getElementById("licenseKeyInput"),licenseActivateBtn=document.getElementById("licenseActivateBtn"),licenseDeactivateBtn=document.getElementById("licenseDeactivateBtn"),licenseStatusEl=document.getElementById("licenseStatus"),proPitchEl=document.getElementById("proPitch"),proThanksEl=document.getElementById("proThanks"),headerCoffeeLinkEl=document.getElementById("headerCoffeeLink"),proCoffeeLinkEl=document.getElementById("proCoffeeLink");function setLicenseStatus(e,t){licenseStatusEl.textContent=e||"",licenseStatusEl.classList.toggle("is-error",!!t)}async function renderLicense(){const e=await YtcLicense.isPro();document.body.classList.toggle("is-pro",e),licenseSectionEl&&(licenseSectionEl.hidden=e),proPitchEl&&(proPitchEl.hidden=e),proThanksEl&&(proThanksEl.hidden=!e),headerCoffeeLinkEl&&(headerCoffeeLinkEl.hidden=!e),proCoffeeLinkEl&&(proCoffeeLinkEl.closest("p").hidden=!e),lockProInputs(e)}function lockProInputs(e){Object.keys(YtcLicense.PRO_KEYS).forEach(t=>{const n=document.getElementById(t)??document.getElementById(`${t}Tags`);if(!n)return;if(n.classList.contains("tag-input")){n.classList.toggle("is-locked",!e);const t=n.querySelector(".tag-input-field");t&&(t.disabled=!e),n.querySelectorAll(".tag-chip-remove").forEach(t=>t.disabled=!e)}else if(n.classList.contains("mute-panel")){n.classList.toggle("is-locked",!e);const t=n.querySelector(".mute-add-input");t&&(t.disabled=!e),n.querySelectorAll(".duration-chip").forEach(t=>t.disabled=!e)}else n.disabled=!e;const l=n.closest(".card-row");l&&l.classList.toggle("is-pro-locked",!e);const o=l?.querySelector(".fav-btn");o&&(o.disabled=!e)});const t=document.getElementById("modeDryRunOption");t&&(t.textContent=Ytci18n.t(e?"modeDryRun":"modeDryRunLocked"))}renderLicense();const LICENSE_ERROR_KEYS={network:"licenseErrorNetwork",empty:"licenseEmptyKey",rate_limited:"licenseErrorRateLimited",forbidden:"licenseErrorServer",server_misconfigured:"licenseErrorServer",upstream_unreachable:"licenseErrorServer",not_found:"licenseErrorServer",invalid_json:"licenseErrorServer"};function licenseErrorMessage(e){return Ytci18n.t(LICENSE_ERROR_KEYS[e]??"licenseErrorInvalid")}function isRowActive(e){const t=e.querySelector('input[type="checkbox"]');if(t)return t.checked;const n=e.querySelector("select");if(n)return n.value!==(DEFAULTS[n.id]??n.options[0]?.value);const l=e.querySelector('input[type="range"]');if(l)return Number(l.value)/100!==DEFAULTS[l.id];const o=e.querySelector('input[type="number"]');if(o)return""!==o.value&&0!==Number(o.value);const a=e.querySelector("textarea");if(a)return""!==a.value.trim();const i=e.querySelector(".tag-list");if(i)return i.children.length>0;const d=e.querySelector("#mutedChannelsList");return d?d.children.length>0:null}function initFilterSearch(){const e=document.getElementById("filterSearchInput"),t=document.getElementById("filterSearchClear"),n=document.getElementById("filterActiveOnlyBtn"),l=document.getElementById("filterSearchEmpty"),o=document.getElementById("filterSearchShortcut"),a=document.getElementById("profilesSection"),i=document.getElementById("proSection"),d=document.getElementById("licenseSection");if(!e)return;const c=[...document.querySelectorAll(".topic")].filter(e=>e.querySelector(".card-row"));let r=!1;function s(){const n=e.value.trim().toLowerCase(),o=n.length>0||r;if(t.hidden=0===n.length,document.body.classList.toggle("is-searching",o),a&&(a.hidden=o),i&&(i.hidden=o),d&&o&&(d.hidden=!0),!o)return c.forEach(e=>{e.hidden=!1,e.querySelectorAll(".branch").forEach(e=>e.hidden=!1),e.querySelectorAll(".card-row").forEach(e=>e.hidden=!1)}),l.hidden=!0,void renderLicense();const s=Ytci18n.t(n.length>0?"filterSearchEmpty":"filterActiveOnlyEmpty");l.textContent!==s&&(l.textContent=s);let u=!1;c.forEach(e=>{let t=!1;e.querySelectorAll(".branch").forEach(e=>{let l=!1;e.querySelectorAll(".card-row").forEach(e=>{const t=e.querySelector(".row-label")?.textContent??"",o=e.querySelector(".row-desc")?.textContent??"",a=0===n.length||`${t} ${o}`.toLowerCase().includes(n),i=!r||!1!==isRowActive(e),d=a&&i;e.hidden=!d,d&&(l=!0)}),e.hidden=!l,l&&(t=!0)}),e.hidden=!t,t&&(u=!0)}),l.hidden=u}if(e.addEventListener("input",s),t.addEventListener("click",()=>{e.value="",s(),e.focus()}),n){n.addEventListener("click",()=>{r=!r,n.setAttribute("aria-pressed",String(r)),s()});for(const e of c)e.addEventListener("change",()=>{r&&s()}),e.addEventListener("input",()=>{r&&s()});chrome.storage.onChanged.addListener(e=>{r&&0!==Object.keys(e).length&&chrome.storage.local.get(ALL_KEYS,e=>{renderPrefsForm(e),s()})})}if(document.addEventListener("keydown",t=>{(t.ctrlKey||t.metaKey)&&"k"===t.key.toLowerCase()&&(t.preventDefault(),e.focus(),e.select())}),o){const t=/Mac|iPod|iPhone|iPad/.test(navigator.platform||navigator.userAgentData?.platform||"");o.textContent=t?"⌘K":"Ctrl + K";const n=()=>{o.hidden=document.activeElement===e||e.value.length>0};e.addEventListener("focus",n),e.addEventListener("blur",n),e.addEventListener("input",n),n()}}licenseActivateBtn.addEventListener("click",async()=>{const e=licenseKeyInput.value.trim();if(!e)return void setLicenseStatus(Ytci18n.t("licenseEmptyKey"),!0);licenseActivateBtn.disabled=!0,setLicenseStatus(Ytci18n.t("licenseActivating"),!1);const t=await YtcLicense.activate(e);licenseActivateBtn.disabled=!1,t.ok?(licenseKeyInput.value="",setLicenseStatus(Ytci18n.t("licenseActivated"),!1),renderLicense()):setLicenseStatus(licenseErrorMessage(t.error),!0)}),licenseDeactivateBtn.addEventListener("click",async()=>{licenseDeactivateBtn.disabled=!0;try{if(!await showModal({title:Ytci18n.t("licenseDeactivateConfirmTitle"),desc:Ytci18n.t("licenseDeactivateConfirmDesc"),showInput:!1,confirmLabel:Ytci18n.t("licenseDeactivateBtn"),danger:!0}))return;if(!(await YtcLicense.deactivate()).ok)return void setLicenseStatus(Ytci18n.t("licenseErrorNetwork"),!0);setLicenseStatus("",!1),flash(Ytci18n.t("licenseDeactivated")),renderLicense()}finally{licenseDeactivateBtn.disabled=!1}}),initFilterSearch(),"#mutedChannelsSection"===location.hash&&document.getElementById("mutedChannelsSection")?.scrollIntoView({behavior:"smooth",block:"center"}),/firefox\//i.test(navigator.userAgent)&&document.getElementById("footerYtNote")?.setAttribute("data-i18n","footerYtNoteFirefox");
const status=document.getElementById("status"),THEMES=["auto","light","dark"],THEME_TITLE_KEY={auto:"themeAutoTitle",light:"themeLightTitle",dark:"themeDarkTitle"},THEME_LABEL_KEY={auto:"themeAuto",light:"themeLight",dark:"themeDark"};function applyTheme(e){"auto"===e?(document.documentElement.removeAttribute("data-theme"),localStorage.removeItem("theme")):(document.documentElement.setAttribute("data-theme",e),localStorage.setItem("theme",e));const t=document.getElementById("themeBtn");t&&(t.dataset.theme=e,t.title=Ytci18n.t(THEME_TITLE_KEY[e]));const n=document.getElementById("themeLabel");n&&(n.textContent=Ytci18n.t(THEME_LABEL_KEY[e]))}chrome.storage.local.get(["theme"],({theme:e="auto"})=>{applyTheme(THEMES.includes(e)?e:"auto")}),document.getElementById("themeBtn")?.addEventListener("click",async()=>{const{theme:e="auto"}=await chrome.storage.local.get(["theme"]),t=THEMES[(THEMES.indexOf(e)+1)%THEMES.length];await chrome.storage.local.set({theme:t}),applyTheme(t)}),chrome.storage.onChanged.addListener(e=>{"theme"in e&&applyTheme(e.theme.newValue||"auto")});let isReloadPending=!1;const MUTE_DEFAULT_DURATION_DAYS=14,MUTE_DAY_MS=864e5,BOOL_KEYS=["hideShorts","hideLive","hideUpcoming","hidePremieres","hideMembers","hideFilterBar","hideMixes","hideDiscoveryShelf","hidePlayablesShelf","hideSubscriptionsAlgo","hideSeen","disableAutoplay","hideRelated","hideEndCards","hideEndScreenFeed","hideLiveChat","hidePlaylistPanel","hideChannelInfo","hideDescription","hideMerchShelf","hideComments","hideVideoActions","hideAskButton","hideSaveButton","hideMoreActionsButton","hideExploreSidebar","hideSubscriptions","hideShortsSidebar","hideMoreFromYoutube","hideNotifications","hideVoiceSearch","blurThumbnails","hideProfilePhotos","disableInfiniteScroll"],NUM_KEYS=["minAgeDays","maxAgeDays","minViews","maxViews","dailyChannelLimit"],TEXTAREA_KEYS=["keywords"],TAG_KEYS=["blockedChannels","whitelistedChannels"],SELECT_KEYS=["watchedMode","homeFeedMode","videosPerRow"],DEFAULTS={hideSeen:!1,hideShorts:!0,hideMixes:!0,hideDiscoveryShelf:!1,hidePlayablesShelf:!0,hideSubscriptionsAlgo:!1,hideLive:!1,hideUpcoming:!1,hidePremieres:!1,hideMembers:!1,hideFilterBar:!1,homeFeedMode:"show",videosPerRow:"3",disableInfiniteScroll:!1,disableAutoplay:!1,hideRelated:!1,hideEndCards:!1,hideEndScreenFeed:!1,hideLiveChat:!1,hidePlaylistPanel:!1,hideChannelInfo:!1,hideDescription:!1,hideMerchShelf:!1,hideComments:!1,hideVideoActions:!1,hideAskButton:!1,hideSaveButton:!1,hideMoreActionsButton:!1,hideExploreSidebar:!1,hideSubscriptions:!1,hideShortsSidebar:!1,hideMoreFromYoutube:!1,hideNotifications:!1,hideVoiceSearch:!1,blurThumbnails:!1,hideProfilePhotos:!1,minDuration:0,maxDuration:0,minAgeDays:0,maxAgeDays:0,minViews:0,maxViews:0,dailyChannelLimit:0,watchedMode:"hide",watchedThreshold:.5,keywords:[],blockedChannels:[],whitelistedChannels:[],mutedChannels:{},muteDefaultDays:14},ALL_KEYS=[...BOOL_KEYS,...NUM_KEYS,...TEXTAREA_KEYS,...TAG_KEYS,...SELECT_KEYS,"watchedThreshold","minDuration","maxDuration","mutedChannels","muteDefaultDays"];let flashHideTimer=null,flashClearTimer=null;function flash(e){clearTimeout(flashHideTimer),clearTimeout(flashClearTimer),status.textContent=e,status.classList.add("is-visible");const t=Math.min(5e3,Math.max(1500,50*e.length));flashHideTimer=setTimeout(()=>{status.classList.remove("is-visible"),flashClearTimer=setTimeout(()=>status.textContent="",150)},t)}function renderPrefsForm(e){BOOL_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.checked=e[t]??DEFAULTS[t])}),NUM_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.value=e[t]??DEFAULTS[t])}),TEXTAREA_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.value=(e[t]??DEFAULTS[t]).join("\n"))}),TAG_KEYS.forEach(t=>{initTagInput(t,e[t]??DEFAULTS[t])}),initMutePanel(e.mutedChannels??DEFAULTS.mutedChannels,e.muteDefaultDays??DEFAULTS.muteDefaultDays),SELECT_KEYS.forEach(t=>{const n=document.getElementById(t);n&&(n.value=e[t]??DEFAULTS[t])});const t=100*(e.watchedThreshold??.5);document.getElementById("watchedThreshold").value=t,document.getElementById("thresholdValue").textContent=Math.round(t);const n=document.getElementById("minDuration");n&&(n.value=(e.minDuration??DEFAULTS.minDuration)/60);const l=document.getElementById("maxDuration");l&&(l.value=(e.maxDuration??DEFAULTS.maxDuration)/60)}chrome.storage.local.get(ALL_KEYS,renderPrefsForm),BOOL_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>chrome.storage.local.set({[e]:t.checked}))});const favButtons=[...document.querySelectorAll(".fav-btn")];function renderFavButtons(e){favButtons.forEach(t=>{t.classList.toggle("is-active",e.includes(t.dataset.fav))})}function clampToInputRange(e,t){const n=e.hasAttribute("min")?Number(e.min):-1/0,l=e.hasAttribute("max")?Number(e.max):1/0;return Math.min(Math.max(t,n),l)}chrome.storage.local.get(["favoriteFilters"],({favoriteFilters:e=[]})=>{renderFavButtons(e)}),favButtons.forEach(e=>{e.addEventListener("click",async()=>{const{favoriteFilters:t=[]}=await chrome.storage.local.get(["favoriteFilters"]),n=e.dataset.fav,l=t.includes(n)?t.filter(e=>e!==n):[...t,n];await chrome.storage.local.set({favoriteFilters:l}),renderFavButtons(l)})}),chrome.storage.onChanged.addListener(e=>{isReloadPending||e.favoriteFilters&&renderFavButtons(e.favoriteFilters.newValue??[])}),NUM_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>{const n=parseInt(t.value,10),l=clampToInputRange(t,isNaN(n)?0:n);t.value=l,chrome.storage.local.set({[e]:l})})}),["minDuration","maxDuration"].forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>{const n=parseFloat(t.value),l=clampToInputRange(t,isNaN(n)?0:n);t.value=l,chrome.storage.local.set({[e]:Math.round(60*l)})})});const CHANNEL_HANDLE_RX=/^@[A-Za-z0-9._-]{2,}$/;function initTagInput(e,t){const n=document.getElementById(`${e}Tags`);if(!n)return;if(n.__ytcTagInput)return void n.__ytcTagInput.setEntries(t);const l=n.querySelector(".tag-list"),o=n.querySelector(".tag-input-field");let a=[...t];function i(){chrome.storage.local.set({[e]:a})}function d(){const e=n.classList.contains("is-locked");l.replaceChildren();for(const t of a){const n=document.createElement("span");n.className="tag-chip";const o=document.createElement("span");o.className="tag-chip-label",o.textContent=t;const c=document.createElement("button");c.type="button",c.className="tag-chip-remove",c.disabled=e,c.setAttribute("aria-label",Ytci18n.t("removeChannelTag",{name:t})),c.textContent="×",c.addEventListener("click",()=>{a=a.filter(e=>e!==t),i(),d()}),n.append(o,c),l.appendChild(n)}}o.addEventListener("keydown",e=>{if("Enter"!==e.key)return;e.preventDefault();const t=o.value.trim();t&&(CHANNEL_HANDLE_RX.test(t)?(a.includes(t)||(a=[...a,t],i(),d()),o.value=""):flash(Ytci18n.t("invalidChannelHandle")))}),n.__ytcTagInput={setEntries(e){a=[...e],d()}},d()}function initMutePanel(e,t){const n=document.getElementById("mutedChannelsTags");if(!n)return;if(n.__ytcMutePanel)return n.__ytcMutePanel.setEntries(e),void n.__ytcMutePanel.setDurationDays(t);const l=document.getElementById("mutedChannelsTable"),o=document.getElementById("mutedChannelsRowsScroll"),a=document.getElementById("mutedChannelsList"),i=document.getElementById("mutedChannelsHead"),d=document.getElementById("mutedChannelsInput"),c=document.getElementById("mutedChannelsUnmuteAllBtn"),r=[...n.querySelectorAll(".duration-chip")];let s={...e},u=t??14;function h(){chrome.storage.local.set({mutedChannels:s})}function m(e,t){const n=Math.ceil((e-t)/864e5);return n<=1?{text:Ytci18n.t("mutedChannelsExpiresToday"),soon:!0}:{text:Ytci18n.t("mutedChannelsDaysLeft",{days:String(n)}),soon:!1}}function f(){const e=n.classList.contains("is-locked"),t=Date.now(),d=Object.entries(s).filter(([,e])=>e>t).sort((e,t)=>e[1]-t[1]);a.replaceChildren(),i.hidden=0===d.length,o.hidden=0===d.length,l.hidden=0===d.length,c.disabled=e;for(const[n,l]of d){const o=document.createElement("div");o.className="mute-row";const i=document.createElement("div");i.className="mute-name",i.textContent=n;const{text:d,soon:c}=m(l,t),r=document.createElement("span");r.className=c?"mute-countdown is-soon":"mute-countdown",r.textContent=d;const u=document.createElement("button");u.type="button",u.className="mute-unmute",u.textContent="×";const p=Ytci18n.t("mutedChannelsUnmute");u.setAttribute("aria-label",p),u.title=p,u.disabled=e,u.addEventListener("click",()=>{delete s[n],h(),f()}),o.append(i,r,u),a.appendChild(o)}}function p(e){u=e,r.forEach(t=>t.classList.toggle("is-on",Number(t.dataset.days)===e))}n.style.setProperty("--mute-scrollbar-w",o.offsetWidth-o.clientWidth+"px"),p(u),r.forEach(e=>{e.addEventListener("click",()=>{n.classList.contains("is-locked")||(p(Number(e.dataset.days)),chrome.storage.local.set({muteDefaultDays:u}))})}),d.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),function(){if(n.classList.contains("is-locked"))return;const e=d.value.trim();e&&(CHANNEL_HANDLE_RX.test(e)?(s={...s,[e]:Date.now()+864e5*u},h(),f(),d.value=""):flash(Ytci18n.t("invalidChannelHandle")))}())}),c.addEventListener("click",async()=>{if(n.classList.contains("is-locked"))return;await showModal({title:Ytci18n.t("mutedChannelsUnmuteAllConfirmTitle"),desc:Ytci18n.t("mutedChannelsUnmuteAllConfirmDesc"),showInput:!1,confirmLabel:Ytci18n.t("mutedChannelsUnmuteAll"),danger:!0})&&(s={},h(),f())}),n.__ytcMutePanel={setEntries(e){s={...e},f()},setDurationDays(e){"number"==typeof e&&p(e)}},f()}SELECT_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",async()=>{if("watchedMode"===e&&"dryrun"===t.value&&!await YtcDevice.isPro()){const{watchedMode:e}=await chrome.storage.local.get(["watchedMode"]);return t.value=e??DEFAULTS.watchedMode,void goToProSection()}chrome.storage.local.set({[e]:t.value})})}),TEXTAREA_KEYS.forEach(e=>{const t=document.getElementById(e);t&&t.addEventListener("change",()=>{const n=t.value.split("\n").map(e=>e.trim()).filter(Boolean);chrome.storage.local.set({[e]:n})})});const thresholdEl=document.getElementById("watchedThreshold"),thresholdValueEl=document.getElementById("thresholdValue");thresholdEl.addEventListener("input",()=>{thresholdValueEl.textContent=thresholdEl.value}),thresholdEl.addEventListener("change",()=>{chrome.storage.local.set({watchedThreshold:parseInt(thresholdEl.value,10)/100})}),document.getElementById("clearHistory").addEventListener("click",async()=>{await showModal({title:Ytci18n.t("clearHistoryConfirmTitle"),desc:Ytci18n.t("clearHistoryConfirmDesc"),showInput:!1,confirmLabel:Ytci18n.t("clearBtn"),danger:!0})&&chrome.storage.local.set({watchedVideos:{}},()=>flash(Ytci18n.t("historyCleared")))}),document.getElementById("exportBtn").addEventListener("click",async()=>{const e=await chrome.storage.local.get(null);delete e.device;const t=new Blob([JSON.stringify(e,null,2)],{type:"application/json"}),n=URL.createObjectURL(t),l=document.createElement("a");l.href=n,l.download=`vidsieve-${(new Date).toISOString().slice(0,10)}.json`,l.click(),URL.revokeObjectURL(n),flash(Ytci18n.t("exported"))});const fileInput=document.getElementById("importFile");document.getElementById("importBtn").addEventListener("click",()=>fileInput.click());const IMPORT_SCHEMA={enabled:"boolean",hideSeen:"boolean",watchedMode:"string",watchedThreshold:"number",hideShorts:"boolean",hideLive:"boolean",hideUpcoming:"boolean",hidePremieres:"boolean",hideMembers:"boolean",hideFilterBar:"boolean",hideMixes:"boolean",hideDiscoveryShelf:"boolean",hidePlayablesShelf:"boolean",hideSubscriptionsAlgo:"boolean",homeFeedMode:"string",videosPerRow:"string",disableInfiniteScroll:"boolean",disableAutoplay:"boolean",hideRelated:"boolean",hideEndCards:"boolean",hideEndScreenFeed:"boolean",hideLiveChat:"boolean",hidePlaylistPanel:"boolean",hideChannelInfo:"boolean",hideDescription:"boolean",hideMerchShelf:"boolean",hideComments:"boolean",hideVideoActions:"boolean",hideAskButton:"boolean",hideSaveButton:"boolean",hideMoreActionsButton:"boolean",hideExploreSidebar:"boolean",hideSubscriptions:"boolean",hideShortsSidebar:"boolean",hideMoreFromYoutube:"boolean",hideNotifications:"boolean",hideVoiceSearch:"boolean",blurThumbnails:"boolean",hideProfilePhotos:"boolean",minDuration:"integer",maxDuration:"integer",minAgeDays:"integer",maxAgeDays:"integer",minViews:"integer",maxViews:"integer",dailyChannelLimit:"integer",keywords:"stringArray",blockedChannels:"stringArray",whitelistedChannels:"stringArray",favoriteFilters:"stringArray",watchedVideos:"stringNumberMap",hiddenCounts:"stringNumberMap",mutedChannels:"stringNumberMap",muteDefaultDays:"integer",profiles:"profileState"};function coerceProfileSettings(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t={};for(const n of YtcProfiles.KEYS){if(!(n in e))continue;const l=e[n];"keywords"!==n?"watchedMode"!==n?"homeFeedMode"!==n?"boolean"!=typeof l?"number"==typeof l&&Number.isFinite(l)&&(t[n]=l):t[n]=l:"show"!==l&&"blank"!==l&&"subscriptions"!==l&&"watchLater"!==l&&"library"!==l||(t[n]=l):"hide"!==l&&"dim"!==l&&"dryrun"!==l||(t[n]=l):Array.isArray(l)&&(t[n]=l.filter(e=>"string"==typeof e).slice(0,5e3))}return t}function coerceProfilesState(e){if(!e||"object"!=typeof e||Array.isArray(e))return;if(!e.items||"object"!=typeof e.items||Array.isArray(e.items))return;const t={};for(const[n,l]of Object.entries(e.items)){if("__proto__"===n||"constructor"===n||"prototype"===n)continue;if(!l||"object"!=typeof l)continue;const e=coerceProfileSettings(l.settings);e&&(t[n]={name:"string"==typeof l.name?l.name.slice(0,40):n,builtin:!!l.builtin,createdAt:Number.isFinite(l.createdAt)?l.createdAt:Date.now(),updatedAt:Number.isFinite(l.updatedAt)?l.updatedAt:Date.now(),settings:e})}return{schemaVersion:1,activeProfileId:"string"==typeof e.activeProfileId?e.activeProfileId:null,items:t}}const IMPORT_NUMBER_RANGES={dailyChannelLimit:[0,50],watchedThreshold:[0,1],muteDefaultDays:[1,365]};function coerce(e,t,n){switch(t){case"boolean":return"boolean"==typeof e?e:void 0;case"string":return"string"==typeof e?e:void 0;case"number":{const t=Number(e);if(!Number.isFinite(t))return;const l=IMPORT_NUMBER_RANGES[n];return l?Math.min(Math.max(t,l[0]),l[1]):t}case"integer":{const t=Number(e);if(!Number.isFinite(t))return;const l=Math.trunc(t),o=IMPORT_NUMBER_RANGES[n];return o?Math.min(Math.max(l,o[0]),o[1]):Math.max(l,0)}case"stringArray":return Array.isArray(e)?e.filter(e=>"string"==typeof e).slice(0,5e3):void 0;case"stringNumberMap":{if(!e||"object"!=typeof e||Array.isArray(e))return;const t=Object.create(null);let n=0;for(const[l,o]of Object.entries(e)){if(n>=2e4)break;if("string"!=typeof l)continue;if("__proto__"===l||"constructor"===l||"prototype"===l)continue;const e=Number(o);Number.isFinite(e)&&(t[l]=e,n++)}return t}case"profileState":return coerceProfilesState(e);default:return}}function sanitizeImport(e){if(!e||"object"!=typeof e||Array.isArray(e))return null;const t={};for(const[n,l]of Object.entries(IMPORT_SCHEMA)){if(!(n in e))continue;const o=coerce(e[n],l,n);void 0!==o&&(t[n]=o)}return t}fileInput.addEventListener("change",async()=>{const e=fileInput.files?.[0];if(e)try{if(e.size>2097152)throw new Error("too large");const t=await e.text(),n=sanitizeImport(JSON.parse(t));if(!n||0===Object.keys(n).length)throw new Error("no keys");isReloadPending=!0,await chrome.storage.local.set(n),flash(Ytci18n.t("imported")),setTimeout(()=>location.reload(),600)}catch{flash(Ytci18n.t("invalidJson"))}});const modalOverlay=document.getElementById("modalOverlay"),modalTitleEl=document.getElementById("modalTitle"),modalDescEl=document.getElementById("modalDesc"),modalInputEl=document.getElementById("modalInput"),modalCancelBtn=document.getElementById("modalCancel"),modalConfirmBtn=document.getElementById("modalConfirm");let modalResolve=null;function closeModal(e){modalOverlay.hidden=!0,document.removeEventListener("keydown",onModalKeydown);const t=modalResolve;modalResolve=null,t?.(e)}function onModalKeydown(e){const t=!modalInputEl.hidden;"Escape"===e.key&&closeModal(!!t&&null),"Enter"===e.key&&t&&(e.preventDefault(),modalConfirmBtn.click())}function showModal({title:e,desc:t,showInput:n,inputValue:l,confirmLabel:o,danger:a}){return modalTitleEl.textContent=e,modalDescEl.textContent=t||"",modalInputEl.hidden=!n,modalInputEl.value=n?l??"":"",modalConfirmBtn.textContent=o,modalConfirmBtn.className=a?"btn-danger":"btn-primary",modalOverlay.hidden=!1,n?(modalInputEl.focus(),modalInputEl.select()):modalConfirmBtn.focus(),document.addEventListener("keydown",onModalKeydown),new Promise(e=>{modalResolve=e})}modalCancelBtn.addEventListener("click",()=>closeModal(!modalInputEl.hidden&&null)),modalConfirmBtn.addEventListener("click",()=>{modalInputEl.hidden?closeModal(!0):closeModal(modalInputEl.value)}),modalOverlay.addEventListener("click",e=>{e.target===modalOverlay&&closeModal(!modalInputEl.hidden&&null)});const profilesCard=document.getElementById("profilesCard"),BUILTIN_DESC_KEY={"preset-deep":"presetDeepDesc","preset-learning":"presetLearningDesc","preset-minimal":"presetMinimalDesc"},BUILTIN_DEFAULT_NAME_KEY={"preset-deep":"profileFocus","preset-learning":"profileStudy","preset-minimal":"profileLight"};function profileFilterCount(e){let t=0;for(const n of YtcProfiles.KEYS){const l=e[n];"boolean"!=typeof l?"number"!=typeof l?Array.isArray(l)&&l.length>0&&t++:l>0&&t++:l&&t++}return t}function closeAllProfileMenus(){document.querySelectorAll(".profile-menu-dropdown").forEach(e=>e.hidden=!0)}function goToProSection(){document.getElementById("pro")?.scrollIntoView({behavior:"smooth",block:"center"})}function buildEmptyProfileCard(e,t){const n=document.createElement("div");n.className="profile-card is-empty"+(t?"":" is-pro-locked"),n.dataset.id=e,n.setAttribute("role","button"),n.tabIndex=0;const l=document.createElement("span");l.className="profile-radio",l.setAttribute("aria-hidden","true"),n.appendChild(l);const o=document.createElement("div");o.className="profile-body";const a=document.createElement("div");a.className="profile-name-row";const i=document.createElement("div");if(i.className="profile-name",i.textContent=Ytci18n.t("profileEmptySlot"),a.appendChild(i),!t){const e=document.createElement("span");e.className="pro-badge",e.textContent=Ytci18n.t("proBadge"),a.appendChild(e)}o.appendChild(a);const d=document.createElement("div");async function c(){if(!t)return void goToProSection();const n=await showModal({title:Ytci18n.t("profileCreateTitle"),desc:Ytci18n.t("profileCreatePrompt"),showInput:!0,inputValue:"",confirmLabel:Ytci18n.t("modalSave")});if(null===n)return;(await YtcProfiles.saveCurrentToSlot(e,n)).error?flash(Ytci18n.t("profileNameRequired")):(flash(Ytci18n.t("profileCreated")),renderProfiles())}return d.className="profile-desc",d.textContent=Ytci18n.t("profileEmptySlotDesc"),o.appendChild(d),n.appendChild(o),n.addEventListener("click",c),n.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),c())}),n}function buildCustomProfilesHintCard(){const e=document.createElement("div");e.className="profile-card is-pro-locked is-hint",e.setAttribute("role","button"),e.tabIndex=0;const t=document.createElement("span");t.className="profile-radio",t.setAttribute("aria-hidden","true"),e.appendChild(t);const n=document.createElement("div");n.className="profile-body";const l=document.createElement("div");l.className="profile-name-row";const o=document.createElement("span");o.className="pro-badge",o.textContent=Ytci18n.t("proBadge"),l.appendChild(o);const a=document.createElement("span");a.className="profile-name",a.textContent=Ytci18n.t("profileLockedPillText"),l.appendChild(a),n.appendChild(l);const i=document.createElement("div");return i.className="profile-desc",i.textContent=Ytci18n.t("profileCustomHintDesc"),n.appendChild(i),e.appendChild(n),e.addEventListener("click",goToProSection),e.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),goToProSection())}),e}document.addEventListener("click",closeAllProfileMenus),document.addEventListener("click",e=>{e.target.closest(".card-row.is-pro-locked")&&goToProSection()});const MENU_ICON_PATHS={rename:"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25ZM20.71 7.04a1.003 1.003 0 0 0 0-1.42l-2.34-2.34a1.003 1.003 0 0 0-1.42 0l-1.83 1.83 3.75 3.75 1.84-1.82Z",schedule:"M17 12h-5v5h5v-5ZM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2Zm3 18H5V8h14v11Z",update:"M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35Z",delete:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12ZM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4Z",check:"M9 16.17L4.83 12l-1.41 1.41L9 19 21 7l-1.41-1.41z",lock:"M12 17a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2 2 2 0 0 0 2 2m6-9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2h1V6a5 5 0 0 1 5-5 5 5 0 0 1 5 5v2h-2V6a3 3 0 0 0-3-3 3 3 0 0 0-3 3v2z"},SVG_NS="http://www.w3.org/2000/svg";function buildIconSvg(e,t){const n=document.createElementNS(SVG_NS,"svg");n.setAttribute("class",t),n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("aria-hidden","true");const l=document.createElementNS(SVG_NS,"path");return l.setAttribute("d",MENU_ICON_PATHS[e]),n.appendChild(l),n}function buildMenuItem(e,t,n="profile-menu-item",l=!1){const o=document.createElement("button");o.type="button",o.className=n,o.appendChild(buildIconSvg(e,"profile-menu-item-icon"));const a=document.createElement("span");return a.className="profile-menu-item-label",a.textContent=t,o.appendChild(a),l&&o.appendChild(buildIconSvg("lock","profile-menu-item-lock")),o}function buildProfileCard(e,t,n,l,o){const a=!t.builtin&&!l,i=document.createElement("div");i.className="profile-card"+(n?" is-active":"")+(a?" is-pro-locked":""),i.dataset.id=e,i.setAttribute("role","radio"),i.setAttribute("aria-checked",n?"true":"false"),i.tabIndex=0;const d=document.createElement("span");d.className="profile-radio",d.setAttribute("aria-hidden","true"),n&&d.appendChild(buildIconSvg("check","profile-radio-check")),i.appendChild(d);const c=document.createElement("div");c.className="profile-body";const r=document.createElement("div");r.className="profile-name-row";const s=document.createElement("div");if(s.className="profile-name",s.textContent=t.name,s.title=t.name,r.appendChild(s),a){const e=document.createElement("span");e.className="pro-badge",e.textContent=Ytci18n.t("proBadge"),r.appendChild(e)}if(l&&o){const e=document.createElement("span");e.className="profile-schedule-badge",e.appendChild(buildIconSvg("schedule","profile-schedule-badge-icon"));const t=document.createElement("span");t.textContent=Ytci18n.t("scheduleBadge"),e.appendChild(t),r.appendChild(e)}c.appendChild(r);const u=BUILTIN_DESC_KEY[e]&&t.name===Ytci18n.t(BUILTIN_DEFAULT_NAME_KEY[e]),h=document.createElement("div");h.className="profile-desc",h.textContent=u?Ytci18n.t(BUILTIN_DESC_KEY[e]):`${profileFilterCount(t.settings)} ${Ytci18n.t("profileFilterCountSuffix")}`,h.title=h.textContent,c.appendChild(h),i.appendChild(c);const m=document.createElement("div");m.className="profile-menu";const f=document.createElement("button");f.type="button",f.className="kebab-btn",f.setAttribute("aria-label",Ytci18n.t("profileMenuLabel")),f.textContent="⋮",m.appendChild(f);const p=document.createElement("div");p.className="profile-menu-dropdown",p.hidden=!0;const E=!l,v=buildMenuItem("rename",Ytci18n.t("profileRenameBtn"),"profile-menu-item",E);v.addEventListener("click",async n=>{if(n.stopPropagation(),p.hidden=!0,!l)return void goToProSection();const o=await showModal({title:Ytci18n.t("profileRenameTitle"),desc:Ytci18n.t("profileRenamePrompt"),showInput:!0,inputValue:t.name,confirmLabel:Ytci18n.t("modalSave")});if(null===o)return;await YtcProfiles.rename(e,o)?(flash(Ytci18n.t("profileRenamed")),renderProfiles()):flash(Ytci18n.t("profileNameRequired"))}),p.appendChild(v);const g=buildMenuItem("schedule",Ytci18n.t("scheduleMenuItem"),"profile-menu-item",E);g.addEventListener("click",async n=>{n.stopPropagation(),p.hidden=!0,l?await openScheduleModal(e,t.name):goToProSection()}),p.appendChild(g);const y=buildMenuItem("update",Ytci18n.t("profileUpdateBtn"),"profile-menu-item",E);if(y.title=Ytci18n.t("profileUpdateHint"),y.addEventListener("click",async t=>{t.stopPropagation(),p.hidden=!0,l?(await YtcProfiles.updateFromCurrent(e),flash(Ytci18n.t("profileUpdated")),renderProfiles()):goToProSection()}),p.appendChild(y),!t.builtin){const t=document.createElement("hr");t.className="profile-menu-divider",p.appendChild(t);const n=buildMenuItem("delete",Ytci18n.t("profileDeleteBtn"),"profile-menu-item profile-menu-item-danger",E);n.addEventListener("click",async t=>{if(t.stopPropagation(),p.hidden=!0,!l)return void goToProSection();if(!await showModal({title:Ytci18n.t("profileDeleteTitle"),desc:Ytci18n.t("profileDeleteConfirm"),showInput:!1,confirmLabel:Ytci18n.t("profileDeleteBtn"),danger:!0}))return;await YtcProfiles.remove(e)?(await YtcSchedule.disableAndClear(e),flash(Ytci18n.t("profileDeleted")),renderProfiles()):renderProfiles()}),p.appendChild(n)}async function S(){a?goToProSection():n||await YtcProfiles.applyProfile(e)}return f.addEventListener("click",e=>{e.stopPropagation();const t=!p.hidden;closeAllProfileMenus(),p.hidden=t}),m.appendChild(p),i.appendChild(m),i.addEventListener("click",S),i.addEventListener("keydown",e=>{"Enter"!==e.key&&" "!==e.key||!a&&n||(e.preventDefault(),S())}),i}async function renderProfiles(){if(!profilesCard)return;const[e,t,n,l]=await Promise.all([YtcProfiles.getState(),YtcProfiles.currentSnapshot(),YtcDevice.isPro(),YtcSchedule.getState()]),o=YtcProfiles.findMatchingProfile(e,t);profilesCard.innerHTML="",YtcProfiles.BUILTIN_ORDER.forEach(t=>{const a=e.items[t];profilesCard.appendChild(buildProfileCard(t,a,t===o,n,l.items[t]?.enabled))}),n?YtcProfiles.CUSTOM_ORDER.forEach(t=>{const a=e.items[t];profilesCard.appendChild(a.empty?buildEmptyProfileCard(t,n):buildProfileCard(t,a,t===o,n,l.items[t]?.enabled))}):profilesCard.appendChild(buildCustomProfilesHintCard())}function profileColorVar(e){return"--profile-color-"+(YtcProfiles.orderedIds().indexOf(e)%6+1)}renderProfiles(),chrome.storage.onChanged.addListener(e=>{isReloadPending||(("profiles"in e||"device"in e||"schedules"in e||YtcProfiles.KEYS.some(t=>t in e))&&renderProfiles(),"device"in e&&renderLicense(),ALL_KEYS.some(t=>t in e)&&chrome.storage.local.get(ALL_KEYS,renderPrefsForm),!scheduleOverviewModalOverlay.hidden&&("schedules"in e||"profiles"in e||"device"in e)&&renderScheduleOverview())});const TIME_OPTIONS=(()=>{const e=[];for(let t=0;t<24;t++)for(const n of[0,30])e.push(`${String(t).padStart(2,"0")}:${String(n).padStart(2,"0")}`);return e})();function dayShortLabels(){const e=new Intl.DateTimeFormat(chrome.i18n.getUILanguage()||void 0,{weekday:"short"}),t=[];for(let n=0;n<7;n++)t.push(e.format(new Date(2024,0,1+n)));return t}const DAY_DISPLAY_ORDER=[6,0,1,2,3,4,5],scheduleModalOverlay=document.getElementById("scheduleModalOverlay"),scheduleModalDescEl=document.getElementById("scheduleModalDesc"),scheduleEnabledToggle=document.getElementById("scheduleEnabledToggle"),scheduleDayChipsEl=document.getElementById("scheduleDayChips"),scheduleAllDayToggle=document.getElementById("scheduleAllDayToggle"),scheduleRangesEl=document.getElementById("scheduleRanges"),scheduleAddRangeBtn=document.getElementById("scheduleAddRange"),scheduleValidationErrorEl=document.getElementById("scheduleValidationError"),scheduleConflictWarningEl=document.getElementById("scheduleConflictWarning"),scheduleModalCancelBtn=document.getElementById("scheduleModalCancel"),scheduleModalSaveBtn=document.getElementById("scheduleModalSave"),scheduleModalCloseBtn=document.getElementById("scheduleModalClose");let scheduleModalProfileId=null,scheduleDraft=null;function buildTimeSelect(e){const t=document.createElement("select");for(const n of TIME_OPTIONS){const l=document.createElement("option");l.value=n,l.textContent=n,n===e&&(l.selected=!0),t.appendChild(l)}return t}function renderScheduleDayChips(){const e=dayShortLabels();scheduleDayChipsEl.innerHTML="",DAY_DISPLAY_ORDER.forEach(t=>{const n=e[t],l=document.createElement("button");l.type="button",l.className="day-chip"+(scheduleDraft.days[t]?" is-on":""),l.textContent=n.slice(0,1).toUpperCase(),l.title=n,l.addEventListener("click",()=>{scheduleDraft.days[t]=!scheduleDraft.days[t],l.classList.toggle("is-on",scheduleDraft.days[t]),renderScheduleConflicts()}),scheduleDayChipsEl.appendChild(l)})}function renderScheduleRanges(){scheduleRangesEl.innerHTML="",scheduleRangesEl.hidden=scheduleDraft.allDay,scheduleAddRangeBtn.hidden=scheduleDraft.allDay,scheduleDraft.ranges.forEach((e,t)=>{const n=document.createElement("div");n.className="schedule-range-row";const l=buildTimeSelect(e.start);l.addEventListener("change",()=>{scheduleDraft.ranges[t].start=l.value,renderScheduleConflicts()});const o=document.createElement("span");o.className="schedule-range-sep",o.textContent=Ytci18n.t("scheduleRangeTo");const a=buildTimeSelect(e.end);if(a.addEventListener("change",()=>{scheduleDraft.ranges[t].end=a.value,renderScheduleConflicts()}),n.appendChild(l),n.appendChild(o),n.appendChild(a),scheduleDraft.ranges.length>1){const e=document.createElement("button");e.type="button",e.className="schedule-range-remove",e.setAttribute("aria-label",Ytci18n.t("scheduleRemoveRangeLabel")),e.textContent="×",e.addEventListener("click",()=>{scheduleDraft.ranges.splice(t,1),renderScheduleRanges(),renderScheduleConflicts()}),n.appendChild(e)}scheduleRangesEl.appendChild(n)})}function validateScheduleDraft(){const e=[];return scheduleDraft.enabled?(scheduleDraft.days.some(Boolean)||e.push(Ytci18n.t("scheduleErrorNoDays")),!scheduleDraft.allDay&&scheduleDraft.ranges.some(e=>e.start>=e.end)&&e.push(Ytci18n.t("scheduleErrorInvalidRange")),e):e}function renderScheduleValidation(){const e=validateScheduleDraft();scheduleValidationErrorEl.textContent=e.join(" "),scheduleValidationErrorEl.hidden=0===e.length,scheduleModalSaveBtn.disabled=e.length>0}let _scheduleConflictsToken=0;async function renderScheduleConflicts(){if(!scheduleModalProfileId)return;renderScheduleValidation();const e=++_scheduleConflictsToken,t=await YtcSchedule.getState();if(e!==_scheduleConflictsToken||!scheduleDraft)return;const n={...t,items:{...t.items,[scheduleModalProfileId]:scheduleDraft}},l=YtcProfiles.orderedIds(),o=YtcScheduler.findOverlaps(n,l).filter(e=>e.a===scheduleModalProfileId||e.b===scheduleModalProfileId);if(!scheduleDraft.enabled||0===o.length)return scheduleConflictWarningEl.hidden=!0,void(scheduleConflictWarningEl.textContent="");const a=await YtcProfiles.getState();if(e!==_scheduleConflictsToken||!scheduleDraft)return;const i=dayShortLabels(),d=o.map(e=>{const t=e.a===scheduleModalProfileId?e.b:e.a,n=e.a===scheduleModalProfileId?e.bRange:e.aRange,l=a.items[t]?.name||t;return Ytci18n.t("scheduleConflictWarning",{profile:l,day:i[e.day],range:`${n.start}–${n.end}`})});scheduleConflictWarningEl.textContent=d.join(" "),scheduleConflictWarningEl.hidden=!1}function renderScheduleModalDesc(e){const t=chrome.i18n.getMessage("scheduleModalDesc")||"Turn on {profile} automatically on a schedule.",[n,l=""]=t.split("{profile}");scheduleModalDescEl.textContent="",scheduleModalDescEl.appendChild(document.createTextNode(n));const o=document.createElement("span");o.className="schedule-modal-desc-profile",o.textContent=e,scheduleModalDescEl.appendChild(o),scheduleModalDescEl.appendChild(document.createTextNode(l))}async function openScheduleModal(e,t){scheduleModalProfileId=e;const n=(await YtcSchedule.getState()).items[e];scheduleDraft={enabled:n.enabled,days:[...n.days],allDay:n.allDay,ranges:n.ranges.map(e=>({...e}))},renderScheduleModalDesc(t),scheduleEnabledToggle.checked=scheduleDraft.enabled,scheduleAllDayToggle.checked=scheduleDraft.allDay,renderScheduleDayChips(),renderScheduleRanges(),await renderScheduleConflicts(),scheduleModalOverlay.hidden=!1,document.addEventListener("keydown",onScheduleModalKeydown)}function closeScheduleModal(){scheduleModalOverlay.hidden=!0,scheduleModalProfileId=null,scheduleDraft=null,document.removeEventListener("keydown",onScheduleModalKeydown)}function onScheduleModalKeydown(e){"Escape"===e.key&&closeScheduleModal()}scheduleEnabledToggle.addEventListener("change",()=>{scheduleDraft.enabled=scheduleEnabledToggle.checked,renderScheduleConflicts()}),scheduleAllDayToggle.addEventListener("change",()=>{scheduleDraft.allDay=scheduleAllDayToggle.checked,renderScheduleRanges(),renderScheduleConflicts()}),scheduleAddRangeBtn.addEventListener("click",()=>{scheduleDraft.ranges.push({start:"09:00",end:"17:00"}),renderScheduleRanges(),renderScheduleConflicts()}),scheduleModalCancelBtn.addEventListener("click",closeScheduleModal),scheduleModalCloseBtn.addEventListener("click",closeScheduleModal),scheduleModalOverlay.addEventListener("click",e=>{e.target===scheduleModalOverlay&&closeScheduleModal()}),scheduleModalSaveBtn.addEventListener("click",async()=>{if(!scheduleModalProfileId)return;if(validateScheduleDraft().length>0)return;if(!await YtcSchedule.save(scheduleModalProfileId,{enabled:scheduleDraft.enabled,days:scheduleDraft.days,allDay:scheduleDraft.allDay,ranges:scheduleDraft.ranges}))return closeScheduleModal(),void flash(Ytci18n.t("scheduleSaveFailed"));closeScheduleModal(),flash(Ytci18n.t("scheduleSaved")),await YtcSchedule.checkAndApply(),renderProfiles()});const scheduleOverviewOpenBtn=document.getElementById("scheduleOverviewOpenBtn"),scheduleOverviewModalOverlay=document.getElementById("scheduleOverviewModalOverlay"),scheduleOverviewModalCloseBtn=document.getElementById("scheduleOverviewModalClose"),scheduleOverviewBody=document.getElementById("scheduleOverviewBody");async function openScheduleOverviewModal(){scheduleOverviewModalOverlay.hidden=!1,document.addEventListener("keydown",onScheduleOverviewModalKeydown),await renderScheduleOverview()}function closeScheduleOverviewModal(){scheduleOverviewModalOverlay.hidden=!0,document.removeEventListener("keydown",onScheduleOverviewModalKeydown)}function onScheduleOverviewModalKeydown(e){"Escape"===e.key&&closeScheduleOverviewModal()}function buildScheduleOverviewUpsell(){const e={items:{"preset-deep":{name:Ytci18n.t("profileFocus")},"preset-learning":{name:Ytci18n.t("profileStudy")}}},t=new Date,n=document.createElement("div");n.className="schedule-overview-preview";const l=document.createElement("div");l.className="schedule-overview-preview-chart",l.setAttribute("aria-hidden","true"),l.appendChild(buildScheduleChart({enabledIds:["preset-deep","preset-learning"],schedulesState:{items:{"preset-deep":{days:{1:!0,2:!0,3:!0,4:!0,5:!0},allDay:!1,ranges:[{start:"09:00",end:"18:00"}]},"preset-learning":{days:{0:!0,6:!0},allDay:!1,ranges:[{start:"10:00",end:"14:00"}]}}},profilesState:e,todayIdx:YtcScheduler.dayIndex(t),nowPct:(60*t.getHours()+t.getMinutes())/1440*100,conflicts:[]})),n.appendChild(l);const o=document.createElement("div");o.className="schedule-overview-preview-overlay";const a=document.createElement("span");a.className="pro-badge",a.textContent=Ytci18n.t("proBadge"),o.appendChild(a);const i=document.createElement("p");i.className="schedule-overview-preview-msg",i.textContent=Ytci18n.t("scheduleOverviewPreviewMsg"),o.appendChild(i);const d=document.createElement("button");return d.type="button",d.className="btn-primary",d.textContent=Ytci18n.t("proCtaUpgrade"),d.addEventListener("click",()=>{closeScheduleOverviewModal(),goToProSection()}),o.appendChild(d),n.appendChild(o),n}function buildScheduleOverviewHourAxis(){const e=document.createElement("div");e.className="schedule-overview-axis";const t=document.createElement("span");t.className="schedule-overview-day-label",e.appendChild(t);const n=document.createElement("div");return n.className="schedule-overview-axis-track",[0,6,12,18,24].forEach(e=>{const t=document.createElement("span");t.textContent=String(e).padStart(2,"0")+"h",n.appendChild(t)}),e.appendChild(n),e}function buildScheduleChart({enabledIds:e,schedulesState:t,profilesState:n,todayIdx:l,nowPct:o,conflicts:a}){const i=document.createDocumentFragment(),d=dayShortLabels();i.appendChild(buildScheduleOverviewHourAxis());const c=document.createElement("div");c.className="schedule-overview-grid",DAY_DISPLAY_ORDER.forEach(i=>{const r=i===l,s=document.createElement("div");s.className="schedule-overview-row"+(r?" is-today":"");const u=document.createElement("span");u.className="schedule-overview-day-label",u.textContent=d[i],s.appendChild(u);const h=document.createElement("div");if(h.className="schedule-overview-track",[...e].reverse().forEach(e=>{const l=t.items[e];if(!l.days[i])return;const o=l.allDay?[{start:"00:00",end:"24:00"}]:l.ranges,d=a.some(t=>t.day===i&&(t.a===e||t.b===e));o.forEach(t=>{const[l,o]=t.start.split(":").map(Number),[a,i]=t.end.split(":").map(Number),c=(60*l+o)/1440*100,r=(60*a+i-(60*l+o))/1440*100,s=document.createElement("div");s.className="schedule-overview-segment"+(d?" has-conflict":""),s.style.left=`${c}%`,s.style.width=`${r}%`,s.style.background=`var(${profileColorVar(e)})`,s.title=`${n.items[e]?.name||e} — ${u.textContent} ${t.start}–${t.end}`,h.appendChild(s)})}),r){const e=document.createElement("div");e.className="schedule-overview-now-line",e.style.left=`${o}%`,h.appendChild(e)}s.appendChild(h),c.appendChild(s)}),i.appendChild(c);const r=document.createElement("div");if(r.className="schedule-overview-legend",e.forEach(e=>{const t=document.createElement("div");t.className="schedule-overview-legend-item";const l=document.createElement("span");l.className="schedule-overview-swatch",l.style.background=`var(${profileColorVar(e)})`,t.appendChild(l);const o=document.createElement("span");o.textContent=n.items[e]?.name||e,t.appendChild(o),r.appendChild(t)}),i.appendChild(r),a.length>0){const e=document.createElement("p");e.className="schedule-conflict-warning",e.textContent=Ytci18n.t("scheduleOverviewConflictHint"),i.appendChild(e)}return i}async function renderScheduleOverview(){if(!scheduleOverviewBody)return;const[e,t,n]=await Promise.all([YtcDevice.isPro(),YtcSchedule.getState(),YtcProfiles.getState()]);if(scheduleOverviewBody.innerHTML="",!e)return void scheduleOverviewBody.appendChild(buildScheduleOverviewUpsell());const l=YtcProfiles.orderedIds(),o=l.filter(e=>t.items[e]?.enabled);if(0===o.length){const e=document.createElement("div");return e.className="schedule-overview-empty",e.textContent=Ytci18n.t("scheduleOverviewEmpty"),void scheduleOverviewBody.appendChild(e)}const a=YtcScheduler.findOverlaps(t,l),i=new Date,d=YtcScheduler.dayIndex(i),c=(60*i.getHours()+i.getMinutes())/1440*100;scheduleOverviewBody.appendChild(buildScheduleChart({enabledIds:o,schedulesState:t,profilesState:n,todayIdx:d,nowPct:c,conflicts:a}))}scheduleOverviewOpenBtn.addEventListener("click",openScheduleOverviewModal),scheduleOverviewModalCloseBtn.addEventListener("click",closeScheduleOverviewModal),scheduleOverviewModalOverlay.addEventListener("click",e=>{e.target===scheduleOverviewModalOverlay&&closeScheduleOverviewModal()});const licenseSectionEl=document.getElementById("licenseSection"),licenseKeyInput=document.getElementById("licenseKeyInput"),licenseActivateBtn=document.getElementById("licenseActivateBtn"),licenseDeactivateBtn=document.getElementById("licenseDeactivateBtn"),licenseStatusEl=document.getElementById("licenseStatus"),proPitchEl=document.getElementById("proPitch"),proThanksEl=document.getElementById("proThanks"),headerCoffeeLinkEl=document.getElementById("headerCoffeeLink"),proCoffeeLinkEl=document.getElementById("proCoffeeLink");function setLicenseStatus(e,t){licenseStatusEl.textContent=e||"",licenseStatusEl.classList.toggle("is-error",!!t)}async function renderLicense(){const e=await YtcDevice.isPro();document.body.classList.toggle("is-pro",e),licenseSectionEl&&(licenseSectionEl.hidden=e),proPitchEl&&(proPitchEl.hidden=e),proThanksEl&&(proThanksEl.hidden=!e),headerCoffeeLinkEl&&(headerCoffeeLinkEl.hidden=!e),proCoffeeLinkEl&&(proCoffeeLinkEl.closest("p").hidden=!e),lockProInputs(e)}function lockProInputs(e){Object.keys(YtcDevice.GATED_KEYS).forEach(t=>{const n=document.getElementById(t)??document.getElementById(`${t}Tags`);if(!n)return;if(n.classList.contains("tag-input")){n.classList.toggle("is-locked",!e);const t=n.querySelector(".tag-input-field");t&&(t.disabled=!e),n.querySelectorAll(".tag-chip-remove").forEach(t=>t.disabled=!e)}else if(n.classList.contains("mute-panel")){n.classList.toggle("is-locked",!e);const t=n.querySelector(".mute-add-input");t&&(t.disabled=!e),n.querySelectorAll(".duration-chip").forEach(t=>t.disabled=!e)}else n.disabled=!e;const l=n.closest(".card-row");l&&l.classList.toggle("is-pro-locked",!e);const o=l?.querySelector(".fav-btn");o&&(o.disabled=!e)});const t=document.getElementById("modeDryRunOption");t&&(t.textContent=Ytci18n.t(e?"modeDryRun":"modeDryRunLocked"))}renderLicense();const LICENSE_ERROR_KEYS={network:"licenseErrorNetwork",empty:"licenseEmptyKey",rate_limited:"licenseErrorRateLimited",forbidden:"licenseErrorServer",server_misconfigured:"licenseErrorServer",upstream_unreachable:"licenseErrorServer",not_found:"licenseErrorServer",invalid_json:"licenseErrorServer"};function licenseErrorMessage(e){return Ytci18n.t(LICENSE_ERROR_KEYS[e]??"licenseErrorInvalid")}function isRowActive(e){const t=e.querySelector('input[type="checkbox"]');if(t)return t.checked;const n=e.querySelector("select");if(n)return n.value!==(DEFAULTS[n.id]??n.options[0]?.value);const l=e.querySelector('input[type="range"]');if(l)return Number(l.value)/100!==DEFAULTS[l.id];const o=e.querySelector('input[type="number"]');if(o)return""!==o.value&&0!==Number(o.value);const a=e.querySelector("textarea");if(a)return""!==a.value.trim();const i=e.querySelector(".tag-list");if(i)return i.children.length>0;const d=e.querySelector("#mutedChannelsList");return d?d.children.length>0:null}function initFilterSearch(){const e=document.getElementById("filterSearchInput"),t=document.getElementById("filterSearchClear"),n=document.getElementById("filterActiveOnlyBtn"),l=document.getElementById("filterSearchEmpty"),o=document.getElementById("filterSearchShortcut"),a=document.getElementById("profilesSection"),i=document.getElementById("proSection"),d=document.getElementById("licenseSection");if(!e)return;const c=[...document.querySelectorAll(".topic")].filter(e=>e.querySelector(".card-row"));let r=!1;function s(){const n=e.value.trim().toLowerCase(),o=n.length>0||r;if(t.hidden=0===n.length,document.body.classList.toggle("is-searching",o),a&&(a.hidden=o),i&&(i.hidden=o),d&&o&&(d.hidden=!0),!o)return c.forEach(e=>{e.hidden=!1,e.querySelectorAll(".branch").forEach(e=>e.hidden=!1),e.querySelectorAll(".card-row").forEach(e=>e.hidden=!1)}),l.hidden=!0,void renderLicense();const s=Ytci18n.t(n.length>0?"filterSearchEmpty":"filterActiveOnlyEmpty");l.textContent!==s&&(l.textContent=s);let u=!1;c.forEach(e=>{let t=!1;e.querySelectorAll(".branch").forEach(e=>{let l=!1;e.querySelectorAll(".card-row").forEach(e=>{const t=e.querySelector(".row-label")?.textContent??"",o=e.querySelector(".row-desc")?.textContent??"",a=0===n.length||`${t} ${o}`.toLowerCase().includes(n),i=!r||!1!==isRowActive(e),d=a&&i;e.hidden=!d,d&&(l=!0)}),e.hidden=!l,l&&(t=!0)}),e.hidden=!t,t&&(u=!0)}),l.hidden=u}if(e.addEventListener("input",s),t.addEventListener("click",()=>{e.value="",s(),e.focus()}),n){n.addEventListener("click",()=>{r=!r,n.setAttribute("aria-pressed",String(r)),s()});for(const e of c)e.addEventListener("change",()=>{r&&s()}),e.addEventListener("input",()=>{r&&s()});chrome.storage.onChanged.addListener(e=>{r&&0!==Object.keys(e).length&&chrome.storage.local.get(ALL_KEYS,e=>{renderPrefsForm(e),s()})})}if(document.addEventListener("keydown",t=>{(t.ctrlKey||t.metaKey)&&"k"===t.key.toLowerCase()&&(t.preventDefault(),e.focus(),e.select())}),o){const t=/Mac|iPod|iPhone|iPad/.test(navigator.platform||navigator.userAgentData?.platform||"");o.textContent=t?"⌘K":"Ctrl + K";const n=()=>{o.hidden=document.activeElement===e||e.value.length>0};e.addEventListener("focus",n),e.addEventListener("blur",n),e.addEventListener("input",n),n()}}licenseActivateBtn.addEventListener("click",async()=>{const e=licenseKeyInput.value.trim();if(!e)return void setLicenseStatus(Ytci18n.t("licenseEmptyKey"),!0);licenseActivateBtn.disabled=!0,setLicenseStatus(Ytci18n.t("licenseActivating"),!1);const t=await YtcDevice.activate(e);licenseActivateBtn.disabled=!1,t.ok?(licenseKeyInput.value="",setLicenseStatus(Ytci18n.t("licenseActivated"),!1),renderLicense()):setLicenseStatus(licenseErrorMessage(t.error),!0)}),licenseDeactivateBtn.addEventListener("click",async()=>{licenseDeactivateBtn.disabled=!0;try{if(!await showModal({title:Ytci18n.t("licenseDeactivateConfirmTitle"),desc:Ytci18n.t("licenseDeactivateConfirmDesc"),showInput:!1,confirmLabel:Ytci18n.t("licenseDeactivateBtn"),danger:!0}))return;if(!(await YtcDevice.deactivate()).ok)return void setLicenseStatus(Ytci18n.t("licenseErrorNetwork"),!0);setLicenseStatus("",!1),flash(Ytci18n.t("licenseDeactivated")),renderLicense()}finally{licenseDeactivateBtn.disabled=!1}}),initFilterSearch(),"#mutedChannelsSection"===location.hash&&document.getElementById("mutedChannelsSection")?.scrollIntoView({behavior:"smooth",block:"center"}),/firefox\//i.test(navigator.userAgent)&&document.getElementById("footerYtNote")?.setAttribute("data-i18n","footerYtNoteFirefox");

@@ -1,1 +0,1 @@

<!doctype html><html><head><meta charset="UTF-8"><script src="../shared/theme-init.js"></script><link rel="stylesheet" href="../shared/tokens.css"><link rel="stylesheet" href="popup.css"></head><body><header class="header"><img class="logo" src="../icons/icon.svg" width="22" height="22" alt=""> <span class="app-name" data-i18n="appShortName">Vidsieve</span> <label class="switch"><input type="checkbox" id="enabled" data-i18n-aria-label="enabled" aria-label="Enabled"> <span class="track"></span></label></header><div class="body"><div class="stats-hero" id="statsHero"><p class="stats-hero-num" id="statsHeroNum">0</p><p class="stats-hero-label" data-i18n="statLifetime">hidden overall</p><p class="stats-hero-sub" id="statsHeroSub"></p></div><div class="review-banner" id="reviewBanner" hidden><div class="review-text"><span class="review-title" id="reviewTitle">Enjoying Vidsieve?</span> <span class="review-sub" data-i18n="reviewSub">A quick rating helps a lot.</span></div><a class="review-btn review-btn-primary" id="reviewRate" href="#" target="_blank" rel="noopener" data-i18n="reviewRate">Rate ★</a> <button class="review-btn review-btn-ghost" id="reviewDismiss" type="button" data-i18n="reviewDismiss">Later</button></div><section class="section"><div class="section-title-row"><p class="section-title" data-i18n="profileBarLabel">Profile</p></div><div class="profile-switch" role="radiogroup" aria-label="Profile"><div class="profile-switch-row" id="profileSwitch"></div><div class="profile-switch-row" id="profileCustomRow"></div></div></section><section class="section"><p class="section-title" data-i18n="quickFilters">Quick filters</p><div id="quickFiltersList"></div><div class="empty-quick-filters" id="quickFiltersEmpty" hidden><svg class="empty-quick-filters-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg><p data-i18n="quickFiltersEmpty">No favorite filters yet. Star the ones you use most in Settings.</p><button class="link-btn" id="quickFiltersEmptyBtn" type="button" data-i18n="quickFiltersEmptyCta">Open Settings →</button></div></section></div><footer class="footer"><div class="footer-group"><button class="icon-btn icon-btn-labeled theme-btn" id="themeBtn" type="button" data-i18n-title="cycleTheme" data-i18n-aria-label="cycleTheme" title="Cycle theme" aria-label="Cycle theme"><svg class="icon theme-icon" data-theme-icon="auto" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 18V4a8 8 0 0 1 0 16Z"/></svg> <svg class="icon theme-icon" data-theme-icon="light" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4" fill="currentColor"/><path stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg> <svg class="icon theme-icon" data-theme-icon="dark" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79Z"/></svg> <span class="icon-btn-label" id="themeLabel">Auto</span></button> <a class="icon-btn icon-btn-labeled icon-btn-accent" id="rateLink" href="#" target="_blank" rel="noopener" data-i18n-title="rateOnStore" data-i18n-aria-label="rateOnStore" title="Rate on the extension store" aria-label="Rate on the extension store"><svg class="icon" aria-hidden="true"><use href="../shared/icons.svg#ic-star"/></svg> <span class="icon-btn-label" data-i18n="rateShort">Rate us</span> </a><button class="icon-btn icon-btn-labeled" id="settingsBtn" type="button" data-i18n-title="advancedSettings" data-i18n-aria-label="advancedSettings" title="Advanced settings" aria-label="Advanced settings"><svg class="icon" aria-hidden="true"><use href="../shared/icons.svg#ic-settings"/></svg> <span class="icon-btn-label" data-i18n="settingsShort">Settings</span></button></div></footer><script src="../shared/i18n.js"></script><script src="../shared/storage.js"></script><script src="../shared/license.js"></script><script src="../shared/profiles.js"></script><script src="popup.js"></script></body></html>
<!doctype html><html><head><meta charset="UTF-8"><script src="../shared/theme-init.js"></script><link rel="stylesheet" href="../shared/tokens.css"><link rel="stylesheet" href="popup.css"></head><body><header class="header"><img class="logo" src="../icons/icon.svg" width="22" height="22" alt=""> <span class="app-name" data-i18n="appShortName">Vidsieve</span> <label class="switch"><input type="checkbox" id="enabled" data-i18n-aria-label="enabled" aria-label="Enabled"> <span class="track"></span></label></header><div class="body"><div class="stats-hero" id="statsHero"><p class="stats-hero-num" id="statsHeroNum">0</p><p class="stats-hero-label" data-i18n="statLifetime">hidden overall</p><p class="stats-hero-sub" id="statsHeroSub"></p></div><div class="review-banner" id="reviewBanner" hidden><div class="review-text"><span class="review-title" id="reviewTitle">Enjoying Vidsieve?</span> <span class="review-sub" data-i18n="reviewSub">A quick rating helps a lot.</span></div><a class="review-btn review-btn-primary" id="reviewRate" href="#" target="_blank" rel="noopener" data-i18n="reviewRate">Rate ★</a> <button class="review-btn review-btn-ghost" id="reviewDismiss" type="button" data-i18n="reviewDismiss">Later</button></div><section class="section"><div class="section-title-row"><p class="section-title" data-i18n="profileBarLabel">Profile</p></div><div class="profile-switch" role="radiogroup" aria-label="Profile"><div class="profile-switch-row" id="profileSwitch"></div><div class="profile-switch-row" id="profileCustomRow"></div></div></section><section class="section"><p class="section-title" data-i18n="quickFilters">Quick filters</p><div id="quickFiltersList"></div><div class="empty-quick-filters" id="quickFiltersEmpty" hidden><svg class="empty-quick-filters-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3.5l2.4 5.1 5.6.7-4.1 3.9 1.1 5.6-4.9-2.8-4.9 2.8 1.1-5.6-4.1-3.9 5.6-.7Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg><p data-i18n="quickFiltersEmpty">No favorite filters yet. Star the ones you use most in Settings.</p><button class="link-btn" id="quickFiltersEmptyBtn" type="button" data-i18n="quickFiltersEmptyCta">Open Settings →</button></div></section></div><footer class="footer"><div class="footer-group"><button class="icon-btn icon-btn-labeled theme-btn" id="themeBtn" type="button" data-i18n-title="cycleTheme" data-i18n-aria-label="cycleTheme" title="Cycle theme" aria-label="Cycle theme"><svg class="icon theme-icon" data-theme-icon="auto" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm0 18V4a8 8 0 0 1 0 16Z"/></svg> <svg class="icon theme-icon" data-theme-icon="light" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4" fill="currentColor"/><path stroke="currentColor" stroke-width="2" stroke-linecap="round" d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg> <svg class="icon theme-icon" data-theme-icon="dark" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79Z"/></svg> <span class="icon-btn-label" id="themeLabel">Auto</span></button> <a class="icon-btn icon-btn-labeled icon-btn-accent" id="rateLink" href="#" target="_blank" rel="noopener" data-i18n-title="rateOnStore" data-i18n-aria-label="rateOnStore" title="Rate on the extension store" aria-label="Rate on the extension store"><svg class="icon" aria-hidden="true"><use href="../shared/icons.svg#ic-star"/></svg> <span class="icon-btn-label" data-i18n="rateShort">Rate us</span> </a><button class="icon-btn icon-btn-labeled" id="settingsBtn" type="button" data-i18n-title="advancedSettings" data-i18n-aria-label="advancedSettings" title="Advanced settings" aria-label="Advanced settings"><svg class="icon" aria-hidden="true"><use href="../shared/icons.svg#ic-settings"/></svg> <span class="icon-btn-label" data-i18n="settingsShort">Settings</span></button></div></footer><script src="../shared/i18n.js"></script><script src="../shared/storage.js"></script><script src="../shared/device.js"></script><script src="../shared/profiles.js"></script><script src="popup.js"></script></body></html>

@@ -1,1 +0,1 @@

const DEFAULT_QUICK_FILTERS=["hideShorts","hideSeen","hideMembers"];function applyStatus(e){document.body.classList.toggle("is-disabled",!e)}async function applyProLogo(){document.body.classList.toggle("is-pro",await YtcLicense.isPro())}chrome.storage.local.get(["enabled"],({enabled:e=!0})=>{const t=document.getElementById("enabled");t&&(t.checked=e),applyStatus(e)}),document.getElementById("enabled")?.addEventListener("change",e=>{chrome.storage.local.set({enabled:e.target.checked}),applyStatus(e.target.checked)}),chrome.storage.onChanged.addListener(e=>{if(e.enabled){const t=e.enabled.newValue,i=document.getElementById("enabled");i&&(i.checked=!!t),applyStatus(!!t)}}),applyProLogo(),chrome.storage.onChanged.addListener(e=>{"license"in e&&applyProLogo()});const quickFiltersList=document.getElementById("quickFiltersList"),quickFiltersEmpty=document.getElementById("quickFiltersEmpty");let draggedQuickFilterRow=null;function persistQuickFilterOrder(){const e=Array.from(quickFiltersList.children).map(e=>e.dataset.id);chrome.storage.local.set({favoriteFilters:e})}function flipQuickFilterRows(e){const t=Array.from(quickFiltersList.children),i=t.map(e=>e.getBoundingClientRect());e(),t.forEach((e,t)=>{const n=i[t].top-e.getBoundingClientRect().top;n&&(e.style.transition="none",e.style.transform=`translateY(${n}px)`,e.getBoundingClientRect(),requestAnimationFrame(()=>{e.style.transition="transform 150ms ease",e.style.transform=""}))})}function setQuickFilterDragImage(e,t){const i=t.getBoundingClientRect(),n=t.cloneNode(!0);n.classList.remove("is-dragging"),n.classList.add("drag-ghost"),n.style.width=`${i.width}px`,n.style.position="fixed",n.style.top="-9999px",n.style.left="-9999px",document.body.appendChild(n),e.dataTransfer.setDragImage(n,e.clientX-i.left,e.clientY-i.top),setTimeout(()=>n.remove(),0)}function buildQuickFilterRow(e){const t=document.createElement("div");t.className="toggle-row",t.dataset.id=e,t.draggable=!0;const i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("class","drag-grip"),i.setAttribute("aria-hidden","true");const n=document.createElementNS("http://www.w3.org/2000/svg","use");n.setAttribute("href","../shared/icons.svg#ic-grip"),i.appendChild(n);const o=document.createElement("div");o.className="toggle-label";const r=document.createElement("span");r.className="toggle-title-row";const s=document.createElement("span");s.className="toggle-title";const a=Ytci18n.t(e);s.textContent=a,s.title=a,r.appendChild(s),o.appendChild(r);const l=document.createElement("div");l.className="toggle-row-start",l.append(i,o);const c=document.createElement("label");c.className="switch",c.draggable=!1;const d=document.createElement("input");d.type="checkbox",d.id=e;const m=document.createElement("span");return m.className="track",c.append(d,m),t.append(l,c),d.addEventListener("change",()=>{chrome.storage.local.set({[e]:d.checked})}),t.addEventListener("dragstart",i=>{draggedQuickFilterRow=t,t.classList.add("is-dragging"),i.dataTransfer.effectAllowed="move",i.dataTransfer.setData("text/plain",e),setQuickFilterDragImage(i,t)}),t.addEventListener("dragend",()=>{t.classList.remove("is-dragging"),draggedQuickFilterRow=null,persistQuickFilterOrder()}),t.addEventListener("dragover",e=>{if(!draggedQuickFilterRow||draggedQuickFilterRow===t)return;e.preventDefault();const i=t.getBoundingClientRect(),n=e.clientY-i.top<i.height/2?t:t.nextSibling;draggedQuickFilterRow.nextSibling!==n&&flipQuickFilterRows(()=>{t.parentNode.insertBefore(draggedQuickFilterRow,n)})}),t.addEventListener("drop",e=>{e.preventDefault()}),t}async function renderQuickFilters(){const{favoriteFilters:e=DEFAULT_QUICK_FILTERS}=await chrome.storage.local.get(["favoriteFilters"]);if(quickFiltersList.innerHTML="",0===e.length)return void(quickFiltersEmpty.hidden=!1);const[t,i]=await Promise.all([chrome.storage.local.get(e),YtcLicense.isPro()]),n=e.filter(e=>!(e in YtcLicense.PRO_KEYS)||i);quickFiltersEmpty.hidden=n.length>0,n.forEach(e=>{const i=buildQuickFilterRow(e);i.querySelector("input").checked=!!t[e],quickFiltersList.appendChild(i)})}renderQuickFilters(),document.getElementById("quickFiltersEmptyBtn")?.addEventListener("click",()=>{chrome.runtime.openOptionsPage(),window.close()}),chrome.storage.onChanged.addListener(e=>{if("favoriteFilters"in e||"license"in e)renderQuickFilters();else for(const t of Object.keys(e)){const i=quickFiltersList.querySelector(`#${CSS.escape(t)}`);i&&(i.checked=!!e[t].newValue)}});const profileSwitch=document.getElementById("profileSwitch"),profileCustomRow=document.getElementById("profileCustomRow");let profileApplyInFlight=!1;async function applyProfileOptimistically(e,t,i){if(!t&&!profileApplyInFlight){profileApplyInFlight=!0,document.querySelectorAll(".profile-seg.is-active").forEach(e=>{e.classList.remove("is-active"),e.setAttribute("aria-checked","false")}),i.classList.add("is-active"),i.setAttribute("aria-checked","true");try{await YtcProfiles.applyProfile(e)}finally{profileApplyInFlight=!1,await renderProfiles()}}}function buildProfileSeg(e,t,i){const n=document.createElement("button");return n.type="button",n.className="profile-seg"+(i?" is-active":""),n.dataset.id=e,n.setAttribute("role","radio"),n.setAttribute("aria-checked",i?"true":"false"),n.textContent=t.name,n.title=t.name,n.addEventListener("click",()=>{applyProfileOptimistically(e,i,n)}),n}async function renderProfiles(){if(!profileSwitch)return;const[e,t,i]=await Promise.all([YtcProfiles.getState(),YtcProfiles.currentSnapshot(),YtcLicense.isPro()]),n=YtcProfiles.findMatchingProfile(e,t);profileSwitch.innerHTML="";for(const t of YtcProfiles.BUILTIN_ORDER)profileSwitch.appendChild(buildProfileSeg(t,e.items[t],t===n));if(profileCustomRow.innerHTML="",!i)return;YtcProfiles.CUSTOM_ORDER.filter(t=>!e.items[t].empty).forEach(t=>{profileCustomRow.appendChild(buildProfileSeg(t,e.items[t],t===n))})}renderProfiles(),chrome.storage.onChanged.addListener(e=>{("profiles"in e||"license"in e||YtcProfiles.KEYS.some(t=>t in e))&&renderProfiles()});const THEMES=["auto","light","dark"],THEME_TITLE_KEY={auto:"themeAutoTitle",light:"themeLightTitle",dark:"themeDarkTitle"},THEME_LABEL_KEY={auto:"themeAuto",light:"themeLight",dark:"themeDark"};function applyTheme(e){"auto"===e?(document.documentElement.removeAttribute("data-theme"),localStorage.removeItem("theme")):(document.documentElement.setAttribute("data-theme",e),localStorage.setItem("theme",e));const t=document.getElementById("themeBtn");t&&(t.dataset.theme=e,t.title=Ytci18n.t(THEME_TITLE_KEY[e]));const i=document.getElementById("themeLabel");i&&(i.textContent=Ytci18n.t(THEME_LABEL_KEY[e]))}chrome.storage.local.get(["theme"],({theme:e="auto"})=>{applyTheme(THEMES.includes(e)?e:"auto")}),document.getElementById("themeBtn").addEventListener("click",async()=>{const{theme:e="auto"}=await chrome.storage.local.get(["theme"]),t=THEMES[(THEMES.indexOf(e)+1)%THEMES.length];await chrome.storage.local.set({theme:t}),applyTheme(t)}),document.getElementById("settingsBtn").addEventListener("click",()=>{chrome.runtime.openOptionsPage(),window.close()});const isFirefox=/firefox\//i.test(navigator.userAgent),CHROME_STORE_REVIEW_URL="https://chromewebstore.google.com/detail/jhdmepohcmocbiiogibbikdekihhmmbl/reviews",FIREFOX_STORE_REVIEW_URL="https://addons.mozilla.org/firefox/addon/vidsieve-hide-youtube-shorts/reviews/",STORE_REVIEW_URL=isFirefox?FIREFOX_STORE_REVIEW_URL:CHROME_STORE_REVIEW_URL;document.getElementById("rateLink").href=STORE_REVIEW_URL;const REVIEW_FIRST_ASK_THRESHOLD=100,REVIEW_LEGENDARY_THRESHOLD=1e6,REVIEW_DISMISS_COOLDOWN_MS=7776e6,REVIEW_EXPOSURE_COOLDOWN_MS=864e5,REVIEW_MAX_DECISIONS=3,REVIEW_FIRST_ASK_MIN_DAYS=3,REVIEW_PROMPT_DEFAULT={rated:!1,dismissedAt:null,lastShownAt:null,decisions:0};function roundDownNice(e){if(e<100)return e;const t=10**(Math.floor(e).toString().length-2);return Math.floor(e/t)*t}function formatStatNumber(e){if(e<1e6)return e.toLocaleString();try{return new Intl.NumberFormat(chrome.i18n.getUILanguage()||void 0,{notation:"compact",minimumFractionDigits:1,maximumFractionDigits:1}).format(e)}catch{return e.toLocaleString()}}chrome.storage.local.get(["totalHidden","reviewPrompt","hiddenCounts"],({totalHidden:e=0,reviewPrompt:t=REVIEW_PROMPT_DEFAULT,hiddenCounts:i={}})=>{if(t.rated)return;const n=t.decisions||0;if(n>=3)return;if(0===n){if(e<100)return;if(Object.keys(i).length<3)return}const o=Date.now();if(t.dismissedAt&&o-t.dismissedAt<7776e6)return;if(t.lastShownAt&&o-t.lastShownAt<864e5)return;const r=document.getElementById("reviewBanner");if(!r)return;document.getElementById("reviewTitle").textContent=Ytci18n.t(e>=1e6?"reviewTitleMilestoneMillion":"reviewTitleMilestone",{count:roundDownNice(e).toLocaleString()}),r.hidden=!1,t={...t,lastShownAt:o},chrome.storage.local.set({reviewPrompt:t});const s=document.getElementById("reviewRate");s.href=STORE_REVIEW_URL,s.addEventListener("click",()=>{chrome.storage.local.set({reviewPrompt:{...t,rated:!0,decisions:n+1}}),r.hidden=!0}),document.getElementById("reviewDismiss").addEventListener("click",()=>{chrome.storage.local.set({reviewPrompt:{...t,dismissedAt:o,decisions:n+1}}),r.hidden=!0})}),chrome.storage.local.get(["hiddenCounts","totalHidden"],({hiddenCounts:e={},totalHidden:t=0})=>{const i=document.getElementById("statsHero"),n=document.getElementById("statsHeroNum"),o=document.getElementById("statsHeroSub");if(!i)return;const r=(new Date).toISOString().slice(0,10),s=Date.now()-6048e5;let a=0;for(const[t,i]of Object.entries(e))new Date(t).getTime()>=s&&(a+=i);n.textContent=formatStatNumber(t),n.title=t>=1e6?t.toLocaleString():"";const l=document.createElement("strong");l.textContent=(e[r]||0).toLocaleString();const c=document.createElement("strong");c.textContent=a.toLocaleString(),o.replaceChildren(l,document.createTextNode(` ${Ytci18n.t("statTodayInline")}, `),c,document.createTextNode(` ${Ytci18n.t("statWeekInline")}`))});
const DEFAULT_QUICK_FILTERS=["hideShorts","hideSeen","hideMembers"];function applyStatus(e){document.body.classList.toggle("is-disabled",!e)}async function applyProLogo(){document.body.classList.toggle("is-pro",await YtcDevice.isPro())}chrome.storage.local.get(["enabled"],({enabled:e=!0})=>{const t=document.getElementById("enabled");t&&(t.checked=e),applyStatus(e)}),document.getElementById("enabled")?.addEventListener("change",e=>{chrome.storage.local.set({enabled:e.target.checked}),applyStatus(e.target.checked)}),chrome.storage.onChanged.addListener(e=>{if(e.enabled){const t=e.enabled.newValue,i=document.getElementById("enabled");i&&(i.checked=!!t),applyStatus(!!t)}}),applyProLogo(),chrome.storage.onChanged.addListener(e=>{"device"in e&&applyProLogo()});const quickFiltersList=document.getElementById("quickFiltersList"),quickFiltersEmpty=document.getElementById("quickFiltersEmpty");let draggedQuickFilterRow=null;function persistQuickFilterOrder(){const e=Array.from(quickFiltersList.children).map(e=>e.dataset.id);chrome.storage.local.set({favoriteFilters:e})}function flipQuickFilterRows(e){const t=Array.from(quickFiltersList.children),i=t.map(e=>e.getBoundingClientRect());e(),t.forEach((e,t)=>{const n=i[t].top-e.getBoundingClientRect().top;n&&(e.style.transition="none",e.style.transform=`translateY(${n}px)`,e.getBoundingClientRect(),requestAnimationFrame(()=>{e.style.transition="transform 150ms ease",e.style.transform=""}))})}function setQuickFilterDragImage(e,t){const i=t.getBoundingClientRect(),n=t.cloneNode(!0);n.classList.remove("is-dragging"),n.classList.add("drag-ghost"),n.style.width=`${i.width}px`,n.style.position="fixed",n.style.top="-9999px",n.style.left="-9999px",document.body.appendChild(n),e.dataTransfer.setDragImage(n,e.clientX-i.left,e.clientY-i.top),setTimeout(()=>n.remove(),0)}function buildQuickFilterRow(e){const t=document.createElement("div");t.className="toggle-row",t.dataset.id=e,t.draggable=!0;const i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("class","drag-grip"),i.setAttribute("aria-hidden","true");const n=document.createElementNS("http://www.w3.org/2000/svg","use");n.setAttribute("href","../shared/icons.svg#ic-grip"),i.appendChild(n);const o=document.createElement("div");o.className="toggle-label";const r=document.createElement("span");r.className="toggle-title-row";const a=document.createElement("span");a.className="toggle-title";const s=Ytci18n.t(e);a.textContent=s,a.title=s,r.appendChild(a),o.appendChild(r);const c=document.createElement("div");c.className="toggle-row-start",c.append(i,o);const l=document.createElement("label");l.className="switch",l.draggable=!1;const d=document.createElement("input");d.type="checkbox",d.id=e;const m=document.createElement("span");return m.className="track",l.append(d,m),t.append(c,l),d.addEventListener("change",()=>{chrome.storage.local.set({[e]:d.checked})}),t.addEventListener("dragstart",i=>{draggedQuickFilterRow=t,t.classList.add("is-dragging"),i.dataTransfer.effectAllowed="move",i.dataTransfer.setData("text/plain",e),setQuickFilterDragImage(i,t)}),t.addEventListener("dragend",()=>{t.classList.remove("is-dragging"),draggedQuickFilterRow=null,persistQuickFilterOrder()}),t.addEventListener("dragover",e=>{if(!draggedQuickFilterRow||draggedQuickFilterRow===t)return;e.preventDefault();const i=t.getBoundingClientRect(),n=e.clientY-i.top<i.height/2?t:t.nextSibling;draggedQuickFilterRow.nextSibling!==n&&flipQuickFilterRows(()=>{t.parentNode.insertBefore(draggedQuickFilterRow,n)})}),t.addEventListener("drop",e=>{e.preventDefault()}),t}async function renderQuickFilters(){const{favoriteFilters:e=DEFAULT_QUICK_FILTERS}=await chrome.storage.local.get(["favoriteFilters"]);if(quickFiltersList.innerHTML="",0===e.length)return void(quickFiltersEmpty.hidden=!1);const[t,i]=await Promise.all([chrome.storage.local.get(e),YtcDevice.isPro()]),n=e.filter(e=>!(e in YtcDevice.GATED_KEYS)||i);quickFiltersEmpty.hidden=n.length>0,n.forEach(e=>{const i=buildQuickFilterRow(e);i.querySelector("input").checked=!!t[e],quickFiltersList.appendChild(i)})}renderQuickFilters(),document.getElementById("quickFiltersEmptyBtn")?.addEventListener("click",()=>{chrome.runtime.openOptionsPage(),window.close()}),chrome.storage.onChanged.addListener(e=>{if("favoriteFilters"in e||"device"in e)renderQuickFilters();else for(const t of Object.keys(e)){const i=quickFiltersList.querySelector(`#${CSS.escape(t)}`);i&&(i.checked=!!e[t].newValue)}});const profileSwitch=document.getElementById("profileSwitch"),profileCustomRow=document.getElementById("profileCustomRow");let profileApplyInFlight=!1;async function applyProfileOptimistically(e,t,i){if(!t&&!profileApplyInFlight){profileApplyInFlight=!0,document.querySelectorAll(".profile-seg.is-active").forEach(e=>{e.classList.remove("is-active"),e.setAttribute("aria-checked","false")}),i.classList.add("is-active"),i.setAttribute("aria-checked","true");try{await YtcProfiles.applyProfile(e)}finally{profileApplyInFlight=!1,await renderProfiles()}}}function buildProfileSeg(e,t,i){const n=document.createElement("button");return n.type="button",n.className="profile-seg"+(i?" is-active":""),n.dataset.id=e,n.setAttribute("role","radio"),n.setAttribute("aria-checked",i?"true":"false"),n.textContent=t.name,n.title=t.name,n.addEventListener("click",()=>{applyProfileOptimistically(e,i,n)}),n}async function renderProfiles(){if(!profileSwitch)return;const[e,t,i]=await Promise.all([YtcProfiles.getState(),YtcProfiles.currentSnapshot(),YtcDevice.isPro()]),n=YtcProfiles.findMatchingProfile(e,t);profileSwitch.innerHTML="";for(const t of YtcProfiles.BUILTIN_ORDER)profileSwitch.appendChild(buildProfileSeg(t,e.items[t],t===n));if(profileCustomRow.innerHTML="",!i)return;YtcProfiles.CUSTOM_ORDER.filter(t=>!e.items[t].empty).forEach(t=>{profileCustomRow.appendChild(buildProfileSeg(t,e.items[t],t===n))})}renderProfiles(),chrome.storage.onChanged.addListener(e=>{("profiles"in e||"device"in e||YtcProfiles.KEYS.some(t=>t in e))&&renderProfiles()});const THEMES=["auto","light","dark"],THEME_TITLE_KEY={auto:"themeAutoTitle",light:"themeLightTitle",dark:"themeDarkTitle"},THEME_LABEL_KEY={auto:"themeAuto",light:"themeLight",dark:"themeDark"};function applyTheme(e){"auto"===e?(document.documentElement.removeAttribute("data-theme"),localStorage.removeItem("theme")):(document.documentElement.setAttribute("data-theme",e),localStorage.setItem("theme",e));const t=document.getElementById("themeBtn");t&&(t.dataset.theme=e,t.title=Ytci18n.t(THEME_TITLE_KEY[e]));const i=document.getElementById("themeLabel");i&&(i.textContent=Ytci18n.t(THEME_LABEL_KEY[e]))}chrome.storage.local.get(["theme"],({theme:e="auto"})=>{applyTheme(THEMES.includes(e)?e:"auto")}),document.getElementById("themeBtn").addEventListener("click",async()=>{const{theme:e="auto"}=await chrome.storage.local.get(["theme"]),t=THEMES[(THEMES.indexOf(e)+1)%THEMES.length];await chrome.storage.local.set({theme:t}),applyTheme(t)}),document.getElementById("settingsBtn").addEventListener("click",()=>{chrome.runtime.openOptionsPage(),window.close()});const isFirefox=/firefox\//i.test(navigator.userAgent),CHROME_STORE_REVIEW_URL="https://chromewebstore.google.com/detail/jhdmepohcmocbiiogibbikdekihhmmbl/reviews",FIREFOX_STORE_REVIEW_URL="https://addons.mozilla.org/firefox/addon/vidsieve-hide-youtube-shorts/reviews/",STORE_REVIEW_URL=isFirefox?FIREFOX_STORE_REVIEW_URL:CHROME_STORE_REVIEW_URL;document.getElementById("rateLink").href=STORE_REVIEW_URL;const REVIEW_FIRST_ASK_THRESHOLD=100,REVIEW_LEGENDARY_THRESHOLD=1e6,REVIEW_DISMISS_COOLDOWN_MS=7776e6,REVIEW_EXPOSURE_COOLDOWN_MS=864e5,REVIEW_MAX_DECISIONS=3,REVIEW_FIRST_ASK_MIN_DAYS=3,REVIEW_PROMPT_DEFAULT={rated:!1,dismissedAt:null,lastShownAt:null,decisions:0};function roundDownNice(e){if(e<100)return e;const t=10**(Math.floor(e).toString().length-2);return Math.floor(e/t)*t}function formatStatNumber(e){if(e<1e6)return e.toLocaleString();try{return new Intl.NumberFormat(chrome.i18n.getUILanguage()||void 0,{notation:"compact",minimumFractionDigits:1,maximumFractionDigits:1}).format(e)}catch{return e.toLocaleString()}}chrome.storage.local.get(["totalHidden","reviewPrompt","hiddenCounts"],({totalHidden:e=0,reviewPrompt:t=REVIEW_PROMPT_DEFAULT,hiddenCounts:i={}})=>{if(t.rated)return;const n=t.decisions||0;if(n>=3)return;if(0===n){if(e<100)return;if(Object.keys(i).length<3)return}const o=Date.now();if(t.dismissedAt&&o-t.dismissedAt<7776e6)return;if(t.lastShownAt&&o-t.lastShownAt<864e5)return;const r=document.getElementById("reviewBanner");if(!r)return;document.getElementById("reviewTitle").textContent=Ytci18n.t(e>=1e6?"reviewTitleMilestoneMillion":"reviewTitleMilestone",{count:roundDownNice(e).toLocaleString()}),r.hidden=!1,t={...t,lastShownAt:o},chrome.storage.local.set({reviewPrompt:t});const a=document.getElementById("reviewRate");a.href=STORE_REVIEW_URL,a.addEventListener("click",()=>{chrome.storage.local.set({reviewPrompt:{...t,rated:!0,decisions:n+1}}),r.hidden=!0}),document.getElementById("reviewDismiss").addEventListener("click",()=>{chrome.storage.local.set({reviewPrompt:{...t,dismissedAt:o,decisions:n+1}}),r.hidden=!0})}),chrome.storage.local.get(["hiddenCounts","totalHidden"],({hiddenCounts:e={},totalHidden:t=0})=>{const i=document.getElementById("statsHero"),n=document.getElementById("statsHeroNum"),o=document.getElementById("statsHeroSub");if(!i)return;const r=(new Date).toISOString().slice(0,10),a=Date.now()-6048e5;let s=0;for(const[t,i]of Object.entries(e))new Date(t).getTime()>=a&&(s+=i);n.textContent=formatStatNumber(t),n.title=t>=1e6?t.toLocaleString():"";const c=document.createElement("strong");c.textContent=(e[r]||0).toLocaleString();const l=document.createElement("strong");l.textContent=s.toLocaleString(),o.replaceChildren(c,document.createTextNode(` ${Ytci18n.t("statTodayInline")}, `),l,document.createTextNode(` ${Ytci18n.t("statWeekInline")}`))});

@@ -1,1 +0,1 @@

const YtcProfiles=(()=>{const e="profiles",i=["preset-deep","preset-learning","preset-minimal"],t=["custom-1","custom-2","custom-3"],n=["hideShorts","hideLive","hideUpcoming","hidePremieres","hideMembers","hideFilterBar","hideMixes","hideDiscoveryShelf","hidePlayablesShelf","hideSubscriptionsAlgo","hideSeen","homeFeedMode","disableAutoplay","hideRelated","hideEndCards","hideEndScreenFeed","hideLiveChat","hidePlaylistPanel","hideChannelInfo","hideDescription","hideMerchShelf","hideComments","hideVideoActions","hideAskButton","hideSaveButton","hideMoreActionsButton","hideExploreSidebar","hideSubscriptions","hideShortsSidebar","hideMoreFromYoutube","hideNotifications","hideVoiceSearch","blurThumbnails","hideProfilePhotos","minAgeDays","maxAgeDays","minViews","maxViews","dailyChannelLimit","keywords","watchedMode","watchedThreshold","minDuration","maxDuration"],r={hideShorts:!1,hideLive:!1,hideUpcoming:!1,hidePremieres:!1,hideMembers:!1,hideFilterBar:!1,hideMixes:!1,hideDiscoveryShelf:!1,hidePlayablesShelf:!1,hideSubscriptionsAlgo:!1,hideSeen:!0,homeFeedMode:"show",disableAutoplay:!1,hideRelated:!1,hideEndCards:!1,hideEndScreenFeed:!1,hideLiveChat:!1,hidePlaylistPanel:!1,hideChannelInfo:!1,hideDescription:!1,hideMerchShelf:!1,hideComments:!1,hideVideoActions:!1,hideAskButton:!1,hideSaveButton:!1,hideMoreActionsButton:!1,hideExploreSidebar:!1,hideSubscriptions:!1,hideShortsSidebar:!1,hideMoreFromYoutube:!1,hideNotifications:!1,hideVoiceSearch:!1,blurThumbnails:!1,hideProfilePhotos:!1,minAgeDays:0,maxAgeDays:0,minViews:0,maxViews:0,dailyChannelLimit:0,keywords:[],watchedMode:"hide",watchedThreshold:.5,minDuration:0,maxDuration:0};function s(e){return{...r,...e}}function o(){return{"preset-deep":{name:Ytci18n.t("profileFocus"),builtin:!0,settings:s({hideShorts:!0,hideMixes:!0,hidePlayablesShelf:!0,hideLive:!0,hideUpcoming:!0,hidePremieres:!0,hideMembers:!0,hideFilterBar:!0,homeFeedMode:"blank",disableAutoplay:!0,hideRelated:!0,hideEndCards:!0,hideEndScreenFeed:!0,hideComments:!0,hideVideoActions:!0,hideAskButton:!0,hideSaveButton:!0,hideMoreActionsButton:!0,hideChannelInfo:!0,hideDescription:!0,hideMerchShelf:!0,hideLiveChat:!0,hidePlaylistPanel:!0,hideExploreSidebar:!0,hideSubscriptions:!0,hideShortsSidebar:!0,hideMoreFromYoutube:!0,hideNotifications:!0,hideVoiceSearch:!0})},"preset-learning":{name:Ytci18n.t("profileStudy"),builtin:!0,settings:s({hideShorts:!0,hideShortsSidebar:!0,hideMixes:!0,hidePlayablesShelf:!0,hideLive:!0,hideUpcoming:!0,hidePremieres:!0,hideMembers:!0,hideEndCards:!0,hideEndScreenFeed:!0,disableAutoplay:!0,hideMerchShelf:!0})},"preset-minimal":{name:Ytci18n.t("profileLight"),builtin:!0,settings:s({hideShorts:!0,hideShortsSidebar:!0,hideMixes:!0,hidePlayablesShelf:!0,hideLive:!0,hideUpcoming:!0,hidePremieres:!0})}}}function d(){return{name:Ytci18n.t("profileEmptySlot"),builtin:!1,empty:!0,createdAt:0,updatedAt:0,settings:null}}function a(e){let r=e,s=!1;r&&"object"==typeof r&&r.items||(r={schemaVersion:1,activeProfileId:null,items:{}},s=!0);const a=o();for(const e of i)if(r.items[e])for(const i of n)i in r.items[e].settings||(r.items[e].settings[i]=a[e].settings[i],s=!0);else r.items[e]=a[e],s=!0;for(const e of t)r.items[e]||(r.items[e]=d(),s=!0);return{state:r,changed:s}}function h(){return[...i,...t]}async function c(){return s(await YtcStorage.get(n))}function l(e,i){return n.every(t=>JSON.stringify(e[t])===JSON.stringify(i[t]))}return{KEYS:n,BUILTIN_ORDER:i,CUSTOM_ORDER:t,builtinDefs:o,getState:async function(){const{profiles:i}=await YtcStorage.get([e]),{state:t,changed:n}=a(i);return n?YtcStorage.mutate(e,e=>a(e).state):t},orderedIds:h,currentSnapshot:c,findMatchingProfile:function(e,i){for(const t of h()){const n=e.items[t];if(!n.empty&&l(s(n.settings),i))return t}return null},applyProfile:async function(i){const t=(await YtcStorage.mutate(e,e=>{const{state:t}=a(e),n=t.items[i];return n&&!n.empty&&(t.activeProfileId=i),t})).items[i];return!(!t||t.empty)&&(await chrome.storage.local.set(s(t.settings)),!0)},filledCustomCount:function(e){return t.filter(i=>!e.items[i].empty).length},saveCurrentToSlot:async function(i,n){if(!await YtcLicense.isPro())return{error:"pro"};if(!t.includes(i))return{error:"invalid"};const r=n.trim().slice(0,40);if(!r)return{error:"name"};const s=await c(),o=Date.now();return await YtcStorage.mutate(e,e=>{const{state:t}=a(e),n=t.items[i];return t.items[i]={name:r,builtin:!1,empty:!1,createdAt:!1===n?.empty?n.createdAt:o,updatedAt:o,settings:s},t.activeProfileId=i,t}),{id:i}},updateFromCurrent:async function(i){if(!await YtcLicense.isPro())return!1;const t=await c(),n=(await YtcStorage.mutate(e,e=>{const{state:n}=a(e),r=n.items[i];return r&&!r.empty&&(r.settings=t,r.updatedAt=Date.now()),n})).items[i];return!!n&&!n.empty},rename:async function(i,t){if(!await YtcLicense.isPro())return!1;const n=t.trim().slice(0,40);if(!n)return!1;const r=(await YtcStorage.mutate(e,e=>{const{state:t}=a(e),r=t.items[i];return r&&!r.empty&&(r.name=n,r.builtin||(r.updatedAt=Date.now())),t})).items[i];return!!r&&!r.empty},remove:async function(i){if(!await YtcLicense.isPro())return!1;const t=(await YtcStorage.mutate(e,e=>{const{state:t}=a(e),n=t.items[i];return!n||n.builtin||(t.items[i]=d(),t.activeProfileId===i&&(t.activeProfileId=null)),t})).items[i];return!!t&&!t.builtin}}})();
const YtcProfiles=(()=>{const e="profiles",i=["preset-deep","preset-learning","preset-minimal"],t=["custom-1","custom-2","custom-3"],n=["hideShorts","hideLive","hideUpcoming","hidePremieres","hideMembers","hideFilterBar","hideMixes","hideDiscoveryShelf","hidePlayablesShelf","hideSubscriptionsAlgo","hideSeen","homeFeedMode","disableAutoplay","hideRelated","hideEndCards","hideEndScreenFeed","hideLiveChat","hidePlaylistPanel","hideChannelInfo","hideDescription","hideMerchShelf","hideComments","hideVideoActions","hideAskButton","hideSaveButton","hideMoreActionsButton","hideExploreSidebar","hideSubscriptions","hideShortsSidebar","hideMoreFromYoutube","hideNotifications","hideVoiceSearch","blurThumbnails","hideProfilePhotos","minAgeDays","maxAgeDays","minViews","maxViews","dailyChannelLimit","keywords","watchedMode","watchedThreshold","minDuration","maxDuration"],r={hideShorts:!1,hideLive:!1,hideUpcoming:!1,hidePremieres:!1,hideMembers:!1,hideFilterBar:!1,hideMixes:!1,hideDiscoveryShelf:!1,hidePlayablesShelf:!1,hideSubscriptionsAlgo:!1,hideSeen:!0,homeFeedMode:"show",disableAutoplay:!1,hideRelated:!1,hideEndCards:!1,hideEndScreenFeed:!1,hideLiveChat:!1,hidePlaylistPanel:!1,hideChannelInfo:!1,hideDescription:!1,hideMerchShelf:!1,hideComments:!1,hideVideoActions:!1,hideAskButton:!1,hideSaveButton:!1,hideMoreActionsButton:!1,hideExploreSidebar:!1,hideSubscriptions:!1,hideShortsSidebar:!1,hideMoreFromYoutube:!1,hideNotifications:!1,hideVoiceSearch:!1,blurThumbnails:!1,hideProfilePhotos:!1,minAgeDays:0,maxAgeDays:0,minViews:0,maxViews:0,dailyChannelLimit:0,keywords:[],watchedMode:"hide",watchedThreshold:.5,minDuration:0,maxDuration:0};function o(e){return{...r,...e}}function s(){return{"preset-deep":{name:Ytci18n.t("profileFocus"),builtin:!0,settings:o({hideShorts:!0,hideMixes:!0,hidePlayablesShelf:!0,hideLive:!0,hideUpcoming:!0,hidePremieres:!0,hideMembers:!0,hideFilterBar:!0,homeFeedMode:"blank",disableAutoplay:!0,hideRelated:!0,hideEndCards:!0,hideEndScreenFeed:!0,hideComments:!0,hideVideoActions:!0,hideAskButton:!0,hideSaveButton:!0,hideMoreActionsButton:!0,hideChannelInfo:!0,hideDescription:!0,hideMerchShelf:!0,hideLiveChat:!0,hidePlaylistPanel:!0,hideExploreSidebar:!0,hideSubscriptions:!0,hideShortsSidebar:!0,hideMoreFromYoutube:!0,hideNotifications:!0,hideVoiceSearch:!0})},"preset-learning":{name:Ytci18n.t("profileStudy"),builtin:!0,settings:o({hideShorts:!0,hideShortsSidebar:!0,hideMixes:!0,hidePlayablesShelf:!0,hideLive:!0,hideUpcoming:!0,hidePremieres:!0,hideMembers:!0,hideEndCards:!0,hideEndScreenFeed:!0,disableAutoplay:!0,hideMerchShelf:!0})},"preset-minimal":{name:Ytci18n.t("profileLight"),builtin:!0,settings:o({hideShorts:!0,hideShortsSidebar:!0,hideMixes:!0,hidePlayablesShelf:!0,hideLive:!0,hideUpcoming:!0,hidePremieres:!0})}}}function d(){return{name:Ytci18n.t("profileEmptySlot"),builtin:!1,empty:!0,createdAt:0,updatedAt:0,settings:null}}function a(e){let r=e,o=!1;r&&"object"==typeof r&&r.items||(r={schemaVersion:1,activeProfileId:null,items:{}},o=!0);const a=s();for(const e of i)if(r.items[e])for(const i of n)i in r.items[e].settings||(r.items[e].settings[i]=a[e].settings[i],o=!0);else r.items[e]=a[e],o=!0;for(const e of t)r.items[e]||(r.items[e]=d(),o=!0);return{state:r,changed:o}}function h(){return[...i,...t]}async function c(){return o(await YtcStorage.get(n))}function l(e,i){return n.every(t=>JSON.stringify(e[t])===JSON.stringify(i[t]))}return{KEYS:n,BUILTIN_ORDER:i,CUSTOM_ORDER:t,builtinDefs:s,getState:async function(){const{profiles:i}=await YtcStorage.get([e]),{state:t,changed:n}=a(i);return n?YtcStorage.mutate(e,e=>a(e).state):t},orderedIds:h,currentSnapshot:c,findMatchingProfile:function(e,i){for(const t of h()){const n=e.items[t];if(!n.empty&&l(o(n.settings),i))return t}return null},applyProfile:async function(i){const t=(await YtcStorage.mutate(e,e=>{const{state:t}=a(e),n=t.items[i];return n&&!n.empty&&(t.activeProfileId=i),t})).items[i];return!(!t||t.empty)&&(await chrome.storage.local.set(o(t.settings)),!0)},filledCustomCount:function(e){return t.filter(i=>!e.items[i].empty).length},saveCurrentToSlot:async function(i,n){if(!await YtcDevice.isPro())return{error:"pro"};if(!t.includes(i))return{error:"invalid"};const r=n.trim().slice(0,40);if(!r)return{error:"name"};const o=await c(),s=Date.now();return await YtcStorage.mutate(e,e=>{const{state:t}=a(e),n=t.items[i];return t.items[i]={name:r,builtin:!1,empty:!1,createdAt:!1===n?.empty?n.createdAt:s,updatedAt:s,settings:o},t.activeProfileId=i,t}),{id:i}},updateFromCurrent:async function(i){if(!await YtcDevice.isPro())return!1;const t=await c(),n=(await YtcStorage.mutate(e,e=>{const{state:n}=a(e),r=n.items[i];return r&&!r.empty&&(r.settings=t,r.updatedAt=Date.now()),n})).items[i];return!!n&&!n.empty},rename:async function(i,t){if(!await YtcDevice.isPro())return!1;const n=t.trim().slice(0,40);if(!n)return!1;const r=(await YtcStorage.mutate(e,e=>{const{state:t}=a(e),r=t.items[i];return r&&!r.empty&&(r.name=n,r.builtin||(r.updatedAt=Date.now())),t})).items[i];return!!r&&!r.empty},remove:async function(i){if(!await YtcDevice.isPro())return!1;const t=(await YtcStorage.mutate(e,e=>{const{state:t}=a(e),n=t.items[i];return!n||n.builtin||(t.items[i]=d(),t.activeProfileId===i&&(t.activeProfileId=null)),t})).items[i];return!!t&&!t.builtin}}})();

@@ -1,1 +0,1 @@

const YtcSchedule=(()=>{const e="schedules",t="ytc-schedule-check";function r(){return{enabled:!1,days:[!1,!1,!1,!1,!1,!1,!1],allDay:!1,ranges:[{start:"09:00",end:"17:00"}]}}function n(e){let t=e,n=!1;t&&"object"==typeof t&&t.items||(t={items:{},prevProfileId:null,engagedProfileId:null,snoozeUntil:0},n=!0);for(const e of YtcProfiles.orderedIds())t.items[e]||(t.items[e]=r(),n=!0);return{state:t,changed:n}}async function a(){const{schedules:t}=await YtcStorage.get([e]),{state:r,changed:a}=n(t);return a?YtcStorage.mutate(e,e=>n(e).state):r}function i(){const e=18e5;return Math.ceil(Date.now()/e)*e}async function o(){const[e,r]=await Promise.all([YtcLicense.isPro(),a()]);e&&function(e){return Object.values(e.items).some(e=>e.enabled)}(r)?chrome.alarms.create(t,{when:i(),periodInMinutes:30}):await chrome.alarms.clear(t)}let s=Promise.resolve();return{getState:a,save:async function(t,r){if(!await YtcLicense.isPro())return!1;const a=!!(await YtcStorage.mutate(e,e=>{const{state:a}=n(e);return a.items[t]&&(a.items[t]={...a.items[t],...r}),a})).items[t];return a&&await o(),a},disableAndClear:async function(t){await YtcStorage.mutate(e,e=>{const{state:r}=n(e);return r.items[t]&&(r.items[t]={...r.items[t],enabled:!1}),r.engagedProfileId===t&&(r.engagedProfileId=null),r.prevProfileId===t&&(r.prevProfileId=null),r}),await o()},checkAndApply:function(){return s=s.catch(()=>{}).then(()=>async function(){if(!await YtcLicense.isPro())return;const[t,r,i]=await Promise.all([a(),YtcProfiles.getState(),YtcProfiles.currentSnapshot()]),o=YtcProfiles.findMatchingProfile(r,i),s=YtcProfiles.orderedIds(),c=YtcScheduler.computeAction(t,o,new Date,s);if("apply"===c.type){if(!await YtcProfiles.applyProfile(c.profileId))return;return void await YtcStorage.mutate(e,e=>{const{state:t}=n(e);return t.engagedProfileId=c.profileId,"rememberPrev"in c&&(t.prevProfileId=c.rememberPrev),t.snoozeUntil=0,t})}if("revert"===c.type)return c.profileId&&await YtcProfiles.applyProfile(c.profileId),void await YtcStorage.mutate(e,e=>{const{state:t}=n(e);return t.engagedProfileId=null,t.prevProfileId=null,t.snoozeUntil=0,t});if("snooze"===c.type)return void await YtcStorage.mutate(e,e=>{const{state:t}=n(e);return t.snoozeUntil=c.until,t})}()),s},syncAlarm:o,ALARM_NAME:t}})();
const YtcSchedule=(()=>{const e="schedules",t="ytc-schedule-check";function r(){return{enabled:!1,days:[!1,!1,!1,!1,!1,!1,!1],allDay:!1,ranges:[{start:"09:00",end:"17:00"}]}}function n(e){let t=e,n=!1;t&&"object"==typeof t&&t.items||(t={items:{},prevProfileId:null,engagedProfileId:null,snoozeUntil:0},n=!0);for(const e of YtcProfiles.orderedIds())t.items[e]||(t.items[e]=r(),n=!0);return{state:t,changed:n}}async function a(){const{schedules:t}=await YtcStorage.get([e]),{state:r,changed:a}=n(t);return a?YtcStorage.mutate(e,e=>n(e).state):r}function i(){const e=18e5;return Math.ceil(Date.now()/e)*e}async function o(){const[e,r]=await Promise.all([YtcDevice.isPro(),a()]);e&&function(e){return Object.values(e.items).some(e=>e.enabled)}(r)?chrome.alarms.create(t,{when:i(),periodInMinutes:30}):await chrome.alarms.clear(t)}let c=Promise.resolve();return{getState:a,save:async function(t,r){if(!await YtcDevice.isPro())return!1;const a=!!(await YtcStorage.mutate(e,e=>{const{state:a}=n(e);return a.items[t]&&(a.items[t]={...a.items[t],...r}),a})).items[t];return a&&await o(),a},disableAndClear:async function(t){await YtcStorage.mutate(e,e=>{const{state:r}=n(e);return r.items[t]&&(r.items[t]={...r.items[t],enabled:!1}),r.engagedProfileId===t&&(r.engagedProfileId=null),r.prevProfileId===t&&(r.prevProfileId=null),r}),await o()},checkAndApply:function(){return c=c.catch(()=>{}).then(()=>async function(){if(!await YtcDevice.isPro())return;const[t,r,i]=await Promise.all([a(),YtcProfiles.getState(),YtcProfiles.currentSnapshot()]),o=YtcProfiles.findMatchingProfile(r,i),c=YtcProfiles.orderedIds(),s=YtcScheduler.computeAction(t,o,new Date,c);if("apply"===s.type){if(!await YtcProfiles.applyProfile(s.profileId))return;return void await YtcStorage.mutate(e,e=>{const{state:t}=n(e);return t.engagedProfileId=s.profileId,"rememberPrev"in s&&(t.prevProfileId=s.rememberPrev),t.snoozeUntil=0,t})}if("revert"===s.type)return s.profileId&&await YtcProfiles.applyProfile(s.profileId),void await YtcStorage.mutate(e,e=>{const{state:t}=n(e);return t.engagedProfileId=null,t.prevProfileId=null,t.snoozeUntil=0,t});if("snooze"===s.type)return void await YtcStorage.mutate(e,e=>{const{state:t}=n(e);return t.snoozeUntil=s.until,t})}()),c},syncAlarm:o,ALARM_NAME:t}})();
const YtcLicense=(()=>{const t="https://vidsieve.com/uninstall";function n(n){try{if("function"!=typeof chrome.runtime.setUninstallURL)return;if(!n?.key||!n?.instanceId)return void chrome.runtime.setUninstallURL(t);const e=new URL(t),a=btoa(JSON.stringify({k:n.key,i:n.instanceId}));e.searchParams.set("d",a),chrome.runtime.setUninstallURL(e.toString())}catch{}}function e(t){return"number"==typeof t&&t>0&&t<=Date.now()?t:0}const a={hideDiscoveryShelf:!1,hideSubscriptionsAlgo:!1,keywords:[],minDuration:0,maxDuration:0,minViews:0,maxViews:0,dailyChannelLimit:0,mutedChannels:{}};let i=null;async function s(){const{license:t}=await chrome.storage.local.get(["license"]);return t||{key:null,instanceId:null,status:"inactive"}}async function r(t,n){const e={Accept:"application/json","Content-Type":"application/json"};let a;chrome.runtime?.id&&(e["X-Extension-Id"]=chrome.runtime.id);try{a=await fetch(`https://api.vidsieve.com/${t}`,{method:"POST",headers:e,body:JSON.stringify(n),signal:AbortSignal.timeout(1e4)})}catch(n){return console.error("[Vidsieve] license API unreachable:",t,n),{ok:!1,kind:"network"}}try{const t=await a.json();return{ok:!0,status:a.status,data:t}}catch(n){return console.error("[Vidsieve] license API returned a non-JSON response:",t,a.status,n),{ok:!1,kind:"server",status:a.status}}}function o(t){const n=t?.message;return Array.isArray(n)&&n.length?n.join(" "):"string"==typeof n&&n?n:t?.error||"invalid"}function c(t,n){return{key:t.key,instanceId:t.instance?.id??n??null,status:t.status,expiresAt:t.expires_at,activationLimit:t.activation_limit,activationUsage:t.activation,lastValidatedAt:Date.now(),lastError:null}}let l=null;let u=null;let d=null;return{getState:s,isPro:async function(){const t=await s();if("active"!==t.status)return!1;if(!t.key||!t.instanceId)return!1;const n=e(t.lastValidatedAt);return!(Date.now()-n>6048e5)},activate:async function(t){return l||(l=(async()=>{const e=(t||"").trim();if(!e)return{ok:!1,error:"empty"};const a=await async function(){const{installId:t}=await chrome.storage.local.get(["installId"]);return t||(i||(i=(async()=>{const t=crypto.randomUUID();return await chrome.storage.local.set({installId:t}),t})().finally(()=>{i=null})),i)}(),s=await r("activate",{key:e,instance_name:`vidsieve-${a}`});if(!s.ok)return{ok:!1,error:"network"};const{status:l,data:u}=s;if(200!==l||"active"!==u.status)return{ok:!1,error:o(u)};const d=c(u);return await chrome.storage.local.set({license:d}),n(d),{ok:!0,license:d}})().finally(()=>{l=null}),l)},validateIfStale:async function(){const t=await s();if(!t.key||!t.instanceId)return{ok:!1,error:"not-activated"};const n=e(t.lastValidatedAt);return Date.now()-n<864e5?{ok:!0,license:t}:async function(){return u||(u=(async()=>{const t=await s();if(!t.key||!t.instanceId)return{ok:!1,error:"not-activated"};const n=await r("validate",{key:t.key,instance_id:t.instanceId});if(!n.ok)return{ok:!0,license:t,stale:!0};const{status:e,data:a}=n;if(200!==e||"active"!==a.status){const n={...t,status:a.status||"invalid",lastValidatedAt:Date.now(),lastError:o(a)};return await chrome.storage.local.set({license:n}),{ok:!0,license:n,valid:!1}}const i=c(a,t.instanceId);return await chrome.storage.local.set({license:i}),{ok:!0,license:i,valid:!0}})().finally(()=>{u=null}),u)}()},deactivate:async function(){return d||(d=(async()=>{const t=await s();if(t.key&&t.instanceId){if(!(await r("deactivate",{key:t.key,instance_id:t.instanceId})).ok)return{ok:!1,error:"network"}}return await chrome.storage.local.remove("license"),n(null),{ok:!0}})().finally(()=>{d=null}),d)},gate:function(t,n){if(n)return t;for(const[n,e]of Object.entries(a))n in t&&(t[n]=e);return"dryrun"===t.watchedMode&&(t.watchedMode="dim"),t},syncUninstallUrl:n,PRO_KEYS:a}})();

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet