Widok kart YouTube, pobieranie i inne funkcje ↴
// ==UserScript== // @name YouTube + // @name:ar YouTube + // @name:az YouTube + // @name:be YouTube + // @name:bg YouTube + // @name:zh-CN YouTube + // @name:de YouTube + // @name:nl YouTube + // @name:en YouTube + // @name:es YouTube + // @name:fr YouTube + // @name:hi YouTube + // @name:id YouTube + // @name:it YouTube + // @name:ja YouTube + // @name:kk YouTube + // @name:ko YouTube + // @name:ky YouTube + // @name:pl YouTube + // @name:pt YouTube + // @name:tr YouTube + // @name:zh-TW YouTube + // @name:uk YouTube + // @name:uz YouTube + // @name:vi YouTube + // @namespace by // @version 2.5.2 // @author diorhc // @description Вкладки для информации, комментариев, видео, плейлиста и скачивание видео и другие функции ↴ // @description:ar Tabview YouTube and download and other features ↴ // @description:az Tabview YouTube və yükləmə və digər xüsusiyyətlər ↴ // @description:be Tabview YouTube і загрузка і іншыя функцыі ↴ // @description:bg Tabview YouTube и изтегляне и други функции ↴ // @description:zh-CN 标签视图 YouTube、下载及其他功能 ↴ // @description:de Tabview YouTube und Download und andere Funktionen ↴ // @description:nl Tabview YouTube en Download en andere functies ↴ // @description:en Tabview YouTube and Download and others features ↴ // @description:es Vista de pestañas de YouTube, descarga y otras funciones ↴ // @description:fr Tabview YouTube et Télécharger et autres fonctionnalités ↴ // @description:hi YouTube टैब व्यू, डाउनलोड और अन्य सुविधाएँ ↴ // @description:id Tampilan tab YouTube, unduh, dan fitur lainnya ↴ // @description:it Vista a schede per YouTube, download e altre funzionalità ↴ // @description:ja タブビューYouTubeとダウンロードおよびその他の機能 ↴ // @description:kk Tabview YouTube және жүктеу және басқа функциялар ↴ // @description:ko Tabview YouTube 및 다운로드 및 기타 기능 ↴ // @description:ky Tabview YouTube жана жүктөө жана башка функциялар ↴ // @description:pl Widok kart YouTube, pobieranie i inne funkcje ↴ // @description:pt Visualização em abas do YouTube, download e outros recursos ↴ // @description:tr Sekmeli Görünüm YouTube ve İndir ve diğer özellikler ↴ // @description:zh-TW 標籤檢視 YouTube 及下載及其他功能 ↴ // @description:uk Перегляд вкладок YouTube, завантаження та інші функції ↴ // @description:uz YouTube uchun tabview va yuklab olish va boshqa xususiyatlar ↴ // @description:vi Chế độ tab cho YouTube, tải xuống và các tính năng khác ↴ // @match *://*.youtube.com/* // @match *://myactivity.google.com/* // @exclude *://accounts.youtube.com/* // @exclude *://www.youtube.com/live_chat_replay* // @exclude *://www.youtube.com/persist_identity* // @exclude /^https?://\w+\.youtube\.com\/live_chat.*$/ // @exclude /^https?://\S+\.(txt|png|jpg|jpeg|gif|xml|svg|manifest|log|ini)[^\/]*$/ // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com // @license MIT // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/browser-id3-writer.min.js#sha256=c8870af850bb4a06059f0eb8318f80fab2e78015c0723114a656bf92c613d2f5 // @require https://cdn.jsdelivr.net/npm/[email protected]/dayjs.min.js#sha256=9cfdb93f38afcf2d076abecd66d32bfd3383cdf1967654ebc26a26605daf4173 // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_addValueChangeListener // @grant GM_xmlhttpRequest // @grant unsafeWindow // @grant GM_addElement // @connect api.livecounts.io // @connect livecounts.io // @connect cnv.cx // @connect mp3yt.is // @connect returnyoutubedislikeapi.com // @connect translate.googleapis.com // @connect ldpccocxlrdsyejfhrvc.supabase.co // @connect raw.githubusercontent.com // @connect cdn.jsdelivr.net // @connect greasyfork.org // @connect update.greasyfork.org // @connect youtube.com // @connect www.youtube.com // @connect m.youtube.com // @connect i.ytimg.com // @connect ytimg.com // @connect yt3.ggpht.com // @connect fonts.googleapis.com // @connect self // @run-at document-start // @noframes // @homepageURL https://github.com/diorhc/YTP // @supportURL https://github.com/diorhc/YTP/discussions // ==/UserScript== !(function() { const t = setTimeout, e = "low", o = "medium", r = "high", i = "critical", a = { maxErrors: 10, errorWindow: 6e4, enableLogging: !0, enableRecovery: !0, storageKey: "youtube_plus_errors", maxPersistAge: 864e5, maxStackLines: 3 }, s = { errors: [], errorCount: 0, lastErrorTime: 0, isRecovering: !1 }, c = t => { const a = t.message?.toLowerCase() || ""; return a.includes("cannot read") || a.includes("undefined") || a.includes("null") ? o : a.includes("network") || a.includes("fetch") || a.includes("timeout") ? e : a.includes("syntax") || a.includes("reference") || a.includes("type") ? r : a.includes("security") || a.includes("csp") ? i : o; }, l = () => { const t = Date.now() - 6e4; return s.errors.filter(e => new Date(e.timestamp).getTime() > t).length; }, d = () => { const t = Date.now() - a.errorWindow; return s.errors.filter(e => new Date(e.timestamp).getTime() > t).length >= a.maxErrors; }, u = t => { try { const a = window.YouTubeUtils; if (!a?.NotificationManager || "function" != typeof a.NotificationManager.show) { return; } const s = c(t); let l = "An error occurred", d = 3e3; s === e ? (l = "A minor issue occurred. Functionality should continue normally.", d = 2e3) : s === o ? (l = "An error occurred. Some features may not work correctly.", d = 3e3) : s === r ? (l = "A serious error occurred. Please refresh the page if issues persist.", d = 5e3) : s === i && (l = "A critical error occurred. YouTube+ may not function properly. Please report this issue.", d = 7e3), a.NotificationManager.show(l, { duration: d, type: "error" }); } catch (t) {} }, p = (o, r) => { if (!a.enableRecovery || s.isRecovering) { return; } const d = c(o); if (d !== i) { s.isRecovering = !0; try { d !== e && l() <= 5 && u(o), window.YouTubePlusErrorRecovery?.attemptRecovery && window.YouTubePlusErrorRecovery.attemptRecovery(o, r), t(() => { s.isRecovering = !1; }, 5e3); } catch (t) { s.isRecovering = !1; } } else { u(o); } }, y = (t, e = {}) => { if (!a.enableLogging) { return; } const o = t instanceof Error ? t : new Error(String(t)), r = o.message?.trim() || ""; if (!(r || o.stack || e.filename)) { return; } const i = r || (e.filename ? `Error in ${e.filename}:${e.lineno}` : "Unknown error"), l = o.stack?.split("\n").slice(0, a.maxStackLines).join("\n") || "", d = { timestamp: (new Date).toISOString(), message: i, stack: l, severity: c(o), context: { url: window.location.pathname, ...e } }; try { const t = window.YouTubePlusLogger; t && "function" == typeof t.error && t.error("ErrorBoundary", i, d); } catch (t) {} s.errors.push(d), s.errors.length > 50 && s.errors.shift(); try { const t = Date.now(), e = JSON.parse(localStorage.getItem(a.storageKey) || "[]"), o = Array.isArray(e) ? e.filter(e => { const o = "string" == typeof e?.timestamp ? new Date(e.timestamp).getTime() : 0; return t - o < a.maxPersistAge; }) : []; o.push(d), o.length > 20 && o.shift(), localStorage.setItem(a.storageKey, JSON.stringify(o)); } catch (t) { "undefined" != typeof console && console.warn && console.warn("[YouTube+ ErrorBoundary] localStorage write failed:", t); } }, m = { withErrorBoundary: (t, e = "unknown") => function(...o) { try { return t.call(this, ...o); } catch (t) { const o = t instanceof Error ? t : new Error(String(t)); return y(o, { module: e }), p(o, { module: e }), null; } }, withAsyncErrorBoundary: (t, e = "unknown") => async function(...o) { try { return await t.call(this, ...o); } catch (t) { const o = t instanceof Error ? t : new Error(String(t)); return y(o, { module: e }), p(o, { module: e }), null; } }, getErrorStats: () => ({ totalErrors: s.errorCount, recentErrors: s.errors.length, lastErrorTime: s.lastErrorTime, isRecovering: s.isRecovering, errorsByType: s.errors.reduce((t, e) => (t[e.severity] = (t[e.severity] || 0) + 1, t), {}) }), clearErrors: () => { s.errors = [], s.errorCount = 0, s.lastErrorTime = 0; try { localStorage.removeItem(a.storageKey); } catch (t) { "undefined" != typeof console && console.warn && console.warn("[YouTube+ ErrorBoundary] localStorage remove failed:", t); } }, logError: y, getErrorRate: l, config: a }; "undefined" != typeof window && (window.addEventListener("error", t => { const e = t.error || new Error(t.message), o = (e.message || t.message || "").trim(); if (o.includes("ResizeObserver loop")) { return !1; } const r = t.filename || "", i = r && !r.startsWith(window.location.origin) && !/YouTube\+/.test(r); if (!o && i) { return !1; } if (!o || "(no message)" === o && i) { return !1; } if (s.errorCount++, s.lastErrorTime = Date.now(), y(e, { type: "uncaught", filename: t.filename, lineno: t.lineno, colno: t.colno }), d()) { try { const t = window.YouTubePlusLogger; t && "function" == typeof t.error && t.error("ErrorBoundary", "Error rate exceeded"); } catch (t) {} return !1; } return p(e, { type: "uncaught" }), !1; }, !0), window.addEventListener("unhandledrejection", t => { const e = t.reason instanceof Error ? t.reason : new Error(String(t.reason)); if (s.errorCount++, s.lastErrorTime = Date.now(), y(e, { type: "unhandledRejection", promise: t.promise }), d()) { try { const t = window.YouTubePlusLogger; t && "function" == typeof t.error && t.error("ErrorBoundary", "Promise rejection rate exceeded"); } catch (t) {} } else { p(e, { type: "unhandledRejection" }); } }, !0), window.YouTubePlusErrorBoundary = m, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusErrorBoundary = m)); })(), (function() { function t(t, e, o, r) { if (a[t] > a[l]) { return; } if (!(function(t) { const e = Date.now(), o = c.get(t); return !o || e > o.resetTime ? (c.set(t, { count: 1, resetTime: e + 6e4 }), !0) : !(o.count >= 60 || (o.count++, 0)); })(e)) { return; } const i = (function(t, e, o) { return `[YouTube+][${e}][${t.toUpperCase()}] ${o}`; })(t, e, o), d = void 0 !== r ? (function(t) { if (t instanceof Error) { return { o: !0, name: t.name, message: t.message, stack: t.stack }; } if (null === t || "object" != typeof t) { return t; } try { return JSON.stringify(t), t; } catch (e) { return String(t); } })(r) : void 0, u = { timestamp: Date.now(), level: t, module: e, message: o, data: d }; s.push(u), s.length > 200 && s.splice(0, s.length - 200), "error" === t ? void 0 !== d ? console.error(i, d) : console.error(i) : "warn" === t && (void 0 !== d ? console.warn(i, d) : console.warn(i)); } function e() { return window.YouTubePlusErrorBoundary || null; } const o = "undefined" != typeof module && module && "function" == typeof require ? require : null, r = o && !window.YouTubePlusErrorBoundary ? () => { try { o("./error-boundary.js"); } catch (t) {} } : null; r && r(); const i = window.YouTubeUtils, a = { error: 0, warn: 1, info: 2, debug: 3 }, s = [], c = new Map; let l = (function() { try { if ("undefined" != typeof window) { if (window.__ytpDevMode) { return !0; } const t = window.YouTubePlusSettingsStore; if (t && "function" == typeof t.get) { if (t.get("debugMode")) { return !0; } } else { const t = localStorage.getItem("youtube_plus_settings"); if (t) { const e = JSON.parse(t); if (e?.debugMode) { return !0; } } } } } catch (t) { i?.logSuppressed?.(t, "Logger"); } return !1; })() ? "debug" : "warn"; const d = { error(e, o, r) { t("error", e, o, r); }, warn(e, o, r) { t("warn", e, o, r); }, info(e, o, r) { t("info", e, o, r); }, debug(e, o, r) { t("debug", e, o, r); }, setLevel(t) { void 0 !== a[t] && (l = t); }, getLevel: () => l, getRecent(t, e) { let o = s; return e && (o = o.filter(t => t.level === e)), o.slice(-("number" == typeof t ? t : 50)); }, export: () => JSON.stringify(s, null, 2), clear() { s.length = 0, c.clear(); }, getStats() { const t = { error: 0, warn: 0, info: 0, debug: 0 }, e = {}; for (const o of s) { t[o.level]++, e[o.module] = (e[o.module] || 0) + 1; } return { totalEntries: s.length, byLevel: t, byModule: e, currentLevel: l }; }, createLogger: e => ({ error(o, r) { t("error", e, o, r); }, warn(o, r) { t("warn", e, o, r); }, info(o, r) { t("info", e, o, r); }, debug(o, r) { t("debug", e, o, r); } }), createChild: e => ({ error(o, r, i) { t("error", `${e}:${o}`, r, i); }, warn(o, r, i) { t("warn", `${e}:${o}`, r, i); }, info(o, r, i) { t("info", `${e}:${o}`, r, i); }, debug(o, r, i) { t("debug", `${e}:${o}`, r, i); } }) }, u = { maxErrors: 10, errorWindow: 6e4, enableLogging: !0, enableRecovery: !0, storageKey: "youtube_plus_errors" }; d.logError = (t, o) => { const r = e(); return r && "function" == typeof r.logError ? r.logError(t, o) : void 0; }, d.withErrorBoundary = (t, o) => { const r = e(); return r && "function" == typeof r.withErrorBoundary ? r.withErrorBoundary(t, o) : t; }, d.withAsyncErrorBoundary = (t, o) => { const r = e(); return r && "function" == typeof r.withAsyncErrorBoundary ? r.withAsyncErrorBoundary(t, o) : t; }, d.getErrorStats = () => { const t = e(); return t && "function" == typeof t.getErrorStats ? t.getErrorStats() : { totalErrors: 0, recentErrors: 0, lastErrorTime: 0, isRecovering: !1, errorsByType: {} }; }, d.clearErrors = () => { const t = e(); t && "function" == typeof t.clearErrors && t.clearErrors(); }, d.getErrorRate = () => { const t = e(); return t && "function" == typeof t.getErrorRate ? t.getErrorRate() : 0; }, d.config = () => { const t = e(); return t?.config ? t.config : u; }, "undefined" != typeof window && (window.YouTubePlusLogger = d, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusLogger = d), window.YouTubePlusErrorBoundary || (window.YouTubePlusErrorBoundary = e())); })(), (function() { if ("undefined" == typeof window) { return; } const t = new Map, e = new Map, o = new Map, r = new Map, i = { LazyLoader: null, i: new Map, register(t, e, o) { this.i.set(t, { fn: e, options: o || {}, loaded: !1 }), this.LazyLoader && "function" == typeof this.LazyLoader.register && this.LazyLoader.register(t, e, o); }, async load(o) { const r = this.i.get(o); if (!r || r.loaded) { return !0; } try { const o = r.options.dependencies || []; for (const r of o) { if (!t.has(r)) { const t = new Promise(t => { const o = e.get(r); if (o) { o.add(() => t(!0)); } else { const o = new Set; o.add(() => t(!0)), e.set(r, o); } }); await t; } } return !(r.options.shouldLoad && !r.options.shouldLoad() || (await r.fn(), r.loaded = !0, 0)); } catch (t) { return !1; } }, async loadAll() { let t = 0; for (const e of this.i.keys()) { await this.load(e) && t++; } return t; }, loadOnIdle(t) { "undefined" != typeof requestIdleCallback ? requestIdleCallback(() => this.loadAll(), { timeout: t }) : setTimeout(() => this.loadAll(), t || 100); }, isLoaded(t) { const e = this.i.get(t); return !!e && e.loaded; }, getStats() { let t = 0, e = 0; for (const o of this.i.values()) { o.loaded ? t++ : e++; } return { loaded: t, pending: e, total: this.i.size }; }, clear() { this.i.clear(); }, async retryBlockedModules() { let t = 0; for (const [e, o] of this.i) { o.loaded || await this.load(e) && t++; } return t; }, attachNavRetry() { this.LazyLoader && "function" == typeof this.LazyLoader.attachNavRetry && this.LazyLoader.attachNavRetry(); }, getStatus() { const t = {}; for (const [e, o] of this.i) { t[e] = o.loaded ? "loaded" : "pending"; } return t; }, getAllEntries() { return [ ...this.i.entries() ].map(([t, e]) => ({ name: t, loaded: e.loaded, options: e.options })); } }, a = { register(o, r) { t.set(o, r); const i = e.get(o); if (i) { for (const t of i) { try { t(r); } catch (t) {} } e.delete(o); } }, get: e => t.has(e) ? t.get(e) : o.has(e) ? o.get(e) : void 0, has: e => t.has(e) || o.has(e), onReady(o, r) { if (t.has(o)) { try { r(t.get(o)); } catch (t) {} } else { e.has(o) || e.set(o, new Set), e.get(o)?.add(r); } }, list: () => [ ...t.keys() ], getStats() { let r = 0; for (const t of e.values()) { r += t.size; } return { modules: t.size, flags: o.size, pendingCallbacks: r }; }, unregister(e) { t.delete(e); }, clear() { t.clear(), o.clear(), e.clear(), r.clear(), i.i.clear(); }, lazyLoader: i, set(t, e) { o.set(t, e); const i = r.get(t); if (i) { for (const t of i) { try { t(e); } catch (t) {} } } }, onChange(t, e) { if (r.has(t) || r.set(t, new Set), r.get(t)?.add(e), o.has(t)) { try { e(o.get(t)); } catch (t) {} } return () => { const o = r.get(t); o && o.delete(e); }; }, all: () => Object.fromEntries(o), deleteFlag(t) { o.delete(t); } }; window.YouTubePlusRegistry = a, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusRegistry = a); })(), (function() { const t = (t, e, o) => { try { const r = o instanceof Error ? o : new Error(e); window.YouTubePlusErrorBoundary?.logError ? window.YouTubePlusErrorBoundary.logError(r, { module: t, message: e }) : window.YouTubeUtils?.logError && window.YouTubeUtils.logError(t, e, o); } catch {} }, e = (function() { const e = new Set, o = new Map, r = { registeredTotal: 0 }, i = new Set, a = new Set, s = new Set, c = new Set, l = new WeakMap; return { registerObserver(t, o) { try { if (t && e.add(t), o && "object" == typeof o) { try { let e = l.get(o); e || (e = new Set, l.set(o, e)), e.add(t); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "CleanupManager" }); } } } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "CleanupManager" }); } return t; }, registerListener(e, i, a, s, c = !1) { try { e.addEventListener(i, a, s); const t = Symbol(); return o.set(t, { target: e, ev: i, fn: a, opts: s, persistent: c }), r.registeredTotal++, t; } catch (e) { return t("cleanupManager", "registerListener failed", e), null; } }, getListenerStats() { try { return { active: o.size, registeredTotal: r.registeredTotal }; } catch (t) { return { active: 0, registeredTotal: 0 }; } }, registerInterval: t => (i.add(t), t), unregisterInterval: t => (i.delete(t), t), registerTimeout: t => (a.add(t), t), registerAnimationFrame: t => (s.add(t), t), register(t) { "function" == typeof t && c.add(t); }, runCallbacks() { for (const e of c) { try { e(); } catch (e) { t("cleanupManager", "callback failed", e); } } c.clear(); }, disconnectObservers() { for (const t of e) { try { t && "function" == typeof t.disconnect && t.disconnect(); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "CleanupManager" }); } } e.clear(); }, removeListeners() { const t = new Set([ "yt-navigate-start", "yt-navigate-finish", "yt-page-data-updated", "yt-page-data-fetched", "popstate", "hashchange", "keydown", "keyup", "keypress", "visibilitychange", "fullscreenchange", "resize", "scroll", "beforeunload" ]), e = [ ...o.entries() ]; for (const [r, i] of e) { if (!i.persistent && !t.has(i.ev)) { try { i.target.removeEventListener(i.ev, i.fn, i.opts); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "CleanupManager" }); } o.delete(r); } } }, clearTimers() { for (const t of i) { clearInterval(t); } i.clear(); for (const t of a) { clearTimeout(t); } a.clear(); for (const t of s) { cancelAnimationFrame(t); } s.clear(); }, cleanup() { try { this.runCallbacks(), this.disconnectObservers(), this.removeListeners(), this.clearTimers(); } catch (e) { t("cleanupManager", "cleanup failed", e); } }, observers: e, elementObservers: l, disconnectForElement(o) { try { const t = l.get(o); if (!t) { return; } for (const o of t) { try { o && "function" == typeof o.disconnect && o.disconnect(), e.delete(o); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "CleanupManager" }); } } l.delete(o); } catch (e) { t("cleanupManager", "disconnectForElement failed", e); } }, disconnectObserver(o) { try { if (!o) { return; } try { "function" == typeof o.disconnect && o.disconnect(); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "CleanupManager" }); } e.delete(o); } catch (e) { t("cleanupManager", "disconnectObserver failed", e); } }, listeners: o, intervals: i, timeouts: a, animationFrames: s }; })(); "undefined" != typeof window && (window.YouTubePlusCleanupManager = e, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusCleanupManager = e), window.YouTubeUtils && !window.YouTubeUtils.cleanupManager && (window.YouTubeUtils.cleanupManager = e)); })(), (function() { if ("undefined" == typeof window) { return; } if (window.YouTubePlusConfig || (window.YouTubePlusConfig = Object.freeze({ enabled: !0, downloaders: { y2mate: !0, xbbuddy: !0 }, debug: !1, performance: { sampleRate: .01 } })), !window.YouTubePlusScrollManager) { const t = new Map; window.YouTubePlusScrollManager = { addScrollListener(e, o, r = {}) { const i = r.debounce || 100; let a = null; const s = () => { a && clearTimeout(a), a = setTimeout(() => o(), i); }; e.addEventListener("scroll", s, { passive: !0 }), t.has(e) || t.set(e, []); const c = { handler: s, cleanup: () => { e.removeEventListener("scroll", s), a && clearTimeout(a); } }; return t.get(e).push(c), r.runInitial && o(), c.cleanup; }, removeAllListeners(e) { const o = t.get(e); if (o) { for (const t of o) { t.cleanup(); } t.delete(e); } } }; } window.YouTubePlusStorage || (window.YouTubePlusStorage = { get(t, e = null) { try { const o = localStorage.getItem(t); return o ? JSON.parse(o) : e; } catch (t) { return e; } }, set(t, e) { try { return localStorage.setItem(t, JSON.stringify(e)), !0; } catch (t) { return !1; } }, remove(t) { try { return localStorage.removeItem(t), !0; } catch (t) { return !1; } } }), void 0 === window.YouTubeUtils && (window.YouTubeUtils = {}); const t = window.YouTubeUtils; t.isSettingsModalOpen || (t.isSettingsModalOpen = () => { try { return Boolean(document.querySelector(".ytp-plus-settings-modal")); } catch (t) { return !1; } }), t.isYouTubeDomain || (t.isYouTubeDomain = () => { try { const t = window.location.hostname || ""; return t.endsWith("youtube.com") && "music.youtube.com" !== t; } catch (t) { return !1; } }), t.isWatchRoute || (t.isWatchRoute = () => { try { return "/watch" === window.location.pathname; } catch (t) { return !1; } }), t.isShortsRoute || (t.isShortsRoute = () => { try { return window.location.pathname.startsWith("/shorts"); } catch (t) { return !1; } }), t.isChannelRoute || (t.isChannelRoute = () => { try { const t = window.location.pathname || ""; return t.startsWith("/channel/") || t.startsWith("/@") || t.startsWith("/c/"); } catch (t) { return !1; } }), t.getHostname || (t.getHostname = () => { try { return window.location.hostname || ""; } catch (t) { return ""; } }), t.isMusicDomain || (t.isMusicDomain = () => "music.youtube.com" === t.getHostname()), t.isStudioDomain || (t.isStudioDomain = () => "studio.youtube.com" === t.getHostname()), t.logSuppressed || (t.logSuppressed = (t, e, o) => { try { const r = window.YouTubePlusErrorBoundary; if (r?.logError) { const i = t instanceof Error ? t : new Error(String(t)); r.logError(i, { module: e, message: o || "Non-critical, suppressed" }); } } catch (t) {} }), "undefined" == typeof window || window.youtubePlus || (window.youtubePlus = {}); const e = (t, e, o, r) => { const i = window.YouTubePlusLogger; if (i && "function" == typeof i[t]) { try { void 0 === r ? i[t](e, o) : i[t](e, o, r); } catch {} } }, o = (t, o, r) => { try { const i = { module: t, message: o, error: r instanceof Error ? { name: r.name, message: r.message, stack: r.stack } : r, timestamp: (new Date).toISOString(), userAgent: "undefined" != typeof navigator ? navigator.userAgent : "unknown", url: "undefined" != typeof window ? window.location.href : "unknown" }; e("error", t, o, r), e("warn", t, "Error details", i); } catch (t) { e("error", "Utils", "Error logging failed", t); } }, r = "youtube_plus_settings", i = (t, e) => { let o, r = !1; return function(...i) { return r || (o = t.apply(this, i), r = !0, setTimeout(() => r = !1, e)), o; }; }, a = (t, o) => { if (!o || "object" != typeof o) { return t; } if (!t || "object" != typeof t) { return t; } const r = [ "__proto__", "constructor", "prototype" ]; for (const i in o) { if (!Object.hasOwn(o, i)) { continue; } if (r.includes(i)) { e("warn", "Security", `Blocked attempt to set dangerous key: ${i}`); continue; } const s = o[i]; t[i] = s && "object" == typeof s && !Array.isArray(s) ? a(t[i] || {}, s) : s; } return t; }, s = { get(t, e = null) { if ("string" != typeof t || !/^[a-zA-Z0-9_\-.]+$/.test(t)) { return o("storage", "Invalid key format", new Error(`Invalid key: ${t}`)), e; } try { const r = localStorage.getItem(t); return null === r ? e : r.length > 5242880 ? (o("storage", "Stored value too large", new Error(`Key: ${t}`)), e) : JSON.parse(r); } catch (t) { return o("storage", "Failed to parse stored value", t), e; } }, set(t, e) { if ("string" != typeof t || !/^[a-zA-Z0-9_\-.]+$/.test(t)) { return o("storage", "Invalid key format", new Error(`Invalid key: ${t}`)), !1; } try { const r = JSON.stringify(e); return r.length > 5242880 ? (o("storage", "Value too large to store", new Error(`Key: ${t}`)), !1) : (localStorage.setItem(t, r), !0); } catch (t) { return o("storage", "Failed to store value", t), !1; } }, remove(t) { try { localStorage.removeItem(t); } catch (t) { o("storage", "Failed to remove value", t); } }, clear() { try { const t = [ "youtube_plus_", "youtube_", "ytp-", "youtube-plus-" ], e = []; for (let o = 0; o < localStorage.length; o++) { const r = localStorage.key(o); r && t.some(t => r.startsWith(t)) && e.push(r); } e.forEach(t => localStorage.removeItem(t)); } catch (t) { o("storage", "Failed to clear storage", t); } }, has(t) { try { return null !== localStorage.getItem(t); } catch (t) { return !1; } } }, c = (() => { let t = 0, o = 0, r = 0, i = 0; return { track() { t++, r++, t > o && (o = t); }, untrack() { t = Math.max(0, t - 1), i++; }, getStats: () => ({ active: t, peak: o, created: r, disconnected: i }), reset() { t = 0, o = 0, r = 0, i = 0; }, dump() { const a = { active: t, peak: o, created: r, disconnected: i }, s = (() => { const t = window.YouTubePlusCleanupManager; if (!t) { return null; } try { return { observers: t.observers?.size ?? "n/a", intervals: t.intervals?.size ?? "n/a", timeouts: t.timeouts?.size ?? "n/a", listeners: "function" == typeof t.getListenerStats ? t.getListenerStats() : "n/a" }; } catch (t) { return null; } })(); return e("warn", "Diagnostics", "ObserverRegistry", a), s && e("warn", "Diagnostics", "CleanupManager", s), { observers: a, cleanup: s }; } }; })(); if (window.__ytpDiagnostics || (window.__ytpDiagnostics = function(t) { const o = c.getStats(), r = (() => { const t = window.YouTubePlusCleanupManager; if (!t) { return null; } try { return { observers: t.observers?.size ?? 0, listeners: "function" == typeof t.getListenerStats ? t.getListenerStats() : { active: 0, registeredTotal: 0 }, intervals: t.intervals?.size ?? 0, timeouts: t.timeouts?.size ?? 0, animationFrames: t.animationFrames?.size ?? 0 }; } catch (t) { return null; } })(), i = { observers: o, cleanupManager: r, timestamp: (new Date).toISOString() }; return e("warn", "Diagnostics", "Observers", o), r && e("warn", "Diagnostics", "CleanupManager", r), t && e("warn", "Diagnostics", JSON.stringify(i, null, 2)), i; }), !window.__ytp_history_wrapped) { window.__ytp_history_wrapped = !0; const t = history.pushState, o = history.replaceState; history.pushState = function() { const o = t.apply(this, arguments); try { window.dispatchEvent(new CustomEvent("ytp-history-navigate", { detail: { type: "pushState" } })); } catch (t) { e("warn", "Utils", "pushState event error", t); } return o; }, history.replaceState = function() { const t = o.apply(this, arguments); try { window.dispatchEvent(new CustomEvent("ytp-history-navigate", { detail: { type: "replaceState" } })); } catch (t) { e("warn", "Utils", "replaceState event error", t); } return t; }; } window.YouTubeUtils || (window.YouTubeUtils = {}); const l = window.YouTubeUtils; Object.getOwnPropertyDescriptor(l, "StyleManager") || Object.defineProperty(l, "StyleManager", { configurable: !0, enumerable: !0, get: () => window.YouTubePlusDesignSystem?.StyleManager || null }), Object.getOwnPropertyDescriptor(l, "cleanupManager") || Object.defineProperty(l, "cleanupManager", { configurable: !0, enumerable: !0, get: () => window.YouTubePlusCleanupManager || null }), Object.getOwnPropertyDescriptor(l, "throttle") || Object.defineProperty(l, "throttle", { configurable: !1, enumerable: !0, get: () => i, set() {} }), Object.getOwnPropertyDescriptor(l, "safeLS") || (l.safeLS = { getItem: (t, e = null) => { try { return localStorage.getItem(t) ?? e; } catch (t) { return e; } }, setItem: (t, e) => { try { return localStorage.setItem(t, e), !0; } catch (t) { return !1; } }, removeItem: t => { try { localStorage.removeItem(t); } catch (t) {} } }), l.logError = l.logError || o, l.debounce = l.debounce || ((t, o, r = {}) => { let i = null, a = null, s = null, c = !1; const l = function(...l) { if (!c) { if (a = l, s = this, null !== i && clearTimeout(i), r.leading && null === i) { try { t.apply(this, l); } catch (t) { e("error", "Utils", "Debounced function error", t); } } i = setTimeout(() => { if (!c && !r.leading) { try { t.apply(s, a); } catch (t) { e("error", "Utils", "Debounced function error", t); } } i = null, a = null, s = null; }, o); } }; return l.cancel = () => { null !== i && clearTimeout(i), i = null, a = null, s = null; }, l.destroy = () => { l.cancel(), c = !0; }, l; }), l.waitForElement = l.waitForElement || ((t, e = 5e3, o = document) => { const r = window.YouTubePlusDOMCache; return r?.waitForElement ? r.waitForElement(t, e, o) : Promise.resolve(o?.querySelector(t) ?? null); }), l.storage = l.storage || s, l.sanitizeHTML = l.sanitizeHTML || (t => "string" != typeof t ? "" : window.YouTubeSafeDOM?.sanitizeHTML?.(t) ?? ""), l.safeMerge = l.safeMerge || a, l.renderTemplateClone = l.renderTemplateClone || ((t, e) => window.YouTubeSafeDOM?.renderTemplateClone?.(t, e)), l.logger = l.logger || (() => { const t = (() => { try { if ("undefined" == typeof window) { return !1; } const t = window.YouTubePlusConfig; return !!t?.debug || void 0 !== window.YTP_DEBUG && !!window.YTP_DEBUG; } catch (t) { return !1; } })(); return { debug: function(...o) { t && e("debug", ...o); }, info: function(...o) { t && e("info", ...o); }, warn: function(...t) { e("warn", ...t); }, error: function(...t) { e("error", ...t); } }; })(), "function" != typeof l.createRetryScheduler && (l.createRetryScheduler = t => { const e = window.YouTubePlusMutationCoordinator; return e?.createRetryScheduler ? e.createRetryScheduler(t) : null; }), l.ObserverRegistry = l.ObserverRegistry || c, l.$ = l.$ || ((t, e) => { const o = window.YouTubePlusDOMCache; return o && "function" == typeof o.querySelector ? o.querySelector(t, e) : o && "function" == typeof o.get && !e ? o.get(t) : (e || document).querySelector(t); }), l.$$ = l.$$ || ((t, e) => { const o = window.YouTubePlusDOMCache; return o && "function" == typeof o.querySelectorAll ? o.querySelectorAll(t, e) : o && "function" == typeof o.getAll && !e ? o.getAll(t) : Array.from((e || document).querySelectorAll(t)); }), l.byId = l.byId || (t => { const e = window.YouTubePlusDOMCache; return e && "function" == typeof e.getElementById ? e.getElementById(t) : document.getElementById(t); }), l.t = l.t || ((t, e = {}) => { if (window.YouTubePlusI18n?.t) { return window.YouTubePlusI18n.t(t, e); } if (!t) { return ""; } let o = String(t); for (const [t, r] of Object.entries(e || {})) { o = o.split(`{${t}}`).join(String(r)); } return o; }), l.createHTML = l.createHTML || (t => "function" == typeof window._ytplusCreateHTML ? window._ytplusCreateHTML(t) : "string" == typeof t ? t : String(t ?? "")), l.getLanguage = l.getLanguage || (() => { if (window.YouTubePlusI18n?.getLanguage) { return window.YouTubePlusI18n.getLanguage(); } const t = document.documentElement?.lang || navigator.language || "en"; return String(t || "en").toLowerCase(); }), l.setSafeHTML = l.setSafeHTML || ((t, e, o = !0) => { t instanceof HTMLElement && (window.YouTubeSafeDOM?.setHTML ? window.YouTubeSafeDOM.setHTML(t, e, { sanitize: o }) : t.replaceChildren(document.createTextNode(String(e || "")))); }), l.loadFeatureEnabled = l.loadFeatureEnabled || ((t, e = !0) => { const o = window.YouTubePlusSettingsStore; if (o && "function" == typeof o.get) { const r = o.get(t, e); return void 0 === r ? e : !1 !== r; } try { const e = localStorage.getItem(r); if (e) { return !1 !== JSON.parse(e)[t]; } } catch (t) { l.logSuppressed(t, "Utils"); } return e; }), l.SETTINGS_KEY = l.SETTINGS_KEY || r, l.isWatchPage = l.isWatchPage || (t => { try { const e = new URL(t || window.location.href); return "/watch" === e.pathname || e.pathname.startsWith("/watch/"); } catch (t) { return !1; } }), l.isShortsPage = l.isShortsPage || (t => { try { return new URL(t || window.location.href).pathname.startsWith("/shorts/"); } catch (t) { return !1; } }), l.isChannelPage = l.isChannelPage || (t => { try { const e = new URL(t || window.location.href).pathname || ""; return e.startsWith("/@") || e.startsWith("/channel/") || e.startsWith("/c/") || e.startsWith("/user/"); } catch (t) { return !1; } }), l.isStudioPage = l.isStudioPage || (() => { try { return t.isStudioDomain?.() ?? !1; } catch (t) { return !1; } }), l.onDomReady = l.onDomReady || (t => { "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", t, { once: !0 }) : t(); }), l.formatTime = l.formatTime || (t => { const e = Number.isFinite(t) && t > 0 ? t : 0, o = Math.floor(e % 60).toString().padStart(2, "0"), r = Math.floor(e / 60 % 60).toString(), i = Math.floor(e / 3600); return i ? `${i}:${r.padStart(2, "0")}:${o}` : `${r}:${o}`; }), l.createVisibilityAwareInterval = l.createVisibilityAwareInterval || ((t, e) => { let o = null, r = null, i = !1; const a = window.YouTubeUtils?.cleanupManager || window.YouTubePlusCleanupManager, s = () => { null === o && (o = setInterval(() => { document.hidden || t(); }, e), a && "function" == typeof a.registerInterval && (r = a.registerInterval(o))); }; return s(), { stop() { if (null !== o && (clearInterval(o), o = null), a && null !== r && "function" == typeof a.unregisterInterval) { try { a.unregisterInterval(r); } catch (t) {} r = null; } }, pause() { null !== o && (clearInterval(o), o = null), i = !0; }, resume() { null === o && i && (i = !1, s()); }, get active() { return null !== o; } }; }), "function" != typeof l.safeSetTimeout && (l.safeSetTimeout = function(t, e, ...o) { const r = setTimeout(t, e, ...o); try { l.cleanupManager?.registerTimeout?.(r); } catch (t) { l.logSuppressed(t, "Utils"); } return r; }), "function" != typeof l.safeSetInterval && (l.safeSetInterval = function(t, e, ...o) { const r = setInterval(t, e, ...o); try { l.cleanupManager?.registerInterval?.(r); } catch (t) { l.logSuppressed(t, "Utils"); } return r; }), "function" != typeof l.safeRequestAnimationFrame && (l.safeRequestAnimationFrame = function(t) { const e = requestAnimationFrame(t); try { l.cleanupManager?.registerAnimationFrame?.(e); } catch (t) { l.logSuppressed(t, "Utils"); } return e; }), l.helpers = l.helpers || { $: l.$, $$: l.$$, byId: l.byId, t: l.t, logger: l.logger || null, createHTML: l.createHTML, debounce: l.debounce, setTimeout_: setTimeout.bind(window), onDomReady: l.onDomReady }; const d = Object.freeze([ "yt-navigate-finish", "yt-page-data-updated", "youtube-plus-settings-modal-opened", "youtube-plus-settings-updated" ]); l.whenRelevant = l.whenRelevant || (t => { const e = t.name || "whenRelevant"; let o = !1; const r = () => { let r = !1; try { r = !!t.isRelevant(); } catch (t) { l.logger?.error?.(e, "isRelevant threw; treating as inactive", t), r = !1; } r && !o ? (() => { if ("function" == typeof t.onEnter) { try { t.onEnter(), o = !0; } catch (t) { l.logger?.error?.(e, "onEnter failed; will retry on next signal", t), o = !1; } } else { o = !0; } })() : !r && o && (() => { if ("function" == typeof t.onLeave) { try { t.onLeave(); } catch (t) { l.logger?.error?.(e, "onLeave failed; ignoring", t); } finally { o = !1; } } else { o = !1; } })(); }, i = (t.signals || d).map(t => { const e = () => r(), o = "youtube-plus-settings-updated" === t ? window : document; return o.addEventListener(t, e), { target: o, name: t, handler: e }; }); return r(), { get active() { return o; }, check: r, dispose: () => { for (const t of i) { t.target.removeEventListener(t.name, t.handler); } i.length = 0; } }; }), l.on = l.on || ((t, e, o, r) => { const i = o; return t.addEventListener(e, i, r), () => { try { t.removeEventListener(e, i, r); } catch (t) {} }; }), l.group = l.group || ((...t) => () => { for (const e of t) { try { e(); } catch (t) {} } }), l.onSectionActive = l.onSectionActive || ((t, e, o) => { let r = !1; const i = o => { const i = o?.detail; if (i && i.section === t) { r = !0; try { e(); } catch (e) { l.logger?.error?.("onSectionActive", `onEnter for "${t}" failed`, e), r = !1; } } }, a = e => { if (!r) { return; } const i = e?.detail; if ((!i || i.section !== t) && (r = !1, "function" == typeof o)) { try { o(); } catch (e) { l.logger?.error?.("onSectionActive", `onLeave for "${t}" failed`, e); } } }; return document.addEventListener("youtube-plus-settings-section-activated", i), document.addEventListener("youtube-plus-settings-modal-closed", a), { dispose: () => { document.removeEventListener("youtube-plus-settings-section-activated", i), document.removeEventListener("youtube-plus-settings-modal-closed", a); } }; }), l.getVideoIdFromUrl = l.getVideoIdFromUrl || (t => { try { return new URLSearchParams(new URL(t).search).get("v"); } catch (t) { return null; } }), l.getVideoIdFromLocation = l.getVideoIdFromLocation || (() => { try { const t = new URLSearchParams(window.location.search || "").get("v"); if (t) { return t; } const e = window.location.pathname || "", o = e.match(/^\/shorts\/([a-zA-Z0-9_-]{11})/); if (o?.[1]) { return o[1]; } const r = e.match(/^\/live\/([a-zA-Z0-9_-]{11})/); if (r?.[1]) { return r[1]; } const i = (window.location.href || "").match(/youtu\.be\/([a-zA-Z0-9_-]{11})/); if (i?.[1]) { return i[1]; } } catch (t) {} return null; }), l.injectModuleStyles = l.injectModuleStyles || ((t, e, o) => { try { const o = l.StyleManager; if (o && "function" == typeof o.add) { return void o.add(t, e); } } catch (t) {} try { let r = document.getElementById(t); r || (r = document.createElement("style"), r.id = t, (o || document.head || document.documentElement).appendChild(r)), r.textContent = e; } catch (t) {} }); try { const t = window; t.p || (t.p = !0, document.addEventListener("yt-navigate-start", () => { try { l.cleanupManager?.cleanup?.(); } catch (t) {} })); } catch (t) {} })(), (function() { if ("undefined" == typeof document || !document.documentElement) { return; } const t = document.documentElement, e = "__ytplusThemeSync", o = "undefined" != typeof window ? window : {}; if (o[e]) { return; } o[e] = !0; const r = () => { try { if (t.hasAttribute("dark")) { return "dark"; } const e = document.querySelector("ytd-app, ytmusic-app"); if (e instanceof Element && e.hasAttribute("dark")) { return "dark"; } const o = document.body; if (o?.hasAttribute("dark")) { return "dark"; } } catch (t) {} return "light"; }; let i = !1, a = !1, s = null; const c = () => { i = !1; const e = r(); if (e !== s) { a = !0; try { s = e, "dark" === e ? (t.removeAttribute("light"), t.setAttribute("data-ytp-theme", "dark")) : (t.setAttribute("light", ""), t.setAttribute("data-ytp-theme", "light")); } finally { a = !1; } } }, l = () => { i || a || (i = !0, "function" == typeof requestAnimationFrame ? requestAnimationFrame(c) : setTimeout(c, 0)); }; c(); const d = "undefined" != typeof window ? window.YouTubePlusMutationCoordinator : null; d && "function" == typeof d.subscribeRoot && d.subscribeRoot("design-system:theme-sync", e => { if (!a) { for (const o of e) { if ("attributes" === o.type) { if ("data-ytp-theme" === o.attributeName) { continue; } if ("dark" === o.attributeName || "light" === o.attributeName) { if (t.hasAttribute("dark") === ("dark" === s)) { continue; } return void l(); } } else if ("childList" === o.type && o.addedNodes.length > 0) { return void l(); } } } }, { attributes: !0, attributeFilter: [ "dark", "light", "data-ytp-theme" ], childList: !0, subtree: !0 }); try { if ("undefined" != typeof window && window.matchMedia) { const t = window.matchMedia("(prefers-color-scheme: dark)"), e = () => l(); "function" == typeof t.addEventListener ? t.addEventListener("change", e) : "function" == typeof t.addListener && t.addListener(e); } } catch (t) {} "undefined" != typeof window && (window.YouTubePlusDesignSystem = { ...window.YouTubePlusDesignSystem || {}, resolveTheme: r, syncTheme: l }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDesignSystem = window.YouTubePlusDesignSystem)); })(), (function() { const t = window.YouTubePlusLogger || window.YouTubeUtils?.logger || null, e = window.YouTubeUtils, o = "youtube-plus-styles", r = new Map; let i = null, a = !1, s = null, c = null, l = null, d = null, u = !1; const p = () => Array.from(r.values()).join("\n\n"), y = () => { if (d) { return; } if ("undefined" == typeof MutationObserver) { return; } const t = i?.isConnected ? i : f(); if (!t) { return; } d = new MutationObserver(() => { b(); }); try { d.observe(t, { childList: !0, characterData: !0, subtree: !0 }); } catch (t) {} const o = t.parentNode; if (o) { try { d.observe(o, { childList: !0, subtree: !1 }); } catch (t) {} } const r = "undefined" != typeof window && window.YouTubePlusCleanupManager || "undefined" != typeof window && e && e.cleanupManager || null; if (r && "function" == typeof r.registerObserver) { try { r.registerObserver(d); } catch (t) {} } }, m = () => { if ("undefined" != typeof process && "test" === process.env?.NODE_ENV) { return u = !1, void h(); } u || (u = !0, "function" == typeof requestAnimationFrame ? requestAnimationFrame(() => { u = !1, h(); }) : setTimeout(() => { u = !1, h(); }, 0)); }, f = () => { if (i?.isConnected) { return i; } const t = document.getElementById(o); if (t) { return i = t, y(), i; } if (!document.head && !document.documentElement) { return null; } const e = document.createElement("style"); if (e.id = o, e.type = "text/css", (document.head || document.documentElement).appendChild(e), i = e, d) { try { d.disconnect(); } catch (t) {} d = null; } return y(), i; }, b = () => { if (0 === r.size) { return; } const t = i?.isConnected ? i : document.getElementById(o), e = p(); t && t.textContent === e ? i = t : m(); }; (() => { if ("undefined" == typeof MutationObserver) { return; } if (!c && document.documentElement) { c = new MutationObserver(() => { const t = document.head || document.documentElement; if (t !== l) { if (s) { try { s.disconnect(); } catch (t) {} s = null; } if (l = t, t) { s = new MutationObserver(() => { b(); }); try { s.observe(t, { childList: !0, subtree: !1 }); } catch (t) { s = null; } } } b(); }); try { c.observe(document.documentElement, { childList: !0, subtree: !1 }); } catch (t) { c = null; } const t = "undefined" != typeof window && window.YouTubePlusCleanupManager || "undefined" != typeof window && e && e.cleanupManager || null; if (t && "function" == typeof t.registerObserver && c) { try { t.registerObserver(c); } catch (t) {} } } const t = document.head || document.documentElement; if (!s && t) { l = t, s = new MutationObserver(() => { b(); }); try { s.observe(t, { childList: !0, subtree: !1 }); } catch (t) { s = null; } const o = "undefined" != typeof window && window.YouTubePlusCleanupManager || "undefined" != typeof window && e && e.cleanupManager || null; if (o && "function" == typeof o.registerObserver && s) { try { o.registerObserver(s); } catch (t) {} } } })(); const h = () => { try { const t = f(), e = p(); if (t) { return void (t.textContent !== e && (t.textContent = e)); } if (a) { return; } a = !0, document.addEventListener("DOMContentLoaded", () => { a = !1; const t = f(); if (!t) { return; } const e = p(); t.textContent !== e && (t.textContent = e); }, { once: !0 }); } catch (e) { t?.error?.("design-system", "StyleManager render failed", e); } }, g = e => { try { if ("string" != typeof e || !e) { return; } if (!r.has(e)) { return; } r.delete(e), m(); } catch (o) { t?.error?.("design-system", `StyleManager remove('${e}') failed`, o); } }, w = { hostId: o, styles: r, has: t => r.has(t), get: t => "string" == typeof t && r.has(t) ? r.get(t) : "", add: (e, a) => { try { if ("string" != typeof e || !e) { return; } if ("string" != typeof a) { return; } if ("" === a) { return void g(e); } if (y(), r.get(e) === a) { const t = i?.isConnected ? i : document.getElementById(o); return void (t && t.textContent === p() || m()); } r.set(e, a), m(); } catch (o) { t?.error?.("design-system", `StyleManager add('${e}') failed`, o); } }, remove: g, clear: () => { try { if (r.clear(), i && (i.remove(), i = null), d) { try { d.disconnect(); } catch (t) {} d = null; } } catch (e) { t?.error?.("design-system", "StyleManager clear failed", e); } }, size: () => r.size, ids: () => Array.from(r.keys()), get host() { return i; } }; "undefined" != typeof window && (window.YouTubePlusDesignSystem = { ...window.YouTubePlusDesignSystem || {}, StyleManager: window.YouTubePlusDesignSystem?.StyleManager || w, repairStyles: b, inspectStyles: () => { const t = i?.isConnected ? i : document.getElementById(o), e = p(); return { hostPresent: !!t, hostConnected: !!t?.isConnected, hostTextLength: t?.textContent?.length || 0, expectedTextLength: e.length, registeredStyleIds: Array.from(r.keys()), textMatchesExpected: (t?.textContent || "") === e }; } }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDesignSystem = window.YouTubePlusDesignSystem)), w.add("yt-plus-design-system", '\n :root{\n --yt-accent:#ff0000;\n --yt-accent-secondary:#1976d2;\n --yt-accent-secondary-light:#42a5f5;\n --yt-accent-secondary-ghost:rgba(25,118,210,0.28);\n --yt-accent-secondary-light-ghost:rgba(66,165,245,0.4);\n --yt-accent-secondary-shadow:rgba(25,118,210,0.25);\n --yt-primary-soft:rgba(33,150,243,.12);\n --yt-primary-soft-hover:rgba(33,150,243,.22);\n --yt-primary-border:rgba(33,150,243,.25);\n --yt-primary-text:#2196f3;\n --yt-surface-soft:rgba(255,255,255,.08);\n --yt-surface-active:rgba(255,255,255,.12);\n --yt-surface-active-strong:rgba(255,255,255,.14);\n --yt-surface-border-strong:rgba(255,255,255,.15);\n --yt-surface-overlay-soft:rgba(255,255,255,.1);\n --yt-surface-overlay-subtle:rgba(255,255,255,.04);\n --yt-surface-overlay-faint:rgba(255,255,255,.02);\n --yt-surface-overlay-border:rgba(255,255,255,.06);\n --yt-danger-soft:rgba(255,59,59,0.15);\n --yt-danger-soft-hover:rgba(255,59,59,0.25);\n --yt-danger-border:rgba(255,59,59,0.3);\n --yt-danger-text:#ff5c5c;\n --yt-danger-ghost:rgba(255,0,0,.12);\n --yt-danger-shadow:rgba(255,0,0,.3);\n --yt-danger-shadow-strong:rgba(255,0,0,.35);\n --yt-danger-card-bg-start:rgba(255,0,0,.28);\n --yt-danger-card-bg-end:rgba(255,0,0,.16);\n --yt-danger-card-border:rgba(255,0,0,.45);\n --yt-danger-card-inset:rgba(255,0,0,.22);\n --yt-success:#4caf50;\n --yt-success-soft:rgba(76,175,80,0.2);\n --yt-success-soft-hover:rgba(76,175,80,.22);\n --yt-danger:#f44336;\n --yt-warning:#ffc107;\n --yt-warning-soft:rgba(255,193,7,0.2);\n --yt-shadow-soft:rgba(0,0,0,.2);\n --yt-shadow-soft-strong:rgba(0,0,0,.3);\n --yt-shadow-inset-soft:rgba(0,0,0,.04);\n --yt-shadow-inset-strong:rgba(0,0,0,.35);\n --yt-shadow-flyout:rgba(0,0,0,.5);\n --yt-shadow-notification:rgba(0,0,0,.3);\n --yt-shadow-deep-1:rgba(0,0,0,.15);\n --yt-shadow-deep-2:rgba(0,0,0,.1);\n --yt-shadow-deep-3:rgba(0,0,0,.06);\n --yt-shadow-deep-4:rgba(0,0,0,.09);\n --yt-border-light:rgba(0,0,0,.25);\n --yt-overlay-strong:rgba(0,0,0,.55);\n --yt-overlay-deep:rgba(0,0,0,.2);\n --yt-overlay-faint:rgba(0,0,0,.15);\n --yt-tab-color-accent:#ff4533;\n --yt-scrollbar-outline:rgba(127,127,127,.5);\n --yt-panel-overlay-subtle:rgba(0,0,0,.05);\n --yt-scrollbar-thumb:rgba(144,144,144,.5);\n --yt-scrollbar-thumb-hover:rgba(170,170,170,.7);\n --yt-panel-overlay-weak:rgba(0,0,0,.02);\n --yt-badge-bg-light:rgba(255,255,255,.1);\n --yt-badge-bg-dark:rgba(0,0,0,.05);\n --yt-text-dark-primary:#0f0f0f;\n --yt-playall-accent-purple:#bf4bcc;\n --yt-playall-accent-blue:#2b66da;\n --yt-search-highlight-bg:rgba(255,99,71,.12);\n --yt-search-highlight-border:rgba(255,99,71,.25);\n --yt-search-highlight-border-strong:rgba(255,99,71,.4);\n --yt-search-highlight-faint:rgba(255,99,71,.1);\n --yt-search-highlight-hover:rgba(255,99,71,.22);\n --yt-search-highlight-accent:#ff5c5c;\n --yt-shorts-shadow-deep:rgba(0,0,0,.4);\n --yt-shorts-overlay-gray:rgba(155,155,155,.15);\n --yt-shorts-border-light:rgba(255,255,255,.2);\n --yt-shorts-shadow-blue:rgba(31,38,135,.37);\n --yt-shorts-feedback-bg-dark:rgba(34,34,34,.7);\n --yt-shorts-feedback-bg-light:rgba(255,255,255,.95);\n --yt-shorts-border-dark:rgba(0,0,0,.08);\n --yt-shorts-help-bg-light:rgba(255,255,255,.98);\n --yt-shorts-header-bg:rgba(255,255,255,.05);\n --yt-shorts-header-bg-light:rgba(0,0,0,.04);\n --yt-shorts-kbd-bg:rgba(255,255,255,.15);\n --yt-shorts-kbd-border:rgba(255,255,255,.2);\n --yt-shorts-kbd-bg-light:rgba(0,0,0,.06);\n --yt-shorts-kbd-hover:rgba(255,255,255,.22);\n --yt-shorts-text-secondary:rgba(255,255,255,.92);\n --yt-shorts-footer-bg:rgba(255,255,255,.05);\n --yt-shorts-footer-bg-light:rgba(0,0,0,.04);\n --yt-shorts-panel-header:rgba(255,255,255,.1);\n --yt-shorts-panel-header-bg:rgba(255,255,255,.05);\n --yt-shorts-feedback-bg:rgba(255,255,255,.15);\n --yt-shorts-feedback-border:rgba(255,255,255,.2);\n --yt-shorts-help-bg:rgba(255,255,255,.15);\n --yt-shorts-help-border:rgba(255,255,255,.2);\n --yt-shorts-kbd-non-editable:rgba(0,0,0,.08);\n --yt-muted-text:#666;\n --yt-success-accent:#10c56a;\n --yt-success-accent-soft:rgba(16,197,106,0.15);\n --yt-surface-contrast:#111;\n --yt-progress-track:#e0e0e0;\n --yt-progress-fill:#1a73e8;\n --yt-modal-surface:rgba(20,20,20,.64);\n --yt-radius-xs:6px;\n --yt-radius-sm:10px;\n --yt-radius-md:14px;\n --yt-radius-lg:20px;\n --yt-space-sm:8px;\n --yt-space-md:16px;\n --yt-space-lg:24px;\n --yt-transition-fast:all .14s cubic-bezier(.2,.8,.2,1);\n --yt-transition-default:all .24s cubic-bezier(.2,.8,.2,1);\n --yt-glass-blur:blur(18px) saturate(180%);\n --yt-glass-blur-light:blur(12px) saturate(160%);\n --yt-glass-blur-heavy:blur(24px) saturate(200%);\n --yt-z-overlay:1000;\n --yt-z-flyout:20000;\n --yt-z-modal:100000;\n --yt-stats-icon-views-bg:rgba(59,130,246,0.15);\n --yt-stats-icon-views:#3b82f6;\n --yt-stats-icon-likes-bg:rgba(34,197,94,0.15);\n --yt-stats-icon-likes:#22c55e;\n --yt-stats-icon-dislikes-bg:rgba(239,68,68,0.15);\n --yt-stats-icon-dislikes:#ef4444;\n --yt-stats-icon-comments-bg:rgba(168,85,247,0.15);\n --yt-stats-icon-comments:#a855f7;\n --yt-stats-icon-viewers-bg:rgba(234,179,8,0.15);\n --yt-stats-icon-viewers:#eab308;\n --yt-stats-icon-subscribers-bg:rgba(236,72,153,0.15);\n --yt-stats-icon-subscribers:#ec4899;\n --yt-stats-icon-videos-bg:rgba(14,165,233,0.15);\n --yt-stats-icon-videos:#0ea5e9;\n --yt-stats-card-bg-dark:rgba(255,255,255,0.05);\n --yt-stats-card-bg-light:rgba(0,0,0,0.03);\n --yt-stats-card-border-dark:rgba(255,255,255,0.08);\n --yt-stats-card-border-light:rgba(0,0,0,0.1);\n --yt-stats-text-secondary-dark:rgba(255,255,255,0.65);\n --yt-stats-text-secondary-light:rgba(0,0,0,0.6);\n --yt-stats-text-label:rgba(255,255,255,0.72);\n --yt-stats-text-exact-dark:rgba(255,255,255,0.5);\n --yt-stats-text-exact-light:rgba(0,0,0,0.5);\n --yt-stats-text-value-dark:#fff;\n --yt-stats-text-value-light:#111;\n --yt-stats-error:#ff6b6b;\n --yt-stats-link-color:#0b61d6;\n --yt-stats-link-hover:#e6f0ff;\n --yt-stats-link-hover-dark:#0647a6;\n --yt-stats-loader-text-dark:#fff;\n --yt-stats-loader-text-light:#666;\n --yt-stats-shadow-hover:rgba(0,0,0,0.3);\n --yt-stats-shadow-deep:rgba(0,0,0,0.32);\n --yt-stats-modal-shadow:rgba(0,0,0,0.45);\n --yt-stats-bg-overlay-dark:rgba(28,28,28,0.75);\n --yt-stats-img-border-dark:rgba(255,255,255,0.06);\n --yt-stats-img-border-light:rgba(0,0,0,0.06);\n --yt-stats-button-bg-dark:rgba(24,24,24,0.68);\n --yt-stats-button-border-dark:rgba(255,255,255,0.08);\n --yt-stats-button-border-light:rgba(0,0,0,0.06);\n --yt-stats-button-bg-light:rgba(255,255,255,0.12);\n --yt-stats-author-name-bright:rgba(255,255,255,0.9);\n --yt-stats-author-name-light:rgba(0,0,0,0.8);\n --yt-stats-channel-button-bg:rgba(0,0,0,0.4);\n --yt-stats-channel-button-border:rgba(255,255,255,0.1);\n --yt-stats-channel-button-hover:rgba(0,0,0,0.6);\n --yt-stats-channel-button-hover-border:rgba(255,255,255,0.3);\n --yt-stats-channel-menu-bg:rgba(28,28,28,0.75);\n --yt-stats-channel-menu-border:rgba(255,255,255,0.08);\n --yt-stats-channel-menu-item-bg:rgba(255,255,255,0.02);\n --yt-stats-channel-label-text:#eee;\n --yt-stats-channel-input-bg:rgba(255,255,255,0.1);\n --yt-stats-channel-input-hover:rgba(255,255,255,0.15);\n --yt-stats-channel-select-option-bg:#333;\n --yt-stats-channel-range-bg:rgba(255,255,255,0.2);\n --yt-stats-channel-range-thumb:#3ea6ff;\n --yt-stats-channel-checkbox-border:rgba(255,255,255,0.4);\n --yt-stats-channel-text-value:#bbb;\n --yt-stats-channel-text-shadow:rgba(0,0,0,0.3);\n --yt-stats-link-color:#0b61d6;\n --yt-stats-link-hover-dark:#0647a6;\n --yt-stats-positive-indicator:#1ed760;\n --yt-stats-negative-indicator:#f3727f;\n --yt-stats-channel-filter-shadow:rgba(0,0,0,0.5);\n --yt-timecode-panel-bg-dark:rgba(34,34,34,0.75);\n --yt-timecode-panel-bg-light:rgba(255,255,255,0.95);\n --yt-timecode-panel-border-dark:rgba(255,255,255,0.12);\n --yt-timecode-panel-border-light:rgba(0,0,0,0.08);\n --yt-timecode-panel-color-dark:#fff;\n --yt-timecode-panel-color-light:#222;\n --yt-timecode-panel-shadow:rgba(0,0,0,0.45);\n --yt-timecode-active-bg-start:rgba(255,68,68,0.12);\n --yt-timecode-active-bg-end:rgba(255,68,68,0.04);\n --yt-timecode-active-border:#ff6666;\n --yt-timecode-active-inset:rgba(255,68,68,0.03);\n --yt-timecode-chapter:#ff4444;\n --yt-timecode-toggle-active-start:#ff6b6b;\n --yt-timecode-export-success-bg:rgba(0,220,0,0.8);\n --yt-update-card-shadow:rgba(6,10,20,0.45);\n --yt-update-available-dot:#ff4444;\n --yt-update-available-text:#ff6666;\n --yt-update-install-bg-start:#ff4500;\n --yt-update-install-bg-end:#ff6b35;\n --yt-update-install-shadow:rgba(255,69,0,0.3);\n --yt-thumbnail-overlay-idle:rgba(0,0,0,0.3);\n --yt-thumbnail-overlay-hover:rgba(0,0,0,0.7);\n --yt-thumbnail-overlay-active:rgba(0,0,0,0.9);\n }\n\n html[dark],html[data-ytp-theme="dark"]{\n --yt-bg-primary:rgba(15,15,15,.85);\n --yt-bg-secondary:rgba(28,28,28,.85);\n --yt-bg-tertiary:rgba(34,34,34,.85);\n --yt-text-primary:#fff;\n --yt-text-secondary:#aaa;\n --yt-border-color:rgba(255,255,255,.2);\n --yt-hover-bg:rgba(255,255,255,.1);\n --yt-shadow:0 4px 12px rgba(0,0,0,.25);\n --yt-glass-bg:rgba(50,50,50,.5);\n --yt-glass-border:rgba(255,255,255,.2);\n --yt-glass-shadow:0 8px 32px rgba(0,0,0,.2);\n --yt-modal-bg:rgba(0,0,0,.75);\n --yt-notification-bg:rgba(28,28,28,.9);\n --yt-panel-bg:rgba(34,34,34,.3);\n --yt-header-bg:rgba(20,20,20,.6);\n --yt-input-bg:rgba(255,255,255,.1);\n --yt-button-bg:rgba(255,255,255,.2);\n --yt-text-stroke:#fff;\n --yt-rail-gradient-start:rgba(255,255,255,.06);\n --yt-rail-gradient-end:rgba(255,255,255,.03);\n --yt-rail-inset:rgba(255,255,255,.08);\n }\n\n html[light],html[data-ytp-theme="light"],html:not([dark]):not([data-ytp-theme="dark"]){\n --yt-bg-primary:rgba(255,255,255,.85);\n --yt-bg-secondary:rgba(248,248,248,.85);\n --yt-bg-tertiary:rgba(240,240,240,.85);\n --yt-text-primary:#030303;\n --yt-text-secondary:#606060;\n --yt-border-color:rgba(0,0,0,.2);\n --yt-hover-bg:rgba(0,0,0,.05);\n --yt-shadow:0 4px 12px rgba(0,0,0,.15);\n --yt-glass-bg:rgba(255,255,255,.7);\n --yt-glass-border:rgba(0,0,0,.1);\n --yt-glass-shadow:0 8px 32px rgba(0,0,0,.1);\n --yt-modal-bg:rgba(0,0,0,.5);\n --yt-notification-bg:rgba(255,255,255,.95);\n --yt-panel-bg:rgba(255,255,255,.7);\n --yt-header-bg:rgba(248,248,248,.8);\n --yt-input-bg:rgba(0,0,0,.05);\n --yt-button-bg:rgba(0,0,0,.1);\n --yt-text-stroke:#030303;\n --yt-rail-gradient-start:rgba(0,0,0,.04);\n --yt-rail-gradient-end:rgba(0,0,0,.02);\n --yt-rail-inset:rgba(0,0,0,.06);\n }\n\n .ytp-plus-btn{\n padding:var(--yt-space-sm) var(--yt-space-md);\n border-radius:18px;\n border:1px solid var(--yt-glass-border);\n font-size:14px;\n font-weight:500;\n cursor:pointer;\n color:var(--yt-text-primary);\n background:var(--yt-button-bg);\n transition:var(--yt-transition-default);\n }\n .ytp-plus-btn:hover{\n transform:translateY(-1px);\n box-shadow:var(--yt-shadow);\n background:var(--yt-hover-bg);\n }\n .ytp-plus-btn--primary{\n background:transparent;\n }\n .ytp-plus-btn--primary:hover{\n background:var(--yt-accent);\n color:#fff;\n box-shadow:0 6px 16px rgba(255,0,0,.35);\n }\n\n .ytp-plus-panel{\n background:var(--yt-glass-bg);\n border:1px solid var(--yt-glass-border);\n border-radius:var(--yt-radius-md);\n box-shadow:var(--yt-glass-shadow);\n color:var(--yt-text-primary);\n }\n\n .ytp-plus-modal-overlay{\n position:fixed;\n inset:0;\n background:var(--yt-modal-bg);\n display:flex;\n align-items:center;\n justify-content:center;\n z-index:var(--yt-z-modal);\n backdrop-filter:blur(8px) saturate(140%);\n -webkit-backdrop-filter:blur(8px) saturate(140%);\n animation:ytEnhanceFadeIn .25s ease-out;\n }\n\n .ytp-plus-modal-content{\n background:var(--yt-glass-bg);\n border:1.5px solid var(--yt-glass-border);\n border-radius:24px;\n color:var(--yt-text-primary);\n box-shadow:0 12px 40px rgba(0,0,0,.45);\n backdrop-filter:blur(14px) saturate(140%);\n -webkit-backdrop-filter:blur(14px) saturate(140%);\n animation:ytEnhanceScaleIn .28s cubic-bezier(.4,0,.2,1);\n }\n\n @keyframes ytEnhanceFadeIn{from{opacity:0;}to{opacity:1;}}\n @keyframes ytEnhanceScaleIn{from{opacity:0;transform:scale(.92) translateY(10px);}to{opacity:1;transform:scale(1) translateY(0);}}\n @keyframes fadeInModal{from{opacity:0}to{opacity:1}}\n @keyframes scaleInModal{from{transform:scale(0.95);opacity:0}to{transform:scale(1);opacity:1}}\n @keyframes spin{to{transform:rotate(360deg)}}\n @keyframes dash{0%{stroke-dashoffset:80}50%{stroke-dashoffset:10}100%{stroke-dashoffset:80}}\n @keyframes slideInFromBottom{from{transform:translateY(100%);opacity:0;}to{transform:translateY(0);opacity:1;}}\n @keyframes slideOutToBottom{from{transform:translateY(0);opacity:1;}to{transform:translateY(100%);opacity:0;}}\n\n @keyframes ytp-resume-fadein{from{opacity:0;}to{opacity:1;}}\n\n @media (prefers-reduced-motion: reduce){\n *,*::before,*::after{\n animation:none !important;\n transition:none !important;\n }\n }\n '); })(), (function() { const t = { "ytp-screenshot-styles": ".ytp-screenshot-button,.ytp-cobalt-button,.ytp-pip-button{position:relative;width:44px;height:100%;display:inline-flex;align-items:center;justify-content:center;vertical-align:top;transition:opacity .15s,transform .15s;}.ytp-screenshot-button:hover,.ytp-cobalt-button:hover,.ytp-pip-button:hover{transform:scale(1.1);}", "ytp-speedcontrol-styles": "\n .speed-control-btn{width:4em!important;position:relative!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;height:100%!important;vertical-align:top!important;text-align:center!important;border-radius:var(--yt-radius-sm);font-size:13px;color:var(--yt-text-primary);cursor:pointer;user-select:none;font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;transition:color .2s;}\n .speed-control-btn:hover{color:var(--yt-accent);font-weight:bold;}\n .speed-options{position:fixed!important;background:var(--yt-glass-bg)!important;color:var(--yt-text-primary)!important;border-radius:var(--yt-radius-md)!important;display:flex!important;flex-direction:column!important;align-items:stretch!important;gap:0!important;transform:translate(-50%,12px)!important;width:92px!important;z-index:2147483647!important;box-shadow:var(--yt-glass-shadow);border:1px solid var(--yt-glass-border);overflow:hidden;opacity:0;pointer-events:none!important;transition:opacity .18s ease,transform .18s ease;box-sizing:border-box;}\n .speed-options.visible{opacity:1;pointer-events:auto!important;transform:translate(-50%,0)!important;backdrop-filter:var(--yt-glass-blur);-webkit-backdrop-filter:var(--yt-glass-blur);}\n .speed-option-item{cursor:pointer!important;height:28px!important;line-height:28px!important;font-size:12px!important;text-align:center!important;transition:background-color .15s,color .15s;}\n .speed-option-active,.speed-option-item:hover{color:var(--yt-accent)!important;font-weight:bold!important;background:var(--yt-hover-bg)!important;}\n #speed-indicator{position:absolute!important;margin:auto!important;top:0!important;right:0!important;bottom:0!important;left:0!important;border-radius:24px!important;font-size:30px!important;background:var(--yt-glass-bg)!important;color:var(--yt-text-primary)!important;z-index:99999!important;width:80px!important;height:80px!important;line-height:80px!important;text-align:center!important;display:none;box-shadow:var(--yt-glass-shadow);border:1px solid var(--yt-glass-border);}\n .speed-submenu{margin:4px 0 12px 12px;}\n .speed-submenu-container{display:flex;flex-direction:column;gap:8px;}\n .speed-hotkeys-row{flex-direction:column!important;align-items:stretch!important;gap:6px;}\n .speed-hotkeys-info{display:flex;flex-direction:column;gap:4px;}\n .speed-hotkeys-fields{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;margin-top:12px;width:100%;}\n .speed-hotkey-field{display:flex;flex-direction:column;align-items:center;gap:8px;font-size:12px;color:var(--yt-text-secondary);flex:1;min-width:80px;}\n .speed-hotkey-field span{text-align:center;width:100%;}\n .speed-hotkey-input{width:100%;height:36px;border-radius:8px;border:1px solid var(--yt-glass-border);background:var(--yt-glass-bg);color:var(--yt-text-primary);text-align:center;text-transform:uppercase;}\n .speed-hotkey-input:focus{background:var(--yt-hover-bg);}\n ", "shorts-keyboard-styles": '\n .shorts-help-panel{position:fixed;top:50%;left:25%;transform:translate(-50%,-50%) scale(.9);z-index:10001;opacity:0;visibility:hidden;transition:opacity .3s ease,visibility .3s ease,transform .3s ease;width:340px;max-width:95vw;max-height:80vh;overflow:hidden;outline:none;color:var(--yt-text-primary,#fff);padding:14px;display:flex;flex-direction:column;gap:12px;}\n .shorts-help-panel.visible{opacity:1;visibility:visible;transform:translate(-50%,-50%) scale(1);}\n .help-topbar{display:flex;align-items:center;justify-content:space-between;gap:10px;}\n .help-header{margin:0;line-height:1.2;}\n .help-close{position:static;display:flex;align-items:center;justify-content:center;padding:4px;flex-shrink:0;}\n .help-body{display:flex;flex-direction:column;gap:12px;min-height:0;}\n .help-content{padding:8px 10px;max-height:400px;overflow-y:auto;cursor:grab;user-select:none;-webkit-user-select:none;touch-action:none;border-radius:12px;background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);}\n .shorts-help-panel.is-dragging .help-content,.help-content:active{cursor:grabbing;}\n .help-item{display:flex;align-items:center;margin-bottom:14px;gap:18px;}\n .help-item kbd{background:var(--yt-shorts-kbd-bg);color:inherit;padding:7px 14px;border-radius:8px;font-family:monospace;font-size:15px;font-weight:700;min-width:60px;text-align:center;border:1.5px solid var(--yt-shorts-kbd-border);cursor:pointer;transition:background-color .2s cubic-bezier(0.2,0,0,1), transform .2s cubic-bezier(0.2,0,0,1), border-color .2s cubic-bezier(0.2,0,0,1);position:relative;}\n html[data-ytp-theme="light"] .help-item kbd,html:not([dark]):not([data-ytp-theme="dark"]) .help-item kbd{background:var(--yt-shorts-kbd-bg-light);color:#222;border:1.5px solid var(--yt-shorts-border-dark);}\n .help-item kbd:hover{background:var(--yt-shorts-kbd-hover);transform:scale(1.07);}\n .help-item kbd:not(.non-editable):active{transform:scale(0.96) !important;}\n .help-item kbd:after{content:"✎";position:absolute;top:-7px;right:-7px;font-size:11px;opacity:0;transition:opacity .2s;}\n .help-item kbd:hover:after{opacity:.7;}\n .help-item kbd.non-editable{cursor:default;opacity:.7;}\n .help-item kbd.non-editable:hover{background:var(--yt-shorts-kbd-bg);transform:none;}\n .help-item kbd.non-editable:after{display:none;}\n .help-item span{font-size:15px;color:var(--yt-shorts-text-secondary);}\n html[data-ytp-theme="light"] .help-item span,html:not([dark]):not([data-ytp-theme="dark"]) .help-item span{color:#222;}\n html[data-ytp-theme="light"] .shorts-help-panel,html:not([dark]):not([data-ytp-theme="dark"]) .shorts-help-panel{color:var(--yt-text-dark-primary,#222);}\n .help-actions{display:flex;justify-content:flex-end;align-items:center;}\n .reset-all-shortcuts{display:inline-flex;align-items:center;justify-content:center;gap:var(--yt-space-sm);}\n .ytp-plus-shorts-download{width:48px;height:48px;border-radius:999px;display:flex;align-items:center;justify-content:center;z-index:1;cursor:pointer;box-shadow:var(--yt-glass-shadow);background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);backdrop-filter:var(--yt-glass-blur);-webkit-backdrop-filter:var(--yt-glass-blur);margin:0 auto 10px;align-self:center;color:var(--yt-text-primary);transition:background-color .3s cubic-bezier(0.2,0,0,1), color .3s cubic-bezier(0.2,0,0,1), border-color .3s cubic-bezier(0.2,0,0,1), transform .15s cubic-bezier(0.2,0,0,1), box-shadow .3s cubic-bezier(0.2,0,0,1);}\n .ytp-plus-shorts-download:active{transform:scale(0.96) !important;}\n .ytp-plus-shorts-download svg{width:22px;height:22px;display:block;pointer-events:none;}\n .ytp-plus-shorts-download:hover{background:var(--yt-glass-border);}\n .shortcut-edit-dialog{z-index:10002;}\n .shortcut-edit-content{padding:28px 32px;min-width:320px;text-align:center;display:flex;flex-direction:column;gap:var(--yt-space-md);color:inherit;}\n html[data-ytp-theme="light"] .shortcut-edit-content,html:not([dark]):not([data-ytp-theme="dark"]) .shortcut-edit-content{color:#222;}\n .shortcut-edit-content h4{margin:0 0 14px;font-size:17px;font-weight:700;}\n .shortcut-edit-content p{margin:0 0 18px;font-size:15px;color:rgba(255,255,255,.85);}\n html[data-ytp-theme="light"] .shortcut-edit-content p,html:not([dark]):not([data-ytp-theme="dark"]) .shortcut-edit-content p{color:#222;}\n .current-shortcut{margin:18px 0;font-size:15px;}\n .current-shortcut kbd{background:var(--yt-shorts-kbd-bg);padding:5px 12px;border-radius:6px;font-family:monospace;border:1.5px solid var(--yt-shorts-kbd-border);}\n html[data-ytp-theme="light"] .current-shortcut kbd,html:not([dark]):not([data-ytp-theme="dark"]) .current-shortcut kbd{background:var(--yt-shorts-kbd-bg-light);color:#222;border:1.5px solid var(--yt-shorts-border-dark);}\n .shortcut-cancel{display:inline-flex;align-items:center;justify-content:center;gap:var(--yt-space-sm);}\n @media(max-width:480px){.shorts-help-panel{width:98vw;max-height:85vh;padding:10px}.help-content{padding:10px 8px}.help-item{gap:10px}.help-item kbd{min-width:44px;font-size:13px;padding:5px 7px}.ytp-plus-shorts-download{width:44px;height:44px;margin-bottom:8px}.shortcut-edit-content{margin:20px;min-width:auto}}\n #shorts-keyboard-feedback{background:var(--yt-shorts-feedback-bg-dark);color:var(--yt-text-primary,#fff);border:1.5px solid var(--yt-shorts-feedback-bg);border-radius:20px;box-shadow:0 8px 32px 0 var(--yt-shorts-shadow-blue);backdrop-filter:blur(12px) saturate(180%);-webkit-backdrop-filter:blur(12px) saturate(180%);}\n html[data-ytp-theme="light"] #shorts-keyboard-feedback,html:not([dark]):not([data-ytp-theme="dark"]) #shorts-keyboard-feedback{background:var(--yt-shorts-feedback-bg-light);color:var(--yt-text-dark-primary,#222);border:1.5px solid var(--yt-shorts-border-dark);}\n ', "pip-styles": "\n .pip-shortcut-editor { display: flex; align-items: center; gap: 8px; }\n .pip-hidden-select { display: none; }\n .pip-submenu-layout { margin-left: 12px; margin-bottom: 12px; }\n .pip-submenu-layout.is-hidden { display: none; }\n .pip-submenu-card { display: flex; flex-direction: column; gap: 8px; }\n .pip-shortcut-item { display: flex; }\n .pip-submenu-toggle-hidden { display: none; }\n .pip-shortcut-editor select, .pip-key-input {background: rgba(34, 34, 34, var(--yt-header-bg-opacity)); color: var(--yt-spec-text-primary); border: 1px solid var(--yt-spec-10-percent-layer); border-radius: var(--yt-radius-sm); padding: 4px;}\n .pip-key-input { width: 35px; text-align: center; }\n ", "timecode-panel-styles": '\n html[dark],html[data-ytp-theme="dark"],body[dark]{--yt-timecode-panel-bg:var(--yt-timecode-panel-bg-dark);--yt-timecode-panel-border:var(--yt-timecode-panel-border-dark);--yt-timecode-panel-color:var(--yt-timecode-panel-color-dark)}\n html[light],html[data-ytp-theme="light"],html:not([dark]):not([data-ytp-theme="dark"]),body:not([dark]){--yt-timecode-panel-bg:var(--yt-timecode-panel-bg-light);--yt-timecode-panel-border:var(--yt-timecode-panel-border-light);--yt-timecode-panel-color:var(--yt-timecode-panel-color-light)}\n #timecode-panel{position:fixed;right:20px;top:80px;background:var(--yt-timecode-panel-bg);border-radius:16px;box-shadow:0 12px 40px var(--yt-timecode-panel-shadow);width:320px;max-height:70vh;z-index:10000;color:var(--yt-timecode-panel-color);backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);border:1.5px solid var(--yt-timecode-panel-border);transition:transform .28s cubic-bezier(.4,0,.2,1),opacity .28s;overflow:hidden;display:flex;flex-direction:column}\n #timecode-panel.hidden{transform:translateX(300px);opacity:0;pointer-events:none}\n #timecode-panel.auto-tracking{box-shadow:0 12px 48px var(--yt-danger-ghost);border-color:var(--yt-danger-border)}\n #timecode-header{display:flex;justify-content:space-between;align-items:center;padding:14px;border-bottom:1px solid var(--yt-surface-overlay-subtle);background:linear-gradient(180deg, var(--yt-surface-overlay-faint), transparent);cursor:move}\n #timecode-title{font-weight:600;margin:0;font-size:15px;user-select:none;display:flex;align-items:center;gap:8px}\n #timecode-tracking-indicator{width:8px;height:8px;background:var(--yt-accent);border-radius:50%;opacity:0;transition:opacity .3s}\n #timecode-panel.auto-tracking #timecode-tracking-indicator{opacity:1}\n #timecode-current-time{font-family:monospace;font-size:12px;padding:2px 6px;background:var(--yt-danger-border);border-radius:3px;margin-left:auto}\n #timecode-header-controls{display:flex;align-items:center;gap:6px}\n #timecode-reload,#timecode-close{background:transparent;border:none;color:inherit;cursor:pointer;width:28px;height:28px;padding:0;display:flex;align-items:center;justify-content:center;border-radius:6px;transition:background .18s,color .18s}\n #timecode-header-controls svg{width:16px;height:16px;display:block;flex-shrink:0}\n #timecode-header-controls svg path{vector-effect:non-scaling-stroke}\n #timecode-reload:hover,#timecode-close:hover{background:var(--yt-surface-overlay-subtle)}\n #timecode-reload.loading{animation:spin .8s linear infinite}\n #timecode-list{overflow-y:auto;padding:8px 0;max-height:calc(70vh - 80px);scrollbar-width:thin;scrollbar-color:var(--yt-scrollbar-outline) transparent}\n #timecode-list::-webkit-scrollbar{width:6px}\n #timecode-list::-webkit-scrollbar-thumb{background:var(--yt-scrollbar-outline);border-radius:3px}\n .timecode-item{padding:10px 14px;display:flex;align-items:center;cursor:pointer;transition:background-color .16s,transform .12s;border-left:3px solid transparent;position:relative;border-radius:8px;margin:6px 10px}\n .timecode-item:hover{background:var(--yt-surface-overlay-subtle);transform:translateY(-2px)}\n .timecode-item:hover .timecode-actions{opacity:1}\n .timecode-item.active{background:linear-gradient(90deg, var(--yt-timecode-active-bg-start), var(--yt-timecode-active-bg-end));border-left-color:var(--yt-timecode-active-border);box-shadow:inset 0 0 0 1px var(--yt-timecode-active-inset)}\n .timecode-item.active.pulse{animation:timecodePulse .8s ease-out}\n .timecode-item.editing{background:linear-gradient(90deg, var(--yt-warning-soft), var(--yt-panel-overlay-weak));border-left-color:var(--yt-warning)}\n .timecode-item.editing .timecode-actions{opacity:1}\n @keyframes timecodePulse{0%{transform:scale(1)}50%{transform:scale(1.02)}100%{transform:scale(1)}}\n .timecode-time{font-family:monospace;margin-right:10px;color:var(--yt-text-secondary);font-size:13px;min-width:45px;flex-shrink:0}\n .timecode-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:13px;flex:1;margin-left:4px}\n .timecode-item:not(:has(.timecode-label)) .timecode-time{flex:1;text-align:left}\n .timecode-item.has-chapter .timecode-time{color:var(--yt-timecode-chapter)}\n .timecode-progress{width:0;height:2px;background:var(--yt-timecode-chapter);position:absolute;bottom:0;left:0;transition:width .3s;opacity:.8}\n .timecode-actions{position:absolute;right:8px;top:50%;transform:translateY(-50%);display:flex;gap:4px;opacity:0;transition:opacity .2s;background:var(--yt-overlay-strong);border-radius:4px;padding:2px}\n .timecode-action{background:none;border:none;color:var(--yt-text-secondary);cursor:pointer;padding:4px;font-size:12px;border-radius:2px;transition:color .2s,background-color .2s}\n .timecode-action:hover{color:var(--yt-text-primary);background:var(--yt-button-bg)}\n .timecode-action.edit:hover{color:var(--yt-warning)}\n .timecode-action.delete:hover{color:var(--yt-timecode-chapter)}\n #timecode-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center;color:var(--yt-text-secondary);font-size:13px}\n #timecode-form{padding:12px;border-top:1px solid var(--yt-surface-overlay-subtle);display:none}\n #timecode-form.visible{display:block}\n #timecode-form input{width:100%;margin-bottom:8px;padding:8px;background:var(--yt-input-bg);border:1px solid var(--yt-glass-border);border-radius:4px;color:var(--yt-text-primary);font-size:13px}\n #timecode-form input::placeholder{color:var(--yt-text-secondary)}\n #timecode-form-buttons{display:flex;gap:8px;justify-content:flex-end}\n #timecode-form-buttons button{padding:6px 12px;border:none;border-radius:4px;cursor:pointer;font-size:12px;transition:background-color .2s}\n #timecode-form-cancel{background:var(--yt-button-bg);color:var(--yt-text-primary)}\n #timecode-form-cancel:hover{background:var(--yt-hover-bg)}\n #timecode-form-save{background:var(--yt-timecode-chapter);color:var(--yt-text-primary)}\n #timecode-form-save:hover{background:var(--yt-timecode-active-border)}\n #timecode-actions{padding:10px;border-top:1px solid var(--yt-surface-overlay-subtle);display:flex;gap:8px;background:linear-gradient(180deg,transparent,var(--yt-panel-overlay-subtle))}\n #timecode-actions button{padding:8px 12px;border:none;border-radius:8px;cursor:pointer;font-size:13px;transition:background .18s;color:inherit;background:var(--yt-surface-overlay-faint)}\n #timecode-export-btn.is-hidden{display:none}\n #timecode-actions button:hover{background:var(--yt-surface-overlay-subtle)}\n #timecode-track-toggle.active{background:linear-gradient(90deg,var(--yt-timecode-toggle-active-start),var(--yt-timecode-chapter));color:var(--yt-text-primary)}\n #timecode-empty .timecode-empty-hint{margin-top:5px;font-size:12px}\n .timecode-submenu-layout{margin-left:12px;margin-bottom:12px}\n .timecode-submenu-layout.is-hidden{display:none}\n .timecode-submenu-card{display:flex;flex-direction:column;gap:8px}\n .timecode-shortcut-row{display:flex}\n .timecode-shortcut-editor{display:flex;align-items:center;gap:8px}\n .timecode-hidden-select{display:none}\n .timecode-submenu-toggle-hidden{display:none}\n .timecode-shortcut-plus{color:inherit;opacity:.8}\n .timecode-key-input{width:35px;text-align:center;background:var(--yt-input-bg);color:var(--yt-text-primary);border:1px solid var(--yt-border-color);border-radius:4px;padding:4px}\n ', "thumbnail-viewer-styles": "\n .thumbnail-player-overlay{position:absolute;top:10%;right:8px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;border-radius:6px;cursor:pointer;z-index:1001;transition:opacity 0.15s ease, background-color 0.15s ease, transform 0.1s cubic-bezier(0.2,0,0,1);opacity:0}\n .thumbnail-player-overlay:active{transform:scale(0.96) !important;}\n .thumbnail-base-overlay{position:absolute;width:28px;height:28px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:1000;opacity:0;transition:opacity 0.2s ease, background-color 0.2s ease, transform 0.1s cubic-bezier(0.2,0,0,1)}\n .thumbnail-base-overlay:active{transform:scale(0.96) !important;}\n .thumb-overlay,.banner-overlay{bottom:8px;left:8px;border-radius:4px}\n .thumb-overlay{background:var(--yt-thumbnail-overlay-idle)}\n .thumb-overlay:hover{background:var(--yt-thumbnail-overlay-hover)}\n .avatar-overlay{top:50%;left:50%;transform:translate(-50%, -50%);border-radius:50%;background:var(--yt-thumbnail-overlay-hover)}\n .avatar-overlay:hover{background:var(--yt-thumbnail-overlay-active)}\n .banner-overlay{background:var(--yt-thumbnail-overlay-hover)}\n .banner-overlay:hover{background:var(--yt-thumbnail-overlay-active)}\n .thumbnail-overlay-container { position: absolute; bottom: 8px; left: 8px; z-index: var(--yt-z-overlay); opacity: 0; transition: opacity 0.2s ease; }\n .thumbnail-overlay-button { width: 28px; height: 28px; background: var(--yt-glass-bg); border: none; border-radius: var(--yt-radius-xs); cursor: pointer; display: flex; align-items: center; justify-content: center; color: var(--yt-text-primary); position: relative; box-shadow: var(--yt-glass-shadow); backdrop-filter: var(--yt-glass-blur); -webkit-backdrop-filter: var(--yt-glass-blur); border: 1px solid var(--yt-glass-border); }\n .thumbnail-overlay-button svg{width:16px;height:16px;display:block;flex:none;}\n .thumbnail-overlay-button:hover { background: var(--yt-hover-bg); }\n .thumbnail-dropdown { position: absolute; bottom: 100%; left: 0; background: var(--yt-glass-bg); border-radius: var(--yt-radius-xs); padding: 4px; margin-bottom: 4px; display: none; flex-direction: column; min-width: 140px; box-shadow: var(--yt-glass-shadow); z-index: var(--yt-z-flyout); backdrop-filter: var(--yt-glass-blur); -webkit-backdrop-filter: var(--yt-glass-blur); border: 1px solid var(--yt-glass-border); }\n .thumbnail-dropdown.show { display: flex !important; }\n .thumbnail-dropdown-item { background: none; border: none; color: var(--yt-text-primary); padding: 8px 12px; cursor: pointer; border-radius: 4px; font-size: 12px; text-align: left; white-space: nowrap; transition: background-color 0.2s ease; }\n .thumbnail-dropdown-item:hover { background: var(--yt-hover-bg); }\n .thumbnailPreview-button { position: absolute; bottom: 10px; left: 5px; background-color: var(--yt-glass-bg); color: var(--yt-text-primary); border: none; border-radius: var(--yt-radius-xs); padding: 3px; font-size: 18px; cursor: pointer; z-index: var(--yt-z-overlay); opacity: 0; transition: opacity 0.3s; display: flex; align-items: center; justify-content: center; box-shadow: var(--yt-glass-shadow); backdrop-filter: var(--yt-glass-blur); -webkit-backdrop-filter: var(--yt-glass-blur); border: 1px solid var(--yt-glass-border); }\n .thumbnailPreview-button svg{width:16px;height:16px;display:block;flex:none;}\n .thumbnailPreview-container { position: relative; }\n .thumbnailPreview-container:hover .thumbnailPreview-button { opacity: 1; }\n .thumbnail-modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: var(--yt-modal-bg); z-index: var(--yt-z-modal); display: flex; align-items: center; justify-content: center; animation: fadeInModal 0.22s cubic-bezier(.4,0,.2,1); backdrop-filter: blur(8px) saturate(140%); -webkit-backdrop-filter: blur(8px) saturate(140%); }\n .thumbnail-modal-content { background: var(--yt-glass-bg); border-radius: var(--yt-radius-lg); box-shadow: 0 12px 40px var(--yt-timecode-panel-shadow); max-width: 78vw; max-height: 90vh; overflow: auto; position: relative; display: flex; flex-direction: column; align-items: center; animation: scaleInModal 0.22s cubic-bezier(.4,0,.2,1); border: 1.5px solid var(--yt-glass-border); backdrop-filter: blur(14px) saturate(150%); -webkit-backdrop-filter: blur(14px) saturate(150%);}\n .thumbnail-modal-wrapper { display: flex; align-items: flex-start; gap: 12px; }\n .thumbnail-modal-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }\n .thumbnail-modal-action-btn { padding: 0; line-height: 0; }\n .thumbnail-modal-action-btn svg{width:18px;height:18px;display:block;flex:none;}\n .thumbnail-modal-close svg{width:36px;height:36px;}\n .thumbnail-modal-img { max-width: 72vw; max-height: 70vh; box-shadow: var(--yt-glass-shadow); background: #222; border: 1px solid var(--yt-glass-border); }\n .thumbnail-modal-options { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }\n .thumbnail-modal-option-btn { background: var(--yt-button-bg); color: var(--yt-text-primary); border: none; border-radius: var(--yt-radius-xs); padding: 8px 18px; font-size: 14px; cursor: pointer; transition: background 0.2s,color .2s; margin-bottom: 6px; box-shadow: var(--yt-glass-shadow); backdrop-filter: var(--yt-glass-blur); -webkit-backdrop-filter: var(--yt-glass-blur); border: 1px solid var(--yt-glass-border); }\n .thumbnail-modal-option-btn:hover { background: var(--yt-hover-bg); color: var(--yt-accent); }\n .thumbnail-modal-title { font-size: 18px; font-weight: 600; color: var(--yt-text-primary); margin-bottom: 10px; text-align: center; text-shadow: 0 2px 8px var(--yt-shadow-deep-1); }\n ", "ytp-resume-overlay-styles": "\n .ytp-resume-overlay{min-width:180px;max-width:36vw;background:var(--yt-glass-bg);color:var(--yt-text-primary,#fff);padding:12px 14px;border-radius:12px;backdrop-filter:blur(8px) saturate(150%);-webkit-backdrop-filter:blur(8px) saturate(150%);box-shadow:0 14px 40px var(--yt-shadow-flyout);border:1.25px solid var(--yt-surface-overlay-border);font-family:Arial,Helvetica,sans-serif;display:flex;flex-direction:column;align-items:center;text-align:center;animation:ytp-resume-fadein 0.3s ease-out}\n @keyframes ytp-resume-fadein{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}\n .ytp-resume-overlay .ytp-resume-title{font-weight:600;margin-bottom:8px;font-size:13px}\n .ytp-resume-overlay .ytp-resume-btn{padding:6px 12px;border-radius:8px;border:none;cursor:pointer;font-size:12px;font-weight:500;transition:background-color 0.2s cubic-bezier(0.2,0,0,1), transform 0.1s cubic-bezier(0.2,0,0,1), color 0.2s cubic-bezier(0.2,0,0,1), box-shadow 0.2s cubic-bezier(0.2,0,0,1);outline:none}\n .ytp-resume-overlay .ytp-resume-btn:focus{box-shadow:0 0 0 2px var(--yt-glass-border);outline:2px solid transparent}\n .ytp-resume-overlay .ytp-resume-btn:hover{transform:translateY(-1px)}\n .ytp-resume-overlay .ytp-resume-btn:active{transform:scale(0.96) !important;}\n .ytp-resume-overlay .ytp-resume-btn.primary{background:var(--yt-accent-secondary);color:#fff}\n .ytp-resume-overlay .ytp-resume-btn.primary:hover{background:var(--yt-accent-secondary-light)}\n .ytp-resume-overlay .ytp-resume-btn.ghost{background:var(--yt-button-bg);color:var(--yt-text-primary)}\n .ytp-resume-overlay .ytp-resume-btn.ghost:hover{background:var(--yt-hover-bg)}\n ", "ytp-plus-comments-modal-style": "\n .ytp-plus-comments-sidepanel{position:fixed;top:10vh;left:calc(50% + 390px);width:min(440px,34vw);max-width:92vw;height:60vh;background:var(--yt-glass-bg);border:1.5px solid var(--yt-glass-border);border-radius:24px;display:none;z-index:100001;box-shadow:0 12px 40px var(--yt-timecode-panel-shadow);overflow:hidden;backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);contain:layout style paint;font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}\n .ytp-plus-comments-sidepanel.open{display:flex;flex-direction:column}\n .ytp-plus-comments-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--yt-stats-card-border-dark)}\n .ytp-plus-comments-title{font-size:16px;font-weight:500;color:var(--yt-text-primary);font-family:inherit}\n .ytp-plus-comments-close{border:0;background:transparent;color:var(--yt-text-secondary);font-size:24px;cursor:pointer;line-height:1}\n .ytp-plus-comments-list{flex:1;overflow:auto;padding:12px 16px;display:flex;flex-direction:column;gap:10px}\n .ytp-plus-comments-item{border:1px solid var(--yt-stats-card-border-dark);background:var(--yt-surface-overlay-faint);border-radius:10px;padding:10px}\n .ytp-plus-comments-item-text{color:var(--yt-text-primary);white-space:pre-wrap;word-break:break-word;font-size:small}\n .ytp-plus-comments-item-meta{margin-top:6px;color:var(--yt-text-secondary);font-size:12px}\n .ytp-plus-comments-form{padding:12px 16px;border-top:1px solid var(--yt-stats-card-border-dark);display:flex;gap:8px;align-items:center}\n #ytp-plus-comments-input{flex:1;min-height:15px;max-height:160px;resize:vertical;background:var(--yt-glass-bg);color:var(--yt-text-primary);border:1px solid var(--yt-glass-border);border-radius:10px;padding:10px}\n #ytp-plus-comments-submit{border:1px solid var(--yt-glass-border);background:var(--yt-accent);color:var(--yt-text-primary);border-radius:10px;padding:10px 14px;cursor:pointer}\n .ytp-plus-voting-item-status-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}\n .ytp-plus-voting-comments-icon{border:1px solid var(--yt-glass-border);background:var(--yt-button-bg);color:var(--yt-text-secondary);border-radius:999px;min-width:28px;height:28px;padding:0 10px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;line-height:1;transition:background-color .2s ease,color .2s ease,border-color .2s ease}\n .ytp-plus-voting-comments-icon:hover{background:var(--yt-hover-bg);color:var(--yt-text-primary)}\n .ytp-plus-voting-comments-icon svg{width:14px;height:14px;display:block;fill:currentColor}\n .ytp-plus-comments-sidepanel textarea,\n .ytp-plus-comments-sidepanel button,\n .ytp-plus-comments-sidepanel .ytp-plus-comments-item,\n .ytp-plus-comments-sidepanel .ytp-plus-comments-item-text,\n .ytp-plus-comments-sidepanel .ytp-plus-comments-item-meta,\n .ytp-plus-comments-sidepanel .ytp-plus-voting-empty{font-family:inherit}\n ", "ytplus-playlist-delete-styles": "\n .ytplus-playlist-search { padding: 8px 16px; background: transparent; border-bottom: 1px solid var(--yt-spec-10-percent-layer); z-index: 50; width: 94%; }\n .ytplus-playlist-search-input { width: 93%; padding: 8px 16px; border: 1px solid var(--yt-spec-10-percent-layer); border-radius: 20px; background: var(--yt-spec-badge-chip-background); color: var(--yt-text-primary); font-size: 14px; font-family: 'Roboto', Arial, sans-serif; outline: none; transition: border-color 0.2s; }\n .ytplus-playlist-search-input.is-focused { border-color: var(--yt-spec-call-to-action); }\n .ytplus-playlist-input-row { display: flex; align-items: center; gap: 6px; }\n .ytplus-playlist-input-row .ytplus-playlist-search-input { width: auto; flex: 1; }\n .ytplus-playlist-delete-toggle { background: transparent; border: 1px solid var(--yt-spec-10-percent-layer); border-radius: 50%; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; color: var(--yt-spec-text-secondary); transition: background-color 0.2s cubic-bezier(0.2,0,0,1), border-color 0.2s cubic-bezier(0.2,0,0,1), color 0.2s cubic-bezier(0.2,0,0,1), transform 0.1s cubic-bezier(0.2,0,0,1); vertical-align: middle; margin-left: 6px; flex-shrink: 0; }\n .ytplus-playlist-delete-toggle:active { transform: scale(0.96) !important; }\n .ytplus-playlist-delete-toggle:hover { color: var(--yt-spec-text-primary); border-color: var(--yt-spec-text-secondary); }\n .ytplus-playlist-delete-bar { display: none; padding: 6px 0 0; gap: 8px; align-items: center; flex-wrap: wrap; }\n .ytplus-playlist-delete-bar.is-visible { display: flex; }\n .ytplus-playlist-selected-count { font-size: 12px; color: var(--yt-spec-text-secondary); margin-right: auto; }\n .ytplus-playlist-delete-action { padding: 5px 12px; border-radius: 16px; border: 1px solid var(--yt-spec-10-percent-layer); cursor: pointer; font-size: 12px; font-weight: 500; background: var(--yt-spec-badge-chip-background); color: var(--yt-spec-text-primary); transition: background-color 0.2s cubic-bezier(0.2,0,0,1), border-color 0.2s cubic-bezier(0.2,0,0,1), color 0.2s cubic-bezier(0.2,0,0,1), transform 0.1s cubic-bezier(0.2,0,0,1); }\n .ytplus-playlist-delete-action:active { transform: scale(0.96) !important; }\n .ytplus-playlist-delete-selected { background: var(--yt-search-highlight-bg); border-color: var(--yt-search-highlight-border); color: var(--yt-search-highlight-accent); }\n .ytplus-playlist-delete-selected:disabled { opacity: 0.5; }\n .ytplus-playlist-delete-selected:not(:disabled):hover { background: var(--yt-search-highlight-hover) !important; }\n .ytplus-playlist-select-all:hover, .ytplus-playlist-clear-all:hover { background: var(--yt-spec-10-percent-layer) !important; }\n .ytplus-playlist-item-checkbox { position: absolute; top: 8px; left: 8px; z-index: 2; cursor: pointer; opacity: 0.85; transition: opacity 0.15s; }\n .ytplus-playlist-item-checkbox:hover { opacity: 1; }\n ", "ytp-download-styles": "\n .ytp-download-button{position:relative!important;display:inline-flex!important;align-items:center!important;justify-content:center!important;height:100%!important;vertical-align:top!important;cursor:pointer!important;}\n .download-options{position:fixed;background:var(--yt-glass-bg);color:var(--yt-text-primary);border-radius:var(--yt-radius-md);width:150px;z-index:2147483647;box-shadow:var(--yt-glass-shadow);border:1px solid var(--yt-glass-border);overflow:hidden;opacity:0;pointer-events:none;transition:opacity .2s ease,transform .2s ease;transform:translateY(8px);box-sizing:border-box;}\n .download-options.visible{opacity:1;pointer-events:auto;transform:translateY(0);backdrop-filter:var(--yt-glass-blur);-webkit-backdrop-filter:var(--yt-glass-blur);}\n .download-options-list{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;}\n .download-option-item{cursor:pointer;padding:12px;text-align:center;transition:background .2s,color .2s;width:100%;}\n .download-option-item:hover{background:var(--yt-hover-bg);color:var(--yt-accent);}\n .download-submenu{margin:4px 0 12px 12px;}\n .download-submenu-container{display:flex;flex-direction:column;gap:8px;}\n .download-site-option{display:flex;flex-direction:column;gap:8px;}\n .download-site-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;}\n .download-site-label{display:flex;flex-direction:column;gap:2px;cursor:pointer;}\n .download-site-name{font-size:13px;font-weight:600;color:var(--yt-text-primary);}\n .download-site-desc{font-size:12px;color:var(--yt-text-secondary);}\n .download-site-controls{display:flex;flex-direction:column;gap:8px;margin-top:4px;}\n .download-site-input{width:100%;height:36px;border-radius:8px;border:1px solid var(--yt-glass-border);background:var(--yt-glass-bg);color:var(--yt-text-primary);padding:0 10px;box-sizing:border-box;}\n .download-site-input.small{height:32px;font-size:12px;}\n .download-site-input:focus{background:var(--yt-hover-bg);outline:none;}\n .download-site-cta{display:flex;gap:8px;flex-wrap:wrap;}\n .download-site-cta.one-btn{justify-content:flex-start;}\n ", "ytp-enhanced-styles": '\n :root{--yt-scrollbar-width:8px;--yt-scrollbar-track:transparent;--yt-scrollbar-thumb:rgba(144,144,144,.5);--yt-scrollbar-thumb-hover:rgba(170,170,170,.7);--yt-scrollbar-thumb-active:rgba(190,190,190,.9);}\n ::-webkit-scrollbar{width:var(--yt-scrollbar-width)!important;height:var(--yt-scrollbar-width)!important;}\n ::-webkit-scrollbar-track{background:var(--yt-scrollbar-track)!important;border-radius:4px!important;}\n ::-webkit-scrollbar-thumb{background:var(--yt-scrollbar-thumb)!important;border-radius:4px!important;transition:background .2s!important;}\n ::-webkit-scrollbar-thumb:hover{background:var(--yt-scrollbar-thumb-hover)!important;}\n ::-webkit-scrollbar-thumb:active{background:var(--yt-scrollbar-thumb-active)!important;}\n ::-webkit-scrollbar-corner{background:transparent!important;}\n html,body,#content,#guide-content,#secondary,#comments,#chat,ytd-comments,ytd-watch-flexy,ytd-browse,ytd-search,ytd-playlist-panel-renderer,#right-tabs,.tab-content-cld,ytmusic-app-layout{scrollbar-width:thin;scrollbar-color:var(--yt-scrollbar-thumb) var(--yt-scrollbar-track);}\n html[dark],html[data-ytp-theme="dark"]{--yt-scrollbar-thumb:rgba(144,144,144,.4);--yt-scrollbar-thumb-hover:rgba(170,170,170,.6);--yt-scrollbar-thumb-active:rgba(190,190,190,.8);}\n html[light],html[data-ytp-theme="light"],html:not([dark]):not([data-ytp-theme="dark"]){--yt-scrollbar-thumb:rgba(60,60,60,.35);--yt-scrollbar-thumb-hover:rgba(60,60,60,.55);--yt-scrollbar-thumb-active:rgba(40,40,40,.75);}\n .top-button{position:fixed;bottom:16px;right:16px;width:40px;height:40px;background:var(--yt-button-bg);color:var(--yt-text-primary);border:1px solid var(--yt-glass-border);border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:2100;opacity:0;visibility:hidden;transition:opacity .3s cubic-bezier(0.2,0,0,1), visibility .3s cubic-bezier(0.2,0,0,1), background-color .3s cubic-bezier(0.2,0,0,1), transform .15s cubic-bezier(0.2,0,0,1), box-shadow .3s cubic-bezier(0.2,0,0,1), border-color .3s cubic-bezier(0.2,0,0,1);backdrop-filter:var(--yt-glass-blur);-webkit-backdrop-filter:var(--yt-glass-blur);box-shadow:var(--yt-shadow);}\n .top-button:hover{background:var(--yt-hover-bg);transform:translateY(-2px) scale(1.07);box-shadow:var(--yt-shadow);}\n .top-button:active{transform:scale(0.96) !important;}\n .top-button:focus{outline:2px solid var(--yt-accent);outline-offset:2px;}\n .top-button.visible{opacity:1;visibility:visible;}\n .top-button svg{transition:transform .2s ease;}\n .top-button:hover svg{transform:translateY(-1px) scale(1.1);}\n html[dark],html[data-ytp-theme="dark"]{--yt-top-btn-bg:var(--yt-button-bg);--yt-top-btn-color:var(--yt-text-primary);--yt-top-btn-border:var(--yt-glass-border);--yt-top-btn-hover:var(--yt-hover-bg);}\n html[data-ytp-theme="light"],html:not([dark]):not([data-ytp-theme="dark"]){--yt-top-btn-bg:var(--yt-button-bg);--yt-top-btn-color:var(--yt-text-primary);--yt-top-btn-border:var(--yt-glass-border);--yt-top-btn-hover:var(--yt-hover-bg);}\n #right-tabs .top-button{position:absolute;z-index:1000;}\n ytd-watch-flexy:not([tyt-tab^="#"]) #right-tabs .top-button{display:none;}\n ytd-playlist-panel-renderer .top-button{position:absolute;z-index:1000;}\n ytd-watch-flexy[flexy] #movie_player, ytd-watch-flexy[flexy] #movie_player .html5-video-container, ytd-watch-flexy[flexy] .html5-main-video{width:100%!important; max-width:100%!important;}\n ytd-watch-flexy[flexy] .html5-main-video{height:auto!important; max-height:100%!important; object-fit:contain!important; transform:none!important;}\n ytd-watch-flexy[flexy] #player-container-outer, ytd-watch-flexy[flexy] #movie_player{display:flex!important; align-items:center!important; justify-content:center!important;}\n dislike-button-view-model,\n ytd-toggle-button-renderer,\n yt-button-shape,\n ytd-segmented-like-dislike-button-renderer{min-width:fit-content!important;width:auto!important;}\n dislike-button-view-model button{min-width:fit-content!important;width:auto!important;}\n dislike-button-view-model .yt-spec-button-shape-next__button-text-content{display:inline-flex!important;align-items:center!important;justify-content:center!important;}\n #ytp-plus-dislike-text{display:inline-block!important;visibility:visible!important;opacity:1!important;}\n #ytp-plus-dislike-text.ytp-plus-dislike-text--regular{margin-left:6px!important;font-size:1.4rem!important;line-height:2rem!important;font-weight:500!important;min-width:2em!important;text-align:center!important;}\n #ytp-plus-dislike-text.ytp-plus-dislike-text--shorts{margin-left:4px!important;font-size:1.2rem!important;line-height:1.8rem!important;font-weight:500!important;min-width:1.5em!important;text-align:center!important;}\n ytd-segmented-like-dislike-button-renderer dislike-button-view-model button{min-width:fit-content!important;}\n ytd-segmented-like-dislike-button-renderer .yt-spec-button-shape-next__button-text-content{min-width:2.4rem!important;}\n ytd-reel-video-renderer dislike-button-view-model #ytp-plus-dislike-text.ytp-plus-dislike-text--shorts{font-size:1.2rem!important;line-height:1.8rem!important;margin-left:4px!important;}\n ytd-reel-video-renderer dislike-button-view-model button{padding:8px 12px!important;min-width:auto!important;}\n ytd-shorts dislike-button-view-model .yt-spec-button-shape-next__button-text-content{display:inline-flex!important;min-width:auto!important;}\n ', "ytp-play-all-styles": ".ytp-play-all-btn{display:inline-flex;align-items:center;padding:0 12px;height:32px;border-radius:8px;background:linear-gradient(135deg,var(--yt-playall-accent-purple),var(--yt-playall-accent-blue));color:#fff;font-size:1.4rem;font-weight:500;text-decoration:none;white-space:nowrap;cursor:pointer;flex-shrink:0;user-select:none;font-family:Roboto,Arial,sans-serif;letter-spacing:.007em;line-height:1;vertical-align:middle;border:none;outline:none}.ytp-play-all-btn:hover{opacity:.85}\n.ytp-play-all-parent{display:flex;flex-wrap:wrap;align-items:center;gap:8px}\n.ytp-play-all-parent>chip-bar-view-model.ytChipBarViewModelHost{flex:1 1 auto;min-width:0}\n .ytp-random-badge-close{font-size:2rem;vertical-align:top;line-height:1;display:inline-block;}", "ytp-stats-styles": ".ytp-stats-btn{display:flex;align-items:center;justify-content:center;gap:8px}\n.ytp-stats-icon{width:20px;height:20px;fill:currentColor}\n.ytp-stats-btn-text{display:flex;align-items:center}\n.ytp-stats-touch-feedback{border-radius:inherit}\n.ytp-stats-channel-menu{display:flex;gap:15px;width:360px}\n.ytp-stats-display-label{display:block;margin-bottom:10px;font-size:16px;font-weight:bold}\n.ytp-stats-font-label{font-size:16px;font-weight:bold}\n.ytp-stats-font-value{font-size:14px;margin-bottom:15px}\n.ytp-stats-spinner{position:absolute;width:100%;height:100%;display:flex;align-items:center;justify-content:center}\n.ytp-stats-change-positive{color:#1ed760}\n.ytp-stats-change-negative{color:#f3727f}", "ytp-music-fab-styles": ".ytp-music-fab-side-panel{position:absolute!important;bottom:20px!important;right:20px!important;z-index:1200!important;pointer-events:auto!important;display:flex}\n.ytp-music-fab{position:fixed;bottom:100px;right:20px;z-index:10000;pointer-events:auto;display:flex}" }, e = e => "string" == typeof e && Object.hasOwn(t, e) ? t[e] : "", o = [ "ytp-screenshot-styles", "ytp-speedcontrol-styles", "shorts-keyboard-styles", "pip-styles", "timecode-panel-styles", "thumbnail-viewer-styles", "ytp-resume-overlay-styles", "ytp-plus-comments-modal-style", "ytplus-playlist-delete-styles", "ytp-download-styles", "ytp-play-all-styles", "ytp-stats-styles", "ytp-music-fab-styles" ], r = () => { try { const t = window.YouTubePlusDesignSystem?.StyleManager; if (!t || "function" != typeof t.add) { return; } for (const r of o) { const o = e(r); o && t.add(r, o); } } catch (t) { try { const e = window.YouTubePlusLogger || window.YouTubeUtils?.logger || null; e?.warn?.("design-system", "Failed to bootstrap static style bundles", t); } catch {} } }; if ("undefined" != typeof window) { window.YouTubePlusDesignSystem = { ...window.YouTubePlusDesignSystem || {}, styleBundles: t, getStyle: e, bootstrapStyleBundleIds: o, bootstrapStaticStyles: r }, r(), "loading" === document.readyState && document.addEventListener("DOMContentLoaded", r, { once: !0 }), window.addEventListener("yt-navigate-finish", r, { passive: !0 }); const i = [ "modifierComboValues", "resolveModifierComboValue", "formatModifierComboLabel", "buildModifierComboOptionItems", "buildModifierComboDropdownItems", "initGlassDropdown" ]; for (const t of i) { if (void 0 === window.YouTubePlusDesignSystem[t]) { try { Object.defineProperty(window.YouTubePlusDesignSystem, t, { configurable: !0, enumerable: !0, get() { const e = "undefined" != typeof window ? window.YouTubePlusModalHandlers : null; if (!e) { return; } const o = e[t]; return "function" == typeof o ? o.bind(e) : o; } }); } catch {} } } "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDesignSystem = window.YouTubePlusDesignSystem), window.YouTubePlusDesignSystem && (window.YouTubePlusDesignSystem.StyleManager && Object.freeze(window.YouTubePlusDesignSystem.StyleManager), Object.freeze(window.YouTubePlusDesignSystem)); } })(), (function() { function t() { if ("undefined" == typeof window || void 0 === window.trustedTypes) { return null; } const t = window.YouTubeTrustedTypes; if (t?.policy) { return t.policy; } try { const t = window.trustedTypes.createPolicy(u, { createHTML: t => { if ("string" != typeof t) { return String(t ?? ""); } if (!t) { return ""; } if (p) { return t; } p = !0; try { const e = (new DOMParser).parseFromString(t, "text/html"), o = document.createDocumentFragment(); e.body ? o.append(...e.body.childNodes) : e.documentElement && o.append(...e.documentElement.childNodes), s(o); const r = document.createElement("div"); return r.append(o), r.innerHTML; } finally { p = !1; } }, createScriptURL: t => { if ("string" != typeof t) { return String(t ?? ""); } try { const e = new URL(t, location.origin); if (e.origin === location.origin) { return t; } if (e.hostname.endsWith(".googleapis.com") || e.hostname.endsWith(".youtube.com")) { return t; } } catch {} return m()?.warn?.("Security", "Blocked untrusted script URL", t), "about:blank"; }, createScript: () => (m()?.warn?.("Security", "Blocked Trusted Types createScript call"), "") }); return "undefined" != typeof window && window.YouTubeTrustedTypes && (window.YouTubeTrustedTypes.policy = t), t; } catch { return t?.policy || null; } } function e(e) { const o = "string" == typeof e ? e : String(e ?? ""), r = t(); return r ? r.createHTML(o) : o; } function o(e) { const o = "string" == typeof e ? e : String(e ?? ""), r = t(); return r ? r.createScriptURL(o) : o; } function r(e) { const o = "string" == typeof e ? e : String(e ?? ""), r = t(); return r ? r.createScript(o) : o; } function i(t) { if ("string" != typeof t) { return !1; } const e = t.trim(); if (!e) { return !0; } if (e.startsWith("#") || e.startsWith("/")) { return !0; } const o = e.toLowerCase(); if (o.startsWith("javascript:")) { return !1; } if (o.startsWith("vbscript:")) { return !1; } if (o.startsWith("data:") && !o.startsWith("data:image/")) { return !1; } try { const t = new URL(e, location.origin); return [ "http:", "https:", "mailto:", "tel:", "blob:" ].includes(t.protocol); } catch { return !1; } } function a(t) { const o = document.createRange(), r = document.body || document.documentElement; r && o.selectNode(r); let i = t; return "string" == typeof t ? i = e(t) : null == t && (i = ""), o.createContextualFragment(i); } function s(t) { const e = window.NodeFilter?.SHOW_ELEMENT || 1, o = document.createTreeWalker(t, e), r = []; for (;o.nextNode(); ) { const t = o.currentNode; if (f.has(t.tagName.toUpperCase())) { r.push(t); continue; } const e = Array.from(t.attributes); for (const o of e) { const e = o.name.toLowerCase(), r = o.value; (e.startsWith("on") || "srcdoc" === e || b.has(e) && !i(r)) && t.removeAttribute(o.name); } } for (const t of r) { t.remove(); } } function c(t) { if ("string" != typeof t || 0 === t.length) { return ""; } const o = a(e(t)); s(o); const r = document.createElement("div"); return r.append(o), r.innerHTML; } function l(t) { return e(c(t)); } function d(t, e) { if (!t || "string" != typeof t) { return null; } if (null == e) { return ""; } if (/^on[a-z]/i.test(t)) { return m()?.warn?.("Security", `Blocked event handler attribute: ${t}`), null; } const o = String(e), r = t.toLowerCase(); if ("href" === r || "src" === r) { if (/^javascript:/i.test(o)) { return m()?.warn?.("Security", `Blocked javascript protocol in ${t}`), null; } if (o.toLowerCase().startsWith("data:") && !o.toLowerCase().startsWith("data:image/")) { return m()?.warn?.("Security", `Blocked non-image data: URI in ${t}`), null; } } return o; } const u = "youtubeplus#sanitize"; let p = !1, y = !1; const m = () => "undefined" != typeof window && window.YouTubePlusLogger || "undefined" != typeof window && window.YouTubeUtils && window.YouTubeUtils.logger || null, f = new Set([ "SCRIPT", "IFRAME", "OBJECT", "EMBED", "LINK", "META", "STYLE", "BASE", "FORM", "NOSCRIPT", "TEMPLATE" ]), b = new Set([ "href", "src", "xlink:href", "formaction", "action", "poster" ]); let h = null; if ("undefined" != typeof window) { h = { policyName: u, isSupported: void 0 !== window.trustedTypes, getPolicy: t, createHTML: e, createScriptURL: o, createScript: r }, window.YouTubeTrustedTypes = h, window._ytplusCreateHTML = e, (function() { if ("undefined" == typeof window || void 0 === window.trustedTypes) { return; } if (window.trustedTypes.defaultPolicy) { return; } const e = t(); try { window.trustedTypes.createPolicy("default", { createHTML: t => { if (y) { return "string" == typeof t ? t : String(t ?? ""); } y = !0; try { const o = "string" == typeof t ? t : String(t ?? ""); return e ? e.createHTML(o) : o; } finally { y = !1; } }, createScriptURL: t => { const o = "string" == typeof t ? t : String(t ?? ""); return e ? e.createScriptURL(o) : o; }, createScript: () => (m()?.warn?.("Security", "Blocked default Trusted Types createScript call"), "") }); } catch {} })(); const s = { createHTML: function(t) { return null == t ? "" : "string" != typeof t ? String(t) : e(t); }, createSafeHTML: l, createFragment: a, sanitizeHTML: c, setHTML: function(t, e, o = {}) { if (!(t instanceof HTMLElement)) { return; } const r = a((!1 !== o.sanitize ? l(e) : e) || ""); t.replaceChildren(r); }, renderTemplateClone: function(t, o) { if (!(t instanceof Element)) { return; } const r = a("string" == typeof o ? e(o) : o ?? e("")); t.replaceChildren(r); }, setText: function(t, e) { t instanceof HTMLElement && (t.textContent = "string" == typeof e ? e : ""); }, escapeHTML: function(t) { if ("string" != typeof t || 0 === t.length) { return ""; } const e = document.createElement("div"); return e.textContent = t, e.innerHTML; }, createTrustedHTML: e, createTrustedScriptURL: o, createTrustedScript: r, createTrustedInlineScript: r, getTrustedTypesPolicy: t, sanitizeAttribute: d, setAttributeSafe: function(t, e, o) { if (!(t instanceof HTMLElement)) { return m()?.error?.("Security", "Invalid element for setAttributeSafe"), !1; } const r = d(e, o); if (null === r) { return !1; } try { return t.setAttribute(e, r), !0; } catch (t) { return m()?.error?.("Security", "setAttribute failed", t), !1; } }, isSafeUrl: i, isValidVideoId: function(t) { return !(!t || "string" != typeof t) && /^[a-zA-Z0-9_-]{11}$/.test(t); }, sanitizeText: function(t) { return t && "string" == typeof t ? t.replace(/[<>]/g, "").replace(/javascript:/gi, "").replace(/on\w+=/gi, "").trim() : ""; } }; window.YouTubeSafeDOM = s, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubeSafeDOM = s); } "undefined" != typeof module && module.exports && (module.exports = "undefined" != typeof window ? window.YouTubeSafeDOM : {}); })(), (function() { function t(t, e, r, i) { const a = Date.now(), s = setInterval(() => { t() ? clearInterval(s) : Date.now() - a >= e && (clearInterval(s), i()); }, r); "undefined" != typeof window && o?.cleanupManager?.registerInterval && o.cleanupManager.registerInterval(s); } function e(e, r = 5e3, i = document) { return new Promise(a => { const s = i.querySelector(e); if (s) { return void a(s); } const c = () => { const t = i.querySelector(e); return !!t && (a(t), !0); }, l = i === document || i === document.body; if ("undefined" != typeof window && window.location && "string" == typeof window.location.pathname && "/playlist" === window.location.pathname && l) { return void t(c, r, 250, () => a(null)); } if (l) { const t = window.YouTubePlusDOMCache; if (t) { t.initSharedObserver(), t.observerCallbacks.add(c); const e = setTimeout(() => { t.observerCallbacks.delete(c), a(null); }, r); o?.cleanupManager?.registerTimeout && o.cleanupManager.registerTimeout(e); } return; } const d = o?.createRetryScheduler; if ("function" == typeof d) { return void d({ interval: 120, maxAttempts: Math.max(1, Math.ceil(r / 120)), check: c, onGiveUp: () => a(null) }); } const u = "undefined" != typeof window ? window.YouTubePlusMutationCoordinator : null; u && "function" == typeof u.createRetryScheduler ? u.createRetryScheduler({ interval: 120, maxAttempts: Math.max(1, Math.ceil(r / 120)), check: c, onGiveUp: () => a(null) }) : t(c, r, 120, () => a(null)); }); } const o = window.YouTubeUtils, r = new class DOMCache { constructor() { this.cache = new Map, this.multiCache = new Map, this.maxAge = 5e3, this.nullMaxAge = 1e3, this.maxSize = 500, this.cleanupSubId = null, this.cleanupPending = !1, this.enabled = !0, this.stats = { hits: 0, misses: 0, evictions: 0 }, this.contextUids = new WeakMap, this.uidCounter = 0, this.observerCallbacks = new Set, this.sharedObserverSubId = null, this.sharedObserverPending = !1, this.startCleanup(); } getContextUid(t) { if (t === document) { return "doc"; } let e = this.contextUids.get(t); return e || (e = ++this.uidCounter, this.contextUids.set(t, e)), e; } querySelector(t, e = document, o = !1) { if (!this.enabled || o) { return e.querySelector(t); } const r = `${t}::${this.getContextUid(e)}`, i = this.cache.get(r); if (i) { const t = i.element ? this.maxAge : this.nullMaxAge; if (Date.now() - i.timestamp < t) { if (!i.element) { return this.stats.hits++, null; } if (this.isElementInDOM(i.element)) { return this.stats.hits++, i.element; } } } if (this.stats.misses++, this.cache.size >= this.maxSize) { const t = this.cache.keys().next().value; void 0 !== t && this.cache.delete(t), this.stats.evictions++; } const a = e.querySelector(t); return this.cache.set(r, { element: a, timestamp: Date.now() }), a; } querySelectorAll(t, e = document, o = !1) { if (!this.enabled || o) { return Array.from(e.querySelectorAll(t)); } const r = `ALL::${t}::${this.getContextUid(e)}`, i = this.multiCache.get(r); if (i && this.areElementsValid(i)) { return i; } const a = Array.from(e.querySelectorAll(t)); return this.multiCache.set(r, a), a; } getElementById(t) { if (!this.enabled) { return document.getElementById(t); } const e = `ID::${t}`, o = this.cache.get(e); if (o) { const t = o.element ? this.maxAge : this.nullMaxAge; if (Date.now() - o.timestamp < t) { if (!o.element) { return null; } if (this.isElementInDOM(o.element)) { return o.element; } } } const r = document.getElementById(t); return this.cache.set(e, { element: r, timestamp: Date.now() }), r; } query(t, e) { return this.querySelector(t, e); } queryAll(t, e) { return this.querySelectorAll(t, e); } byId(t) { return this.getElementById(t); } get(t) { return this.querySelector(t); } getAll(t) { return this.querySelectorAll(t); } waitForElement(t, o) { return e(t, o, document); } isElementInDOM(t) { return !(!t || !document.contains(t)); } areElementsValid(t) { return !(!t || 0 === t.length) && this.isElementInDOM(t[0]) && this.isElementInDOM(t[t.length - 1]); } invalidate(t) { if (t) { for (const e of this.cache.keys()) { e.includes(t) && this.cache.delete(e); } for (const e of this.multiCache.keys()) { e.includes(t) && this.multiCache.delete(e); } } else { this.clear(); } } clear() { this.cache.clear(), this.multiCache.clear(); } startCleanup() { if (this.cleanupSubId) { return; } const t = () => { const t = Date.now(); for (const [e, o] of this.cache.entries()) { (t - o.timestamp > this.maxAge || o.element && !this.isElementInDOM(o.element)) && this.cache.delete(e); } for (const [t, e] of this.multiCache.entries()) { this.areElementsValid(e) || this.multiCache.delete(t); } }, e = window.YouTubePlusMutationCoordinator; e?.subscribeRoot && (this.cleanupSubId = e.subscribeRoot("dom-cache::cleanup", () => { if (this.cleanupPending) { return; } this.cleanupPending = !0; const e = () => { this.cleanupPending = !1, t(); }; "function" == typeof requestIdleCallback ? requestIdleCallback(e, { timeout: 1e3 }) : setTimeout(e, 0); }, { childList: !0, attributes: !0, subtree: !0 }), this.cleanupSubId && o?.cleanupManager?.register && o.cleanupManager.register(() => { this.cleanupSubId && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(this.cleanupSubId), this.cleanupSubId = null), this.cleanupPending = !1; })); } destroy() { this.cleanupSubId && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(this.cleanupSubId), this.cleanupSubId = null), this.cleanupPending = !1, this.clear(), this.sharedObserverSubId && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(this.sharedObserverSubId), this.sharedObserverSubId = null), this.observerCallbacks.clear(); } getStats() { return { size: this.cache.size, multiSize: this.multiCache.size, enabled: this.enabled }; } initSharedObserver() { if (this.sharedObserverSubId) { return; } const t = window.YouTubePlusMutationCoordinator; t?.subscribeRoot && (this.sharedObserverSubId = t.subscribeRoot("dom-cache::waitForElementShared", () => { if (0 === this.observerCallbacks.size) { return; } if (this.sharedObserverPending) { return; } this.sharedObserverPending = !0; const t = () => { this.sharedObserverPending = !1; for (const t of this.observerCallbacks) { try { t(); } catch (t) { "undefined" != typeof window && o?.logError && o.logError("DOMCache", "Observer callback error", t); } } }; "function" == typeof requestAnimationFrame ? requestAnimationFrame(t) : setTimeout(t, 0); })); } }; if ("undefined" != typeof window) { window.YouTubePlusDOMCache = r; const t = (t, o) => e(t, o, document); window.waitForElement = t, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDOMCache = r, unsafeWindow.waitForElement = t), o && (o.domCache = r, Object.defineProperty(o, "waitForElement", { configurable: !1, enumerable: !0, get: () => (t, o) => e(t, o, document), set() {} })); } "undefined" != typeof window && window.addEventListener && (window.addEventListener("yt-navigate-finish", () => { r.invalidate(); }), window.addEventListener("spfdone", () => { r.invalidate(); })), "undefined" != typeof window && window.addEventListener && window.addEventListener("beforeunload", () => { r.destroy(); }); })(), (function() { if ("undefined" == typeof window || window.YouTubePlusMutationCoordinator) { return; } const t = window.YouTubeUtils?.logger || null, e = new Map; let o = null, r = !1, i = [], a = null; const s = t => t ? JSON.stringify(t) : "null", c = (t, e) => { if (!t) { return !0; } for (const o of e) { const e = o.target; if (e instanceof Element && (e.matches(t) || e.closest(t))) { return !0; } for (const e of o.addedNodes) { if (e instanceof Element && (e.matches(t) || e.querySelector(t))) { return !0; } } } return !1; }, l = (t, e) => { const o = []; for (const r of e) { if ("attributes" === r.type) { if (!t.attributes) { continue; } if (t.attributeFilter && t.attributeFilter.length > 0 && r.attributeName && !t.attributeFilter.includes(r.attributeName)) { continue; } } ("childList" !== r.type || t.childList) && o.push(r); } return o; }, d = () => { if (r = !1, 0 === i.length) { return; } const o = i; i = []; for (const r of e.values()) { try { if (!c(r.selector, o)) { continue; } const t = l(r, o); t.length > 0 && r.callback(t); } catch (e) { t?.error?.("MutationCoordinator", "subscriber failed", e); } } }, u = () => { if (0 === e.size) { return o && (o.disconnect(), o = null), a = null, i = [], void (r = !1); } (t => { const e = document.body || document.documentElement; e && (o || (o = new MutationObserver(t => { i.push(...t), r || (r = !0, "function" == typeof requestAnimationFrame ? requestAnimationFrame(d) : setTimeout(d, 0)); })), s(a) !== s(t) && (o.disconnect(), o.observe(e, t), a = t)); })((() => { let t = !1, o = !1, r = !1; const i = new Set; for (const a of e.values()) { if (t = t || a.childList, o = o || a.attributes, a.attributes) { if (a.attributeFilter && 0 !== a.attributeFilter.length) { for (const t of a.attributeFilter) { i.add(t); } } else { r = !0; } } } return { childList: t, subtree: !0, attributes: o, attributeFilter: o && !r && i.size > 0 ? [ ...i ] : void 0 }; })()); }, p = new Map; let y = 0; const m = (e, o, r = "managed") => { const i = `ytp:timeout:${Date.now().toString(36)}:${y++}`, a = setTimeout(() => { p.delete(i); try { e(); } catch (e) { t?.error?.("MutationCoordinator", "managed timeout failed", e); } }, o); return p.set(i, { kind: "timeout", handle: a, label: r }), i; }, f = { subscribeRoot: (t, o, r = {}) => t && "function" == typeof o ? (e.set(t, { id: t, callback: o, selector: "string" == typeof r.selector ? r.selector : null, attributes: !0 === r.attributes, childList: !1 !== r.childList, subtree: !1 !== r.subtree, attributeFilter: Array.isArray(r.attributeFilter) ? r.attributeFilter.filter(t => "string" == typeof t && t.length > 0) : null }), u(), t) : null, subscribe: (t, e, o) => f.subscribeRoot(t, e, o), unsubscribe(t) { t && (e.delete(t), u()); }, watchTarget(t, e, o, r = {}) { if (!(t && e instanceof Node) || "function" != typeof o) { return null; } const i = { attributes: !1 !== r.attributes, childList: !1 !== r.childList, subtree: !1 !== r.subtree, attributeFilter: Array.isArray(r.attributeFilter) ? r.attributeFilter.filter(t => "string" == typeof t && t.length > 0) : null }; return f.subscribeRoot(t, t => { const r = t.filter(t => ((t, e, o) => { const r = !1 !== o.subtree; if ("attributes" === e.type) { return !!o.attributes && !(o.attributeFilter && o.attributeFilter.length > 0 && e.attributeName && !o.attributeFilter.includes(e.attributeName)) && (e.target === t || !!r && t instanceof Element && t.contains(e.target)); } if ("childList" === e.type) { if (!o.childList) { return !1; } if (e.target === t) { return !0; } if (!r) { return !1; } if (t instanceof Element && t.contains(e.target)) { return !0; } for (const o of e.addedNodes) { if (o === t) { return !0; } if (t instanceof Element && o instanceof Element && t.contains(o)) { return !0; } } for (const o of e.removedNodes) { if (o === t) { return !0; } } } return !1; })(e, t, i)); r.length > 0 && o(r); }, { selector: "string" == typeof r.selector ? r.selector : null, attributes: i.attributes, childList: i.childList, subtree: !0, attributeFilter: i.attributeFilter }); }, watch: (t, e, o, r) => f.watchTarget(t, e, o, r), unwatch(t) { f.unsubscribe(t); }, createRetryScheduler(e) { const {check: o, maxAttempts: r = 20, interval: i = 250, onGiveUp: a, label: s = "retry"} = e || {}; let c = 0, l = null, d = !1; const u = () => { if (!d) { c += 1; try { if (o()) { return void (d = !0); } } catch (e) { t?.error?.("MutationCoordinator", "retry check failed", e); } if (c >= r) { if (d = !0, "function" == typeof a) { try { a(); } catch (e) { t?.error?.("MutationCoordinator", "retry give-up callback failed", e); } } } else { l = m(u, i, s); } } }; return l = m(u, 0, s), { stop() { d = !0, l && (t => { if (!t) { return; } const e = p.get(t); e && (clearTimeout(e.handle), p.delete(t)); })(l), l = null; } }; }, getStats: () => ({ rootSubscribers: e.size, rootObserverActive: !!o, managedTimers: p.size }), dispose() { o && (o.disconnect(), o = null), a = null, i = [], r = !1, e.clear(); for (const [t, e] of p) { clearTimeout(e.handle), p.delete(t); } } }; "undefined" != typeof window && window.addEventListener && window.addEventListener("pagehide", () => f.dispose()), "undefined" != typeof window && (window.YouTubePlusMutationCoordinator = f, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusMutationCoordinator = f)); })(), (function() { if ("undefined" == typeof window) { return; } if (window.YouTubePlusEventDelegation) { return; } const t = window.YouTubeUtils?.logger || null; class EventDelegator { constructor() { this.delegatedHandlers = new Map, this.registeredDelegators = new Map, this.m = new WeakMap, this.h = 0, this.stats = { totalDelegations: 0, totalHandlers: 0 }; } on(e, o, r, i, a) { if (!(e && o && r && i)) { return void t?.warn?.("EventDelegator", "Invalid parameters"); } const s = e, c = `${this.k(s)}:${o}`; let l = this.delegatedHandlers.get(c); l || (l = new Map, this.delegatedHandlers.set(c, l)); let d = l.get(r); d || (d = new Set, l.set(r, d)), d.add(i), this.stats.totalHandlers++, this.S(s, o, a); } off(t, e, o, r) { if (!(t && e && o && r)) { return; } const i = t, a = `${this.k(i)}:${e}`, s = this.delegatedHandlers.get(a); if (!s) { return; } const c = s.get(o); c?.delete(r) && (this.stats.totalHandlers--, 0 === c.size && s.delete(o), 0 === s.size && (this.T(i, e), this.delegatedHandlers.delete(a))); } getStats() { return { ...this.stats, uniqueDelegations: this.registeredDelegators.size, delegationKeys: this.delegatedHandlers.size }; } clear() { for (const [t, e] of this.registeredDelegators.entries()) { for (const o of e.keys()) { try { const r = e.get(o); r && t.removeEventListener(o, r); } catch (t) {} } } this.delegatedHandlers.clear(), this.registeredDelegators.clear(), this.m = new WeakMap, this.h = 0, this.stats = { totalDelegations: 0, totalHandlers: 0 }; } S(e, o, r) { let i = this.registeredDelegators.get(e); if (i || (i = new Map, this.registeredDelegators.set(e, i)), i.has(o)) { return; } const a = t => { this.L(e, o, t); }; e.addEventListener(o, a, r), i.set(o, a), this.stats.totalDelegations++, t?.debug?.(`[EventDelegator] Created delegation on ${this.k(e)} for ${o}`); } L(e, o, r) { const i = `${this.k(e)}:${o}`, a = this.delegatedHandlers.get(i); if (!a) { return; } const s = r.target; for (const [o, i] of a.entries()) { const a = s?.closest(o); if (a && e.contains(a)) { for (const e of i) { try { e.call(a, r, a); } catch (e) { t?.error?.("EventDelegator", "Handler error", e); } } } } } T(t, e) { const o = this.registeredDelegators.get(t); if (!o) { return; } const r = o.get(e); r && (t.removeEventListener(e, r), this.stats.totalDelegations--), o.delete(e), 0 === o.size && this.registeredDelegators.delete(t); } k(t) { if (t === document) { return "document"; } if (t === window) { return "window"; } if (t === document.body) { return "body"; } const e = t; if (e.id) { return e.id; } const o = this.m.get(e); if (o) { return o; } this.h += 1; const r = `${e.tagName || "ELEM"}_${this.h}`; return this.m.set(e, r), r; } } const e = new EventDelegator, o = { EventDelegator, on: (t, o, r, i, a) => e.on(t, o, r, i, a), off: (t, o, r, i) => e.off(t, o, r, i), delegate: (t, o, r, i, a) => e.on(t, o, r, i, a), undelegate: (t, o, r, i) => e.off(t, o, r, i), getStats: () => e.getStats(), clear: () => e.clear() }; window.YouTubePlusEventDelegation = o, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusEventDelegation = o); })(), (function() { async function t(t) { if ("undefined" != typeof GM_xmlhttpRequest) { const e = await new Promise((e, o) => { const r = S(() => o(new Error("i18n request timeout")), 12e3); GM_xmlhttpRequest({ method: "GET", url: t, timeout: 12e3, headers: { Accept: "application/json" }, onload: t => { clearTimeout(r), t.status >= 200 && t.status < 300 ? e(t.responseText || "") : o(new Error(`HTTP ${t.status}: ${t.statusText || "request failed"}`)); }, onerror: t => { clearTimeout(r), o(new Error(`Network error: ${String(t)}`)); }, ontimeout: () => { clearTimeout(r), o(new Error("i18n request timeout")); } }); }); return JSON.parse(String(e || "{}")); } const e = await fetch(t, { cache: "default", headers: { Accept: "application/json" } }); if (!e.ok) { throw new Error(`HTTP ${e.status}`); } return e.json(); } function e(o) { const r = g.includes(o) ? o : "en", i = L.get(r); if (i) { return Promise.resolve(i); } const a = M.get(r); if (a) { return a; } const s = (async () => { try { const e = await (async function(e) { try { if ("undefined" != typeof window && window.YouTubePlusEmbeddedTranslations) { const t = window.YouTubePlusEmbeddedTranslations[e]; if (t) { return T?.debug?.("i18n", `Using embedded translations for ${e}`), t; } } } catch (t) { T?.warn?.("i18n", "Error reading embedded translations", t); } try { const o = `${h.github}/${e}.json`; return await t(o); } catch (o) { try { const o = `${h.jsdelivr}/${e}.json?_=${Date.now()}`; return T?.warn?.("i18n", `Raw GitHub fetch failed, trying jsDelivr: ${o}`), await t(o); } catch (t) { throw T?.error?.("i18n", `Failed to fetch translations for ${e}`, { err: t, firstErr: o }), t; } } })(r), o = (function(t) { if (!t || "object" != typeof t || Array.isArray(t)) { throw new Error("Invalid translation data: expected an object"); } const e = {}; for (const [o, r] of Object.entries(t)) { if ("string" != typeof o || "string" != typeof r) { throw new Error("Invalid translation entry: key and value must be strings"); } "__proto__" !== o && "constructor" !== o && "prototype" !== o && (e[o] = r); } return e; })(e); try { const t = []; for (const e of [ "loading", "fetching" ]) { Object.hasOwn(o, e) || t.push(e); } t.length > 0 && T?.warn?.("i18n", `Translations for ${r} missing keys: ${t.join(", ")} (source may be stale)`); } catch (t) {} return L.set(r, o), M.delete(r), o; } catch (t) { if (M.delete(r), "en" !== r) { return e("en"); } throw t; } })(); return M.set(r, s), s; } function o(t) { const e = String(t || "").toLowerCase(); if (!e) { return "en"; } if (x[e]) { return x[e]; } if (g.includes(e)) { return e; } const o = e.slice(0, 2); return x[o] ? x[o] : g.includes(o) ? o : v[e] ? v[e] : v[o] ? v[o] : "en"; } function r() { try { const t = document.documentElement.lang || window.YouTubeUtils?.$?.("html")?.getAttribute("lang"); if (t) { return o(t); } try { const t = new URLSearchParams(window.location.search).get("hl"); if (t) { return o(t); } } catch {} try { const t = window.ytcfg || window.yt?.config_; if (t && "function" == typeof t.get) { const e = t.get("HL") || t.get("GAPI_LOCALE"); if (e) { return o(e); } } } catch {} return o(navigator.language || navigator.userLanguage || "en"); } catch (t) { return T?.error?.("i18n", "Error detecting language", t), "en"; } } function i(t, e = {}) { if ("undefined" != typeof window) { try { window.dispatchEvent(new CustomEvent(t, { detail: P(e) })); } catch (e) { try { window.dispatchEvent(new Event(t)); } catch {} } } } function a(t, e) { if ("string" != typeof t || !t) { return ""; } const o = Object.entries(e || {}); if (0 === o.length) { return t; } let r = t; for (const [t, e] of o) { r = r.split(`{${t}}`).join(String(e)); } return r; } function s(t) { return _ && Object.hasOwn(_, t) ? { text: _[t], found: !0 } : I && Object.hasOwn(I, t) ? { text: I[t], found: !0 } : { text: "", found: !1 }; } function c(t, e = {}) { if ("string" != typeof t || !t) { return null == t ? "" : String(t); } const o = e && "object" == typeof e ? e : {}, r = Object.keys(o); if (0 === r.length) { if (C.has(t)) { return C.get(t) ?? t; } const {text: e, found: o} = s(t), r = o ? e : t; return !o && Object.keys(_).length > 0 && Object.keys(I).length > 0 && T?.warn?.("i18n", `Missing translation for key: ${t}`), C.set(t, r), r; } let i = ""; for (let t = 0; t < r.length; t++) { const e = r[t]; i += `${e}:${o[e]};`; } const c = `${t}:${i}`; if (C.has(c)) { return C.get(c) ?? t; } const {text: l, found: d} = s(t); let u; return d ? u = a(l, o) : (Object.keys(_).length > 0 && Object.keys(I).length > 0 && T?.warn?.("i18n", `Missing translation for key: ${t}`), u = a(t, o)), C.set(c, u), u; } async function l() { return A ? (await A, !0) : (A = (async () => { try { if (T?.debug?.("i18n", `Loading translations for ${z}...`), _ = await e(z), !I || 0 === Object.keys(I).length) { try { const t = "undefined" != typeof window && window.YouTubePlusEmbeddedTranslations && window.YouTubePlusEmbeddedTranslations.en; I = t && "object" == typeof t ? t : await e("en"); } catch (t) { I = {}; } } return C.clear(), T?.debug?.("i18n", `Loaded ${Object.keys(_).length} translations for ${z}`), !0; } catch (t) { return T?.error?.("i18n", "Failed to load translations", t), "en" !== z && (z = "en", l()); } finally { A = null; } })(), A); } function d() { return z; } function u() { return g.slice(); } function p() { return null === A && Object.keys(_).length > 0; } async function y() { try { z = r(), T?.debug?.("i18n", `Detected language: ${z} (${w[z] || z})`), await l(), i("youtube-plus-i18n-ready", { language: z }); } catch (t) { T?.error?.("i18n", "Initialization error", t), z = "en"; } } const m = "diorhc", f = "main", b = "locales", h = { github: `https://raw.githubusercontent.com/${m}/YTP/${f}/${b}`, jsdelivr: `https://cdn.jsdelivr.net/gh/${m}/YTP@${f}/${b}` }, g = [ "en", "ru", "ko", "fr", "nl", "zh-CN", "zh-TW", "ja", "tr", "es", "pt", "de", "it", "pl", "uk", "ar", "hi", "id", "vi", "uz", "kk", "ky", "be", "bg", "az" ], w = { en: "English", ru: "Русский", ko: "한국어", fr: "Français", nl: "Nederlands", "zh-CN": "简体中文", "zh-TW": "繁體中文", ja: "日本語", tr: "Türkçe", es: "Español", pt: "Português", de: "Deutsch", it: "Italiano", pl: "Polski", uk: "Українська", sv: "Svenska", no: "Norsk", da: "Dansk", fi: "Suomi", cs: "Čeština", sk: "Slovenčina", hu: "Magyar", ro: "Română", bg: "Български", hr: "Hrvatski", sr: "Српски", sl: "Slovenščina", el: "Ελληνικά", lt: "Lietuvių", lv: "Latviešu", et: "Eesti", mk: "Македонски", sq: "Shqip", bs: "Bosanski", is: "Íslenska", ca: "Català", eu: "Euskara", gl: "Galego", ar: "العربية", he: "עברית", fa: "فارسی", sw: "Kiswahili", zu: "isiZulu", af: "Afrikaans", am: "አማርኛ", hi: "हिन्दी", th: "ไทย", vi: "Tiếng Việt", id: "Bahasa Indonesia", ms: "Bahasa Melayu", bn: "বাংলা", ta: "தமிழ்", te: "తెలుగు", mr: "मराठी", gu: "ગુજરાતી", kn: "ಕನ್ನಡ", ml: "മലയാളം", pa: "ਪੰਜਾਬੀ", fil: "Filipino", km: "ភាសាខ្មែរ", lo: "ລາວ", my: "မြန်မာ", ne: "नेपाली", si: "සිංහල", az: "Azərbaycanca", be: "Беларуская", hy: "Հայերեն", ka: "ქართული", kk: "Қазақ", ky: "Кыргыз", mn: "Монгол", tg: "Тоҷикӣ", uz: "Oʻzbekcha" }, v = { es: "es", "es-es": "es", "es-mx": "es", "es-419": "es", pt: "pt", "pt-br": "pt", "pt-pt": "pt", de: "de", "de-de": "de", "de-at": "de", "de-ch": "de", it: "it", pl: "pl", uk: "uk", "uk-ua": "uk", ar: "ar", "ar-sa": "ar", "ar-ae": "ar", "ar-eg": "ar", hi: "hi", "hi-in": "hi", vi: "vi", "vi-vn": "vi", id: "id", "id-id": "id", bg: "bg", "bg-bg": "bg", sr: "ru", "sr-rs": "ru", az: "az", "az-az": "az", be: "be", "be-by": "be", hy: "ru", kk: "kk", "kk-kz": "kk", ky: "ky", mn: "ru", tg: "ru", uz: "uz", "uz-uz": "uz", mk: "ru", ca: "es", eu: "es", gl: "es", ...Object.fromEntries([ "th", "th-th", "ms", "ms-my", "sv", "sv-se", "no", "nb-no", "nn-no", "da", "da-dk", "fi", "fi-fi", "cs", "cs-cz", "sk", "sk-sk", "hu", "hu-hu", "ro", "ro-ro", "hr", "hr-hr", "sl", "sl-si", "el", "el-gr", "he", "he-il", "iw", "fa", "fa-ir", "bn", "bn-in", "ta", "ta-in", "te", "te-in", "mr", "mr-in", "gu", "gu-in", "kn", "kn-in", "ml", "ml-in", "pa", "pa-in", "fil", "fil-ph", "tl", "km", "lo", "my", "ne", "si", "sw", "sw-ke", "zu", "af", "am", "ka", "lt", "lt-lt", "lv", "lv-lv", "et", "et-ee", "sq", "bs", "is" ].map(t => [ t, "en" ])) }, x = { ko: "ko", "ko-kr": "ko", fr: "fr", "fr-fr": "fr", "fr-ca": "fr", "fr-be": "fr", "fr-ch": "fr", nl: "nl", "nl-nl": "nl", "nl-be": "nl", zh: "zh-CN", "zh-cn": "zh-CN", "zh-hans": "zh-CN", "zh-sg": "zh-CN", "zh-tw": "zh-TW", "zh-hk": "zh-TW", "zh-hant": "zh-TW", ja: "ja", "ja-jp": "ja", tr: "tr", "tr-tr": "tr", ru: "ru", "ru-ru": "ru", en: "en", "en-us": "en", "en-gb": "en", "en-au": "en", "en-ca": "en", "en-in": "en", "zh-CN": "zh-CN", "zh-TW": "zh-TW", ...v }, k = { ru: "ru-RU", ko: "ko-KR", fr: "fr-FR", nl: "nl-NL", "zh-CN": "zh-CN", "zh-TW": "zh-TW", ja: "ja-JP", tr: "tr-TR", es: "es-ES", pt: "pt-PT", de: "de-DE", it: "it-IT", pl: "pl-PL", uk: "uk-UA", ar: "ar-SA", hi: "hi-IN", vi: "vi-VN", id: "id-ID", uz: "uz-UZ", kk: "kk-KZ", ky: "ky-KG", be: "be-BY", bg: "bg-BG", az: "az-AZ" }, S = setTimeout.bind(window), T = window.YouTubePlusLogger || window.YouTubeUtils?.logger || null, L = new Map, M = new Map, C = new Map, E = new Set; let z = "en", _ = {}, I = {}, A = null; const P = t => { if (null == t || "object" != typeof t) { return t; } try { const e = globalThis?.structuredClone; if ("function" == typeof e) { return e(t); } } catch (t) {} try { return JSON.parse(JSON.stringify(t, (t, e) => { if ("function" != typeof e && "symbol" != typeof e) { return "bigint" == typeof e ? e.toString() : e; } })); } catch (t) { return {}; } }, j = { t: c, translate: c, getLanguage: d, setLanguage: async function(t) { if (t === z) { return !0; } const e = z; z = t; try { const t = await l(); if (t) { for (const t of E) { try { t(z, e); } catch (t) { T?.error?.("i18n", "Error in language change listener", t); } } i("youtube-plus-language-changed", { language: z, previousLanguage: e }); } return t; } catch (t) { return T?.error?.("i18n", "Failed to change language", t), z = e, !1; } }, detectLanguage: r, getAllTranslations: function() { return { ..._ }; }, getAvailableLanguages: u, hasTranslation: function(t) { return "string" == typeof t && (_ && Object.hasOwn(_, t) || I && Object.hasOwn(I, t)); }, addTranslation: function(t, e) { "string" == typeof t && t && (_[t] = String(e ?? ""), C.clear()); }, addTranslations: function(t) { t && "object" == typeof t && (Object.assign(_, t), C.clear()); }, onLanguageChange: function(t) { return "function" != typeof t ? () => {} : (E.add(t), () => E.delete(t)); }, formatNumber: function(t, e = {}) { try { const o = d(); return new Intl.NumberFormat(k[o] || "en-US", e).format(t); } catch (e) { return T?.error?.("i18n", "Error formatting number", e), String(t); } }, formatDate: function(t, e = {}) { try { const o = d(), r = k[o] || "en-US", i = t instanceof Date ? t : new Date(t); return new Intl.DateTimeFormat(r, e).format(i); } catch (e) { return T?.error?.("i18n", "Error formatting date", e), String(t); } }, pluralize: function(t, e, o, r) { if ("ru" === d() && r) { const i = t % 10, a = t % 100; return 1 === i && 11 !== a ? e : i >= 2 && i <= 4 && (a < 10 || a >= 20) ? r : o; } return 1 === t ? e : o; }, clearCache: function() { C.clear(); }, getCacheStats: function() { return { size: C.size, currentLanguage: z, availableLanguages: u(), translationsLoaded: Object.keys(_).length, fallbackLoaded: Object.keys(I).length }; }, getStats: function() { return { currentLanguage: z, translationCount: Object.keys(_).length, fallbackCount: Object.keys(I).length, cacheSize: C.size, availableLanguages: u(), ready: p() }; }, isReady: p, loadTranslations: l, initialize: y, get translations() { return { ..._ }; }, get currentLanguage() { return z; } }; "undefined" != typeof window && (window.YouTubePlusI18n = j, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusI18n = j), window.YouTubePlusI18nLoader = { loadTranslations: e, AVAILABLE_LANGUAGES: g, LANGUAGE_NAMES: w, CDN_URLS: h }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusI18nLoader = window.YouTubePlusI18nLoader), Object.freeze(window.YouTubePlusI18n), window.YouTubePlusI18nLoader && Object.freeze(window.YouTubePlusI18nLoader)), y().then(() => { T?.debug?.("i18n", "i18n system initialized successfully"); }); })(), (function() { function t(t) { if ("undefined" == typeof localStorage) { return null; } try { return localStorage.getItem(t); } catch (t) { return R("SettingsStore", "readRaw failed", t), null; } } function e(t, e) { if ("undefined" == typeof localStorage) { return !1; } try { return localStorage.setItem(t, e), !0; } catch (t) { return R("SettingsStore", "writeRaw failed", t), !1; } } function o(t, e) { if ("string" != typeof t || !t) { return e; } try { return JSON.parse(t); } catch (t) { return e; } } function r(t, e) { if (t && "object" == typeof t && e) { return e.split(".").filter(Boolean).reduce((t, e) => null == t ? void 0 : t[e], t); } } function i(t, e, o) { if (!t || "object" != typeof t || !e || "string" != typeof e) { return !1; } const r = e.split(".").filter(Boolean); if (!r.length) { return !1; } const i = r.pop(); if (!i) { return !1; } let a = t; for (const t of r) { Object.hasOwn(a, t) && "object" == typeof a[t] && null !== a[t] || (a[t] = {}), a = a[t]; } return a[i] = o, !0; } function a(t) { if (null == t) { return t; } try { return JSON.parse(JSON.stringify(t)); } catch (e) { return t; } } function s(t) { const e = { ...j }; if (!t || "object" != typeof t) { return e; } "boolean" == typeof t.enableMusic && (e.enableMusic = t.enableMusic); for (const o of Object.keys(j)) { "enableMusic" !== o && "boolean" == typeof t[o] && (e[o] = t[o]); } return "boolean" == typeof t.enableImmersiveSearch && (e.immersiveSearchStyles = t.enableImmersiveSearch), "boolean" == typeof t.enableSidebarHover && (e.hoverStyles = t.enableSidebarHover), "boolean" == typeof t.enableCenteredPlayer && (e.centeredPlayerStyles = t.enableCenteredPlayer), "boolean" == typeof t.enableScrollToTop && (e.scrollToTopStyles = t.enableScrollToTop), !!(t.enableMusicStyles || t.enableMusicEnhancements || t.enableImmersiveSearch || t.enableSidebarHover || t.enableCenteredPlayer || t.enableScrollToTop) && "boolean" != typeof t.enableMusic && (e.enableMusic = !0), e; } function c() { const e = (function(t) { try { if ("undefined" != typeof GM_getValue) { const e = GM_getValue(t, null); return "string" == typeof e && e ? e : null; } } catch {} return null; })(P.music); if (e) { const t = o(e, null); if (t && "object" == typeof t) { return s(t); } } const r = t(P.music); if (r) { const t = o(r, null); if (t && "object" == typeof t) { return s(t); } } return { ...j }; } function l(t) { const o = t && "object" == typeof t ? s(t) : { ...j }, r = JSON.stringify(o); return e(P.music, r), (function(t, e) { try { if ("undefined" != typeof GM_setValue) { return GM_setValue(t, e), !0; } } catch {} })(P.music, r), o; } function d(t) { if (!t || "object" != typeof t) { return null; } const e = {}, o = t.speedControl; o && "boolean" == typeof o.enabled && (e.enableSpeedControl = o.enabled); const r = t.screenshot; r && "boolean" == typeof r.enabled && (e.enableScreenshot = r.enabled); const i = t.download; return i && "boolean" == typeof i.enabled && (e.enableDownload = i.enabled), t.downloadSites && "object" == typeof t.downloadSites && (e.downloadSites = a(t.downloadSites)), Object.keys(e).length ? e : null; } function u(t, e) { if (!F.size) { return; } const o = F.get(t); if (o) { for (const r of o) { try { r(e, t); } catch (t) { R("SettingsStore", "subscriber callback failed", t); } } } } function p() { if (N) { return N; } let r = o(t(P.main), null), i = !1; if (!r || "object" != typeof r) { const e = d(o(t(P.all), null)); e && (r = e, i = !0); } const s = a(H); if (r && "object" == typeof r) { for (const t of Object.keys(r)) { if ("__proto__" === t || "constructor" === t || "prototype" === t) { continue; } const e = r[t]; s[t] = e && "object" == typeof e && !Array.isArray(e) && s[t] && "object" == typeof s[t] && !Array.isArray(s[t]) ? { ...s[t], ...a(e) } : a(e); } } if (i) { try { e(P.main, JSON.stringify(s)); } catch {} } return N = s, s; } function y(t) { const o = t && "object" == typeof t ? t : {}, r = JSON.stringify(o); if (e(P.main, r), N = null, "undefined" != typeof window) { try { window.dispatchEvent(new CustomEvent("youtube-plus-settings-updated", { detail: o })); } catch {} } } function m() { return c(); } function f(t) { if (!t || "object" != typeof t) { return !1; } const e = { ...c(), ...t }; if (l(e), u("music", e), "undefined" != typeof window) { try { window.dispatchEvent(new CustomEvent("youtube-plus-settings-updated", { detail: { music: e } })); } catch {} } return !0; } function b(t, e) { if ("string" != typeof t || "function" != typeof e) { return () => {}; } let o = F.get(t); return o || (o = new Set, F.set(t, o)), o.add(e), () => { const o = F.get(t); o && (o.delete(e), o.size || F.delete(t)); }; } function h(t) { return window.YouTubeSafeDOM?.escapeHTML ? window.YouTubeSafeDOM.escapeHTML(t) : "string" != typeof t ? "" : t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); } function g(t, e, o, r = !1) { const i = r ? " active" : "", a = h(t), s = h(e); return `\n <div class="ytp-plus-settings-nav-item${i}" data-section="${a}" data-label="${s}" title="${s}" aria-label="${s}">\n ${o}\n <span class="ytp-plus-settings-nav-item-label">${s}</span>\n </div>\n `; } function w(t, e) { try { const o = localStorage.getItem(t); if (null == o) { return e; } try { const t = JSON.parse(o); if ("object" == typeof t && null !== t && "enabled" in t) { return Boolean(t.enabled); } } catch (t) {} return "false" !== o; } catch (t) { return e; } } function v(t, e) { try { const o = localStorage.getItem(t); if (!o) { return e; } const r = JSON.parse(o); if (r && "object" == typeof r && r.shortcut) { return { ...e, ...r.shortcut }; } } catch (t) {} return e; } function x(t) { try { const e = localStorage.getItem("ytp-plus-submenu-states"); if (!e) { return null; } const o = JSON.parse(e); if (o && "boolean" == typeof o[t]) { return o[t]; } } catch (t) {} return null; } function k(t, e, o) { const r = t => { const e = window.YouTubePlusDesignSystem?.formatModifierComboLabel; return "function" == typeof e ? e(t, { noneLabel: o("none"), translatePart: t => o(t.toLowerCase()) }) : "none" === t ? o("none") : t.split("+").map(t => o(t.toLowerCase())).map(t => t.charAt(0).toUpperCase() + t.slice(1)).join("+"); }, i = (t => { const e = window.YouTubePlusDesignSystem?.resolveModifierComboValue; return "function" == typeof e ? e(t) : "none"; })(e), a = window.YouTubePlusDesignSystem?.buildModifierComboOptionItems?.(i, r) || "", s = window.YouTubePlusDesignSystem?.buildModifierComboDropdownItems?.(i, r) || ""; return `\n <select id="${t}-modifier-combo" class="${t}-hidden-select">\n ${a}\n </select>\n\n <div class="glass-dropdown" id="${t}-modifier-dropdown" tabindex="0" role="listbox" aria-expanded="false">\n <button class="glass-dropdown__toggle" type="button" aria-haspopup="listbox">\n <span class="glass-dropdown__label">${r(i)}</span>\n <svg class="glass-dropdown__chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>\n </button>\n <ul class="glass-dropdown__list" role="presentation">\n ${s}\n </ul>\n </div>\n\n <span class="${t}-shortcut-plus">+</span>\n <input type="text" id="${t}-key" class="${t}-key-input" value="${h(e.key)}" maxlength="1" autocomplete="off" spellcheck="false">\n `; } function S(t, e, o, r) { const i = h(o), a = `ytp-plus-setting-${i}`; return `\n <div class="ytp-plus-settings-item">\n <div>\n <label class="ytp-plus-settings-item-label" for="${a}">${h(t)}</label>\n <div class="ytp-plus-settings-item-description">${h(e)}</div>\n </div>\n <input type="checkbox" id="${a}" class="ytp-plus-settings-checkbox" data-setting="${i}" ${r ? "checked" : ""}>\n </div>\n `; } function T(t, e, o, r, i) { const a = h(o), s = `ytp-plus-setting-${a}`, c = i.map(t => `<option value="${h(String(t.value))}"${String(r) === String(t.value) ? " selected" : ""}>${h(t.label)}</option>`).join(""); return `\n <div class="ytp-plus-settings-item">\n <div>\n <label class="ytp-plus-settings-item-label" for="${s}">${h(t)}</label>\n <div class="ytp-plus-settings-item-description">${h(e)}</div>\n </div>\n <select id="${s}" class="ytp-plus-settings-select" data-setting="${a}">${c}</select>\n </div>\n `; } function L(t) { const {key: e, name: o, description: r, checked: i, hasControls: a, controls: s} = t, c = h(e), l = `download-site-${c}`; return `\n <div class="download-site-option">\n <div class="download-site-header">\n <label for="${l}" class="download-site-label">\n <div class="download-site-name">${h(o)}</div>\n <div class="download-site-desc">${h(r)}</div>\n </label>\n <input type="checkbox" id="${l}" class="ytp-plus-settings-checkbox" data-setting="downloadSite_${c}" ${i ? "checked" : ""}>\n </div>\n ${a ? `<div class="download-site-controls" style="display:${i ? "flex" : "none"};">${s}</div>` : ""}\n </div>\n `; } function M(t, e) { const o = t?.name || "SSYouTube", r = t?.url || "https://ssyoutube.com/watch?v={videoId}", i = e("siteName"), a = e("urlTemplate"); return `\n <input type="text" placeholder="${h(i)}" value="${h(o)}"\n data-site="externalDownloader" data-field="name" class="download-site-input"\n aria-label="${h(i)}">\n <input type="text" placeholder="${h(a)}" value="${h(r)}"\n data-site="externalDownloader" data-field="url" class="download-site-input small"\n aria-label="${h(a)}">\n <div class="download-site-cta">\n <button class="glass-button" id="download-externalDownloader-save">${h(e("saveButton"))}</button>\n <button class="glass-button danger" id="download-externalDownloader-reset">${h(e("resetButton"))}</button>\n </div>\n `; } function C(t, e) { try { const o = t(e); if ("string" == typeof o && o && o !== e) { return o; } } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "SettingsHelpers" }); } return e; } function E(t, e) { const o = !!t.enableDownload, r = !1 !== t.enableZenStyles, i = !!t.enableSpeedControl; return `\n <div class="ytp-plus-settings-section" data-section="basic">\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label" for="ytp-plus-setting-enableZenStyles">${C(e, "zenStylesTitle")}</label>\n <div class="ytp-plus-settings-item-description">${C(e, "zenStylesDesc")}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle"\n data-submenu="style"\n aria-label="Toggle styles submenu"\n aria-expanded="${r ? "true" : "false"}"\n ${r ? "" : "disabled"}\n style="display:${r ? "inline-flex" : "none"};"\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" id="ytp-plus-setting-enableZenStyles" class="ytp-plus-settings-checkbox" data-setting="enableZenStyles" ${r ? "checked" : ""}>\n </div>\n </div>\n ${(function(t, e) { const o = t.enableZenStyles ? "block" : "none", r = Number(t.zenStyles?.sideVideosColumns), i = Number.isFinite(r) ? Math.max(0, Math.min(2, r)) : 0, a = !0 === t.zenStyles?.sideVideosColumnsEnabled || i > 0; return `\n <div class="style-submenu" data-submenu="style" style="display:${o};">\n <div class="glass-card style-submenu-container">\n ${[ { label: C(e, "zenStyleThumbnailHoverLabel"), desc: C(e, "zenStyleThumbnailHoverDesc"), key: "zenStyles.thumbnailHover", value: t.zenStyles?.thumbnailHover }, { label: C(e, "zenStyleImmersiveSearchLabel"), desc: C(e, "zenStyleImmersiveSearchDesc"), key: "zenStyles.immersiveSearch", value: t.zenStyles?.immersiveSearch }, { label: C(e, "zenStyleHideVoiceSearchLabel"), desc: C(e, "zenStyleHideVoiceSearchDesc"), key: "zenStyles.hideVoiceSearch", value: t.zenStyles?.hideVoiceSearch }, { label: C(e, "zenStyleTransparentHeaderLabel"), desc: C(e, "zenStyleTransparentHeaderDesc"), key: "zenStyles.transparentHeader", value: t.zenStyles?.transparentHeader }, { label: C(e, "zenStyleHideSideGuideLabel"), desc: C(e, "zenStyleHideSideGuideDesc"), key: "zenStyles.hideSideGuide", value: t.zenStyles?.hideSideGuide }, { label: C(e, "zenStyleCleanSideGuideLabel"), desc: C(e, "zenStyleCleanSideGuideDesc"), key: "zenStyles.cleanSideGuide", value: t.zenStyles?.cleanSideGuide }, { label: C(e, "zenStyleFixFeedLayoutLabel"), desc: C(e, "zenStyleFixFeedLayoutDesc"), key: "zenStyles.fixFeedLayout", value: t.zenStyles?.fixFeedLayout }, { label: C(e, "zenStyleCompactFeedLabel"), desc: C(e, "zenStyleCompactFeedDesc"), key: "zenStyles.compactFeed", value: t.zenStyles?.compactFeed }, { label: C(e, "zenStyleBetterCaptionsLabel"), desc: C(e, "zenStyleBetterCaptionsDesc"), key: "zenStyles.betterCaptions", value: t.zenStyles?.betterCaptions }, { label: C(e, "zenStylePlayerBlurLabel"), desc: C(e, "zenStylePlayerBlurDesc"), key: "zenStyles.playerBlur", value: t.zenStyles?.playerBlur }, { label: C(e, "zenStyleTheaterEnhancementsLabel"), desc: C(e, "zenStyleTheaterEnhancementsDesc"), key: "zenStyles.theaterEnhancements", value: t.zenStyles?.theaterEnhancements } ].map(t => S(t.label, t.desc, t.key, t.value)).join("")}\n ${(function(t, e, o, r, i, a, s, c, l) { const d = h("zenStyles.sideVideosColumnsEnabled"), u = h("style-side-videos"), p = `ytp-plus-setting-${d}`; return `\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label" for="${p}">${h(t)}</label>\n <div class="ytp-plus-settings-item-description">${h(e)}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle"\n data-submenu="${u}"\n aria-label="Toggle ${u} submenu"\n aria-expanded="${r ? "true" : "false"}"\n ${r ? "" : "disabled"}\n style="display:${r ? "inline-flex" : "none"};"\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" id="${p}" class="ytp-plus-settings-checkbox" data-setting="${d}" ${r ? "checked" : ""} aria-label="${h(t)}">\n </div>\n </div>\n <div class="style-side-videos-submenu" data-submenu="${u}" style="display:${r ? "block" : "none"};">\n <div class="glass-card ytp-plus-settings-submenu-card">\n ${T(a, s, "zenStyles.sideVideosColumns", l, [ { value: 0, label: "Default (Off)" }, { value: 1, label: "1 Column" }, { value: 2, label: "2 Columns" } ])}\n </div>\n </div>\n `; })(C(e, "zenStyleSideVideosColumnsLabel"), C(e, "zenStyleSideVideosColumnsDesc"), 0, a, 0, C(e, "zenStyleSideVideosColumnsLabel"), C(e, "zenStyleSideVideosColumnsDesc"), 0, i)}\n </div>\n </div>\n `; })(t, e)}\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label" for="ytp-plus-setting-enableSpeedControl">${e("speedControl")}</label>\n <div class="ytp-plus-settings-item-description">${e("speedControlDesc")}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle"\n data-submenu="speed"\n aria-label="Toggle speed submenu"\n aria-expanded="${i ? "true" : "false"}"\n ${i ? "" : "disabled"}\n style="display:${i ? "inline-flex" : "none"};"\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" id="ytp-plus-setting-enableSpeedControl" class="ytp-plus-settings-checkbox" data-setting="enableSpeedControl" ${i ? "checked" : ""}>\n </div>\n </div>\n ${(function(t, e) { const o = t.enableSpeedControl ? "block" : "none", r = (t.speedControlHotkeys?.decrease || "g").slice(0, 1).toLowerCase(), i = (t.speedControlHotkeys?.increase || "h").slice(0, 1).toLowerCase(), a = (t.speedControlHotkeys?.reset || "b").slice(0, 1).toLowerCase(); return `\n <div class="speed-submenu" data-submenu="speed" style="display:${o};">\n <div class="glass-card speed-submenu-container">\n <div class="ytp-plus-settings-item speed-hotkeys-row">\n <div class="speed-hotkeys-info">\n <div class="ytp-plus-settings-item-label">${C(e, "speedHotkeysTitle")}</div>\n <div class="ytp-plus-settings-item-description">${C(e, "speedHotkeysDesc")}</div>\n <div class="speed-hotkeys-fields">\n <label class="speed-hotkey-field">\n <input\n type="text"\n class="speed-hotkey-input"\n data-speed-hotkey="decrease"\n value="${h(r)}"\n maxlength="1"\n autocomplete="off"\n spellcheck="false"\n >\n <span>${C(e, "decreaseSpeedHotkey")}</span>\n </label>\n <label class="speed-hotkey-field">\n <input\n type="text"\n class="speed-hotkey-input"\n data-speed-hotkey="increase"\n value="${h(i)}"\n maxlength="1"\n autocomplete="off"\n spellcheck="false"\n >\n <span>${C(e, "increaseSpeedHotkey")}</span>\n </label>\n <label class="speed-hotkey-field">\n <input\n type="text"\n class="speed-hotkey-input"\n data-speed-hotkey="reset"\n value="${h(a)}"\n maxlength="1"\n autocomplete="off"\n spellcheck="false"\n >\n <span>${C(e, "resetButton")}</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n </div>\n `; })(t, e)}\n ${S(e("screenshotButton"), e("screenshotButtonDesc"), "enableScreenshot", t.enableScreenshot)}\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label" for="ytp-plus-setting-enableDownload">${e("downloadButton")}</label>\n <div class="ytp-plus-settings-item-description">${e("downloadButtonDesc")}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle"\n data-submenu="download"\n aria-label="Toggle download submenu"\n aria-expanded="${o ? "true" : "false"}"\n ${o ? "" : "disabled"}\n style="display:${o ? "inline-flex" : "none"};"\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" id="ytp-plus-setting-enableDownload" class="ytp-plus-settings-checkbox" data-setting="enableDownload" ${t.enableDownload ? "checked" : ""}>\n </div>\n </div>\n ${(function(t, e) { return `\n <div class="download-submenu" data-submenu="download" style="display:${t.enableDownload ? "block" : "none"};">\n <div class="glass-card download-submenu-container">\n ${[ { key: "externalDownloader", name: t.downloadSiteCustomization?.externalDownloader?.name || "SSYouTube", description: e("customDownloader"), checked: t.downloadSites?.externalDownloader, hasControls: !0, controls: M(t.downloadSiteCustomization?.externalDownloader, e) }, { key: "ytdl", name: e("byYTDL"), description: e("customDownload"), checked: t.downloadSites?.ytdl, hasControls: !0, controls: '\n <div class="download-site-cta one-btn">\n <button class="glass-button" id="open-ytdl-github">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>\n <polyline points="15,3 21,3 21,9"/>\n <line x1="10" y1="14" x2="21" y2="3"/>\n </svg>\n GitHub\n </button>\n </div>\n ' }, { key: "direct", name: e("directDownload"), description: e("directDownloadDesc"), checked: t.downloadSites?.direct, hasControls: !1 } ].map(t => L(t)).join("")}\n </div>\n </div>\n `; })(t, e)}\n ${S(e("adBlocker"), e("adBlockerDescription"), "enableAdBlocker", w("youtube_adblocker_settings", !0))}\n </div>\n `; } function z() { try { return V.getMusicSettings(); } catch (t) { return { ...j }; } } function _(t, e) { const o = z(), r = !!o.enableMusic, i = !1 !== t.enableEnhanced, a = { enableTabview: !1 !== t.enableTabview, enableCommentTranslate: !1 !== t.enableCommentTranslate, enablePlayAll: !1 !== t.enablePlayAll, enableResumeTime: !1 !== t.enableResumeTime, enableZoom: !1 !== t.enableZoom, enableThumbnail: !1 !== t.enableThumbnail, enablePlaylistSearch: !1 !== t.enablePlaylistSearch, enableScrollToTopButton: !1 !== t.enableScrollToTopButton, enableRememberManualQuality: !1 !== t.enableRememberManualQuality }; return `\n <div class="ytp-plus-settings-section hidden" data-section="advanced">\n <div class="ytp-plus-settings-group">\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label">${C(e, "enhancedFeaturesTitle")}</label>\n <div class="ytp-plus-settings-item-description">${C(e, "enhancedFeaturesDesc")}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle"\n data-submenu="enhanced"\n aria-label="Toggle enhanced features submenu"\n aria-expanded="${i ? "true" : "false"}"\n ${i ? "" : "disabled"}\n style="display:${i ? "inline-flex" : "none"};"\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" class="ytp-plus-settings-checkbox" data-setting="enableEnhanced" ${i ? "checked" : ""}>\n </div>\n </div>\n\n <div class="enhanced-submenu" data-submenu="enhanced" style="display:${i ? "block" : "none"};">\n <div class="glass-card ytp-plus-settings-submenu-card">\n <div class="endscreen-settings-slot"></div>\n ${S(C(e, "enableTabviewLabel"), C(e, "enableTabviewDesc"), "enableTabview", a.enableTabview)}\n ${S(C(e, "enableCommentTranslateLabel"), C(e, "enableCommentTranslateDesc"), "enableCommentTranslate", a.enableCommentTranslate)}\n ${S(C(e, "enablePlayAllLabel"), C(e, "enablePlayAllDesc"), "enablePlayAll", a.enablePlayAll)}\n ${S(C(e, "enableResumeTimeLabel"), C(e, "enableResumeTimeDesc"), "enableResumeTime", a.enableResumeTime)}\n ${S(C(e, "enableZoomLabel"), C(e, "enableZoomDesc"), "enableZoom", a.enableZoom)}\n ${S(C(e, "thumbnailPreview"), C(e, "thumbnailPreviewDesc"), "enableThumbnail", a.enableThumbnail)}\n ${S(C(e, "enablePlaylistSearchLabel"), C(e, "enablePlaylistSearchDesc"), "enablePlaylistSearch", a.enablePlaylistSearch)}\n ${S(C(e, "scrollToTopButtonLabel"), C(e, "scrollToTopButtonDesc"), "enableScrollToTopButton", a.enableScrollToTopButton)}\n ${S(C(e, "rememberManualQualityLabel"), C(e, "rememberManualQualityDesc"), "enableRememberManualQuality", a.enableRememberManualQuality)}\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu ytp-plus-settings-item--top-gap">\n <div>\n <label class="ytp-plus-settings-item-label">${C(e, "enableLoopLabel")}</label>\n <div class="ytp-plus-settings-item-description">${C(e, "enableLoopDesc")}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <input type="checkbox" class="ytp-plus-settings-checkbox" data-setting="enableLoop" ${t.enableLoop ? "checked" : ""}>\n </div>\n </div>\n ${(function(t, e) { const o = t.enableLoop ? "block" : "none", r = (t.loopHotkeys?.setPointA || "k").slice(0, 1).toLowerCase(), i = (t.loopHotkeys?.setPointB || "l").slice(0, 1).toLowerCase(), a = (t.loopHotkeys?.resetPoints || "o").slice(0, 1).toLowerCase(); return `\n <div class="loop-submenu loop-submenu-compact" data-submenu="loop" style="display:${o};">\n <div class="ytp-plus-settings-item loop-hotkeys-row loop-hotkeys-row-no-margin">\n <div class="loop-hotkeys-info">\n <div class="ytp-plus-settings-item-label">${C(e, "loopSegmentTitle")}</div>\n <div class="ytp-plus-settings-item-description">${C(e, "loopSegmentDesc")}</div>\n <div class="loop-hotkeys-fields">\n <label class="loop-hotkey-field">\n <input\n type="text"\n class="loop-hotkey-input"\n data-loop-hotkey="setPointA"\n value="${h(r)}"\n maxlength="1"\n autocomplete="off"\n spellcheck="false"\n >\n <span>${C(e, "setPointAHotkey")}</span>\n </label>\n <label class="loop-hotkey-field">\n <input\n type="text"\n class="loop-hotkey-input"\n data-loop-hotkey="setPointB"\n value="${h(i)}"\n maxlength="1"\n autocomplete="off"\n spellcheck="false"\n >\n <span>${C(e, "setPointBHotkey")}</span>\n </label>\n <label class="loop-hotkey-field">\n <input\n type="text"\n class="loop-hotkey-input"\n data-loop-hotkey="resetPoints"\n value="${h(a)}"\n maxlength="1"\n autocomplete="off"\n spellcheck="false"\n >\n <span>${C(e, "resetButton")}</span>\n </label>\n </div>\n </div>\n </div>\n </div>\n `; })(t, e)}\n </div>\n </div>\n\n <div class="ytp-plus-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label">${e("youtubeMusicTitle")}</label>\n <div class="ytp-plus-settings-item-description">${e("youtubeMusicDesc")}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle"\n data-submenu="music"\n aria-label="Toggle YouTube Music submenu"\n aria-expanded="${r ? "true" : "false"}"\n ${r ? "" : "disabled"}\n style="display:${r ? "inline-flex" : "none"};"\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" class="ytp-plus-settings-checkbox" data-setting="enableMusic" ${o.enableMusic ? "checked" : ""}>\n </div>\n </div>\n\n <div class="music-submenu" data-submenu="music" style="display:${r ? "block" : "none"};">\n <div class="glass-card ytp-plus-settings-submenu-card">\n ${S(e("immersiveSearchLabel"), e("immersiveSearchDesc"), "immersiveSearchStyles", o.immersiveSearchStyles)}\n ${S(e("sidebarHoverLabel"), e("sidebarHoverDesc"), "hoverStyles", o.hoverStyles)}\n ${S(e("playerSidebarStylesLabel"), e("playerSidebarStylesDesc"), "playerSidebarStyles", o.playerSidebarStyles)}\n ${S(e("centeredPlayerLabel"), e("centeredPlayerDesc"), "centeredPlayerStyles", o.centeredPlayerStyles)}\n ${S(e("playerBarStylesLabel"), e("playerBarStylesDesc"), "playerBarStyles", o.playerBarStyles)}\n ${S(e("centeredPlayerBarStylesLabel"), e("centeredPlayerBarStylesDesc"), "centeredPlayerBarStyles", o.centeredPlayerBarStyles)}\n ${S(e("miniPlayerStylesLabel"), e("miniPlayerStylesDesc"), "miniPlayerStyles", o.miniPlayerStyles)}\n </div>\n </div>\n\n ${(function(t, e) { const o = w("youtube_pip_settings", !0), r = v("youtube_pip_settings", { key: "P", shiftKey: !0, altKey: !1, ctrlKey: !1 }), i = x("pip"), a = "boolean" != typeof i || i, s = o && a; return `\n <div class="ytp-plus-settings-item pip-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label" for="pip-enable-checkbox">${h(e("pipTitle"))}</label>\n <div class="ytp-plus-settings-item-description">${h(e("pipDescription"))}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle${o ? "" : " pip-submenu-toggle-hidden"}"\n data-submenu="pip"\n aria-label="${h(e("togglePipSubmenu"))}"\n aria-expanded="${a ? "true" : "false"}"\n ${o ? "" : "disabled"}\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" class="ytp-plus-settings-checkbox" data-setting="enablePiP" id="pip-enable-checkbox" ${o ? "checked" : ""}>\n </div>\n </div>\n\n <div class="pip-submenu pip-submenu-layout${s ? "" : " is-hidden"}" data-submenu="pip">\n <div class="glass-card pip-submenu-card">\n <div class="ytp-plus-settings-item pip-shortcut-item">\n <div>\n <label class="ytp-plus-settings-item-label">${h(e("pipShortcutTitle"))}</label>\n <div class="ytp-plus-settings-item-description">${h(e("pipShortcutDescription"))}</div>\n </div>\n <div class="pip-shortcut-editor">\n ${k("pip", r, e)}\n </div>\n </div>\n </div>\n </div>\n `; })(0, e)}\n\n ${(function(t, e) { const o = w("youtube_timecode_settings", !0), r = v("youtube_timecode_settings", { key: "T", shiftKey: !0, altKey: !1, ctrlKey: !1 }), i = x("timecode"), a = "boolean" != typeof i || i, s = o && a; return `\n <div class="ytp-plus-settings-item timecode-settings-item ytp-plus-settings-item--with-submenu">\n <div>\n <label class="ytp-plus-settings-item-label" for="timecode-enable-checkbox">${h(e("enableTimecode"))}</label>\n <div class="ytp-plus-settings-item-description">${h(e("enableDescription"))}</div>\n </div>\n <div class="ytp-plus-settings-item-actions">\n <button\n type="button"\n class="ytp-plus-submenu-toggle timecode-submenu-toggle${o ? "" : " timecode-submenu-toggle-hidden"}"\n data-submenu="timecode"\n aria-label="Toggle timecode submenu"\n aria-expanded="${a ? "true" : "false"}"\n ${o ? "" : "disabled"}\n >\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="6 9 12 15 18 9"></polyline>\n </svg>\n </button>\n <input type="checkbox" id="timecode-enable-checkbox" class="ytp-plus-settings-checkbox" data-setting="timecodeEnabled" ${o ? "checked" : ""}>\n </div>\n </div>\n\n <div class="timecode-submenu timecode-submenu-layout${s ? "" : " is-hidden"}" data-submenu="timecode">\n <div class="glass-card timecode-submenu-card">\n <div class="ytp-plus-settings-item timecode-settings-item timecode-shortcut-item timecode-shortcut-row">\n <div>\n <label class="ytp-plus-settings-item-label">${h(e("keyboardShortcut"))}</label>\n <div class="ytp-plus-settings-item-description">${h(e("shortcutDescription"))}</div>\n </div>\n <div class="timecode-shortcut-editor">\n ${k("timecode", r, e)}\n </div>\n </div>\n </div>\n </div>\n `; })(0, e)}\n </div>\n </div>\n `; } function I(t, e) { const o = "solid" === t?.zenStyles?.themeVariant ? "solid" : "glass"; return `\n <div class="ytp-plus-settings-section hidden" data-section="experimental">\n <div class="ytp-plus-settings-item ytp-plus-theme-item">\n <div>\n <label class="ytp-plus-settings-item-label">${C(e, "zenStyleThemeVariantLabel")}</label>\n <div class="ytp-plus-settings-item-description">${C(e, "zenStyleThemeVariantDesc")}</div>\n </div>\n <div class="ytp-plus-theme-grid" role="radiogroup" aria-label="${C(e, "zenStyleThemeVariantLabel")}">\n <button\n type="button"\n class="ytp-plus-theme-card ${"glass" === o ? "active" : ""}"\n role="radio"\n aria-checked="${"glass" === o ? "true" : "false"}"\n data-setting-card="zenStyles.themeVariant"\n data-value="glass"\n >\n <span class="ytp-plus-theme-card-title">${C(e, "themeVariantGlass")}</span>\n </button>\n <button\n type="button"\n class="ytp-plus-theme-card ${"solid" === o ? "active" : ""}"\n role="radio"\n aria-checked="${"solid" === o ? "true" : "false"}"\n data-setting-card="zenStyles.themeVariant"\n data-value="solid"\n >\n <span class="ytp-plus-theme-card-title">${C(e, "themeVariantSolid")}</span>\n </button>\n </div>\n </div>\n ${S(e("statisticsButton"), e("statisticsButtonDescription"), "enableStatsButton", w("youtube_stats_button_enabled", !0))}\n ${S(e("channelStatsTitle"), e("channelStatsDescription"), "enableChannelStats", w("youtube_channel_stats_settings", !0))}\n <div class="ytp-plus-settings-item comment-manager-settings-item">\n <div>\n <label class="ytp-plus-settings-item-label">${e("commentManagement")}</label>\n <div class="ytp-plus-settings-item-description">${e("bulkDeleteDescription")}</div>\n </div>\n <button class="ytp-plus-button update-open-page-btn comment-manager-settings-open-button" id="open-comment-history-page">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>\n <polyline points="15,3 21,3 21,9"/>\n <line x1="10" y1="14" x2="21" y2="3"/>\n </svg>\n </button>\n </div>\n </div>\n `; } function A(t, e) { const o = C(e, "votingPreviewBefore"), r = C(e, "votingPreviewAfter"); return `\n <div class="ytp-plus-settings-section hidden" data-section="voting">\n <div class="ytp-plus-settings-voting-header">\n <h3>${C(e, "votingTitle")}</h3>\n <p class="ytp-plus-settings-voting-desc">${C(e, "votingDesc")}</p>\n </div>\n\n <div class="ytp-plus-voting-preview">\n <div class="ytp-plus-ba-container">\n <div class="ytp-plus-ba-before">\n <img src="https://i.imgur.com/FVW4tdH.jpeg" alt="${o}" draggable="false" />\n <span class="ytp-plus-ba-label ytp-plus-ba-label-before">${o}</span>\n </div>\n <div class="ytp-plus-ba-after">\n <img src="https://i.imgur.com/ljq1KeL.jpeg" alt="${r}" draggable="false" />\n <span class="ytp-plus-ba-label ytp-plus-ba-label-after">${r}</span>\n </div>\n <div class="ytp-plus-ba-divider" role="separator" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50"></div>\n </div>\n\n <div class="ytp-plus-vote-bar-section" id="ytp-plus-vote-bar-section">\n <div class="ytp-plus-vote-bar-buttons">\n <div class="ytp-plus-vote-bar-track" id="ytp-plus-vote-bar-fill"></div>\n <button class="ytp-plus-vote-bar-btn" id="ytp-plus-vote-bar-up" type="button" aria-label="${C(e, "like")}" data-vote="1">\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20.9751 12.1852L20.2361 12.0574L20.9751 12.1852ZM20.2696 16.265L19.5306 16.1371L20.2696 16.265ZM6.93776 20.4771L6.19055 20.5417H6.19055L6.93776 20.4771ZM6.1256 11.0844L6.87281 11.0198L6.1256 11.0844ZM13.9949 5.22142L14.7351 5.34269V5.34269L13.9949 5.22142ZM13.3323 9.26598L14.0724 9.38725V9.38725L13.3323 9.26598ZM6.69813 9.67749L6.20854 9.10933H6.20854L6.69813 9.67749ZM8.13687 8.43769L8.62646 9.00585H8.62646L8.13687 8.43769ZM10.518 4.78374L9.79207 4.59542L10.518 4.78374ZM10.9938 2.94989L11.7197 3.13821L11.7197 3.13821L10.9938 2.94989ZM12.6676 2.06435L12.4382 2.77841L12.4382 2.77841L12.6676 2.06435ZM12.8126 2.11093L13.0419 1.39687L13.0419 1.39687L12.8126 2.11093ZM9.86194 6.46262L10.5235 6.81599V6.81599L9.86194 6.46262ZM13.9047 3.24752L13.1787 3.43584V3.43584L13.9047 3.24752ZM11.6742 2.13239L11.3486 1.45675L11.3486 1.45675L11.6742 2.13239ZM20.2361 12.0574L19.5306 16.1371L21.0086 16.3928L21.7142 12.313L20.2361 12.0574ZM13.245 21.25H8.59634V22.75H13.245V21.25ZM7.68497 20.4125L6.87281 11.0198L5.37839 11.149L6.19055 20.5417L7.68497 20.4125ZM19.5306 16.1371C19.0238 19.0677 16.3813 21.25 13.245 21.25V22.75C17.0712 22.75 20.3708 20.081 21.0086 16.3928L19.5306 16.1371ZM13.2548 5.10015L12.5921 9.14472L14.0724 9.38725L14.7351 5.34269L13.2548 5.10015ZM7.18772 10.2456L8.62646 9.00585L7.64728 7.86954L6.20854 9.10933L7.18772 10.2456ZM11.244 4.97206L11.7197 3.13821L10.2678 2.76157L9.79207 4.59542L11.244 4.97206ZM12.4382 2.77841L12.5832 2.82498L13.0419 1.39687L12.897 1.3503L12.4382 2.77841ZM10.5235 6.81599C10.8354 6.23198 11.0777 5.61339 11.244 4.97206L9.79207 4.59542C9.65572 5.12107 9.45698 5.62893 9.20041 6.10924L10.5235 6.81599ZM12.5832 2.82498C12.8896 2.92342 13.1072 3.16009 13.1787 3.43584L14.6306 3.05921C14.4252 2.26719 13.819 1.64648 13.0419 1.39687L12.5832 2.82498ZM11.7197 3.13821C11.7547 3.0032 11.8522 2.87913 11.9998 2.80804L11.3486 1.45675C10.8166 1.71309 10.417 2.18627 10.2678 2.76157L11.7197 3.13821ZM11.9998 2.80804C12.1345 2.74311 12.2931 2.73181 12.4382 2.77841L12.897 1.3503C12.3872 1.18655 11.8312 1.2242 11.3486 1.45675L11.9998 2.80804ZM14.1537 10.9842H19.3348V9.4842H14.1537V10.9842ZM14.7351 5.34269C14.8596 4.58256 14.824 3.80477 14.6306 3.0592L13.1787 3.43584C13.3197 3.97923 13.3456 4.54613 13.2548 5.10016L14.7351 5.34269ZM8.59634 21.25C8.12243 21.25 7.726 20.887 7.68497 20.4125L6.19055 20.5417C6.29851 21.7902 7.34269 22.75 8.59634 22.75V21.25ZM8.62646 9.00585C9.30632 8.42 10.0391 7.72267 10.5235 6.81599L9.20041 6.10924C8.85403 6.75767 8.30249 7.30493 7.64728 7.86954L8.62646 9.00585ZM21.7142 12.313C21.9695 10.8365 20.8341 9.4842 19.3348 9.4842V10.9842C19.9014 10.9842 20.3332 11.4959 20.2361 12.0574L21.7142 12.313ZM12.5921 9.14471C12.4344 10.1076 13.1766 10.9842 14.1537 10.9842V9.4842C14.1038 9.4842 14.0639 9.43901 14.0724 9.38725L12.5921 9.14471ZM6.87281 11.0198C6.84739 10.7258 6.96474 10.4378 7.18772 10.2456L6.20854 9.10933C5.62021 9.61631 5.31148 10.3753 5.37839 11.149L6.87281 11.0198Z" fill="currentColor"></path> <path opacity="0.5" d="M3.9716 21.4709L3.22439 21.5355L3.9716 21.4709ZM3 10.2344L3.74721 10.1698C3.71261 9.76962 3.36893 9.46776 2.96767 9.48507C2.5664 9.50239 2.25 9.83274 2.25 10.2344L3 10.2344ZM4.71881 21.4063L3.74721 10.1698L2.25279 10.299L3.22439 21.5355L4.71881 21.4063ZM3.75 21.5129V10.2344H2.25V21.5129H3.75ZM3.22439 21.5355C3.2112 21.383 3.33146 21.2502 3.48671 21.2502V22.7502C4.21268 22.7502 4.78122 22.1281 4.71881 21.4063L3.22439 21.5355ZM3.48671 21.2502C3.63292 21.2502 3.75 21.3686 3.75 21.5129H2.25C2.25 22.1954 2.80289 22.7502 3.48671 22.7502V21.2502Z" fill="currentColor"></path> </svg>\n </button>\n <button class="ytp-plus-vote-bar-btn" id="ytp-plus-vote-bar-down" type="button" aria-label="${C(e, "dislike")}" data-vote="-1">\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20.9751 11.8148L20.2361 11.9426L20.9751 11.8148ZM20.2696 7.73505L19.5306 7.86285L20.2696 7.73505ZM6.93776 3.52293L6.19055 3.45832H6.19055L6.93776 3.52293ZM6.1256 12.9156L6.87281 12.9802L6.1256 12.9156ZM13.9949 18.7786L14.7351 18.6573V18.6573L13.9949 18.7786ZM13.3323 14.734L14.0724 14.6128V14.6128L13.3323 14.734ZM6.69813 14.3225L6.20854 14.8907H6.20854L6.69813 14.3225ZM8.13687 15.5623L8.62646 14.9942H8.62646L8.13687 15.5623ZM10.518 19.2163L9.79207 19.4046L10.518 19.2163ZM10.9938 21.0501L11.7197 20.8618L11.7197 20.8618L10.9938 21.0501ZM12.6676 21.9356L12.4382 21.2216L12.4382 21.2216L12.6676 21.9356ZM12.8126 21.8891L13.0419 22.6031L13.0419 22.6031L12.8126 21.8891ZM9.86194 17.5374L10.5235 17.184V17.184L9.86194 17.5374ZM13.9047 20.7525L13.1787 20.5642V20.5642L13.9047 20.7525ZM11.6742 21.8676L11.3486 22.5433L11.3486 22.5433L11.6742 21.8676ZM20.2361 11.9426L19.5306 7.86285L21.0086 7.60724L21.7142 11.687L20.2361 11.9426ZM13.245 2.75H8.59634V1.25H13.245V2.75ZM7.68497 3.58754L6.87281 12.9802L5.37839 12.851L6.19055 3.45832L7.68497 3.58754ZM19.5306 7.86285C19.0238 4.93226 16.3813 2.75 13.245 2.75V1.25C17.0712 1.25 20.3708 3.91895 21.0086 7.60724L19.5306 7.86285ZM13.2548 18.8998L12.5921 14.8553L14.0724 14.6128L14.7351 18.6573L13.2548 18.8998ZM7.18772 13.7544L8.62646 14.9942L7.64728 16.1305L6.20854 14.8907L7.18772 13.7544ZM11.244 19.0279L11.7197 20.8618L10.2678 21.2384L9.79207 19.4046L11.244 19.0279ZM12.4382 21.2216L12.5832 21.175L13.0419 22.6031L12.897 22.6497L12.4382 21.2216ZM10.5235 17.184C10.8354 17.768 11.0777 18.3866 11.244 19.0279L9.79207 19.4046C9.65572 18.8789 9.45698 18.3711 9.20041 17.8908L10.5235 17.184ZM12.5832 21.175C12.8896 21.0766 13.1072 20.8399 13.1787 20.5642L14.6306 20.9408C14.4252 21.7328 13.819 22.3535 13.0419 22.6031L12.5832 21.175ZM11.7197 20.8618C11.7547 20.9968 11.8522 21.1209 11.9998 21.192L11.3486 22.5433C10.8166 22.2869 10.417 21.8137 10.2678 21.2384L11.7197 20.8618ZM11.9998 21.192C12.1345 21.2569 12.2931 21.2682 12.4382 21.2216L12.897 22.6497C12.3872 22.8135 11.8312 22.7758 11.3486 22.5433L11.9998 21.192ZM14.1537 13.0158H19.3348V14.5158H14.1537V13.0158ZM14.7351 18.6573C14.8596 19.4174 14.824 20.1952 14.6306 20.9408L13.1787 20.5642C13.3197 20.0208 13.3456 19.4539 13.2548 18.8998L14.7351 18.6573ZM8.59634 2.75C8.12243 2.75 7.726 3.11302 7.68497 3.58754L6.19055 3.45832C6.29851 2.20975 7.34269 1.25 8.59634 1.25V2.75ZM8.62646 14.9942C9.30632 15.58 10.0391 16.2773 10.5235 17.184L9.20041 17.8908C8.85403 17.2423 8.30249 16.6951 7.64728 16.1305L8.62646 14.9942ZM21.7142 11.687C21.9695 13.1635 20.8341 14.5158 19.3348 14.5158V13.0158C19.9014 13.0158 20.3332 12.5041 20.2361 11.9426L21.7142 11.687ZM12.5921 14.8553C12.4344 13.8924 13.1766 13.0158 14.1537 13.0158V14.5158C14.1038 14.5158 14.0639 14.561 14.0724 14.6128L12.5921 14.8553ZM6.87281 12.9802C6.84739 13.2742 6.96474 13.5622 7.18772 13.7544L6.20854 14.8907C5.62021 14.3837 5.31148 13.6247 5.37839 12.851L6.87281 12.9802Z" fill="currentColor"></path> <path opacity="0.5" d="M3.9716 2.52911L3.22439 2.4645L3.9716 2.52911ZM3 13.7656L3.74721 13.8302C3.71261 14.2304 3.36893 14.5322 2.96767 14.5149C2.5664 14.4976 2.25 14.1673 2.25 13.7656L3 13.7656ZM4.71881 2.59372L3.74721 13.8302L2.25279 13.701L3.22439 2.4645L4.71881 2.59372ZM3.75 2.48709V13.7656H2.25V2.48709H3.75ZM3.22439 2.4645C3.2112 2.61704 3.33146 2.74983 3.48671 2.74983V1.24983C4.21268 1.24983 4.78122 1.87192 4.71881 2.59372L3.22439 2.4645ZM3.48671 2.74983C3.63292 2.74983 3.75 2.63139 3.75 2.48709H2.25C2.25 1.80457 2.80289 1.24983 3.48671 1.24983V2.74983Z" fill="currentColor"></path> </svg>\n </button>\n </div>\n <div class="ytp-plus-vote-bar-count" id="ytp-plus-vote-bar-count">0</div>\n </div>\n </div>\n\n <div id="ytp-plus-voting-container"></div>\n </div>\n `; } const P = Object.freeze({ main: "youtube_plus_settings", all: "youtube_plus_all_settings_v2", music: "youtube-plus-music-settings" }), j = Object.freeze({ enableMusic: !0, immersiveSearchStyles: !0, hoverStyles: !0, playerSidebarStyles: !0, playerBarStyles: !0, centeredPlayerStyles: !0, centeredPlayerBarStyles: !0, miniPlayerStyles: !0, scrollToTopStyles: !0 }), H = Object.freeze({ enableDownload: !0, enableZenStyles: !0, enableSpeedControl: !0, enableScreenshot: !0, enableEnhanced: !0, enableLoop: !0, enableTabview: !0, enableCommentTranslate: !0, enablePlayAll: !0, enableResumeTime: !0, enableZoom: !0, enableThumbnail: !0, enablePlaylistSearch: !0, enableScrollToTopButton: !0, enableRememberManualQuality: !0, hideSideGuide: !1, zenStyles: { thumbnailHover: !0, immersiveSearch: !0, hideVoiceSearch: !0, transparentHeader: !0, hideSideGuide: !0, cleanSideGuide: !0, fixFeedLayout: !0, compactFeed: !0, betterCaptions: !0, playerBlur: !0, theaterEnhancements: !0, sideVideosColumns: 0, sideVideosColumnsEnabled: !1, themeVariant: "glass" }, speedControlHotkeys: { decrease: "g", increase: "h", reset: "b" }, loopHotkeys: { setPointA: "k", setPointB: "l", resetPoints: "o" }, downloadSites: { externalDownloader: !0, ytdl: !0, direct: !0 }, downloadSiteCustomization: { externalDownloader: { name: "SSYouTube", url: "https://ssyoutube.com/watch?v={videoId}" } }, music: { ...j } }), D = Object.freeze(new Set(Object.keys(H))), O = Object.freeze({ music: j, download: { enableDownload: !0, downloadSites: { externalDownloader: !0, ytdl: !0, direct: !0 } }, styles: H.zenStyles, speed: { enableSpeedControl: !0, speedControlHotkeys: H.speedControlHotkeys }, loop: { enableLoop: !0, loopHotkeys: H.loopHotkeys }, enhanced: { enableEnhanced: !0, enableTabview: !0, enableCommentTranslate: !0, enablePlayAll: !0, enableResumeTime: !0, enableZoom: !0, enableThumbnail: !0, enablePlaylistSearch: !0, enableScrollToTopButton: !0, enableRememberManualQuality: !0 }, screenshot: { enableScreenshot: !0 } }), B = "undefined" != typeof window && window.YouTubeUtils && window.YouTubeUtils.logger || null, R = (t, e, o) => { try { B?.warn?.(t, e, o); } catch {} }, F = new Map; let N = null; if ("undefined" != typeof window) { try { window.addEventListener("storage", () => { N = null; }); } catch (t) {} try { window.addEventListener("youtube-plus-settings-updated", () => { N = null; }); } catch (t) {} } const Z = Object.freeze({ STORAGE_KEYS: P, DEFAULTS: H, MUSIC_DEFAULTS: j, FEATURE_DEFAULTS: O, KEY_REGISTRY: D, readMusic: c, writeMusic: l, migrateLegacyV2: d, mergeMusicWithDefaults: s }), V = Object.freeze({ STORAGE_KEYS: P, DEFAULTS: H, MUSIC_DEFAULTS: j, FEATURE_DEFAULTS: O, KEY_REGISTRY: D, load: p, save: y, get: function(t, e) { const o = r(p(), t); return void 0 === o ? e : o; }, set: function(t, e) { const o = p(); return !!i(o, t, e) && (y(o), u(t, e), !0); }, update: function(t, e) { const o = p(), a = r(o, t); let s; return s = a && "object" == typeof a && !Array.isArray(a) && e && "object" == typeof e && !Array.isArray(e) ? { ...a, ...e } : e, !!i(o, t, s) && (y(o), u(t, s), !0); }, hasKey: function(t) { if ("string" != typeof t || !t) { return !1; } const e = t.split(".")[0]; return D.has(e); }, getFeature: function(t) { if ("music" === t) { return m(); } const e = O[t], o = p(); if (!e) { return null != o[t] ? a(o[t]) : {}; } const r = a(e); for (const t of Object.keys(e)) { Object.hasOwn(o, t) && (r[t] = a(o[t])); } return r; }, updateFeature: function(t, e) { if (!t || !e || "object" != typeof e) { return !1; } if ("music" === t) { return f(e); } const o = O[t]; if (!o) { return !1; } const r = p(), i = a(o); for (const t of Object.keys(o)) { Object.hasOwn(r, t) && null != r[t] && (i[t] = r[t]); } Object.assign(i, e); for (const t of Object.keys(i)) { r[t] = i[t]; } return y(r), u(t, i), !0; }, subscribe: b, getMusicSettings: m, saveMusicSettings: function(t) { return l(t); }, updateMusicSettings: f, subscribeMusicSettings: function(t) { return b("music", t); }, reset: function() { if ((function(t) { if ("undefined" != typeof localStorage) { try { localStorage.removeItem(t); } catch (t) { R("SettingsStore", "removeRaw failed", t); } } })(P.main), "undefined" != typeof window) { try { window.dispatchEvent(new CustomEvent("youtube-plus-settings-updated", { detail: a(H) })); } catch {} } }, M: Z }); "undefined" != typeof window && (window.YouTubePlusSettingsHelpers = { createSettingsSidebar: function(t) { return `\n <div class="ytp-plus-settings-nav ytp-plus-settings-nav-rail">\n ${g("basic", t("basicTab"), '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path opacity="0.5" d="M2 12.2039C2 9.91549 2 8.77128 2.5192 7.82274C3.0384 6.87421 3.98695 6.28551 5.88403 5.10813L7.88403 3.86687C9.88939 2.62229 10.8921 2 12 2C13.1079 2 14.1106 2.62229 16.116 3.86687L18.116 5.10812C20.0131 6.28551 20.9616 6.87421 21.4808 7.82274C22 8.77128 22 9.91549 22 12.2039V13.725C22 17.6258 22 19.5763 20.8284 20.7881C19.6569 22 17.7712 22 14 22H10C6.22876 22 4.34315 22 3.17157 20.7881C2 19.5763 2 17.6258 2 13.725V12.2039Z" stroke="currentColor" stroke-width="1.5"></path> <path d="M15 18H9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> </svg>\n ', !0)}\n ${g("advanced", t("advancedTab"), '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path opacity="0.5" d="M2 12C2 7.28595 2 4.92893 3.46447 3.46447C4.92893 2 7.28595 2 12 2C16.714 2 19.0711 2 20.5355 3.46447C22 4.92893 22 7.28595 22 12" stroke="currentColor" stroke-width="1.5"></path> <path d="M2 14C2 11.1997 2 9.79961 2.54497 8.73005C3.02433 7.78924 3.78924 7.02433 4.73005 6.54497C5.79961 6 7.19974 6 10 6H14C16.8003 6 18.2004 6 19.27 6.54497C20.2108 7.02433 20.9757 7.78924 21.455 8.73005C22 9.79961 22 11.1997 22 14C22 16.8003 22 18.2004 21.455 19.27C20.9757 20.2108 20.2108 20.9757 19.27 21.455C18.2004 22 16.8003 22 14 22H10C7.19974 22 5.79961 22 4.73005 21.455C3.78924 20.9757 3.02433 20.2108 2.54497 19.27C2 18.2004 2 16.8003 2 14Z" stroke="currentColor" stroke-width="1.5"></path> <path d="M9.5 14.4L10.9286 16L14.5 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> </svg>\n ')}\n ${g("experimental", t("experimentalTab"), '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M9.74872 2.49415L18.1594 7.31987M9.74872 2.49415L2.65093 14.7455C1.31093 17.0584 2.10615 20.0159 4.42709 21.3513C6.74803 22.6867 9.7158 21.8942 11.0558 19.5813L12.5511 17.0003L14.1886 14.1738L15.902 11.2163L18.1594 7.31987M9.74872 2.49415L8.91283 2M18.1594 7.31987L19 7.80374" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path opacity="0.5" d="M15.9021 11.2164L13.3441 9.74463M14.1887 14.1739L9.98577 11.7557M12.5512 17.0004L9.93848 15.4972" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path opacity="0.5" d="M22 14.9166C22 16.0672 21.1046 16.9999 20 16.9999C18.8954 16.9999 18 16.0672 18 14.9166C18 14.1967 18.783 13.2358 19.3691 12.6174C19.7161 12.2512 20.2839 12.2512 20.6309 12.6174C21.217 13.2358 22 14.1967 22 14.9166Z" stroke="currentColor" stroke-width="1.5"></path> </svg>\n ')}\n ${g("voting", C(t, "votingTab"), '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="12" cy="6" r="4" stroke="currentColor" stroke-width="1.5"></circle> <path opacity="0.5" d="M15 13.3271C14.0736 13.1162 13.0609 13 12 13C7.58172 13 4 15.0147 4 17.5C4 19.9853 4 22 12 22C17.6874 22 19.3315 20.9817 19.8068 19.5" stroke="currentColor" stroke-width="1.5"></path> <circle cx="18" cy="16" r="4" stroke="currentColor" stroke-width="1.5"></circle> <path d="M18 14.6667V17.3333" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M16.6665 16L19.3332 16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> </svg>\n ')}\n ${g("report", t("reportTab"), '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4 6V19C4 20.6569 5.34315 22 7 22H17C18.6569 22 20 20.6569 20 19V9C20 7.34315 18.6569 6 17 6H4ZM4 6V5" stroke="currentColor" stroke-width="1.5"></path> <path d="M18 6.00002V6.75002H18.75V6.00002H18ZM15.7172 2.32614L15.6111 1.58368L15.7172 2.32614ZM4.91959 3.86865L4.81353 3.12619H4.81353L4.91959 3.86865ZM5.07107 6.75002H18V5.25002H5.07107V6.75002ZM18.75 6.00002V4.30604H17.25V6.00002H18.75ZM15.6111 1.58368L4.81353 3.12619L5.02566 4.61111L15.8232 3.0686L15.6111 1.58368ZM4.81353 3.12619C3.91638 3.25435 3.25 4.0227 3.25 4.92895H4.75C4.75 4.76917 4.86749 4.63371 5.02566 4.61111L4.81353 3.12619ZM18.75 4.30604C18.75 2.63253 17.2678 1.34701 15.6111 1.58368L15.8232 3.0686C16.5763 2.96103 17.25 3.54535 17.25 4.30604H18.75ZM5.07107 5.25002C4.89375 5.25002 4.75 5.10627 4.75 4.92895H3.25C3.25 5.9347 4.06532 6.75002 5.07107 6.75002V5.25002Z" fill="currentColor"></path> <path opacity="0.5" d="M8 12H16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path opacity="0.5" d="M8 15.5H13.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> </svg>\n ')}\n ${g("about", t("aboutTab"), '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M15.5 9L15.6716 9.17157C17.0049 10.5049 17.6716 11.1716 17.6716 12C17.6716 12.8284 17.0049 13.4951 15.6716 14.8284L15.5 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path d="M13.2942 7.17041L12.0001 12L10.706 16.8297" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path d="M8.49994 9L8.32837 9.17157C6.99504 10.5049 6.32837 11.1716 6.32837 12C6.32837 12.8284 6.99504 13.4951 8.32837 14.8284L8.49994 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path opacity="0.5" d="M2 12C2 7.28595 2 4.92893 3.46447 3.46447C4.92893 2 7.28595 2 12 2C16.714 2 19.0711 2 20.5355 3.46447C22 4.92893 22 7.28595 22 12C22 16.714 22 19.0711 20.5355 20.5355C19.0711 22 16.714 22 12 22C7.28595 22 4.92893 22 3.46447 20.5355C2 19.0711 2 16.714 2 12Z" stroke="currentColor" stroke-width="1.5"></path> </svg>\n ')}\n </div>\n `; }, createMainContent: function(t, e) { return `\n <div class="ytp-plus-settings-main">\n <div class="ytp-plus-settings-content">\n ${E(t, e)}\n ${_(t, e)}\n ${I(t, e)}\n ${A(0, e)}\n <div class="ytp-plus-settings-section hidden" data-section="report"></div>\n ${(function(t) { return `\n <div class="ytp-plus-settings-section hidden" data-section="about">\n <div class="about-section-content">\n <svg class="app-icon" width="90" height="90" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">\n <path d="m23.24,4.62c-0.85,0.45 -2.19,2.12 -4.12,5.13c-1.54,2.41 -2.71,4.49 -3.81,6.8c-0.55,1.14 -1.05,2.2 -1.13,2.35c-0.08,0.16 -0.78,0.7 -1.66,1.28c-1.38,0.91 -1.8,1.29 -1.4,1.28c0.08,0 0.67,-0.35 1.31,-0.77c0.64,-0.42 1.19,-0.76 1.2,-0.74c0.02,0.02 -0.1,0.31 -0.25,0.66c-1.03,2.25 -1.84,5.05 -1.84,6.37c0.01,1.89 0.84,2.67 2.86,2.67c1.08,0 1.94,-0.31 3.66,-1.29c1.84,-1.06 3.03,-1.93 4.18,-3.09c1.69,-1.7 2.91,-3.4 3.28,-4.59c0.59,-1.9 -0.1,-3.08 -2.02,-3.44c-0.87,-0.16 -2.85,-0.14 -3.75,0.06c-1.78,0.38 -2.74,0.76 -2.5,1c0.03,0.03 0.5,-0.1 1.05,-0.28c1.49,-0.48 2.34,-0.59 3.88,-0.53c1.64,0.07 2.09,0.19 2.69,0.75l0.46,0.43l0,0.87c0,0.74 -0.05,0.98 -0.35,1.6c-0.69,1.45 -2.69,3.81 -4.37,5.14c-0.93,0.74 -2.88,1.94 -4.07,2.5c-1.64,0.77 -3.56,0.72 -4.21,-0.11c-0.39,-0.5 -0.5,-1.02 -0.44,-2.11c0.05,-0.85 0.16,-1.32 0.67,-2.86c0.34,-1.01 0.86,-2.38 1.15,-3.04c0.52,-1.18 0.55,-1.22 1.6,-2.14c4.19,-3.65 8.42,-9.4 9.02,-12.26c0.2,-0.94 0.13,-1.46 -0.21,-1.7c-0.31,-0.22 -0.38,-0.21 -0.89,0.06m0.19,0.26c-0.92,0.41 -3.15,3.44 -5.59,7.6c-1.05,1.79 -3.12,5.85 -3.02,5.95c0.07,0.07 1.63,-1.33 2.58,-2.34c1.57,-1.65 3.73,-4.39 4.88,-6.17c1.31,-2.03 2.06,-4.11 1.77,-4.89c-0.13,-0.34 -0.16,-0.35 -0.62,-0.15m11.69,13.32c-0.3,0.6 -1.19,2.54 -1.98,4.32c-1.6,3.62 -1.67,3.71 -2.99,4.34c-1.13,0.54 -2.31,0.85 -3.54,0.92c-0.99,0.06 -1.08,0.04 -1.38,-0.19c-0.28,-0.22 -0.31,-0.31 -0.26,-0.7c0.03,-0.25 0.64,-1.63 1.35,-3.08c1.16,-2.36 2.52,-5.61 2.52,-6.01c0,-0.49 -0.36,0.19 -1.17,2.22c-0.51,1.26 -1.37,3.16 -1.93,4.24c-0.55,1.08 -1.04,2.17 -1.09,2.43c-0.1,0.59 0.07,1.03 0.49,1.28c0.78,0.46 3.3,0.06 5.13,-0.81l0.93,-0.45l-0.66,1.25c-0.7,1.33 -3.36,6.07 -4.31,7.67c-2.02,3.41 -3.96,5.32 -6.33,6.21c-2.57,0.96 -4.92,0.74 -6.14,-0.58c-0.81,-0.88 -0.82,-1.71 -0.04,-3.22c1.22,-2.36 6.52,-6.15 10.48,-7.49c0.52,-0.18 0.95,-0.39 0.95,-0.46c0,-0.21 -0.19,-0.18 -1.24,0.2c-1.19,0.43 -3.12,1.37 -4.34,2.11c-2.61,1.59 -5.44,4.09 -6.13,5.43c-1.15,2.2 -0.73,3.61 1.4,4.6c0.59,0.28 0.75,0.3 2.04,0.3c1.67,0 2.42,-0.18 3.88,-0.89c1.87,-0.92 3.17,-2.13 4.72,-4.41c0.98,-1.44 4.66,-7.88 5.91,-10.33c0.25,-0.49 0.68,-1.19 0.96,-1.56c0.28,-0.37 0.76,-1.15 1.06,-1.73c0.82,-1.59 2.58,-6.10 2.58,-6.6c0,-0.06 -0.07,-0.1 -0.17,-0.1c-0.10,0 -0.39,0.44 -0.71,1.09m-1.34,3.7c-0.93,2.08 -1.09,2.48 -0.87,2.2c0.19,-0.24 1.66,-3.65 1.6,-3.71c-0.02,-0.02 -0.35,0.66 -0.73,1.51" fill="none" fill-rule="evenodd" stroke="currentColor" />\n </svg>\n <h1>YouTube +</h1>\n </div>\n <div class="ytp-plus-about-actions">\n <button class="glass-button" id="open-ytp-github" type="button">${t("openGitHubButton")}</button>\n <button class="glass-button" id="open-ytp-discussions" type="button">${t("openDiscussionsButton")}</button>\n <button class="glass-button" id="open-ytp-greasyfork" type="button">${t("openGreasyForkButton")}</button>\n </div>\n <div class="ytp-plus-about-footer">\n <div>Made with ❤️ by <a href="https://github.com/diorhc" target="_blank" rel="noopener noreferrer" class="ytp-plus-about-author-link">diorhc</a></div>\n <div>License: MIT</div>\n </div>\n </div>\n `; })(e)}\n </div>\n </div>\n `; }, createSettingsItem: S, createSettingsSelect: T, createDownloadSiteOption: L, createBasicSettingsSection: E, createAdvancedSettingsSection: _, createExperimentalSettingsSection: I, createVotingSection: A, readSubmenuExpanded: x, buildShortcutEditorHTML: k, getMusicSettings: z }, window.YouTubePlusSettingsStore = V, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusSettingsHelpers = window.YouTubePlusSettingsHelpers, unsafeWindow.YouTubePlusSettingsStore = window.YouTubePlusSettingsStore)); })(), (function() { function t(t, e) { c(); const o = l(); if (!o) { return; } t.speedControl.activeAnimationId && (cancelAnimationFrame(t.speedControl.activeAnimationId), window.YouTubeUtils?.cleanupManager?.unregisterAnimationFrame?.(t.speedControl.activeAnimationId), t.speedControl.activeAnimationId = null), o.textContent = `${e}x`, o.style.display = "block", o.style.opacity = "0.8"; const r = performance.now(), i = e => { const a = Math.min((e - r) / 1500, 1); o.style.opacity = String(.8 * (1 - a)), a < 1 ? t.speedControl.activeAnimationId = window.YouTubeUtils?.cleanupManager?.registerAnimationFrame?.(requestAnimationFrame(i)) || requestAnimationFrame(i) : (o.style.display = "none", t.speedControl.activeAnimationId = null); }; t.speedControl.activeAnimationId = window.YouTubeUtils?.cleanupManager?.registerAnimationFrame?.(requestAnimationFrame(i)) || requestAnimationFrame(i); } function e(t) { (window.YouTubePlusDOMCache && "function" == typeof window.YouTubePlusDOMCache.getAll ? window.YouTubePlusDOMCache.getAll("video") : document.querySelectorAll("video")).forEach(e => { e && e.playbackRate !== t.speedControl.currentSpeed && (e.playbackRate = t.speedControl.currentSpeed); }); } function o(o, r) { const i = Number(r); o.speedControl.currentSpeed = i, localStorage.setItem(o.speedControl.storageKey, String(i)); const a = o.getElement(".speed-control-btn span", !1); a && (a.textContent = `${i}x`), document.querySelectorAll(".speed-option-item").forEach(t => { t.classList.toggle("speed-option-active", parseFloat(t.dataset?.speed || "0") === i); }), e(o), t(o, i); } function r(t, e) { const r = t.speedControl.availableSpeeds; if (!Array.isArray(r) || !r.length) { return; } const i = Number(t.speedControl.currentSpeed); let a = 0, s = Number.POSITIVE_INFINITY; for (let t = 0; t < r.length; t += 1) { const e = Math.abs(r[t] - i); e < s && (s = e, a = t); } const c = Math.max(0, Math.min(r.length - 1, a + (e > 0 ? 1 : -1))); c !== a && o(t, r[c]); } const i = window.YouTubeUtils?.logger || window.YouTubePlusLogger || null, a = setTimeout, s = "ytp-speedcontrol-styles", c = () => { try { const t = window.YouTubeUtils?.StyleManager; if (!t || "function" != typeof t.add) { return; } const e = window.YouTubePlusDesignSystem?.getStyle?.(s) || ""; t.add(s, e); } catch (t) { i?.warn?.("speedcontrol", "Failed to inject styles", t); } }, l = () => { let t = document.getElementById("speed-indicator"); if (t) { return t; } t = document.createElement("div"), t.id = "speed-indicator"; const e = document.getElementById("movie_player"); return e && e.appendChild(t), t; }; "undefined" != typeof window && (window.YouTubePlusSpeedControl = { addButton: function(t, e) { if (!t.settings.enableSpeedControl) { return; } c(), l(); const r = document.createElement("button"); r.type = "button", r.className = "ytp-button speed-control-btn", r.setAttribute("aria-label", window.YouTubeUtils?.t?.("speedControl") || "Speed control"), r.setAttribute("aria-haspopup", "true"), r.setAttribute("aria-expanded", "false"), window.YouTubeUtils?.setSafeHTML?.(r, `<span>${t.speedControl.currentSpeed}x</span>`); const i = document.createElement("div"); i.className = "speed-options", i.setAttribute("role", "menu"); const s = e => { o(t, e), p(); }; t.speedControl.availableSpeeds.forEach(e => { const o = document.createElement("div"); o.className = "speed-option-item" + (Number(e) === t.speedControl.currentSpeed ? " speed-option-active" : ""), o.textContent = `${e}x`, o.dataset.speed = String(e), o.setAttribute("role", "menuitem"), o.tabIndex = 0, o.addEventListener("click", () => s(e)), o.addEventListener("keydown", t => { "Enter" !== t.key && " " !== t.key || (t.preventDefault(), s(e)); }), i.appendChild(o); }); const d = document.querySelector(".speed-options"); d && d.remove(); try { document.body.appendChild(i); } catch (t) { r.appendChild(i); } const u = () => { const t = r.getBoundingClientRect(); i.style.left = `${t.left + t.width / 2}px`, i.style.bottom = window.innerHeight - t.top + 8 + "px"; }, p = () => { i.classList.remove("visible"), r.setAttribute("aria-expanded", "false"); }, y = () => { u(), i.classList.add("visible"), r.setAttribute("aria-expanded", "true"); }; let m, f; m = window.YouTubeUtils?.cleanupManager?.registerListener?.(document, "click", t => { r.isConnected ? i.classList.contains("visible") && (r.contains(t.target) || i.contains(t.target) || p()) : m && (window.YouTubeUtils?.cleanupManager?.unregisterListener?.(m), m = void 0); }, !0), window.YouTubeUtils?.cleanupManager?.registerListener?.(document, "keydown", t => { "Escape" === t.key && i.classList.contains("visible") && (p(), r.focus()); }, !0), window.YouTubeUtils?.cleanupManager?.registerListener?.(window, "resize", () => { i.classList.contains("visible") && u(); }), window.YouTubeUtils?.cleanupManager?.registerListener?.(window, "scroll", () => { i.classList.contains("visible") && u(); }, !0), r.addEventListener("mouseenter", () => { clearTimeout(f), y(); }), r.addEventListener("mouseleave", () => { clearTimeout(f), f = a(p, 200); }), i.addEventListener("mouseenter", () => { clearTimeout(f), y(); }), i.addEventListener("mouseleave", () => { clearTimeout(f), f = a(p, 200); }), r.addEventListener("keydown", t => { "Enter" === t.key || " " === t.key ? (t.preventDefault(), i.classList.contains("visible") ? p() : y()) : "Escape" === t.key && p(); }), e.insertBefore(r, e.firstChild); }, changeSpeed: o, applyCurrentSpeed: e, setupVideoObserver: function(t) { t.C && clearInterval(t.C), t.C = null, t.I || (t.I = !0, t.A = !1, window.YouTubeUtils?.cleanupManager?.registerListener?.(document, "mousedown", e => { 0 === e.button && (t.A = !0); }, { passive: !0, capture: !0 }), window.YouTubeUtils?.cleanupManager?.registerListener?.(document, "mouseup", e => { 0 === e.button && (t.A = !1); }, { passive: !0, capture: !0 })); const o = () => e(t), r = () => t.updateLoopProgressBar?.(), i = () => t.applyLoopStateToCurrentVideo?.(), a = e => { if (e.P) { return; } e.P = !0, e.addEventListener("loadedmetadata", o), e.addEventListener("loadedmetadata", r), e.addEventListener("loadedmetadata", i), e.addEventListener("playing", o); let a = !1; e.addEventListener("ratechange", () => { a || t.A && e.playbackRate > t.speedControl.currentSpeed || e.playbackRate !== t.speedControl.currentSpeed && (a = !0, e.playbackRate = t.speedControl.currentSpeed, a = !1); }), o(); }, s = document.querySelector("#movie_player") || document.querySelector("ytd-player"); s ? s.querySelectorAll("video").forEach(a) : document.querySelectorAll("video").forEach(a); const c = window.YouTubePlusMutationCoordinator, l = "speedcontrol::videoElements", d = document.querySelector("#movie_player") || document.querySelector("ytd-player") || document.body; d && c?.watchTarget && (c.watchTarget(l, d, t => { for (const e of t) { for (const t of e.addedNodes) { "VIDEO" === t.nodeName && a(t), t instanceof Element && t.querySelectorAll?.("video").forEach(a); } } }, { childList: !0, attributes: !1, subtree: !0 }), window.YouTubeUtils?.cleanupManager?.register?.(() => { c.unwatch(l); })); }, showSpeedIndicator: t, adjustSpeedByStep: r, refreshVisibility: function(t) { const e = document.querySelector(".speed-control-btn"); e && e.style && e.style.setProperty("display", t ? "" : "none", "important"); const o = document.querySelector(".speed-options"); o && o.style && (o.style.setProperty("display", t ? "" : "none", "important"), t || o.classList.remove("visible")); }, registerHotkeys: function(t) { try { window.YouTubeUtils?.cleanupManager?.registerListener?.(document, "keydown", e => { if (!t.settings.enableSpeedControl || !e?.key) { return; } if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; } if (t.isEditableTarget(document.activeElement)) { return; } const i = String(e.key).toLowerCase(), a = t.normalizeSpeedHotkey(t.settings.speedControlHotkeys?.decrease, "g"), s = t.normalizeSpeedHotkey(t.settings.speedControlHotkeys?.increase, "h"), c = t.normalizeSpeedHotkey(t.settings.speedControlHotkeys?.reset, "b"); i === a ? (e.preventDefault(), r(t, -1)) : i === s ? (e.preventDefault(), r(t, 1)) : i === c && (e.preventDefault(), o(t, 1)); }, !0); } catch (t) { window.YouTubeUtils?.logError?.("SpeedControl", "Failed to register speed hotkeys", t); } }, injectStyles: c }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusSpeedControl = window.YouTubePlusSpeedControl)), i?.debug?.("speedcontrol", "Speed control module loaded"); })(), (function() { function t(t) { const e = t.getElement("video", !1); if (!e) { return !1; } const r = document.createElement("canvas"); r.width = e.videoWidth, r.height = e.videoHeight; const i = r.getContext("2d"); if (!i) { return !1; } i.drawImage(e, 0, 0, r.width, r.height); const a = document.title.replace(/\s-\sYouTube$/, "").trim(), s = document.createElement("a"); s.href = r.toDataURL("image/png"), s.download = `${a}.png`; try { s.click(); const e = "function" == typeof o?.t ? o.t("screenshotSaved") : null; return t.showNotification(e && "screenshotSaved" !== e ? e : "Screenshot saved", 2e3), !0; } catch (e) { o?.logError?.("Screenshot", "Screenshot download failed", e); const r = "function" == typeof o?.t ? o.t("screenshotFailed") : null; return t.showNotification(r && "screenshotFailed" !== r ? r : "Screenshot failed", 3e3), !1; } } const e = window.YouTubeUtils?.logger || window.YouTubePlusLogger || null, o = window.YouTubeUtils, r = "ytp-screenshot-styles", i = () => { try { const t = o?.StyleManager; if (!t || "function" != typeof t.add) { return; } const e = window.YouTubePlusDesignSystem?.getStyle?.(r) || ""; t.add(r, e); } catch (t) { e?.warn?.("screenshot", "Failed to inject styles", t); } }; "undefined" != typeof window && (window.YouTubePlusScreenshot = { addButton: function(e, r) { i(); const a = document.createElement("button"); a.className = "ytp-button ytp-screenshot-button", a.setAttribute("title", o?.t?.("takeScreenshot") || "Take screenshot"), a.setAttribute("aria-label", o?.t?.("takeScreenshot") || "Take screenshot"), o?.setSafeHTML?.(a, '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity="0.5" d="M7.142 18.9706C5.18539 18.8995 3.99998 18.6568 3.17157 17.8284C2 16.6569 2 14.7712 2 11C2 7.22876 2 5.34315 3.17157 4.17157C4.34315 3 6.22876 3 10 3H14C17.7712 3 19.6569 3 20.8284 4.17157C22 5.34315 22 7.22876 22 11C22 14.7712 22 16.6569 20.8284 17.8284C20.0203 18.6366 18.8723 18.8873 17 18.965" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path d="M9.94955 16.0503C10.8806 15.1192 11.3461 14.6537 11.9209 14.6234C11.9735 14.6206 12.0261 14.6206 12.0787 14.6234C12.6535 14.6537 13.119 15.1192 14.0501 16.0503C16.0759 18.0761 17.0888 19.089 16.8053 19.963C16.7809 20.0381 16.7506 20.1112 16.7147 20.1815C16.2973 21 14.8648 21 11.9998 21C9.13482 21 7.70233 21 7.28489 20.1815C7.249 20.1112 7.21873 20.0381 7.19436 19.963C6.91078 19.089 7.92371 18.0761 9.94955 16.0503Z" stroke="currentColor" stroke-width="1.5"></path></svg>\n '), a.addEventListener("click", () => t(e)), r.insertBefore(a, r.firstChild); }, capture: t, refreshVisibility: function(t) { const e = document.querySelector(".ytp-screenshot-button"); e && e.style && (e.style.display = t ? "" : "none"); }, registerHotkey: function(e) { try { o?.cleanupManager?.registerListener?.(document, "keydown", o => { o?.key && ("s" !== o.key && "S" !== o.key || o.altKey || o.ctrlKey || o.metaKey || o.shiftKey || e.settings.enableScreenshot && (e.isEditableTarget(document.activeElement) || t(e))); }, !0); } catch (t) { o?.logError?.("Screenshot", "Failed to register screenshot hotkey", t); } }, injectStyles: i }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusScreenshot = window.YouTubePlusScreenshot)), e?.debug?.("screenshot", "Screenshot module loaded"); })(), (function() { if ("undefined" != typeof window && window.YouTubePerformance) { return; } const t = (() => { try { return "undefined" != typeof process && !!process?.env?.JEST_WORKER_ID; } catch { return !1; } })(), e = window.YouTubeUtils?.logger || window.YouTubePlusLogger || null, o = { enabled: !0, sampleRate: t ? 1 : .01, metricsRetention: 100 }; if (!t) { try { const t = window.YouTubePlusConfig, e = t?.performance?.sampleRate ?? t?.performanceSampleRate ?? t?.perfSampleRate ?? void 0; "number" == typeof e && Number.isFinite(e) && (o.sampleRate = Math.min(1, Math.max(0, e))); } catch {} o.sampleRate < 1 && Math.random() > o.sampleRate && (o.enabled = !1); } const r = { timings: new Map, marks: new Map, measures: [], webVitals: { LCP: null, CLS: 0, FID: null, INP: null, FCP: null, TTFB: null } }, i = t => { if (o.enabled) { try { "undefined" != typeof performance && performance.mark && performance.mark(t), r.marks.set(t, Date.now()); } catch (t) { e?.warn?.("Performance", "Failed to create mark", t); } } }, a = (t, i, a) => { if (!o.enabled) { return 0; } try { const e = r.marks.get(i); if (!e) { return 0; } const s = (a ? r.marks.get(a) ?? Date.now() : Date.now()) - e; if (r.measures.push({ name: t, startMark: i, endMark: a || "now", duration: s, timestamp: Date.now() }), r.measures.length > o.metricsRetention && r.measures.shift(), "undefined" != typeof performance && performance.measure) { try { performance.measure(t, i, a); } catch {} } return s; } catch (t) { return e?.warn?.("Performance", "Failed to measure", t), 0; } }, s = (t, e, i = {}) => { o.enabled && r.timings.set(t, { name: t, value: e, timestamp: Date.now(), ...i }); }, c = t => { if (t) { const e = r.measures.filter(e => e.name === t); if (0 === e.length) { return null; } const o = e.map(t => t.duration); return { name: t, count: o.length, min: Math.min(...o), max: Math.max(...o), avg: o.reduce((t, e) => t + e, 0) / o.length, latest: o[o.length - 1] }; } const e = {}; return [ ...new Set(r.measures.map(t => t.name)) ].forEach(t => { e[t] = c(t); }), { metrics: e, webVitals: { ...r.webVitals }, totalMeasures: r.measures.length, totalMarks: r.marks.size, customMetrics: Object.fromEntries(r.timings) }; }, l = t => { if ("undefined" == typeof performance || !performance.getEntriesByType) { return []; } try { return performance.getEntriesByType(t); } catch { return []; } }, d = () => { if (o.enabled) { try { const t = l("navigation")[0]; t && (s("page-load-time", t.loadEventEnd - t.fetchStart), s("dom-content-loaded", t.domContentLoadedEventEnd), s("dom-interactive", t.domInteractive)); } catch (t) { e?.warn?.("Performance", "Failed to log page metrics", t); } } }, u = { mark: i, measure: a, timeFunction: (t, e) => o.enabled ? function(...o) { const r = `${t}-start`; i(r); try { const i = e.apply(this, o); return i && "function" == typeof i.then && "function" == typeof i.finally ? i.finally(() => { a(t, r, void 0); }) : (a(t, r, void 0), i); } catch (e) { throw a(t, r, void 0), e; } } : e, timeAsyncFunction: (t, e) => o.enabled ? async function(...o) { const r = `${t}-start`; i(r); try { const i = await e.apply(this, o); return a(t, r, void 0), i; } catch (e) { throw a(t, r, void 0), e; } } : e, recordMetric: s, getStats: c, getPerformanceEntries: l, clearMetrics: () => { if (r.timings.clear(), r.marks.clear(), r.measures = [], r.webVitals = { LCP: null, CLS: 0, FID: null, INP: null, FCP: null, TTFB: null }, "undefined" != typeof performance) { try { performance.clearMarks?.(), performance.clearMeasures?.(); } catch {} } }, config: o }; "undefined" != typeof window && ("complete" === document.readyState ? d() : window.addEventListener("load", d, { once: !0 }), o.enabled && ((() => { if ("undefined" != typeof PerformanceObserver) { try { new PerformanceObserver(t => { const e = t.getEntries(), o = e[e.length - 1]; o && (r.webVitals.LCP = o.startTime); }).observe({ type: "largest-contentful-paint", buffered: !0 }), new PerformanceObserver(t => { for (const e of t.getEntries()) { e.hadRecentInput || (r.webVitals.CLS += e.value || 0); } }).observe({ type: "layout-shift", buffered: !0 }), new PerformanceObserver(t => { const e = t.getEntries()[0]; r.webVitals.FID = (e?.processingStart || 0) - (e?.startTime || 0); }).observe({ type: "first-input", buffered: !0 }); try { new PerformanceObserver(t => { const e = t.getEntries(); if (e.length > 0) { const t = Math.max(...e.map(t => t.duration)); r.webVitals.INP = t; } }).observe({ type: "event", buffered: !0, durationThreshold: 16 }); } catch {} } catch (t) { e?.warn?.("Performance", "Failed to init PerformanceObserver", t); } } })(), (() => { if ("undefined" != typeof PerformanceObserver && (!Array.isArray(PerformanceObserver.supportedEntryTypes) || PerformanceObserver.supportedEntryTypes.includes("longtask"))) { try { const t = []; new PerformanceObserver(e => { for (const o of e.getEntries()) { t.push({ duration: o.duration, startTime: o.startTime, name: o.name }), t.length > 50 && t.shift(); } s("long-tasks-count", t.length); const o = t.reduce((t, e) => t + Math.max(0, e.duration - 50), 0); s("total-blocking-time", o); }).observe({ type: "longtask", buffered: !0 }); } catch {} } })()), window.addEventListener("yt-navigate-start", () => i("yt-navigate-start"), { passive: !0 }), window.addEventListener("yt-navigate-finish", () => { i("yt-navigate-finish"), a("yt-navigation-duration", "yt-navigate-start", void 0); }, { passive: !0 }), Object.defineProperty(window, "YouTubePerformance", { value: u, configurable: !0, enumerable: !1, writable: !0 }), window.YouTubeUtils?.logger?.debug?.("[YouTube+] Performance diagnostics initialised")); })(); const basicSetTimeout_ = setTimeout, basicUiState_ = { submenuStates: { read() { try { const t = localStorage.getItem("ytp-plus-submenu-states"), e = t ? JSON.parse(t) : {}; return e && "object" == typeof e ? e : {}; } catch (t) { return YouTubePlusLogger?.warn?.("Basic", "Submenu state read failed", t), {}; } }, write(t) { try { localStorage.setItem("ytp-plus-submenu-states", JSON.stringify(t || {})); } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Submenu state write failed", t); } } }, activeNavSection: { read() { try { return localStorage.getItem("ytp-plus-active-nav-section") || ""; } catch (t) { return ""; } }, write(t) { try { localStorage.setItem("ytp-plus-active-nav-section", t); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } } }, lastOpenSection: { read() { try { return localStorage.getItem("youtube_plus_last_active_section") || ""; } catch (t) { return ""; } }, write(t) { try { localStorage.setItem("youtube_plus_last_active_section", t); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } } } }, basicSubmenuSelector_ = t => { switch (t) { case "music": return `.music-submenu[data-submenu="${t}"]`; case "download": return `.download-submenu[data-submenu="${t}"]`; case "style": return `.style-submenu[data-submenu="${t}"]`; case "speed": return `.speed-submenu[data-submenu="${t}"]`; case "loop": return `.loop-submenu[data-submenu="${t}"]`; case "pip": return `.pip-submenu[data-submenu="${t}"]`; case "timecode": return `.timecode-submenu[data-submenu="${t}"]`; case "enhanced": return `.enhanced-submenu[data-submenu="${t}"]`; default: return `[data-submenu="${t}"]`; } }, basicNormalizeHotkeyMap_ = (t, e) => { const o = { ...t && "object" == typeof t ? t : {} }; for (const t of Object.keys(e)) { o[t] = basicNormalizeSingleHotkey_(o[t], e[t]); } return o; }, basicNormalizeSingleHotkey_ = (t, e) => { const o = "string" == typeof t ? t.trim().toLowerCase() : ""; return o ? o.slice(0, 1) : String(e || "").trim().toLowerCase().slice(0, 1) || "g"; }, basicHasSettingsButton_ = () => { const t = window.YouTubePlusDOMCache; return t && "function" == typeof t.querySelector ? !!t.querySelector(".ytp-plus-settings-button", document, !0) : "undefined" != typeof document && !!document.querySelector(".ytp-plus-settings-button"); }, basicFallbackUtils_ = (() => { const t = window.YouTubeUtils || {}, e = window.YouTubePlusStorage || {}, o = t.t || ((t, e = {}) => { const o = window.YouTubePlusI18n, r = o?.translate || o?.t; if ("function" == typeof r) { try { return r(t, e); } catch (t) {} } if (!t) { return ""; } let i = String(t); for (const [t, o] of Object.entries(e || {})) { i = i.split(`{${t}}`).join(String(o)); } return i; }), r = t.logError || ((t, e, o) => { (window.YouTubePlusLogger?.error || console.error)(`[${t}]`, e, o); }), i = t.storage || e || { get: (t, e = null) => { try { const o = localStorage.getItem(t); return o ? JSON.parse(o) : e; } catch (t) { return e; } }, set: (t, e) => { try { return localStorage.setItem(t, JSON.stringify(e)), !0; } catch (t) { return !1; } }, remove: t => { try { return localStorage.removeItem(t), !0; } catch (t) { return !1; } } }, a = t.cleanupManager, s = t.createElement || ((t, e = {}, o = []) => { const r = document.createElement(t); for (const [t, o] of Object.entries(e || {})) { "className" === t ? r.className = String(o) : "style" === t && o && "object" == typeof o ? Object.assign(r.style, o) : "dataset" === t && o && "object" == typeof o ? Object.assign(r.dataset, o) : t.startsWith("on") && "function" == typeof o ? r.addEventListener(t.slice(2).toLowerCase(), o) : null != o && r.setAttribute(t, String(o)); } for (const t of o) { "string" == typeof t ? r.appendChild(document.createTextNode(t)) : t instanceof Node && r.appendChild(t); } return r; }), c = { load() { const t = window.YouTubePlusSettingsStore; if (t && "function" == typeof t.load) { try { const e = t.load(); return e && "object" == typeof e ? e : null; } catch (t) { YouTubePlusLogger?.warn?.("Basic", "SettingsManager.load via store failed", t); } } return null; }, save(t) { const e = window.YouTubePlusSettingsStore; if (e && "function" == typeof e.save) { try { return e.save(t && "object" == typeof t ? t : {}), !0; } catch (t) { return YouTubePlusLogger?.warn?.("Basic", "SettingsManager.save via store failed", t), !1; } } return !1; }, get(t) { const e = window.YouTubePlusSettingsStore; if (e && "function" == typeof e.get) { return e.get(t); } }, set(t, e) { const o = window.YouTubePlusSettingsStore; return !(!o || "function" != typeof o.set) && !0 === o.set(t, e); } }, l = window.YouTubePlusDesignSystem?.StyleManager || null, d = { queue: [], activeNotifications: new Set, maxVisible: 3, defaultDuration: 3e3, show(t, e = {}) { if (!t || "string" != typeof t) { return r("NotificationManager", "Invalid message", new Error("Message must be a non-empty string")), null; } const {duration: o = this.defaultDuration, position: i = null, action: c = null} = e; this.activeNotifications.forEach(e => { e.dataset.message === t && this.remove(e); }); const l = { "top-right": { top: "20px", right: "20px" }, "top-left": { top: "20px", left: "20px" }, "bottom-right": { bottom: "20px", right: "20px" }, "bottom-left": { bottom: "20px", left: "20px" } }; try { const e = s("div", { className: "youtube-enhancer-notification", dataset: { message: t }, style: { zIndex: "10001", width: "auto", display: "flex", alignItems: "center", gap: "10px", ...i && l[i] ? l[i] : {} } }); e.setAttribute("role", "status"), e.setAttribute("aria-live", "polite"), e.setAttribute("aria-atomic", "true"); const r = s("span", { style: { flex: "1" } }, [ t ]); if (e.appendChild(r), c?.text && "function" == typeof c.callback) { const t = s("button", { style: { background: "var(--yt-button-bg)", border: "1px solid var(--yt-glass-border)", color: "white", padding: "4px 12px", borderRadius: "4px", cursor: "pointer", fontSize: "12px", fontWeight: "600", transition: "background 0.2s" }, onClick: () => { c.callback(), this.remove(e); } }, [ c.text ]); e.appendChild(t); } const d = "youtube-enhancer-notification-container"; let u = window.YouTubePlusDOMCache?.getElementById?.(d) || ("undefined" != typeof document ? document.getElementById(d) : null); if (!u) { u = s("div", { id: d, className: "youtube-enhancer-notification-container" }); try { const t = document.body || document.documentElement; if (!t) { return null; } t.appendChild(u); } catch (t) { const o = document.body || document.documentElement; o && (o.appendChild(e), this.activeNotifications.add(e)); } } try { u.insertBefore(e, u.firstChild); } catch (t) { const o = document.body || document.documentElement; o && o.appendChild(e); } try { e.style.pointerEvents = "auto"; } catch (t) {} this.activeNotifications.add(e); try { e.style.animation = "slideInFromBottom 0.38s ease-out forwards"; } catch (t) {} if (o > 0) { const t = basicSetTimeout_(() => this.remove(e), o); a.registerTimeout(t); } if (this.activeNotifications.size > this.maxVisible) { const t = Array.from(this.activeNotifications)[0]; this.remove(t); } return e; } catch (t) { return r("NotificationManager", "Failed to show notification", t), null; } }, remove(t) { if (t?.isConnected) { try { try { t.style.animation = "slideOutToBottom 0.32s ease-in forwards"; const e = basicSetTimeout_(() => { try { t.remove(), this.activeNotifications.delete(t); } catch (t) { r("NotificationManager", "Failed to remove notification", t); } }, 340); a.registerTimeout(e); } catch (e) { try { t.remove(), this.activeNotifications.delete(t); } catch (t) { r("NotificationManager", "Failed to remove notification (fallback)", t); } } } catch (e) { r("NotificationManager", "Failed to animate notification removal", e), t.remove(), this.activeNotifications.delete(t); } } }, clearAll() { this.activeNotifications.forEach(t => { try { t.remove(); } catch (t) { r("NotificationManager", "Failed to clear notification", t); } }), this.activeNotifications.clear(); } }; return window.addEventListener("beforeunload", () => { a.cleanup(), window.YouTubePlusDOMCache?.invalidate?.(), l?.clear(), d.clearAll(); }), a.registerListener(window, "unhandledrejection", t => { r("Global", "Unhandled promise rejection", t.reason), t.preventDefault(); }), a.registerListener(window, "error", t => { const e = String(t?.message || ""), o = String(t?.error?.message || ""); e.includes("ResizeObserver loop") || o.includes("ResizeObserver loop") || t.filename?.includes("youtube") && r("Global", "Uncaught error", new Error(`${t.message} at ${t.filename}:${t.lineno}:${t.colno}`)); }), { logError: r, storage: i, cleanupManager: a, SettingsManager: c, NotificationManager: d, clearCache: () => { window.YouTubePlusDOMCache?.invalidate?.(); }, t: o, createElement: s, get StyleManager() { return t.StyleManager || window.YouTubePlusDesignSystem?.StyleManager || null; } }; })(); if ("undefined" != typeof window) { window.YouTubeUtils = window.YouTubeUtils || {}; const t = window.YouTubeUtils; try { for (const e of Object.keys(basicFallbackUtils_)) { void 0 === t[e] && (t[e] = basicFallbackUtils_[e]); } } catch (t) { YouTubePlusLogger?.error?.("Basic", "Failed to merge core utilities", t); } const YouTubeUtils = window.YouTubeUtils; window.YouTubeUtils && YouTubeUtils.logger?.debug?.("[YouTube+ v2.4.5] Core utilities merged"), window.YouTubePlusDebug = { version: "2.5.2", cacheSize: () => YouTubeUtils.cleanupManager.observers.size + YouTubeUtils.cleanupManager.listeners.size + YouTubeUtils.cleanupManager.intervals.size, clearAll: () => { YouTubeUtils.cleanupManager.cleanup(), YouTubeUtils.clearCache(), YouTubeUtils.StyleManager.clear(), YouTubeUtils.NotificationManager.clearAll(), window.YouTubeUtils && YouTubeUtils.logger?.debug?.("[YouTube+] All resources cleared"); }, stats: () => ({ observers: YouTubeUtils.cleanupManager.observers.size, listeners: YouTubeUtils.cleanupManager.listeners.size, intervals: YouTubeUtils.cleanupManager.intervals.size, timeouts: YouTubeUtils.cleanupManager.timeouts.size, animationFrames: YouTubeUtils.cleanupManager.animationFrames.size, styles: YouTubeUtils.StyleManager.styles.size, notifications: YouTubeUtils.NotificationManager.activeNotifications.size }) }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDebug = window.YouTubePlusDebug); let e = !0; try { "undefined" != typeof sessionStorage && (e = !sessionStorage.getItem("youtube_plus_started"), e && sessionStorage.setItem("youtube_plus_started", "true")); } catch (t) { e = !0; } e && basicSetTimeout_(() => { YouTubeUtils.NotificationManager && YouTubeUtils.NotificationManager.show("YouTube+ v2.5.2 loaded", { type: "success", duration: 2e3, position: "bottom-right" }); }, 1e3); } !(function() { const YouTubeUtils = window.YouTubeUtils, t = YouTubeUtils.setSafeHTML, {t: e} = YouTubeUtils, YouTubeEnhancer = { speedControl: { currentSpeed: 1, activeAnimationId: null, storageKey: "youtube_playback_speed", availableSpeeds: [ .25, .5, .75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3 ] }, U: !1, j: null, H: null, D: null, O: null, B: null, R: null, F: !1, settings: { enableSpeedControl: !0, speedControlHotkeys: { decrease: "g", increase: "h", reset: "b" }, enableScreenshot: !0, enableDownload: !0, enableZenStyles: !0, zenStyles: { thumbnailHover: !0, immersiveSearch: !0, hideVoiceSearch: !0, transparentHeader: !0, hideSideGuide: !0, cleanSideGuide: !1, fixFeedLayout: !0, sideVideosColumnsEnabled: !1, sideVideosColumns: 0, betterCaptions: !0, playerBlur: !0, theaterEnhancements: !0 }, enableEnhanced: !0, enableTabview: !0, enableCommentTranslate: !0, enablePlayAll: !0, enableResumeTime: !0, enableZoom: !0, enableThumbnail: !0, enablePlaylistSearch: !0, enableScrollToTopButton: !0, enableRememberManualQuality: !0, enableLoop: !0, loopHotkeys: { toggleLoop: "r", setPointA: "k", setPointB: "l", resetPoints: "o" }, downloadSites: { direct: !0, externalDownloader: !0, ytdl: !0 }, downloadSiteCustomization: { externalDownloader: "undefined" != typeof window && window.YouTubePlusConstants ? window.YouTubePlusConstants.DOWNLOAD_SITES.EXTERNAL_DOWNLOADER : { name: "SSYouTube", url: "https://ssyoutube.com/watch?v={videoId}" } }, storageKey: window.YouTubeUtils?.SETTINGS_KEY || "youtube_plus_settings", hideSideGuide: !1 }, getElement(t, e = !0) { const o = window.YouTubePlusDOMCache; if (!o || "function" != typeof o.querySelector) { return "undefined" != typeof document ? document.querySelector(t) : null; } if (e) { const e = o.get(t); if (e && e.isConnected) { return e; } if (e) { try { o.invalidate?.(t); } catch {} } } return o.querySelector(t, document, !e); }, loadSettings() { try { const t = window.YouTubePlusSettingsStore, e = t && "function" == typeof t.load ? t.load() : null; if (!e || "object" != typeof e) { return; } const o = e; if (!o) { return; } window.YouTubeUtils?.safeMerge ? window.YouTubeUtils.safeMerge(this.settings, o) : "object" == typeof o && Object.assign(this.settings, o); } catch (t) { YouTubePlusLogger?.error?.("Basic", "Error loading settings", t); } }, init() { this.U || (this.U = !0, this.loadAndNormalizeSettings_(), this.mountBootUI_(), this.setupCurrentPageIfWatch_(), this.registerVisibilityListener_(), this.registerFeatureHotkeys_(), this.registerLoopHotkeyHandler_()); }, loadAndNormalizeSettings_() { try { this.loadSettings(), this.migrateLegacyLoopHotkeys_(), this.normalizeAllHotkeys_(), this.restorePlaybackSpeed_(); } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Failed to load settings during init", t); } }, migrateLegacyLoopHotkeys_() { try { const t = this.settings.loopHotkeys || {}; let e = !1; if ("l" === t.setPointA && (t.setPointA = "k", e = !0), "o" === t.setPointB && (t.setPointB = "l", e = !0), "k" === t.resetPoints && (t.resetPoints = "o", e = !0), e) { this.settings.loopHotkeys = t; try { this.saveSettings(); } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Failed to save migrated loop hotkeys", t); } } } catch (t) {} }, normalizeAllHotkeys_() { this.settings.speedControlHotkeys = basicNormalizeHotkeyMap_(this.settings.speedControlHotkeys, { decrease: "g", increase: "h", reset: "b" }), this.settings.loopHotkeys = basicNormalizeHotkeyMap_(this.settings.loopHotkeys, { toggleLoop: "r", setPointA: "k", setPointB: "l", resetPoints: "o" }); }, restorePlaybackSpeed_() { try { const t = localStorage.getItem(this.speedControl.storageKey); if (null !== t) { const e = Number(t); Number.isFinite(e) && e > 0 && e <= 16 && (this.speedControl.currentSpeed = e); } } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Speed restore error", t); } }, mountBootUI_() { this.insertStyles(), this.addSettingsButtonToHeader(), this.setupNavigationObserver(), basicSetTimeout_(() => { try { this.insertStyles(); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } }, 1200); }, setupCurrentPageIfWatch_() { location.href.includes("watch?v=") && this.setupCurrentPage(); }, registerVisibilityListener_() { this.j || (this.j = () => { !document.hidden && location.href.includes("watch?v=") && this.setupCurrentPage(); }, YouTubeUtils.cleanupManager.registerListener(document, "visibilitychange", this.j)); }, registerFeatureHotkeys_() { try { window.YouTubePlusScreenshot?.registerHotkey?.(this); } catch (t) { YouTubeUtils?.logError?.("Basic", "Failed to initialize screenshot hotkey module", t); } try { window.YouTubePlusSpeedControl?.registerHotkeys?.(this); } catch (t) { YouTubeUtils?.logError?.("Basic", "Failed to initialize speed hotkey module", t); } }, registerLoopHotkeyHandler_() { try { if (this.H) { return; } this.H = t => { if (!this.settings.enableLoop || !t?.key) { return; } if (t.altKey || t.ctrlKey || t.metaKey || t.shiftKey) { return; } if (this.isEditableTarget(document.activeElement)) { return; } const e = String(t.key).toLowerCase(), o = this.normalizeSpeedHotkey(this.settings.loopHotkeys?.toggleLoop, "r"), r = this.normalizeSpeedHotkey(this.settings.loopHotkeys?.setPointA, "k"), i = this.normalizeSpeedHotkey(this.settings.loopHotkeys?.setPointB, "l"), a = this.normalizeSpeedHotkey(this.settings.loopHotkeys?.resetPoints, "o"); e === o ? (t.preventDefault(), window.YouTubePlusTimeLoop?.toggleLoop()) : e === r ? (t.preventDefault(), window.YouTubePlusTimeLoop?.setLoopPoint?.("A")) : e === i ? (t.preventDefault(), window.YouTubePlusTimeLoop?.setLoopPoint?.("B")) : e === a && (t.preventDefault(), window.YouTubePlusTimeLoop?.resetLoopPoints?.()); }, YouTubeUtils.cleanupManager.registerListener(document, "keydown", this.H, !0); } catch (t) { YouTubeUtils?.logError && YouTubeUtils.logError("Basic", "Failed to register loop keyboard shortcuts", t); } }, isEditableTarget(t) { const e = t; if (!e) { return !1; } const o = (e.tagName || "").toLowerCase(); return "input" === o || "textarea" === o || "select" === o || Boolean(e.isContentEditable); }, normalizeSpeedHotkey(t, e) { const o = "string" == typeof t ? t.trim().toLowerCase() : ""; return o ? o.slice(0, 1) : String(e || "").trim().toLowerCase().slice(0, 1) || "g"; }, adjustSpeedByStep(t) { const e = window.YouTubePlusSpeedControl; e && "function" == typeof e.adjustSpeedByStep && e.adjustSpeedByStep(this, t); }, saveSettings() { const t = window.YouTubePlusSettingsStore; t && "function" == typeof t.save ? t.save(this.settings) : void 0 !== window.YouTubePlusLogger && window.YouTubePlusLogger?.warn?.("Basic", "settings store unavailable; settings not persisted"), this.updatePageBasedOnSettings(), this.refreshDownloadButton(); try { window.youtubePlus = window.youtubePlus || {}, window.youtubePlus.settings = this.settings; } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Settings exposure error", t); } }, updatePageBasedOnSettings() { window.YouTubePlusScreenshot?.refreshVisibility?.(!!this.settings.enableScreenshot), window.YouTubePlusSpeedControl?.refreshVisibility?.(!!this.settings.enableSpeedControl), window.YouTubePlusDownloadButton?.refreshVisibility?.(!!this.settings.enableDownload); }, refreshDownloadButton() { "undefined" != typeof window && window.YouTubePlusDownloadButton && window.YouTubePlusDownloadButton.createDownloadButtonManager({ settings: this.settings, t: e, getElement: this.getElement.bind(this), YouTubeUtils }).refreshDownloadButton(); }, setupCurrentPage() { this.waitForElement("#player-container-outer .html5-video-player, .ytp-right-controls", 5e3).then(() => { this.addCustomButtons(), this.setupVideoObserver(), this.applyCurrentSpeed(), window.YouTubePlusTimeLoop?.applyLoopStateToCurrentVideo?.(), this.updatePageBasedOnSettings(), this.refreshDownloadButton(); }).catch(() => {}); }, insertStyles() { const t = ".youtube-enhancer-notification-container{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;gap:10px;z-index:2147483647;pointer-events:none;max-width:calc(100% - 32px);width:100%;box-sizing:border-box;padding:0 16px;}\n .youtube-enhancer-notification{position:relative;max-width:700px;width:auto;background:var(--yt-glass-bg);color:var(--yt-text-primary);padding:8px 14px;font-size:13px;border-radius:var(--yt-radius-md);z-index:inherit;transition:opacity .35s,transform .32s;box-shadow:var(--yt-glass-shadow);border:1px solid var(--yt-glass-border);font-weight:500;box-sizing:border-box;display:flex;align-items:center;gap:10px;pointer-events:auto;}\n .ytp-plus-loop-indicator{position:absolute;height:100%;background:linear-gradient(90deg,var(--yt-accent-secondary-ghost) 0%,var(--yt-accent-secondary-light-ghost) 50%,var(--yt-accent-secondary-ghost) 100%);border-left:2px solid var(--yt-accent-secondary);border-right:2px solid var(--yt-accent-secondary);display:none;pointer-events:none;top:0;z-index:1000;box-shadow:inset 0 0 4px var(--yt-accent-secondary-shadow);}\n .ytp-plus-settings-button{box-sizing:border-box;width:40px;height:40px;min-width:40px;flex:0 0 auto;background:transparent;border:none;color:var(--yt-text-primary,#fff);cursor:pointer;padding:8px;margin:0 4px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;align-self:center;transition:background-color .2s,transform .2s;}\n .ytp-plus-settings-button svg{width:24px;height:24px;display:block;}\n .ytp-plus-settings-button:hover{transform:rotate(30deg);background:var(--yt-glass-bg,rgba(255,255,255,.12));}\n ytmusic-nav-bar .ytp-plus-settings-button{color:var(--ytmusic-color-icon-active,#fff);}\n ytcp-header .ytp-plus-settings-button{color:var(--ytcp-icon-color,#606060);}\n .ytp-plus-settings-button--floating{position:fixed;right:18px;bottom:18px;z-index:100001;margin-right:0;padding:10px;border-radius:999px;background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);box-shadow:var(--yt-glass-shadow);backdrop-filter:blur(10px) saturate(130%);-webkit-backdrop-filter:blur(10px) saturate(130%);}\n .ytp-plus-settings-button--floating:hover{transform:translateY(-2px) rotate(30deg);}\n @media(max-width:768px){.ytp-plus-settings-button--floating{right:12px;bottom:12px;padding:8px;}}\n .ytSearchboxComponentInputBox { background: transparent !important; }", e = '\n .ytp-plus-settings-modal{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--yt-modal-bg);display:flex;align-items:center;justify-content:center;z-index:100000;backdrop-filter:blur(8px) saturate(140%);-webkit-backdrop-filter:blur(8px) saturate(140%);animation:ytEnhanceFadeIn .25s ease-out;contain:layout style paint;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}\n .ytp-plus-settings-shell{max-width:45vw;max-height:65vh;display:flex;flex-direction:row;gap:12px;animation:ytEnhanceScaleIn .28s cubic-bezier(.4,0,.2,1);will-change:transform,opacity;}\n .ytp-plus-settings-sidebar{display:flex;align-items:center;justify-content:center;padding-top:44px;box-sizing:border-box;}\n .ytp-plus-settings-column{flex:1;min-width:0;display:flex;flex-direction:column;gap:12px;}\n .ytp-plus-settings-topbar{display:flex;align-items:center;gap:12px;padding:0 2px;}\n .ytp-plus-settings-title{font-size:14px;font-weight:500;margin:0;padding:var(--yt-space-sm) var(--yt-space-md);border-radius:18px;border:1px solid var(--yt-glass-border);color:var(--yt-text-primary);cursor:default;transition:transform .25s cubic-bezier(.4,0,.2,1),background-color .25s cubic-bezier(.4,0,.2,1),border-color .25s cubic-bezier(.4,0,.2,1);white-space:nowrap;background:var(--yt-glass-bg);text-wrap:balance;}\n .ytp-plus-settings-active-label{flex:1;font-size:13px;font-weight:600;color:var(--yt-text-secondary);text-align:center;white-space:nowrap;letter-spacing:.03em;text-transform:uppercase;opacity:.75;text-wrap:balance;}\n .ytp-plus-settings-panel{background:var(--yt-glass-bg);color:var(--yt-text-primary);border-radius:24px;flex:1;min-width:0;min-height:0;overflow:hidden;box-shadow:var(--yt-glass-shadow);backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);border:1.5px solid var(--yt-glass-border);contain:layout style paint;display:flex;}\n .ytp-plus-settings-side-actions{display:flex;flex-direction:column;gap:10px;padding-top:50px;align-self:flex-start;}\n .ytp-plus-settings-close{width:40px;height:40px;border-radius:50%;background:var(--yt-glass-bg);border:1px solid var(--yt-surface-active);display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 14px var(--yt-shadow-soft);transition:transform .12s cubic-bezier(.2,0,0,1),background-color .12s cubic-bezier(.2,0,0,1),color .2s;color:var(--yt-text-primary);padding:0;}\n .ytp-plus-settings-close:hover{transform:translateY(-2px);background:var(--yt-danger-ghost);color:var(--yt-accent);}\n .ytp-plus-settings-close:active{transform:scale(0.96) !important;}\n .ytp-plus-settings-nav{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;width:100%;}\n .ytp-plus-settings-nav-rail{border:1px solid var(--yt-glass-border);border-radius:24px;background:var(--yt-glass-bg);box-shadow:inset 0 1px 0 var(--yt-rail-inset);padding:10px 8px;}\n .ytp-plus-settings-nav-item{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0;width:44px;height:44px;border-radius:14px;cursor:pointer;transition:transform .2s cubic-bezier(.4,0,.2,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1),box-shadow .2s cubic-bezier(.4,0,.2,1);font-size:11px;border:none;color:var(--yt-text-primary);padding:4px 4px;text-align:center;}\n .ytp-plus-settings-nav-item-label{display:none;}\n .ytp-plus-settings-nav-item:hover{background:var(--yt-hover-bg);transform:translateY(-1px);}\n .ytp-plus-settings-nav-item:active{transform:scale(0.96) !important;}\n .ytp-plus-settings-nav-item.active{background:var(--yt-panel-bg);color:var(--yt-accent);box-shadow:inset 0 0 0 1px var(--yt-surface-active-strong);}\n .ytp-plus-settings-nav-item svg{width:20px;height:20px;margin-right:0;opacity:.92;transition:opacity .2s,transform .2s;flex-shrink:0;}\n .ytp-plus-settings-nav-item.active svg{opacity:1;transform:scale(1.1);}\n .ytp-plus-settings-nav-item:hover svg{transform:scale(1.06);}\n .ytp-plus-settings-main{flex:1;display:flex;flex-direction:column;min-height:0;overflow:hidden;}\n .ytp-plus-settings-content{flex:1;padding:var(--yt-space-md) var(--yt-space-lg);overflow-y:auto;min-height:0;}\n .ytp-plus-settings-section{margin-bottom:var(--yt-space-lg);}\n .ytp-plus-settings-section-title{font-size:16px;font-weight:500;margin-bottom:var(--yt-space-md);color:var(--yt-text-primary);text-wrap:balance;}\n .ytp-plus-settings-section.hidden{display:none !important;}\n .ytp-plus-settings-item{display:flex;align-items:center;margin-bottom:var(--yt-space-md);padding:14px 18px;background:transparent;transition:transform .25s cubic-bezier(.4,0,.2,1),background-color .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1);border-radius:var(--yt-radius-md);cursor:pointer;}\n .ytp-plus-settings-item:hover{background:var(--yt-hover-bg);transform:translateX(6px);box-shadow:0 2px 8px rgba(0,0,0,.1);}\n .ytp-plus-settings-item-actions{display:flex;align-items:center;gap:10px;margin-left:auto;}\n .ytp-plus-submenu-toggle{position:relative;width:26px;height:26px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:1px solid var(--yt-glass-border);color:var(--yt-text-primary);cursor:pointer;opacity:.9;transition:transform .15s ease,background-color .15s ease,opacity .15s ease;}\n .ytp-plus-submenu-toggle::after{content:"";position:absolute;top:-7px;left:-7px;right:-7px;bottom:-7px;}\n .ytp-plus-submenu-toggle:hover{background:var(--yt-hover-bg);transform:scale(1.06);}\n .ytp-plus-submenu-toggle:active{transform:scale(0.96) !important;}\n .ytp-plus-submenu-toggle:disabled{opacity:.35;cursor:not-allowed;transform:none;}\n .ytp-plus-submenu-toggle svg{width:16px;height:16px;transition:transform .15s ease;}\n .ytp-plus-submenu-toggle[aria-expanded="false"] svg{transform:rotate(-90deg);}\n .ytp-plus-submenu-toggle[aria-expanded="true"] svg{transform:rotate(0deg);}\n .ytp-plus-settings-item-label{flex:1;font-size:14px;color:var(--yt-text-primary);}\n .ytp-plus-settings-item-description{font-size:12px;color:var(--yt-text-secondary);margin-top:4px;text-wrap:pretty;}\n .ytp-plus-settings-checkbox{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:20px;height:20px;min-width:20px;min-height:20px;margin-left:auto;border:2px solid var(--yt-glass-border);border-radius:50%;background:transparent;display:inline-flex;align-items:center;justify-content:center;transition:transform 250ms cubic-bezier(.4,0,.23,1),background-color 250ms cubic-bezier(.4,0,.23,1),border-color 250ms cubic-bezier(.4,0,.23,1);cursor:pointer;position:relative;flex-shrink:0;color:var(--yt-text-primary);box-sizing:border-box;}\n .ytp-plus-settings-checkbox:focus-visible{outline:2px solid var(--yt-accent);outline-offset:2px;}\n .ytp-plus-settings-checkbox:hover{background:var(--yt-hover-bg);transform:scale(1.1);}\n .ytp-plus-settings-checkbox:active{transform:scale(0.96) !important;}\n .ytp-plus-settings-checkbox::before{content:"";width:5px;height:2px;background:var(--yt-text-primary);position:absolute;transform:rotate(45deg);top:6px;left:3px;transition:width 100ms ease 50ms,opacity 50ms;transform-origin:0% 0%;opacity:0;}\n .ytp-plus-settings-checkbox::after{content:"";width:0;height:2px;background:var(--yt-text-primary);position:absolute;transform:rotate(305deg);top:12px;left:7px;transition:width 100ms ease,opacity 50ms;transform-origin:0% 0%;opacity:0;}\n .ytp-plus-settings-checkbox:checked{transform:rotate(0deg) scale(1.15);}\n .ytp-plus-settings-checkbox:checked::before{width:9px;opacity:1;background:var(--yt-text-primary);transition:width 150ms ease 100ms,opacity 150ms ease 100ms;}\n .ytp-plus-settings-checkbox:checked::after{width:16px;opacity:1;background:var(--yt-text-primary);transition:width 150ms ease 250ms,opacity 150ms ease 250ms;}\n .ytp-plus-settings-select{margin-left:auto;flex-shrink:0;background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);border-radius:8px;color:var(--yt-text-primary);font-size:13px;padding:4px 8px;cursor:pointer;outline:none;transition:border-color .2s;}\n .ytp-plus-settings-select:focus{border-color:var(--yt-accent,#f00);}\n html[data-ytp-theme="light"] .ytp-plus-settings-select,html:not([dark]):not([data-ytp-theme="dark"]) .ytp-plus-settings-select{background:var(--yt-input-bg);border-color:var(--yt-border-color);}\n .ytp-plus-button{padding:var(--yt-space-sm) var(--yt-space-md);border-radius:18px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:transform .25s cubic-bezier(.4,0,.2,1),background-color .25s cubic-bezier(.4,0,.2,1),box-shadow .25s cubic-bezier(.4,0,.2,1),color .25s cubic-bezier(.4,0,.2,1);}\n .ytp-plus-button-primary{background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);color:var(--yt-text-primary);}\n .ytp-plus-button-primary:hover{background:var(--yt-accent);color:#fff;box-shadow:0 6px 16px var(--yt-danger-shadow-strong);transform:translateY(-2px);}\n .ytp-plus-button:active{transform:scale(0.96) !important;}\n .update-open-page-btn{padding:12px 16px;font-size:13px;background:var(--yt-button-bg);border:1px solid var(--yt-glass-border);display:inline-flex;align-items:center;justify-content:center;}\n .update-open-page-btn svg{stroke:currentColor;}\n .update-open-page-btn:hover{background:var(--yt-hover-bg);transform:translateY(-1px);box-shadow:var(--yt-shadow);}\n .ytp-plus-settings-item .update-open-page-btn{margin-left:auto;}\n .app-icon{fill:var(--yt-text-primary);stroke:var(--yt-text-primary);transition:fill .3s,stroke .3s;}\n .about-section-content{display:flex;flex-direction:row;align-items:center;justify-content:center;flex-wrap:nowrap;width:fit-content;max-width:100%;line-height:1;gap:12px;text-align:center;margin:6px auto 12px;}\n .about-section-content .app-icon{display:block;flex:0 0 auto;margin:0;}\n @media(max-width:768px){.ytp-plus-settings-shell{max-height:86vh;flex-direction:column;gap:8px;}\n .ytp-plus-settings-sidebar{width:100%;max-height:70px;overflow-x:auto;padding-top:0;}\n .ytp-plus-settings-nav{flex-direction:row;}\n .ytp-plus-settings-nav-rail{max-width:none;border:none;border-radius:0;background:transparent;box-shadow:none;padding:0;flex-direction:row;display:flex;gap:4px;}\n .ytp-plus-settings-nav-item{width:40px;height:40px;}\n .ytp-plus-settings-side-actions{flex-direction:row;padding-top:0;align-self:auto;}\n .ytp-plus-settings-panel{min-height:0;}\n .ytp-plus-settings-active-label{display:none;}\n .ytp-plus-settings-item{padding:10px 12px;}}\n .about-section-content h1{margin:0;white-space:nowrap;font-family:\'Montserrat\',sans-serif;font-size:52px;font-weight:600;line-height:1.05;color:transparent;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:var(--yt-text-stroke);cursor:pointer;transition:color .2s;}\n .about-section-content h1:hover{color:var(--yt-accent);-webkit-text-stroke-width:1px;-webkit-text-stroke-color:transparent;}\n .glass-panel{background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);border-radius:var(--yt-radius-md);box-shadow:var(--yt-glass-shadow);}\n .glass-card{background:var(--yt-panel-bg);border:1px solid var(--yt-glass-border);border-radius:var(--yt-radius-md);padding:var(--yt-space-md);box-shadow:var(--yt-shadow);}\n .stats-value, .ytp-plus-dislike-text, .speed-control-btn, .ytp-plus-voting-comments-icon{font-variant-numeric:tabular-nums;}\n .glass-modal{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--yt-modal-bg);display:flex;align-items:center;justify-content:center;z-index:99999;}\n .glass-button{background:var(--yt-button-bg);border:1px solid var(--yt-glass-border);border-radius:var(--yt-radius-md);padding:var(--yt-space-sm) var(--yt-space-md);color:var(--yt-text-primary);cursor:pointer;transition:background-color .2s ease,transform .1s cubic-bezier(0.2,0,0,1),box-shadow .2s ease,color .2s ease,border-color .2s ease;}\n .glass-button:hover{background:var(--yt-hover-bg);transform:translateY(-1px);box-shadow:var(--yt-shadow);}\n .glass-button:active{transform:scale(0.96) !important;}\n .glass-button.danger{background:var(--yt-danger-soft);border-color:var(--yt-danger-border);color:var(--yt-danger-text);}\n .glass-button.danger:hover{background:var(--yt-danger-soft-hover);}\n .download-site-controls{display:flex;flex-direction:column;gap:8px;margin-top:4px;}\n .download-site-input{width:100%;height:36px;border-radius:10px;border:1px solid var(--yt-glass-border);background:var(--yt-input-bg, rgba(255,255,255,.06));color:var(--yt-text-primary);padding:10px 12px;box-sizing:border-box;}\n .download-site-input.small{height:32px;font-size:12px;padding:6px 10px;}\n .download-site-input:focus{background:var(--yt-hover-bg);outline:none;}\n .download-site-cta{display:flex;gap:8px;width:100%;box-sizing:border-box;}\n .download-site-cta.one-btn{justify-content:center;}\n .download-site-cta .glass-button{flex:1;}\n .download-site-cta.one-btn .glass-button{width:100%;}\n .style-submenu{margin:4px 0 12px 12px;}\n .style-submenu-container{display:flex;flex-direction:column;gap:8px;}\n .style-side-videos-submenu{margin-left:12px;margin-bottom:8px;}\n .enhanced-submenu,.music-submenu{margin-left:12px;margin-bottom:12px;}\n .ytp-plus-settings-submenu-card{display:flex;flex-direction:column;gap:8px;}\n .ytp-plus-settings-item--top-gap{margin-top:4px;}\n .loop-submenu-compact{margin:0 0 4px 0;}\n .loop-hotkeys-row-no-margin{margin-bottom:0;}\n .loop-submenu-container{display:flex;flex-direction:column;gap:8px;}\n .loop-hotkeys-row{flex-direction:column!important;align-items:stretch!important;gap:6px;}\n .loop-hotkeys-info{display:flex;flex-direction:column;gap:4px;}\n .loop-hotkeys-fields{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;margin-top:12px;width:100%;}\n .loop-hotkey-field{display:flex;flex-direction:column;align-items:center;gap:8px;font-size:12px;color:var(--yt-text-secondary);flex:1;min-width:80px;}\n .loop-hotkey-field span{text-align:center;width:100%;}\n .loop-hotkey-input{width:100%;height:36px;border-radius:8px;border:1px solid var(--yt-glass-border);background:var(--yt-glass-bg);color:var(--yt-text-primary);text-align:center;text-transform:uppercase;}\n .loop-hotkey-input:focus{background:var(--yt-hover-bg);}\n .ytp-plus-about-actions{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin:16px 0;}\n .ytp-plus-about-footer{text-align:center;color:var(--yt-text-secondary);font-size:13px;line-height:1.6;margin-bottom:12px;}\n .ytp-plus-about-author-link{color:var(--yt-text-primary);font-style:italic;text-decoration:none;}\n .ytplus-guide-toggle-btn{position:fixed;right:12px;bottom:12px;z-index:100000;background:var(--yt-spec-call-to-action);color:#fff;border:none;border-radius:8px;padding:8px 10px;box-shadow:0 6px 18px var(--yt-shadow-notification);cursor:pointer;opacity:.95;font-size:13px;}\n .ytp-plus-settings-panel select,\n .ytp-plus-settings-panel select option {background: var(--yt-panel-bg) !important; color: var(--yt-text-primary) !important;}\n .ytp-plus-settings-panel select {-webkit-appearance: menulist !important; appearance: menulist !important; padding: 6px 8px !important; border-radius: 6px !important; border: 1px solid var(--yt-glass-border) !important;}\n .ytp-plus-theme-item{display:flex;flex-direction:column;align-items:stretch;gap:12px;text-align:left;}\n .ytp-plus-theme-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;width:100%}\n .ytp-plus-theme-card{display:flex;align-items:center;justify-content:center;min-height:44px;border-radius:12px;border:1px solid var(--yt-glass-border);background:var(--yt-panel-bg);color:var(--yt-text-secondary);font-size:13px;font-weight:500;cursor:pointer;transition:background-color .18s ease,color .18s ease,border-color .18s ease,transform .18s ease,box-shadow .18s ease}\n .ytp-plus-theme-card:hover{background:var(--yt-hover-bg);color:var(--yt-text-primary)}\n .ytp-plus-theme-card:active{transform:scale(0.96) !important;}\n .ytp-plus-theme-card.active{color:#fff;background:linear-gradient(180deg,var(--yt-danger-card-bg-start),var(--yt-danger-card-bg-end));border-color:var(--yt-danger-card-border);box-shadow:0 0 0 1px var(--yt-danger-card-inset) inset}\n @media(max-width:580px){.ytp-plus-theme-grid{grid-template-columns:1fr}}\n .glass-dropdown{position:relative;display:inline-block;min-width:110px}\n .glass-dropdown__toggle{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:6px 8px;border-radius:8px;background:linear-gradient(180deg, var(--yt-surface-overlay-subtle), var(--yt-surface-overlay-faint));color:inherit;border:1px solid var(--yt-surface-overlay-border);cursor:pointer}\n .glass-dropdown__toggle:focus{outline:2px solid var(--yt-surface-overlay-border)}\n .glass-dropdown__label{font-size:12px}\n .glass-dropdown__chev{opacity:0.9}\n .glass-dropdown__list{position:absolute;left:0;right:0;bottom:calc(100% + 8px);top:auto;z-index:20000;display:none;margin:0;padding:6px;border-radius:10px;list-style:none;background:var(--yt-header-bg);border:1px solid var(--yt-surface-overlay-border);box-shadow:0 8px 30px var(--yt-shadow-flyout);backdrop-filter:blur(10px) saturate(130%);-webkit-backdrop-filter:blur(10px) saturate(130%);max-height:220px;overflow:auto}\n .glass-dropdown__list.glass-dropdown__list--down{bottom:auto;top:calc(100% + 8px)}\n .glass-dropdown__item{padding:8px 10px;border-radius:6px;margin:4px 0;cursor:pointer;color:inherit;font-size:13px}\n .glass-dropdown__item:hover{background:var(--yt-surface-overlay-subtle)}\n .glass-dropdown__item[aria-selected="true"]{background:linear-gradient(90deg, var(--yt-surface-overlay-subtle), var(--yt-surface-overlay-faint));box-shadow:inset 0 0 0 1px var(--yt-surface-overlay-faint)}\n .ytp-plus-settings-voting-header{margin-bottom:var(--yt-space-lg);}\n .ytp-plus-settings-voting-header h3{font-size:18px;font-weight:500;margin:0 0 8px 0;color:var(--yt-text-primary);}\n .ytp-plus-settings-voting-desc{font-size:13px;color:var(--yt-text-secondary);margin:0;}\n .ytp-plus-voting{display:flex;flex-direction:column;gap:12px;}\n .ytp-plus-voting-header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;}\n .ytp-plus-voting-list{display:flex;flex-direction:column;gap:12px;}\n .ytp-plus-voting-item{display:flex;align-items:flex-start;justify-content:space-between;padding:16px;background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);border-radius:var(--yt-radius-md);transition:background-color .2s ease,transform .2s ease,border-color .2s ease,box-shadow .2s ease;gap:12px;}\n .ytp-plus-voting-item:hover{background:var(--yt-hover-bg);transform:translateX(4px);}\n .ytp-plus-voting-item-content{flex:1;padding-right:16px;}\n .ytp-plus-voting-item-title{font-size:14px;font-weight:500;color:var(--yt-text-primary);margin-bottom:4px;}\n .ytp-plus-voting-item-desc{font-size:12px;color:var(--yt-text-secondary);line-height:1.4;}\n .ytp-plus-voting-item-status{font-size:11px;min-height:28px;padding:0 10px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;background:var(--yt-surface-overlay-soft);color:var(--yt-text-secondary);border:1px solid var(--yt-glass-border);line-height:1;}\n .ytp-plus-voting-item-status.completed{background:var(--yt-success-soft);color:var(--yt-success);}\n .ytp-plus-voting-item-status.in-progress{background:var(--yt-warning-soft);color:var(--yt-warning);}\n .ytp-plus-voting-item-votes{display:flex;flex-direction:column;align-items:stretch;gap:8px;min-width:120px;}\n .ytp-plus-voting-score{display:flex;align-items:baseline;gap:8px;justify-content:center;}\n .ytp-plus-vote-total{font-size:12px;color:var(--yt-text-secondary);}\n .ytp-plus-voting-buttons{position:relative;display:flex;justify-content:center;gap:0;border:1px solid var(--yt-glass-border);border-radius:20px;overflow:hidden;}\n .ytp-plus-voting-buttons-track{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;transition:background .4s ease;border-radius:20px;pointer-events:none;}\n .ytp-plus-vote-btn{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;width:42px;height:32px;border:none;background:transparent;cursor:pointer;transition:color .15s ease,opacity .15s ease,transform .1s cubic-bezier(0.2,0,0,1);color:var(--yt-text-secondary);opacity:.95}\n .ytp-plus-vote-btn:first-of-type{border-right:1px solid var(--yt-glass-border)}\n .ytp-plus-vote-btn:hover{color:var(--yt-text-primary);opacity:1}\n .ytp-plus-vote-btn:active{transform:scale(0.96) !important;}\n .ytp-plus-vote-btn.active{color:#fff;opacity:1}\n .ytp-plus-vote-icon{width:20px;height:20px;fill:currentColor;opacity:.92}\n .ytp-plus-vote-btn.active .ytp-plus-vote-icon,.ytp-plus-vote-btn:hover .ytp-plus-vote-icon{opacity:1}\n .ytp-plus-voting-loading,.ytp-plus-voting-empty{text-align:center;padding:24px;color:var(--yt-text-secondary);font-size:13px;}\n .ytp-plus-voting-add-btn{background:var(--yt-accent);color:#fff;border:none;padding:8px 16px;border-radius:18px;font-size:13px;font-weight:500;cursor:pointer;transition:background-color .2s cubic-bezier(0.2,0,0,1),transform .2s cubic-bezier(0.2,0,0,1),box-shadow .2s cubic-bezier(0.2,0,0,1);}\n .ytp-plus-voting-add-btn:hover{transform:translateY(-2px);box-shadow:0 4px 12px var(--yt-danger-shadow);}\n .ytp-plus-voting-add-btn:active{transform:scale(0.96) !important;}\n .ytp-plus-voting-add-form{margin-top:16px;padding:16px;background:var(--yt-glass-bg);border:1px solid var(--yt-glass-border);border-radius:var(--yt-radius-md);}\n .ytp-plus-voting-add-form input,.ytp-plus-voting-add-form textarea{width:100%;padding:10px 12px;margin-bottom:12px;background:var(--yt-header-bg);border:1px solid var(--yt-glass-border);border-radius:8px;color:var(--yt-text-primary);font-size:13px;box-sizing:border-box;}\n .ytp-plus-voting-add-form input:focus,.ytp-plus-voting-add-form textarea:focus{border-color:var(--yt-accent);outline:none;}\n .ytp-plus-voting-add-form textarea{min-height:80px;resize:vertical;}\n .ytp-plus-voting-form-actions{display:flex;gap:8px;justify-content:flex-end;}\n .ytp-plus-voting-cancel{background:transparent;border:1px solid var(--yt-glass-border);color:var(--yt-text-primary);padding:8px 16px;border-radius:18px;font-size:13px;cursor:pointer;transition:background-color .2s cubic-bezier(0.2,0,0,1),border-color .2s cubic-bezier(0.2,0,0,1),transform .2s cubic-bezier(0.2,0,0,1);}\n .ytp-plus-voting-cancel:hover{background:var(--yt-hover-bg);}\n .ytp-plus-voting-cancel:active{transform:scale(0.96) !important;}\n .ytp-plus-voting-submit{background:var(--yt-accent);color:#fff;border:none;padding:8px 16px;border-radius:18px;font-size:13px;font-weight:500;cursor:pointer;transition:background-color .2s cubic-bezier(0.2,0,0,1),transform .2s cubic-bezier(0.2,0,0,1),box-shadow .2s cubic-bezier(0.2,0,0,1);}\n .ytp-plus-voting-submit:hover{transform:translateY(-2px);box-shadow:0 4px 12px var(--yt-danger-shadow);}\n .ytp-plus-voting-submit:active{transform:scale(0.96) !important;}\n @media (max-width: 680px){.ytp-plus-voting-item{flex-direction:column;align-items:stretch}.ytp-plus-voting-item-content{padding-right:0}.ytp-plus-voting-item-votes{min-width:0;width:100%}}\n .ytp-plus-voting-preview{margin-bottom:20px;}\n .ytp-plus-ba-container{position:relative;width:100%;height:260px;overflow:hidden;border-radius:var(--yt-radius-md);border:1px solid var(--yt-glass-border);user-select:none;cursor:ew-resize;background:var(--yt-glass-bg);}\n .ytp-plus-ba-before,.ytp-plus-ba-after{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;}\n .ytp-plus-ba-before img,.ytp-plus-ba-after img{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;display:block;pointer-events:none;}\n .ytp-plus-ba-after{clip-path:inset(0 0 0 50%);}\n .ytp-plus-ba-divider{position:absolute;top:0;left:50%;transform:translateX(-50%);width:8px;height:100%;background:transparent;pointer-events:auto;z-index:3;cursor:ew-resize;transition:left .6s linear}\n .ytp-plus-ba-divider::after{content:\'\';position:absolute;left:50%;top:0;transform:translateX(-50%);width:2px;height:100%;background:var(--yt-accent,#f00);}\n .ytp-plus-ba-divider.autoplay{animation:ytpPlusSlideDivider 6s linear infinite}\n @keyframes ytpPlusSlideDivider{0%{left:10%}50%{left:90%}100%{left:10%}}\n .ytp-plus-ba-label{position:absolute;top:10px;padding:4px 10px;border-radius:4px;font-size:12px;font-weight:600;color:#fff;background:var(--yt-overlay-strong);pointer-events:none;z-index:5;}\n .ytp-plus-ba-label-before{left:10px;}\n .ytp-plus-ba-label-after{right:10px;}\n .ytp-plus-vote-bar-section{margin-top:12px;display:flex;flex-direction:column;align-items:center;gap:6px;}\n .ytp-plus-vote-bar-buttons{position:relative;display:flex;gap:0;border-radius:20px;overflow:hidden;border:1px solid var(--yt-glass-border);}\n .ytp-plus-vote-bar-track{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;transition:background .4s ease;background:linear-gradient(to right, var(--yt-success) 50%, var(--yt-danger) 50%);border-radius:20px;}\n .ytp-plus-vote-bar-btn{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;padding:8px 18px;background:transparent;border:none;color:var(--yt-text-secondary);cursor:pointer;transition:color .15s;font-size:14px;}\n .ytp-plus-vote-bar-btn:first-of-type{border-right:1px solid var(--yt-glass-border);}\n .ytp-plus-vote-bar-btn:hover{color:var(--yt-text-primary);}\n .ytp-plus-vote-bar-btn.active{color:#fff;}\n .ytp-plus-vote-bar-btn svg{fill:currentColor;width:20px;height:20px;display:block;}\n .ytp-plus-vote-bar-btn svg path{fill:currentColor;}\n .ytp-plus-vote-bar-count{font-size:12px;color:var(--yt-text-secondary);}', o = window.YouTubePlusDOMCache, r = t => o && "function" == typeof o.getElementById ? o.getElementById(t) : "undefined" != typeof document ? document.getElementById(t) : null, i = () => { try { const t = YouTubeUtils?.StyleManager; if (t && "function" == typeof t.add) { t.add("yt-enhancer-nc-styles", e); const o = r("yt-enhancer-nc-styles"); return void (o && o.remove && o.remove()); } } catch (t) {} if (!r("yt-enhancer-nc-styles")) { const t = document.createElement("style"); t.id = "yt-enhancer-nc-styles", t.textContent = e, (document.head || document.documentElement).appendChild(t); } }; this.ensureNonCriticalStyles = i, (() => { try { const e = YouTubeUtils?.StyleManager; if (e && "function" == typeof e.add) { return void e.add("yt-enhancer-main", t); } } catch (t) {} if (!r("yt-enhancer-main")) { const e = document.createElement("style"); e.id = "yt-enhancer-main", e.textContent = t, (document.head || document.documentElement).appendChild(e); } })(), i(); }, createSettingsLauncherButton() { const o = document.createElement("div"); return o.className = "ytp-plus-settings-button", o.setAttribute("title", e("youtubeSettings")), t(o, '\n <svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round">\n <path d="M39.23,26a16.52,16.52,0,0,0,.14-2,16.52,16.52,0,0,0-.14-2l4.33-3.39a1,1,0,0,0,.25-1.31l-4.1-7.11a1,1,0,0,0-1.25-.44l-5.11,2.06a15.68,15.68,0,0,0-3.46-2l-.77-5.43a1,1,0,0,0-1-.86H19.9a1,1,0,0,0-1,.86l-.77,5.43a15.36,15.36,0,0,0-3.46,2L9.54,9.75a1,1,0,0,0-1.25.44L4.19,17.3a1,1,0,0,0,.25,1.31L8.76,22a16.66,16.66,0,0,0-.14,2,16.52,16.52,0,0,0,.14,2L4.44,29.39a1,1,0,0,0-.25,1.31l4.1,7.11a1,1,0,0,0,1.25.44l5.11-2.06a15.68,15.68,0,0,0,3.46,2l.77,5.43a1,1,0,0,0,1,.86h8.2a1,1,0,0,0,1-.86l.77-5.43a15.36,15.36,0,0,0,3.46-2l5.11,2.06a1,1,0,0,0,1.25-.44l4.1-7.11a1,1,0,0,0-.25-1.31ZM24,31.18A7.18,7.18,0,1,1,31.17,24,7.17,7.17,0,0,1,24,31.18Z"/>\n </svg>\n '), o.addEventListener("click", this.openSettingsModal.bind(this)), o; }, getSettingsButtonTargets() { const t = String(location.hostname || "").toLowerCase(); return "music.youtube.com" === t ? [ "ytmusic-nav-bar #right-content", "ytmusic-nav-bar .right-content", "ytmusic-nav-bar #right-divider ~ *", "ytmusic-nav-bar tp-yt-paper-icon-button#right-content", "ytmusic-nav-bar .center-content", "ytmusic-nav-bar" ] : "studio.youtube.com" === t || t.endsWith(".studio.youtube.com") ? [ "ytcp-header #right-content", "ytcp-header .right-content", "ytcp-header #account-section", "ytcp-header #notifications-button", "tp-yt-app-header #right-content", "ytcp-header" ] : [ "ytd-masthead #end", "ytd-masthead #buttons", "ytd-masthead", "#end" ]; }, mountSettingsButton(t) { if (basicHasSettingsButton_()) { return; } const e = this.createSettingsLauncherButton(), o = t.querySelector('ytd-topbar-menu-button-renderer, ytmusic-settings-button, ytmusic-user-settings-button, [id*="avatar" i], [aria-label*="account" i]'); o && o.parentElement === t ? t.insertBefore(e, o) : t.appendChild(e); }, addFloatingSettingsButton() { if (basicHasSettingsButton_()) { return; } const t = this.createSettingsLauncherButton(); t.classList.add("ytp-plus-settings-button--floating"), (document.body || document.documentElement).appendChild(t); }, addSettingsButtonToHeader() { if (basicHasSettingsButton_()) { return; } const t = this.getSettingsButtonTargets(); for (const e of t) { const t = this.getElement(e); if (t) { return void this.mountSettingsButton(t); } } this.waitForElement(t[t.length - 1], 5e3).then(() => { if (!basicHasSettingsButton_()) { for (const e of t) { const t = this.getElement(e); if (t) { return void this.mountSettingsButton(t); } } this.addFloatingSettingsButton(); } }).catch(() => { this.addFloatingSettingsButton(); }); }, handleModalClickActions(t, e, o, r, i, a) { const s = t.classList?.contains("ytp-plus-settings-nav-item") ? t : t.closest?.(".ytp-plus-settings-nav-item"); if (s) { o.handleSidebarNavigation(s, e); } else { if ("ytp-plus-save-settings" === t.id || "ytp-plus-save-settings-icon" === t.id) { this.saveSettings(); try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-modal-closed", { bubbles: !0 })); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } return e.N?.disconnect(), e.remove(), void this.showNotification(a("settingsSaved")); } "download-externalDownloader-save" !== t.id ? "download-externalDownloader-reset" === t.id && o.handleExternalDownloaderReset(e, this.settings, this.saveSettings.bind(this), this.showNotification.bind(this), a) : o.handleExternalDownloaderSave(t, this.settings, this.saveSettings.bind(this), this.showNotification.bind(this), a); } }, createSettingsModal() { const o = document.createElement("div"); o.className = "ytp-plus-settings-modal"; const r = window.YouTubePlusSettingsHelpers, i = window.YouTubePlusModalHandlers; t(o, `\n <div class="ytp-plus-settings-shell">\n <div class="ytp-plus-settings-sidebar">${r.createSettingsSidebar(e)}</div>\n <div class="ytp-plus-settings-column">\n <div class="ytp-plus-settings-topbar">\n <h2 class="ytp-plus-settings-title">${e("settingsTitle")}</h2>\n <div class="ytp-plus-settings-active-label" id="ytp-plus-active-section-label"></div>\n <button class="ytp-plus-button ytp-plus-button-primary" id="ytp-plus-save-settings">${e("saveChanges")}</button>\n </div>\n <div class="ytp-plus-settings-panel">${r.createMainContent(this.settings, e)}</div>\n </div>\n <div class="ytp-plus-settings-side-actions">\n <button class="ytp-plus-settings-close" id="ytp-plus-close-settings" aria-label="${e("closeButton")}">\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 9.50002L9.5 14.5M9.49998 9.5L14.5 14.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>\n </button>\n </div>\n </div>\n `); let a = null, s = null; const c = () => { const t = o.querySelector(".ytp-plus-settings-shell"), e = o.querySelector(".ytp-plus-settings-sidebar"), r = o.querySelector(".ytp-plus-settings-column"), i = o.querySelector(".ytp-plus-settings-topbar"), a = o.querySelector(".ytp-plus-settings-panel"), s = o.querySelector(".ytp-plus-settings-main"), c = o.querySelector(".ytp-plus-settings-content"), l = o.querySelector(".ytp-plus-settings-side-actions"), d = o.querySelector(".ytp-plus-settings-nav-rail"), u = o.querySelectorAll(".ytp-plus-settings-nav-item"), p = o.querySelectorAll(".ytp-plus-settings-section.hidden"), y = o.querySelector(".ytp-plus-settings-nav-item svg"), m = o.querySelector(".ytp-plus-settings-nav-item-label"), f = o.querySelector(".ytp-plus-settings-item"); let b = !1; try { const e = t ? window.getComputedStyle(t) : null, o = a ? window.getComputedStyle(a) : null, r = m ? window.getComputedStyle(m) : null, i = f ? window.getComputedStyle(f) : null, s = y?.getBoundingClientRect?.().width || 0; b = !(t && a) || "flex" !== e?.display || "flex" !== o?.display || s > 64 || "none" !== r?.display || "flex" !== i?.display; } catch (t) { b = !0; } if (b) { o.setAttribute("data-ytp-inline-fallback", "true"), Object.assign(o.style, { position: "fixed", inset: "0", display: "flex", alignItems: "center", justifyContent: "center", padding: "16px", boxSizing: "border-box", background: "var(--yt-modal-bg, rgba(0,0,0,.72))", zIndex: "100000" }), t && Object.assign(t.style, { display: "flex", flexDirection: "row", gap: "12px", width: "min(960px, 92vw)", maxWidth: "92vw", maxHeight: "86vh" }), e && Object.assign(e.style, { display: "flex", alignItems: "center", justifyContent: "center", paddingTop: "44px", boxSizing: "border-box" }), r && Object.assign(r.style, { flex: "1", minWidth: "0", display: "flex", flexDirection: "column", gap: "12px" }), i && Object.assign(i.style, { display: "flex", alignItems: "center", gap: "12px", padding: "0 2px" }), a && Object.assign(a.style, { display: "flex", flex: "1", minWidth: "0", minHeight: "0", overflow: "hidden", background: "var(--yt-glass-bg, rgba(24,24,24,.92))", color: "var(--yt-text-primary, #fff)", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", borderRadius: "24px", boxShadow: "var(--yt-glass-shadow, 0 12px 40px rgba(0,0,0,.35))" }), s && Object.assign(s.style, { flex: "1", minHeight: "0", display: "flex", flexDirection: "column" }), c && Object.assign(c.style, { flex: "1", minHeight: "0", overflowY: "auto", padding: "16px 20px" }), l && Object.assign(l.style, { display: "flex", flexDirection: "column", gap: "10px", paddingTop: "50px", alignSelf: "flex-start" }), d && Object.assign(d.style, { display: "flex", flexDirection: "column", gap: "8px", padding: "10px 8px", borderRadius: "24px", background: "var(--yt-glass-bg, rgba(24,24,24,.92))", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))" }); for (const t of p) { t instanceof HTMLElement && (t.style.display = "none"); } for (const t of u) { t instanceof HTMLElement && Object.assign(t.style, { position: "relative", width: "44px", height: "44px", display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "14px", color: "var(--yt-text-primary, #fff)", flexShrink: "0" }); } o.querySelectorAll(".ytp-plus-settings-nav-item-label").forEach(t => { t instanceof HTMLElement && (t.style.display = "none"); }), o.querySelectorAll(".ytp-plus-settings-item:not(.ytp-plus-theme-item)").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", alignItems: "center", gap: "16px", padding: "14px 18px", marginBottom: "12px", borderRadius: "14px", boxSizing: "border-box" }); }), o.querySelectorAll(".ytp-plus-theme-item").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", flexDirection: "column", alignItems: "stretch", gap: "12px", padding: "14px 18px", marginBottom: "12px", borderRadius: "14px", boxSizing: "border-box", textAlign: "left" }); }), o.querySelectorAll(".ytp-plus-settings-item-actions").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", alignItems: "center", gap: "10px", marginLeft: "auto", flexShrink: "0" }); }), o.querySelectorAll(".ytp-plus-button").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "8px", minHeight: "36px", padding: "8px 14px", borderRadius: "18px", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: "var(--yt-glass-bg, rgba(255,255,255,.08))", color: "var(--yt-text-primary, #fff)", boxSizing: "border-box" }); }), o.querySelectorAll(".glass-button").forEach(t => { if (!(t instanceof HTMLElement)) { return; } const e = t.classList.contains("danger"); Object.assign(t.style, { display: "inline-flex", alignItems: "center", justifyContent: "center", gap: "8px", minHeight: "36px", padding: "8px 14px", borderRadius: "14px", border: e ? "1px solid var(--yt-danger-border, rgba(255,59,59,0.3))" : "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: e ? "var(--yt-danger-soft, rgba(255,59,59,0.15))" : "var(--yt-button-bg, rgba(255,255,255,.08))", color: e ? "var(--yt-danger-text, #ff5c5c)" : "var(--yt-text-primary, #fff)", boxSizing: "border-box" }); }), o.querySelectorAll(".download-site-cta").forEach(t => { t instanceof HTMLElement && (Object.assign(t.style, { display: "flex", gap: "8px", width: "100%", boxSizing: "border-box" }), t.querySelectorAll(".glass-button").forEach(e => { e instanceof HTMLElement && (e.style.flex = "1", t.classList.contains("one-btn") && (e.style.width = "100%")); })); }), o.querySelectorAll(".download-site-controls").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "none" === t.style.display ? "none" : "flex", flexDirection: "column", gap: "8px", marginTop: "4px" }); }), o.querySelectorAll(".ytp-plus-submenu-toggle").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: t.hasAttribute("disabled") ? "none" : "inline-flex", alignItems: "center", justifyContent: "center", width: "26px", height: "26px", borderRadius: "999px", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: "transparent", color: "var(--yt-text-primary, #fff)", flexShrink: "0" }); }), o.querySelectorAll(".ytp-plus-settings-checkbox").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { appearance: "none", WebkitAppearance: "none", width: "20px", height: "20px", minWidth: "20px", minHeight: "20px", marginLeft: "auto", borderRadius: "50%", border: "2px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: "transparent", display: "inline-flex", alignItems: "center", justifyContent: "center", boxSizing: "border-box", flexShrink: "0" }); }), o.querySelectorAll('.ytp-plus-settings-item input[type="text"], .ytp-plus-settings-item input[type="email"], .ytp-plus-settings-item textarea, .download-site-input, .pip-key-input, .ytp-plus-settings-panel input[type="text"], .ytp-plus-settings-panel input[type="email"], .ytp-plus-settings-panel textarea, .ytp-plus-settings-panel select').forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { background: "var(--yt-input-bg, rgba(255,255,255,.06))", color: "var(--yt-text-primary, #fff)", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", borderRadius: "10px", padding: "10px 12px", boxSizing: "border-box" }); }), o.querySelectorAll(".glass-dropdown").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { position: "relative", display: "inline-block", minWidth: "140px" }); }), o.querySelectorAll(".glass-dropdown__toggle").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "8px", width: "100%", padding: "8px 10px", borderRadius: "10px", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: "var(--yt-button-bg, rgba(255,255,255,.08))", color: "var(--yt-text-primary, #fff)", boxSizing: "border-box" }); }), o.querySelectorAll(".glass-dropdown__list").forEach(t => { t instanceof HTMLElement && (Object.assign(t.style, { listStyle: "none", margin: "0 0 8px 0", padding: "6px", borderRadius: "10px", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: "var(--yt-panel-bg, rgba(24,24,24,.96))", boxSizing: "border-box", top: "auto", bottom: "calc(100% + 8px)" }), t.classList.contains("glass-dropdown__list--down") && (t.style.bottom = "auto", t.style.top = "calc(100% + 8px)", t.style.margin = "8px 0 0 0"), "true" === t.parentElement?.getAttribute("aria-expanded") || t.style.display || (t.style.display = "none")); }), o.querySelectorAll(".glass-dropdown__item").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { listStyle: "none", padding: "8px 10px", margin: "0", borderRadius: "8px", cursor: "pointer" }); }), o.querySelectorAll(".ytp-plus-theme-grid").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "grid", gridTemplateColumns: "repeat(2, minmax(0, 1fr))", gap: "10px", width: "100%" }); }), o.querySelectorAll(".ytp-plus-theme-card").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "44px", borderRadius: "12px", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: t.classList.contains("active") ? "linear-gradient(180deg, var(--yt-danger-card-bg-start, rgba(255,0,0,.4)), var(--yt-danger-card-bg-end, rgba(180,0,0,.45)))" : "var(--yt-panel-bg, rgba(255,255,255,.04))", color: "var(--yt-text-primary, #fff)", boxSizing: "border-box" }); }), o.querySelectorAll(".ytp-plus-about-actions").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", flexWrap: "wrap", justifyContent: "center", gap: "10px", margin: "16px 0" }); }), o.querySelectorAll(".ytp-plus-about-footer").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { textAlign: "center", color: "var(--yt-text-secondary, rgba(255,255,255,.72))", fontSize: "13px", lineHeight: "1.6" }); }), o.querySelectorAll(".ytp-plus-voting, .ytp-plus-voting-list").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", flexDirection: "column", gap: "12px" }); }), o.querySelectorAll(".ytp-plus-voting-item").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "12px", padding: "16px", borderRadius: "16px", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))", background: "var(--yt-glass-bg, rgba(255,255,255,.04))", boxSizing: "border-box" }); }), o.querySelectorAll(".ytp-plus-voting-buttons, .ytp-plus-vote-bar-buttons").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { position: "relative", display: "flex", alignItems: "center", gap: "0", borderRadius: "20px", overflow: "hidden", border: "1px solid var(--yt-glass-border, rgba(255,255,255,.12))" }); }), o.querySelectorAll(".ytp-plus-vote-btn, .ytp-plus-vote-bar-btn").forEach(t => { t instanceof HTMLElement && Object.assign(t.style, { position: "relative", zIndex: "1", display: "inline-flex", alignItems: "center", justifyContent: "center", minWidth: "42px", minHeight: "32px", border: "none", background: "transparent", color: "var(--yt-text-primary, #fff)" }); }), o.querySelectorAll(".ytp-plus-settings-section").forEach(t => { t instanceof HTMLElement && (t.classList.contains("hidden") || (t.style.display = "")); }), o.querySelectorAll("svg").forEach(t => { if (!(t instanceof SVGElement)) { return; } const e = t.classList.contains("app-icon"); t.getAttribute("width") || t.setAttribute("width", e ? "72" : "20"), t.getAttribute("height") || t.setAttribute("height", e ? "72" : "20"), t.style.display = "block", t.style.flexShrink = "0", t.style.maxWidth = "100%"; }); } }; c(), requestAnimationFrame(c); try { a = new MutationObserver(() => { "true" === o.getAttribute("data-ytp-inline-fallback") && null === s && (s = requestAnimationFrame(() => { s = null, c(); })); }), o.N = a, a.observe(o, { childList: !0, subtree: !0 }); } catch (t) { a = null; } const l = o.querySelector(".ytp-plus-settings-nav-item.active"), d = o.querySelector("#ytp-plus-active-section-label"); l && d && (d.textContent = l.dataset?.label || ""); const u = () => {}, p = { settings: this.settings, getElement: this.getElement.bind(this), addDownloadButton: this.addDownloadButton.bind(this), addSpeedControlButton: this.addSpeedControlButton.bind(this), refreshDownloadButton: this.refreshDownloadButton.bind(this), updatePageBasedOnSettings: this.updatePageBasedOnSettings.bind(this) }; o.addEventListener("click", t => { const r = t.target, a = r.closest(".ytp-plus-submenu-toggle"); if (a) { try { if (a instanceof HTMLElement && "BUTTON" === a.tagName && a.hasAttribute("disabled")) { return; } const t = a.dataset?.submenu; if (!t) { return; } const e = a.closest(".ytp-plus-settings-panel"); if (!e) { return; } const o = e.querySelector(basicSubmenuSelector_(t)); if (!(o instanceof HTMLElement)) { return; } const r = !("none" === window.getComputedStyle(o).display || o.hidden || o.classList.contains("is-hidden")); o.style.display = r ? "none" : "", o.classList.toggle("is-hidden", r), a.setAttribute("aria-expanded", r ? "false" : "true"); const i = basicUiState_.submenuStates.read(); i[t] = !r, basicUiState_.submenuStates.write(i); } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Submenu toggle error", t); } return; } const s = r.closest(".ytp-plus-theme-card[data-setting-card][data-value]"); if (s instanceof HTMLElement) { const t = s.dataset.settingCard, e = s.dataset.value; if (t && "string" == typeof e) { i.setSettingByPath(this.settings, t, e); const o = s.closest(".ytp-plus-theme-grid"); o && o.querySelectorAll(".ytp-plus-theme-card").forEach(t => { const e = t === s; t.classList.toggle("active", e), t.setAttribute("aria-checked", e ? "true" : "false"); }), i.applySettingLive(t, p), this.saveSettings(); } return; } if (r === o) { try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-modal-closed", { bubbles: !0 })); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } return o.N?.disconnect(), void o.remove(); } if ("ytp-plus-close-settings" === r.id || "ytp-plus-close-settings-icon" === r.id || r.classList.contains("ytp-plus-settings-close") || r.closest(".ytp-plus-settings-close") || r.closest("#ytp-plus-close-settings") || r.closest("#ytp-plus-close-settings-icon")) { try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-modal-closed", { bubbles: !0 })); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } return o.N?.disconnect(), void o.remove(); } if ("open-ytdl-github" === r.id || r.closest("#open-ytdl-github")) { return void window.open("https://github.com/diorhc/YTDL", "_blank"); } if ("open-ytp-github" === r.id || r.closest("#open-ytp-github")) { return void window.open("https://github.com/diorhc/YTP", "_blank"); } if ("open-ytp-discussions" === r.id || r.closest("#open-ytp-discussions")) { return void window.open("https://github.com/diorhc/YTP/discussions", "_blank"); } if ("open-ytp-greasyfork" === r.id || r.closest("#open-ytp-greasyfork")) { return void window.open("https://greasyfork.org/en/scripts/537017-youtube", "_blank"); } const c = r.closest(".ytp-plus-settings-item"); if (c && !r.closest("input, select, button, a, .glass-dropdown, .ytp-plus-submenu-toggle")) { const t = c.querySelector(".ytp-plus-settings-checkbox"); if (t instanceof HTMLInputElement) { return t.checked = !t.checked, void t.dispatchEvent(new Event("change", { bubbles: !0 })); } } this.handleModalClickActions(r, o, i, u, p, e); }), o.addEventListener("change", t => { const r = t.target; if ("SELECT" === r.tagName && r.dataset?.setting) { const t = r.dataset.setting, e = r.value, o = Number(e), a = "" !== e && Number.isNaN(o) ? e : o; return i.setSettingByPath(this.settings, t, a), i.applySettingLive(t, p), void this.saveSettings(); } if (!r.classList.contains("ytp-plus-settings-checkbox")) { return; } const {dataset: a} = r, {setting: s} = a; if (s) { if (s.startsWith("downloadSite_")) { const t = s.replace("downloadSite_", ""); return void i.handleDownloadSiteToggle(r, t, this.settings, u, this.saveSettings.bind(this)); } i.isMusicSetting?.(s) ? i.handleMusicSettingToggle(r, s, this.showNotification.bind(this), e) : i.handleSimpleSettingToggle(r, s, this.settings, p, u, this.saveSettings.bind(this), o); } }), o.addEventListener("input", t => { const o = t.target; if (!o.classList.contains("speed-hotkey-input") && !o.classList.contains("loop-hotkey-input") && o.classList.contains("download-site-input")) { const {dataset: t} = o, {site: r, field: a} = t; if (!r || !a) { return; } i.handleDownloadSiteInput(o, r, a, this.settings, u, e); } }), o.addEventListener("blur", t => { const e = t.target; if (e.classList.contains("speed-hotkey-input")) { const t = e.dataset?.speedHotkey; if ("decrease" !== t && "increase" !== t && "reset" !== t) { return; } const o = e, r = this.normalizeSpeedHotkey(o.value, "decrease" === t ? "g" : "increase" === t ? "h" : "b"); return this.settings.speedControlHotkeys = this.settings.speedControlHotkeys || { decrease: "g", increase: "h", reset: "b" }, this.settings.speedControlHotkeys[t] = r, o.value = r, void this.saveSettings(); } if (e.classList.contains("loop-hotkey-input")) { const t = e.dataset?.loopHotkey; if ("setPointA" !== t && "setPointB" !== t && "resetPoints" !== t) { return; } const o = e, r = this.normalizeSpeedHotkey(o.value, "setPointA" === t ? "k" : "setPointB" === t ? "l" : "o"); return this.settings.loopHotkeys = this.settings.loopHotkeys || { toggleLoop: "r", setPointA: "k", setPointB: "l", resetPoints: "o" }, this.settings.loopHotkeys[t] = r, o.value = r, void this.saveSettings(); } }, !0); try { if ("undefined" != typeof window && window.youtubePlusReport && "function" == typeof window.youtubePlusReport.render) { try { window.youtubePlusReport.render(o); } catch (t) { YouTubeUtils.logError("Report", "report.render failed", t); } } } catch (t) { YouTubeUtils.logError("Report", "Failed to initialize report section", t); } const y = basicUiState_.submenuStates.read(); try { Object.entries(y).forEach(([t, e]) => { const r = o.querySelector(`.ytp-plus-submenu-toggle[data-submenu="${t}"]`); if (r instanceof HTMLElement && !r.hasAttribute("disabled")) { const i = o.querySelector(basicSubmenuSelector_(t)); if (i instanceof HTMLElement) { const t = !!e; i.style.display = t ? "" : "none", i.classList.toggle("is-hidden", !t), r.setAttribute("aria-expanded", t ? "true" : "false"); } } }); } catch (t) {} try { const t = o.querySelector('.ytp-plus-settings-section[data-section="advanced"]'); if (t instanceof HTMLElement) { const e = (e, o, r) => { if (Object.hasOwn(y, e)) { return; } const i = t.querySelector(`.ytp-plus-settings-checkbox[data-setting="${o}"]`), a = t.querySelector(r), s = t.querySelector(`.ytp-plus-submenu-toggle[data-submenu="${e}"]`); i instanceof Element && i.classList.contains("ytp-plus-settings-checkbox") && i.checked && a instanceof HTMLElement && (a.style.display = "", a.classList.remove("is-hidden"), s instanceof HTMLElement && s.setAttribute("aria-expanded", "true")); }; e("enhanced", "enableEnhanced", basicSubmenuSelector_("enhanced")), e("music", "enableMusic", basicSubmenuSelector_("music")); } } catch (t) {} try { const t = new Set(Array.from(o.querySelectorAll(".ytp-plus-settings-nav-item")).map(t => t.dataset?.section)), e = o.querySelector(".ytp-plus-settings-nav-item")?.dataset?.section || null, r = t.has(basicUiState_.activeNavSection.read()) ? basicUiState_.activeNavSection.read() : e; if (r) { const t = o.querySelector(`.ytp-plus-settings-nav-item[data-section="${r}"]`); if (t) { o.querySelectorAll(".ytp-plus-settings-nav-item").forEach(t => t.classList.remove("active")), o.querySelectorAll(".ytp-plus-settings-section").forEach(t => { t.classList.add("hidden"), "true" === o.getAttribute("data-ytp-inline-fallback") && t instanceof HTMLElement && (t.style.display = "none"); }), t.classList.add("active"); const e = o.querySelector(`.ytp-plus-settings-section[data-section="${r}"]`); e instanceof HTMLElement && (e.classList.remove("hidden"), "true" === o.getAttribute("data-ytp-inline-fallback") && (e.style.display = "")); try { setTimeout(() => { document.dispatchEvent(new CustomEvent("youtube-plus-settings-section-activated", { detail: { section: r, label: t.dataset?.label || "" }, bubbles: !0 })); }, 0); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } } } } catch (t) {} return o; }, openSettingsModal() { try { this.insertStyles(), window.YouTubePlusDesignSystem?.repairStyles?.(); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } const t = this.getElement(".ytp-plus-settings-modal", !1); if (t) { try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-modal-closed", { bubbles: !0 })); } catch (t) { window.YouTubePlusErrorBoundary?.logError?.(t instanceof Error ? t : new Error(String(t)), { module: "Basic" }); } t.remove(); } if ("function" == typeof this.ensureNonCriticalStyles && this.ensureNonCriticalStyles(), (document.body || document.documentElement).appendChild(this.createSettingsModal()), window.YouTubePlus?.Voting) { const t = window.YouTubePlusDOMCache, e = t?.getElementById?.("ytp-plus-voting-container") || ("undefined" != typeof document ? document.getElementById("ytp-plus-voting-container") : null); e && (window.YouTubePlus.Voting.init(), window.YouTubePlus.Voting.createUI(e)); } try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-modal-opened", { bubbles: !0 })); } catch (t) {} }, waitForElement(t, e = 5e3) { if (!t) { return Promise.resolve(null); } const o = window.YouTubePlusDOMCache; return o && "function" == typeof o.waitForElement ? o.waitForElement(t, e) : new Promise(o => { if ("undefined" == typeof document) { return void o(null); } const r = document.querySelector(t); if (r) { return void o(r); } const i = Date.now(), a = setInterval(() => { const r = document.querySelector(t); if (r) { return clearInterval(a), YouTubeUtils.cleanupManager?.unregisterInterval?.(a), void o(r); } Date.now() - i >= e && (clearInterval(a), YouTubeUtils.cleanupManager?.unregisterInterval?.(a), o(null)); }, 120); YouTubeUtils.cleanupManager?.registerInterval?.(a); }); }, addCustomButtons() { const t = this.getElement(".ytp-right-controls"); t && (this.getElement(".ytp-screenshot-button") || this.addScreenshotButton(t), this.getElement(".ytp-download-button") || this.addDownloadButton(t), this.getElement(".speed-control-btn") || this.addSpeedControlButton(t), this.handleFullscreenChange()); }, addScreenshotButton(t) { const e = window.YouTubePlusScreenshot; e && "function" == typeof e.addButton && e.addButton(this, t); }, addDownloadButton(t) { "undefined" != typeof window && window.YouTubePlusDownloadButton && window.YouTubePlusDownloadButton.createDownloadButtonManager({ settings: this.settings, t: e, getElement: this.getElement.bind(this), YouTubeUtils }).addDownloadButton(t); }, addSpeedControlButton(t) { const e = window.YouTubePlusSpeedControl; e && "function" == typeof e.addButton && e.addButton(this, t); }, applyGuideVisibility() { try { const t = Boolean(YouTubeUtils.storage.get("ytplus.hideGuide", !1)); document.documentElement.classList.toggle("ytp-hide-guide", t); const e = window.YouTubePlusDOMCache?.getElementById?.("ytplus-guide-toggle-btn") || ("undefined" != typeof document ? document.getElementById("ytplus-guide-toggle-btn") : null); if (e) { e.setAttribute("aria-pressed", String(t)); const o = t ? "Show side guide" : "Hide side guide"; e.title = o, e.setAttribute("aria-label", o); } } catch (t) { YouTubePlusLogger?.warn?.("Basic", "applyGuideVisibility failed", t); } }, toggleSideGuide() { try { const t = Boolean(YouTubeUtils.storage.get("ytplus.hideGuide", !1)); YouTubeUtils.storage.set("ytplus.hideGuide", !t), this.applyGuideVisibility(); } catch (t) { YouTubePlusLogger?.warn?.("Basic", "toggleSideGuide failed", t); } }, createGuideToggleButton() { try { if ((() => { const t = window.YouTubePlusDOMCache; return t && "function" == typeof t.getElementById ? !!t.getElementById("ytplus-guide-toggle-btn") : "undefined" != typeof document && !!document.getElementById("ytplus-guide-toggle-btn"); })()) { return; } const t = document.createElement("button"); t.id = "ytplus-guide-toggle-btn", t.type = "button", t.className = "ytplus-guide-toggle-btn", t.setAttribute("aria-pressed", "false"), t.setAttribute("aria-label", "Hide side guide"), t.title = "Hide side guide", t.textContent = "Toggle Guide", t.addEventListener("click", t => { t.preventDefault(), t.stopPropagation(), this.toggleSideGuide(); }), t.addEventListener("keydown", t => { "Enter" !== t.key && " " !== t.key || (t.preventDefault(), this.toggleSideGuide()); }), document.body.appendChild(t), this.applyGuideVisibility(); } catch (t) { YouTubePlusLogger?.warn?.("Basic", "createGuideToggleButton failed", t); } }, captureFrame() { const t = window.YouTubePlusScreenshot; t && "function" == typeof t.capture ? t.capture(this) : YouTubePlusLogger?.warn?.("Basic", "Screenshot module not loaded"); }, showNotification(t, e = 2e3) { YouTubeUtils.NotificationManager.show(t, { duration: e, type: "info" }); }, handleFullscreenChange() { document.querySelectorAll(".ytp-screenshot-button, .ytp-cobalt-button").forEach(t => { t.style.bottom = "0px"; }); }, changeSpeed(t) { const e = window.YouTubePlusSpeedControl; if (e && "function" == typeof e.changeSpeed) { return void e.changeSpeed(this, t); } const o = Number(t); this.speedControl.currentSpeed = o, localStorage.setItem(this.speedControl.storageKey, String(o)); }, applyCurrentSpeed() { const t = window.YouTubePlusSpeedControl; t && "function" == typeof t.applyCurrentSpeed && t.applyCurrentSpeed(this); }, setupVideoObserver() { const t = window.YouTubePlusSpeedControl; t && "function" == typeof t.setupVideoObserver && t.setupVideoObserver(this); }, setupNavigationObserver() { if (this.F) { return; } this.F = !0; let t = location.href; this.D || (this.D = this.handleFullscreenChange.bind(this)), YouTubeUtils.cleanupManager.registerListener(document, "fullscreenchange", this.D), this.R || (this.R = () => { this.insertStyles(), location.href.includes("watch?v=") && this.setupCurrentPage(), this.addSettingsButtonToHeader(); }), YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-finish", this.R); const e = () => { if (t !== location.href) { if (t = location.href, location.href.includes("watch?v=")) { const t = basicSetTimeout_(() => this.setupCurrentPage(), 500); try { YouTubeUtils.cleanupManager?.registerTimeout?.(t); } catch (t) {} } this.addSettingsButtonToHeader(); } }; this.O || (this.O = e), this.B || (this.B = e), YouTubeUtils.cleanupManager.registerListener(window, "popstate", this.O), YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-start", this.B); }, showSpeedIndicator(t) { const e = window.YouTubePlusSpeedControl; e && "function" == typeof e.showSpeedIndicator && e.showSpeedIndicator(this, t); } }, o = YouTubeEnhancer.init.bind(YouTubeEnhancer); try { window.YouTubePlus = window.YouTubePlus || {}, window.YouTubePlus.openSettings = t => { try { return t && "string" == typeof t.section && basicUiState_.lastOpenSection.write(t.section), YouTubeEnhancer.openSettingsModal(), !0; } catch (t) { return YouTubePlusLogger?.warn?.("Basic", "openSettings failed", t), !1; } }, window.YouTubePlus.closeSettings = () => { try { const t = window.YouTubePlusDOMCache, e = t?.querySelector?.(".ytp-plus-settings-modal", document, !0) || ("undefined" != typeof document ? document.querySelector(".ytp-plus-settings-modal") : null); if (e) { try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-modal-closed", { bubbles: !0 })); } catch (t) {} return e.remove(), !0; } return !1; } catch (t) { return YouTubePlusLogger?.warn?.("Basic", "closeSettings failed", t), !1; } }; } catch (t) { YouTubePlusLogger?.warn?.("Basic", "Failed to expose public settings API", t); } (() => { if ("undefined" == typeof window) { return !0; } const t = window; return !t.Z && (t.Z = !0, !0); })() && ("loading" === document.readyState ? document.addEventListener("DOMContentLoaded", o) : o()); })(); const executionScript = () => { function t(t) { return r && "function" == typeof r.createTrustedHTML ? r.createTrustedHTML(t) : t; } if ("undefined" != typeof window && window.__ytpMainExecDone__) { return; } "undefined" != typeof window && (window.__ytpMainExecDone__ = !0); const e = "undefined" != typeof window && window.YouTubePlusLogger?.createLogger ? window.YouTubePlusLogger.createLogger("Tabview") : { error: console.error, warn: console.warn, info: console.log, debug: () => {}, log: console.log }, o = "undefined" != typeof window ? window.YouTubePlusCleanupManager : null, r = "undefined" != typeof window && window.YouTubeSafeDOM, i = "undefined" != typeof window && window.YouTubePlusMutationCoordinator, a = 16, s = 32, c = 64, l = 128, d = 4096; if ("undefined" != typeof trustedTypes && null === trustedTypes.defaultPolicy) { const x = r && "function" == typeof r.getTrustedTypesPolicy ? r.getTrustedTypesPolicy() : null; let k = !1; const S = t => { if (k) { return "string" == typeof t ? t : String(t ?? ""); } k = !0; try { const e = "string" == typeof t ? t : String(t ?? ""); return x && "function" == typeof x.createHTML ? x.createHTML(e) : e; } finally { k = !1; } }, T = t => { const e = "string" == typeof t ? t : String(t ?? ""); return x && "function" == typeof x.createScriptURL ? x.createScriptURL(e) : e; }; try { trustedTypes.createPolicy("default", { createHTML: S, createScriptURL: T, createScript: () => { throw new Error("Script creation not allowed by YouTube Plus TT policy"); } }); } catch (L) {} } let u = null; try { const M = document.createElement("div"); r && "function" == typeof r.createFragment ? M.appendChild(r.createFragment(t("1"))) : M.textContent = t("1"); } catch (C) { u = C; } if (u) { e.error("trustHTMLErr", u); } else { try { let E = 0; if ("undefined" == typeof CustomElementRegistry) { return; } if (CustomElementRegistry.prototype.define000) { return; } if ("function" != typeof CustomElementRegistry.prototype.define) { return; } const z = HTMLElement.prototype.constructor, _ = (t, e) => z.prototype.querySelector.call(t, e), I = (t, o) => { if (t) { for (const t of Object.keys(o)) { o[t] || (e.warn(`defineProperties ERROR: Property ${t} is undefined`), delete o[t]); } return Object.defineProperties(t, o); } e.warn("defineProperties ERROR: Prototype is undefined"); }, A = function(...t) { let e = this.firstChild; for (;e; ) { const t = e.nextSibling; e.remove(), e = t; } this.append(...t); }, P = Object.getOwnPropertyDescriptors(DocumentFragment.prototype); P.replaceChildren ? I(DocumentFragment.prototype, { replaceChildren000: P.replaceChildren }) : DocumentFragment.prototype.replaceChildren000 = A; const j = Object.getOwnPropertyDescriptors(Node.prototype); j.appendChild000 || j.insertBefore000 || I(Node.prototype, { appendChild000: j.appendChild, insertBefore000: j.insertBefore }); const H = Object.getOwnPropertyDescriptors(Element.prototype); if (!H.setAttribute000 && !H.querySelector000) { const Ne = { setAttribute000: H.setAttribute, getAttribute000: H.getAttribute, hasAttribute000: H.hasAttribute, removeAttribute000: H.removeAttribute, querySelector000: H.querySelector }; H.replaceChildren ? Ne.replaceChildren000 = H.replaceChildren : Element.prototype.replaceChildren000 = A, I(Element.prototype, Ne); } Element.prototype.setAttribute111 = function(t, e) { e = `${e}`, this.getAttribute000(t) !== e && this.setAttribute000(t, e); }, Element.prototype.incAttribute111 = function(t) { let e = +this.getAttribute000(t) || 0; return e = e > 1e9 ? 9 : e + 1, this.setAttribute000(t, `${e}`), e; }, Element.prototype.assignChildren111 = function(t, e, o) { let r = []; for (let t = this.firstChild; t instanceof Node; t = t.nextSibling) { t !== e && r.push(t); } if (de = !0, e.parentNode === this) { let i = new DocumentFragment; r.length > 0 && i.replaceChildren000(...r), t && t.length > 0 && (i.replaceChildren000(...t), this.insertBefore000(i, e)), o && o.length > 0 && (i.replaceChildren000(...o), this.appendChild000(i)), i.replaceChildren000(), i = null; } else { t || (t = []), o || (o = []), this.replaceChildren000(...t, e, ...o); } if (de = !1, r.length > 0) { for (const t of r) { t instanceof Element && !1 === t.isConnected && t.remove(); } } r.length = 0, r = null; }; let D = 0; const O = t => { if (D) { let e, o; D++; try { o = t(); } catch (t) { e = t; } if (D--, e) { throw e; } return o; } { const e = document.querySelector("#secondary-inner"), o = document.querySelector("secondary-wrapper#secondary-inner-wrapper"); if (e && o) { let r, i; D++, e.id = "secondary-inner-", o.id = "secondary-inner"; try { i = t(); } catch (t) { r = t; } if (e.id = "secondary-inner", o.id = "secondary-inner-wrapper", D--, r) { throw r; } return i; } return t(); } }, B = !0; (() => { const t = "undefined" != typeof unsafeWindow ? unsafeWindow : this instanceof Window ? this : window; if (!t.V) { let r = 4; class n extends Set { add(t) { if (r <= 0) { return e.warn("yt.config_ is already applied on the page."); } "function" == typeof t && super.add(t); } } let i = (async () => {})().constructor, a = t.V = new n, s = () => { const e = t.ytcsi.originalYtcsi; e && (t.ytcsi = e, s = null); }, c = null, l = () => { if (r >= 1) { const e = (t.yt || 0).config_ || (t.ytcfg || 0).data_ || 0; if ("string" == typeof e.INNERTUBE_API_KEY && "object" == typeof e.EXPERIMENT_FLAGS) { for (const t of (--r <= 0 && s && s(), c = !0, a)) { t(e); } } } }, d = 1, u = e => { if (e = e || t.ytcsi) { return t.ytcsi = new Proxy(e, { get: (t, e) => "originalYtcsi" === e ? t : (l(), c && --d <= 0 && s?.(), t[e]) }), !0; } }; u() || Object.defineProperty(t, "ytcsi", { get() {}, set: e => (e && (delete t.ytcsi, u(e)), !0), enumerable: !1, configurable: !0 }); const {addEventListener: p, removeEventListener: y} = Document.prototype; function o(e) { l(), e && t.removeEventListener("DOMContentLoaded", o, !1); } new i(t => { if ("undefined" != typeof AbortSignal) { p.call(document, "yt-page-data-fetched", t, { once: !0 }), p.call(document, "yt-navigate-finish", t, { once: !0 }), p.call(document, "spfdone", t, { once: !0 }); } else { const e = () => { t(), y.call(document, "yt-page-data-fetched", e, !1), y.call(document, "yt-navigate-finish", e, !1), y.call(document, "spfdone", e, !1); }; p.call(document, "yt-page-data-fetched", e, !1), p.call(document, "yt-navigate-finish", e, !1), p.call(document, "spfdone", e, !1); } }).then(l), new i(t => { if ("undefined" != typeof AbortSignal) { p.call(document, "yt-action", t, { once: !0, capture: !0 }); } else { const e = () => { t(), y.call(document, "yt-action", e, !0); }; p.call(document, "yt-action", e, !0); } }).then(l), i.resolve().then(() => { "loading" !== document.readyState ? o() : t.addEventListener("DOMContentLoaded", o, !1); }); } })(); let R = !1; window.V.add(t => { if (R) { return; } R = !0; const e = t.EXPERIMENT_FLAGS || 0, o = t.EXPERIMENTS_FORCED_FLAGS || 0; for (const t of [ e, o ]) { t && (t.web_watch_chat_hide_button_killswitch = !1, t.web_watch_theater_chat = !1, t.suppress_error_204_logging = !0, t.kevlar_watch_grid = !1, B && (t.enable_shadydom_free_scoped_node_methods = !1, t.enable_shadydom_free_scoped_query_methods = !1, t.enable_shadydom_free_scoped_readonly_properties_batch_one = !1, t.enable_shadydom_free_parent_node = !1, t.enable_shadydom_free_children = !1, t.enable_shadydom_free_last_child = !1)); } }); const F = "function" == typeof WeakRef ? t => t ? new WeakRef(t) : null : t => t || null, N = t => t?.deref ? t.deref() : t, Z = (async () => {})().constructor, V = t => new Z(e => setTimeout(e, t)), Y = t => t ? t.polymerController || t.inst || t || 0 : t || 0, q = setTimeout.bind(window), G = t => !1 === t.paused && t.readyState > 2 && !t.ended, W = function(t) { let e = this; for (;e; ) { if (e.matches(t)) { return e; } e = e.parentElement || (e.getRootNode() instanceof ShadowRoot ? e.getRootNode().host : null); } return null; }, J = function(t) { const e = this.querySelector(t); if (e) { return e; } const o = this.querySelectorAll("*"); for (const e of o) { const o = e.shadowRoot; if (o) { const e = o.querySelector(t); if (e) { return e; } } } return null; }, K = t => { let e = t; for (;e; ) { const t = e.parentElement; if (!t) { break; } if ("YTD-COMMENTS" === t.nodeName || "YTD-ITEM-SECTION-RENDERER" === t.nodeName) { const o = Array.from(t.children).indexOf(e); if (o >= 0) { return { parent: t, index: o }; } } e = t; } return null; }, X = ((t, e) => { const o = (o, r) => { t = o, e = r; }; return class PromiseExternal extends Z { constructor(r = o) { super(r), r === o && (this.resolve = t, this.reject = e); } }; })(), Q = "undefined" != typeof globalThis && globalThis.nextBrowserTick ? globalThis.nextBrowserTick : null, tt = Q && Q.version >= 2 ? Q : (() => { const t = "undefined" != typeof self ? self : "undefined" != typeof global ? global : this, o = "undefined" != typeof location && location.origin || "*"; let r = !0; if (!(function e(i) { return i ? r = !1 : t.postMessage && !t.importScripts && t.addEventListener ? (t.addEventListener("message", e, !1), t.postMessage("$$$", o), t.removeEventListener("message", e, !1), r) : void 0; })()) { return void e.warn("Your browser environment cannot use nextBrowserTick"); } const i = (async () => {})().constructor; let a = null; const s = new Map, {floor: c, random: l} = Math; let d; do { d = `$$nextBrowserTick$$${(l() + 8).toString().slice(2)}$$`; } while (d in t); const u = d, p = u.length + 9; t[u] = 1, t.addEventListener("message", t => { if (0 !== s.size) { const e = (t || 0).data; if ("string" == typeof e && e.length === p && t.source === (t.target || 1) && (!t.origin || t.origin === o)) { const t = s.get(e); t && ("p" === e[0] && (a = null), s.delete(e), t()); } } }, !1); const y = (e = s) => { if (e === s) { if (a) { return a; } let e; do { e = `p${u}${c(314159265359 * l() + 314159265359).toString(36)}`; } while (s.has(e)); return a = new i(t => { s.set(e, t); }), t.postMessage(e, o), e = null, a; } { let r; do { r = `f${u}${c(314159265359 * l() + 314159265359).toString(36)}`; } while (s.has(r)); s.set(r, e), t.postMessage(r, o); } }; return y.version = 2, y; })(); "undefined" != typeof globalThis && (globalThis.nextBrowserTick = tt); const et = !("function" == typeof IntersectionObserver) || { capture: !0, passive: !0 }; class Attributer { constructor(t) { this.list = t, this.flag = 0; } makeString() { let t = 1, e = "", o = 0; for (;this.flag >= t; ) { this.flag & t && (e += this.list[o]), o++, t <<= 1; } return e; } } const nt = new Attributer("icp"), ot = new WeakMap, rt = new Proxy({ related: null, comments: null, infoExpander: null }, { get: (t, e) => N(t[e]), set(t, e, o) { if (o) { let r = ot.get(o); r || (r = F(o), ot.set(o, r)), t[e] = r; } else { t[e] = null; } return !0; } }), it = () => { const t = rt.infoExpander; return t && (t.matches("[tyt-main-info]") ? t : t.querySelector000("[tyt-main-info]")) || null; }; let at = null; const st = window.YouTubePlusI18n?.t || (t => t), ct = '<path d="M80 27H12A12 12 90 0 0 0 39v42a12 12 90 0 0 12 12h12v20a2 2 90 0 0 3.4 2L47 93h33a12 12 90 0 0 12-12V39a12 12 90 0 0-12-12zM20 47h26a2 2 90 1 1 0 4H20a2 2 90 1 1 0-4zm52 28H20a2 2 90 1 1 0-4h52a2 2 90 1 1 0 4zm0-12H20a2 2 90 1 1 0-4h52a2 2 90 1 1 0 4zm36-58H40a12 12 90 0 0-12 12v6h52c9 0 16 7 16 16v42h0v4l7 7a2 2 90 0 0 3-1V71h2a12 12 90 0 0 12-12V17a12 12 90 0 0-12-12z"/>', lt = '<path d="M89 10c0-4-3-7-7-7H7c-4 0-7 3-7 7v70c0 4 3 7 7 7h75c4 0 7-3 7-7V10zm-62 2h13v10H27V12zm-9 66H9V68h9v10zm0-56H9V12h9v10zm22 56H27V68h13v10zm-3-25V36c0-2 2-3 4-2l12 8c2 1 2 4 0 5l-12 8c-2 1-4 0-4-2zm25 25H49V68h13v10zm0-56H49V12h13v10zm18 56h-9V68h9v10zm0-56h-9V12h9v10z"/>', dt = '<path d="M30 0C13.3 0 0 13.3 0 30s13.3 30 30 30 30-13.3 30-30S46.7 0 30 0zm6.2 46.6c-1.5.5-2.6 1-3.6 1.3a10.9 10.9 0 0 1-3.3.5c-1.7 0-3.3-.5-4.3-1.4a4.68 4.68 0 0 1-1.6-3.6c0-.4.2-1 .2-1.5a20.9 20.9 90 0 1 .3-2l2-6.8c.1-.7.3-1.3.4-1.9a8.2 8.2 90 0 0 .3-1.6c0-.8-.3-1.4-.7-1.8s-1-.5-2-.5a4.53 4.53 0 0 0-1.6.3c-.5.2-1 .2-1.3.4l.6-2.1c1.2-.5 2.4-1 3.5-1.3s2.3-.6 3.3-.6c1.9 0 3.3.6 4.3 1.3s1.5 2.1 1.5 3.5c0 .3 0 .9-.1 1.6a10.4 10.4 90 0 1-.4 2.2l-1.9 6.7c-.2.5-.2 1.1-.4 1.8s-.2 1.3-.2 1.6c0 .9.2 1.6.6 1.9s1.1.5 2.1.5a6.1 6.1 90 0 0 1.5-.3 9 9 90 0 0 1.4-.4l-.6 2.2zm-3.8-35.2a1 1 0 010 8.6 1 1 0 010-8.6z"/>', ut = '<path d="M0 3h12v2H0zm0 4h12v2H0zm0 4h8v2H0zm16 0V7h-2v4h-4v2h4v4h2v-4h4v-2z"/>', pt = (t, e, o, r, i, a) => `<svg${a ? ` class=${a}` : ""} width="${t}" height="${e}" viewBox="0 0 ${o} ${r}" preserveAspectRatio="xMidYMid meet">${i}</svg>`, yt = 0; function p() { const t = `${pt(16, 16, 90, 90, lt)}<span>${st("videos")}</span>`, e = `${pt(16, 16, 60, 60, dt)}<span>${st("info")}</span>`, o = `${pt(16, 16, 20, 20, ut)}<span>${st("playlist")}</span>`, r = '\n <paper-ripple class="style-scope yt-icon-button">\n <div id="background" class="style-scope paper-ripple" style="opacity:0;"></div>\n <div id="waves" class="style-scope paper-ripple"></div>\n </paper-ripple>\n ', i = '\n <div class="font-size-right">\n <div class="font-size-btn font-size-plus" tyt-di="8rdLQ">\n <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"\n stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">\n <path d="M12 25H38M25 12V38"/>\n </svg>\n </div><div class="font-size-btn font-size-minus" tyt-di="8rdLQ">\n <svg width="12" height="12" viewbox="0 0 50 50" preserveAspectRatio="xMidYMid meet"\n stroke="currentColor" stroke-width="6" stroke-linecap="round" vector-effect="non-scaling-size">\n <path d="M12 25h26"/>\n </svg>\n </div>\n </div>\n '.replace(/[\r\n]+/g, ""); return `\n <div id="right-tabs">\n <tabview-view-pos-thead></tabview-view-pos-thead>\n <header>\n <div id="material-tabs">\n ${[ `<a id="tab-btn1" tyt-di="q9Kjc" tyt-tab-content="#tab-info" class="tab-btn${1 & ~yt ? "" : " tab-btn-hidden"}">${e}${r}${i}</a>`, `<a id="tab-btn3" tyt-di="q9Kjc" tyt-tab-content="#tab-comments" class="tab-btn${2 & ~yt ? "" : " tab-btn-hidden"}">${pt(16, 16, 120, 120, ct)}<span id="tyt-cm-count"></span>${r}${i}</a>`, `<a id="tab-btn4" tyt-di="q9Kjc" tyt-tab-content="#tab-videos" class="tab-btn${4 & ~yt ? "" : " tab-btn-hidden"}">${t}${r}${i}</a>`, `<a id="tab-btn5" tyt-di="q9Kjc" tyt-tab-content="#tab-list" class="tab-btn tab-btn-hidden">${o}${r}${i}</a>` ].join("")}\n </div>\n </header>\n <div class="tab-content">\n <div id="tab-info" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>\n <div id="tab-comments" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>\n <div id="tab-videos" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>\n <div id="tab-list" class="tab-content-cld tab-content-hidden" tyt-hidden userscript-scrollbar-render></div>\n </div>\n </div>\n `; } const mt = () => { try { const t = window.YouTubePlusI18n?.getLanguage?.() || document.documentElement?.lang || "en"; document.documentElement?.setAttribute("data-ytplus-lang", t); } catch (t) {} }, ft = {}, bt = new Proxy(ft, { get: (t, e) => t[e] || 0, set: () => !0 }), ht = new Proxy(ft, { get: (t, e) => (t[e] > 1e9 && (t[e] = 9), t[e] = (t[e] || 0) + 1), set: () => !0 }); let gt = new X, wt = new X, vt = !1, xt = new X, kt = new X; const St = () => { vt = !1, gt = new X, wt = new X, xt = new X, kt = new X, rt.related = null, rt.comments = null, rt.infoExpander = null, rt.flexy = null, rt.chat = null, rt.playlist = null, Z.all([ gt, wt ]).then(Ae.onceInsertRightTabs).catch(e.warn), Z.all([ wt, kt ]).then(Ae.onceInfoExpanderElementProvidedPromised).catch(e.warn); }, Tt = {}, Lt = t => { const o = [], r = new Set; for (const e of t) { let t = ""; switch (e.attributeName) { case "data-ytlstm-new-layout": case "data-ytlstm-overlay-text-shadow": case "data-ytlstm-theater-mode": t = "external.ytlstm", r.add(t); } t && !Tt[t] && (Tt[t] = !0, o.push(t)); } rt.flexy && r.has("external.ytlstm") && rt.flexy.setAttribute("tyt-external-ytlstm", document.querySelector("[data-ytlstm-theater-mode]") ? "1" : "0"); for (const t of o) { const o = ge[`${t}`]; o ? o.activate() : e.warn(`No Plugin Activator for ${t}`); } }; if (i?.subscribeRoot) { i.subscribeRoot("main::pluginDetect", Lt, { selector: "html, body", attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "data-ytlstm-new-layout", "data-ytlstm-overlay-text-shadow", "data-ytlstm-theater-mode" ] }); } else { const Ze = new MutationObserver(Lt); Ze.observe(document.documentElement, { attributes: !0 }), document.body && Ze.observe(document.body, { attributes: !0 }), o?.registerObserver?.(Ze), wt.then(() => { Ze.observe(document.documentElement, { attributes: !0 }), document.body && Ze.observe(document.body, { attributes: !0 }); }); } const Mt = function() { const t = this.content || this.$.content; this.canToggle = this.shouldUseNumberOfLines && (this.alwaysCollapsed || this.collapsed || !1 === this.isToggled) ? this.alwaysToggleable || this.isToggled || t && t.offsetHeight < t.scrollHeight : this.alwaysToggleable || this.isToggled || t && t.scrollHeight > this.collapsedHeight; }, $t = async t => { if (bt.aoChatAttrAsyncLock !== t) { return; } const e = rt.chat, o = rt.flexy; if (e && o) { const t = e.hasAttribute000("collapsed"); t ? o.setAttribute111("tyt-chat-collapsed", "") : o.removeAttribute000("tyt-chat-collapsed"), o.setAttribute111("tyt-chat", t ? "-" : "+"); } }, Ct = async t => { if (bt.aoPlayListAttrAsyncLock !== t) { return; } const e = rt.playlist, o = rt.flexy; let r = 0; e && o ? r = e.closest("[hidden]") || e.hasAttribute000("collapsed") ? 2 : 1 : o && (r = 2), 1 === r ? "" !== o.getAttribute000("tyt-playlist-expanded") && o.setAttribute111("tyt-playlist-expanded", "") : 2 === r && o.hasAttribute000("tyt-playlist-expanded") && o.removeAttribute000("tyt-playlist-expanded"); }, Et = () => { Z.resolve(ht.aoChatAttrAsyncLock).then($t).catch(e.warn); }; let zt = null; const _t = () => { Z.resolve(ht.aoPlayListAttrAsyncLock).then(Ct).catch(e.warn); }; let It = null; const At = async t => { const o = rt.comments, r = rt.flexy; if (!o) { return; } let i = !1, a = !1, s = !1; for (const e of t) { "hidden" === e.attributeName && e.target === o ? i = !0 : "tyt-comments-video-id" === e.attributeName && e.target === o ? a = !0 : "tyt-comments-data-status" === e.attributeName && e.target === o && (s = !0); } if (i && (o.hasAttribute000("hidden") || Z.resolve(o).then(Ae.settingCommentsVideoId).catch(e.warn), Z.resolve(ht.removeKeepCommentsScrollerLock).then(re).catch(e.warn)), (i || a || s) && r) { const t = +o.getAttribute000("tyt-comments-data-status"); 2 === t ? r.setAttribute111("tyt-comment-disabled", "") : 1 === t && r.removeAttribute000("tyt-comment-disabled"), Z.resolve(ht.checkCommentsShouldBeHiddenLock).then(Ae.checkCommentsShouldBeHidden).catch(e.warn); const i = ht.rightTabReadyLock01; if (await xt.then(), bt.rightTabReadyLock01 !== i) { return; } if (rt.comments !== o) { return; } if (!1 === o.isConnected) { return; } if (o.closest("#tab-comments")) { const t = !o.closest("[hidden]"); document.querySelector('[tyt-tab-content="#tab-comments"]').classList.toggle("tab-btn-hidden", !t); } } }; let Pt = null; const Ut = new IntersectionObserver(t => { for (const e of t) { const t = e.target, o = Y(t); if (e.isIntersecting && t instanceof z && "function" == typeof o.calculateCanCollapse) { o.calculateCanCollapse(!0), t.setAttribute111("io-intersected", ""); const e = rt.flexy; e && !e.hasAttribute000("keep-comments-scroller") && e.setAttribute111("keep-comments-scroller", ""); } else { t.hasAttribute000("io-intersected") && t.removeAttribute000("io-intersected"); } } }, { threshold: [ 0 ], rootMargin: "32px" }); let jt = !1, Ht = 0; const Dt = new ResizeObserver(t => { const e = Math.round(t[t.length - 1].borderBoxSize[0].inlineSize); Ht !== e && (Ht = e, 2 & ~Bt ? jt = !0 : (jt = !1, Z.resolve(1).then(Ae.fixForTabDisplay))); }), Ot = t => { "string" == typeof t && (t = document.querySelector(`a[tyt-tab-content="${t}"]`) || null); const e = rt.flexy, o = document.querySelectorAll("#material-tabs a[tyt-tab-content]"); for (const e of o) { const o = document.querySelector(e.getAttribute000("tyt-tab-content")); e && o && (e !== t ? (e.classList.remove("active"), o.classList.add("tab-content-hidden"), o.hasAttribute000("tyt-hidden") || o.setAttribute111("tyt-hidden", "")) : (e.classList.add("active"), o.hasAttribute000("tyt-hidden") && o.removeAttribute000("tyt-hidden"), o.classList.remove("tab-content-hidden"))); } const r = t ? t.getAttribute000("tyt-tab-content") : ""; r && (ee = te = r), "" === e.getAttribute000("tyt-chat") && e.removeAttribute000("tyt-chat"), e.setAttribute111("tyt-tab", r), r && (jt = !1, Z.resolve(0).then(Ae.fixForTabDisplay)); }; let Bt = 0; const Rt = (t, e) => { const o = rt.flexy; return o ? (1 & e && (t |= 1, o.hasAttribute000("theater") || (t -= 1)), 2 & e && (t |= 2, o.getAttribute000("tyt-tab") || (t -= 2)), 4 & e && (t |= 4, "-" !== o.getAttribute000("tyt-chat") && (t -= 4)), 8 & e && (t |= 8, "+" !== o.getAttribute000("tyt-chat") && (t -= 8)), e & a && (t |= a, o.hasAttribute000("is-two-columns_") || (t -= a)), e & s && (t |= s, o.hasAttribute000("tyt-egm-panel_") || (t -= s)), e & c && (t |= c, document.fullscreenElement || (t -= c)), e & l && (t |= l, o.hasAttribute000("tyt-playlist-expanded") || (t -= l)), e & d && (t |= d, "1" !== o.getAttribute("tyt-external-ytlstm") && (t -= d)), t) : t; }; function y() { if ((function() { const t = rt.flexy; return t?.hasAttribute000("theater"); })()) { const t = document.querySelector("ytd-watch-flexy #ytd-player button.ytp-size-button"); t && t.click(); } } function m(t) { const e = document.querySelectorAll(t); let o = -1, r = -1; for (let t = 0, i = e.length; t < i; t++) { const i = e[t].getElementsByTagName("*").length; i > r && (r = i, o = t); } return o >= 0 ? e[o] : null; } function f() { const t = m("ytd-live-chat-frame#chat"), e = Y(t); if (e && "boolean" == typeof e.collapsed) { if ("function" == typeof e.setCollapsedState && (e.setCollapsedState({ setLiveChatCollapsedStateAction: { collapsed: !1 } }), !1 === e.collapsed)) { return; } if (e.collapsed = !1, !1 === e.collapsed) { return; } !0 === e.isHiddenByUser && !0 === e.collapsed && (e.isHiddenByUser = !1, e.collapsed = !1); } let o = document.querySelector("ytd-live-chat-frame#chat[collapsed] > .ytd-live-chat-frame#show-hide-button"); o && (o = o.querySelector000("div.yt-spec-touch-feedback-shape") || o.querySelector000("ytd-toggle-button-renderer"), o && o.click()); } function b() { const t = m("ytd-live-chat-frame#chat"), e = Y(t); if (e && "boolean" == typeof e.collapsed) { if ("function" == typeof e.setCollapsedState && (e.setCollapsedState({ setLiveChatCollapsedStateAction: { collapsed: !0 } }), !0 === e.collapsed)) { return; } if (e.collapsed = !0, !0 === e.collapsed) { return; } !1 === e.isHiddenByUser && !1 === e.collapsed && (e.isHiddenByUser = !0, e.collapsed = !0); } let o = document.querySelector("ytd-live-chat-frame#chat:not([collapsed]) > .ytd-live-chat-frame#show-hide-button"); o && (o = o.querySelector000("div.yt-spec-touch-feedback-shape") || o.querySelector000("ytd-toggle-button-renderer"), o && o.click()); } function h(t) { if (!t) { return; } "length" in t || (t = [ t ]); const e = rt.flexy; if (!e) { return; } let o = []; for (const e of t) { if (!e) { continue; } const t = e.panelId, r = e.toHide, i = e.toShow; !0 !== r || i ? !0 !== i || r || o.push({ showEngagementPanelEndpoint: { panelIdentifier: t } }) : o.push({ hideEngagementPanelEndpoint: { panelIdentifier: t } }); } o.length > 0 && Y(e).resolveCommand({ signalServiceEndpoint: { signal: "CLIENT_SIGNAL", actions: o } }, {}, !1), o = null; } function g(t) { const e = Y(t), o = (e.data || 0).panelIdentifier; if (o && "string" == typeof o) { return o; } const r = ((e.data || 0).identifier || 0).tag; if (r && "string" == typeof r) { return r; } const i = (e.data || 0).targetId; return i && "string" == typeof i ? i : t.getAttribute000("target-id") || ""; } function w() { const t = []; for (const e of document.querySelectorAll("ytd-watch-flexy[tyt-tab] #panels.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility]:not([hidden])")) { if ("ENGAGEMENT_PANEL_VISIBILITY_EXPANDED" === e.getAttribute("visibility") && !e.closest("[hidden]")) { const o = g(e); t.push({ panelId: o, toHide: !0 }); } } h(t); } function v() { const t = Y(rt.playlist); t && "boolean" == typeof t.collapsed && (t.collapsed = !0); } const Ft = function() { "ytd-watch-grid" !== this.is && O(() => { this.updatePageMediaQueries(), this.schedulePlayerSizeUpdate_(); }); }, Nt = new WeakMap, Zt = document.createElement("noscript"), Vt = Symbol(), Yt = Symbol(), qt = Symbol(), Gt = async function() { const t = N(this); if (!t) { return; } const e = Y(t), o = e.data ? e.data[Vt] || 1 : 0; e[qt] !== o && (e[qt] = o > 0 ? e.data[Vt] = Date.now() : 0, await Z.resolve(), Jt(t, "tyt-data-change-counter")); }, Wt = function(t) { const e = N(this); if (!e) { return; } const o = N(e[Yt] || null) || null; if (!o) { return; } const r = Y(e), i = Y(o); if (t) { let a = !1; for (const e of t) { ("tyt-clone-refresh-count" === e.attributeName && e.target === o || "tyt-data-change-counter" === e.attributeName && e.target === o) && (a = !0); } a && i.data && (e.replaceWith(Zt), r.data = Object.assign({}, i.data), Zt.replaceWith(e)); } }, Jt = (t, e) => { let o = (+t.getAttribute000(e) || 0) + 1; return o > 1e9 && (o = 9), t.setAttribute000(e, o), o; }, Kt = t => "string" == typeof t && 24 === t.length && /UC[-_a-zA-Z0-9+=.]{22}/.test(t), Xt = t => { if (null !== t && bt.infoFixLock !== t) { return; } const r = rt.infoExpander, a = (r ? r.parentNode : null) || document.querySelector("#tab-info"), s = rt.flexy; if (!a || !s) { return; } if (r && !r.matches("#tab-info > [class]") && !r.matches("#tab-info > [tyt-main-info]")) { return; } const c = [ ...document.querySelectorAll('ytd-watch-metadata.ytd-watch-flexy div[slot="extra-content"] > *, ytd-watch-metadata.ytd-watch-flexy #extra-content > *') ].filter(t => "string" == typeof t.is).map(t => { const e = t.is; for (;t instanceof z; ) { const o = [ ...t.querySelectorAll(e) ].filter(t => Y(t).data); if (o.length >= 1) { return o[0]; } t = t.parentNode; } }).filter(t => !!t && "string" == typeof t.is).map(t => { const e = Y(t); return { data: e.data, tag: e.is, elm: t }; }); let l = document.querySelector("noscript#aythl"); l || (l = document.createElement("noscript"), l.id = "aythl", de = !0, s.insertBefore000(l, s.firstChild), de = !1); const d = l; let u = !1; const p = new Set, y = a; for (const {data: t, tag: r, elm: a} of c) { let s = Nt.get(a); if (s = s ? N(s) : s, s) { s.parentNode !== y && (u = !0); } else { const t = Y(a), c = t.constructor.prototype, l = document.createElement(r); d.appendChild(l), s = l, s[Yt] = F(a); const p = F(s), y = `main::moChangeReflection:${a.dataset?.tytSrcId || ++_e}`; if (i?.watchTarget) { i.watchTarget(y, a, Wt.bind(p), { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "tyt-clone-refresh-count", "tyt-data-change-counter" ] }); } else { const t = new MutationObserver(Wt.bind(p)); t.observe(a, { attributes: !0, attributeFilter: [ "tyt-clone-refresh-count", "tyt-data-change-counter" ] }), o?.registerObserver?.(t); } if (a.jy8432 = 1, c instanceof Node || c.Y || "function" != typeof c.q) { if (!(c instanceof Node || c.Y) && !0 === c.useSignals && Y(a).signalProxy) { const o = t?.signalProxy?.signalCache?.data; !o || "function" != typeof o.setWithPath || o.setWithPath573 || o.controller573 || (o.controller573 = F(t), o.setWithPath573 = o.setWithPath, o.setWithPath = function() { const t = N(this.controller573 || null) || null; return t && "function" == typeof t.G && Z.resolve(t).then(t.G).catch(e.warn), this.setWithPath573(...arguments); }, c.Y = function() { const t = this.hostElement || this; t.jy8432 && Jt(t, "tyt-data-change-counter"); }, c.G = t => t.Y()); } } else { c.Y = function() { const t = this.hostElement || this; t.jy8432 && Jt(t, "tyt-data-change-counter"); }, c.q("data", "_dataChanged496", void 0); } if (!c.Y) { const t = "main::monitorDataChanged:" + ++Ie; if (i?.watchTarget) { i.watchTarget(t, a, Gt.bind(s[Yt]), { attributes: !0, childList: !0, subtree: !0 }); } else { const t = new MutationObserver(Gt.bind(s[Yt])); t.observe(a, { attributes: !0, childList: !0, subtree: !0 }), o?.registerObserver?.(t); } } Nt.set(a, p), u = !0; } u || Y(s).data !== t && (u = !0), p.add(s), c.mirrored = s; } const m = [ ...p ]; if (p.clear(), !u) { let t = r ? -1 : 0; for (let e = y.firstChild; e instanceof Node; e = e.nextSibling) { const o = t < 0 ? r : m[t]; if (t++, e !== o) { u = !0; break; } } u || t === m.length + 1 || (u = !0); } if (u) { r ? y.assignChildren111(null, r, m) : y.replaceChildren000(...m); for (const t of m) { const e = Jt(t, "tyt-clone-refresh-count"), o = N(t[Yt] || null) || null; o && o.setAttribute111("tyt-clone-refresh-count", e); } } m.length = 0, c.length = 0; }, Qt = t => { if (bt.layoutFixLock !== t) { return; } const e = document.querySelector("#secondary-inner.style-scope.ytd-watch-flexy > secondary-wrapper"); if (e) { const t = e.parentNode, o = document.querySelector("#columns.style-scope.ytd-watch-flexy [tyt-chat-container]"); if (t.firstChild !== t.lastChild || o && !o.closest("secondary-wrapper")) { const r = [], i = []; for (let a = t.firstChild; a instanceof Node; a = a.nextSibling) { if (a === o && o) {} else if (a === e) { for (let t = e.firstChild; t instanceof Node; t = t.nextSibling) { t === o && o || ("right-tabs" === t.id && o && i.push(o), i.push(t)); } } else { r.push(a); } } de = !0, e.replaceChildren000(...r, ...i), de = !1; const a = rt.chat, s = Y(a); s && "function" == typeof s.urlChanged && e.contains(a) && ("function" == typeof s.urlChangedAsync12 ? s.urlChanged() : setTimeout(() => s.urlChanged(), 136)); } } }; let te = "", ee = ""; const ne = () => { Z.resolve(ht.updateEgmPanelsLock).then(ie).catch(e.warn); }; let oe = null; const re = async t => { if (bt.removeKeepCommentsScrollerLock !== t) { return; } if (await Z.resolve(), bt.removeKeepCommentsScrollerLock !== t) { return; } const e = rt.flexy; e && e.removeAttribute000("keep-comments-scroller"); }, ie = async t => { if (t !== bt.updateEgmPanelsLock) { return; } if (await wt.then().catch(e.warn), t !== bt.updateEgmPanelsLock) { return; } const o = rt.flexy; if (!o) { return; } let r = [], i = [], a = []; for (const t of document.querySelectorAll("[tyt-egm-panel][target-id][visibility]")) { const e = t.getAttribute000("visibility"); "ENGAGEMENT_PANEL_VISIBILITY_HIDDEN" === e || t.closest("[hidden]") ? t.hasAttribute000("tyt-visible-at") && (t.removeAttribute000("tyt-visible-at"), i.push(t)) : "ENGAGEMENT_PANEL_VISIBILITY_EXPANDED" !== e || t.closest("[hidden]") || (t.getAttribute000("tyt-visible-at") || (t.setAttribute111("tyt-visible-at", Date.now()), r.push(t)), a.push(t)); } if (r.length >= 1 && a.length >= 2) { const t = r[r.length - 1], e = []; for (const o of a) { if (o === t) { continue; } const r = g(o); e.push({ panelId: r, toHide: !0 }); } e.length >= 1 && h(e); } a.length >= 1 ? o.setAttribute111("tyt-egm-panel_", "") : o.removeAttribute000("tyt-egm-panel_"), r.length = 0, r = null, i.length = 0, i = null, a.length = 0, a = null; }, ae = (t, e) => { for (const o of document.querySelectorAll(t)) { if (!o.closest(e)) { return o; } } return null; }; let se = 0; const {handleNavigateFactory: ce} = (() => { function t(t) { if (1 === arguments.length) { const e = document.querySelector(`#tab-comments ytd-comments ytd-comment-renderer #header-author a[href*="lc=${t}"]`); if (e) { const o = W.call(e, "ytd-comment-renderer"); if (o && t) { return { lc: t, commentRendererElm: o }; } } } else if (0 === arguments.length) { const e = document.querySelector("#tab-comments ytd-comments ytd-comment-renderer > #linked-comment-badge span:not(:empty)"); if (e) { const o = W.call(e, "ytd-comment-renderer"); if (o) { const e = J.call(o, "#header-author"); if (e) { const o = J.call(e, 'a[href*="lc="]'); if (o) { const e = o.getAttribute("href") || "", r = /[&?]lc=([\w_.-]+)/.exec(e); r && (t = r[1]); } } } if (o && t) { return { lc: t, commentRendererElm: o }; } } } return null; } function o(o, r, i) { let a = 0; try { const e = t(r), s = t(o); if (!e || !s) { return !1; } const c = Y(e.commentRendererElm), l = Y(s.commentRendererElm), d = c.data, u = Object.assign({}, i); d.linkedCommentBadge = null, delete d.linkedCommentBadge; const p = Object.assign({}, d); p.linkedCommentBadge = null, delete p.linkedCommentBadge, c.data = Object.assign({}, p), l.data = Object.assign({}, l.data, { linkedCommentBadge: u }), a = 1; } catch (t) { e.warn(t); } return 1 === a; } let r = !1; const i = async t => { const o = t?.target; if (!o || "VIDEO" !== o.nodeName && "AUDIO" !== o.nodeName) { return; } const r = o, i = le.getMediaElement(0), a = le.getMediaElements(2); if (null !== i && a.length > 0) { if (r !== i && !1 === i.paused) { G(i) && Z.resolve(r).then(t => !1 === t.paused && t.pause()).catch(e.warn); } else if (r === i) { for (const t of a) { if (!1 === t.paused) { Z.resolve(t).then(t => !1 === t.paused && t.pause()).catch(e.warn); break; } } } else { Z.resolve(i).then(t => !1 === t.paused && t.pause()).catch(e.warn); } } }, a = () => { if (document.querySelector("ytd-page-manager#page-manager > ytd-browse[page-subtype]")) { return !0; } const t = [ ...document.querySelectorAll("#movie_player") ].filter(t => !t.closest("[hidden]"))[0]; if (t) { const e = _(t, "video[class], audio[class]"); if (e && e.currentTime > 3 && e.duration - e.currentTime > 3 && !1 === e.paused) { return !0; } } return !1; }; let s = 0; return { handleNavigateFactory: c => function(l) { s > 1e9 && (s = 9); const d = ++s, u = arguments; let p = null; if ((t => { const e = t ? t.command : null; if (e) { if (e && (e.commandMetadata || 0).webCommandMetadata && e.watchEndpoint) {} else if (e && (e.commandMetadata || 0).webCommandMetadata && e.browseEndpoint && Kt(e.browseEndpoint.browseId)) {} else if (!e || !e.browseEndpoint && !e.searchEndpoint || e.urlEndpoint || e.watchEndpoint) { return !1; } return !!a() && "watch" === at; } })(l) && (p = (r => { let i = !1, a = r ? r.command : null; if (a && (a.commandMetadata || 0).webCommandMetadata && a.watchEndpoint) { const r = a.watchEndpoint.videoId, i = a.commandMetadata.webCommandMetadata.url; if ("string" == typeof r && "string" == typeof i && i.indexOf("lc=") > 0) { const a = /^\/watch\?v=([\w_-]+)&lc=([\w_.-]+)$/.exec(i); if (a && a[1] === r) { const r = t(a[2]), s = r ? t() : null; if (r && s && 1 == (r.lc === s.lc || (function(r, i) { let a = 0; try { const s = t(i), c = t(r); if (!s || !c) { return !1; } const l = s.commentRendererElm, d = c.commentRendererElm; if ("object" == typeof Y(l).data.linkedCommentBadge && void 0 === Y(d).data.linkedCommentBadge) { const t = Object.assign({}, Y(l).data.linkedCommentBadge); ((t || 0).metadataBadgeRenderer || 0).trackingParams && delete t.metadataBadgeRenderer.trackingParams; const s = K(l), c = K(d); if (s.parent !== c.parent || "YTD-COMMENTS" !== c.parent.nodeName && "YTD-ITEM-SECTION-RENDERER" !== c.parent.nodeName) { return !1; } if (c.index >= 0) { if ("YTD-COMMENT-REPLIES-RENDERER" === c.parent.nodeName) { o(r, i, t) && (a = 1); } else { const s = Y(c.parent), l = (s.data || 0).contents || 0; l || e.warn("v2Conents is not found"), s.data = Object.assign({}, s.data, { contents: [].concat([ l[c.index] ], l.slice(0, c.index), l.slice(c.index + 1)) }), o(r, i, t) && (a = 1); } } } } catch (t) { e.warn(t); } return 1 === a; })(r.lc, s.lc) ? 1 : 0)) { return void le.xReplaceState(history.state, i); } } } } if (a && (a.commandMetadata || 0).webCommandMetadata && a.browseEndpoint && Kt(a.browseEndpoint.browseId)) { i = !0; } else if (a && (a.browseEndpoint || a.searchEndpoint) && !a.urlEndpoint && !a.watchEndpoint) { if (a.browseEndpoint && "FEwhat_to_watch" === a.browseEndpoint.browseId) { const t = le.getMediaElement(1); t && !1 === t.paused && (i = !0); } else if (a.commandMetadata?.webCommandMetadata) { const t = a.commandMetadata.webCommandMetadata; t?.url && t.webPageType && (i = !0); } } return i || (a = null), a; })(l)), !p || !a()) { return c.apply(this, u); } const y = document.querySelector("ytd-app"), m = Y(y); let f = null; try { f = m.data.response.currentVideoEndpoint.watchEndpoint || null; } catch (t) { f = null; } "object" != typeof f && (f = null); const b = { once: !0 }; if (null !== f && !("playlistId" in f)) { let t = F(f); const o = 3; let r = 0; Object.defineProperty(N(t) || {}, "playlistId", { get() { return r++, r === o && delete this.playlistId, "*"; }, set(t) { delete this.playlistId, this.playlistId = t; }, enumerable: !1, configurable: !0 }); let i = null, a = 0; Z.race([ new Z(t => { a = setTimeout(t, 4e3); }), new Z(t => { i = () => { a > 0 && (clearTimeout(a), a = 0), t(); }, document.addEventListener("yt-page-type-changed", i, b); }) ]).then(() => { 0 !== a && (i && document.removeEventListener("yt-page-type-changed", i, b), a = 0), i = null, r = o - 1; const e = N(t); return t = null, e ? e.playlistId : null; }).catch(e.warn); } r || (r = !0, document.addEventListener("loadstart", i, !0)); const h = `${p?.commandMetadata?.webCommandMetadata?.url || ""}`; h?.endsWith("/about") && /\/channel\/UC[-_a-zA-Z0-9+=.]{22}\/about/.test(h) && (async t => { let o = new X; const r = () => { o?.resolve(), o = null; }; document.addEventListener("yt-navigate-finish", r, !1), await o.then(), o = null, document.removeEventListener("yt-navigate-finish", r, !1), t === s && setTimeout(() => { const t = [ ...document.querySelectorAll("ytd-about-channel-renderer") ].filter(t => !t.closest("[hidden]"))[0]; let o = !1; if (t) { const r = t.closest("ytd-popup-container"); if (r) { const t = Y(r); let i = null; try { i = t.handleGetOpenedPopupsAction_(); } catch (t) { e.warn("handleGetOpenedPopupsAction_ failed", t); } i && 0 === i.length && (o = !0); } else { o = !1; } } else { o = !0; } if (o) { const t = [ ...document.querySelectorAll("yt-description-preview-view-model") ].filter(t => !t.closest("[hidden]"))[0]; if (t) { const e = [ ...t.querySelectorAll("button") ].filter(t => !t.closest("[hidden]") && `${t.textContent}`.trim().length > 0)[0]; e && e.click(); } } }, 80); })(d), c.apply(this, u); } }; })(), le = (() => { let t = 0; const o = e => { if (0 === t) { const e = document.querySelector(".video-stream.html5-main-video") || document.querySelector("#movie_player video, #movie_player audio") || document.querySelector("body video[src], body audio[src]"); e && ("VIDEO" === e.nodeName ? t = 1 : "AUDIO" === e.nodeName && (t = 2)); } if (!t) { return null; } if (1 === t) { switch (e) { case 1: return "ytd-player#ytd-player video[src]"; case 2: return 'ytd-browse[role="main"] video[src]'; default: return "#movie_player video[src]"; } } else if (2 === t) { switch (e) { case 1: return "ytd-player#ytd-player audio.video-stream.html5-main-video[src]"; case 2: return 'ytd-browse[role="main"] audio.video-stream.html5-main-video[src]'; default: return "#movie_player audio.video-stream.html5-main-video[src]"; } } return null; }; return { xReplaceState(t, o) { try { history.replaceState(t, "", o); } catch (t) {} if (t.endpoint) { try { const e = document.querySelector("ytd-app"); Y(e).replaceState(t.endpoint, "", o); } catch (t) { e.warn("replaceState failed", t); } } }, getMediaElement(t) { const e = o(t) || ""; return e ? document.querySelector(e) : null; }, getMediaElements(t) { const e = o(t) || ""; return e ? document.querySelectorAll(e) : []; } }; })(); let de = !1, ue = ""; const pe = () => { const t = rt.flexy, o = Y(t); return o && "string" == typeof o.videoId ? o.videoId : t && "string" == typeof t.videoId ? t.videoId : (e.info("video id not found"), ""); }, ye = t => { try { t.updateIsAttributedExpanded(); } catch (t) { e.warn("updateIsAttributedExpanded failed", t); } try { t.updateIsFormattedExpanded(); } catch (t) { e.warn("updateIsFormattedExpanded failed", t); } try { t.updateTextOnSnippetTypeChange(); } catch (t) { e.warn("updateTextOnSnippetTypeChange failed", t); } try { t.updateStyles(); } catch (t) { e.warn("updateStyles failed", t); } }, me = t => { "function" == typeof t.set ? (t.set("isExpanded", !0), "function" == typeof t.isExpandedChanged && t.isExpandedChanged()) : !1 === t.isExpanded && (t.isExpanded = !0, "function" == typeof t.isExpandedChanged && t.isExpandedChanged()); }, fe = { updateTextOnSnippetTypeChange() { !1 === this.isResetMutation && (this.isResetMutation = !0), !0 === this.isExpanded && (this.isExpanded = !1), me(this, !0), !1 === this.isResetMutation && (this.isResetMutation = !0); }, collapse() {}, computeExpandButtonOffset: () => 0, dataChanged() {} }, be = t => { t && !t.W && (t.W = !0, t.dataChanged = fe.dataChanged, t.updateTextOnSnippetTypeChange = fe.updateTextOnSnippetTypeChange, "function" == typeof t.collapse && (t.collapse = fe.collapse), "function" == typeof t.computeExpandButtonOffset && (t.computeExpandButtonOffset = fe.computeExpandButtonOffset), "boolean" == typeof t.isResetMutation && (t.isResetMutation = !0), "string" == typeof t.collapseLabel && (t.collapseLabel = ""), ye(t)); }, he = () => { const t = it(); if (!t) { return; } const e = t.querySelector("ytd-text-inline-expander"), o = Y(e); be(o); }, ge = { minibrowser: { activated: !1, toUse: !0, activate() { if (this.activated) { return; } if ("function" != typeof IntersectionObserver) { return; } this.activated = !0; const t = document.querySelector("ytd-app"), e = Y(t); if (!e) { return; } const o = e.constructor.prototype; o.handleNavigate && (o.handleNavigate.J || (o.handleNavigate = ce(o.handleNavigate), o.handleNavigate.J = 1)); } }, autoExpandInfoDesc: { activated: !1, toUse: !1, mo: null, promiseReady: new X, moFn(t) { if (bt.autoExpandInfoDescAttrAsyncLock !== t) { return; } const o = it(); if (o) { switch (((o || 0).nodeName || "").toLowerCase()) { case "ytd-expander": if (o.hasAttribute000("collapsed")) { let t = !1; try { Y(o).handleMoreTap(new Event("tap")), t = !0; } catch (t) { e.warn("handleMoreTap failed", t); } t && o.setAttribute111("tyt-no-less-btn", ""); } break; case "ytd-expandable-video-description-body-renderer": { const t = o.querySelector("ytd-text-inline-expander"), e = Y(t); e && !1 === e.isExpanded && me(e, !0); break; } } } }, activate() { this.activated || (this.moFn = this.moFn.bind(this), this.moSubId = null, this.moCallback = () => { Z.resolve(ht.autoExpandInfoDescAttrAsyncLock).then(this.moFn).catch(e.warn); }, this.activated = !0, this.promiseReady.resolve()); }, async onMainInfoSet(t) { await this.promiseReady.then(), this.moSubId && i?.unwatch && i.unwatch(this.moSubId), this.moSubId = "main::autoExpandInfoDesc", i?.watchTarget ? "ytd-expander" === t.nodeName.toLowerCase() ? i.watchTarget(this.moSubId, t, this.moCallback, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "collapsed", "attr-8ifv7" ] }) : i.watchTarget(this.moSubId, t, this.moCallback, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "attr-8ifv7" ] }) : (this.mo && this.mo.disconnect(), this.mo = new MutationObserver(this.moCallback), "ytd-expander" === t.nodeName.toLowerCase() ? this.mo.observe(t, { attributes: !0, attributeFilter: [ "collapsed", "attr-8ifv7" ] }) : this.mo.observe(t, { attributes: !0, attributeFilter: [ "attr-8ifv7" ] }), o?.registerObserver?.(this.mo)), t.incAttribute111("attr-8ifv7"); } }, fullChannelNameOnHover: { activated: !1, toUse: !0, mo: null, ro: null, promiseReady: new X, checkResize: 0, mouseEnterFn(t) { const e = t ? t.target : null; if (!(e instanceof z)) { return; } const o = e.closest("ytd-watch-metadata"); o && (o.classList.remove("tyt-metadata-hover-resized"), this.checkResize = Date.now() + 300, o.classList.add("tyt-metadata-hover")); }, mouseLeaveFn(t) { const e = t ? t.target : null; if (!(e instanceof z)) { return; } const o = e.closest("ytd-watch-metadata"); o && (o.classList.remove("tyt-metadata-hover-resized"), o.classList.remove("tyt-metadata-hover")); }, moFn(t) { if (bt.fullChannelNameOnHoverAttrAsyncLock !== t) { return; } const e = document.querySelector("#primary.ytd-watch-flexy ytd-watch-metadata #upload-info"); if (!e) { return; } const o = { passive: !0, capture: !1 }; e.removeEventListener("pointerenter", this.mouseEnterFn, o), e.removeEventListener("pointerleave", this.mouseLeaveFn, o), e.addEventListener("pointerenter", this.mouseEnterFn, o), e.addEventListener("pointerleave", this.mouseLeaveFn, o); }, async onNavigateFinish() { await this.promiseReady.then(); const t = document.querySelector("#primary.ytd-watch-flexy ytd-watch-metadata #upload-info"); t && (this.moSubId && i?.unwatch && i.unwatch(this.moSubId), this.moSubId = "main::fullChannelNameOnHover", i?.watchTarget ? i.watchTarget(this.moSubId, t, this.moCallback, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "hidden", "attr-3wb0k" ] }) : (this.mo = new MutationObserver(this.moCallback), this.mo.observe(t, { attributes: !0, attributeFilter: [ "hidden", "attr-3wb0k" ] }), o?.registerObserver?.(this.mo)), t.incAttribute111("attr-3wb0k"), this.ro.observe(t)); }, activate() { this.activated || "function" == typeof IntersectionObserver && (this.activated = !0, this.mouseEnterFn = this.mouseEnterFn.bind(this), this.mouseLeaveFn = this.mouseLeaveFn.bind(this), this.moFn = this.moFn.bind(this), this.moSubId = null, this.moCallback = () => { Z.resolve(ht.fullChannelNameOnHoverAttrAsyncLock).then(this.moFn).catch(e.warn); }, this.ro = new ResizeObserver(t => { if (!(Date.now() > this.checkResize)) { for (const e of t) { const t = e.target; if (t && e.contentRect.width > 0 && e.contentRect.height > 0) { const e = t.closest("ytd-watch-metadata"); e.classList.contains("tyt-metadata-hover") && e.classList.add("tyt-metadata-hover-resized"); break; } } } }), this.promiseReady.resolve()); } }, "external.ytlstm": { activated: !1, toUse: !0, activate() { this.activated || (this.activated = !0, document.documentElement.classList.add("external-ytlstm")); } } }; sessionStorage.__$$tmp_UseAutoExpandInfoDesc$$__ && (ge.autoExpandInfoDesc.toUse = !0); const we = Symbol(), ve = t => { const o = de; de = !1; for (const o of document.querySelectorAll(`${t}`)) { "function" != typeof (Y(o) || 0).attached498 || o[we] || Z.resolve(o).then(Ae[`${t}::attached`]).catch(e.warn); } de = o; }, xe = async () => { for (let t = 2; t-- > 0; ) { const o = document.querySelector("#columns.style-scope.ytd-watch-flexy ytd-live-chat-frame#chat"); if (o instanceof Element) { return o; } t > 0 && (e.info("ytd-live-chat-frame::attached - delayPn(200)"), await V(200)); } return null; }, ke = () => { let t = document.querySelector("ytd-watch-flexy noscript[ns-template]"); return t || (t = document.createElement("noscript"), t.setAttribute("ns-template", ""), document.querySelector("ytd-watch-flexy").appendChild(t)), t; }, Se = (t, e) => !!(t && t instanceof Element && t.nodeName) && !!t.closest(e) && !0 === t.isConnected, Te = t => { if (t instanceof HTMLElement) { const e = HTMLElement.prototype.closest.call(t, "ytd-watch-flexy"); if (!e) { return !0; } const o = rt.flexy; if (o && o !== e) { return !0; } } return !1; }; let Le = null, Me = null, $e = null, Ce = null, Ee = null, ze = null, _e = 0, Ie = 0; const Ae = { ceHack: () => { nt.flag |= 2, document.documentElement.setAttribute111("tabview-loaded", nt.makeString()), je("ytd-watch-flexy").then(Ae["ytd-watch-flexy::defined"]).catch(e.warn), je("ytd-expander").then(Ae["ytd-expander::defined"]).catch(e.warn), je("ytd-watch-next-secondary-results-renderer").then(Ae["ytd-watch-next-secondary-results-renderer::defined"]).catch(e.warn), je("ytd-comments-header-renderer").then(Ae["ytd-comments-header-renderer::defined"]).catch(e.warn), je("ytd-live-chat-frame").then(Ae["ytd-live-chat-frame::defined"]).catch(e.warn), je("ytd-comments").then(Ae["ytd-comments::defined"]).catch(e.warn), je("ytd-engagement-panel-section-list-renderer").then(Ae["ytd-engagement-panel-section-list-renderer::defined"]).catch(e.warn), je("ytd-watch-metadata").then(Ae["ytd-watch-metadata::defined"]).catch(e.warn), je("ytd-playlist-panel-renderer").then(Ae["ytd-playlist-panel-renderer::defined"]).catch(e.warn), je("ytd-expandable-video-description-body-renderer").then(Ae["ytd-expandable-video-description-body-renderer::defined"]).catch(e.warn); }, fixForTabDisplay: t => { jt = !1; for (const t of document.querySelectorAll("[io-intersected]")) { const o = Y(t); if (t instanceof z && "function" == typeof o.calculateCanCollapse) { try { o.calculateCanCollapse(!0); } catch (t) { e.warn("calculateCanCollapse failed", t); } } } if (!t && "#tab-info" === ee) { for (const t of document.querySelectorAll("#tab-info ytd-video-description-infocards-section-renderer, #tab-info yt-chip-cloud-renderer, #tab-info ytd-horizontal-card-list-renderer, #tab-info yt-horizontal-list-renderer")) { const o = Y(t); if (t instanceof z && "function" == typeof o.notifyResize) { try { o.notifyResize(); } catch (t) { e.warn("notifyResize failed", t); } } } for (const t of document.querySelectorAll("#tab-info ytd-text-inline-expander")) { const e = Y(t); t instanceof z && "function" == typeof e.resize && e.resize(!1), ye(e); } } if (!t && "string" == typeof ee && ee.startsWith("#tab-")) { const t = document.querySelector(".tab-content-cld:not(.tab-content-hidden)"); if (t) { const o = t.querySelectorAll("yt-chip-cloud-renderer"); for (const t of o) { const o = Y(t); if ("function" == typeof o.notifyResize) { try { o.notifyResize(); } catch (t) { e.warn("notifyResize failed", t); } } } } } }, "ytd-watch-flexy::defined": t => { t.updateChatLocation498 || "function" != typeof t.updateChatLocation || 0 !== t.updateChatLocation.length || (t.updateChatLocation498 = t.updateChatLocation, t.updateChatLocation = Ft), t.isTwoColumnsChanged498_ || "function" != typeof t.isTwoColumnsChanged_ || 2 !== t.isTwoColumnsChanged_.length || (t.isTwoColumnsChanged498_ = t.isTwoColumnsChanged_, t.isTwoColumnsChanged_ = function(t, e, ...o) { return O(() => { if ("function" == typeof this.isTwoColumnsChanged498_) { return this.isTwoColumnsChanged498_(t, e, ...o); } }); }), t.defaultTwoColumnLayoutChanged498 || "function" != typeof t.defaultTwoColumnLayoutChanged || 0 !== t.defaultTwoColumnLayoutChanged.length || (t.defaultTwoColumnLayoutChanged498 = t.defaultTwoColumnLayoutChanged, t.defaultTwoColumnLayoutChanged = function(...t) { return O(() => { if ("function" == typeof this.defaultTwoColumnLayoutChanged498) { return this.defaultTwoColumnLayoutChanged498(...t); } }); }), t.updatePlayerLocation498 || "function" != typeof t.updatePlayerLocation || 0 !== t.updatePlayerLocation.length || (t.updatePlayerLocation498 = t.updatePlayerLocation, t.updatePlayerLocation = function(...t) { return O(() => { if ("function" == typeof this.updatePlayerLocation498) { return this.updatePlayerLocation498(...t); } }); }), t.updateCinematicsLocation498 || "function" != typeof t.updateCinematicsLocation || 0 !== t.updateCinematicsLocation.length || (t.updateCinematicsLocation498 = t.updateCinematicsLocation, t.updateCinematicsLocation = function(...t) { return O(() => { if ("function" == typeof this.updateCinematicsLocation498) { return this.updateCinematicsLocation498(...t); } }); }), t.updatePanelsLocation498 || "function" != typeof t.updatePanelsLocation || 0 !== t.updatePanelsLocation.length || (t.updatePanelsLocation498 = t.updatePanelsLocation, t.updatePanelsLocation = function(...t) { return O(() => { if ("function" == typeof this.updatePanelsLocation498) { return this.updatePanelsLocation498(...t); } }); }), t.swatcherooUpdatePanelsLocation498 || "function" != typeof t.swatcherooUpdatePanelsLocation || 6 !== t.swatcherooUpdatePanelsLocation.length || (t.swatcherooUpdatePanelsLocation498 = t.swatcherooUpdatePanelsLocation, t.swatcherooUpdatePanelsLocation = function(t, e, o, r, i, a, ...s) { return O(() => { if ("function" == typeof this.swatcherooUpdatePanelsLocation498) { return this.swatcherooUpdatePanelsLocation498(t, e, o, r, i, a, ...s); } }); }), t.updateErrorScreenLocation498 || "function" != typeof t.updateErrorScreenLocation || 0 !== t.updateErrorScreenLocation.length || (t.updateErrorScreenLocation498 = t.updateErrorScreenLocation, t.updateErrorScreenLocation = function(...t) { return O(() => { if ("function" == typeof this.updateErrorScreenLocation498) { return this.updateErrorScreenLocation498(...t); } }); }), t.updateFullBleedElementLocations498 || "function" != typeof t.updateFullBleedElementLocations || 0 !== t.updateFullBleedElementLocations.length || (t.updateFullBleedElementLocations498 = t.updateFullBleedElementLocations, t.updateFullBleedElementLocations = function(...t) { return O(() => { if ("function" == typeof this.updateFullBleedElementLocations498) { return this.updateFullBleedElementLocations498(...t); } }); }); }, "ytd-watch-next-secondary-results-renderer::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-watch-next-secondary-results-renderer::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-watch-next-secondary-results-renderer::detached"]).catch(e.warn), this.detached498(); }), ve("ytd-watch-next-secondary-results-renderer"); }, "ytd-watch-next-secondary-results-renderer::attached": t => { Te(t) || (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected && t instanceof z && t.matches("#columns #related ytd-watch-next-secondary-results-renderer") && !t.matches("#right-tabs ytd-watch-next-secondary-results-renderer, [hidden] ytd-watch-next-secondary-results-renderer") && (rt.related = t.closest("#related"), t.setAttribute111("tyt-videos-list", ""))); }, "ytd-watch-next-secondary-results-renderer::detached": t => { t instanceof z && !t.closest("noscript") && !1 === t.isConnected && (t.hasAttribute000("tyt-videos-list") && (rt.related = null, t.removeAttribute000("tyt-videos-list")), e.info("ytd-watch-next-secondary-results-renderer::detached", t)); }, settingCommentsVideoId: t => { if (!(t instanceof z && t.classList.length > 0) || t.closest("noscript")) { return; } const e = Y(t); if (rt.comments !== t || !0 !== t.isConnected || !0 !== e.isAttached || !e.data || !1 !== e.hidden) { return; } const o = rt.flexy, r = o ? Y(o) : null; r?.videoId ? t.setAttribute111("tyt-comments-video-id", r.videoId) : t.removeAttribute000("tyt-comments-video-id"); }, checkCommentsShouldBeHidden: t => { if (bt.checkCommentsShouldBeHiddenLock !== t) { return; } const e = rt.comments, o = rt.flexy; if (e && o && !e.hasAttribute000("hidden")) { const t = Y(o); if ("string" == typeof t.videoId) { const o = e.getAttribute("tyt-comments-video-id"); o && o !== t.videoId && e.setAttribute111("hidden", ""); } } }, "ytd-comments::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-comments::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-comments::detached"]).catch(e.warn), this.detached498(); }), t.K = function() { Z.resolve(this.hostElement).then(Ae["ytd-comments::_dataChanged498"]).catch(e.warn); }, "function" == typeof t.q ? t.q("data", "_dataChanged498", void 0) : "function" == typeof t.dataChanged_ ? (t.X = t.dataChanged_, t.dataChanged_ = function() { return Z.resolve(this.hostElement).then(Ae["ytd-comments::_dataChanged498"]).catch(e.warn), this.X(); }) : "function" == typeof t.dataChanged && (t.X = t.dataChanged, t.dataChanged = function() { return Z.resolve(this.hostElement).then(Ae["ytd-comments::_dataChanged498"]).catch(e.warn), this.X(); }), ve("ytd-comments"); }, "ytd-comments::_dataChanged498": t => { if (!t.hasAttribute000("tyt-comments-area")) { return; } let o = 0; const r = Y(t), i = r ? r.data : null, a = i ? i.contents : null; i && (a && 1 === a.length && a[0].messageRenderer && (o = 2), a && a.length > 1 && a[0].commentThreadRenderer && (o = 1)), o ? t.setAttribute111("tyt-comments-data-status", o) : t.removeAttribute000("tyt-comments-data-status"), Z.resolve(t).then(Ae.settingCommentsVideoId).catch(e.warn); }, "ytd-comments::attached": async t => { if (Te(t)) { return; } if (t instanceof Element && (t[we] = !0), !(t instanceof z && t.classList.length > 0) || t.closest("noscript")) { return; } if (!0 !== t.isConnected) { return; } if ("comments" !== t?.id) { return; } if (rt.comments = t, e.info("ytd-comments::attached"), Z.resolve(t).then(Ae.settingCommentsVideoId).catch(e.warn), Pt && i?.unwatch && i.unwatch(Pt), Pt = "main::aoComment", i?.watchTarget) { i.watchTarget(Pt, t, At, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "hidden", "tyt-comments-video-id", "tyt-comments-data-status" ] }); } else { const e = new MutationObserver(At); e.observe(t, { attributes: !0 }), o?.registerObserver?.(e); } t.setAttribute111("tyt-comments-area", ""); const r = ht.rightTabReadyLock02; if (await xt.then(), bt.rightTabReadyLock02 === r && rt.comments === t && !1 !== t.isConnected) { if (t && !t.closest("#right-tabs")) { document.querySelector("#tab-comments").assignChildren111(null, t, null); } else { const t = rt.comments?.closest("#tab-comments") && !rt.comments.closest("[hidden]"); document.querySelector('[tyt-tab-content="#tab-comments"]').classList.toggle("tab-btn-hidden", !t), Z.resolve(ht.removeKeepCommentsScrollerLock).then(re).catch(e.warn); } } }, "ytd-comments::detached": t => { t instanceof z && !t.closest("noscript") && !1 === t.isConnected && t.hasAttribute000("tyt-comments-area") && (t.removeAttribute000("tyt-comments-area"), Pt && i?.unwatch && (i.unwatch(Pt), Pt = null), rt.comments = null, document.querySelector('[tyt-tab-content="#tab-comments"]').classList.add("tab-btn-hidden"), Z.resolve(ht.removeKeepCommentsScrollerLock).then(re).catch(e.warn)); }, "ytd-comments-header-renderer::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-comments-header-renderer::attached"]).catch(e.warn), Z.resolve(this.hostElement).then(Ae["ytd-comments-header-renderer::dataChanged"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-comments-header-renderer::detached"]).catch(e.warn), this.detached498(); }), t.dataChanged498 || "function" != typeof t.dataChanged || (t.dataChanged498 = t.dataChanged, t.dataChanged = function() { return Z.resolve(this.hostElement).then(Ae["ytd-comments-header-renderer::dataChanged"]).catch(e.warn), this.dataChanged498(); }), ve("ytd-comments-header-renderer"); }, "ytd-comments-header-renderer::attached": t => { if (!Te(t) && (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected && t?.classList.contains("ytd-item-section-renderer"))) { if (t === document.querySelector("[tyt-comments-area] ytd-comments-header-renderer")) { t.setAttribute111("tyt-comments-header-field", ""); } else { const e = t.parentNode; e instanceof z && e.querySelector("[tyt-comments-header-field]") && t.setAttribute111("tyt-comments-header-field", ""); } } }, "ytd-comments-header-renderer::detached": t => { if (t instanceof z && !t.closest("noscript") && !1 === t.isConnected) { if (t.hasAttribute000("field-of-cm-count")) { t.removeAttribute000("field-of-cm-count"); const e = document.querySelector("#tyt-cm-count"); e && !document.querySelector("#tab-comments ytd-comments-header-renderer[field-of-cm-count]") && (e.textContent = ""); } t.hasAttribute000("tyt-comments-header-field") && t.removeAttribute000("tyt-comments-header-field"); } }, "ytd-comments-header-renderer::dataChanged": t => { if (!(t instanceof z && t.classList.length > 0) || t.closest("noscript")) { return; } const e = rt.flexy; let r = !1; if ((Y(t) && t.closest("#tab-comments") && document.querySelector("#tab-comments ytd-comments-header-renderer") === t || t instanceof z && t.parentNode instanceof z && t.parentNode.querySelector("[tyt-comments-header-field]")) && (r = !0), r && (t.setAttribute111("tyt-comments-header-field", ""), e?.removeAttribute000("tyt-comment-disabled")), t.hasAttribute000("tyt-comments-header-field") && !0 === t.isConnected) { i?.watchTarget ? (Me && i.unwatch(Me), Me = "main::commentsHeaderCounter", i.watchTarget(Me, t.parentNode, Ae["ytd-comments-header-renderer::deferredCounterUpdate"], { childList: !0, attributes: !1, subtree: !1 })) : (Le || (Le = new MutationObserver(Ae["ytd-comments-header-renderer::deferredCounterUpdate"])), Le.disconnect(), Le.observe(t.parentNode, { subtree: !1, childList: !0 }), o?.registerObserver?.(Le)), $e || ($e = document.createElementNS("http://www.w3.org/2000/svg", "defs")); const e = $e; t.insertAdjacentElement("afterend", e), e.remove(); } }, "ytd-comments-header-renderer::deferredCounterUpdate": () => { const t = document.querySelectorAll("#tab-comments ytd-comments-header-renderer[class]"); if (1 === t.length) { const o = t[0], r = Y(o).data; if (!r) { return; } let i = ""; if (r.commentsCount?.runs && r.commentsCount.runs.length >= 1) { let t = -1; const e = r.commentsCount.runs.map(e => { const o = e.text.replace(/\D+/g, "").length; return o > t && (t = o), [ e.text, o ]; }).filter(e => e[1] === t); e.length >= 1 && (i = e[0][0]); } else if (r.countText?.runs && r.countText.runs.length >= 1) { let t = -1; const e = r.countText.runs.map(e => { const o = e.text.replace(/\D+/g, "").length; return o > t && (t = o), [ e.text, o ]; }).filter(e => e[1] === t); e.length >= 1 && (i = e[0][0]); } const a = document.querySelector("#tyt-cm-count"); i ? (o.setAttribute111("field-of-cm-count", ""), a && (a.textContent = i.trim())) : (o.removeAttribute000("field-of-cm-count"), a && (a.textContent = ""), e.warn("no text for #tyt-cm-count")); } }, "ytd-expander::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-expander::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-expander::detached"]).catch(e.warn), this.detached498(); }), t.calculateCanCollapse498 || "function" != typeof t.calculateCanCollapse || (t.calculateCanCollapse498 = t.calculateCanCollapse, t.calculateCanCollapse = Mt), t.childrenChanged498 || "function" != typeof t.childrenChanged || (t.childrenChanged498 = t.childrenChanged, t.childrenChanged = function() { return Z.resolve(this.hostElement).then(Ae["ytd-expander::childrenChanged"]).catch(e.warn), this.childrenChanged498(); }), ve("ytd-expander"); }, "ytd-expander::childrenChanged": t => { t instanceof Node && t.hasAttribute000("hidden") && t.hasAttribute000("tyt-main-info") && t.firstElementChild && t.removeAttribute("hidden"); }, "ytd-expandable-video-description-body-renderer::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-expandable-video-description-body-renderer::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-expandable-video-description-body-renderer::detached"]).catch(e.warn), this.detached498(); }), ve("ytd-expandable-video-description-body-renderer"); }, "ytd-expandable-video-description-body-renderer::attached": async t => { if (t instanceof z && Se(t, "[tyt-info-renderer]") && !t.matches("[tyt-main-info]")) { rt.infoExpander = t, e.info(128384, rt.infoExpander), kt.resolve(), t.setAttribute111("tyt-main-info", ""), ge.autoExpandInfoDesc.toUse && ge.autoExpandInfoDesc.onMainInfoSet(t); const r = ht.rightTabReadyLock03; if (await xt.then(), bt.rightTabReadyLock03 !== r) { return; } if (rt.infoExpander !== t) { return; } if (!1 === t.isConnected) { return; } e.info(7932, "infoExpander"), rt.infoExpander.classList.add("tyt-main-info"); const a = rt.infoExpander, s = a.querySelector("ytd-text-inline-expander"); if (s) { const t = () => { const t = document.querySelector("#tab-info ytd-text-inline-expander"); sessionStorage.__$$tmp_UseAutoExpandInfoDesc$$__ = t?.hasAttribute("is-expanded") ? "1" : "", t && he(); }; if (i?.watchTarget) { Ce && i.unwatch(Ce), Ce = "main::inlineExpander", i.watchTarget(Ce, s, t, { attributes: !0, childList: !1, subtree: !0, attributeFilter: [ "is-expanded", "attr-6v8qu", "hidden" ] }); } else { const e = new MutationObserver(t); e.observe(s, { attributes: !0, attributeFilter: [ "is-expanded", "attr-6v8qu", "hidden" ], subtree: !0 }), o?.registerObserver?.(e); } s.incAttribute111("attr-6v8qu"); const e = Y(s); e && ye(e); } if (a && !a.closest("#right-tabs")) { document.querySelector("#tab-info").assignChildren111(null, a, null); } else if (document.querySelector('[tyt-tab-content="#tab-info"]')) { const t = rt.infoExpander?.closest("#tab-info"); document.querySelector('[tyt-tab-content="#tab-info"]').classList.toggle("tab-btn-hidden", !t); } Z.resolve(ht.infoFixLock).then(Xt).catch(e.warn); } if (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected && !Se(t, "#tab-info [tyt-main-info]") && !t.closest("#tab-info")) { const e = t; let o = document.querySelector("ytd-expandable-video-description-body-renderer[tyt-info-renderer]"); o || (o = document.createElement("ytd-expandable-video-description-body-renderer"), o.setAttribute("tyt-info-renderer", ""), ke().appendChild(o)), Y(o).data = Object.assign({}, Y(e).data); const r = o.querySelector("ytd-text-inline-expander"), i = Y(r); be(i), rt.infoExpanderRendererBack = e, rt.infoExpanderRendererFront = o, e.setAttribute("tyt-info-renderer-back", ""), o.setAttribute("tyt-info-renderer-front", ""); } }, "ytd-expandable-video-description-body-renderer::detached": async t => { t instanceof z && !t.closest("noscript") && !1 === t.isConnected && t.hasAttribute000("tyt-main-info") && (rt.infoExpander = null, t.removeAttribute000("tyt-main-info")); }, "ytd-expander::attached": async t => { Te(t) || (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected && t instanceof z && t.matches("[tyt-comments-area] #contents ytd-expander#expander") && !t.matches("[hidden] ytd-expander#expander") && (t.setAttribute111("tyt-content-comment-entry", ""), Ut.observe(t))); }, "ytd-expander::detached": t => { t instanceof z && !t.closest("noscript") && !1 === t.isConnected && (t.hasAttribute000("tyt-content-comment-entry") ? (Ut.unobserve(t), t.removeAttribute000("tyt-content-comment-entry")) : t.hasAttribute000("tyt-main-info") && (rt.infoExpander = null, t.removeAttribute000("tyt-main-info"))); }, "ytd-live-chat-frame::defined": t => { let o = 0; if (t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return o = Date.now(), de || Z.resolve(this.hostElement).then(Ae["ytd-live-chat-frame::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return o = Date.now(), de || Z.resolve(this.hostElement).then(Ae["ytd-live-chat-frame::detached"]).catch(e.warn), this.detached498(); }), "function" == typeof t.urlChanged && !t.urlChanged66 && !t.urlChangedAsync12 && 0 === t.urlChanged.length) { t.urlChanged66 = t.urlChanged; let o = 0; t.urlChangedAsync12 = async function() { await this.tt; const t = o = 1 + (1073741823 & o), r = this.chatframe || (this.$ || 0).chatframe || 0; if (r instanceof HTMLIFrameElement) { if (null === r.contentDocument && (await Z.resolve("#").catch(e.warn), t !== o)) { return; } if (await new Z(t => q(t, 1)).catch(e.warn), t !== o) { return; } const i = !this.data || this.collapsed, a = new Z(t => q(t, 706)).catch(e.warn); let s = null; const c = new Z(t => { s = new IntersectionObserver((e, o) => { for (const r of e) { const e = r.boundingClientRect || 0; if (i || e.width > 0 && e.height > 0) { o.disconnect(), s = null, t("#"); break; } } }), s.observe(r); }).catch(e.warn); if (await Z.race([ a, c ]), s && (s.disconnect(), s = null), t !== o) { return; } } this.urlChanged66(); }, t.urlChanged = function() { const t = this.tt = 1 + (1073741823 & this.tt); tt(() => { t === this.tt && this.urlChangedAsync12(); }); }; } ve("ytd-live-chat-frame"); }, "ytd-live-chat-frame::attached": async t => { if (Te(t)) { return; } if (t instanceof Element && (t[we] = !0), !(t instanceof z && t.classList.length > 0) || t.closest("noscript")) { return; } if (!0 !== t.isConnected) { return; } if ("chat" !== t?.id) { return; } e.info("ytd-live-chat-frame::attached"); const r = ht.ytdLiveAttachedLock, a = await xe(); if (bt.ytdLiveAttachedLock === r && a === t) { if (rt.chat = a, zt && i?.unwatch && i.unwatch(zt), zt = "main::aoChat", i?.watchTarget) { i.watchTarget(zt, a, Et, { attributes: !0, childList: !1, subtree: !1 }); } else { const t = new MutationObserver(Et); t.observe(a, { attributes: !0 }), o?.registerObserver?.(t); } } }, "ytd-live-chat-frame::detached": t => { if (t instanceof z && !t.closest("noscript") && !1 === t.isConnected && (e.info("ytd-live-chat-frame::detached"), t.hasAttribute000("tyt-active-chat-frame"))) { zt && i?.unwatch && (i.unwatch(zt), zt = null), t.removeAttribute000("tyt-active-chat-frame"), rt.chat = null; const e = rt.flexy; e && (e.removeAttribute000("tyt-chat-collapsed"), e.setAttribute111("tyt-chat", "")); } }, "ytd-engagement-panel-section-list-renderer::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-engagement-panel-section-list-renderer::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-engagement-panel-section-list-renderer::detached"]).catch(e.warn), this.detached498(); }), ve("ytd-engagement-panel-section-list-renderer"); }, "ytd-engagement-panel-section-list-renderer::bindTarget": t => { if (t.matches("#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer[target-id][visibility]")) { if (t.setAttribute111("tyt-egm-panel", ""), Z.resolve(ht.updateEgmPanelsLock).then(ie).catch(e.warn), oe && i?.unwatch && i.unwatch(oe), oe = "main::aoEgmPanels", i?.watchTarget) { i.watchTarget(oe, t, ne, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "visibility", "hidden" ] }); } else { const e = new MutationObserver(ne); e.observe(t, { attributes: !0, attributeFilter: [ "visibility", "hidden" ] }), o?.registerObserver?.(e); } } }, "ytd-engagement-panel-section-list-renderer::attached": t => { if (!Te(t) && (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected && t.matches("#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer"))) { if (null === t.getAttribute("target-id") && t.hasAttribute("visibility") && t.matches('#panels.ytd-watch-flexy > ytd-engagement-panel-section-list-renderer[visibility*="ENGAGEMENT_PANEL_VISIBILITY_"]')) { let e = ""; try { e = crypto.randomUUID(); } catch { e = `${Date.now().toString(36)}-${Math.random().toString(36).substring(2)}`; } t.setAttribute000("target-id", `tid051-${e}`); } if (t.hasAttribute000("target-id") && t.hasAttribute000("visibility")) { Z.resolve(t).then(Ae["ytd-engagement-panel-section-list-renderer::bindTarget"]).catch(e.warn); } else if (t.setAttribute000("tyt-egm-panel-jclmd", ""), ze && i?.unwatch && i.unwatch(ze), ze = "main::moEgmPanelReady", i?.watchTarget) { i.watchTarget(ze, t, Be, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "visibility", "target-id" ] }); } else { const e = new MutationObserver(Be); e.observe(t, { attributes: !0, attributeFilter: [ "visibility", "target-id" ] }), o?.registerObserver?.(e); } } }, "ytd-engagement-panel-section-list-renderer::detached": t => { t instanceof z && !t.closest("noscript") && !1 === t.isConnected && (t.hasAttribute000("tyt-egm-panel") ? (t.removeAttribute000("tyt-egm-panel"), Z.resolve(ht.updateEgmPanelsLock).then(ie).catch(e.warn)) : t.hasAttribute000("tyt-egm-panel-jclmd") && (t.removeAttribute000("tyt-egm-panel-jclmd"), Re())); }, "ytd-watch-metadata::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-watch-metadata::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-watch-metadata::detached"]).catch(e.warn), this.detached498(); }), ve("ytd-watch-metadata"); }, "ytd-watch-metadata::attached": t => { Te(t) || (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected && ge.fullChannelNameOnHover.activated && ge.fullChannelNameOnHover.onNavigateFinish()); }, "ytd-watch-metadata::detached": t => { t instanceof z && t.closest("noscript"); }, "ytd-playlist-panel-renderer::defined": t => { t.attached498 || "function" != typeof t.attached || (t.attached498 = t.attached, t.attached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-playlist-panel-renderer::attached"]).catch(e.warn), this.attached498(); }), t.detached498 || "function" != typeof t.detached || (t.detached498 = t.detached, t.detached = function() { return de || Z.resolve(this.hostElement).then(Ae["ytd-playlist-panel-renderer::detached"]).catch(e.warn), this.detached498(); }), ve("ytd-playlist-panel-renderer"); }, "ytd-playlist-panel-renderer::attached": t => { if (!Te(t) && (t instanceof Element && (t[we] = !0), t instanceof z && t.classList.length > 0 && !t.closest("noscript") && !0 === t.isConnected)) { if (rt.playlist = t, It && i?.unwatch && i.unwatch(It), It = "main::aoPlayList", i?.watchTarget) { i.watchTarget(It, t, _t, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "hidden", "collapsed", "attr-1y6nu" ] }); } else { const e = new MutationObserver(_t); e.observe(t, { attributes: !0, attributeFilter: [ "hidden", "collapsed", "attr-1y6nu" ] }), o?.registerObserver?.(e); } t.incAttribute111("attr-1y6nu"); } }, "ytd-playlist-panel-renderer::detached": t => { t instanceof z && t.closest("noscript"); }, nt: () => { nt.flag |= 4, document.documentElement.setAttribute111("tabview-loaded", nt.makeString()); }, relatedElementProvided: t => { t.closest("[hidden]") || (rt.related = t, e.info("relatedElementProvided"), gt.resolve()); }, onceInfoExpanderElementProvidedPromised: () => { if (!document.documentElement.hasAttribute("tabview-loaded")) { return; } e.info("hide-default-text-inline-expander"); const t = rt.flexy; t && t.setAttribute111("hide-default-text-inline-expander", ""); }, refreshSecondaryInner: t => { if (!document.documentElement.hasAttribute("tabview-loaded")) { return; } if (bt.refreshSecondaryInnerLock !== t) { return; } const e = rt.flexy; e?.matches("ytd-watch-flexy[theater][full-bleed-player]:not([full-bleed-no-max-width-columns])") && e.setAttribute111("full-bleed-no-max-width-columns", ""); const o = rt.related; o?.isConnected && !o.closest("#right-tabs #tab-videos") && document.querySelector("#tab-videos").assignChildren111(null, o, null); const r = rt.infoExpander; r?.isConnected && !r.closest("#right-tabs #tab-info") && document.querySelector("#tab-info").assignChildren111(null, r, null); const i = rt.comments; i && i.isConnected && !i.closest("#right-tabs #tab-comments") && document.querySelector("#tab-comments").assignChildren111(null, i, null); }, "yt-navigate-finish": () => { if (!document.documentElement.hasAttribute("tabview-loaded")) { return; } const t = document.querySelector("ytd-page-manager#page-manager.style-scope.ytd-app"), o = Y(t); if (at = o ? (o.data || 0).page : null, !document.querySelector("ytd-watch-flexy #player")) { return; } vt && !document.querySelector("#right-tabs") && (St(), rt.related && gt.resolve()); const r = [ ...document.querySelectorAll("ytd-watch-flexy") ].filter(t => !t.closest("[hidden]") && t.querySelector("#player")); if (1 === r.length) { if (rt.flexy = r[0], vt) { Bt = 0, ee = "", te = ""; const t = rt.flexy; t && (Ee && i?.unwatch && i.unwatch(Ee), Ee = "main::aoFlexy", i?.watchTarget ? i.watchTarget(Ee, t, Ae.aoFlexyFn, { attributes: !0, childList: !1, subtree: !1 }) : new MutationObserver(Ae.aoFlexyFn).observe(t, { attributes: !0 })), Z.resolve(ht.refreshSecondaryInnerLock).then(Ae.refreshSecondaryInner).catch(e.warn), Z.resolve(ht.removeKeepCommentsScrollerLock).then(re).catch(e.warn); } else { wt.resolve(), ge.minibrowser.toUse && ge.minibrowser.activate(), ge.autoExpandInfoDesc.toUse && ge.autoExpandInfoDesc.activate(), ge.fullChannelNameOnHover.toUse && ge.fullChannelNameOnHover.activate(); } const t = rt.chat; t instanceof Element && t.setAttribute111("tyt-active-chat-frame", "CF"); const o = rt.infoExpander; o?.closest("#right-tabs") && Z.resolve(ht.infoFixLock).then(Xt).catch(e.warn), Z.resolve(ht.layoutFixLock).then(Qt).catch(e.warn), ge.fullChannelNameOnHover.activated && ge.fullChannelNameOnHover.onNavigateFinish(); } }, onceInsertRightTabs: () => { if (!document.documentElement.hasAttribute("tabview-loaded")) { return; } const r = rt.related; let a = document.querySelector("#right-tabs"); if (!a && r) { mt(); let e = window.YouTubeSafeDOM ? window.YouTubeSafeDOM.createFragment(p()) : null; e || (e = document.createElement("div"), e.innerHTML = t(p())); const o = e.firstElementChild; null !== o && (de = !0, r.parentNode.insertBefore000(o, r), de = !1), a = o, a && a.querySelector('[tyt-tab-content="#tab-comments"]').classList.add("tab-btn-hidden"); const i = document.createElement("secondary-wrapper"); i.classList.add("tabview-secondary-wrapper"), i.id = "secondary-inner-wrapper"; const s = document.querySelector("#secondary-inner.style-scope.ytd-watch-flexy"); s && (de = !0, i.replaceChildren000(...s.childNodes), s.insertBefore000(i, s.firstChild), de = !1), a && a.querySelector("#material-tabs").addEventListener("click", Ae["tabs-btn-click"], !0), de = !0, a.closest("secondary-wrapper") || i.appendChild000(a), de = !1; } if (a) { vt = !0; const t = new IntersectionObserver(t => { for (const e of t) { const t = e.boundingClientRect; e.target.classList.toggle("tab-btn-visible", t.width && t.height); } }, { rootMargin: "0px" }); for (const e of document.querySelectorAll(".tab-btn[tyt-tab-content]")) { t.observe(e); } o?.registerObserver?.(t), r.closest("#right-tabs") || document.querySelector("#tab-videos").assignChildren111(null, r, null); const s = rt.infoExpander; s && !s.closest("#right-tabs") && document.querySelector("#tab-info").assignChildren111(null, s, null); const c = rt.comments; if (c && !c.closest("#right-tabs") && document.querySelector("#tab-comments").assignChildren111(null, c, null), c) { const t = a.querySelector('[tyt-tab-content="#tab-comments"]'); if (t) { const e = c.closest("#tab-comments") && !c.closest("[hidden]"); t.classList.toggle("tab-btn-hidden", !e); } } xt.resolve(), Dt.disconnect(), Dt.observe(a), o?.registerObserver?.(Dt); const l = rt.flexy; if (Ee && i?.unwatch && i.unwatch(Ee), Ee = "main::aoFlexy", i?.watchTarget) { i.watchTarget(Ee, l, Ae.aoFlexyFn, { attributes: !0, childList: !1, subtree: !1 }); } else { const t = new MutationObserver(Ae.aoFlexyFn); t.observe(l, { attributes: !0 }), o?.registerObserver?.(t); } Z.resolve(ht.fixInitialTabStateLock).then(Ae.fixInitialTabStateFn).catch(e.warn), l.incAttribute111("attr-7qlsy"); } }, aoFlexyFn: () => { Z.resolve(ht.checkCommentsShouldBeHiddenLock).then(Ae.checkCommentsShouldBeHidden).catch(e.warn), Z.resolve(ht.refreshSecondaryInnerLock).then(Ae.refreshSecondaryInner).catch(e.warn), Z.resolve(ht.tabsStatusCorrectionLock).then(Ae.tabsStatusCorrection).catch(e.warn); const t = pe(); t !== ue && (ue = t, Z.resolve(ht.updateOnVideoIdChangedLock).then(Ae.updateOnVideoIdChanged).catch(e.warn)); }, twoColumnChanged10: t => { if (t === bt.twoColumnChanged10Lock) { for (const t of document.querySelectorAll("#tab-videos ytd-watch-next-secondary-results-renderer ytd-continuation-item-renderer")) { if (t.closest("[hidden]")) { continue; } const e = Y(t); if ("boolean" == typeof e.showButton) { if (!1 === e.showButton) { continue; } e.showButton = !1; const t = e.ytRendererBehavior || e; "function" == typeof t.invalidate && t.invalidate(!1); } } } }, tabsStatusCorrection: t => { if (t !== bt.tabsStatusCorrectionLock) { return; } const o = rt.flexy; if (!o) { return; } const r = Bt, i = Rt(r, 4351); let d = !1; if (r !== i) { e.info(388, r, i); let t = !1, u = 0; if (ge["external.ytlstm"].activated && (i & c || (4121 == (4127 & r) && 4117 == (4127 & i) ? u = 3 : 17 & ~i || !document.querySelector("[data-ytlstm-theater-mode]") ? !(25 & ~i) && document.querySelector('[is-two-columns_][theater][tyt-chat="+"]') && (u = 2) : u = 1)), u || (0 === (r & l) && (i & l) === l ? te = "playlist" : 8 & r || 8 & ~i ? ((!(4 & ~r) && !(12 & i) || !(8 & ~r) && !(12 & i)) && "chat" === te || 8 == (12 & r) && 4 == (12 & i) && "chat" === te || (r & l) === l && 0 === (i & l) && "playlist" === te) && (te = ee || "", d = !0) : te = "chat"), Bt = i, u) { return void (1 === u ? ("+" !== o.getAttribute("tyt-chat") && f(), o.getAttribute("tyt-tab") && Ot(null)) : 2 === u ? b() : 3 === u && (y(), ee && Ot(ee))); } let p = !1; 2 == (2 ^ i) && jt && (p = !0), (r & a) === a && 0 === (i & a) && Z.resolve(ht.twoColumnChanged10Lock).then(Ae.twoColumnChanged10).catch(e.warn), !(2 & ~r) ^ !(2 & ~i) && !(2 & ~i) && (p = !0), !(2 & r) && !(2 & ~i) && (r & l) === l && (i & l) === l && (te = ee || "", v(), t = !0), 128 == (136 & r) && !(136 & ~i) && "chat" === te && (te = ee || "", v(), t = !0), 27 == (255 & r) && 26 == (255 & i) && (te = ee || "", b(), t = !0), 2 == (130 & r) && !(130 & ~i) && "playlist" === te && (Ot(null), t = !0), 8 == (136 & r) && !(136 & ~i) && "playlist" === te && (te = ee || "", b(), t = !0), 17 == (145 & r) && !(145 & ~i) && (y(), t = !0), 144 == (145 & r) && !(145 & ~i) && (te = ee || "", v(), t = !0), (i & c) === c ? t = !1 : (r & c) === c && 0 === (i & c) ? ((i & s) === s && w(), !(10 & ~i) && ("chat" === te ? (Ot(null), t = !0) : te && (b(), t = !0))) : 17 == (59 & r) && 25 == (59 & i) ? (y(), t = !0) : 16 == (49 & r) && 48 == (49 & i) && (10 & i) > 0 ? (2 & i && (Ot(null), t = !0), 8 & i && (b(), t = !0)) : 24 == (27 & r) && (27 & i) === a && 0 === (i & l) ? ee && (Ot(ee), t = !0) : 1 & r || 1 & ~i ? 1 != (3 & r) || 3 & ~i ? 2 != (10 & r) || 10 & ~i ? (32 != (40 & r) || 40 & ~i) && (32 != (34 & r) || 34 & ~i) ? 8 != (10 & r) || 10 & ~i ? !(1 & ~r) && !(33 & i) && ("chat" === te ? (f(), t = !0) : te === ee && ee && (Ot(ee), t = !0)) : (b(), t = !0) : (w(), t = !0) : (Ot(null), t = !0) : (y(), t = !0) : ((i & s) === s && w(), 8 == (9 & r) && !(9 & ~i) && b(), Ot(null), t = !0), t || (i & l) !== l || (te = "playlist", !(2 & ~i) && (Ot(null), t = !0)); let m = !1; !(2 & ~r) && 128 == (130 & i) || !(8 & ~r) && 128 == (136 & i) || (t || (17 & r) !== a || (123 & i) !== a ? 20 == (255 & i) && (m = !0) : m = !0), m && (e.info(388, "d"), "chat" === te ? (e.info(388, "d1c"), f(), t = !0) : "playlist" === te ? (e.info(388, "d1p"), (function() { const t = Y(rt.playlist); t && "boolean" == typeof t.collapsed && (t.collapsed = !1); })(), t = !0) : ee ? (e.info(388, "d2t"), Ot(ee), t = !0) : d && (e.info(388, "d2d"), Z.resolve(ht.fixInitialTabStateLock).then(Ae.fixInitialTabStateFn).catch(e.warn), t = !0)), p && (jt = !1, Z.resolve(0).then(Ae.fixForTabDisplay).catch(e.warn)), (r & a) === a ^ (i & a) === a && (Z.resolve(ht.infoFixLock).then(Xt).catch(e.warn), Z.resolve(ht.removeKeepCommentsScrollerLock).then(re).catch(e.warn), Z.resolve(ht.layoutFixLock).then(Qt).catch(e.warn)); } }, updateOnVideoIdChanged: t => { if (t !== bt.updateOnVideoIdChangedLock) { return; } if (!ue) { return; } const o = rt.infoExpanderRendererBack, r = rt.infoExpanderRendererFront; r && o && (Y(r).data = Y(o).data), Z.resolve(ht.infoFixLock).then(Xt).catch(e.warn); }, fixInitialTabStateFn: async t => { if (bt.fixInitialTabStateLock !== t) { return; } const e = se > 0 ? 200 : 1; if (await V(e), bt.fixInitialTabStateLock !== t) { return; } const o = document.querySelector("[tyt-tab]"), r = o && "" !== o.getAttribute("tyt-tab") ? null : ae("ytd-watch-flexy[is-two-columns_]", "[hidden]"); if (ae("ytd-playlist-panel-renderer#playlist", "[hidden], [collapsed]")) { Ot(null); } else if (ae("ytd-live-chat-frame#chat", "[hidden], [collapsed]")) { Ot(null), ae("ytd-watch-flexy[theater]", "[hidden]") && b(); } else if (r) { if (r.hasAttribute("theater")) { Ot(null); } else { const t = document.querySelector(".tab-btn-visible"); Ot(t || null); } } se++; }, "tabs-btn-click": t => { const e = t.target; e instanceof z && e.classList.contains("tab-btn") && e.hasAttribute000("tyt-tab-content") && (t.preventDefault(), t.stopPropagation(), t.stopImmediatePropagation(), Ot(e)); } }; Z.all([ gt, wt ]).then(Ae.onceInsertRightTabs).catch(e.warn), Z.all([ wt, kt ]).then(Ae.onceInfoExpanderElementProvidedPromised).catch(e.warn); const Pe = "undefined" != typeof customElements && "function" == typeof (customElements || 0).whenDefined, Ue = Pe ? Z.resolve(0) : new Z(t => { const e = "ytI-ce-registry-created"; if ("undefined" == typeof customElements) { "ot" in document || Object.defineProperty(document, "ot", { get() {}, set(t) { return "object" == typeof t && (delete this.ot, this.ot = t, this.dispatchEvent(new CustomEvent(e))), !0; }, enumerable: !1, configurable: !0 }); let o = () => { document.removeEventListener(e, o, !1); const r = t; t = null, o = null, r(); }; document.addEventListener(e, o, !1); } else { t(); } }), je = async t => { try { Pe || await Ue, await customElements.whenDefined(t); const e = document.querySelector(t) || document.createElement(t); return Y(e).constructor.prototype; } catch (t) { e.warn(t); } }, He = { nt: () => (window || 0)._yt_player || 0 }; let De = null; const Oe = () => { if (De && (De.resolve(), De = null), "function" == typeof He.nt) { const t = He.nt(); t && (He.nt = t, Ae.nt()); } }; if (i?.subscribeRoot) { i.subscribeRoot("main::moOverall", Oe, { childList: !0, attributes: !1, subtree: !0 }); } else { const Ve = new MutationObserver(Oe); Ve.observe(document, { subtree: !0, childList: !0 }), o?.registerObserver?.(Ve); } const Be = t => { for (const o of t) { const t = o.target; t.hasAttribute000("tyt-egm-panel-jclmd") && t.hasAttribute000("target-id") && t.hasAttribute000("visibility") && (t.removeAttribute000("tyt-egm-panel-jclmd"), Re(), Z.resolve(t).then(Ae["ytd-engagement-panel-section-list-renderer::bindTarget"]).catch(e.warn)); } }, Re = () => { null === document.querySelector("[tyt-egm-panel-jclmd]") && ze && i?.unwatch && (i.unwatch(ze), ze = null); }; document.addEventListener("yt-navigate-finish", Ae["yt-navigate-finish"], !1), document.addEventListener("animationstart", t => { const e = Ae[t.animationName]; "function" == typeof e && e(t.target); }, et), (() => { try { const t = "undefined" != typeof window ? window.YouTubePlusSettingsStore : null; if (t && "function" == typeof t.get) { return !1 !== t.get("enableTabview"); } const e = "undefined" != typeof localStorage ? localStorage.getItem("youtube_plus_settings") : null; if (e) { const t = JSON.parse(e); return !t || !1 !== t.enableTabview; } } catch (t) {} return !0; })() && (nt.flag |= 1, document.documentElement.setAttribute111("tabview-loaded", nt.makeString())), Ue.then(Ae.ceHack).catch(e.warn), (function() { try { const t = window.YouTubePlusI18n, e = { info: "Info", videos: "Videos", playlist: "Playlist" }, o = () => { for (const {id: o, key: r} of [ { id: "tab-btn1", key: "info" }, { id: "tab-btn4", key: "videos" }, { id: "tab-btn5", key: "playlist" } ]) { const i = document.getElementById(o); if (!i) { continue; } const a = i.querySelectorAll("span"); let s = null; for (const t of a) { if ("tyt-cm-count" !== t.id) { s = t; break; } } if (s) { if (t) { const e = t.t(r); if (e && e !== r) { s.textContent = e; continue; } } s.textContent = e[r] || r; } } }, r = () => { if (!t) { return; } const e = t.t("loading"); e && "loading" !== e && document.documentElement.style.setProperty("--tabview-text-loading", e); const o = t.t("fetching"); o && "fetching" !== o && document.documentElement.style.setProperty("--tabview-text-fetching", o); }, i = () => { r(), o(); }; t && "function" == typeof t.onLanguageChange && t.onLanguageChange(i), t && window.addEventListener("youtube-plus-i18n-ready", i, { once: !0 }), xt.then(i); } catch (t) {} })(); const Fe = () => { document.documentElement.removeAttribute("tabview-loaded"); const t = rt.related, e = rt.comments, o = rt.infoExpander, r = document.querySelector("#primary-inner.style-scope.ytd-watch-flexy"), a = document.querySelector("#secondary-inner.style-scope.ytd-watch-flexy"); if (a) { const t = a.querySelector("#secondary-inner-wrapper"); if (t) { for (de = !0; t.firstChild; ) { a.insertBefore(t.firstChild, t); } t.remove(), de = !1; } } if (t && a && (de = !0, a.appendChild(t), de = !1), o && r) { de = !0; const t = r.querySelector("#comments"); t ? r.insertBefore(o, t) : r.appendChild(o), de = !1; } e && r && (de = !0, r.appendChild(e), de = !1); const s = document.querySelector("#right-tabs"); s && s.remove(), Dt && Dt.disconnect(), Ee && i?.unwatch && (i.unwatch(Ee), Ee = null), Bt = 0, ee = "", te = "", vt = !1, St(); }; window.addEventListener("youtube-plus-settings-updated", t => { try { const e = !1 !== t?.detail?.enableTabview, o = document.documentElement.hasAttribute("tabview-loaded"); e && !o ? (nt.flag |= 1, document.documentElement.setAttribute111("tabview-loaded", nt.makeString()), vt = !1, "function" == typeof Ae?.onceInsertRightTabs && Ae.onceInsertRightTabs(), "function" == typeof Ae?.onceInfoExpanderElementProvidedPromised && Ae.onceInfoExpanderElementProvidedPromised(), "function" == typeof Ae?.["yt-navigate-finish"] && Ae["yt-navigate-finish"]()) : !e && o && Fe(); } catch (t) { e.warn("Error handling tabview toggle in settings update", t); } }), E = 1; } catch (Ye) { e.error("error 0xF491", Ye); } } }, styles_main = '\n @keyframes relatedElementProvided {\n0%{background-position-x:3px}\n100%{background-position-x:4px}\n}\nhtml[tabview-loaded="icp"] #related.ytd-watch-flexy{animation:relatedElementProvided 1ms linear 0s 1 normal forwards}\nhtml[tabview-loaded="icp"] #right-tabs #related.ytd-watch-flexy,html[tabview-loaded="icp"] [hidden] #related.ytd-watch-flexy{animation:initial}\nhtml[tabview-loaded="icp"] #right-tabs ytd-expander#expander,html[tabview-loaded="icp"] [hidden] ytd-expander#expander,html[tabview-loaded="icp"] ytd-comments ytd-expander#expander{animation:initial}\n#secondary.ytd-watch-flexy{position:relative}\n#secondary-inner.style-scope.ytd-watch-flexy{height:100%}\nytd-watch-flexy #secondary{--tyt-secondary-mt:var(--ytd-margin-6x);--tyt-secondary-mb:var(--ytd-margin-6x);--tyt-secondary-mr:var(--ytd-margin-6x)}\nytd-watch-flexy[reduced-top-margin] #secondary{--tyt-secondary-mt:var(--ytd-margin-3x);--tyt-secondary-mb:var(--ytd-margin-3x)}\nsecondary-wrapper{display:flex;flex-direction:column;flex-wrap:nowrap;box-sizing:border-box;padding:0;margin:0;border:0;height:100%;max-height:calc(100vh - var(--ytd-toolbar-height,56px));position:absolute;top:0;right:0;left:0;contain:size style;padding-top:var(--tyt-secondary-mt);padding-right:var(--tyt-secondary-mr);padding-bottom:var(--tyt-secondary-mb)}\n#right-tabs{position:relative;display:flex;padding:0;margin:0;flex-grow:1;flex-direction:column}\n[tyt-tab=""] #right-tabs{flex-grow:0}\n[tyt-tab=""] #right-tabs .tab-content{border:0}\n#right-tabs .tab-content{flex-grow:1}\nytd-watch-flexy[hide-default-text-inline-expander] #primary.style-scope.ytd-watch-flexy ytd-text-inline-expander{display:none}\nytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden{--comment-pre-load-sizing:90px;visibility:collapse;z-index:-1;position:fixed!important;left:2px;top:2px;width:var(--comment-pre-load-sizing)!important;height:var(--comment-pre-load-sizing)!important;display:block!important;pointer-events:none!important;overflow:hidden;contain:strict;border:0;margin:0;padding:0}\nytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections{display:block!important;overflow:hidden;height:var(--comment-pre-load-sizing);width:var(--comment-pre-load-sizing);contain:strict;border:0;margin:0;padding:0}\nytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents{display:flex!important;flex-direction:row;gap:60px;overflow:hidden;height:var(--comment-pre-load-sizing);width:var(--comment-pre-load-sizing);contain:strict;border:0;margin:0;padding:0}\nytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments #contents{--comment-pre-load-display:none}\nytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments #contents > :only-of-type,ytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments #contents > :last-child{--comment-pre-load-display:block}\nytd-watch-flexy:not([keep-comments-scroller]) #tab-comments.tab-content-hidden ytd-comments#comments #contents > *{display:var(--comment-pre-load-display)!important}\n#right-tabs #material-tabs{position:relative;display:flex;padding:0;border:1px solid var(--ytd-searchbox-legacy-border-color);overflow:hidden}\n[tyt-tab] #right-tabs #material-tabs{border-radius:var(--tyt-rounded-a1) var(--tyt-rounded-a1) var(--tyt-rounded-a1) var(--tyt-rounded-a1)}\n[tyt-tab^="#"] #right-tabs #material-tabs{border-radius:var(--tyt-rounded-a1) var(--tyt-rounded-a1) 0 0}\nytd-watch-flexy:not([is-two-columns_]) #right-tabs #material-tabs{outline:0}\n#right-tabs #material-tabs a.tab-btn[tyt-tab-content] > *{pointer-events:none}\n#right-tabs #material-tabs a.tab-btn[tyt-tab-content] > .font-size-right{pointer-events:initial;display:none}\nytd-watch-flexy #right-tabs .tab-content{padding:0;box-sizing:border-box;display:block;border:1px solid var(--ytd-searchbox-legacy-border-color);border-top:0;position:relative;top:0;display:flex;flex-direction:row;overflow:hidden;border-radius:0 0 var(--tyt-rounded-a1) var(--tyt-rounded-a1)}\nytd-watch-flexy:not([is-two-columns_]) #right-tabs .tab-content{height:100%}\nytd-watch-flexy #right-tabs .tab-content-cld{box-sizing:border-box;position:relative;display:block;width:100%;overflow:auto;--tab-content-padding:var(--ytd-margin-4x);padding:var(--tab-content-padding);contain:layout paint}\n.tab-content-cld,#right-tabs,.tab-content{transition:none;animation:none}\n#right-tabs #emojis.ytd-commentbox{inset:auto 0 auto 0;width:auto}\nytd-watch-flexy[is-two-columns_] #right-tabs .tab-content-cld{height:100%;width:100%;contain:size style;position:absolute}\nytd-watch-flexy #right-tabs .tab-content-cld.tab-content-hidden{display:none;width:100%;contain:size layout paint style}\n@supports (color: var(--tabview-tab-btn-define)) {\nytd-watch-flexy #right-tabs .tab-btn{background:var(--yt-spec-general-background-a)}\nhtml{--tyt-tab-btn-flex-grow:1;--tyt-tab-btn-flex-basis:0;--tyt-tab-bar-color-1-def:#ff4533;--tyt-tab-bar-color-2-def:var(--yt-sys-color-baseline--genai-4,var(--yt-sys-color-baseline--static-brand-red,var(--accent-color,var(--yt-brand-light-red))));--tyt-tab-bar-color-1:var(--main-color,var(--tyt-tab-bar-color-1-def));--tyt-tab-bar-color-2:var(--main-color,var(--tyt-tab-bar-color-2-def));--tyt-tab-text-primary:var(--yt-sys-color-baseline--text-primary,var(--yt-spec-text-primary));--tyt-tab-text-secondary:var(--yt-sys-color-baseline--text-secondary,var(--yt-spec-text-secondary))}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]{flex-grow:1;flex-shrink:1;flex-basis:0;flex-grow:var(--tyt-tab-btn-flex-grow);flex-basis:var(--tyt-tab-btn-flex-basis);position:relative;display:inline-block;text-decoration:none;text-transform:uppercase;--tyt-tab-btn-color:var(--tyt-tab-text-secondary);color:var(--tyt-tab-btn-color);text-align:center;padding:14px 8px 10px;border:0;border-bottom:4px solid transparent;font-weight:500;font-size:12px;line-height:18px;cursor:pointer;transition:border 200ms linear 100ms;background-color:var(--ytd-searchbox-legacy-button-color);text-transform:var(--yt-button-text-transform,inherit);user-select:none!important;overflow:hidden;white-space:nowrap;text-overflow:clip}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg{height:18px;padding-right:0;vertical-align:bottom;opacity:.5;margin-right:0;color:var(--yt-button-color,inherit);fill:var(--iron-icon-fill-color,currentcolor);stroke:var(--iron-icon-stroke-color,none)}\nytd-watch-flexy #right-tabs .tab-btn{--tabview-btn-txt-ml:8px}\nytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"]{--tabview-btn-txt-ml:0}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]>svg+span{margin-left:var(--tabview-btn-txt-ml)}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content] svg{pointer-events:none}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active{font-weight:500;outline:0;--tyt-tab-btn-color:var(--tyt-tab-text-primary);background-color:var(--ytd-searchbox-legacy-button-focus-color);border-bottom:2px var(--tyt-tab-bar-color-1) solid;border-bottom-color:var(--tyt-tab-bar-color-2)}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].active svg{opacity:.9}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover{background-color:var(--ytd-searchbox-legacy-button-hover-color);--tyt-tab-btn-color:var(--tyt-tab-text-primary)}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]:not(.active):hover svg{opacity:.9}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content]{user-select:none!important}\nytd-watch-flexy #right-tabs .tab-btn[tyt-tab-content].tab-btn-hidden{display:none}\nytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"],ytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"]:hover{--tyt-tab-btn-color:var(--yt-sys-color-baseline--text-disabled,var(--yt-spec-text-disabled))}\nytd-watch-flexy[tyt-comment-disabled] #right-tabs .tab-btn[tyt-tab-content="#tab-comments"] span#tyt-cm-count:empty{display:none}\nytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty::after{display:inline-block;width:4em;text-align:left;font-size:inherit;color:currentColor;transform:scaleX(0.8)}\n}\n@supports (color: var(--tyt-cm-count-define)) {\nytd-watch-flexy{--tyt-x-loading-content-letter-spacing:2px}\nhtml{--tabview-text-loading:Loading;--tabview-text-fetching:Fetching;--tabview-panel-loading:var(--tabview-text-loading)}\nytd-watch-flexy #right-tabs .tab-btn span#tyt-cm-count:empty::after{content:var(--tabview-text-loading);letter-spacing:var(--tyt-x-loading-content-letter-spacing)}\n}\n@supports (color: var(--tabview-font-size-btn-define)) {\n.font-size-right{display:inline-flex;flex-direction:column;position:absolute;right:0;top:0;bottom:0;width:16px;padding:4px 0;justify-content:space-evenly;align-content:space-evenly;pointer-events:none}\nhtml body ytd-watch-flexy.style-scope .font-size-btn{user-select:none!important}\n.font-size-btn{--tyt-font-size-btn-display:none;display:var(--tyt-font-size-btn-display,none);width:12px;height:12px;color:var(--tyt-tab-text-secondary);background-color:var(--yt-spec-badge-chip-background);box-sizing:border-box;cursor:pointer;transform-origin:left top;margin:0;padding:0;position:relative;font-family:\'Menlo\',\'Lucida Console\',\'Monaco\',\'Consolas\',monospace;line-height:100%;font-weight:900;transition:background-color 90ms linear,color 90ms linear;pointer-events:all}\n.font-size-btn:hover{background-color:var(--tyt-tab-text-primary);color:var(--yt-spec-general-background-a)}\n@supports (zoom: 0.5) {\n.tab-btn .font-size-btn{--tyt-font-size-btn-display:none}\n.tab-btn.active:hover .font-size-btn{--tyt-font-size-btn-display:inline-block}\n}\n}\nbody ytd-watch-flexy:not([is-two-columns_]) #columns.ytd-watch-flexy{flex-direction:column}\nbody ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy{display:block;width:100%;box-sizing:border-box}\nbody ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper{padding-left:var(--ytd-margin-6x);contain:content;height:initial}\nbody ytd-watch-flexy:not([is-two-columns_]) #secondary.ytd-watch-flexy secondary-wrapper #right-tabs{overflow:auto}\n[tyt-chat="+"]{--tyt-chat-grow:1}\n[tyt-chat="+"] secondary-wrapper > [tyt-chat-container]{flex-grow:var(--tyt-chat-grow);flex-shrink:0;display:flex;flex-direction:column}\n[tyt-chat="+"] secondary-wrapper > [tyt-chat-container] > #chat{flex-grow:var(--tyt-chat-grow)}\nytd-watch-flexy[is-two-columns_]:not([theater]) #columns.style-scope.ytd-watch-flexy{min-height:calc(100vh - var(--ytd-toolbar-height,56px))}\nytd-watch-flexy[is-two-columns_]:not([full-bleed-player]) ytd-live-chat-frame#chat{min-height:initial!important;height:initial!important}\nytd-watch-flexy[tyt-tab^="#"]:not([is-two-columns_]):not([tyt-chat="+"]) #right-tabs{min-height:var(--ytd-watch-flexy-chat-max-height)}\nbody ytd-watch-flexy:not([is-two-columns_]) #chat.ytd-watch-flexy{margin-top:0}\nbody ytd-watch-flexy:not([is-two-columns_]) ytd-watch-metadata.ytd-watch-flexy{margin-bottom:0}\nytd-watch-metadata.ytd-watch-flexy ytd-metadata-row-container-renderer{display:none}\n#tab-info [show-expand-button] #expand-sizer.ytd-text-inline-expander{visibility:initial}\n#tab-info #collapse.button.ytd-text-inline-expander{display:none}\n#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer > #left-arrow{border:6px solid transparent;opacity:.65}\n#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer >#right-arrow{border:6px solid transparent;opacity:.65}\n#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #left-arrow-container.ytd-video-description-infocards-section-renderer > #left-arrow:hover{opacity:1}\n#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > #right-arrow-container.ytd-video-description-infocards-section-renderer >#right-arrow:hover{opacity:1}\n#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > div#left-arrow-container::before{content:\'\';background:transparent;width:40px;display:block;height:40px;position:absolute;left:-20px;top:0;z-index:-1}\n#tab-info #social-links.style-scope.ytd-video-description-infocards-section-renderer > div#right-arrow-container::before{content:\'\';background:transparent;width:40px;display:block;height:40px;position:absolute;right:-20px;top:0;z-index:-1}\nbody ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy{flex-grow:1;flex-shrink:0;display:flex;flex-direction:column}\nbody ytd-watch-flexy[is-two-columns_][tyt-egm-panel_] #columns.style-scope.ytd-watch-flexy #panels.style-scope.ytd-watch-flexy ytd-engagement-panel-section-list-renderer[target-id][visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"]{height:0;max-height:initial;min-height:initial;flex-grow:1;flex-shrink:0;display:flex;flex-direction:column}\nsecondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] ytd-transcript-renderer:not(:empty),secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #body.ytd-transcript-renderer:not(:empty),secondary-wrapper [visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"] #content.ytd-transcript-renderer:not(:empty){flex-grow:1;height:initial;max-height:initial;min-height:initial}\nsecondary-wrapper #content.ytd-engagement-panel-section-list-renderer{position:relative}\nsecondary-wrapper #content.ytd-engagement-panel-section-list-renderer > [panel-target-id]:only-child{contain:style size}\nsecondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-list-renderer.ytd-transcript-search-panel-renderer{flex-grow:1;contain:strict}\nsecondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-renderer.style-scope.ytd-transcript-segment-list-renderer{contain:layout paint style}\nsecondary-wrapper #content.ytd-engagement-panel-section-list-renderer ytd-transcript-segment-renderer.style-scope.ytd-transcript-segment-list-renderer > .segment{contain:layout paint style}\nbody ytd-watch-flexy[theater] #secondary.ytd-watch-flexy{margin-top:var(--ytd-margin-3x);padding-top:0}\nbody ytd-watch-flexy[theater] secondary-wrapper{margin-top:0;padding-top:0}\nbody ytd-watch-flexy[theater] #chat.ytd-watch-flexy{margin-bottom:var(--ytd-margin-2x)}\n#tab-comments ytd-comments#comments [field-of-cm-count]{margin-top:0}\n#tab-info > ytd-expandable-video-description-body-renderer{margin-bottom:var(--ytd-margin-3x)}\n#tab-info [class]:last-child{margin-bottom:0;padding-bottom:0}\n#tab-info ytd-rich-metadata-row-renderer ytd-rich-metadata-renderer{max-width:initial}\nytd-watch-flexy[is-two-columns_] secondary-wrapper #chat.ytd-watch-flexy{margin-bottom:var(--ytd-margin-3x)}\nytd-watch-flexy[tyt-tab] tp-yt-paper-tooltip{white-space:nowrap;contain:content}\nytd-watch-info-text tp-yt-paper-tooltip.style-scope.ytd-watch-info-text{margin-bottom:-300px;margin-top:-96px}\n[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata{font-size:1.2rem;line-height:1.8rem}\n[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata yt-animated-rolling-number{font-size:inherit}\n[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata #info-container.style-scope.ytd-watch-info-text{align-items:center}\nytd-watch-flexy[hide-default-text-inline-expander]{--tyt-bottom-watch-metadata-margin:6px}\n[hide-default-text-inline-expander] #bottom-row #description.ytd-watch-metadata > #description-inner.ytd-watch-metadata{margin:6px 12px}\n[hide-default-text-inline-expander] ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata{font-size:1.8rem}\nytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-merch-shelf-renderer{padding:0;border:0;margin:0}\nytd-watch-flexy[is-two-columns_][hide-default-text-inline-expander] #below.style-scope.ytd-watch-flexy ytd-watch-metadata.ytd-watch-flexy{margin-bottom:6px}\n#tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--horizontal .yt-video-attribute-view-model__link-container .yt-video-attribute-view-model__hero-section{flex-shrink:0}\n#tab-info yt-video-attribute-view-model .yt-video-attribute-view-model__overflow-menu{background:var(--yt-emoji-picker-category-background-color);border-radius:99px}\n#tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--image-square.yt-video-attribute-view-model--image-large .yt-video-attribute-view-model__hero-section{max-height:128px}\n#tab-info yt-video-attribute-view-model .yt-video-attribute-view-model--image-large .yt-video-attribute-view-model__hero-section{max-width:128px}\n#tab-info ytd-reel-shelf-renderer #items.yt-horizontal-list-renderer ytd-reel-item-renderer.yt-horizontal-list-renderer{max-width:142px}\nytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #view-count.style-scope.ytd-watch-info-text{align-items:center}\nytd-watch-info-text#ytd-watch-info-text.style-scope.ytd-watch-metadata #date-text.style-scope.ytd-watch-info-text{align-items:center}\nytd-watch-info-text:not([detailed]) #info.ytd-watch-info-text a.yt-simple-endpoint.yt-formatted-string{pointer-events:none}\nbody ytd-app > ytd-popup-container > tp-yt-iron-dropdown > #contentWrapper > [slot="dropdown-content"]{backdrop-filter:none}\n#tab-info [tyt-clone-refresh-count]{overflow:visible!important}\n#tab-info #items.ytd-horizontal-card-list-renderer yt-video-attribute-view-model.ytd-horizontal-card-list-renderer{contain:layout}\n#tab-info #thumbnail-container.ytd-structured-description-channel-lockup-renderer{flex-shrink:0}\n#tab-info ytd-media-lockup-renderer[is-compact] #thumbnail-container.ytd-media-lockup-renderer{flex-shrink:0}\nsecondary-wrapper ytd-donation-unavailable-renderer{--ytd-margin-6x:var(--ytd-margin-2x);--ytd-margin-5x:var(--ytd-margin-2x);--ytd-margin-4x:var(--ytd-margin-2x);--ytd-margin-3x:var(--ytd-margin-2x)}\n[tyt-no-less-btn] #less{display:none}\n.tyt-metadata-hover-resized #purchase-button,.tyt-metadata-hover-resized #sponsor-button,.tyt-metadata-hover-resized #analytics-button,.tyt-metadata-hover-resized #subscribe-button{display:none!important}\n.tyt-metadata-hover #upload-info{max-width:max-content;min-width:max-content;flex-basis:100vw;flex-shrink:0}\n#tab-info ytd-structured-description-playlist-lockup-renderer[collections] #playlist-thumbnail.style-scope.ytd-structured-description-playlist-lockup-renderer{max-width:100%}\n#tab-info ytd-structured-description-playlist-lockup-renderer[collections] #lockup-container.ytd-structured-description-playlist-lockup-renderer{padding:1px}\n#tab-info ytd-structured-description-playlist-lockup-renderer[collections] #thumbnail.ytd-structured-description-playlist-lockup-renderer{outline:1px solid rgba(127,127,127,0.5)}\nytd-live-chat-frame#chat[collapsed] ytd-message-renderer ~ #show-hide-button.ytd-live-chat-frame>ytd-toggle-button-renderer.ytd-live-chat-frame{padding:0}\n.tyt-info-invisible{display:none}\n[tyt-playlist-expanded] secondary-wrapper > ytd-playlist-panel-renderer#playlist{overflow:auto;flex-shrink:1;flex-grow:1;max-height:unset!important}\n[tyt-playlist-expanded] secondary-wrapper > ytd-playlist-panel-renderer#playlist > #container{max-height:unset!important}\nsecondary-wrapper ytd-playlist-panel-renderer{--ytd-margin-6x:var(--ytd-margin-3x)}\nytd-watch-flexy[theater] ytd-playlist-panel-renderer[collapsible][collapsed] .header.ytd-playlist-panel-renderer{padding:6px 8px}\nytd-watch-flexy[theater] #playlist.ytd-watch-flexy{margin-bottom:var(--ytd-margin-2x)}\nytd-watch-flexy[theater] #right-tabs .tab-btn[tyt-tab-content]{padding:8px 4px 6px;border-bottom:0 solid transparent}\nytd-watch-flexy{--tyt-bottom-watch-metadata-margin:12px}\nytd-watch-flexy{--tyt-rounded-a1:12px}\nytd-watch-flexy[rounded-info-panel],ytd-watch-flexy[rounded-player-large]{--tyt-rounded-a1:12px}\n#bottom-row.style-scope.ytd-watch-metadata .item.ytd-watch-metadata{margin-right:var(--tyt-bottom-watch-metadata-margin,12px);margin-top:var(--tyt-bottom-watch-metadata-margin,12px)}\n#cinematics{contain:layout style size}\nbody[data-ytlstm-theater-mode] #secondary-inner[class] > secondary-wrapper[class]:not(#chat-container):not(#chat){display:flex!important}\nbody[data-ytlstm-theater-mode] secondary-wrapper{all:unset;height:100vh}\nbody[data-ytlstm-theater-mode] #right-tabs{display:none}\nbody[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] [tyt-chat="+"]{--tyt-chat-grow:unset}\nbody[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] #columns.style-scope.ytd-watch-flexy,body[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] #secondary.style-scope.ytd-watch-flexy,body[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] #secondary-inner.style-scope.ytd-watch-flexy,body[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] secondary-wrapper,body[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] #chat-container.style-scope,body[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] [tyt-chat-container].style-scope{pointer-events:none}\nbody[data-ytlstm-theater-mode] [data-ytlstm-chat-over-video] #chat[class]{pointer-events:auto}\n@supports (color: var(--tyt-fix-20251124)) {\n#below ytd-watch-metadata .ytTextCarouselItemViewModelImageType{height:16px;width:16px}\n#below ytd-watch-metadata yt-text-carousel-item-view-model{column-gap:6px}\n#below ytd-watch-metadata ytd-watch-info-text#ytd-watch-info-text{font-size:inherit;line-height:inherit}\n}\n '; (async () => { // (HMR, tampermonkey re-injection, double @require, etc.) would call if ("undefined" != typeof window && window.__ytpMainBootDone__) { return; } "undefined" != typeof window && (window.__ytpMainBootDone__ = !0); const t = "undefined" != typeof window && window.YouTubePlusDesignSystem || {}, e = `ck-${Date.now()}-${Math.floor(314159265359 * Math.random() + 314159265359).toString(36)}`, o = (async () => {})().constructor; document.documentElement || await new o(t => { const e = () => { document.documentElement ? t() : setTimeout(e, 0); }; e(); }); const r = `(${executionScript})("${e}");\n\n//# sourceURL=debug://tabview-youtube/tabview.execution.js\n`; !1 !== window.YouTubeUtils?.loadFeatureEnabled?.("enableTabview") && t.StyleManager && "function" == typeof t.StyleManager.add && t.StyleManager.add("yt-plus-tabview-core", styles_main), GM_addElement(document.head || document.documentElement, "script", { textContent: r }), window.addEventListener("youtube-plus-settings-updated", e => { try { !1 !== e?.detail?.enableTabview ? t.StyleManager && "function" == typeof t.StyleManager.add && t.StyleManager.add("yt-plus-tabview-core", styles_main) : t.StyleManager && "function" == typeof t.StyleManager.remove && t.StyleManager.remove("yt-plus-tabview-core"); } catch (t) {} }); })(), (function() { const t = window.YouTubeUtils, e = t?.$ || document.querySelector.bind(document), o = (t, e, o) => { if (!t || "object" != typeof t) { return; } if (!e || "string" != typeof e) { return; } if (!e.includes(".")) { return void (t[e] = o); } const r = e.split(".").filter(Boolean); if (!r.length) { return; } const i = r.pop(); if (!i) { return; } let a = t; for (const t of r) { Object.hasOwn(a, t) && "object" == typeof a[t] && a[t] || (a[t] = {}), a = a[t]; } a[i] = o; }, r = t => { t.downloadSites || (t.downloadSites = { externalDownloader: !0, ytdl: !0, direct: !0 }), t.downloadSites && Object.hasOwn(t.downloadSites, "y2mate") && (Object.hasOwn(t.downloadSites, "externalDownloader") || (t.downloadSites.externalDownloader = t.downloadSites.y2mate), delete t.downloadSites.y2mate); }, i = t => { try { const e = t.closest(".download-site-option"); if (e) { const o = e.querySelector(".download-site-controls"); o && (o.style.display = t.checked ? "block" : "none"); } } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "toggle download-site-controls failed:", t); } }, a = t => { try { t(); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "autosave downloadSite toggle failed:", t); } }, s = (t, o) => { const {settings: r, refreshDownloadButton: i} = o; try { o.updatePageBasedOnSettings && o.updatePageBasedOnSettings(), "enableDownload" === t ? (t => { const {settings: o, getElement: r, addDownloadButton: i} = t, a = r(".ytp-right-controls"), s = r(".ytp-download-button", !1); if (o.enableDownload) { a && !s && i(a); } else { s && s.remove(); const t = e(".download-options"); t && t.remove(); } })(o) : "enableSpeedControl" === t && (t => { const {settings: o, getElement: r, addSpeedControlButton: i} = t, a = r(".ytp-right-controls"), s = r(".speed-control-btn", !1); if (o.enableSpeedControl) { a && !s && i(a); } else { s && s.remove(); const t = e(".speed-options"); t && t.remove(); } })(o), i && i(); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "live apply specific toggle failed:", t); } (t => { "undefined" != typeof window && window.youtubePlus && (window.youtubePlus.settings = window.youtubePlus.settings || t); })(r); }, c = t => { try { "undefined" != typeof window && window.youtubePlus && "function" == typeof window.youtubePlus.rebuildDownloadDropdown && (window.youtubePlus.settings = window.youtubePlus.settings || t, window.youtubePlus.rebuildDownloadDropdown()); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "rebuildDownloadDropdown call failed:", t); } }, l = t => { t.downloadSiteCustomization || (t.downloadSiteCustomization = { externalDownloader: { name: "SSYouTube", url: "https://ssyoutube.com/watch?v={videoId}" } }), t.downloadSiteCustomization.externalDownloader || (t.downloadSiteCustomization.externalDownloader = { name: "", url: "" }); }, d = () => { try { "undefined" != typeof window && window.youtubePlus && "function" == typeof window.youtubePlus.rebuildDownloadDropdown && window.youtubePlus.rebuildDownloadDropdown(); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "rebuildDownloadDropdown call failed:", t); } }, u = [ "none", "ctrl", "alt", "shift", "ctrl+alt", "ctrl+shift", "alt+shift", "ctrl+alt+shift" ]; "undefined" != typeof window && (window.YouTubePlusModalHandlers = { setSettingByPath: o, initializeDownloadSites: r, toggleDownloadSiteControls: i, safelySaveSettings: a, handleDownloadSiteToggle: (e, o, s, l, d) => { r(s); const u = e; s.downloadSites[o] = u.checked; try { l(); } catch (e) { t.logSuppressed(e, "ModalHandlers"); } i(u), c(s), a(d); }, handleSimpleSettingToggle: (e, r, i, a, c, l, d) => { const u = e.checked; if (o(i, r, u), "zenStyles.sideVideosColumnsEnabled" === r && u) { const t = Number(i.zenStyles?.sideVideosColumns); if (!Number.isFinite(t) || t <= 0) { o(i, "zenStyles.sideVideosColumns", 1); const t = d.querySelector('.style-side-videos-submenu select[data-setting="zenStyles.sideVideosColumns"]'); t instanceof HTMLSelectElement && (t.value = "1"); } } try { c(); } catch (e) { t.logSuppressed(e, "ModalHandlers"); } try { s(r, a); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "apply settings live failed:", t); } try { l(); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "autosave simple setting failed:", t); } if ("enableDownload" === r) { const t = d.querySelector(".download-submenu"); t && (t.style.display = u ? "block" : "none"); const e = d.querySelector('.ytp-plus-submenu-toggle[data-submenu="download"]'); e instanceof HTMLElement && (u ? (e.removeAttribute("disabled"), e.setAttribute("aria-expanded", "true"), e.style.display = "inline-flex") : (e.setAttribute("disabled", ""), e.setAttribute("aria-expanded", "false"), e.style.display = "none")); } if ("enableZenStyles" === r) { const t = d.querySelector(".style-submenu"); t && (t.style.display = u ? "block" : "none"); const e = d.querySelector('.ytp-plus-submenu-toggle[data-submenu="style"]'); e instanceof HTMLElement && (u ? (e.removeAttribute("disabled"), e.setAttribute("aria-expanded", "true"), e.style.display = "inline-flex") : (e.setAttribute("disabled", ""), e.setAttribute("aria-expanded", "false"), e.style.display = "none")); } if ("zenStyles.sideVideosColumnsEnabled" === r) { const t = d.querySelector('.style-side-videos-submenu[data-submenu="style-side-videos"]'); t instanceof HTMLElement && (t.style.display = u ? "block" : "none"); const e = d.querySelector('.ytp-plus-submenu-toggle[data-submenu="style-side-videos"]'); e instanceof HTMLElement && (u ? (e.removeAttribute("disabled"), e.setAttribute("aria-expanded", "true"), e.style.display = "inline-flex") : (e.setAttribute("disabled", ""), e.setAttribute("aria-expanded", "false"), e.style.display = "none")); } if ("enableSpeedControl" === r) { const t = d.querySelector(".speed-submenu"); t && (t.style.display = u ? "block" : "none"); const e = d.querySelector('.ytp-plus-submenu-toggle[data-submenu="speed"]'); e instanceof HTMLElement && (u ? (e.removeAttribute("disabled"), e.setAttribute("aria-expanded", "true"), e.style.display = "inline-flex") : (e.setAttribute("disabled", ""), e.setAttribute("aria-expanded", "false"), e.style.display = "none")); } if ("enableEnhanced" === r) { const t = d.querySelector(".enhanced-submenu"); t && (t.style.display = u ? "block" : "none"); const e = d.querySelector('.ytp-plus-submenu-toggle[data-submenu="enhanced"]'); e instanceof HTMLElement && (u ? (e.removeAttribute("disabled"), e.setAttribute("aria-expanded", "true"), e.style.display = "inline-flex") : (e.setAttribute("disabled", ""), e.setAttribute("aria-expanded", "false"), e.style.display = "none")); } if ("enableLoop" === r) { const t = d.querySelector(".loop-submenu"); t && (t.style.display = u ? "block" : "none"); const e = d.querySelector('.ytp-plus-submenu-toggle[data-submenu="loop"]'); e instanceof HTMLElement && (u ? (e.removeAttribute("disabled"), e.setAttribute("aria-expanded", "true"), e.style.display = "inline-flex") : (e.setAttribute("disabled", ""), e.setAttribute("aria-expanded", "false"), e.style.display = "none")); } }, handleDownloadSiteInput: (e, o, r, i, a, s) => { (t => { t.downloadSiteCustomization || (t.downloadSiteCustomization = { externalDownloader: { name: "SSYouTube", url: "https://ssyoutube.com/watch?v={videoId}" } }), t.downloadSiteCustomization && Object.hasOwn(t.downloadSiteCustomization, "y2mate") && (Object.hasOwn(t.downloadSiteCustomization, "externalDownloader") || (t.downloadSiteCustomization.externalDownloader = t.downloadSiteCustomization.y2mate), delete t.downloadSiteCustomization.y2mate); })(i), ((t, e) => { t.downloadSiteCustomization[e] || (t.downloadSiteCustomization[e] = { name: "", url: "" }); })(i, o), i.downloadSiteCustomization[o][r] = e.value; try { a(); } catch (e) { t.logSuppressed(e, "ModalHandlers"); } "name" === r && ((t, e, o) => { const r = t.closest(".download-site-option")?.querySelector(".download-site-name"); if (r) { const i = t.value, a = ((t, e) => "externalDownloader" === t ? "SSYouTube" : e("ytdl" === t ? "byYTDL" : "directDownload"))(e, o); r.textContent = i || a; } })(e, o, s), c(i); }, handleExternalDownloaderSave: (t, e, o, r, i) => { l(e); const a = t.closest(".download-site-option"); a && ((t, e) => { const o = t.querySelector('input.download-site-input[data-site="externalDownloader"][data-field="name"]'), r = t.querySelector('input.download-site-input[data-site="externalDownloader"][data-field="url"]'); o && (e.downloadSiteCustomization.externalDownloader.name = o.value), r && (e.downloadSiteCustomization.externalDownloader.url = r.value); })(a, e), o(), window.youtubePlus && (window.youtubePlus.settings = window.youtubePlus.settings || e), d(); try { r(i && "function" == typeof i && i("externalDownloaderSettingsSaved") || i("y2mateSettingsSaved")); } catch (t) { r("Settings saved"); } }, handleExternalDownloaderReset: (t, e, o, r, i) => { (t => { l(t), t.downloadSiteCustomization.externalDownloader = { name: "SSYouTube", url: "https://ssyoutube.com/watch?v={videoId}" }; })(e); const a = t.querySelector(".download-site-option"); a && ((t, e) => { const o = t.querySelector('input.download-site-input[data-site="externalDownloader"][data-field="name"]'), r = t.querySelector('input.download-site-input[data-site="externalDownloader"][data-field="url"]'), i = t.querySelector(".download-site-name"), a = e.downloadSiteCustomization.externalDownloader; o && (o.value = a.name), r && (r.value = a.url), i && (i.textContent = a.name); })(a, e), o(), window.youtubePlus && (window.youtubePlus.settings = window.youtubePlus.settings || e), d(); try { r(i && "function" == typeof i && i("externalDownloaderReset") || i("y2mateReset")); } catch (t) { r("Settings reset"); } }, handleSidebarNavigation: (e, o) => { const r = e.dataset?.section, i = "true" === o.getAttribute("data-ytp-inline-fallback"); o.querySelectorAll(".ytp-plus-settings-nav-item").forEach(t => t.classList.remove("active")), o.querySelectorAll(".ytp-plus-settings-section").forEach(t => { t.classList.add("hidden"), i && t instanceof HTMLElement && (t.style.display = "none"); }), e.classList.add("active"); const a = o.querySelector("#ytp-plus-active-section-label"); a && (a.textContent = e.dataset?.label || ""); const s = o.querySelector(`.ytp-plus-settings-section[data-section="${r}"]`); s && (s.classList.remove("hidden"), i && s instanceof HTMLElement && (s.style.display = "")), "voting" === r && window.YouTubePlus?.Voting?.initSlider && requestAnimationFrame(() => window.YouTubePlus.Voting.initSlider()); try { localStorage.setItem("ytp-plus-active-nav-section", r); } catch (e) { t.logSuppressed(e, "ModalHandlers"); } try { document.dispatchEvent(new CustomEvent("youtube-plus-settings-section-activated", { detail: { section: r, label: e.dataset?.label || "" }, bubbles: !0 })); } catch (e) { t.logSuppressed(e, "ModalHandlers"); } }, applySettingLive: s, handleMusicSettingToggle: (e, o, r, i) => { try { const a = { enableMusic: !0, immersiveSearchStyles: !0, hoverStyles: !0, playerSidebarStyles: !0, centeredPlayerStyles: !0, playerBarStyles: !0, centeredPlayerBarStyles: !0, miniPlayerStyles: !0, scrollToTopStyles: !0 }; if (!new Set(Object.keys(a)).has(o)) { return; } let s = { ...a }; try { if ("undefined" != typeof GM_getValue) { const t = GM_getValue("youtube-plus-music-settings", null); if ("string" == typeof t && t) { const e = JSON.parse(t); e && "object" == typeof e && (s = { ...s, ...e }); } } } catch (e) { t.logSuppressed(e, "ModalHandlers"); } try { const t = localStorage.getItem("youtube-plus-music-settings"); if (t) { const e = JSON.parse(t); e && "object" == typeof e && (s = { ...s, ...e }); } } catch (e) { t.logSuppressed(e, "ModalHandlers"); } s[o] = e.checked; try { if ("enableMusic" === o) { const t = !!s.enableMusic, o = e.closest(".ytp-plus-settings-section") || e.closest(".ytp-plus-settings-panel"); if (o) { const e = o.querySelector('.music-submenu[data-submenu="music"]'); e instanceof HTMLElement && (e.style.display = t ? "block" : "none"); const r = o.querySelector('.ytp-plus-submenu-toggle[data-submenu="music"]'); r instanceof HTMLElement && (t ? (r.removeAttribute("disabled"), r.style.display = "inline-flex") : (r.setAttribute("disabled", ""), r.style.display = "none"), r.setAttribute("aria-expanded", t ? "true" : "false")); } } } catch (e) { t.logSuppressed(e, "ModalHandlers"); } localStorage.setItem("youtube-plus-music-settings", JSON.stringify(s)); try { "undefined" != typeof GM_setValue && GM_setValue("youtube-plus-music-settings", JSON.stringify(s)); } catch (e) { t.logSuppressed(e, "ModalHandlers"); } "undefined" != typeof window && window.YouTubeMusic && (window.YouTubeMusic.saveSettings && window.YouTubeMusic.saveSettings(s), window.YouTubeMusic.applySettingsChanges && window.YouTubeMusic.applySettingsChanges()), r && i && r(i("musicSettingsSaved")); } catch (t) { window.YouTubePlusLogger?.warn?.("ModalHandlers", "handleMusicSettingToggle failed"); } }, isMusicSetting: t => "enableMusic" === t || "immersiveSearchStyles" === t || "hoverStyles" === t || "playerSidebarStyles" === t || "centeredPlayerStyles" === t || "playerBarStyles" === t || "centeredPlayerBarStyles" === t || "miniPlayerStyles" === t || "scrollToTopStyles" === t, createFocusTrap: t => { const e = e => { if ("Tab" !== e.key) { return; } const o = Array.from(t.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter(t => null !== t.offsetParent); if (0 === o.length) { return; } const r = o[0], i = o[o.length - 1]; e.shiftKey ? document.activeElement === r && (e.preventDefault(), i.focus()) : document.activeElement === i && (e.preventDefault(), r.focus()); }; return t.addEventListener("keydown", e), () => t.removeEventListener("keydown", e); }, initGlassDropdown: t => { const e = t?.dropdown, o = t?.hiddenSelect; if (!e || !o) { return; } const r = e.querySelector(".glass-dropdown__toggle"), i = e.querySelector(".glass-dropdown__list"), a = e.querySelector(".glass-dropdown__label"); if (!(r instanceof HTMLElement && i instanceof HTMLElement)) { return; } let s = Array.from(i.querySelectorAll(".glass-dropdown__item")), c = s.findIndex(t => "true" === t.getAttribute("aria-selected")); c < 0 && (c = 0); const l = () => { e.setAttribute("aria-expanded", "true"), i.style.display = "block", s = Array.from(i.querySelectorAll(".glass-dropdown__item")), i.classList.remove("glass-dropdown__list--down"); let t = e.parentElement; for (;t && t !== document.body; ) { const e = window.getComputedStyle(t).overflowY; if ("auto" === e || "scroll" === e || "hidden" === e) { break; } t = t.parentElement; } if (t) { const e = r.getBoundingClientRect(), o = t.getBoundingClientRect(), a = i.getBoundingClientRect(); e.top - o.top < (a.height > 0 ? a.height : Math.min(36 * s.length, 220)) + 8 && i.classList.add("glass-dropdown__list--down"); } }, d = () => { e.setAttribute("aria-expanded", "false"), i.style.display = "none", i.classList.remove("glass-dropdown__list--down"); }; r.addEventListener("click", t => { t.stopPropagation(), "true" === e.getAttribute("aria-expanded") ? d() : l(); }), document.addEventListener("click", t => { e.contains(t.target) || d(); }), e.addEventListener("keydown", t => { const r = "true" === e.getAttribute("aria-expanded"); if ("ArrowDown" === t.key) { t.preventDefault(), r || l(), c = Math.min(c + 1, s.length - 1), s.forEach(t => t.removeAttribute("aria-selected")), s[c].setAttribute("aria-selected", "true"), s[c].scrollIntoView({ block: "nearest" }); } else if ("ArrowUp" === t.key) { t.preventDefault(), r || l(), c = Math.max(c - 1, 0), s.forEach(t => t.removeAttribute("aria-selected")), s[c].setAttribute("aria-selected", "true"), s[c].scrollIntoView({ block: "nearest" }); } else if ("Enter" === t.key || " " === t.key) { if (t.preventDefault(), !r) { return void l(); } const e = s[c]; e && (o.value = e.dataset?.value ?? o.value, a && (a.textContent = e.textContent ?? ""), o.dispatchEvent(new Event("change", { bubbles: !0 })), d()); } else { "Escape" === t.key && d(); } }), i.addEventListener("click", t => { const e = t.target && t.target.closest?.(".glass-dropdown__item"); e instanceof HTMLElement && (o.value = e.dataset?.value ?? o.value, i.querySelectorAll(".glass-dropdown__item").forEach(t => t.removeAttribute("aria-selected")), e.setAttribute("aria-selected", "true"), a && (a.textContent = e.textContent ?? ""), o.dispatchEvent(new Event("change", { bubbles: !0 })), d()); }); }, modifierComboValues: u, resolveModifierComboValue: t => { const e = !!t?.ctrlKey, o = !!t?.altKey, r = !!t?.shiftKey; return e && o && r ? "ctrl+alt+shift" : e && o ? "ctrl+alt" : e && r ? "ctrl+shift" : o && r ? "alt+shift" : e ? "ctrl" : o ? "alt" : r ? "shift" : "none"; }, formatModifierComboLabel: (t, e) => { if ("none" === t) { return e?.noneLabel || "None"; } const o = e?.translatePart; return t.split("+").map(t => o ? o(t) : t).map(t => "string" == typeof t && t.length ? t.charAt(0).toUpperCase() + t.slice(1) : t).join("+"); }, buildModifierComboOptionItems: (t, e) => u.map(o => `<option value="${o}"${o === t ? " selected" : ""}>${e(o)}</option>`).join(""), buildModifierComboDropdownItems: (t, e) => u.map(o => `<li class="glass-dropdown__item" data-value="${o}" role="option"${o === t ? ' aria-selected="true"' : ""}>${e(o)}</li>`).join("") }); })(), /** * YouTube+ Download Module * Unified download system with button UI and download functionality * @version 3.0 */ (function() { function t() { return "undefined" != typeof unsafeWindow ? unsafeWindow : window; } function e(t) { try { if (!t || -1 === t.indexOf("/api/timedtext")) { return; } const e = new URL(t, "https://www.youtube.com"), o = e.searchParams.get("v"), r = e.searchParams.get("pot"); if (!o || !r) { return; } const i = {}; for (const t of rt) { const o = e.searchParams.get(t); null != o && "" !== o && (i[t] = o); } if (ot.set(o, i), ot.size > 50) { const t = ot.keys().next().value; void 0 !== t && ot.delete(t); } } catch (t) {} } function o(t) { try { return new URL(t, "https://www.youtube.com").searchParams.get("v") || ""; } catch (t) { return ""; } } function r() { if (G?.getVideoIdFromLocation) { return G.getVideoIdFromLocation(); } try { const t = new URLSearchParams(window.location.search || "").get("v"); if (t) { return t; } const e = window.location.pathname || "", o = e.match(/^\/shorts\/([a-zA-Z0-9_-]{11})/); if (o?.[1]) { return o[1]; } const r = e.match(/^\/live\/([a-zA-Z0-9_-]{11})/); if (r?.[1]) { return r[1]; } const i = (window.location.href || "").match(/youtu\.be\/([a-zA-Z0-9_-]{11})/); if (i?.[1]) { return i[1]; } } catch (t) { G?.logSuppressed?.(t, "Download"); } return null; } function i() { const t = r(); return t ? `https://www.youtube.com/watch?v=${t}` : window.location.href; } function a() { try { const t = ut("h1.ytd-video-primary-info-renderer yt-formatted-string") || ut("h1.title yt-formatted-string") || ut("ytd-watch-metadata h1"); return t ? t.textContent.trim() : "video"; } catch (t) { return "video"; } } function s(t) { return t.replace(/[<>:"/\\|?*]/g, "").replace(/[\x00-\x1f\x7f\u200b-\u200f\u2028-\u202f\ufeff]/g, "").replace(/\s+/g, " ").trim().substring(0, 200); } function c(t) { if (0 === t) { return "0 B"; } const e = Math.floor(Math.log(t) / Math.log(1024)); return `${parseFloat((t / 1024 ** e).toFixed(2))} ${[ "B", "KB", "MB", "GB" ][e]}`; } function l(t, e, o) { return { ...t, onload: o => { t.onload && t.onload(o), e(o); }, onerror: e => { t.onerror && t.onerror(e), o(e); }, ontimeout: () => { t.ontimeout && t.ontimeout(), o(new Error("Request timeout")); } }; } function d(t) { return new Promise((e, o) => { if (t.url && !ft.canRequest(t.url)) { return void o(new Error("[YouTube+ Download] Rate limit exceeded — request blocked")); } if ("undefined" != typeof GM_xmlhttpRequest) { return void GM_xmlhttpRequest(l(t, e, o)); } const r = globalThis.GM; r && "function" == typeof r.xmlHttpRequest ? r.xmlHttpRequest(l(t, e, o)) : (async () => { try { const o = await (async function(t) { const e = { method: t.method || "GET", headers: t.headers || {}, body: t.data || t.body || void 0 }, o = await fetch(t.url, e), r = (function(t) { return { status: t.status, statusText: t.statusText, finalUrl: t.url, headers: {}, responseText: null, response: null }; })(o); return await (async function(t, e) { try { e.responseText = await t.text(); } catch (t) { e.responseText = null; } })(o, r), await (async function(t, e, o) { if ("blob" === o) { try { e.response = await t.blob(); } catch (t) { e.response = null; } } })(o, r, t.responseType), t.onload && t.onload(r), r; })(t); e(o); } catch (e) { t.onerror && t.onerror(e), o(e); } })(); }); } async function u(t) { const e = bt.get(t); if (e) { return e; } const o = await d({ method: "POST", url: "https://www.youtube.com/youtubei/v1/player", headers: { "Content-Type": "application/json", "User-Agent": mt.HEADERS["User-Agent"] }, data: JSON.stringify({ context: { client: { clientName: "WEB", clientVersion: "2.20240304.00.00" } }, videoId: t }) }); if (200 !== o.status) { throw new Error(`Failed to get player data: ${o.status}`); } const r = JSON.parse(o.responseText); return bt.set(t, r), r; } function p(t) { const e = t?.streamingData || {}, o = [ ...Array.isArray(e.formats) ? e.formats : [], ...Array.isArray(e.adaptiveFormats) ? e.adaptiveFormats : [] ], r = new Set; return o.forEach(t => { if (!String(t?.mimeType || "").includes("video/")) { return; } const e = String(t?.qualityLabel || "").trim().match(/(\d{3,4})p/i); e && r.add(e[1]); }), Array.from(r).sort((t, e) => Number(t) - Number(e)); } function y(t, e) { if (e < 0 || e >= t.length || "{" !== t[e]) { return null; } let o = 0, r = !1, i = !1; for (let a = e; a < t.length; a++) { const s = t[a]; if (i) { i = !1; } else if (r) { "\\" === s ? i = !0 : '"' === s && (r = !1); } else if ('"' === s) { r = !0; } else if ("{" === s) { o++; } else if ("}" === s && (o--, 0 === o)) { return t.slice(e, a + 1); } } return null; } async function m(t) { try { const e = `https://www.youtube.com/watch?v=${encodeURIComponent(t)}`, o = await d({ method: "GET", url: e }); if (200 !== o.status || !o.responseText) { return null; } const r = String(o.responseText), i = /ytInitialPlayerResponse\s*=\s*\{/g; let a; for (;null !== (a = i.exec(r)); ) { const t = y(r, a.index + a[0].length - 1); if (t) { try { return JSON.parse(t); } catch (t) {} } } return null; } catch (t) { return tt.warn("Watch HTML subtitle fallback failed:", t), null; } } function f(t) { const e = b(t); return e ? e.includes("fmt=") ? e : `${e}&fmt=srv1` : ""; } function b(t) { const e = String(t || "").trim(); return e ? e.replace(/&/g, "&") : ""; } async function h(t) { const e = String(t?.responseText || "").trim(); if (e) { return e; } const o = t?.response; if ("string" == typeof o && o.trim()) { return o.trim(); } const r = t?.responseXML; if (r && window.XMLSerializer) { try { const t = (new window.XMLSerializer).serializeToString(r).trim(); if (t) { return t; } } catch (t) {} } if (o && "object" == typeof o) { const t = o; if ("string" == typeof t?.documentElement?.nodeName && window.XMLSerializer) { try { const e = (new window.XMLSerializer).serializeToString(t).trim(); if (e) { return e; } } catch (t) {} } } if (o && o instanceof ArrayBuffer) { try { return window.TextDecoder ? new window.TextDecoder("utf-8").decode(o).trim() : ""; } catch (t) { return ""; } } if (o && ArrayBuffer.isView(o)) { try { const t = o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength); if (window.TextDecoder) { return new window.TextDecoder("utf-8").decode(t).trim(); } } catch (t) {} } if ("undefined" != typeof Blob && o instanceof Blob) { try { return (await o.text()).trim(); } catch (t) {} } if (o && "object" == typeof o) { const t = o, e = t.text || t.data || t.content; if ("string" == typeof e && e.trim()) { return e.trim(); } if ("function" == typeof t.text) { try { const e = await t.text(); if ("string" == typeof e && e.trim()) { return e.trim(); } } catch (t) {} } } return ""; } function g(t) { return t.map(t => ({ name: t.name?.simpleText || t.languageCode, languageCode: t.languageCode, url: f(t.baseUrl), baseUrl: b(t.baseUrl), isAutoGenerated: "asr" === t.kind, trackId: String(t?.vssId || ""), kind: String(t?.kind || "") })); } function w(t, e = {}) { const o = Array.isArray(t) ? t.filter(Boolean) : []; if (0 === o.length) { return null; } const r = String(e.languageCode || "").trim(), i = b(e.baseUrl || ""), a = String(e.trackId || "").trim(), s = "boolean" == typeof e.isAutoGenerated ? e.isAutoGenerated : null, c = t => { let e = 0; const o = b(t?.baseUrl || ""), c = String(t?.languageCode || ""), l = String(t?.vssId || ""), d = "asr" === t?.kind, u = r ? r.split("-")[0] : ""; return a && l && l === a && (e += 120), i && o && o === i && (e += 100), r && c === r ? e += 40 : u && c.startsWith(u) && (e += 20), null !== s && (e += d === s ? 15 : -5), !1 !== t?.isTranslatable && (e += 5), o && (e += 2), e; }; return o.map(t => ({ track: t, score: c(t) })).sort((t, e) => e.score - t.score)[0]?.track || null; } function v(t, e) { const o = b(e?.baseUrl || ""), r = String(e?.languageCode || ""), i = String(e?.vssId || ""); return t.map(t => ({ name: t.languageName?.simpleText || t.languageCode, languageCode: t.languageCode, sourceLanguageCode: r || "", baseUrl: o, url: f(o), isAutoGenerated: "asr" === e?.kind, trackId: i, translateTo: t.languageCode })); } async function x(e) { try { let o = null; try { o = await u(e); } catch (t) { tt.warn("Primary subtitle API request failed, trying page fallback:", t); } let r = (function() { try { const e = a(), o = t(), r = o.ytInitialPlayerResponse, i = r?.captions?.playerCaptionsTracklistRenderer; if (i) { return { captions: i, videoTitle: r?.videoDetails?.title || e }; } const s = G.byId("movie_player"), c = s instanceof HTMLElement ? s : null, l = "function" == typeof c?.getPlayerResponse && c.getPlayerResponse() || null, d = l?.captions?.playerCaptionsTracklistRenderer; if (d) { return { captions: d, videoTitle: l?.videoDetails?.title || e }; } const u = o?.ytplayer?.config?.args?.player_response; if ("string" == typeof u && u.length > 0) { try { const t = JSON.parse(u), o = t?.captions?.playerCaptionsTracklistRenderer; if (o) { return { captions: o, videoTitle: t?.videoDetails?.title || e }; } } catch (t) { G.logSuppressed(t, "Download"); } } } catch (t) { tt.warn("Subtitle fallback extraction failed:", t); } return null; })(); if (!r) { const t = await m(e); t?.captions?.playerCaptionsTracklistRenderer && (r = { captions: t.captions.playerCaptionsTracklistRenderer, videoTitle: t?.videoDetails?.title || a() }); } const i = o?.videoDetails?.title || r?.videoTitle || "video", s = o?.captions?.playerCaptionsTracklistRenderer || r?.captions || null; if (!s) { return (function(t, e) { return { videoId: t, videoTitle: e, subtitles: [], autoTransSubtitles: [] }; })(e, i); } const c = s.captionTracks || [], l = s.translationLanguages || [], d = (function(t) { return w(t, { isAutoGenerated: !0 }) || w(t) || null; })(c); return { videoId: e, videoTitle: i, subtitles: g(c), autoTransSubtitles: v(l, d) }; } catch (t) { return tt.error("Error getting subtitles:", t), null; } } function k(t) { const e = [], o = String(t || "").replace(/\uFEFF/g, ""), r = "function" == typeof window.DOMParser ? new window.DOMParser : null; if (r) { try { const t = r.parseFromString(o, "text/xml"); "parsererror" === (t.documentElement?.nodeName?.toLowerCase?.() || "") || t.getElementsByTagName("parsererror").length > 0 || Array.from(t.getElementsByTagName("text")).forEach(t => { const o = parseFloat(t.getAttribute("start") || "0"), r = parseFloat(t.getAttribute("dur") || "0"), i = S(String(t.textContent || "").trim()); i && e.push({ start: o, duration: r, text: i }); }); } catch (t) {} } if (e.length > 0) { return e; } const i = /<text\b([^>]*)>([\s\S]*?)<\/text>/gi; let a; for (;null !== (a = i.exec(o)); ) { const t = a[1] || "", o = /\bstart\s*=\s*["']([^"']+)["']/i.exec(t)?.[1] || "0", r = /\bdur\s*=\s*["']([^"']+)["']/i.exec(t)?.[1] || "0", i = parseFloat(o || "0"), s = parseFloat(r || "0"); let c = a[2] || ""; c = c.replace(/<!\[CDATA\[(.*?)\]\]>/g, "$1"), c = S(c.replace(/<br\s*\/?>/gi, " ").trim()), c = c.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim(), c && e.push({ start: i, duration: s, text: c }); } const s = /<p\b([^>]*)>([\s\S]{0,20000}?)<\/p>/gi; for (;null !== (a = s.exec(o)); ) { const t = a[1] || "", o = a[2] || "", r = /\bt="([^"]+)"/i.exec(t)?.[1] || "0", i = /\bd="([^"]+)"/i.exec(t)?.[1] || "0", s = Math.max(0, Number(r) / 1e3), c = Math.max(0, Number(i) / 1e3), l = S((o.includes("<s") ? o.replace(/<s\b[^>]*>/gi, "").replace(/<\/s>/gi, "").replace(/<br\s*\/?>/gi, " ") : o).replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim()); l && e.push({ start: s, duration: c > 0 ? c : 2, text: l }); } return e; } function S(t) { return t.replace(/&(#x?[0-9A-Fa-f]+|[a-zA-Z]+);/g, (t, e) => { if (ht[e]) { return ht[e]; } if (e.startsWith("#") && !e.startsWith("#x")) { const o = parseInt(e.slice(1), 10); return o > 0 && o < 1114111 ? String.fromCharCode(o) : t; } if (e.startsWith("#x")) { const o = parseInt(e.slice(2), 16); return o > 0 && o < 1114111 ? String.fromCharCode(o) : t; } return t; }); } function T(t) { const e = Math.floor(t / 3600), o = Math.floor(t % 3600 / 60), r = Math.floor(t % 60), i = Math.floor(t % 1 * 1e3); return `${String(e).padStart(2, "0")}:${String(o).padStart(2, "0")}:${String(r).padStart(2, "0")},${String(i).padStart(3, "0")}`; } function L(t) { try { const e = JSON.parse(t), o = Array.isArray(e?.events) ? e.events : [], r = []; return o.forEach(t => { const e = (Array.isArray(t?.segs) ? t.segs : []).map(t => String(t?.utf8 || "")).join("").replace(/\s+/g, " ").trim(); if (!e) { return; } const o = Number(t?.tStartMs || 0) / 1e3, i = Math.max(0, Number(t?.dDurationMs || 0) / 1e3); r.push({ start: o, duration: i, text: e }); }), r; } catch (t) { return []; } } function M(t) { const e = [], o = String(t || "").replace(/\r/g, "").split(/\n\n+/), r = t => { const e = String(t || "").trim(); if (!e) { return 0; } const o = e.split(":"); if (2 !== o.length && 3 !== o.length) { return 0; } if (!o.every(t => { if (!t) { return !1; } let e = !1; for (let o = 0; o < t.length; o += 1) { const r = t[o]; if (!(r >= "0" && r <= "9")) { if ("." !== r || e) { return !1; } e = !0; } } return !0; })) { return 0; } let r = 0, i = 0, a = ""; 2 === o.length ? (i = Number(o[0]), a = o[1]) : (r = Number(o[0]), i = Number(o[1]), a = o[2]); const s = a.indexOf("."), c = Number(s >= 0 ? a.slice(0, s) : a), l = s >= 0 ? a.slice(s + 1) : "", d = l ? Number(l.padEnd(3, "0").slice(0, 3)) : 0; return Number.isFinite(r) && Number.isFinite(i) && Number.isFinite(c) && Number.isFinite(d) ? 3600 * r + 60 * i + c + d / 1e3 : 0; }; return o.forEach(t => { const o = t.split("\n").map(t => t.trim()).filter(Boolean); if (0 === o.length) { return; } if ("WEBVTT" === o[0]) { return; } const i = o.findIndex(t => t.includes("--\x3e")); if (i < 0) { return; } const a = o[i].split("--\x3e"); if (a.length < 2) { return; } const s = r(a[0]), c = r(a[1].split(" ")[0]), l = Math.max(0, c - s), d = o.slice(i + 1).join(" ").replace(/<[^>]*>/g, "").replace(/\s+/g, " ").trim(); d && e.push({ start: s, duration: l, text: d }); }), e; } function C(t) { const e = [], o = String(t || "").replace(/\uFEFF/g, ""), r = /<p\b([^>]*)>([\s\S]{0,20000}?)<\/p>/gi, i = t => { const e = String(t || "").trim(); if (!e) { return 0; } const o = e[e.length - 1]; if ("s" === o || "S" === o) { const t = Number(e.slice(0, -1)); return Number.isFinite(t) ? t : 0; } const r = e.split(":"); if (2 !== r.length && 3 !== r.length) { return 0; } if (!r.every(t => { if (!t) { return !1; } let e = !1; for (let o = 0; o < t.length; o += 1) { const r = t[o]; if (!(r >= "0" && r <= "9")) { if ("." !== r || e) { return !1; } e = !0; } } return !0; })) { return 0; } let i = 0, a = 0, s = ""; 2 === r.length ? (a = Number(r[0]), s = r[1]) : (i = Number(r[0]), a = Number(r[1]), s = r[2]); const c = s.indexOf("."), l = Number(c >= 0 ? s.slice(0, c) : s), d = c >= 0 ? s.slice(c + 1) : "", u = d ? Number(d.padEnd(3, "0").slice(0, 3)) : 0; return Number.isFinite(i) && Number.isFinite(a) && Number.isFinite(l) && Number.isFinite(u) ? 3600 * i + 60 * a + l + u / 1e3 : 0; }, a = "function" == typeof window.DOMParser ? new window.DOMParser : null; if (a) { try { const t = a.parseFromString(o, "text/xml"); "parsererror" === (t.documentElement?.nodeName?.toLowerCase?.() || "") || t.getElementsByTagName("parsererror").length > 0 || Array.from(t.getElementsByTagName("p")).forEach(t => { const o = i(t.getAttribute("begin") || t.getAttribute("start") || ""), r = i(t.getAttribute("end") || ""), a = i(t.getAttribute("dur") || "") || Math.max(0, r - o), s = S(String(t.textContent || "").replace(/\s+/g, " ").trim()); s && e.push({ start: o, duration: a, text: s }); }); } catch (t) {} } if (e.length > 0) { return e; } let s; for (;null !== (s = r.exec(o)); ) { const t = s[1] || "", o = s[2] || "", r = /\bbegin\s*=\s*["']([^"']+)["']/i.exec(t)?.[1] || "", a = /\bend\s*=\s*["']([^"']+)["']/i.exec(t)?.[1] || "", c = /\bdur\s*=\s*["']([^"']+)["']/i.exec(t)?.[1] || "", l = i(r); let d = 0; c ? d = i(c) : a && (d = Math.max(0, i(a) - l)); const u = S(o.replace(/<br\s*\/?\s*>/gi, " ").replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim()); u && e.push({ start: l, duration: d, text: u }); } return e; } function E(t) { return `<?xml version="1.0" encoding="utf-8"?><transcript>${t.map(t => { const e = Number(t?.start || 0), o = Number(t?.duration || 0), r = (function(t) { return String(t || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); })(String(t?.text || "").trim()); return `<text start="${e.toFixed(3)}" dur="${o.toFixed(3)}">${r}</text>`; }).join("")}</transcript>`; } function z(t, e, o) { try { const r = new URL(t); return r.searchParams.set(e, o), r.toString(); } catch (r) { const i = `${encodeURIComponent(e)}=${encodeURIComponent(o)}`, a = String(t || ""), s = a.indexOf("?"), c = a.indexOf("#"), l = s >= 0 ? s : c >= 0 ? c : a.length, d = a.slice(0, l), u = c >= 0 ? a.slice(c) : "", p = a.slice(s >= 0 ? s + 1 : l, c >= 0 ? c : a.length), y = p ? p.split("&").filter(Boolean) : []; let m = !1; for (let t = 0; t < y.length; t += 1) { const o = y[t], r = o.indexOf("="), a = r >= 0 ? o.slice(0, r) : o; decodeURIComponent(a) === e && (y[t] = i, m = !0); } return m || y.push(i), `${d}?${y.join("&")}${u}`; } } function _(t, e) { try { const o = new URL(t); return o.searchParams.delete(e), o.toString(); } catch (o) { const r = String(t || ""), i = r.indexOf("?"); if (i < 0) { return r; } const a = r.indexOf("#"), s = r.slice(0, i), c = a >= 0 ? r.slice(a) : "", l = r.slice(i + 1, a >= 0 ? a : r.length).split("&").filter(Boolean).filter(t => { const o = t.indexOf("="), r = o >= 0 ? t.slice(0, o) : t; return decodeURIComponent(r) !== e; }).join("&"); return `${s}${l ? `?${l}` : ""}${c}`; } } function I(t) { return Array.from(new Set((t || []).filter(t => (function(t) { try { const e = new URL(String(t || "")); return "http:" === e.protocol || "https:" === e.protocol; } catch (t) { return !1; } })(t)))); } function A(t) { return new Promise(e => setTimeout(e, Math.max(0, Number(t) || 0))); } function P(t) { const e = []; for (const o of I(t)) { const t = _(o, "fmt"), r = _(t, "tlang"), i = _(r, "kind"); e.push(i), e.push(r), e.push(t); } return I(e).slice(0, 3); } function j(t, e) { if (!t) { return []; } let o = t; try { const t = new URL(o); t.searchParams.delete("tlang"), t.searchParams.delete("fmt"), o = t.toString(); } catch (t) { o = o.replace(/[&?]tlang=[^&]*/g, "").replace(/[&?]fmt=[^&]*/g, ""), o = o.replace(/\?&/, "?").replace(/\?$/, ""); } return e && (o = z(o, "tlang", e)), I([ o, z(o, "fmt", "srv1"), z(o, "fmt", "json3"), z(o, "fmt", "srv3"), z(o, "fmt", "vtt") ]); } function H(t, e, o, r) { if (!t || !e) { return []; } const i = new URLSearchParams({ v: t, lang: e }); o && i.set("kind", "asr"), r && i.set("tlang", r); const a = (t = "") => { const e = new URLSearchParams(i); return t && e.set("fmt", t), `https://www.youtube.com/api/timedtext?${e.toString()}`; }; return I([ a(), a("srv1"), a("srv3"), a("json3"), a("vtt") ]); } function D(t) { const e = String(t || "").trim(); return !e || e.length < 10 || e.includes("<!DOCTYPE") || e.includes("<html") || e.includes("</html>") || /^\s*<!DOCTYPE/i.test(e) ? null : e.startsWith("{") ? L(e).length > 0 ? { text: e, kind: "json3" } : null : e.includes("WEBVTT") || e.includes("--\x3e") ? M(e).length > 0 ? { text: e, kind: "vtt" } : null : (e.includes("<transcript") || e.includes("<text")) && k(e).length > 0 ? { text: e, kind: "xml" } : (e.includes("<tt") || e.includes("<p ")) && C(e).length > 0 ? { text: e, kind: "ttml" } : e.length > 20 ? { text: e, kind: "raw" } : null; } async function O(e) { try { const o = t(), r = o?.fetch; if ("function" != typeof r) { return null; } for (const t of I(e)) { try { const e = await r(t, { method: "GET", credentials: "include", cache: "no-store", headers: { Accept: "*/*" } }); if (!e?.ok) { continue; } const o = D(await e.text()); if (o) { return o; } } catch (t) {} } } catch (t) {} return null; } async function B(e, r = {}) { let i = null, a = !1; const s = !0 === r.minimalMode, c = [ { method: "GET", withCredentials: !0, anonymous: !1, responseType: "text", headers: { Referer: "https://www.youtube.com/", "Accept-Encoding": "identity", "Cache-Control": "no-cache", Pragma: "no-cache" } }, { method: "GET", withCredentials: !0, anonymous: !1, headers: { Referer: "https://www.youtube.com/", "Accept-Encoding": "identity" } } ], l = s ? c.slice(0, 1) : c; if (!s) { try { const r = (e || []).map(o).find(Boolean) || ""; r && !ot.has(r) && await (async function() { if (at) { return !1; } at = !0; try { const e = t(), o = (() => { try { return new URLSearchParams(e.location?.search || "").get("v") || ""; } catch (t) { return ""; } })(); if (!o) { return !1; } if (ot.has(o)) { return !0; } const r = e.document?.querySelector?.(".html5-video-player"); if (!r) { return !1; } let i = null; try { i = "function" == typeof r.getOption ? r.getOption("captions", "track") : null; } catch (t) { i = null; } let a = null; try { const t = "function" == typeof r.getOption && r.getOption("captions", "tracklist", { includeAsr: !0 }) || []; Array.isArray(t) && t.length && (a = t.find(t => t && "ru" === t.languageCode && "asr" === t.kind) || t[0]); } catch (t) { a = null; } if (a && "function" == typeof r.setOption) { try { r.setOption("captions", "track", a); } catch (t) {} } else { try { const t = e.document?.querySelector?.(".ytp-subtitles-button"); t && "true" !== t.getAttribute("aria-pressed") && t.click(); } catch (t) {} } const s = Date.now() + 2200; for (;Date.now() < s && !ot.has(o); ) { await A(120); } try { if (i && "function" == typeof r.setOption) { r.setOption("captions", "track", i); } else if ("function" == typeof r.toggleSubtitles) { const t = e.document?.querySelector?.(".ytp-subtitles-button"); t && "true" === t.getAttribute("aria-pressed") && t.click(); } } catch (t) {} return ot.has(o); } catch (t) { return !1; } finally { at = !1; } })(); } catch (t) {} } const u = s ? P(e) : I(e), p = s ? u : (function(t) { if (!Array.isArray(t) || 0 === t.length) { return t || []; } const e = []; for (const r of t) { try { const t = o(r), i = t ? ot.get(t) : null; if (!i) { continue; } const a = new URL(r, "https://www.youtube.com"); for (const [t, e] of Object.entries(i)) { a.searchParams.set(t, e); } e.push(a.toString()); } catch (t) {} } const r = e.concat(t); return Array.from(new Set(r.filter(t => "string" == typeof t && t.length > 0))); })(u); if (!s) { try { const t = await O(p); if (t && "raw" !== t.kind) { return { payload: t, hadRateLimit: a }; } t && !i && (i = t); } catch (t) {} } for (const t of p) { for (const e of l) { try { const o = await d({ ...e, url: t }), r = Number(o?.status || 0); if (429 === r) { a = !0, await A(350); continue; } if (0 !== r && !(r >= 200 && r < 400)) { continue; } const s = D(await h(o)); if (s && "raw" !== s.kind) { return { payload: s, hadRateLimit: a }; } !i && s && (i = s); } catch (t) {} } a && await A(220); } if (!i) { const t = await O(p); if (t) { return { payload: t, hadRateLimit: a }; } } return i || !a || s ? { payload: i, hadRateLimit: a } : (await A(1200), B(p, { minimalMode: !0 })); } function R(t, e, o = 1500) { const r = URL.createObjectURL(t), i = document.createElement("a"); i.href = r, i.download = e, i.style.display = "none", document.body.appendChild(i), i.click(), document.body.removeChild(i), K(() => URL.revokeObjectURL(r), Math.max(500, Number(o) || 1500)); } async function F(t = {}) { const {videoId: e, url: o, languageCode: r, languageName: i, isAutoGenerated: c = !1, format: l = "srt", translateTo: d = null, trackId: u = ""} = t; if (!e || !o && !r) { throw new Error("Video ID and subtitle source are required"); } const p = a(), y = /firefox/i.test(navigator.userAgent || ""), f = [ ...j(o, d), ...H(e, r, c, d) ], h = [ ...j(o, null), ...H(e, r, c, null) ], g = [ ...j(_(String(o || ""), "tlang"), null), ...H(e, r, !1, null) ], v = d ? f : h, x = y ? P(d ? [ ...v ] : [ ...g, ...h ]) : v; pt.show(yt("subtitleDownloading"), { duration: 2e3, type: "info" }); let S = !1; try { let {payload: t, hadRateLimit: a} = await B(x, { minimalMode: y }); if (S = S || a, !t && a && await A(900), !t && c && !d) { const e = await B(g); t = e.payload, a = a || e.hadRateLimit, S = S || e.hadRateLimit; } if (!t && a) { const e = P(d ? [ ...f ] : [ ...g, ...h ]), o = await B(e, { minimalMode: !0 }); t = o.payload, S = S || o.hadRateLimit; } if (!t) { try { const i = await m(e), a = w(i?.captions?.playerCaptionsTracklistRenderer?.captionTracks || [], { languageCode: r, isAutoGenerated: c, baseUrl: o, trackId: u }); if (a?.baseUrl) { const o = b(a.baseUrl), i = d ? [ ...j(o, d), ...H(e, r, c, d) ] : [ ...j(o, null), ...H(e, r, c, null), ...H(e, r, !1, null) ], s = await B(i); t = s.payload, S = S || s.hadRateLimit; } } catch (t) {} } if (!t) { if (d) { throw new Error("Translated subtitle track is unavailable for this video/language"); } throw new Error("Empty subtitle response"); } const v = t.text, z = t.kind; let _, I, D = []; if ("xml" === z ? D = k(v) : "json3" === z ? D = L(v) : "vtt" === z ? D = M(v) : "ttml" === z ? D = C(v) : (D = k(v), 0 === D.length && (D = L(v)), 0 === D.length && (D = M(v)), 0 === D.length && (D = C(v))), "xml" === l) { _ = "xml" === z ? v : E(D), I = "xml"; } else { if (0 === D.length) { throw new Error("No subtitle cues found"); } "srt" === l ? (_ = (function(t) { let e = ""; return t.forEach((t, o) => { const r = T(t.start), i = T(t.start + t.duration), a = t.text.replace(/\n/g, " ").trim(); e += `${o + 1}\n`, e += `${r} --\x3e ${i}\n`, e += `${a}\n\n`; }), e; })(D), I = "srt") : "txt" === l ? (_ = (function(t) { return t.map(t => t.text.trim()).join("\n"); })(D), I = "txt") : (_ = "xml" === z ? v : E(D), I = "xml"); } const O = s(`${p} - ${i} (${d ? `${r}-${d}` : r}).${I}`); R(new Blob([ _ ], { type: "text/plain;charset=utf-8" }), O), pt.show(yt("subtitleDownloaded"), { duration: 3e3, type: "success" }), tt.debug("Subtitle downloaded:", O); } catch (t) { throw S && "Empty subtitle response" === String(t?.message || "") && (t.message = "YouTube temporarily limited subtitle requests (HTTP 429). Please retry in 20-60 seconds."), tt.error("Error downloading subtitle:", t), pt.show(`${yt("subtitleDownloadFailed")} ${t.message}`, { duration: 5e3, type: "error" }), t; } } async function N(t = {}) { const {format: e = mt.DEFAULTS.format, quality: o = mt.DEFAULTS.videoQuality, audioBitrate: l = mt.DEFAULTS.audioBitrate, embedThumbnail: u = mt.DEFAULTS.embedThumbnail, onProgress: p = null} = t, y = r(); if (!y) { throw new Error("Video ID not found"); } const m = i(), f = a(); pt.show(yt("startingDownload"), { duration: 2e3, type: "info" }); try { tt.debug("Fetching API key..."); const t = await d({ method: "GET", url: mt.API.KEY_URL, headers: mt.HEADERS }); if (200 !== t.status) { throw new Error(`Failed to get API key: ${t.status}`); } const r = JSON.parse(t.responseText); if (!r?.key) { throw new Error("API key not found in response"); } const {key: i} = r; let a; tt.debug("API key obtained"), a = "video" === e ? { link: m, format: "mp4", audioBitrate: "128", videoQuality: o, filenameStyle: "pretty", vCodec: parseInt(o, 10) > 1080 ? "vp9" : "h264" } : { link: m, format: "mp3", audioBitrate: l, filenameStyle: "pretty" }, tt.debug("Requesting conversion...", { format: a?.format, videoQuality: a?.videoQuality, audioBitrate: a?.audioBitrate }); const b = { ...mt.HEADERS, key: i }, h = await d({ method: "POST", url: mt.API.CONVERT_URL, headers: b, data: JSON.stringify(a) }); if (200 !== h.status) { throw new Error(`Conversion failed: ${h.status}`); } const g = JSON.parse(h.responseText); if (tt.debug("Conversion response received"), !g.url) { throw new Error("No download URL received from API"); } return tt.debug("Downloading file from:", (function(t) { try { if (!t || "string" != typeof t) { return ""; } const e = new URL(t, window.location.origin || "https://www.youtube.com"), o = [ "v", "videoId", "pot", "potc", "key", "token", "sig", "signature", "oauth", "authorization", "cookie" ]; for (const t of o) { e.searchParams.has(t) && e.searchParams.set(t, "<redacted>"); } return `${e.origin}${e.pathname}`; } catch (t) { return "<redacted-url>"; } })(String(g.url || ""))), new Promise((t, o) => { if ("undefined" == typeof GM_xmlhttpRequest) { return tt.warn("GM_xmlhttpRequest not available, opening in new tab"), window.open(g.url, "_blank"), void t(); } GM_xmlhttpRequest({ method: "GET", url: g.url, responseType: "blob", headers: { "User-Agent": mt.HEADERS["User-Agent"], Referer: "https://mp3yt.is/", Accept: "*/*" }, onprogress: t => { p && p({ loaded: t.loaded, total: t.total, percent: t.total ? Math.round(t.loaded / t.total * 100) : 0 }); }, onload: async r => { if (200 === r.status && r.response) { let i = r.response; if (0 === i.size) { return void o(new Error(yt("zeroBytesError"))); } if (G && YouTubeUtils.logger?.debug?.(`[Download] File downloaded: ${c(i.size)}`), "audio" === e && u) { try { tt.debug("Embedding album art..."); const t = `https://i.ytimg.com/vi/${y}/maxresdefault.jpg`, e = await (function(t) { return new Promise((e, o) => { const r = document.createElement("img"); r.crossOrigin = "anonymous", r.onload = () => { const t = document.createElement("canvas"), i = Math.min(r.width, r.height); t.width = i, t.height = i; const a = t.getContext("2d"); if (!a) { return t.width = 0, t.height = 0, void o(new Error("Failed to get canvas context")); } a.drawImage(r, (r.width - i) / 2, (r.height - i) / 2, i, i, 0, 0, i, i), t.toBlob(r => { t.width = 0, t.height = 0, r ? e(r) : o(new Error("Failed to create blob")); }, "image/jpeg", .95); }, r.onerror = () => o(new Error("Failed to load thumbnail")), r.src = t; }); })(t); i = await (async function(t, e, o) { try { if (void 0 === window.ID3Writer) { return tt.warn("ID3Writer not available, skipping album art embedding"), t; } const r = await t.arrayBuffer(), i = new window.ID3Writer(r); if (o.title && i.setFrame("TIT2", o.title), o.artist && i.setFrame("TPE1", [ o.artist ]), o.album && i.setFrame("TALB", o.album), e) { const t = await e.arrayBuffer(); i.setFrame("APIC", { type: 3, data: t, description: "Cover" }); } return i.addTag(), new Blob([ i.arrayBuffer ], { type: "audio/mpeg" }); } catch (e) { return tt.error("Error embedding album art:", e), t; } })(i, e, { title: f }), tt.debug("Album art embedded successfully"); } catch (t) { tt.error("Failed to embed album art:", t); } } const a = g.filename || `${f}.${"video" === e ? "mp4" : "mp3"}`; R(i, s(a), 2e3), pt.show(yt("downloadCompleted"), { duration: 3e3, type: "success" }), tt.debug("Download completed:", a), t(); } else { o(new Error(`Download failed: ${r.status}`)); } }, onerror: () => o(new Error("Download failed - network error")), ontimeout: () => o(new Error("Download timeout")) }); }); } catch (t) { throw tt.error("Error:", t), pt.show(`${yt("downloadFailed")} ${t.message}`, { duration: 5e3, type: "error" }), t; } } function Z(t) { try { t.qualitySelect && (t.qualitySelect.disabled = !1), t.downloadBtn && (t.downloadBtn.disabled = !1), t.cancelBtn && (t.cancelBtn.disabled = !1), t.downloadBtn && (t.downloadBtn.style.opacity = "1", t.downloadBtn.style.cursor = "pointer", t.downloadBtn.style.pointerEvents = "auto"); } catch (t) { tt.error("Error enabling form controls", t); } } function V(t, e, o) { if ("subtitle" === e) { return t.qualitySelect.style.display = "none", t.embedLabel.style.display = "none", t.subtitleWrapper.style.display = "block", void (async function(t, e) { const o = r(); if (o) { t.subtitleSelect.setPlaceholder(yt("loading")), t.subtitleSelect.disabled = !0; try { const r = await x(o); if (!r) { return void t.subtitleSelect.setPlaceholder(yt("noSubtitles")); } if (e.original = r.subtitles, e.translated = r.autoTransSubtitles.map(t => ({ ...t, url: t.url || (t.baseUrl ? f(t.baseUrl) : ""), translateTo: t.languageCode })), e.all = [ ...e.original, ...e.translated ], 0 === e.all.length) { return void t.subtitleSelect.setPlaceholder(yt("noSubtitles")); } const i = e.all.map((t, e) => ({ value: e, text: t.name + (t.translateTo ? yt("autoTranslateSuffix") : "") })); t.subtitleSelect.setOptions(i), t.subtitleSelect.disabled = !1; } catch (e) { tt.error("Failed to load subtitles:", e), t.subtitleSelect.setPlaceholder(yt("subtitleLoadError")); } } })(t, o); } if ("video" === e) { t.qualitySelect.style.display = "flex", t.embedLabel.style.display = "none", t.subtitleWrapper.style.display = "none"; const s = r() || "", c = String(Date.now()) + Math.random().toString(36).slice(2); t.qualitySelect.dataset.renderToken = c, t.qualitySelect.replaceChildren(); const l = document.createElement("div"); function i(e) { const o = document.createElement("button"); return o.type = "button", o.setAttribute("role", "radio"), o.setAttribute("aria-checked", "false"), o.dataset.value = e, o.textContent = `${e}p`, Object.assign(o.style || {}, { display: "inline-flex", alignItems: "center", gap: "8px", padding: "8px 12px", borderRadius: "999px", border: "1px solid var(--yt-surface-soft)", background: "var(--yt-surface-overlay-faint)", color: "var(--yt-text-primary)", cursor: "pointer", fontSize: "13px", fontWeight: "600" }), o.addEventListener("click", () => { Array.from(t.qualitySelect.children).forEach(t => { t.dataset?.value && (t.style.background = "transparent", t.style.color = "var(--yt-text-primary)", t.style.border = "1px solid var(--yt-surface-soft)", t.setAttribute && t.setAttribute("aria-checked", "false")); }), o.style.background = "var(--yt-surface-contrast)", o.style.color = "var(--yt-success-accent)", o.style.border = "1px solid var(--yt-success-accent-soft)", o.setAttribute("aria-checked", "true"), t.qualitySelect.value = e; }), o; } return l.textContent = yt("loading"), Object.assign(l.style || {}, { fontSize: "13px", color: "var(--yt-text-secondary)", padding: "8px 0" }), t.qualitySelect.appendChild(l), void (async function(t) { if (!t) { return mt.VIDEO_QUALITIES.slice(); } try { const e = p(await u(t)); if (e.length > 0) { return e; } } catch (t) { tt.warn("Primary player quality fetch failed:", t); } try { const e = p(await m(t)); if (e.length > 0) { return e; } } catch (t) { tt.warn("Watch HTML quality fallback failed:", t); } return mt.VIDEO_QUALITIES.slice(); })(s).then(o => { if ("video" !== e) { return; } if (t.qualitySelect.dataset.renderToken !== c) { return; } const r = Array.isArray(o) && o.length > 0 ? o : mt.VIDEO_QUALITIES.slice(), a = r.filter(t => parseInt(t, 10) <= 1080), s = r.filter(t => parseInt(t, 10) > 1080), l = String(t.qualitySelect.value || ""); if (t.qualitySelect.replaceChildren(), a.forEach(e => t.qualitySelect.appendChild(i(e))), s.length > 0) { const e = document.createElement("div"); Object.assign(e.style || {}, { display: "flex", alignItems: "center", gap: "12px", width: "100%", margin: "8px 0" }); const o = document.createElement("div"); o.style.flex = "1", o.style.borderTop = "1px solid var(--yt-surface-overlay-border)"; const r = document.createElement("div"); r.textContent = yt("vp9Label"), Object.assign(r.style || {}, { fontSize: "12px", color: "var(--yt-text-secondary)", padding: "0 8px" }); const a = document.createElement("div"); a.style.flex = "1", a.style.borderTop = "1px solid var(--yt-surface-overlay-border)", e.appendChild(o), e.appendChild(r), e.appendChild(a), t.qualitySelect.appendChild(e), s.forEach(e => t.qualitySelect.appendChild(i(e))); } t.qualitySelect.value = (function(t, e) { if (!Array.isArray(t) || 0 === t.length) { return e || mt.DEFAULTS.videoQuality; } if (t.includes(e)) { return e; } if (t.includes(mt.DEFAULTS.videoQuality)) { return mt.DEFAULTS.videoQuality; } const o = t.slice().sort((t, e) => Number(t) - Number(e)); return o[o.length - 1] || e || mt.DEFAULTS.videoQuality; })(r, l); const d = Array.from(t.qualitySelect.children).find(e => e.dataset && e.dataset.value === t.qualitySelect.value); d && d.click(); }); } t.qualitySelect.style.display = "flex", t.embedLabel.style.display = "flex", t.subtitleWrapper.style.display = "none", t.qualitySelect.replaceChildren(), mt.AUDIO_BITRATES.forEach(e => { const o = document.createElement("button"); o.type = "button", o.setAttribute("role", "radio"), o.setAttribute("aria-checked", "false"), o.dataset.value = e, o.textContent = `${e} kbps`, Object.assign(o.style || {}, { display: "inline-flex", alignItems: "center", gap: "8px", padding: "8px 12px", borderRadius: "999px", border: "1px solid var(--yt-surface-soft)", background: "var(--yt-surface-overlay-faint)", color: "var(--yt-text-primary)", cursor: "pointer", fontSize: "13px", fontWeight: "600" }), o.addEventListener("click", () => { Array.from(t.qualitySelect.children).forEach(t => { t.style.background = "transparent", t.style.color = "var(--yt-text-primary)", t.style.border = "1px solid var(--yt-surface-soft)", t.setAttribute && t.setAttribute("aria-checked", "false"); }), o.style.background = "var(--yt-surface-contrast)", o.style.color = "var(--yt-success-accent)", o.style.border = "1px solid var(--yt-success-accent-soft)", o.setAttribute("aria-checked", "true"), t.qualitySelect.value = e; }), t.qualitySelect.appendChild(o); }), t.qualitySelect.value = mt.DEFAULTS.audioBitrate; const a = Array.from(t.qualitySelect.children).find(e => e.dataset.value === t.qualitySelect.value); a && a.click(), t.embedLabel.style.display = "none"; } function Y() { if (gt) { try { const t = gt.overlay?.querySelector('[role="listbox"]'); t && "function" == typeof t.destroy && t.destroy(), gt.overlay?.parentNode && gt.overlay.parentNode.removeChild(gt.overlay); } catch {} gt = null; } } function q() { if (!kt) { kt = !0, et(); try { G && YouTubeUtils.logger?.debug?.("[YouTube+ Download] Unified module loaded"), G && YouTubeUtils.logger?.debug?.("[YouTube+ Download] Use window.YouTubePlusDownload.downloadVideo() to download"), G && YouTubeUtils.logger?.debug?.("[YouTube+ Download] Button manager available"); } catch (t) { G.logSuppressed(t, "Download"); } } } const G = window.YouTubeUtils, W = G.setSafeHTML, J = G?.createVisibilityAwareInterval, K = setTimeout.bind(window), X = "ytp-download-styles", Q = window.YouTubePlusLogger, tt = void 0 !== Q && Q ? Q.createLogger("Download") : { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} }, et = () => { try { const t = window.YouTubePlusDesignSystem?.getStyle(X) || ""; if (!t) { return; } const e = YouTubeUtils?.StyleManager; e && "function" == typeof e.add && e.add(X, t); } catch (t) { tt?.warn?.("[YouTube+ Download] style injection failed:", t); } }, nt = t => { const e = document.querySelector(".ytp-download-button"), o = document.querySelector(".download-options"); e && e.style.setProperty("display", t ? "" : "none", "important"), o && (o.style.setProperty("display", t ? "" : "none", "important"), t || o.classList.remove("visible")); }, ot = new Map, rt = [ "pot", "potc", "c", "cver", "cplayer", "cos", "cosver", "cplatform", "cbr", "cbrver", "xorb", "xobt", "xovt" ]; let it = !1, at = !1, st = null, ct = null; !(function() { if (it) { return; } const o = t(); if (o && "object" == typeof o) { try { st = o.fetch, "function" == typeof st && (o.fetch = function(t, o) { try { const o = t && "object" == typeof t ? t : {}, r = "string" == typeof t ? t : t instanceof URL ? t.toString() : "string" == typeof o.url ? o.url : ""; r && e(r); } catch (t) {} return st.call(this, t, o); }); const t = o.XMLHttpRequest?.prototype; t && "function" == typeof t.open && (ct = t.open, t.open = function(...t) { try { const o = t[1]; "string" == typeof o && e(o); } catch (t) {} return ct.apply(this, t); }), it = !0; } catch (t) {} } })(), "function" == typeof G?.cleanupManager?.register && G.cleanupManager.register(function() { if (!it) { return; } const e = t(); if (e && "object" == typeof e) { try { st && "function" == typeof st && (e.fetch = st, st = null); const t = e.XMLHttpRequest?.prototype; ct && t && "function" == typeof ct && (t.open = ct, ct = null), it = !1; } catch (t) {} } }); const lt = () => G.isWatchRoute() || G.isShortsRoute(), dt = G?.onDomReady || (t => { "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", t, { once: !0 }) : t(); }), ut = t => G.$(t); if ("undefined" == typeof YouTubeUtils) { return void window.YouTubePlusLogger?.error?.("Download", "YouTubeUtils not found!"); } const {NotificationManager: pt} = YouTubeUtils, yt = (t, e = {}) => { if (G?.t) { return G.t(t, e); } const o = String(t || ""); if (!e || 0 === Object.keys(e).length) { return o; } let r = o; for (const [t, o] of Object.entries(e)) { r = r.split(`{${t}}`).join(String(o)); } return r; }, mt = { API: { KEY_URL: "https://cnv.cx/v2/sanity/key", CONVERT_URL: "https://cnv.cx/v2/converter" }, HEADERS: { "Content-Type": "application/json", Origin: "https://mp3yt.is", Accept: "*/*", "User-Agent": "undefined" != typeof navigator ? navigator.userAgent : "" }, VIDEO_QUALITIES: [ "144", "240", "360", "480", "720", "1080", "1440", "2160" ], AUDIO_BITRATES: [ "64", "128", "192", "256", "320" ], DEFAULTS: { format: "video", videoQuality: "1080", audioBitrate: "320", embedThumbnail: !0 } }, ft = (() => { const t = [ "/api/timedtext", "/api/timedtext_ui" ], e = new Map, o = new Map; return { canRequest(r) { let i = "unknown", a = ""; try { const t = new URL(r); i = t.hostname, a = t.pathname; } catch (t) {} if (t.some(t => a.startsWith(t))) { return !0; } const s = Date.now(), c = o.get(i) || 0; if (s < c) { return tt.warn(`Rate limit backoff: ${i} blocked for ${Math.ceil((c - s) / 1e3)}s more`), !1; } const l = (e.get(i) || []).filter(t => s - t < 6e4); if (l.length >= 15) { const t = Math.min(5, Math.floor(l.length / 15)), e = Math.min(6e4, 2e3 * 2 ** t); return o.set(i, s + e), tt.warn(`Rate limit: ${l.length}/15 requests to ${i}, backing off ${e}ms`), !1; } return l.push(s), e.set(i, l), !0; } }; })(), bt = (() => { const t = new Map; return { get(e) { const o = t.get(e); return o ? Date.now() - o.ts > 3e5 ? (t.delete(e), null) : o.data : null; }, set(e, o) { if (t.size >= 10) { const e = t.keys().next().value; "string" == typeof e && t.delete(e); } t.set(e, { data: o, ts: Date.now() }); } }; })(), ht = { amp: "&", lt: "<", gt: ">", quot: '"', "#39": "'", apos: "'", nbsp: " " }; let gt = null; const wt = (t, e, o) => (t || "").replace("{videoId}", e || "").replace("{videoUrl}", encodeURIComponent(o || "")), vt = (() => { let t = null, e = null, o = null; const r = () => { if (!e || !o) { return; } const r = e.getBoundingClientRect(), i = Math.max(8, r.left + r.width / 2 - 75), a = Math.max(8, window.innerHeight - r.top + 12); o.style.left = `${i}px`, o.style.bottom = `${a}px`, t = null, e = null, o = null; }; return (i, a) => { e = i, o = a, null === t && (t = requestAnimationFrame(r)); }; })(), xt = (() => { let t = !1; const e = new WeakMap, o = (t, o) => e.set(t, o), r = t => { const o = (t => e.get(t))(t); void 0 !== o && (clearTimeout(o), e.delete(t)); }, i = (t, e) => { r(t), r(e), vt(t, e), e.classList.add("visible"), t.setAttribute("aria-expanded", "true"); }, a = (t, e) => { r(t), r(e); const i = setTimeout(() => { e.classList.remove("visible"), t.setAttribute("aria-expanded", "false"); }, 180); o(t, i); }; return () => { t || (t = !0, document.addEventListener("mouseenter", t => { const e = t.target?.closest?.(".ytp-download-button"); if (e) { const t = ut(".download-options"); return void (t && (r(e), r(t), i(e, t))); } const o = t.target?.closest?.(".download-options"); if (o) { const t = ut(".ytp-download-button"); t && (r(t), r(o), i(t, o)); } }, !0), document.addEventListener("mouseleave", t => { const e = t.target?.closest?.(".ytp-download-button"); if (e) { const t = ut(".download-options"); if (t) { r(e), r(t); const i = setTimeout(() => a(e, t), 180); o(e, i); } return; } const i = t.target?.closest?.(".download-options"); if (i) { const t = ut(".ytp-download-button"); if (t) { r(t), r(i); const e = setTimeout(() => a(t, i), 180); o(i, e); } } }, !0), document.addEventListener("keydown", t => { const e = t.target?.closest?.(".ytp-download-button"); if (e && ("Enter" === t.key || " " === t.key)) { const t = ut(".download-options"); if (!t) { return; } t.classList.contains("visible") ? a(e, t) : i(e, t); } })); }; })(); let kt = !1; "undefined" != typeof window && (window.YouTubePlusDownload = { downloadVideo: N, getSubtitles: x, downloadSubtitle: F, getVideoId: r, getVideoUrl: i, getVideoTitle: a, sanitizeFilename: s, formatBytes: c, DownloadConfig: mt, openModal: function() { const t = (function() { if (gt) { return gt; } let t = "video"; const e = { all: [], original: [], translated: [] }, o = document.createElement("div"); Object.assign(o.style || {}, { position: "fixed", inset: "0", background: "rgba(0,0,0,0.6)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: "999999" }); const i = document.createElement("div"); Object.assign(i.style || {}, { width: "420px", maxWidth: "94%", background: "var(--yt-glass-bg)", color: "var(--yt-text-primary)", borderRadius: "12px", boxShadow: "0 8px 40px var(--yt-shadow-flyout)", fontFamily: "Arial, sans-serif", border: "1px solid var(--yt-surface-overlay-border)", backdropFilter: "blur(8px)" }); const a = (function() { const t = document.createElement("div"); t.role = "radiogroup", t.value = mt.DEFAULTS.videoQuality, Object.assign(t.style || {}, { display: "flex", flexWrap: "wrap", gap: "10px", padding: "12px 6px", borderRadius: "10px", width: "100%", alignItems: "center", justifyContent: "center", background: "transparent" }); const e = document.createElement("input"); e.type = "checkbox", e.checked = mt.DEFAULTS.embedThumbnail; const o = document.createElement("label"); o.style.fontSize = "13px", o.style.display = "flex", o.style.alignItems = "center", o.style.gap = "6px", o.style.color = "var(--yt-text-primary)", o.style.display = "none", o.appendChild(e), o.appendChild(document.createTextNode(yt("embedThumbnail"))); const r = document.createElement("div"); r.style.display = "none"; const i = (function() { const t = document.createElement("div"); t.setAttribute("role", "listbox"), t.setAttribute("aria-expanded", "false"), t.setAttribute("aria-label", "Subtitle language"), t.setAttribute("tabindex", "0"), Object.assign(t.style || {}, { position: "relative", width: "100%", marginBottom: "8px", fontSize: "14px", color: "var(--yt-text-primary)", cursor: "pointer" }); const e = document.createElement("div"); Object.assign(e.style || {}, { padding: "10px 12px", borderRadius: "10px", background: "linear-gradient(135deg, var(--yt-glass-bg), var(--yt-surface-overlay-faint))", border: "1px solid var(--yt-glass-border)", display: "flex", alignItems: "center", justifyContent: "space-between", gap: "8px", backdropFilter: "blur(6px)", boxShadow: "0 4px 18px var(--yt-shadow-inset-strong) inset" }); const o = document.createElement("div"); o.style && (o.style.flex = "1", o.style.overflow = "hidden", o.style.textOverflow = "ellipsis", o.style.whiteSpace = "nowrap"), o.textContent = yt("loading"); const r = document.createElement("div"); r.textContent = "▾", r.style && (r.style.opacity = "0.8"), e.appendChild(o), e.appendChild(r); const i = document.createElement("div"); Object.assign(i.style || {}, { position: "absolute", top: "calc(100% + 8px)", left: "0", right: "0", maxHeight: "220px", overflowY: "auto", borderRadius: "10px", background: "linear-gradient(180deg, var(--yt-glass-bg), var(--yt-surface-overlay-faint))", border: "1px solid var(--yt-glass-border)", boxShadow: "0 8px 30px var(--yt-shadow-flyout)", backdropFilter: "blur(8px)", zIndex: "9999", display: "none" }), t.appendChild(e), t.appendChild(i), i.addEventListener("click", e => { const o = e.target; if (!(o instanceof HTMLElement)) { return; } const r = o.closest("[data-value]"); r && i.contains(r) && (t.value = r.dataset?.value || "", i.style && (i.style.display = "none")); }), i.addEventListener("mouseover", t => { const e = t.target; if (!(e instanceof HTMLElement)) { return; } const o = e.closest("[data-value]"); o && i.contains(o) && o.style && (o.style.background = "var(--yt-surface-overlay-faint)"); }), i.addEventListener("mouseout", t => { const e = t.target; if (!(e instanceof HTMLElement)) { return; } const o = e.closest("[data-value]"); if (!o || !i.contains(o)) { return; } const r = t.relatedTarget; r && o.contains(r) || o.style && (o.style.background = "transparent"); }), t.rt = [], t.st = "", t.ct = !1, t.setPlaceholder = e => { o.textContent = e || "", t.rt = [], i.replaceChildren(), t.st = ""; }, t.setOptions = e => { t.rt = e || [], i.replaceChildren(), t.rt.forEach(t => { const e = document.createElement("div"); e.textContent = t.text, e.dataset.value = String(t.value), Object.assign(e.style || {}, { padding: "10px 12px", cursor: "pointer", borderBottom: "1px solid var(--yt-surface-overlay-faint)", color: "var(--yt-text-primary)" }), i.appendChild(e); }), t.rt.length > 0 ? t.value = String(t.rt[0].value) : (t.st = "", o.textContent = yt("noSubtitles")); }, Object.defineProperty(t, "value", { get: () => t.st, set(e) { t.st = String(e); const r = t.rt.find(e => String(e.value) === t.st); o.textContent = r ? r.text : ""; } }), Object.defineProperty(t, "disabled", { get: () => t.ct, set(o) { t.ct = !!o, e.style && (e.style.opacity = t.ct ? "0.5" : "1"), t.style && (t.style.pointerEvents = t.ct ? "none" : "auto"); } }), e.addEventListener("click", () => { if (t.ct) { return; } const e = !!i.style && "none" !== i.style.display; i.style && (i.style.display = e ? "none" : ""), t.setAttribute("aria-expanded", e ? "false" : "true"); }), t.addEventListener("keydown", e => { if (t.ct) { return; } const o = !!i.style && "none" !== i.style.display; if ("Enter" === e.key || " " === e.key) { e.preventDefault(), i.style && (i.style.display = o ? "none" : ""), t.setAttribute("aria-expanded", o ? "false" : "true"); } else if ("Escape" === e.key && o) { e.preventDefault(), i.style && (i.style.display = "none"), t.setAttribute("aria-expanded", "false"); } else if ("ArrowDown" === e.key || "ArrowUp" === e.key) { e.preventDefault(), o || (i.style && (i.style.display = ""), t.setAttribute("aria-expanded", "true")); const r = t.rt; if (0 === r.length) { return; } const a = r.findIndex(e => String(e.value) === t.st), s = "ArrowDown" === e.key ? Math.min(a + 1, r.length - 1) : Math.max(a - 1, 0); t.value = String(r[s].value); } }); const a = new AbortController; return document.addEventListener("click", e => { const o = e.target; o instanceof Node && t.contains(o) || (i.style && (i.style.display = "none"), t.setAttribute("aria-expanded", "false")); }, { signal: a.signal }), t.destroy = () => a.abort(), t; })(), a = document.createElement("div"); a.role = "radiogroup", a.value = "srt", Object.assign(a.style || {}, { display: "flex", gap: "8px", padding: "6px 0", borderRadius: "6px", width: "100%", alignItems: "center", justifyContent: "center", background: "transparent" }), [ "srt", "txt", "xml" ].forEach(t => { const e = document.createElement("button"); e.type = "button", e.setAttribute("role", "radio"), e.setAttribute("aria-checked", "false"), e.dataset.value = t, e.textContent = t.toUpperCase(), Object.assign(e.style || {}, { padding: "6px 12px", borderRadius: "999px", border: "1px solid var(--yt-surface-soft)", background: "var(--yt-surface-overlay-faint)", color: "var(--yt-text-primary)", cursor: "pointer", fontSize: "13px", fontWeight: "600" }), e.addEventListener("click", () => { Array.from(a.children).forEach(t => { t.style.background = "transparent", t.style.color = "var(--yt-text-primary)", t.style.border = "1px solid var(--yt-surface-soft)", t.setAttribute && t.setAttribute("aria-checked", "false"); }), e.style.background = "var(--yt-surface-contrast)", e.style.color = "var(--yt-success-accent)", e.style.border = "1px solid var(--yt-success-accent-soft)", e.setAttribute("aria-checked", "true"), a.value = t; }), a.appendChild(e); }); const s = Array.from(a.children).find(t => t.dataset?.value === a.value); s && s.click(), r.appendChild(i), r.appendChild(a); const c = document.createElement("button"); c.type = "button", c.textContent = yt("cancel"), Object.assign(c.style || {}, { padding: "8px 16px", borderRadius: "8px", border: "1px solid var(--yt-surface-active)", background: "transparent", cursor: "pointer", fontSize: "14px", color: "var(--yt-text-primary)" }); const l = document.createElement("button"); l.type = "button", l.textContent = yt("download"), Object.assign(l.style || {}, { padding: "8px 20px", borderRadius: "8px", border: "1px solid var(--yt-surface-active)", background: "transparent", color: "var(--yt-text-primary)", cursor: "pointer", fontSize: "14px", fontWeight: "600" }); const d = document.createElement("div"); d.style.display = "none", d.style.marginTop = "12px"; const u = document.createElement("div"); Object.assign(u.style || {}, { width: "100%", height: "3px", background: "var(--yt-progress-track)", borderRadius: "5px", overflow: "hidden", marginBottom: "6px" }); const p = document.createElement("div"); Object.assign(p.style || {}, { width: "0%", height: "100%", background: "var(--yt-progress-fill)", transition: "width 200ms linear" }), u.appendChild(p); const y = document.createElement("div"); return y.style.fontSize = "12px", y.style.color = "var(--yt-muted-text)", d.appendChild(u), d.appendChild(y), { qualitySelect: t, embedLabel: o, subtitleWrapper: r, subtitleSelect: i, formatSelect: a, cancelBtn: c, downloadBtn: l, progressWrapper: d, progressFill: p, progressText: y }; })(), s = (function() { function o(o) { [ i, s, c ].forEach(t => { t.style.background = "transparent", t.style.color = "var(--yt-muted-text)", t.style.border = "1px solid var(--yt-surface-overlay-border)", t.style.boxShadow = "none", t.setAttribute("aria-selected", "false"); }), Object.assign(o.style, { background: "var(--yt-success-accent)", color: "var(--yt-text-primary)", border: "1px solid var(--yt-shadow-inset-soft)", boxShadow: "0 1px 0 var(--yt-shadow-inset-soft) inset" }), o.setAttribute("aria-selected", "true"); try { t = o.dataset.format, V(a, t, e); } catch (t) {} } const r = document.createElement("div"); r.setAttribute("role", "tablist"), Object.assign(r.style || {}, { display: "flex", gap: "8px", padding: "12px", justifyContent: "center", alignItems: "center", background: "transparent" }); const i = document.createElement("button"); i.textContent = yt("videoTab"), i.dataset.format = "video"; const s = document.createElement("button"); s.textContent = yt("audioTab"), s.dataset.format = "audio"; const c = document.createElement("button"); return c.textContent = yt("subtitleTab"), c.dataset.format = "subtitle", [ i, s, c ].forEach(t => { Object.assign(t.style, { flex: "initial", padding: "8px 18px", border: "1px solid var(--yt-surface-overlay-border)", background: "transparent", cursor: "pointer", fontSize: "13px", fontWeight: "600", transition: "background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.1s cubic-bezier(0.2,0,0,1), box-shadow 0.18s ease", color: "var(--yt-muted-text)", borderRadius: "999px" }), t.type = "button", t.setAttribute("role", "tab"), t.setAttribute("aria-selected", "false"), t.style.outline = "none", t.style.userSelect = "none"; }), [ i, s, c ].forEach(t => { t.addEventListener("click", () => { o(t); try { t.blur(); } catch {} }), t.addEventListener("mousedown", () => { t.style.transform = "scale(0.96)"; }); const e = () => { t.style.transform = ""; }; t.addEventListener("mouseup", e), t.addEventListener("mouseleave", e); }), r.appendChild(i), r.appendChild(s), r.appendChild(c), r.addEventListener("keydown", t => { if ("ArrowLeft" !== t.key && "ArrowRight" !== t.key) { return; } const e = [ i, s, c ], o = e.indexOf(document.activeElement); if (o < 0) { return; } t.preventDefault(); const r = "ArrowRight" === t.key ? e[(o + 1) % e.length] : e[(o - 1 + e.length) % e.length]; r.focus(), r.click(); }), setTimeout(() => o(i), 0), r; })(), l = document.createElement("div"); l.style.padding = "16px", l.appendChild(a.qualitySelect), l.appendChild(a.embedLabel), l.appendChild(a.subtitleWrapper), l.appendChild(a.progressWrapper); const d = document.createElement("div"); return Object.assign(d.style || {}, { display: "flex", gap: "8px", padding: "16px", justifyContent: "center" }), d.appendChild(a.cancelBtn), d.appendChild(a.downloadBtn), i.appendChild(s), i.appendChild(l), i.appendChild(d), o.appendChild(i), V(a, t, e), (function(e, o, i) { e.cancelBtn.addEventListener("click", () => Y()), e.downloadBtn.addEventListener("click", async () => { if (e.downloadBtn.disabled) { return; } !(function(t) { try { t.qualitySelect && (t.qualitySelect.disabled = !0), t.downloadBtn && (t.downloadBtn.disabled = !0, t.downloadBtn.style.opacity = "0.5", t.downloadBtn.style.cursor = "not-allowed"), t.cancelBtn && (t.cancelBtn.disabled = !0); } catch (t) { tt.error("Error disabling form controls", t); } })(e), (function(t) { t.progressWrapper.style.display = "", t.progressFill.style.width = "0%", t.progressText.textContent = yt("starting"); })(e); const o = t; try { "subtitle" === o ? await (async function(t, e) { const o = e(), i = parseInt(t.subtitleSelect.value, 10), a = o.all[i], s = t.formatSelect.value; if (!a) { throw new Error(yt("noSubtitleSelected")); } const c = r() || "", l = a.sourceLanguageCode || a.languageCode, d = a.translateTo || null; await F({ videoId: c, url: a.baseUrl || a.url, languageCode: l, languageName: a.name, isAutoGenerated: !!a.isAutoGenerated, format: s, translateTo: d, trackId: a.trackId || "" }); })(e, i) : await (async function(t, e) { const o = { format: e, quality: t.qualitySelect.value, audioBitrate: t.qualitySelect.value, embedThumbnail: "audio" === e, onProgress: e => { const o = Number(e?.loaded || 0), r = Number(e?.total || 0), i = Number.isFinite(r) && r > 0; let a = Number(e?.percent || 0); if (i) { return a = Math.max(0, Math.min(100, Math.round(o / r * 100))), t.progressFill.style.width = `${a}%`, void (t.progressText.textContent = `${a}% • ${c(o)} / ${c(r)}`); } const s = Math.min(95, Math.max(5, Math.round(4 * Math.log2(o + 1)))); t.progressFill.style.width = `${s}%`, t.progressText.textContent = `${yt("downloading")} • ${c(o)} / —`; } }; await N(o); })(e, o), (function(t) { t.progressText.textContent = yt("completed"), setTimeout(() => Y(), 800); })(e); } catch (t) { tt.error("Download error", t), (function(t, e) { const o = e?.message || "Unknown error"; t.progressText.textContent = `${yt("downloadFailed")} ${o}`, t.progressText.style.color = "var(--yt-danger-text)", Z(t), K(() => { try { Z(t); } catch (t) { tt.error("Failed to re-enable controls", t); } }, 500), K(() => { t.progressText.style.color = "#fff"; }, 3e3); })(e, t); } finally { K(() => { e.downloadBtn && !e.downloadBtn.disabled || Z(e); }, 1e3); } }); })(a, 0, () => e), gt = { overlay: o, box: i, ...a }, gt; })(); if (t) { try { document.body.contains(t.overlay) || document.body.appendChild(t.overlay); } catch {} } }, init: q }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDownload = window.YouTubePlusDownload), window.YouTubePlusDownloadButton = { createDownloadButtonManager: t => { const {settings: e, t: o, getElement: r, YouTubeUtils: i} = t, a = ((t, e) => { const o = async () => { const o = await new Promise(t => { let e = 0; if (void 0 !== window.YouTubePlusDownload) { return t(window.YouTubePlusDownload); } const o = J(() => (e += 200, void 0 !== window.YouTubePlusDownload ? (o.stop(), t(window.YouTubePlusDownload)) : e >= 2e3 ? (o.stop(), t(void 0)) : void 0), 200); try { G?.cleanupManager?.register && G.cleanupManager.register(() => o.stop()); } catch (t) { G.logSuppressed(t, "Download"); } }); if (!o) { return tt.error("Direct download module not loaded"), void e.NotificationManager.show(t("directDownloadModuleNotAvailable"), { duration: 3e3, type: "error" }); } try { if ("function" == typeof o.openModal) { return void o.openModal(); } if ("function" == typeof o.downloadVideo) { return void await o.downloadVideo({ format: "video", quality: "1080" }); } } catch (t) { tt.error("Direct download invocation failed", t); } e.NotificationManager.show(t("directDownloadModuleNotAvailable"), { duration: 3e3, type: "error" }); }, r = o => { const r = new URLSearchParams(location.search).get("v"), i = r ? `https://www.youtube.com/watch?v=${r}` : location.href; navigator.clipboard.writeText(i).then(() => { e.NotificationManager.show(t("copiedToClipboard"), { duration: 2e3, type: "success" }); }).catch(() => { (async (t, e, o) => { try { if (navigator.clipboard?.writeText) { return await navigator.clipboard.writeText(t), void o.show(e("copiedToClipboard"), { duration: 2e3, type: "success" }); } const r = document.createElement("textarea"); r.value = t, r.setAttribute("readonly", ""), Object.assign(r.style, { position: "fixed", left: "-9999px", top: "-9999px", opacity: "0" }), document.body.appendChild(r), r.select(), r.setSelectionRange(0, t.length); let i = !1; try { i = document.execCommand("copy"); } catch (t) { tt.warn("[Download] execCommand copy not supported"); } document.body.removeChild(r), i ? o.show(e("copiedToClipboard"), { duration: 2e3, type: "success" }) : o.show(e("copyFailed") || "Copy failed", { duration: 2e3, type: "error" }); } catch (t) { tt.warn("[Download] Clipboard copy failed:", t), o.show(e("copyFailed") || "Copy failed", { duration: 2e3, type: "error" }); } })(i, t, e.NotificationManager); }), window.open(o, "_blank"); }; return { handleDirectDownload: o, handleYTDLDownload: r, openDownloadSite: (t, e, i, a, s) => { a.classList.remove("visible"), s.setAttribute("aria-expanded", "false"), i ? o() : e ? r(t) : window.open(t, "_blank"); } }; })(o, i), s = (t => (e, o, r, i) => { const a = [ { key: "externalDownloader", name: e?.externalDownloader?.name || "SSYouTube", url: wt(e?.externalDownloader?.url || "https://ssyoutube.com/watch?v={videoId}", r, i), isYTDL: !1, isDirect: !1 }, { key: "ytdl", name: "by YTDL", url: "http://localhost:5005", isYTDL: !0, isDirect: !1 }, { key: "direct", name: t("directDownload"), url: "#", isYTDL: !1, isDirect: !0 } ], s = a.filter(t => !1 !== o[t.key]); return { baseSites: a, downloadSites: s }; })(o), c = t => { if (!e.enableDownload) { return; } et(); try { const e = t.querySelector(".ytp-download-button"); e && e.remove(); } catch (t) {} const r = new URLSearchParams(location.search).get("v"), i = r ? `https://www.youtube.com/watch?v=${r}` : location.href, l = e.downloadSiteCustomization || { externalDownloader: { name: "SSYouTube", url: "https://ssyoutube.com/watch?v={videoId}" } }, d = e.downloadSites || { externalDownloader: !0, ytdl: !0, direct: !0 }, {downloadSites: u} = s(l, d, r, i), p = (t => { const e = document.createElement("div"); return e.className = "ytp-button ytp-download-button", e.setAttribute("title", t("downloadOptions")), e.setAttribute("tabindex", "0"), e.setAttribute("role", "button"), e.setAttribute("aria-haspopup", "true"), e.setAttribute("aria-expanded", "false"), W(e, '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity="0.5" d="M3 15C3 17.8284 3 19.2426 3.87868 20.1213C4.75736 21 6.17157 21 9 21H15C17.8284 21 19.2426 21 20.1213 20.1213C21 19.2426 21 17.8284 21 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M12 3V16M12 16L16 11.625M12 16L8 11.625" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>\n '), e; })(o), y = ut(".download-options"); y && y.remove(); try { "undefined" != typeof window && (window.youtubePlus = window.youtubePlus || {}, window.youtubePlus.downloadButtonManager = window.youtubePlus.downloadButtonManager || {}, window.youtubePlus.downloadButtonManager.addDownloadButton = t => c(t), window.youtubePlus.downloadButtonManager.refreshDownloadButton = () => { try { const t = ut(".ytp-download-button"), o = ut(".download-options"); if (e.enableDownload && (!t || !o)) { try { const t = ut(".ytp-right-controls"); t && c(t); } catch (t) {} } nt(!!e.enableDownload); } catch {} }, window.youtubePlus.rebuildDownloadDropdown = () => { try { const t = ut(".ytp-right-controls"); if (!t) { return; } window.youtubePlus.downloadButtonManager.addDownloadButton(t), window.youtubePlus.settings = window.youtubePlus.settings || e; } catch (t) { tt.warn("rebuildDownloadDropdown failed", t); } }); } catch (t) { tt.warn("expose rebuildDownloadDropdown failed", t); } if (1 === u.length) { const e = u[0]; p.style.cursor = "pointer"; const o = document.createElement("div"); return p.addEventListener("click", () => a.openDownloadSite(e.url, e.isYTDL, e.isDirect, o, p)), void t.insertBefore(p, t.firstChild); } const m = ((t, e, o) => { const r = document.createElement("div"); r.className = "download-options", r.setAttribute("role", "menu"); const i = document.createElement("div"); i.className = "download-options-list", t.forEach(t => { const e = document.createElement("div"); e.className = "download-option-item", e.textContent = t.name, e.setAttribute("role", "menuitem"), e.setAttribute("tabindex", "0"), e.dataset.url = t.url, e.dataset.isYtdl = t.isYTDL ? "true" : "false", e.dataset.isDirect = t.isDirect ? "true" : "false", i.appendChild(e); }); const a = t => { t && o(t.dataset.url, "true" === t.dataset.isYtdl, "true" === t.dataset.isDirect, r, e); }; return i.addEventListener("click", t => { const e = t.target?.closest?.(".download-option-item"); e && i.contains(e) && a(e); }), i.addEventListener("keydown", t => { const e = t.target?.closest?.(".download-option-item"); e && i.contains(e) && ("Enter" !== t.key && " " !== t.key || a(e)); }), r.appendChild(i), r; })(u, p, a.openDownloadSite); try { document.body.appendChild(m); } catch (t) { p.appendChild(m); } xt(p, m), t.insertBefore(p, t.firstChild); }; return { addDownloadButton: c, refreshDownloadButton: () => { const t = r(".ytp-download-button"); let o = ut(".download-options"); if (e.enableDownload && (!t || !o)) { try { const t = ut(".ytp-right-controls"); t && (c(t), o = ut(".download-options")); } catch (t) { tt?.warn?.("[YouTube+] recreate download button failed:", t); } } nt(!!e.enableDownload); } }; }, refreshVisibility: nt, injectStyles: et }, "undefined" != typeof unsafeWindow && (unsafeWindow.YouTubePlusDownloadButton = window.YouTubePlusDownloadButton)); const St = () => { lt() && ("function" == typeof requestIdleCallback ? requestIdleCallback(q, { timeout: 1500 }) : setTimeout(q, 0)); }; G?.whenRelevant ? G.whenRelevant({ name: "download", isRelevant: lt, onEnter: St }) : dt(St), "function" == typeof G?.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-finish", St, { passive: !0 }) : document.addEventListener("yt-navigate-finish", St, { passive: !0 }); })(); const enhancedSetTimeout_ = setTimeout, {$, $$, byId} = window.YouTubeUtils || {}, onDomReady = window.YouTubeUtils.onDomReady, enhancedLogger = window.YouTubeUtils?.logger || window.YouTubePlusLogger || null, U = window.YouTubeUtils; !(function() { const t = U.setSafeHTML, e = U.getLanguage, o = U?.t || (t => t || ""), r = { enabled: U?.loadFeatureEnabled?.("enableScrollToTopButton") ?? !0, storageKey: "youtube_top_button_settings" }, i = U.debounce; let a = null, s = null; const c = new Set; let l = [], d = null, u = 0; const p = () => { const t = Date.now(); return d && t - u < 5e3 || (d = [ $("ytmusic-app-layout #layout"), $("ytmusic-app-layout"), $("ytmusic-browse-response #contents"), $("ytmusic-section-list-renderer") ].filter(Boolean), u = t), d; }, y = () => { try { const t = U?.getHostname?.() || "", e = []; if ("music.youtube.com" === t) { const t = p(); e.push(...t), e.push($("ytmusic-tabbed-page #content"), $("ytmusic-app-layout #content"), $("#content"), $("ytmusic-app")); } else { "studio.youtube.com" === t && e.push($("ytcp-entity-page #scrollable-content"), $("ytcp-app #content"), $("#main-content"), $("#content"), $("#main"), $("ytcp-app")); } e.push(document.scrollingElement, document.documentElement, document.body); for (const t of e) { if (t && t.scrollHeight > t.clientHeight + 50) { return t; } } if ("music.youtube.com" === t || "studio.youtube.com" === t) { return document.scrollingElement || document.documentElement; } } catch (t) { enhancedLogger?.warn?.("Enhanced", "Error detecting scroll container", t); } return document.scrollingElement || document.documentElement; }; let m = null, f = null, b = null; const h = () => { if (!U?.isMusicDomain?.()) { return null; } const t = [ "ytmusic-player-queue #contents", "ytmusic-player-queue", "#side-panel #contents", "#side-panel", 'ytmusic-tab-renderer[page-type="MUSIC_PAGE_TYPE_QUEUE"] #contents', "ytmusic-queue #automix-contents", "ytmusic-queue #contents" ]; for (const e of t) { try { const t = $(e); if (t && t.scrollHeight > t.clientHeight + 30) { return t; } } catch (t) { U.logSuppressed(t, "Enhanced"); } } const e = [ $("ytmusic-player-page"), $("ytmusic-app-layout"), $("ytmusic-app") ], o = [ "#side-panel", "#right-content", "ytmusic-player-queue", "ytmusic-queue", "ytmusic-tab-renderer[selected] #contents", ".side-panel" ]; for (const t of e) { if (t) { for (const e of o) { try { const o = t.querySelector(e); if (o && o.scrollHeight > o.clientHeight + 30) { return o; } } catch (t) { U.logSuppressed(t, "Enhanced"); } } } } return null; }, g = () => { try { const t = byId("right-tabs-top-button"); t && t.remove(); } catch (t) { U.logSuppressed(t, "Enhanced"); } try { const t = byId("playlist-panel-top-button"); t && t.remove(); } catch (t) { U.logSuppressed(t, "Enhanced"); } (() => { try { const t = byId("music-side-top-button"); t && t.remove(); } catch (t) { U.logSuppressed(t, "Enhanced"); } try { f && b && b.removeEventListener("scroll", f); } catch (t) { U.logSuppressed(t, "Enhanced"); } f = null, b = null; })(), (() => { try { const t = byId("universal-top-button"); t && t.remove(); } catch (t) { U.logSuppressed(t, "Enhanced"); } try { a && s && s.removeEventListener("scroll", a); } catch (t) { U.logSuppressed(t, "Enhanced"); } try { m && window.removeEventListener("scroll", m); } catch (t) { U.logSuppressed(t, "Enhanced"); } try { if (m && c.size) { for (const t of c) { try { t.removeEventListener("scroll", m), t.dt && (t.dt = !1); } catch (t) { U.logSuppressed(t, "Enhanced"); } } } } catch (t) { U.logSuppressed(t, "Enhanced"); } try { l.length && l.forEach(t => clearTimeout(t)); } catch (t) { U.logSuppressed(t, "Enhanced"); } a = null, s = null, m = null, c.clear(), l = []; })(); try { $$("#right-tabs .tab-content-cld").forEach(t => { t?.ut && (t.removeEventListener("scroll", t.ut), t.ut = null); }); } catch (t) { enhancedLogger?.warn?.("Enhanced", "Error cleaning up tab scroll handlers", t); } try { const t = byId("right-tabs"); t && (t.ut && (t.removeEventListener("scroll", t.ut), t.ut = null), t.ft && (t.ft(), t.ft = null)); } catch (t) { U.logSuppressed(t, "Enhanced"); } try { const t = $("ytd-playlist-panel-renderer #items"); t?.ut && (t.removeEventListener("scroll", t.ut), t.ut = null); } catch (t) { U.logSuppressed(t, "Enhanced"); } }; let w = null, v = 0, x = !1, k = null, S = !1, T = null, L = null, M = null; const C = () => (U?.isWatchPage?.() ?? !1) || (U?.isShortsPage?.() ?? !1), E = t => t && ("right-tabs-top-button" === t.id || "universal-top-button" === t.id || "playlist-panel-top-button" === t.id || "music-side-top-button" === t.id), z = t => { try { if (!t) { return; } if ("right-tabs-top-button" === t.id) { const e = $("#right-tabs .tab-content-cld:not(.tab-content-hidden)"), r = byId("right-tabs"), i = r && r.scrollTop > 0 ? r : e && e.scrollTop > 0 ? e : e || r; return void (i && ("scrollBehavior" in (document.documentElement.style || {}) ? i.scrollTo({ top: 0, behavior: "smooth" }) : i.scrollTop = 0, t.setAttribute("aria-label", "Scrolled to top"), enhancedSetTimeout_(() => { t.setAttribute("aria-label", o("scrollToTop")); }, 1e3))); } if ("universal-top-button" === t.id) { const t = U?.getHostname?.() || "", e = "music.youtube.com" === t, o = e || "studio.youtube.com" === t ? y() : s || y(), r = t => { "scrollBehavior" in (document.documentElement.style || {}) ? t.scrollTo({ top: 0, behavior: "smooth" }) : t.scrollTop = 0; }; if (o === window || o === document || o === document.body || o === document.documentElement ? window.scrollTo({ top: 0, behavior: "smooth" }) : o && "function" == typeof o.scrollTo && r(o), e) { window.scrollTo({ top: 0, behavior: "smooth" }); for (const t of p()) { t && t.scrollTop > 0 && r(t); } } return; } if ("playlist-panel-top-button" === t.id) { const t = $("ytd-playlist-panel-renderer"), e = t ? $("#items", t) : null; return void (e && ("scrollBehavior" in (document.documentElement.style || {}) ? e.scrollTo({ top: 0, behavior: "smooth" }) : e.scrollTop = 0)); } if ("music-side-top-button" === t.id) { const t = h() || b; t && ("scrollBehavior" in (document.documentElement.style || {}) ? t.scrollTo({ top: 0, behavior: "smooth" }) : t.scrollTop = 0); } } catch (t) { enhancedLogger?.error?.("Enhanced", "Error scrolling to top", t); } }, _ = (() => { let t = !1; return () => { if (t) { return; } t = !0; const e = window.YouTubePlusEventDelegation; if (e?.on) { e.on(document, "click", ".top-button", (t, e) => { E(e) && z(e); }), e.on(document, "keydown", ".top-button", (t, e) => { E(e) && ("Enter" !== t.key && " " !== t.key || (t.preventDefault(), z(e))); }); } else { const t = U?.cleanupManager, e = t => { const e = t.target?.closest?.(".top-button"); E(e) && z(e); }, o = t => { const e = t.target?.closest?.(".top-button"); E(e) && ("Enter" !== t.key && " " !== t.key || (t.preventDefault(), z(e))); }; t?.registerListener ? (t.registerListener(document, "click", e, !0), t.registerListener(document, "keydown", o, !0)) : (document.addEventListener("click", e, !0), document.addEventListener("keydown", o, !0)); } }; })(), I = t => (t && clearTimeout(t), null), A = () => { try { const t = U?.StyleManager; if (t && "function" == typeof t.add) { const e = window.YouTubePlusDesignSystem?.getStyle?.("ytp-enhanced-styles") || ""; t.add("ytp-enhanced-styles", e); const o = byId("custom-styles"); o && o.remove(); } } catch (t) { enhancedLogger?.warn?.("Enhanced", "Failed to inject enhanced styles via StyleManager", t); } }, P = (t, e) => { try { if (!e || !t) { return; } e.classList.toggle("visible", t.scrollTop > 100); } catch (t) { enhancedLogger?.error?.("Enhanced", "Error in handleScroll", t); } }, j = (() => { let t = null; return () => { t && clearTimeout(t), t = enhancedSetTimeout_(() => { try { $$(".tab-content-cld").forEach(t => { t.ut && (t.removeEventListener("scroll", t.ut), delete t.ut), t.bt && (t.bt.disconnect(), delete t.bt), window.YouTubePlusScrollManager?.removeAllListeners?.(t); }); try { const t = byId("right-tabs"); t && (t.ut && (t.removeEventListener("scroll", t.ut), delete t.ut), t.ft && (t.ft(), delete t.ft)); } catch (t) { enhancedLogger?.warn?.("Enhanced", "Error cleaning up right-tabs scroll handler", t); } const t = $("#right-tabs .tab-content-cld:not(.tab-content-hidden)"), e = byId("right-tabs-top-button"); if (t && e) { const o = byId("right-tabs"), r = o && o !== t && o.scrollHeight > o.clientHeight + 10 ? o : t; if (window.YouTubePlusScrollManager) { const t = window.YouTubePlusScrollManager.addScrollListener(r, () => P(r, e), { debounce: 100, runInitial: !0 }); r.ft = t; } else { const t = i(() => P(r, e), 100); r.ut = t, r.addEventListener("scroll", t, { passive: !0, capture: !1 }), P(r, e); } } } catch (t) { enhancedLogger?.error?.("Enhanced", "Error in setupScrollListener", t); } }, 100); }; })(), H = () => { try { if (_(), byId("universal-top-button")) { return; } if (!r.enabled) { return; } const e = y(), d = e === document.scrollingElement || e === document.documentElement || e === document.body ? window : e; s = d; const u = document.createElement("button"); u.id = "universal-top-button", u.className = "top-button", u.title = o("scrollToTop"), u.setAttribute("aria-label", o("scrollToTop")), t(u, '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>'); const f = U?.getHostname?.() || ""; "music.youtube.com" !== f && "studio.youtube.com" !== f || (u.style.zIndex = "10000"), document.body.appendChild(u); const b = i(() => { const t = d === window ? window.scrollY : d.scrollTop; u.classList.toggle("visible", t > 100); }, 100); a = b, d.addEventListener("scroll", b, { passive: !0 }); const h = d === window ? window.scrollY : d.scrollTop; if (u.classList.toggle("visible", h > 100), "music.youtube.com" === f || "studio.youtube.com" === f) { const t = () => { const t = p(); return d !== window && d instanceof Element && !t.includes(d) ? [ ...t, d ] : t; }, e = i(() => { let e = window.scrollY > 100; if (!e) { for (const o of t()) { if (o.scrollTop > 100) { e = !0; break; } } } u.classList.toggle("visible", e); }, 100); window.addEventListener("scroll", e, { passive: !0 }), m = e; const o = () => { const t = [ $("ytmusic-app-layout #layout"), $("ytmusic-app-layout") ]; for (const o of t) { o && !o.dt && (o.dt = !0, o.addEventListener("scroll", e, { passive: !0 }), c.add(o)); } }; o(), l.push(enhancedSetTimeout_(o, 1e3)), l.push(enhancedSetTimeout_(o, 3e3)); } } catch (t) { enhancedLogger?.error?.("Enhanced", "Error creating universal button", t); } }, D = () => { try { if (!U?.isMusicDomain?.()) { return; } if (_(), byId("music-side-top-button")) { return; } if (!r.enabled) { return; } const e = h(); if (!e) { return void U?.createRetryScheduler?.({ check: () => !(!byId("music-side-top-button") && r.enabled) || !!h() && (D(), !0), maxAttempts: 8, interval: 500 }); } const a = document.createElement("button"); a.id = "music-side-top-button", a.className = "top-button", a.title = o("scrollToTop"), a.setAttribute("aria-label", o("scrollToTop")), t(a, '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>'), e.style.position = e.style.position || "relative", Object.assign(a.style, { position: "absolute", bottom: "16px", right: "16px", zIndex: "1000" }), e.appendChild(a); const s = i(() => { a.classList.toggle("visible", e.scrollTop > 100); }, 100); b = e, f = s, e.addEventListener("scroll", s, { passive: !0 }), a.classList.toggle("visible", e.scrollTop > 100); } catch (t) { enhancedLogger?.error?.("Enhanced", "Error creating music side button", t); } }, O = "https://returnyoutubedislikeapi.com/votes", B = 6e5, R = new Map; let F = null, N = null, Z = null, V = null; const Y = (t, e) => { if (!t) { return null; } const o = t.shadowRoot || t, r = o.querySelector(e); if (r) { return r; } const i = o.querySelectorAll("*"); for (const t of i) { const o = Y(t, e); if (o) { return o; } } return null; }, q = (t, e, o = []) => { if (!t) { return o; } if (t.querySelectorAll) { const r = t.querySelectorAll(e); for (const t of r) { o.push(t); } } const r = t.querySelectorAll ? t.querySelectorAll("*") : []; for (const t of r) { t.shadowRoot && q(t.shadowRoot, e, o); } return o; }, G = () => { try { const t = new URL(window.location.href), e = t.pathname || ""; if (e.startsWith("/shorts/")) { return e.slice(8); } if (e.startsWith("/clip/")) { const t = $("meta[itemprop='videoId'], meta[itemprop='identifier']"); return t?.getAttribute("content") || null; } let o = t.searchParams.get("v"); if (o) { return o; } const r = $("ytd-watch-flexy"); if (r && (o = r.getAttribute("video-id"), o)) { return o; } const i = byId("movie_player") || $("#movie_player"); if (i && "function" == typeof i.getVideoData && (o = i.getVideoData()?.video_id, o)) { return o; } const a = $("meta[itemprop='videoId']"); return a && (o = a.getAttribute("content"), o) ? o : null; } catch (t) { return null; } }, W = () => window.location.pathname.startsWith("/shorts") ? (() => { const t = $("ytd-reel-video-renderer[is-active]"); if (t) { const e = $("dislike-button-view-model", t) || $("like-button-view-model", t)?.parentElement?.querySelector('[aria-label*="islike"]')?.closest("button")?.parentElement || $("#dislike-button", t); if (e) { return e; } } const e = $("ytd-shorts"); if (e) { const t = $("dislike-button-view-model", e) || $("#dislike-button", e); if (t) { return t; } } return $("dislike-button-view-model") || $("#dislike-button") || null; })() : (t => { if (!t) { return null; } const e = t.querySelector("ytd-segmented-like-dislike-button-renderer"); if (e) { const t = e.querySelector("dislike-button-view-model") || e.querySelector("#segmented-dislike-button") || e.children[1]; if (t) { return t; } } const o = t.querySelector("dislike-button-view-model"); if (o) { return o; } const r = t.querySelector('button[aria-label*="dislike" i]') || t.querySelector('button[aria-label*="islike" i]') || t.querySelector('button[aria-label*="не нравится" i]'); return r ? r.closest("dislike-button-view-model") || r.parentElement : t.children?.[1] ? t.children[1] : null; })($("ytd-watch-flexy:not([hidden]) ytd-menu-renderer.ytd-watch-metadata > div#top-level-buttons-computed") || $("ytd-watch-flexy:not([hidden]) ytd-menu-renderer.ytd-video-primary-info-renderer > div") || $("ytd-watch-flexy:not([hidden]) #menu-container #top-level-buttons-computed") || $("ytd-menu-renderer.ytd-watch-metadata > div#top-level-buttons-computed") || $("ytd-menu-renderer.ytd-video-primary-info-renderer > div") || $("#menu-container #top-level-buttons-computed") || null) || $("ytd-watch-flexy:not([hidden]) ytd-watch-metadata ytd-segmented-like-dislike-button-renderer dislike-button-view-model") || $("ytd-watch-flexy:not([hidden]) ytd-watch-metadata dislike-button-view-model") || $("ytd-watch-metadata ytd-segmented-like-dislike-button-renderer dislike-button-view-model") || $("ytd-watch-metadata dislike-button-view-model") || $("ytd-segmented-like-dislike-button-renderer dislike-button-view-model") || $("dislike-button-view-model") || $("#segmented-dislike-button") || null, J = (t, o) => { try { const r = (t => { if (!t) { return null; } if (window.location.pathname.startsWith("/shorts")) { const e = Y(t, "yt-formatted-string") || Y(t, 'span[role="text"]') || Y(t, "span.label") || Y(t, ".label"); if (e) { return e.hasAttribute("data-ytp-original-text") || e.setAttribute("data-ytp-original-text", e.innerText || "Dislike"), e; } } const e = Y(t, "#ytp-plus-dislike-text"); if (e) { return e; } const o = Y(t, "button") || t.querySelector("button") || t.closest("button") || t; let r = Y(o, ".yt-spec-button-shape-next__button-text-content"); if (!r && (r = (o.shadowRoot || o).querySelector(".yt-spec-button-shape-next__button-text-content"), !r)) { r = document.createElement("div"), r.className = "yt-spec-button-shape-next__button-text-content"; const t = Y(o, ".yt-spec-button-shape-next__icon"); (t ? t.parentNode : o).appendChild(r); } const i = document.createElement("span"); i.id = "ytp-plus-dislike-text", i.setAttribute("role", "text"), i.className = "yt-core-attributed-string yt-core-attributed-string--white-space-no-wrap", i.classList.add("ytp-plus-dislike-text--regular"), r.appendChild(i); try { const t = r.getRootNode(); if (t instanceof ShadowRoot && !t.querySelector("#ytp-plus-dislike-style")) { const e = document.createElement("style"); e.id = "ytp-plus-dislike-style", e.textContent = "\n #ytp-plus-dislike-text.ytp-plus-dislike-text--regular {\n margin-left: 6px !important;\n font-size: 1.4rem !important;\n line-height: 2rem !important;\n font-weight: 500 !important;\n display: inline-block !important;\n visibility: visible !important;\n opacity: 1 !important;\n min-width: 2em !important;\n text-align: center !important;\n }\n :host {\n min-width: fit-content !important;\n width: auto !important;\n }\n yt-button-shape {\n min-width: fit-content !important;\n width: auto !important;\n }\n button.yt-spec-button-shape-next--icon-only-default,\n button.yt-spec-button-shape-next--segmented-end,\n button.yt-spec-button-shape-next,\n button {\n min-width: fit-content !important;\n width: auto !important;\n display: inline-flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n button.yt-spec-button-shape-next--segmented-end {\n padding-left: 8px !important;\n padding-right: 12px !important;\n }\n button.yt-spec-button-shape-next--icon-only-default {\n padding-left: 8px !important;\n padding-right: 8px !important;\n }\n .yt-spec-button-shape-next__button-text-content {\n display: inline-flex !important;\n align-items: center !important;\n justify-content: center !important;\n min-width: fit-content !important;\n }\n ", t.appendChild(e); } } catch (t) { enhancedLogger?.warn?.("Enhanced", "Failed to inject shadow style", t); } try { o.style.minWidth = "auto", o.style.width = "auto"; const e = t.closest("ytDislikeButtonViewModelHost"); e && (e.style.minWidth = "auto"), t.style.minWidth = "auto"; } catch (t) { enhancedLogger?.warn?.("Enhanced", "Failed to style dislike button", t); } return i; })(t); if (!r) { return; } const i = (t => { try { return new Intl.NumberFormat(e() || "en", { notation: "compact", compactDisplay: "short" }).format(Number(t) || 0); } catch (e) { return String(t || 0); } })(o); if (r.innerText !== String(i)) { r.innerText = String(i), r.style.display = "inline-block", r.style.visibility = "visible", r.style.opacity = "1"; const e = r.closest("button") || Y(t, "button") || t.querySelector("button"); e && (e.style.minWidth = "fit-content", e.style.width = "auto"); } } catch (t) { enhancedLogger?.warn?.("Enhanced", "Failed to set dislike display", t); } }, K = async () => { try { if (Z && (clearInterval(Z), Z = null), N) { return; } const t = async () => { const t = W(); if (t) { const e = window.location.pathname.startsWith("/shorts"); if (!e && !(Y(t, "button") || t.querySelector("button") || "BUTTON" === t.tagName && t)) { return !1; } const o = G(); if (!o) { return !1; } const r = Y(t, e ? 'yt-formatted-string, span[role="text"], span.label, .label' : "#ytp-plus-dislike-text"); if (t.getAttribute("data-ytp-video-id") === o && r) { if (e) { const t = r.getAttribute("data-ytp-original-text"); if (t && r.innerText !== t) { return !0; } } else if (r.innerText && "" !== r.innerText.trim()) { return !0; } } const i = await (async t => { if (!t) { return 0; } const e = R.get(t); if (e && Date.now() < e.expiresAt) { return e.value; } if (R.size > 50) { const t = Date.now(); for (const [e, o] of R) { t >= o.expiresAt && R.delete(e); } if (R.size > 50) { const t = R.keys(); for (;R.size > 25; ) { const e = t.next(); if (e.done) { break; } R.delete(e.value); } } } try { if ("undefined" != typeof GM_xmlhttpRequest) { const e = await new Promise((e, o) => { const r = enhancedSetTimeout_(() => o(new Error("timeout")), 8e3); GM_xmlhttpRequest({ method: "GET", url: `${O}?videoId=${encodeURIComponent(t)}`, timeout: 8e3, headers: { Accept: "application/json" }, onload: t => { clearTimeout(r), t.status >= 200 && t.status < 300 ? e(t.responseText) : o(new Error(`HTTP ${t.status}`)); }, onerror: t => { clearTimeout(r), o(t || new Error("network")); }, ontimeout: () => { clearTimeout(r), o(new Error("timeout")); } }); }), o = JSON.parse(e || "{}"), r = o && "object" == typeof o ? o.dislikes : void 0, i = Number.isFinite(Number(r)) ? Math.max(0, Math.floor(Number(r))) : 0; return R.set(t, { value: i, expiresAt: Date.now() + B }), i; } const e = new AbortController, o = enhancedSetTimeout_(() => e.abort(), 8e3); try { const r = await fetch(`${O}?videoId=${encodeURIComponent(t)}`, { method: "GET", cache: "no-cache", signal: e.signal, headers: { Accept: "application/json" } }); if (clearTimeout(o), !r.ok) { throw new Error(`HTTP ${r.status}`); } const i = await r.json(), a = i && "object" == typeof i ? i.dislikes : void 0, s = Number.isFinite(Number(a)) ? Math.max(0, Math.floor(Number(a))) : 0; return R.set(t, { value: s, expiresAt: Date.now() + B }), s; } finally { clearTimeout(o); } } catch (t) { return 0; } })(o); return J(t, i), t.setAttribute("data-ytp-video-id", o), (t => { if (!t) { return; } const e = (Y(t, "button") || t.querySelector("button") || t).getRootNode(); if (!F || V !== e) { F && (F.disconnect(), F = null), V = e; try { F = new MutationObserver(() => { const t = G(), e = R.get(t); if (e) { const t = W(); t && J(t, e.value); } }), F.observe(e, { childList: !0, subtree: !0, attributes: !0 }); } catch (t) { enhancedLogger?.warn?.("Enhanced", "Failed to create dislike direct observer", t); } } })(t), !0; } return !1; }, e = async (o = 0) => { try { !await t() && o < 15 && enhancedSetTimeout_(() => e(o + 1), 100 + 100 * o); } catch (t) {} }; await e(); const o = window.location.pathname.startsWith("/shorts"), r = 2e4, i = Date.now(), a = window.YouTubePlusMutationCoordinator; a?.subscribeRoot && (N = "enhanced::dislikePoll", a.subscribeRoot(N, async () => { if (Date.now() - i > r) { return N && a.unsubscribe(N), void (N = null); } await e(); }, { selector: o ? "#shorts-container, ytd-shorts" : "ytd-watch-flexy, #page-manager, #below", childList: !0, attributes: !1, subtree: !0 })), Z = setInterval(async () => { if (C()) { try { await t(); } catch (t) {} } else { Z && (clearInterval(Z), Z = null); } }, 1500); } catch (t) { enhancedLogger?.warn?.("Enhanced", "Failed to initialize Return YouTube Dislike", t); } }, X = () => { const t = U?.getHostname?.() || ""; if ("music.youtube.com" === t || "studio.youtube.com" === t) { return !0; } if (U?.isWatchPage?.() || U?.isShortsPage?.()) { return !(U?.loadFeatureEnabled?.("enableTabview") ?? 1); } const e = window.location.pathname, {search: o} = window.location; return "/results" === e && o.includes("search_query=") || "/playlist" === e && o.includes("list="), !0; }, Q = t => { try { const {target: e} = t, o = e?.closest?.(".tab-btn[tyt-tab-content]"); o && enhancedSetTimeout_(j, 100); } catch (t) { enhancedLogger?.error?.("Enhanced", "Error in click handler", t); } }, tt = () => { v++; try { T && "object" == typeof T && T.stop ? T.stop() : T = I(T); } catch (t) { U.logSuppressed(t, "Enhanced"); } T = null; try { L && "object" == typeof L && L.stop ? L.stop() : L = I(L); } catch (t) { U.logSuppressed(t, "Enhanced"); } L = null; try { if (w && window.YouTubePlusMutationCoordinator?.unsubscribe?.(w), w) { try { U?.ObserverRegistry?.untrack?.(); } catch (t) { U.logSuppressed(t, "Enhanced"); } } } catch (t) { U.logSuppressed(t, "Enhanced"); } w = null, (() => { try { if (!x) { return; } const t = window.YouTubePlusEventDelegation; S && t?.off && k ? t.off(document, "click", ".tab-btn[tyt-tab-content]", k) : document.removeEventListener("click", Q, !0), k = null, S = !1, x = !1; } catch (t) { enhancedLogger?.error?.("Enhanced", "Error cleaning up events", t); } })(); try { (() => { try { N && (window.YouTubePlusMutationCoordinator?.unsubscribe?.(N), N = null), Z && (clearInterval(Z), Z = null), F && (F.disconnect(), F = null), V = null; const t = []; q(document.body, "#ytp-plus-dislike-text", t), t.forEach(t => { try { t.parentNode && t.parentNode.removeChild(t); } catch (t) { U.logSuppressed(t, "Enhanced"); } }); const e = []; q(document.body, "[data-ytp-video-id]", e), e.forEach(t => { try { t.removeAttribute("data-ytp-video-id"); } catch (t) { U.logSuppressed(t, "Enhanced"); } }); const o = []; q(document.body, "[data-ytp-original-text]", o), o.forEach(t => { try { t.innerText = t.getAttribute("data-ytp-original-text") || "", t.removeAttribute("data-ytp-original-text"); } catch (t) { U.logSuppressed(t, "Enhanced"); } }); } catch (t) { enhancedLogger?.warn?.("Enhanced", "Dislike cleanup error", t); } })(); } catch (t) { U.logSuppressed(t, "Enhanced"); } }, et = () => { if (!r.enabled) { return; } if (!U?.isWatchPage?.()) { return; } const e = ++v; (() => { try { if (x) { return; } const t = window.YouTubePlusEventDelegation; t?.on ? (k = (t, e) => { e && enhancedSetTimeout_(j, 100); }, t.on(document, "click", ".tab-btn[tyt-tab-content]", k, { capture: !0 }), S = !0) : document.addEventListener("click", Q, !0), x = !0; } catch (t) { enhancedLogger?.error?.("Enhanced", "Error in setupEvents", t); } })(); const a = U?.createRetryScheduler?.({ check: () => { if (e !== v || !U?.isWatchPage?.()) { return !0; } if ($("#right-tabs")) { (() => { try { _(); const e = $("#right-tabs"); if (!e || byId("right-tabs-top-button")) { return; } if (!r.enabled) { return; } const i = document.createElement("button"); i.id = "right-tabs-top-button", i.className = "top-button", i.title = o("scrollToTop"), i.setAttribute("aria-label", o("scrollToTop")), t(i, '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>'), e.style.position = "relative", e.appendChild(i), j(); } catch (t) { enhancedLogger?.error?.("Enhanced", "Error creating button", t); } })(); try { w && window.YouTubePlusMutationCoordinator?.unsubscribe?.(w); } catch (t) { U.logSuppressed(t, "Enhanced"); } return w = (() => { try { const t = window.YouTubePlusMutationCoordinator; if (!t?.subscribeRoot) { return null; } const e = "enhanced::tabChanges"; t.subscribeRoot(e, t => { try { t.some(t => "attributes" === t.type && "class" === t.attributeName && t.target instanceof Element && t.target.classList.contains("tab-content-cld")) && enhancedSetTimeout_(j, 100); } catch (t) { enhancedLogger?.error?.("Enhanced", "Error in mutation observer", t); } }, { selector: "#right-tabs .tab-content-cld", attributes: !0, childList: !1, subtree: !0, attributeFilter: [ "class" ] }); try { U?.ObserverRegistry?.track?.(); } catch (t) { U.logSuppressed(t, "Enhanced"); } if ($("#right-tabs")) { return e; } try { U?.ObserverRegistry?.untrack?.(); } catch (t) { U.logSuppressed(t, "Enhanced"); } return t.unsubscribe(e), null; } catch (t) { return enhancedLogger?.error?.("Enhanced", "Error in observeTabChanges", t), null; } })(), !0; } return !1; }, maxAttempts: 40, interval: 250 }), s = U?.createRetryScheduler?.({ check: () => { if (e !== v || !U?.isWatchPage?.()) { return !0; } try { if ($("ytd-playlist-panel-renderer") && !byId("playlist-panel-top-button")) { return (() => { try { _(); const e = $("ytd-playlist-panel-renderer"); if (!e || byId("playlist-panel-top-button")) { return; } if (!r.enabled) { return; } const a = document.createElement("button"); a.id = "playlist-panel-top-button", a.className = "top-button", a.title = o("scrollToTop"), a.setAttribute("aria-label", o("scrollToTop")), t(a, '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>'); const s = $("#items", e); if (!s) { return; } e.style.position = e.style.position || "relative", Object.assign(a.style, { position: "absolute", bottom: "16px", right: "16px", zIndex: "1000" }), e.appendChild(a); const c = i(() => P(s, a), 100); s.ut = c, s.addEventListener("scroll", c, { passive: !0 }), P(s, a); const l = () => { try { if (!e.isConnected || e.hidden) { return void (a.style.display = "none"); } if (null === e.offsetParent && "fixed" !== e.style.position) { return void (a.style.display = "none"); } const {width: t, height: o} = e.getBoundingClientRect(); if (t < 40 || o < 40) { return void (a.style.display = "none"); } if (!s || 0 === s.offsetHeight || 0 === s.scrollHeight) { return void (a.style.display = "none"); } a.style.display = ""; } catch (t) { try { a.style.display = "none"; } catch (t) { U.logSuppressed(t, "Enhanced"); } } }; let d = null; try { "undefined" != typeof ResizeObserver && (d = new ResizeObserver(l), d.observe(e), s && d.observe(s)); } catch (t) { d = null; } const u = window.YouTubePlusMutationCoordinator; u?.watchTarget && u.watchTarget("enhanced::playlistPanelVisibility", e, l, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "class", "style", "hidden" ] }), l(); try { U && YouTubeUtils.cleanupManager && d && YouTubeUtils.cleanupManager.register(() => { try { d.disconnect(); } catch (t) { U.logSuppressed(t, "Enhanced"); } }); } catch (t) { U.logSuppressed(t, "Enhanced"); } } catch (t) { enhancedLogger?.error?.("Enhanced", "Error creating playlist panel button", t); } })(), !0; } } catch (t) { enhancedLogger?.error?.("Enhanced", "Error checking for playlist panel", t); } return !1; }, maxAttempts: 30, interval: 300 }); T = a, L = s; }, nt = () => { try { A(); const t = () => { try { X() && !byId("universal-top-button") && H(), U?.isMusicDomain?.() && !byId("music-side-top-button") && D(); } catch (t) { enhancedLogger?.error?.("Enhanced", "Error checking page type", t); } }, e = () => { if (tt(), d = null, u = 0, t(), C()) { try { K(); } catch (t) { enhancedLogger?.warn?.("Enhanced", "initReturnDislike error", t); } } et(); }; if (e(), "function" == typeof U?.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-finish", () => enhancedSetTimeout_(e, 200), { passive: !0 }) : window.addEventListener("yt-navigate-finish", () => { enhancedSetTimeout_(e, 200); }), U?.isMusicDomain?.()) { window.addEventListener("popstate", () => enhancedSetTimeout_(e, 200)); const t = window.YouTubePlusMutationCoordinator; t?.subscribeRoot && (M = "enhanced::musicSidePanel", t.subscribeRoot(M, () => { !byId("music-side-top-button") && r.enabled && D(); }, { selector: "ytmusic-player-page, ytmusic-app-layout, ytmusic-app, #layout", childList: !0, attributes: !1, subtree: !0 })); } } catch (t) { enhancedLogger?.error?.("Enhanced", "Error in initialization", t); } }; window.addEventListener("youtube-plus-settings-updated", t => { try { const e = !1 !== t?.detail?.enableScrollToTopButton, o = !1 !== t?.detail?.enableTabview, i = ((U?.isWatchPage?.() ?? !1) || (U?.isShortsPage?.() ?? !1)) && !o; if (r.enabled = e, !r.enabled) { return g(), void tt(); } if (A(), g(), tt(), !X() && !i || byId("universal-top-button") || H(), U?.isMusicDomain?.() && !byId("music-side-top-button") && D(), et(), C()) { try { K(); } catch (t) { enhancedLogger?.warn?.("Enhanced", "initReturnDislike error after settings update", t); } } } catch (t) { U.logSuppressed(t, "Enhanced"); } }), onDomReady(() => { "function" == typeof requestIdleCallback ? requestIdleCallback(nt, { timeout: 4e3 }) : enhancedSetTimeout_(nt, 0); }); })(), (function() { const t = "youtube_plus_manual_playback_quality", e = [ "highres", "hd2160", "hd1440", "hd1080", "hd720", "large", "medium", "small", "tiny", "auto" ]; let o = [], r = ""; const i = () => { try { const t = window.location.pathname || ""; return "/watch" === t || t.startsWith("/shorts/"); } catch (t) { return !1; } }, a = t => { const e = String(t || "").trim().toLowerCase(); return e && "unknown" !== e ? e : ""; }, s = () => byId("movie_player"), c = () => { o.forEach(t => clearTimeout(t)), o = []; }, l = e => { const o = a(e); try { if (!o || "auto" === o) { return void localStorage.removeItem(t); } localStorage.setItem(t, o); } catch (t) { U.logSuppressed(t, "Enhanced"); } }, d = () => { if (!(U?.loadFeatureEnabled?.("enableRememberManualQuality") ?? 1)) { return !0; } if (!i()) { return !0; } const o = (() => { try { return a(localStorage.getItem(t)); } catch (t) { return ""; } })(); if (!o) { return !0; } const c = s(); if (!c) { return !1; } const l = (() => { try { const t = window.location.pathname || ""; if ("/watch" === t) { return new URLSearchParams(window.location.search || "").get("v") || ""; } if (t.startsWith("/shorts/")) { return t.split("/")[2] || ""; } } catch (t) { U.logSuppressed(t, "Enhanced"); } return ""; })(), d = a(c?.getPlaybackQuality?.()); if (l && r === l && d === o) { return !0; } try { const t = "function" == typeof c.getAvailableQualityLevels ? c.getAvailableQualityLevels().map(a).filter(Boolean) : []; if (!t.length || 1 === t.length && "auto" === t[0]) { return !1; } let i = o; if (!t.includes(o)) { const r = e.indexOf(o); -1 !== r && (i = e.slice(r).find(e => t.includes(e)) || "auto"); } "function" == typeof c.setPlaybackQualityRange && c.setPlaybackQualityRange(i, i), "function" == typeof c.setPlaybackQuality && c.setPlaybackQuality(i); try { localStorage.setItem("yt-player-quality", JSON.stringify({ data: i, expiration: Date.now() + 2592e6, creation: Date.now() })); } catch (t) {} return r = l, !0; } catch (t) { return !1; } }, u = () => { if (c(), (U?.loadFeatureEnabled?.("enableRememberManualQuality") ?? 1) && i()) { for (let t = 0; t < 16; t += 1) { const e = enhancedSetTimeout_(() => { d() && c(); }, 350 * t); o.push(e); } } }, p = () => { r = "", u(); }; document.addEventListener("click", t => { const e = t.target instanceof HTMLElement ? t.target : null, o = e?.closest?.(".ytp-quality-menu .ytp-menuitem, .ytp-panel-menu .ytp-menuitem"); if (!o) { return; } const r = String(o.textContent || "").trim().toLowerCase(), i = String(o.getAttribute("data-value") || o.dataset?.value || "").trim(); if (!r && !i) { return; } if (!i && !/(\bauto\b|авто|\d{3,4}p|\bhd\b|\b4k\b|\b8k\b)/.test(r)) { return; } const c = ((t, e) => { const o = a(e); if ([ "highres", "hd2160", "hd1440", "hd1080", "hd720", "large", "medium", "small", "tiny", "auto" ].includes(o)) { return o; } const r = String(t || "").toLowerCase(); return r.includes("2160p") || r.includes("4k") || r.includes("2160") ? "hd2160" : r.includes("1440p") || r.includes("2k") || r.includes("1440") ? "hd1440" : r.includes("1080p") || r.includes("1080") ? "hd1080" : r.includes("720p") || r.includes("720") ? "hd720" : r.includes("480p") || r.includes("480") ? "large" : r.includes("360p") || r.includes("360") ? "medium" : r.includes("240p") || r.includes("240") ? "small" : r.includes("144p") || r.includes("144") ? "tiny" : r.includes("auto") || r.includes("авто") ? "auto" : o.includes("2160") ? "hd2160" : o.includes("1440") ? "hd1440" : o.includes("1080") ? "hd1080" : o.includes("720") ? "hd720" : o.includes("480") ? "large" : o.includes("360") ? "medium" : o.includes("240") ? "small" : o.includes("144") ? "tiny" : o.includes("auto") ? "auto" : o; })(r, i); if (c) { if (!(U?.loadFeatureEnabled?.("enableRememberManualQuality") ?? 1)) { return; } l(c), enhancedSetTimeout_(() => { u(); }, 50); } else { enhancedSetTimeout_(() => { if (!(U?.loadFeatureEnabled?.("enableRememberManualQuality") ?? 1)) { return; } if ("auto" === i || /\bauto\b|авто/.test(r)) { return void l("auto"); } const t = a(s()?.getPlaybackQuality?.()); t && l(t), u(); }, 150); } }, !0), document.addEventListener("loadedmetadata", t => { const e = t.target; e instanceof HTMLElement && "VIDEO" === e.tagName && u(); }, !0), window.addEventListener("youtube-plus-settings-updated", () => { r = "", u(); }), window.addEventListener("yt-navigate-finish", p, { passive: !0 }), window.addEventListener("ytp:nav-refresh", p, { passive: !0 }), onDomReady(u); })(), (function() { try { const t = "undefined" == typeof location ? "" : location.hostname; if (!t) { return; } if (!/(^|\.)youtube\.com$/.test(t) && !/\.youtube\.google/.test(t)) { return; } const e = U?.SETTINGS_KEY || "youtube_plus_settings", o = "ytp-zen-features-style", r = "ytp-zen-features-style-noncritical", i = "zen-features-style", a = "zen-features-style-noncritical"; let s = null; const c = { enableZenStyles: !0, hideSideGuide: !1, zenStyles: { themeVariant: "glass", thumbnailHover: !0, immersiveSearch: !0, hideVoiceSearch: !0, transparentHeader: !0, hideSideGuide: !0, cleanSideGuide: !1, fixFeedLayout: !0, sideVideosColumnsEnabled: !1, sideVideosColumns: 0, compactFeed: !0, betterCaptions: !0, playerBlur: !0, theaterEnhancements: !0 } }, l = () => { let t = null; try { const o = window.YouTubePlusSettingsStore; if (o && "function" == typeof o.load) { t = o.load(); } else { const o = localStorage.getItem(e); o && (t = JSON.parse(o)); } } catch (t) { enhancedLogger?.warn?.("Enhanced", "Zen settings parse error", t); } const o = { ...c, ...t && "object" == typeof t ? t : null }; o.zenStyles = { ...c.zenStyles, ...o.zenStyles && "object" == typeof o.zenStyles ? o.zenStyles : null }, !0 === o.hideSideGuide && !0 !== o.zenStyles.hideSideGuide && (o.zenStyles.hideSideGuide = !0), !0 !== o.zenStyles.sideVideosTwoColumns || null != o.zenStyles.sideVideosColumns && "" !== o.zenStyles.sideVideosColumns || (o.zenStyles.sideVideosColumns = 2), !0 === o.zenStyles.sideVideosTwoColumns && (o.zenStyles.sideVideosColumnsEnabled = !0); const r = Number(o.zenStyles.sideVideosColumns); return o.zenStyles.sideVideosColumns = !Number.isFinite(r) || r < 0 ? 0 : r, o.zenStyles.sideVideosColumns = Math.min(2, o.zenStyles.sideVideosColumns), "boolean" != typeof o.zenStyles.sideVideosColumnsEnabled && (o.zenStyles.sideVideosColumnsEnabled = o.zenStyles.sideVideosColumns > 0), o; }, d = { thumbnailHover: "\n /* yt-thumbnail hover */\n #inline-preview-player {transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) 1s !important; transform: scale(1) !important;}\n #video-preview-container:has(#inline-preview-player) {transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important; border-radius: 1.2em !important; overflow: hidden !important; transform: scale(1) !important;}\n #video-preview-container:has(#inline-preview-player):hover {transform: scale(1.25) !important; box-shadow: rgba(0,0,0,0.5) 0px 0px 60px !important; transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) 2s !important;}\n ytd-app #content {opacity: 1 !important; transition: opacity 0.3s ease-in-out !important;}\n ytd-app:has(#video-preview-container:hover) #content {opacity: 0.5 !important; transition: opacity 4s ease-in-out 1s !important;}\n ", immersiveSearch: '\n /* yt-Immersive search */\n #page-manager, yt-searchbox {transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.35) !important;}\n #masthead yt-searchbox button[aria-label="Search"] {display: none !important;}\n .ytSearchboxComponentInputBox {border-radius: 2em !important;}\n yt-searchbox:has(.ytSearchboxComponentInputBoxHasFocus) {position: relative !important; left: 0vw !important; top: -30vh !important; height: 40px !important; max-width: 600px !important; transform: scale(1) !important;}\n @media only screen and (min-width: 1400px) {yt-searchbox:has(.ytSearchboxComponentInputBoxHasFocus) { height: 60px !important; max-width: 700px !important; transform: scale(1.1) !important;}}\n yt-searchbox:has(.ytSearchboxComponentInputBoxHasFocus) .ytSearchboxComponentInputBox,\n yt-searchbox:has(.ytSearchboxComponentInputBoxHasFocus) #i0 {background-color: var(--yt-bg-primary) !important; box-shadow: black 0 0 30px !important;}\n yt-searchbox:has(.ytSearchboxComponentInputBoxHasFocus) #i0 {margin-top: 10px !important;}\n @media only screen and (min-width: 1400px) {yt-searchbox:has(.ytSearchboxComponentInputBoxHasFocus) #i0 {margin-top: 30px !important;}}\n .ytd-masthead #center:has(.ytSearchboxComponentInputBoxHasFocus) {height: 100vh !important; width: 100vw !important; left: 0 !important; top: 0 !important; position: fixed !important; justify-content: center !important; align-items: center !important;}\n #content:has(.ytSearchboxComponentInputBoxHasFocus) #page-manager {filter: blur(20px) !important; transform: scale(1.05) !important;}\n ', hideVoiceSearch: "\n /* No voice search button */\n #voice-search-button {display: none !important;}\n ", transparentHeader: "\n /* Transparent header */\n :root{\n --yt-spec-base-background: transparent;\n --ytd-masthead-background: transparent;\n --yt-spec-brand-background-primary: transparent;\n --yt-spec-brand-background-solid: transparent;\n --yt-spec-general-background-a: transparent;\n --yt-spec-raised-background: transparent;\n --yt-spec-additive-background: transparent;\n }\n #masthead-container,\n #masthead,\n ytd-masthead,\n #background.ytd-masthead,\n ytd-masthead #background,\n ytd-masthead #container,\n ytd-masthead #contentContainer,\n ytd-masthead #end,\n ytd-masthead #start,\n ytd-masthead #center,\n ytd-masthead #frosted-glass,\n ytd-masthead #background-content,\n #frosted-glass,\n ytd-masthead tp-yt-app-header-layout,\n ytd-mini-guide-renderer,\n ytd-topbar-logo-renderer,\n ytd-app #masthead,\n ytd-app #masthead-container,\n tp-yt-app-header-layout #masthead-container {\n background-color: transparent !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n ", hideSideGuide: '\n /* Hide side guide */\n ytd-mini-guide-renderer, [theater=""] #contentContainer::after {display: none !important;}\n tp-yt-app-drawer > #contentContainer:not([opened=""]),\n #contentContainer:not([opened=""]) #guide-content,\n ytd-mini-guide-renderer,\n ytd-mini-guide-entry-renderer {background-color: var(--yt-spec-text-primary-inverse) !important; background: var(--yt-spec-text-primary-inverse) !important;}\n #content:not(:has(#contentContainer[opened=""])) #page-manager {margin-left: 0 !important;}\n ytd-app:not([guide-persistent-and-visible=""]) tp-yt-app-drawer > #contentContainer {background-color: var(--yt-spec-text-primary-inverse) !important;}\n ytd-alert-with-button-renderer {align-items: center !important; justify-content: center !important;}\n ', cleanSideGuide: '\n /* Clean side guide */\n ytd-guide-section-renderer:has([title="YouTube Premium"]),\n ytd-guide-renderer #footer {display: none !important;}\n ytd-guide-section-renderer, ytd-guide-collapsible-section-entry-renderer {border: none !important;}\n ', fixFeedLayout: "\n /* Fix new feed layout */\n @media only screen and (min-width: 1400px) {\n ytd-rich-item-renderer[rendered-from-rich-grid] { --ytd-rich-grid-items-per-row: 4 !important; }\n }\n @media only screen and (min-width: 1700px) {\n ytd-rich-item-renderer[rendered-from-rich-grid] { --ytd-rich-grid-items-per-row: 5 !important; }\n }\n @media only screen and (min-width: 2180px) {\n ytd-rich-item-renderer[rendered-from-rich-grid] { --ytd-rich-grid-items-per-row: 6 !important; }\n }\n ytd-rich-item-renderer[is-in-first-column] { margin-left: calc(var(--ytd-rich-grid-item-margin) / 2) !important; }\n #contents { padding-left: calc(var(--ytd-rich-grid-item-margin) / 2 + var(--ytd-rich-grid-gutter-margin)) !important; }\n ", betterCaptions: "\n /* Better captions */\n .caption-window { backdrop-filter: blur(10px) brightness(70%) !important; border-radius: 1em !important; padding: 1em !important; box-shadow: rgba(0,0,0,0.5) 0 0 20px !important; width: fit-content !important; }\n .ytp-caption-segment { background: none !important; }\n ", playerBlur: "\n /* Player controls blur */\n .ytp-left-controls .ytp-play-button,\n .ytp-left-controls .ytp-volume-area,\n .ytp-left-controls .ytp-time-display.notranslate > span,\n .ytp-left-controls .ytp-chapter-container > button,\n .ytp-left-controls .ytp-prev-button,\n .ytp-left-controls .ytp-next-button,\n .ytp-right-controls,\n .ytp-time-wrapper,\n .ytPlayerQuickActionButtonsHost,\n .ytPlayerQuickActionButtonsHostCompactControls,\n .ytPlayerQuickActionButtonsHostDisableBackdropFilter { backdrop-filter: blur(5px) !important; background-color: rgba(0,0,0,0.4) !important; }\n .ytp-popup { backdrop-filter: blur(10px) !important; background-color: rgba(0,0,0,0.45) !important; }\n ", theaterEnhancements: "\n /* Zen view comments (from zeninternet) */\n /* Hide secondary column visually but break containment so fixed children can escape */\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #columns #secondary { display: block !important;width: 0 !important;min-width: 0 !important;max-width: 0 !important;padding: 0 !important;margin: 0 !important;border: 0 !important;overflow: visible !important;pointer-events: none !important;flex: 0 0 0px !important;contain: none !important;\n }\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #secondary-inner { overflow: visible !important;contain: none !important;position: static !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #secondary-inner secondary-wrapper,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #secondary-inner .tabview-secondary-wrapper { contain: none !important;overflow: visible !important;position: static !important;max-height: none !important;height: auto !important;padding: 0 !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #right-tabs { display: block !important;overflow: visible !important;contain: none !important;position: static !important;width: 0 !important;height: 0 !important;padding: 0 !important;margin: 0 !important;border: 0 !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #right-tabs > header { display: none !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #right-tabs .tab-content { display: block !important;overflow: visible !important;contain: none !important;position: static !important;width: 0 !important;height: 0 !important;padding: 0 !important;margin: 0 !important;border: 0 !important;}\n /* Break containment on tab-comments so its fixed-position child can escape */\n /* Extra .tab-content-hidden selector to beat main.js specificity (line 5169) */\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments.tab-content-hidden,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments.tab-content-cld { contain: none !important;overflow: visible !important;position: static !important;display: block !important;visibility: visible !important;width: 0 !important;height: 0 !important;padding: 0 !important;margin: 0 !important;z-index: auto !important;pointer-events: none !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments.tab-content-hidden ytd-comments#comments > ytd-item-section-renderer#sections > #contents,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments.tab-content-hidden ytd-comments#comments #contents { contain: none !important;width: auto !important;height: auto !important;max-height: none !important;overflow: visible !important;visibility: visible !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-comments.tab-content-hidden ytd-comments#comments #contents > * { display: block !important;}\n /* Hide other tabs content */\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-info,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-videos,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #tab-list { display: none !important;}\n /* Comments overlay panel */\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) ytd-comments { visibility: visible !important;display: block !important;background-color: var(--yt-live-chat-shimmer-background-color) !important;backdrop-filter: blur(20px) !important;padding: 0 2em !important;border-radius: 2em 0 0 2em !important;max-height: calc(100vh - 120px) !important;overflow-y: auto !important;position: fixed !important;z-index: 2000 !important;top: 3vh !important;right: -42em !important;width: 40em !important;height: 90vh !important;opacity: 0 !important;pointer-events: auto !important;transition: opacity 0.4s ease, right 0.4s ease !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) ytd-comments:hover { opacity: 1 !important;right: 0 !important;}\n /* Transparent overlay chat — fixed panel */\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) [tyt-chat-container],\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat-container { contain: none !important;overflow: visible !important;position: static !important;display: block !important;pointer-events: none !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat { visibility: visible !important;display: block !important;position: fixed !important;top: 3vh !important;right: 0 !important;width: 400px !important;height: calc(100vh - 120px) !important;max-height: calc(100vh - 120px) !important;z-index: 2001 !important;opacity: 0.85 !important;pointer-events: auto !important;border-radius: 2em 0 0 2em !important;overflow: hidden !important;backdrop-filter: blur(20px) !important;transition: opacity 0.4s ease !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat[collapsed] { visibility: visible !important;display: block !important;position: fixed !important;top: 3vh !important;right: 0 !important;width: 400px !important;height: calc(100vh - 120px) !important;max-height: calc(100vh - 120px) !important;z-index: 2001 !important;opacity: 0.85 !important;pointer-events: auto !important;overflow: hidden !important;border-radius: 2em 0 0 2em !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat[collapsed] > #show-hide-button,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat[collapsed] > .ytd-live-chat-frame#show-hide-button { display: none !important;visibility: hidden !important;opacity: 0 !important;pointer-events: none !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat[collapsed] iframe { display: block !important;visibility: visible !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat iframe { height: 100% !important;width: 100% !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) yt-live-chat-renderer { background: transparent !important;}\n /* Ambient mode: fix black bars in theater */\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #cinematics-container,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #cinematics { position: absolute !important;top: 0 !important;left: 0 !important;width: 100% !important;height: 100% !important;overflow: hidden !important;pointer-events: none !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #cinematics canvas,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #cinematics video { position: absolute !important;top: 50% !important;left: 50% !important;transform: translate(-50%, -50%) scale(1.2) !important;min-width: 100% !important;min-height: 100% !important;object-fit: cover !important;}\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #player-full-bleed-container { overflow: hidden !important;}\n ytd-watch-flexy[fullscreen] ytd-live-chat-frame { background-color: var(--app-drawer-content-container-background-color) !important;}\n ", compactFeed: "\n /* Compact feed – reduced spacing, hover menus, inline details */\n ytd-rich-item-renderer { margin-bottom: 15px !important;}\n ytd-rich-item-renderer[rendered-from-rich-grid] { --ytd-rich-item-row-usable-width: calc(100% - var(--ytd-rich-grid-gutter-margin) * 1) !important;}\n ytd-rich-item-renderer #metadata.ytd-video-meta-block { flex-direction: row !important;}\n ytd-rich-item-renderer #metadata.ytd-video-meta-block #metadata-line span:nth-child(3) { height: 1em !important;margin-left: 1em !important;}\n ytd-rich-grid-media { border-radius: 1.2em;height: 100% !important;}\n ytd-rich-grid-media ytd-menu-renderer #button { opacity: 0 !important;transition: opacity 0.3s ease-in-out !important;}\n ytd-rich-grid-media:hover ytd-menu-renderer #button { opacity: 1 !important;}\n ", themeSolid: '\n html {\n --yt-glass-blur:none !important;\n --yt-glass-blur-light:none !important;\n --yt-glass-blur-heavy:none !important;\n }\n html[dark],html[data-ytp-theme="dark"] {\n --yt-glass-bg:rgba(24,24,24,.96) !important;\n --yt-panel-bg:rgba(30,30,30,.98) !important;\n --yt-header-bg:rgba(22,22,22,.98) !important;\n --yt-button-bg:rgba(42,42,42,.98) !important;\n --yt-input-bg:rgba(34,34,34,.98) !important;\n --yt-glass-shadow:0 10px 28px rgba(0,0,0,.28) !important;\n }\n html[light],html[data-ytp-theme="light"],html:not([dark]):not([data-ytp-theme="dark"]) {\n --yt-glass-bg:rgba(255,255,255,.98) !important;\n --yt-panel-bg:rgba(250,250,250,.99) !important;\n --yt-header-bg:rgba(245,245,245,.99) !important;\n --yt-button-bg:rgba(236,236,236,.98) !important;\n --yt-input-bg:rgba(245,245,245,.98) !important;\n --yt-glass-shadow:0 10px 24px rgba(0,0,0,.12) !important;\n }\n .ytp-plus-settings-panel,\n .ytp-plus-settings-sidebar,\n .top-button,\n .download-options.visible,\n .speed-options.visible,\n .glass-dropdown__list,\n .glass-panel,\n .glass-card,\n .ytp-plus-comments-sidepanel,\n .ytp-plus-comments-item,\n .youtube-enhancer-notification,\n .stats-modal-content,\n .settings-menu,\n #timecode-panel,\n #shorts-keyboard-feedback,\n .shortsStats,\n .ytp-popup,\n .ytPlayerQuickActionButtonsHost,\n .ytPlayerQuickActionButtonsHostCompactControls,\n .ytPlayerQuickActionButtonsHostDisableBackdropFilter,\n .caption-window,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) ytd-comments,\n ytd-watch-flexy:is([theater],[full-bleed-player]):not([fullscreen]) #chat {\n backdrop-filter:none !important;\n -webkit-backdrop-filter:none !important;\n }\n ', clsPrevention: "\n /* CLS Prevention - Reserve space for dynamic elements */\n #ytp-plus-dislike-text { min-width: 1.5em;display: inline-block !important;}\n /* Contain layout only for our own panels (not YouTube layout elements) */\n .ytp-plus-stats-panel, .ytp-plus-modal-content { contain: layout style;}\n /* Reduce CLS from late-loading channel avatars */\n #owner #avatar { min-width: 40px; min-height: 40px; }\n /* Reserve space for action buttons to prevent shift */\n ytd-menu-renderer.ytd-watch-metadata { min-height: 36px; }\n /* Subscribe button stability */\n ytd-subscribe-button-renderer { min-width: 90px; }\n " }, u = t => { const e = t?.zenStyles || {}; let o = d.clsPrevention; return "solid" === (e.themeVariant || "glass") && (o += d.themeSolid), e.hideSideGuide && (o += d.hideSideGuide), e.fixFeedLayout && (o += d.fixFeedLayout), e.theaterEnhancements && (o += d.theaterEnhancements), o.trim(); }, p = t => { const e = t?.zenStyles || {}, o = e.themeVariant || "glass"; let r = ""; e.thumbnailHover && (r += d.thumbnailHover), e.immersiveSearch && (r += d.immersiveSearch), e.hideVoiceSearch && (r += d.hideVoiceSearch), e.transparentHeader && (r += d.transparentHeader), e.cleanSideGuide && (r += d.cleanSideGuide); const i = Number(e.sideVideosColumns), a = Number.isFinite(i) ? Math.max(0, Math.min(2, i)) : 0; return !0 === e.sideVideosColumnsEnabled && a > 0 && (r += `#secondary #related{min-width:0 !important;overflow:visible !important;}#secondary{overflow:visible !important;}#secondary #related ytd-item-section-renderer.ytd-watch-next-secondary-results-renderer{width:${a >= 2 ? "200%" : "100%"}!important;}#secondary #related #contents,#secondary #related ytd-watch-next-secondary-results-renderer #items{display:grid !important;grid-template-columns:repeat(${a},minmax(0,1fr)) !important;gap:8px !important;padding:0 !important;align-items:start !important;}#secondary #related yt-lockup-view-model{width:100% !important;min-width:0 !important;max-width:100% !important;margin:0 !important;box-sizing:border-box !important;}#secondary #related .ytLockupViewModelHost{display:flex !important;flex-direction:column !important;align-items:stretch !important;width:100% !important;min-width:0 !important;gap:0 !important;flex-wrap:nowrap !important;}#secondary #related .ytLockupViewModelContentImage{width:100% !important;max-width:100% !important;min-width:0 !important;flex:0 0 auto !important;position:relative !important;}#secondary #related .ytThumbnailViewModelHost{width:100% !important;max-width:100% !important;}#secondary #related .ytThumbnailViewModelImage{width:100% !important;aspect-ratio:16 / 9 !important;}#secondary #related .ytThumbnailViewModelImage img{width:100% !important;height:100% !important;object-fit:cover !important;display:block !important;}#secondary #related .ytLockupViewModelMetadata{width:100% !important;min-width:0 !important;flex:1 1 auto !important;}#secondary #related yt-lockup-metadata-view-model{width:100% !important;}#secondary #related .ytLockupMetadataViewModelTextContainer{width:100% !important;min-width:0 !important;}#secondary #related .ytLockupMetadataViewModelHeadingReset{width:100% !important;min-width:0 !important;overflow:hidden !important;text-overflow:ellipsis !important;display:-webkit-box !important;-webkit-line-clamp:2 !important;-webkit-box-orient:vertical !important;}#secondary #related ytd-compact-video-renderer,#secondary #related ytd-compact-radio-renderer,#secondary #related ytd-compact-playlist-renderer{width:100% !important;min-width:0 !important;max-width:100% !important;margin:0 !important;box-sizing:border-box !important;}#secondary #related ytd-compact-video-renderer #dismissible,#secondary #related ytd-compact-radio-renderer #dismissible,#secondary #related ytd-compact-playlist-renderer #dismissible{display:flex !important;flex-direction:column !important;gap:6px !important;width:100% !important;}#secondary #related ytd-compact-video-renderer ytd-thumbnail,#secondary #related ytd-compact-radio-renderer ytd-thumbnail,#secondary #related ytd-compact-playlist-renderer ytd-thumbnail{width:100% !important;max-width:100% !important;min-width:0 !important;}#secondary #related ytd-compact-video-renderer .details,#secondary #related ytd-compact-video-renderer #meta{padding-left:0 !important;min-width:0 !important;width:100% !important;box-sizing:border-box !important;}`), e.betterCaptions && "solid" !== o && (r += d.betterCaptions), e.playerBlur && "solid" !== o && (r += d.playerBlur), e.compactFeed && (r += d.compactFeed), r.trim(); }, y = () => { try { U?.StyleManager?.remove && (U.StyleManager.remove(i), U.StyleManager.remove(a)); } catch (t) { U.logSuppressed(t, "Enhanced"); } if (s) { if ("undefined" != typeof window && "function" == typeof window.cancelIdleCallback) { try { window.cancelIdleCallback(s); } catch (t) { U.logSuppressed(t, "Enhanced"); } } else { clearTimeout(s); } s = null; } const t = byId(o); if (t) { try { t.remove(); } catch (t) { U.logSuppressed(t, "Enhanced"); } } const e = byId(r); if (e) { try { e.remove(); } catch (t) { U.logSuppressed(t, "Enhanced"); } } }, m = t => { try { const e = U?.StyleManager; if (e && "function" == typeof e.add) { e.add(a, t || ""); const o = byId(r); return void (o && o.remove()); } } catch (t) {} if (!t) { const t = byId(r); return void (t && t.remove()); } let e = byId(r); e || (e = document.createElement("style"), e.id = r, (document.head || document.documentElement).appendChild(e)), e.textContent = t; }, f = (t, e = !1) => { if (!1 === t?.enableZenStyles) { return void y(); } const r = u(t), a = p(t); if (!r && !a) { return void y(); } try { if (U?.StyleManager?.add) { U.StyleManager.add(i, r || ""); const t = byId(o); if (t && t.remove(), s) { if ("undefined" != typeof window && "function" == typeof window.cancelIdleCallback) { try { window.cancelIdleCallback(s); } catch (t) { U.logSuppressed(t, "Enhanced"); } } else { clearTimeout(s); } } return void (e ? (m(a), s = null) : s = "function" == typeof requestIdleCallback ? requestIdleCallback(() => m(a), { timeout: 5e3 }) : enhancedSetTimeout_(() => m(a), 200)); } } catch (t) { U.logSuppressed(t, "Enhanced"); } let c = byId(o); if (c || (c = document.createElement("style"), c.id = o, (document.head || document.documentElement).appendChild(c)), c.textContent = r || "", s) { if ("undefined" != typeof window && "function" == typeof window.cancelIdleCallback) { try { window.cancelIdleCallback(s); } catch (t) { U.logSuppressed(t, "Enhanced"); } } else { clearTimeout(s); } } e ? (m(a), s = null) : s = "function" == typeof requestIdleCallback ? requestIdleCallback(() => m(a), { timeout: 5e3 }) : enhancedSetTimeout_(() => m(a), 200); }, b = (t = !1) => f(l(), t); b(!0); try { const t = () => { const t = $("yt-searchbox"); t instanceof HTMLElement && (t.style.willChange = "transform"); }, e = () => { const t = $("yt-searchbox"); t instanceof HTMLElement && (t.style.willChange = ""); }, o = e => { e.target instanceof Element && e.target.closest("yt-searchbox") && t(); }, r = t => { t.target instanceof Element && t.target.closest("yt-searchbox") && e(); }; document.addEventListener("focusin", o, { passive: !0, capture: !0 }), document.addEventListener("focusout", r, { passive: !0, capture: !0 }), U?.cleanupManager?.register && U.cleanupManager.register(() => { document.removeEventListener("focusin", o, { capture: !0 }), document.removeEventListener("focusout", r, { capture: !0 }); }); } catch (t) { U.logSuppressed(t, "Enhanced"); } window.addEventListener("youtube-plus-settings-updated", t => { try { f(t?.detail || l(), !0); } catch (t) { b(!0); } }), window.addEventListener("yt-navigate-finish", () => { b(!0); }, { passive: !0 }); } catch (t) { enhancedLogger?.error?.("Enhanced", "zen-youtube-features injection failed", t); } })(), (function() { const t = "undefined" == typeof location ? "" : location.hostname; if (!t) { return; } if (!/(^|\.)youtube\.com$/.test(t) && !/\.youtube\.google/.test(t)) { return; } const e = U?.SETTINGS_KEY || "youtube_plus_settings", o = "data-ytp-zen-comments-preloaded", r = t => { if (t) { try { t.dispatchEvent(new window.MouseEvent("click", { bubbles: !0, cancelable: !0, view: window })); } catch (e) { try { t.click(); } catch (t) { U.logSuppressed(t, "Enhanced"); } } } }; let i = 0; const a = () => { if (!U?.isWatchPage?.()) { return; } if (!(() => { const t = (() => { try { const t = window.YouTubePlusSettingsStore; if (t && "function" == typeof t.load) { return t.load(); } const o = localStorage.getItem(e); if (!o) { return null; } const r = JSON.parse(o); return r && "object" == typeof r ? r : null; } catch (t) { return null; } })(); return !t || !1 !== t.enableZenStyles && (!t.zenStyles || !1 !== t.zenStyles.theaterEnhancements); })()) { return; } const t = $("ytd-watch-flexy"); t && !t.hasAttribute("fullscreen") && (t.hasAttribute("theater") || t.hasAttribute("full-bleed-player") || t.hasAttribute("theater-requested_")) && ((() => { const t = $("ytd-live-chat-frame#chat"); if (!t) { return; } if (t.hasAttribute("collapsed")) { if (i >= 3) { return; } i++; let e = !1; try { const o = t.polymerController || (void 0 !== t.ht ? t : null) || (t.inst ? t.inst : null); o && "function" == typeof o.setCollapsedState && (o.setCollapsedState({ setLiveChatCollapsedStateAction: { collapsed: !1 } }), e = !1 === o.collapsed), !e && o && "boolean" == typeof o.collapsed && (o.collapsed = !1, !0 === o.isHiddenByUser && (o.isHiddenByUser = !1), e = !1 === o.collapsed); } catch (t) { U.logSuppressed(t, "Enhanced"); } if (!e) { const e = t.querySelector("#show-hide-button div.yt-spec-touch-feedback-shape, #show-hide-button ytd-toggle-button-renderer, #show-hide-button button"); e && r(e); } } const e = t.querySelector("iframe#chatframe"); e && !e.src && t.url && (e.src = t.url); })(), (t => { const e = $("#tab-comments"), i = $('#material-tabs a[tyt-tab-content="#tab-comments"]'); if (!e || !i || "1" === e.getAttribute(o)) { return; } t && !t.hasAttribute("keep-comments-scroller") && t.setAttribute("keep-comments-scroller", ""); const a = $("#material-tabs a[tyt-tab-content].active"); r(i), requestAnimationFrame(() => { e.setAttribute(o, "1"), a && a !== i && a.isConnected && r(a); }); })(t)); }; let s = null; const c = () => { s && clearTimeout(s), s = enhancedSetTimeout_(a, 150); }, l = () => { const t = window.YouTubePlusMutationCoordinator; if (!t?.watchTarget) { return; } const e = "enhanced::overlayFlexy"; let o = null; const r = () => { const r = $("ytd-watch-flexy"); r && r !== o && (t.watchTarget(e, r, c, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "theater", "full-bleed-player", "theater-requested_", "fullscreen" ] }), o = r); }, a = "enhanced::overlayChat"; let s = null; const l = () => { const e = $("ytd-live-chat-frame#chat"); e && e !== s && (t.watchTarget(a, e, c, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "collapsed" ] }), s = e); }; r(), l(); const d = () => { i = 0, enhancedSetTimeout_(() => { r(), l(), c(); }, 180); }; U?.cleanupManager?.registerListener ? U.cleanupManager.registerListener(window, "yt-navigate-finish", d, { passive: !0 }) : window.addEventListener("yt-navigate-finish", d, { passive: !0 }); try { U?.cleanupManager?.register && U.cleanupManager.register(() => { t.unwatch(e), t.unwatch(a); }); } catch (t) { U.logSuppressed(t, "Enhanced"); } }; "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", () => { c(), l(); }, { once: !0 }) : (c(), l()); })(), (function() { const t = setTimeout.bind(window), e = window.YouTubeUtils, o = e.logger || null, r = (t, o = document) => e.$(t, o), i = [ ".ytp-ad-skip-button", ".ytp-ad-skip-button-modern", ".ytp-skip-ad-button", ".videoAdUiSkipButton", "button.ytp-ad-skip-button-modern", ".ytp-ad-skip-button-slot button", ".ytp-ad-skip-button-container button", ".ytp-ad-skip-button-modern .ytp-ad-skip-button-container", ".ytp-skip-ad-button__text", 'button[class*="skip"]', ".ytp-ad-skip-button-modern button", "ytd-button-renderer.ytp-ad-skip-button-renderer button" ].join(","), a = { config: { enableLogging: !1, maxRetries: 2, enabled: !0, storageKey: "youtube_adblocker_settings" }, state: { isYouTubeShorts: !1, isYouTubeMusic: "music.youtube.com" === location.hostname, lastSkipAttempt: 0, retryCount: 0, initialized: !1, moviePlayerSubId: null, adSlotSubId: null }, cache: { moviePlayer: null, ytdPlayer: null, lastCacheTime: 0, cacheTimeout: 1e4 }, selectors: { ads: ".ytp-ad-timed-pie-countdown-container,.ytp-ad-survey-questions,.ytp-ad-overlay-container,.ytp-ad-progress,.ytp-ad-progress-list", elements: "#masthead-ad,ytd-merch-shelf-renderer,.yt-mealbar-promo-renderer,ytmusic-mealbar-promo-renderer,ytmusic-statement-banner-renderer,.ytp-featured-product,ytd-in-feed-ad-layout-renderer,ytd-banner-promo-renderer,ytd-statement-banner-renderer,ytd-brand-video-singleton-renderer,ytd-brand-video-shelf-renderer,ytd-promoted-sparkles-web-renderer,ytd-display-ad-renderer,ytd-promoted-video-renderer,.ytd-mealbar-promo-renderer", video: "video.html5-main-video", removal: "ytd-reel-video-renderer .ytd-ad-slot-renderer, ytd-ad-slot-renderer, #player-ads, ytd-in-feed-ad-layout-renderer, ytd-display-ad-renderer, ytd-promoted-sparkles-web-renderer, ytd-promoted-video-renderer, ad-slot-renderer, ytd-player-legacy-desktop-watch-ads-renderer" }, wrappers: [ "ytd-rich-item-renderer", "ytd-grid-video-renderer", "ytd-compact-video-renderer", "ytd-rich-grid-media", "ytd-rich-shelf-renderer", "ytd-rich-grid-row", "ytd-video-renderer", "ytd-playlist-renderer", "ytd-reel-video-renderer" ], settings: { load() { try { const t = localStorage.getItem(a.config.storageKey); if (!t) { return; } const e = JSON.parse(t); if ("object" != typeof e || null === e) { return void o?.warn?.("AdBlocker", "Invalid settings format"); } a.config.enabled = "boolean" != typeof e.enabled || e.enabled, a.config.enableLogging = "boolean" == typeof e.enableLogging && e.enableLogging; } catch (t) { o?.error?.("AdBlocker", "Error loading settings", t), a.config.enabled = !0, a.config.enableLogging = !1; } }, save() { try { localStorage.setItem(a.config.storageKey, JSON.stringify({ enabled: a.config.enabled, enableLogging: a.config.enableLogging })); } catch (t) { o?.error?.("AdBlocker", "Error saving settings", t); } } }, getPlayer() { const t = Date.now(); t - a.cache.lastCacheTime > a.cache.cacheTimeout && (a.cache.moviePlayer = r("#movie_player"), a.cache.ytdPlayer = r("#ytd-player"), a.cache.lastCacheTime = t); const e = a.cache.ytdPlayer; return { element: a.cache.moviePlayer, player: e?.getPlayer?.() || e }; }, skipAd() { if (!a.config.enabled) { return; } const t = Date.now(); if (t - a.state.lastSkipAttempt < 300) { return; } if (a.state.lastSkipAttempt = t, location.pathname.startsWith("/shorts/")) { return; } const e = r("#movie_player"); if (e && (e.classList.contains("ad-showing") || e.classList.contains("ad-interrupting"))) { try { const t = document.querySelectorAll(i), e = Array.from(t, t => t.getBoundingClientRect()); for (let o = 0; o < t.length; o++) { if (e[o].width > 0 && e[o].height > 0) { return t[o].click(), void (a.state.retryCount = 0); } } const s = r(a.selectors.video); if (s && (s.muted = !0, s.duration && Number.isFinite(s.duration) && s.duration > 0)) { try { s.currentTime = Math.max(s.duration - .1, 0); } catch (t) { o?.warn?.("AdBlocker", "Ad seek error", t); } } const c = [ ".ytp-ad-overlay-close-button", ".ytp-ad-overlay-close-container button", ".ytp-ad-overlay-close-button button", ".ytp-ad-overlay-ad-info-button-container", 'button[id="dismiss-button"]' ]; for (const t of c) { const e = r(t); if (e) { e.click(); break; } } a.state.retryCount = 0; } catch (t) { a.state.retryCount < a.config.maxRetries && (a.state.retryCount++, setTimeout(a.skipAd, 800)); } } else { a.state.retryCount = 0; } }, dismissAdBlockerWarning() { if (a.config.enabled) { try { const t = document.querySelector("ytd-enforcement-message-view-model"); if (t) { const e = t.querySelectorAll("button, tp-yt-paper-button, a.yt-spec-button-shape-next--outline"); for (const t of e) { const e = (t.textContent || "").toLowerCase().trim(); if (e.includes("allow") || e.includes("dismiss") || e.includes("разрешить") || t.getAttribute("aria-label")?.includes("close")) { return void t.click(); } } return void t.remove(); } const e = document.querySelectorAll("tp-yt-paper-dialog, ytd-popup-container tp-yt-paper-dialog, yt-dialog-container"); for (const t of e) { const e = (t.textContent || "").toLowerCase(); if (!(e.includes("ad blocker") || e.includes("ad blockers") || e.includes("блокировщик") || e.includes("will be blocked") || e.includes("будет заблокирован") || e.includes("allow") && e.includes("ads") || e.includes("blocker") && e.includes("video"))) { continue; } const o = t.querySelectorAll('#dismiss-button button, .dismiss-button, button[id*="dismiss"], tp-yt-paper-button, yt-button-renderer button, a[href]'); for (const t of o) { const e = (t.textContent || "").toLowerCase(); if (e.includes("dismiss") || e.includes("allow") || e.includes("not using") || e.includes("report")) { return void t.click(); } } return t.style.display = "none", void t.remove(); } const o = document.querySelectorAll("tp-yt-iron-overlay-backdrop, .yt-dialog-overlay"); for (const t of o) { "none" !== t.style.display && null !== t.offsetParent && (t.style.display = "none"); } } catch (t) {} } }, addCss() { if (r("#yt-ab-styles") || !a.config.enabled) { return; } const t = `${a.selectors.ads}{display:none!important;}`, e = YouTubeUtils?.StyleManager; e && "function" == typeof e.add && e.add("yt-ab-styles", t); }, removeCss() { const t = YouTubeUtils?.StyleManager; t && "function" == typeof t.remove && t.remove("yt-ab-styles"); }, removeElements() { if (!a.config.enabled || a.state.isYouTubeMusic) { return; } const t = () => { try { document.querySelectorAll(a.selectors.elements).forEach(t => { try { t.remove(); } catch (t) { e.logSuppressed(t, "AdBlocker"); } }); } catch (t) { e.logSuppressed(t, "AdBlocker"); } document.querySelectorAll(a.selectors.removal).forEach(t => { try { for (const e of a.wrappers) { const o = t.closest(e); if (o) { return void o.remove(); } } const e = t.closest("ytd-reel-video-renderer"); if (e) { return void e.remove(); } const o = t.closest("ytd-ad-slot-renderer") || t.closest(".ad-container") || t; o?.remove && o.remove(); } catch (t) { a.config.enableLogging && o?.warn?.("AdBlocker", "removeElements error", t); } }); }, r = window.requestIdleCallback; "function" == typeof r ? r(t, { timeout: 100 }) : setTimeout(t, 0); }, attachSettingsHandler() { try { const t = document.getElementById("ytp-plus-setting-enableAdBlocker"); if (!(t instanceof HTMLInputElement)) { return; } if (t.dataset.handlerAttached) { return; } t.dataset.handlerAttached = "true", t.checked = a.config.enabled, t.addEventListener("change", t => { a.config.enabled = t.target.checked, a.settings.save(), a.config.enabled ? a.addCss() : a.removeCss(); }); } catch (t) {} }, init() { if (a.state.initialized) { return; } a.state.initialized = !0, a.settings.load(), a.config.enabled && (a.addCss(), a.removeElements()); let e = null, i = 0; const s = () => { const t = (() => { const t = Date.now(); return (!e || t - i > 5e3) && (e = r("#movie_player"), i = t), e; })(); return t && (t.classList.contains("ad-showing") || t.classList.contains("ad-interrupting")); }, c = () => { a.config.enabled && s() && (a.skipAd(), a.dismissAdBlockerWarning()); }; try { const e = () => { const o = window.YouTubePlusMutationCoordinator; if (!o?.watchTarget) { return; } const i = r("#movie_player"); i ? (a.state.moviePlayerSubId && o.unwatch(a.state.moviePlayerSubId), a.state.moviePlayerSubId = "adblocker::moviePlayerClass", o.watchTarget(a.state.moviePlayerSubId, i, () => { a.config.enabled && s() && (a.skipAd(), a.dismissAdBlockerWarning()); }, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "class" ] }), YouTubeUtils.cleanupManager?.register && YouTubeUtils.cleanupManager.register(() => { a.state.moviePlayerSubId && (o.unwatch(a.state.moviePlayerSubId), a.state.moviePlayerSubId = null); })) : t(e, 1500); }; e(); } catch (t) { o?.warn?.("AdBlocker", "Ad observer setup error", t); } try { const t = () => { a.config.enabled && setTimeout(c, 100); }; YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "playing", t, { capture: !0, passive: !0 }) : document.addEventListener("playing", t, { capture: !0, passive: !0 }); } catch (t) { o?.warn?.("AdBlocker", "Ad play listener error", t); } const l = () => { a.state.isYouTubeShorts = location.pathname.startsWith("/shorts/"), a.cache.lastCacheTime = 0, a.config.enabled && a.removeElements(); }, d = () => setTimeout(l, 50); YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(window, "ytp-history-navigate", d) : window.addEventListener("ytp-history-navigate", d); const u = () => { setTimeout(a.attachSettingsHandler, 50); }; YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", u) : document.addEventListener("youtube-plus-settings-modal-opened", u); try { const t = window.YouTubePlusMutationCoordinator; t?.subscribeRoot && (a.state.adSlotSubId && t.unsubscribe(a.state.adSlotSubId), a.state.adSlotSubId = "adblocker::adSlots", t.subscribeRoot(a.state.adSlotSubId, () => { a.removeElements(); }, { selector: "ytd-ad-slot-renderer, ytd-merch-shelf-renderer, #player-ads, ad-slot-renderer", childList: !0, attributes: !1, subtree: !0 }), YouTubeUtils.cleanupManager?.register && YouTubeUtils.cleanupManager.register(() => { a.state.adSlotSubId && (t.unsubscribe(a.state.adSlotSubId), a.state.adSlotSubId = null); })); } catch (t) { a.config.enableLogging && o?.warn?.("AdBlocker", "Failed to create adSlotObserver", t); } a.config.enabled && (setTimeout(a.skipAd, 200), setTimeout(a.dismissAdBlockerWarning, 500)); } }; "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", a.init, { once: !0 }) : a.init(); })(), (function() { const t = window.YouTubeUtils, {logger: e, $: o, byId: r, setTimeout_: i} = t?.helpers ?? {}, a = { enabled: !0, shortcut: { key: "P", shiftKey: !0, altKey: !1, ctrlKey: !1 }, storageKey: "youtube_pip_settings" }, s = "youtube_plus_pip_session", c = "__ytplusFirefoxPipBridgeInstalled", l = "__ytplusFirefoxPipKeydownBridge", d = "__ytplusPipShortcut", u = () => { try { if ("undefined" != typeof unsafeWindow) { const t = unsafeWindow?.wrappedJSObject; return t && "object" == typeof t ? t : unsafeWindow; } } catch (e) { t.logSuppressed(e, "Pip"); } return window; }, p = window.YouTubeSafeDOM?.createTrustedScript || (e => { const o = "string" == typeof e ? e : String(e ?? ""); try { const t = window.YouTubeTrustedTypes && "function" == typeof window.YouTubeTrustedTypes.getPolicy && window.YouTubeTrustedTypes.getPolicy() || window.YouTubeTrustedTypes?.policy || null; if (t && "function" == typeof t.createScript) { return t.createScript(o); } } catch (e) { t.logSuppressed(e, "Pip"); } return o; }); let y = null, m = 0; const f = () => { try { const t = Date.now(); if (y && t - m < 2e3) { const t = y.deref?.(); if (t?.isConnected) { return t; } y = null; } const e = u(), r = e?.document?.querySelector?.("video.html5-main-video, #movie_player video, video") || "function" == typeof YouTubeUtils?.querySelector && YouTubeUtils.querySelector("video") || o("video"); if (r?.tagName && "video" === r.tagName.toLowerCase()) { const e = r; try { y = new WeakRef(e), m = t; } catch (t) {} return e; } return null; } catch (t) { return e?.error?.("PiP", "Error getting video element", t), null; } }, b = async t => { if ("function" == typeof t.requestPictureInPicture) { return t.requestPictureInPicture(); } const e = u(), o = e?.document?.querySelector?.("video.html5-main-video, #movie_player video, video"), r = e?.HTMLVideoElement?.prototype; if (o && "function" == typeof o.requestPictureInPicture) { return o.requestPictureInPicture(); } if (o && r && "function" == typeof r.requestPictureInPicture) { return r.requestPictureInPicture.call(o); } const i = e?.document?.getElementById?.("movie_player") || e?.document?.querySelector?.("#movie_player"); if (i && "function" == typeof i.togglePictureInPicture) { return i.togglePictureInPicture(); } if (i && "function" == typeof i.requestPictureInPicture) { return i.requestPictureInPicture(); } throw new Error("requestPictureInPicture is not available on video element"); }, h = () => { const t = u(); if (!t || t[c]) { return !0; } const r = `(() => {\n if (window['${c}']) return;\n window['${c}'] = true;\n\n const selectVideo = () =>\n document['querySelector']('video.html5-main-video, #movie_player video, video');\n\n const clickNativePipButton = () => {\n const selectors = [\n 'button.ytp-pip-button',\n '.ytp-right-controls .ytp-pip-button',\n '.ytp-right-controls button[aria-keyshortcuts="i"]'\n ];\n for (const selector of selectors) {\n const button = document['querySelector'](selector);\n if (!(button instanceof HTMLElement)) continue;\n const disabled =\n button.getAttribute('aria-disabled') === 'true' ||\n button.hasAttribute('disabled') ||\n button.classList.contains('ytp-button-disabled');\n if (disabled) continue;\n button.click();\n return true;\n }\n return false;\n };\n\n const safeTargetOrigin =\n typeof location !== 'undefined' && typeof location.origin === 'string' && location.origin\n ? location.origin\n : '*';\n\n window.addEventListener('message', event => {\n if (event.source !== window) return;\n // Allow same-origin page messages and Firefox/userscript sandbox-origin messages.\n // In some Firefox userscript contexts event.origin may be "null".\n const msgOrigin = String(event.origin || '');\n if (msgOrigin && msgOrigin !== 'null' && msgOrigin !== location.origin) return;\n if (event.data?.type !== 'ytp-pip-request' || typeof event.data?.id !== 'string') return;\n if (event.data.id.length > 80) return;\n\n const respond = success => {\n window.postMessage({ type: 'ytp-pip-response', id: event.data.id, success }, safeTargetOrigin);\n };\n\n Promise.resolve()\n .then(async () => {\n const video = selectVideo();\n if (document.pictureInPictureElement && typeof document.exitPictureInPicture === 'function') {\n await document.exitPictureInPicture();\n return true;\n }\n if (video && typeof video.requestPictureInPicture === 'function') {\n await video.requestPictureInPicture();\n return true;\n }\n return clickNativePipButton();\n })\n .then(success => respond(Boolean(success)))\n .catch(() => respond(false));\n }, true);\n})();\n//# sourceURL=debug://youtube-plus/pip-firefox-bridge.js`; try { const t = globalThis.GM_addElement; if ("function" == typeof t) { return t("script", { textContent: String(r) }), !0; } } catch (t) {} try { const e = o("script[nonce]") || o("[nonce]") || document.documentElement, i = e?.nonce || e?.getAttribute?.("nonce") || document.documentElement?.getAttribute?.("nonce") || ""; if (i) { const e = document.createElement("script"); if (e.setAttribute("nonce", i), e.textContent = p(r), (document.head || document.documentElement).appendChild(e), e.remove(), t[c]) { return !0; } } } catch (t) {} return e?.warn?.("PiP", "Firefox PiP bridge could not be installed (CSP). Using button fallback."), !1; }, g = () => { try { const t = u(); t && (t[d] = { key: a.shortcut.key, shiftKey: a.shortcut.shiftKey, altKey: a.shortcut.altKey, ctrlKey: a.shortcut.ctrlKey, enabled: a.enabled }); } catch (e) { t.logSuppressed(e, "Pip"); } }, w = () => new Promise(t => { try { if (!h()) { return void t(!1); } const e = `ytp-pip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; let o = !1; const r = e => { o || (o = !0, window.removeEventListener("message", a, !0), t(Boolean(e))); }, a = t => { if (t.source !== window) { return; } const o = String(t.origin || ""); o && "null" !== o && o !== location.origin || "ytp-pip-response" === t.data?.type && t.data?.id === e && r(Boolean(t.data?.success)); }; window.addEventListener("message", a, !0); const s = "undefined" != typeof location && "string" == typeof location.origin && location.origin ? location.origin : "*"; window.postMessage({ type: "ytp-pip-request", id: e }, s), i(function() { r(!1); }, 1200); } catch (e) { t(!1); } }), v = () => { const e = [ "button.ytp-pip-button", ".ytp-right-controls .ytp-pip-button", '.ytp-right-controls button[aria-keyshortcuts="i"]' ], o = []; try { o.push(document), "undefined" != typeof unsafeWindow && unsafeWindow?.document && o.push(unsafeWindow.document); } catch (e) { t.logSuppressed(e, "Pip"); } (() => { const e = r("movie_player"); if (!(e instanceof HTMLElement)) { return; } const o = e.getBoundingClientRect(), i = Math.round(o.left + o.width - 32), a = Math.round(o.top + o.height - 32); [ "mousemove", "mouseover", "mouseenter" ].forEach(o => { try { e.dispatchEvent(new MouseEvent(o, { bubbles: !0, cancelable: !0, view: window, clientX: i, clientY: a })); } catch (e) { t.logSuppressed(e, "Pip"); } }); })(); for (const t of o) { for (const o of e) { const e = t.querySelector(o); if (e instanceof HTMLElement) { if ("true" === e.getAttribute("aria-disabled") || e.hasAttribute("disabled") || e.classList.contains("ytp-button-disabled")) { continue; } return e.click(), !0; } } } return !1; }, x = e => { try { e ? sessionStorage.setItem(s, "true") : sessionStorage.removeItem(s); } catch (e) { t.logSuppressed(e, "Pip"); } }, k = () => { try { const t = localStorage.getItem(a.storageKey); if (!t) { return; } const o = JSON.parse(t); if ("object" != typeof o || null === o) { return void e?.warn?.("PiP", "Invalid settings format"); } "boolean" == typeof o.enabled && (a.enabled = o.enabled), o.shortcut && "object" == typeof o.shortcut && ("string" == typeof o.shortcut.key && o.shortcut.key.length > 0 && (a.shortcut.key = o.shortcut.key), "boolean" == typeof o.shortcut.shiftKey && (a.shortcut.shiftKey = o.shortcut.shiftKey), "boolean" == typeof o.shortcut.altKey && (a.shortcut.altKey = o.shortcut.altKey), "boolean" == typeof o.shortcut.ctrlKey && (a.shortcut.ctrlKey = o.shortcut.ctrlKey)); } catch (t) { e?.error?.("PiP", "Error loading settings", t); } }, S = () => { try { localStorage.setItem(a.storageKey, JSON.stringify({ enabled: a.enabled, shortcut: a.shortcut })); } catch (t) { e?.error?.("PiP", "Error saving settings", t); } g(); }, T = () => { const t = document.pictureInPictureElement; if (t && "object" == typeof t && "tagName" in t) { const e = t.tagName; if ("string" == typeof e && "video" === e.toLowerCase()) { return t; } } if (/firefox/i.test(navigator.userAgent || "")) { try { const t = u(), e = t?.document || document, o = e.querySelector("video[__pip]") || e.querySelector("video._pip"); if (o && "video" === o.tagName?.toLowerCase()) { return o; } } catch {} } return null; }, L = async t => { if (a.enabled && t) { try { if (/firefox/i.test(navigator.userAgent || "")) { if (h(), "function" == typeof document.exitPictureInPicture && document.pictureInPictureElement) { try { return await document.exitPictureInPicture(), void x(!1); } catch {} } if (v()) { return void x(!0); } try { const t = u(), e = t?.document?.querySelector?.("video.html5-main-video, #movie_player video, video"); if (e && "function" == typeof e.requestPictureInPicture) { return await e.requestPictureInPicture(), void x(!0); } const o = t?.HTMLVideoElement?.prototype; if (e && o && "function" == typeof o.requestPictureInPicture) { return await o.requestPictureInPicture.call(e), void x(!0); } } catch {} try { if (await w()) { return void x(!0); } const t = u(); if (t) { const e = t.document?.querySelector?.("video"); e && "function" == typeof e.requestPictureInPicture && (e.requestPictureInPicture().catch(() => {}), x(!0)); } } catch (t) { e?.warn?.("PiP", "All Firefox PiP fallbacks exhausted"); } return; } const o = T(); if (o && o !== t && ("function" == typeof document.exitPictureInPicture && await document.exitPictureInPicture(), x(!1)), T() === t) { return "function" == typeof document.exitPictureInPicture && await document.exitPictureInPicture(), void x(!1); } const r = !0 === t.disablePictureInPicture; if (r) { try { t.disablePictureInPicture = !1; } catch {} } try { await b(t); } catch (e) { await (t => new Promise(e => { if (!t || t.readyState >= 1) { return void e(); } let o = !1; const r = () => { o || (o = !0, t.removeEventListener("loadedmetadata", r), e()); }; t.addEventListener("loadedmetadata", r, { once: !0 }), setTimeout(r, 700); }))(t); try { await b(t); } catch (t) { if (!v()) { throw new Error("requestPictureInPicture is not available on video element"); } } } if (r) { try { t.disablePictureInPicture = !0; } catch {} } x(!0); } catch (t) { e?.error?.("PiP", "Failed to toggle Picture-in-Picture", t); } } }, M = () => { const e = o('.ytp-plus-settings-section[data-section="advanced"]'); if (!e) { return; } const i = e.querySelector(".pip-settings-item"); if (!i || i.dataset.handlerAttached) { return; } i.dataset.handlerAttached = "1", (() => { if (r("pip-styles")) { return; } const t = window.YouTubePlusDesignSystem?.getStyle?.("pip-styles") || ""; YouTubeUtils.StyleManager.add("pip-styles", t); })(); const s = o('.pip-submenu[data-submenu="pip"]'); window.YouTubePlusDesignSystem?.initGlassDropdown?.({ dropdown: r("pip-modifier-dropdown"), hiddenSelect: r("pip-modifier-combo") }); const c = r("pip-enable-checkbox"); c instanceof HTMLInputElement && c.addEventListener("change", e => { a.enabled = e.target.checked; const o = i.querySelector('.ytp-plus-submenu-toggle[data-submenu="pip"]'); if (o instanceof HTMLElement) { if (a.enabled) { const e = (() => { try { const t = localStorage.getItem("ytp-plus-submenu-states"); if (!t) { return null; } const e = JSON.parse(t); if (e && "boolean" == typeof e.pip) { return e.pip; } } catch (e) { t.logSuppressed(e, "Pip"); } return null; })(), r = "boolean" != typeof e || e; o.removeAttribute("disabled"), o.classList.remove("pip-submenu-toggle-hidden"), o.setAttribute("aria-expanded", r ? "true" : "false"), s instanceof HTMLElement && s.classList.toggle("is-hidden", !r); } else { o.setAttribute("disabled", ""), o.classList.add("pip-submenu-toggle-hidden"), s instanceof HTMLElement && s.classList.add("is-hidden"); } } S(); }); const l = r("pip-modifier-combo"); l instanceof HTMLSelectElement && l.addEventListener("change", t => { const e = t.target.value; a.shortcut.ctrlKey = e.includes("ctrl"), a.shortcut.altKey = e.includes("alt"), a.shortcut.shiftKey = e.includes("shift"), S(); }); const d = r("pip-key"); d instanceof HTMLInputElement && (d.addEventListener("input", t => { const e = t.target; e.value && (a.shortcut.key = e.value.toUpperCase(), S()); }), d.addEventListener("keydown", t => t.stopPropagation())); }; let C = !1; const E = () => { if (C) { return; } C = !0, k(); let r = 0; const i = o => { const i = o; if (!i || "object" != typeof i || "string" != typeof i.key || "string" != typeof i.code) { return; } if (!a.enabled) { return; } if (i.repeat || i.isComposing) { return; } if (i.metaKey) { return; } if ((t => { const e = t; if (!e || "object" != typeof e) { return !1; } const o = String(e.tagName || "").toUpperCase(); return !0 === e.isContentEditable || "INPUT" === o || "TEXTAREA" === o || "SELECT" === o || "function" == typeof e.closest && !!e.closest('input, textarea, select, [contenteditable="true"]'); })(i.target)) { return; } const {shiftKey: s, altKey: c, ctrlKey: d, key: p} = a.shortcut, y = (t => { const e = String(t || "").trim().toUpperCase(); if (!e) { return ""; } const o = { "`": "Backquote", "~": "Backquote", "-": "Minus", _: "Minus", "=": "Equal", "+": "Equal", "[": "BracketLeft", "{": "BracketLeft", "]": "BracketRight", "}": "BracketRight", "\\": "Backslash", "|": "Backslash", ";": "Semicolon", ":": "Semicolon", "'": "Quote", '"': "Quote", ",": "Comma", "<": "Comma", ".": "Period", ">": "Period", "/": "Slash", "?": "Slash" }; return Object.hasOwn(o, e) ? o[e] : 1 === e.length && /[A-Z]/.test(e) ? `Key${e}` : 1 === e.length && /[0-9]/.test(e) ? `Digit${e}` : e; })(p), m = String(i.code || ""), h = String(i.key || "").toUpperCase() === p.toUpperCase() || y && m === y; if (i.shiftKey === s && i.altKey === c && i.ctrlKey === d && h) { const s = Date.now(); if (s - r < 250) { return void o.preventDefault(); } r = s; const c = /firefox/i.test(navigator.userAgent || ""); if (c) { const e = u(), o = Boolean(e?.[l]); if (s - Number(e?.wt || 0) < 300) { return; } const r = ((e, o) => { if (T() && "function" == typeof document.exitPictureInPicture) { return document.exitPictureInPicture(), x(!1), !0; } const r = f(); if (!r) { return v() ? (x(!0), e.preventDefault(), e.stopPropagation(), "function" == typeof e.stopImmediatePropagation && e.stopImmediatePropagation(), !0) : (w().then(t => { t && x(!0); }), !o && (e.preventDefault(), e.stopPropagation(), "function" == typeof e.stopImmediatePropagation && e.stopImmediatePropagation(), !0)); } try { !0 === r.disablePictureInPicture && (r.disablePictureInPicture = !1); } catch (e) { t.logSuppressed(e, "Pip"); } let i = !1; return v() && (x(!0), i = !0), i || (w().then(t => { t ? x(!0) : b(r).then(() => x(!0)).catch(() => { v() && x(!0); }); }), i = !o), i || document.pictureInPictureElement || setTimeout(() => { if (!document.pictureInPictureElement) { if (v()) { return void x(!0); } w().then(t => { t && x(!0); }); } }, 70), i || o || (L(r), i = !0), !!i && (e.preventDefault(), e.stopPropagation(), "function" == typeof e.stopImmediatePropagation && e.stopImmediatePropagation(), !0); })(i, !o && (() => { const t = a.shortcut, e = String(t.key || "").trim(); return !0 === t.ctrlKey && !0 === t.shiftKey && !1 === t.altKey && "]" === e; })()); if (!r) { return; } } else { const t = f(); t ? L(t) : v() || e?.warn?.("PiP", "Picture-in-Picture API is unavailable in this browser/context"); } c || document.pictureInPictureElement || f() || e?.warn?.("PiP", "Picture-in-Picture API is unavailable in this browser/context"), o.stopPropagation(), "function" == typeof o.stopImmediatePropagation && o.stopImmediatePropagation(), o.preventDefault(); } }; YouTubeUtils.cleanupManager.registerListener(document, "keydown", i, { capture: !0 }), YouTubeUtils.cleanupManager.registerListener(window, "keydown", i, { capture: !0 }), /firefox/i.test(navigator.userAgent || "") && (() => { const t = u(); if (!t) { return !1; } if (t[l]) { return !0; } g(); const e = `(() => {\n if (window['${l}']) return;\n window['${l}'] = true;\n\n const selectVideo = () =>\n document['querySelector']('video.html5-main-video, #movie_player video, video');\n\n const clickPipBtn = () => {\n const sels = ['button.ytp-pip-button', '.ytp-right-controls .ytp-pip-button',\n '.ytp-right-controls button[aria-keyshortcuts="i"]'];\n for (const sel of sels) {\n const btn = document['querySelector'](sel);\n if (!(btn instanceof HTMLElement)) continue;\n if (btn.getAttribute('aria-disabled') === 'true' || btn.hasAttribute('disabled') ||\n btn.classList.contains('ytp-button-disabled')) continue;\n btn.click();\n return true;\n }\n return false;\n };\n\n const getShortcut = () => window['${d}'] || { key: 'P', shiftKey: true, altKey: false, ctrlKey: false, enabled: true };\n const keyToCode = key => {\n const normalized = String(key || '').trim().toUpperCase();\n if (!normalized) return '';\n const symbolCodeMap = {\n '-': 'Minus',\n _: 'Minus',\n '=': 'Equal',\n '+': 'Equal',\n '[': 'BracketLeft',\n '{': 'BracketLeft',\n ']': 'BracketRight',\n '}': 'BracketRight',\n ';': 'Semicolon',\n ':': 'Semicolon',\n "'": 'Quote',\n '"': 'Quote',\n ',': 'Comma',\n '<': 'Comma',\n '.': 'Period',\n '>': 'Period',\n '/': 'Slash',\n '?': 'Slash'\n };\n if (Object.prototype.hasOwnProperty.call(symbolCodeMap, normalized)) {\n return symbolCodeMap[normalized];\n }\n if (normalized.length === 1 && /[A-Z]/.test(normalized)) return 'Key' + normalized;\n if (normalized.length === 1 && /[0-9]/.test(normalized)) return 'Digit' + normalized;\n return normalized;\n };\n\n const handlePiPHotkey = function ytplusPipKeydown(e) {\n const s = getShortcut();\n if (!s || !s.enabled) return;\n if (e.repeat || e.isComposing || e.metaKey) return;\n const expectedCode = keyToCode(String(s.key || ''));\n const eventCode = String(e.code || '');\n const eventKey = String(e.key || '').toUpperCase();\n const keyMatches =\n eventKey === String(s.key || '').toUpperCase() || (expectedCode && eventCode === expectedCode);\n const modsMatch = !!e.shiftKey === !!s.shiftKey && !!e.altKey === !!s.altKey && !!e.ctrlKey === !!s.ctrlKey;\n if (!keyMatches || !modsMatch) return;\n\n // Check active element is not a text input\n const ae = document.activeElement;\n if (ae && (ae.tagName === 'INPUT' || ae.tagName === 'TEXTAREA' ||\n ae.tagName === 'SELECT' || ae.isContentEditable)) return;\n\n e.preventDefault();\n e.stopPropagation();\n if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation();\n\n // Signal the userscript handler to not double-toggle\n window['__ytplusPipPageHandled'] = Date.now();\n\n if (document.pictureInPictureElement) {\n document.exitPictureInPicture && document.exitPictureInPicture();\n return;\n }\n\n const video = selectVideo();\n if (video && typeof video.requestPictureInPicture === 'function') {\n video.requestPictureInPicture().catch(() => clickPipBtn());\n return;\n }\n clickPipBtn();\n };\n\n document.addEventListener('keydown', handlePiPHotkey, true);\n window.addEventListener('keydown', handlePiPHotkey, true);\n})();`, r = globalThis.GM_addElement; if ("function" == typeof r) { try { if (r("script", { textContent: String(e) }), t[l]) { return !0; } } catch (t) {} } try { const r = o("script[nonce]") || o("[nonce]") || document.documentElement, i = r?.nonce || r?.getAttribute?.("nonce") || document.documentElement?.getAttribute?.("nonce") || "", a = document.createElement("script"); if (i && a.setAttribute("nonce", i), a.textContent = p(e), (document.head || document.documentElement).appendChild(a), a.remove(), t[l]) { return !0; } } catch (t) {} })(); try { const t = u(), e = t?.document, o = t; e && e !== document && e.addEventListener && e.addEventListener("keydown", i, { capture: !0 }), o && o !== window && o.addEventListener && o.addEventListener("keydown", i, { capture: !0 }); } catch (t) { e?.warn?.("PiP", "Could not register page-context keydown listener (Firefox sandbox)"); } YouTubeUtils.cleanupManager.registerListener(window, "storage", t => { t instanceof StorageEvent && t.key === a.storageKey && k(); }), window.addEventListener("load", () => { if (!a.enabled || !(() => { try { return "true" === sessionStorage.getItem(s); } catch (t) { return !1; } })() || document.pictureInPictureElement) { return; } const e = () => { const t = f(); t && L(t).catch(() => { x(!1); }); }, o = e => { if (e) { try { document.removeEventListener("pointerdown", e, !0); } catch (e) { t.logSuppressed(e, "Pip"); } } }, r = () => { o(i), o(c); }, i = () => { r(), e(); }, c = () => { r(), e(); }; document.addEventListener("pointerdown", i, { once: !0, capture: !0 }), document.addEventListener("keydown", c, { once: !0, capture: !0 }); }); const c = () => { M(); }; YouTubeUtils.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", () => { setTimeout(c, 50); }), YouTubeUtils.cleanupManager.registerListener(document, "leavepictureinpicture", () => { x(!1); }), YouTubeUtils.cleanupManager.registerListener(document, "click", t => { if (!(t instanceof MouseEvent)) { return; } const e = t.target.closest(".ytp-plus-settings-nav-item"); "advanced" === e?.dataset?.section && setTimeout(c, 25); }, !0); }; document.addEventListener("youtube-plus-settings-modal-opened", () => { setTimeout(() => { M(); }, 50); }), window.YouTubeUtils?.whenRelevant ? window.YouTubeUtils.whenRelevant({ name: "pip.runtime", isRelevant: () => "object" == typeof window.location && /^\/watch/.test(window.location.pathname), onEnter: E }) : "object" == typeof window.location && /^\/watch/.test(window.location.pathname) && E(), window.YouTubeUtils?.onSectionActive && window.YouTubeUtils.onSectionActive("advanced", () => { try { setTimeout(() => { M(); }, 25); } catch (t) {} }); })(), (function() { const t = window.YouTubeUtils, {$: e, $$: o, byId: r, setTimeout_: i} = t?.helpers ?? {}, a = t?.throttle, s = t?.waitForElement; if (window._timecodeModuleInitialized) { return; } window._timecodeModuleInitialized = !0; const c = window.YouTubeUtils?.t || (t => t || ""), l = window.YouTubeUtils?.logger || null, d = { enabled: !0, autoDetect: !0, shortcut: { key: "T", shiftKey: !0, altKey: !1, ctrlKey: !1 }, storageKey: "youtube_timecode_settings", autoSave: !0, autoTrackPlayback: !0, panelPosition: null, export: !0 }, u = { timecodes: new Map, dom: {}, isReloading: !1, activeIndex: null, trackingId: 0, dragging: !1, editingIndex: null, resizeListenerKey: null, settingsIntegrationStarted: !1 }; let p = !1; const y = () => window.YouTubeUtils.isWatchRoute(), m = t => { const e = String(t || ""); let o = 0; const r = () => { const t = o; for (;o < e.length && e[o] >= "0" && e[o] <= "9"; ) { o += 1; } return o > t ? e.slice(t, o) : ""; }, i = r(); if (!i || o >= e.length || ":" !== e[o]) { return null; } o += 1; const a = r(); if (2 !== a.length) { return null; } if (o < e.length && ":" === e[o]) { o += 1; const t = r(); return 2 !== t.length ? null : { token: `${i}:${a}:${t}`, length: o }; } return { token: `${i}:${a}`, length: o }; }, f = t => { const e = String(t || "").trimStart(), o = m(e); if (!o) { return e; } let r = e.slice(o.length).trimStart(); return (r.startsWith("-") || r.startsWith("–") || r.startsWith("—") || r.startsWith(":")) && (r = r.slice(1).trimStart()), r; }, b = () => { try { const t = localStorage.getItem(d.storageKey); if (!t) { return; } const e = JSON.parse(t); if ("object" != typeof e || null === e) { return void l?.warn?.("Timecode", "Invalid settings format"); } if ("boolean" == typeof e.enabled && (d.enabled = e.enabled), "boolean" == typeof e.autoDetect && (d.autoDetect = e.autoDetect), "boolean" == typeof e.autoSave && (d.autoSave = e.autoSave), "boolean" == typeof e.autoTrackPlayback && (d.autoTrackPlayback = e.autoTrackPlayback), "boolean" == typeof e.export && (d.export = e.export), e.shortcut && "object" == typeof e.shortcut && ("string" == typeof e.shortcut.key && (d.shortcut.key = e.shortcut.key), "boolean" == typeof e.shortcut.shiftKey && (d.shortcut.shiftKey = e.shortcut.shiftKey), "boolean" == typeof e.shortcut.altKey && (d.shortcut.altKey = e.shortcut.altKey), "boolean" == typeof e.shortcut.ctrlKey && (d.shortcut.ctrlKey = e.shortcut.ctrlKey)), e.panelPosition && "object" == typeof e.panelPosition) { const {left: t, top: o} = e.panelPosition; "number" == typeof t && "number" == typeof o && !Number.isNaN(t) && !Number.isNaN(o) && t >= 0 && o >= 0 && (d.panelPosition = { left: t, top: o }); } } catch (t) { l?.error?.("Timecode", "Error loading settings", t); } }, h = () => { try { localStorage.setItem(d.storageKey, JSON.stringify({ enabled: d.enabled, autoDetect: d.autoDetect, shortcut: d.shortcut, autoSave: d.autoSave, autoTrackPlayback: d.autoTrackPlayback, panelPosition: d.panelPosition, export: d.export })); } catch (t) { l?.error?.("Timecode", "Error saving settings", t); } }, g = (t, e, o) => { try { if (!(t && t instanceof HTMLElement)) { return l?.warn?.("Timecode", "Invalid panel element"), { left: 0, top: 0 }; } if ("number" != typeof e || "number" != typeof o || Number.isNaN(e) || Number.isNaN(o)) { return l?.warn?.("Timecode", "Invalid position coordinates"), { left: 0, top: 0 }; } const r = t.getBoundingClientRect(), i = r.height || 0, a = Math.max(0, window.innerWidth - (r.width || 0)), s = Math.max(0, window.innerHeight - i); return { left: Math.min(Math.max(0, e), a), top: Math.min(Math.max(0, o), s) }; } catch (t) { return l?.error?.("Timecode", "Error clamping panel position", t), { left: 0, top: 0 }; } }, w = (t, e) => { try { if ("number" != typeof t || "number" != typeof e || Number.isNaN(t) || Number.isNaN(e)) { return void l?.warn?.("Timecode", "Invalid position coordinates for saving"); } d.panelPosition = { left: t, top: e }, h(); } catch (t) { l?.error?.("Timecode", "Error saving panel position", t); } }, v = t => { t && d.panelPosition && requestAnimationFrame(() => { const {left: e, top: o} = g(t, d.panelPosition.left, d.panelPosition.top); t.style.left = `${e}px`, t.style.top = `${o}px`, t.style.right = "auto"; }); }, x = (t, e = 2e3, o = "info") => { YouTubeUtils.NotificationManager.show(t, { duration: e, type: o }); }, k = t => window.YouTubeUtils?.formatTime?.(t) || "0:00", S = t => { if (!t || t.length < 10) { return t; } let e = t.trim(); e = e.replace(/\s*\.{2,}$/, "").replace(/\s*…$/, ""); const o = e.split(/\s+/); if (o.length < 4) { return e; } const r = Math.floor(o.length / 2); if (r >= 2) { const t = o.slice(0, r).join(" "); if (t === o.slice(r, 2 * r).join(" ")) { return t; } } const i = Math.max(2, Math.floor(o.length / 4)); for (let t = Math.floor(o.length / 2); t >= i; t--) { const e = o.slice(0, t).join(" "), r = o.slice(0, t); for (let i = 1; i <= o.length - t; i++) { let a = 0, s = !1; const c = o.slice(i, Math.min(i + t, o.length)); for (let t = 0; t < r.length; t++) { const e = r[t], o = c[t]; if (!o) { break; } e === o ? a++ : (o.length >= 3 && e.startsWith(o) || e.length >= 3 && o.startsWith(e)) && (a += .8, s = !0); } const l = a / r.length, d = Math.floor(a); if (l >= .7 && (d >= 2 || a >= 1.5 && s)) { return e; } } } return e; }, T = t => { try { if (!t || "string" != typeof t) { return null; } const e = t.trim(); if (0 === e.length || e.length > 12) { return null; } let o = e.match(/^(\d+):(\d{1,2}):(\d{2})$/); if (o) { const [, t, e, r] = o.map(Number); if (Number.isNaN(t) || Number.isNaN(e) || Number.isNaN(r)) { return null; } if (e >= 60 || r >= 60 || t < 0 || e < 0 || r < 0) { return null; } const i = 3600 * t + 60 * e + r; return i <= 86400 ? i : null; } if (o = e.match(/^(\d{1,2}):(\d{2})$/), o) { const [, t, e] = o.map(Number); return Number.isNaN(t) || Number.isNaN(e) || t >= 60 || e >= 60 || t < 0 || e < 0 ? null : 60 * t + e; } return null; } catch (t) { return l?.error?.("Timecode", "Error parsing time", t), null; } }, L = t => { try { if (!t || "string" != typeof t) { return []; } t.length > 5e4 && (l?.warn?.("Timecode", "Text too long, truncating"), t = t.substring(0, 5e4)); const e = [], o = String(t || "").replace(/\r/g, "").split("\n"), r = 1e3; for (let t = 0; t < o.length && t < r; t += 1) { const r = o[t].trim(); if (!r) { continue; } const i = m(r); if (!i) { continue; } const a = T(i.token); if (null === a) { continue; } let s = f(r.slice(i.length)); s = s.trim().replace(/^\d+[.)]\s*/, "").replace(/\s+/g, " ").substring(0, 100); const c = s; s = s.replace(/[<>"']/g, ""), s = S(s), c !== s && s.length > 0 && l?.warn?.("Timecode", `Description deduplicated: ${c} -> ${s}`); const d = e.findIndex(t => t.time === a); -1 !== d ? (s || "").length > (e[d].label || "").length && (e[d] = { time: a, label: s || "", originalText: i.token }) : e.push({ time: a, label: s || "", originalText: i.token }); } return o.length > r && l?.warn?.("Timecode", "Maximum iterations reached during extraction"), e.sort((t, e) => t.time - e.time); } catch (t) { return l?.error?.("Timecode", "Error extracting timecodes", t), []; } }, M = [ "#description-inline-expander yt-attributed-string", "#description-inline-expander yt-formatted-string", "#description-inline-expander ytd-text-inline-expander", "#description-inline-expander .yt-core-attributed-string", "#description ytd-text-inline-expander", "#description ytd-expandable-video-description-body-renderer", "#description.ytd-watch-metadata yt-formatted-string", "#description.ytd-watch-metadata #description-inline-expander", "#tab-info ytd-expandable-video-description-body-renderer yt-formatted-string", "#tab-info ytd-expandable-video-description-body-renderer yt-attributed-string", "#structured-description ytd-text-inline-expander", "#structured-description yt-formatted-string", 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-macro-markers-description-chapters"] yt-formatted-string', 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-macro-markers-description-chapters"] yt-attributed-string', "ytd-watch-metadata #description", "ytd-watch-metadata #description-inline-expander", "#description" ], C = M.join(","), E = [ "#description-inline-expander yt-button-shape button", "#description-inline-expander tp-yt-paper-button#expand", "#description-inline-expander tp-yt-paper-button[aria-label]", "ytd-watch-metadata #description-inline-expander yt-button-shape button", "ytd-text-inline-expander[collapsed] yt-button-shape button", "ytd-text-inline-expander[collapsed] tp-yt-paper-button#expand", "ytd-expandable-video-description-body-renderer #expand", 'ytd-engagement-panel-section-list-renderer[target-id="engagement-panel-macro-markers-description-chapters"] #expand' ], z = (t = 250) => new Promise(e => setTimeout(e, t)), _ = () => { const t = []; return M.forEach(e => { o(e).forEach(e => { const o = e?.textContent?.trim(); o && t.push(o); }); }), t.join("\n"); }, I = [ "ytd-comment-thread-renderer #content-text", "ytd-comment-renderer #content-text", "ytd-comment-thread-renderer yt-formatted-string#content-text", "ytd-comment-renderer yt-formatted-string#content-text", "#comments ytd-comment-thread-renderer #content-text" ], A = async () => { for (const t of E) { const o = e(t); if (!o) { continue; } if ("true" === o.getAttribute("aria-expanded")) { return !1; } const r = o.getAttribute("aria-label")?.toLowerCase(); if (r?.includes("less")) { return !1; } if (null !== o.offsetParent) { try { return o.click(), await z(400), !0; } catch (t) { l?.warn?.("Timecode", "Failed to click expand button", t); } } } const t = e("ytd-text-inline-expander[collapsed]"); if (t) { try { t.removeAttribute("collapsed"); } catch (t) { YouTubeUtils.logError("TimecodePanel", "Failed to expand description", t); } return await z(300), !0; } return !1; }, P = async (t = {}) => { const {force: e = !1} = t; if (!d.enabled) { return []; } if (!e && !d.autoDetect) { return []; } const r = new URLSearchParams(window.location.search).get("v"); if (!r) { return []; } const i = `detect_${r}`; if (!e && u.timecodes.has(i)) { const t = u.timecodes.get(i); if (Array.isArray(t) && t.length) { return t; } u.timecodes.delete(i); } await (async () => { const t = _(); if (!t) { for (let e = 0; e < 3; e++) { try { await s(C, 1500); } catch (t) {} await z(200); const e = await A(); await z(e ? 500 : 200); const o = _(); if (o && o.length > t.length) { return; } } } })(); const a = new Map, c = _(); if (c && L(c).forEach(t => { t.time >= 0 && a.set(t.time.toString(), t); }), j().forEach(t => { if (t.time >= 0) { const e = t.time.toString(), o = a.get(e); a.set(e, o && t.label && t.label.length > o.label.length ? { ...o, label: t.label, isChapter: !0 } : o ? { ...o, isChapter: !0 } : t); } }), 0 === a.size) { try { const t = ((t = 30) => { try { const e = []; for (const r of I) { if (o(r).forEach(o => { if (e.length >= t) { return; } const r = o?.textContent?.trim(); r && e.push(r); }), e.length >= t) { break; } } return e.join("\n"); } catch (t) { return YouTubeUtils.logError("TimecodePanel", "collectCommentsText failed", t), ""; } })(); t && L(t).forEach(t => { t.time >= 0 && a.set(t.time.toString(), t); }); } catch (t) { YouTubeUtils.logError("TimecodePanel", "Comment scanning failed", t); } } const l = Array.from(a.values()).sort((t, e) => t.time - e.time), p = u.dom.list?.childElementCount > 0; return l.length > 0 ? (V(l), u.timecodes.set(i, l), d.autoSave && G(l)) : (!e && p || V([]), e && u.timecodes.delete(i)), l; }, j = () => { const t = o([ "ytd-macro-markers-list-item-renderer", "ytd-chapter-renderer", 'ytd-engagement-panel-section-list-renderer[target-id*="description-chapters"] ytd-macro-markers-list-item-renderer', 'ytd-engagement-panel-section-list-renderer[target-id*="description-chapters"] #details', "#structured-description ytd-horizontal-card-list-renderer ytd-macro-markers-list-item-renderer" ].join(", ")), e = new Map; return t.forEach(t => { const o = [ ".time-info", ".timestamp", "#time", 'span[id*="time"]' ], r = [ ".marker-title", ".chapter-title", "#details", "h4", ".title" ]; let i = null; for (const e of o) { const o = t.querySelector(e); if (o?.textContent) { i = o.textContent; break; } } let a = null; for (const e of r) { const o = t.querySelector(e); if (o?.textContent) { a = o.textContent; break; } } if (i) { const t = T(i.trim()); if (null !== t) { let o = a?.trim().replace(/\s+/g, " ") || ""; o && o.length > 0 && l?.warn?.("Timecode", `Debug raw chapter title: ${o}`), o = f(o); const r = S(o); o !== r && l?.warn?.("Timecode", `Removed duplicate: ${o} -> ${r}`), o = r, e.set(t.toString(), { time: t, label: o, isChapter: !0 }); } } }), Array.from(e.values()).sort((t, e) => t.time - e.time); }, H = () => { const o = e('.ytp-plus-settings-section[data-section="advanced"]'); if (!o) { return; } const i = o.querySelector(".timecode-settings-item"); if (!i || i.dataset.handlerAttached) { return; } i.dataset.handlerAttached = "1"; const a = o.querySelector('.timecode-submenu[data-submenu="timecode"]'); window.YouTubePlusDesignSystem?.initGlassDropdown?.({ dropdown: r("timecode-modifier-dropdown"), hiddenSelect: r("timecode-modifier-combo") }); const s = r("timecode-enable-checkbox"); s instanceof HTMLInputElement && s.addEventListener("change", () => { d.enabled = s.checked; const e = i.querySelector('.ytp-plus-submenu-toggle[data-submenu="timecode"]'); if (e instanceof HTMLElement) { if (d.enabled) { const o = (() => { try { const t = localStorage.getItem("ytp-plus-submenu-states"); if (!t) { return null; } const e = JSON.parse(t); if (e && "boolean" == typeof e.timecode) { return e.timecode; } } catch (e) { t.logSuppressed(e, "Timecode"); } return null; })(), r = "boolean" != typeof o || o; e.removeAttribute("disabled"), e.classList.remove("timecode-submenu-toggle-hidden"), e.setAttribute("aria-expanded", r ? "true" : "false"), a instanceof HTMLElement && a.classList.toggle("is-hidden", !r); } else { e.setAttribute("disabled", ""), e.classList.add("timecode-submenu-toggle-hidden"), a instanceof HTMLElement && a.classList.add("is-hidden"); } } K(d.enabled), h(); }); const c = r("timecode-modifier-combo"); c instanceof HTMLSelectElement && c.addEventListener("change", () => { const t = c.value; d.shortcut.ctrlKey = t.includes("ctrl"), d.shortcut.altKey = t.includes("alt"), d.shortcut.shiftKey = t.includes("shift"), h(); }); const l = r("timecode-key"); l instanceof HTMLInputElement && (l.addEventListener("input", () => { l.value && (d.shortcut.key = l.value.toUpperCase(), h()); }), l.addEventListener("keydown", t => { t.stopPropagation(); })); }, D = t => { const {target: o} = t, i = o.closest(".timecode-item"), a = o.closest ? o.closest("#timecode-reload") : "timecode-reload" === o.id ? o : null; if (a) { return t.preventDefault(), void (async (t = null) => { const e = t || u.dom.reloadButton || r("timecode-reload"); if (!u.isReloading && d.enabled) { u.isReloading = !0, e && (e.disabled = !0, e.classList.add("loading")); try { const t = await P({ force: !0 }); Array.isArray(t) && t.length ? x(c("foundTimecodes").replace("{count}", String(t.length))) : (V([]), x(c("noTimecodesFound"))); } catch (t) { YouTubeUtils.logError("TimecodePanel", "Reload failed", t), x(c("reloadError")); } finally { e && (e.disabled = !1, e.classList.remove("loading")), u.isReloading = !1; } } })(a); } if (o.closest ? o.closest("#timecode-close") : "timecode-close" === o.id && o) { K(!1); } else if ("timecode-add-btn" === o.id) { const t = YouTubeUtils.querySelector ? YouTubeUtils.querySelector("video") : e("video"); t && R(t.currentTime); } else if ("timecode-track-toggle" === o.id) { d.autoTrackPlayback = !d.autoTrackPlayback, o.textContent = c(d.autoTrackPlayback ? "tracking" : "track"), o.classList.toggle("active", d.autoTrackPlayback), u.dom.panel.classList.toggle("auto-tracking", d.autoTrackPlayback), h(), d.autoTrackPlayback && q(); } else if ("timecode-export-btn" === o.id) { Z(); } else if ("timecode-form-cancel" === o.id) { F(); } else if ("timecode-form-save" === o.id) { N(); } else if (o.classList.contains("timecode-action")) { t.stopPropagation(); const e = o.dataset.action, r = parseInt(o.closest(".timecode-item").dataset.index, 10); "edit" === e ? O(r) : "delete" === e && B(r); } else if (i && !o.closest(".timecode-actions")) { const t = parseFloat(i.dataset.time), o = e("video"); o && !Number.isNaN(t) && (o.currentTime = t, o.paused && o.play(), Y(i)); } }, O = t => { const e = J(); if (t < 0 || t >= e.length) { return; } const o = e[t]; u.editingIndex = t; const r = u.dom.list.querySelector(`.timecode-item[data-index="${t}"]`); r && (r.classList.add("editing"), u.dom.list.querySelectorAll(".timecode-item.editing").forEach(t => { t !== r && t.classList.remove("editing"); })), R(o.time, o.label); }, B = t => { const e = J(); if (t < 0 || t >= e.length) { return; } const o = e[t]; !o.isChapter || o.isUserAdded ? confirm(c("confirmDelete").replace("{label}", o.label)) && (e.splice(t, 1), V(e), G(e), x(c("timecodeDeleted"))) : x(c("cannotDeleteChapter")); }, R = (t, e = "") => { const {form: o, timeInput: r, labelInput: i} = u.dom; o.classList.add("visible"), r.value = k(t), i.value = e, requestAnimationFrame(() => i.focus()); }, F = () => { u.dom.form.classList.remove("visible"), u.editingIndex = null, u.dom.list?.querySelectorAll(".timecode-item.editing").forEach(t => { t.classList.remove("editing"); }); }, N = () => { const {timeInput: t, labelInput: e} = u.dom, o = t.value.trim(), r = e.value.trim(), i = T(o); if (null === i) { return void x(c("invalidTimeFormat")); } const a = J(), s = { time: i, label: r || "", isUserAdded: !0, isChapter: !1 }; if (null !== u.editingIndex) { const t = a[u.editingIndex]; if (t.isChapter && !t.isUserAdded) { return x(c("cannotEditChapter")), void F(); } a[u.editingIndex] = { ...t, ...s }, x(c("timecodeUpdated")); } else { a.push(s), x(c("timecodeAdded")); } const l = a.sort((t, e) => t.time - e.time); V(l), G(l), F(); }, Z = () => { const t = J(); if (!t.length) { return void x(c("noTimecodesToExport")); } const e = u.dom.panel?.querySelector("#timecode-export-btn"); e && (e.textContent = c("copied"), e.style.backgroundColor = "var(--yt-timecode-export-success-bg)", i(function() { e.textContent = c("export"), e.style.backgroundColor = ""; }, 2e3)); let o = `${document.title.replace(/\s-\sYouTube$/, "")}\n\nTimecodes:\n`; t.forEach(t => { const e = t.label?.trim(); o += e ? `${k(t.time)} - ${e}\n` : `${k(t.time)}\n`; }), navigator.clipboard?.writeText && navigator.clipboard.writeText(o).then(() => { x(c("timecodesCopied")); }); }, V = t => { const {list: e, empty: o} = u.dom; if (!e || !o) { return; } const r = !t.length; o.style.display = r ? "flex" : "none", e.style.display = r ? "none" : "block", r ? e.replaceChildren() : window.YouTubeUtils.renderTemplateClone(e, t.map((t, e) => { const o = k(t.time); let r = t.label?.trim() || ""; r = f(r); const i = r; r = S(r), i !== r && r.length > 0 && l?.warn?.("Timecode", `Display deduplicated: ${i} -> ${r}`); const a = o.replace(/^0+:/, ""), s = r.replace(/^0+:/, ""), d = { "<": "<", ">": ">", "&": "&", '"': """, "'": "'" }, u = (r && r !== o && s !== a && r !== t.originalText && r.length > 0 ? r : "").replace(/[<>&"']/g, t => d[t]); return `\n <div class="timecode-item ${t.isChapter ? "has-chapter" : ""}" data-time="${t.time}" data-index="${e}">\n <div class="timecode-time">${o}</div>\n ${u ? `<div class="timecode-label" title="${u}">${u}</div>` : ""}\n <div class="timecode-progress"></div>\n ${!t.isChapter || t.isUserAdded ? `\n <div class="timecode-actions">\n <button class="timecode-action edit" data-action="edit" title="${c("edit")}">✎</button>\n <button class="timecode-action delete" data-action="delete" title="${c("delete")}">✕</button>\n </div>\n ` : ""}\n </div>\n `; }).join("")); }, Y = t => { const e = u.dom.list?.querySelectorAll(".timecode-item"); e && (e.forEach(t => t.classList.remove("active", "pulse")), t && (t.classList.add("active", "pulse"), setTimeout(() => t.classList.remove("pulse"), 800))); }, q = () => { if (u.trackingId) { return; } const t = () => { try { const o = e("video"), {panel: r, currentTime: i, list: a} = u.dom; if (!o || !r || r.classList.contains("hidden") || !d.autoTrackPlayback) { return void (u.trackingId && (cancelAnimationFrame(u.trackingId), u.trackingId = 0)); } i && !Number.isNaN(o.currentTime) && (i.textContent = k(o.currentTime)); const s = a?.querySelectorAll(".timecode-item"); if (s?.length) { let t = -1, e = -1; for (let r = 0; r < s.length; r++) { const i = s[r].dataset.time; if (!i) { continue; } const a = parseFloat(i); Number.isNaN(a) || (o.currentTime >= a ? t = r : -1 === e && (e = r)); } if (u.activeIndex !== t) { if (null !== u.activeIndex && u.activeIndex >= 0 && s[u.activeIndex] && s[u.activeIndex].classList.remove("active"), t >= 0 && s[t]) { s[t].classList.add("active"); try { s[t].scrollIntoView({ behavior: "smooth", block: "center" }); } catch (e) { s[t].scrollIntoView(!1); } } u.activeIndex = t; } if (t >= 0 && e >= 0 && s[t]) { const r = s[t].dataset.time, i = s[e].dataset.time; if (r && i) { const e = parseFloat(r), a = parseFloat(i); if (!Number.isNaN(e) && !Number.isNaN(a) && a > e) { const r = (o.currentTime - e) / (a - e) * 100, i = s[t].querySelector(".timecode-progress"); if (i) { const t = Math.min(100, Math.max(0, r)); i.style.width = `${t}%`; } } } } } d.autoTrackPlayback && (u.trackingId = requestAnimationFrame(t)); } catch (t) { l?.warn?.("Timecode", "Tracking error", t), u.trackingId && (cancelAnimationFrame(u.trackingId), u.trackingId = 0); } }; u.trackingId = requestAnimationFrame(t); }, G = e => { const o = new URLSearchParams(window.location.search).get("v"); if (o) { try { const t = e.map(t => ({ t: t.time, l: t.label?.trim() || "", c: t.isChapter, u: t.isUserAdded })); localStorage.setItem(`yt_tc_${o}`, JSON.stringify(t)); } catch (e) { t.logSuppressed(e, "Timecode"); } } }, W = () => { const t = new URLSearchParams(window.location.search).get("v"); if (!t) { return null; } try { const e = localStorage.getItem(`yt_tc_${t}`); return e ? JSON.parse(e).map(t => ({ time: t.t, label: t.l, isChapter: t.c, isUserAdded: t.u })).sort((t, e) => t.time - e.time) : null; } catch (t) { return null; } }, J = () => { const t = u.dom.list?.querySelectorAll(".timecode-item"); return t ? Array.from(t).map(t => { const e = parseFloat(t.dataset.time), o = t.querySelector(".timecode-label"); return { time: e, label: o?.textContent?.trim() || "", isChapter: t.classList.contains("has-chapter"), isUserAdded: !t.classList.contains("has-chapter") }; }).sort((t, e) => t.time - e.time) : []; }, K = t => { o("#timecode-panel").forEach(t => { t !== u.dom.panel && t.remove(); }); const e = u.dom.panel || (() => { if (u.dom.panel) { return u.dom.panel; } o("#timecode-panel").forEach(t => t.remove()); const t = document.createElement("div"); return t.id = "timecode-panel", t.className = d.enabled ? "" : "hidden", d.autoTrackPlayback && t.classList.add("auto-tracking"), window.YouTubeUtils.renderTemplateClone(t, `\n <div id="timecode-header">\n <h3 id="timecode-title">\n <div id="timecode-tracking-indicator"></div>\n ${c("timecodes")}\n <span id="timecode-current-time"></span>\n </h3>\n <div id="timecode-header-controls">\n <button id="timecode-reload" title="${c("reload")}" aria-label="${c("reload")}">\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M21.5 2v6h-6M2.5 22v-6h6"/>\n <path d="M19.13 11.48A10 10 0 0 0 12 2C6.48 2 2 6.48 2 12c0 .34.02.67.05 1M4.87 12.52A10 10 0 0 0 12 22c5.52 0 10-4.48 10-10 0-.34-.02-.67-.05-1"/>\n </svg>\n </button>\n <button id="timecode-close" title="${c("close")}" aria-label="${c("close")}">\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M6 6L18 18M18 6L6 18"/>\n </svg>\n </button>\n </div>\n </div>\n <div id="timecode-list"></div>\n <div id="timecode-empty">\n <div>${c("noTimecodesFound")}</div>\n <div class="timecode-empty-hint">${c("clickToAdd")}</div>\n </div>\n <div id="timecode-form">\n <input type="text" id="timecode-form-time" placeholder="${c("timePlaceholder")}">\n <input type="text" id="timecode-form-label" placeholder="${c("labelPlaceholder")}">\n <div id="timecode-form-buttons">\n <button type="button" id="timecode-form-cancel">${c("cancel")}</button>\n <button type="button" id="timecode-form-save" class="save">${c("saveButton")}</button>\n </div>\n </div>\n <div id="timecode-actions">\n <button id="timecode-add-btn">${c("add")}</button>\n <button id="timecode-export-btn" class="${d.export ? "" : "is-hidden"}">${c("export")}</button>\n <button id="timecode-track-toggle" class="${d.autoTrackPlayback ? "active" : ""}">${c(d.autoTrackPlayback ? "tracking" : "track")}</button>\n </div>\n `), u.dom = { panel: t, list: t.querySelector("#timecode-list"), empty: t.querySelector("#timecode-empty"), form: t.querySelector("#timecode-form"), timeInput: t.querySelector("#timecode-form-time"), labelInput: t.querySelector("#timecode-form-label"), currentTime: t.querySelector("#timecode-current-time"), trackToggle: t.querySelector("#timecode-track-toggle"), reloadButton: t.querySelector("#timecode-reload") }, t.addEventListener("click", D), (t => { const e = t.querySelector("#timecode-header"); if (!e) { return; } let o, r, i, a; YouTubeUtils.cleanupManager.registerListener(e, "mousedown", e => { if (0 !== e.button) { return; } u.dragging = !0, o = e.clientX, r = e.clientY; const s = t.getBoundingClientRect(); t.style.left || (t.style.left = `${s.left}px`), t.style.top || (t.style.top = `${s.top}px`), t.style.right = "auto", i = parseFloat(t.style.left) || s.left, a = parseFloat(t.style.top) || s.top; const c = e => { if (!u.dragging) { return; } const s = e.clientX - o, c = e.clientY - r, {left: l, top: d} = g(t, i + s, a + c); t.style.left = `${l}px`, t.style.top = `${d}px`, t.style.right = "auto"; }, l = () => { if (!u.dragging) { return; } u.dragging = !1, document.removeEventListener("mousemove", c), document.removeEventListener("mouseup", l); const e = t.getBoundingClientRect(), {left: o, top: r} = g(t, e.left, e.top); t.style.left = `${o}px`, t.style.top = `${r}px`, t.style.right = "auto", w(o, r); }; document.addEventListener("mousemove", c), document.addEventListener("mouseup", l); }); })(t), document.body.appendChild(t), v(t), t; })(); if (void 0 === t && (t = e.classList.contains("hidden")), e.classList.toggle("hidden", !t), t) { v(e); const t = W(); t?.length ? V(t) : d.autoDetect && P().catch(t => { l?.error?.("Timecode", "Detection failed", t); }), d.autoTrackPlayback && q(); } else { u.trackingId && (cancelAnimationFrame(u.trackingId), u.trackingId = 0); } }, X = () => { u.trackingId && (cancelAnimationFrame(u.trackingId), u.trackingId = 0), u.dom.panel && (u.dom.panel.remove(), u.dom.panel = null); }, Q = () => { if (u.settingsIntegrationStarted) { return; } u.settingsIntegrationStarted = !0, b(); const t = () => { H(); }; YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", t) : document.addEventListener("youtube-plus-settings-modal-opened", t); const e = t => { const e = t.target, o = e?.closest?.(".ytp-plus-settings-nav-item"); "advanced" === o?.dataset?.section && H(); }; YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "click", e, !0) : document.addEventListener("click", e, !0); }, tt = () => { if (p) { return; } if ("www.youtube.com" !== t?.getHostname?.() || window.frameElement) { return; } if (!y()) { return; } if (!("function" == typeof YouTubeUtils?.querySelector && YouTubeUtils.querySelector("ytd-app") || e("ytd-app"))) { return void (() => { const t = YouTubeUtils.createRetryScheduler; if ("function" == typeof t) { return void t({ label: "timecode-init", interval: 120, maxAttempts: 30, check: () => !!("function" == typeof YouTubeUtils.querySelector && YouTubeUtils.querySelector("ytd-app") || e("ytd-app")) && (tt(), !0) }); } const o = requestAnimationFrame(tt); YouTubeUtils.cleanupManager?.registerAnimationFrame?.(o); })(); } p = !0, b(), (() => { if (r("timecode-panel-styles")) { return; } const t = window.YouTubePlusDesignSystem?.getStyle?.("timecode-panel-styles") || ""; YouTubeUtils.StyleManager.add("timecode-panel-styles", t); })(), (() => { const t = t => { if (!d.enabled) { return; } const e = t.target; if (e.matches?.("input, textarea, [contenteditable]")) { return; } const {key: o, shiftKey: r, altKey: i, ctrlKey: a} = d.shortcut; t.key.toUpperCase() === o && t.shiftKey === r && t.altKey === i && t.ctrlKey === a && (t.preventDefault(), K()); }; window.YouTubeUtils && YouTubeUtils.cleanupManager ? YouTubeUtils.cleanupManager.registerListener(document, "keydown", t) : document.addEventListener("keydown", t); })(), (() => { let t = new URLSearchParams(window.location.search).get("v"); const e = () => { const e = new URLSearchParams(window.location.search).get("v"); if (e !== t && "/watch" === window.location.pathname && (t = e, u.activeIndex = null, u.editingIndex = null, u.timecodes.clear(), d.enabled && u.dom.panel && !u.dom.panel.classList.contains("hidden"))) { const t = W(); t?.length ? V(t) : d.autoDetect && setTimeout(() => P().catch(t => { l?.error?.("Timecode", "Detection failed", t); }), 500), d.autoTrackPlayback && q(); } }; window.YouTubeUtils && YouTubeUtils.cleanupManager ? YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-finish", e) : document.addEventListener("yt-navigate-finish", e); })(); let o = null, i = null; const s = () => { const r = e(".ytp-plus-settings-modal"); r && ((r => { if (!(r && r instanceof Element)) { return; } const a = window.YouTubePlusMutationCoordinator; if (o && a?.unsubscribe) { try { a.unsubscribe(o); } catch (e) { t.logSuppressed(e, "Timecode"); } o = null; } a?.watchTarget && (o = `timecode::settingsModal::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`, a.watchTarget(o, r, () => { i || (i = setTimeout(() => { i = null, e('.ytp-plus-settings-section[data-section="advanced"]:not(.hidden)') && !e(".timecode-settings-item") && H(); }, 30)); }, { childList: !0, subtree: !0, attributes: !0, attributeFilter: [ "class" ] }), YouTubeUtils.cleanupManager?.register && YouTubeUtils.cleanupManager.register(() => { o && a?.unsubscribe && (a.unsubscribe(o), o = null); })); })(r), H()); }; if (YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", s) : document.addEventListener("youtube-plus-settings-modal-opened", s), YouTubeUtils.cleanupManager.registerListener(document, "click", t => { const e = t.target, o = e?.closest?.(".ytp-plus-settings-nav-item"); "advanced" === o?.dataset?.section && H(); }, !0), d.enabled && !u.resizeListenerKey) { const t = a(() => { if (!u.dom.panel) { return; } const t = u.dom.panel.getBoundingClientRect(), {left: e, top: o} = g(u.dom.panel, t.left, t.top); u.dom.panel.style.left = `${e}px`, u.dom.panel.style.top = `${o}px`, u.dom.panel.style.right = "auto", w(e, o); }, 200); u.resizeListenerKey = YouTubeUtils.cleanupManager.registerListener(window, "resize", t); } }, et = () => { Q(), y() ? tt() : p && X(); }; document.addEventListener("youtube-plus-settings-modal-opened", () => { try { Q(), H(); } catch (t) {} }), window.YouTubeUtils?.whenRelevant ? window.YouTubeUtils.whenRelevant({ name: "timecode", isRelevant: y, onEnter: et }) : "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", et, { once: !0 }) : et(), window.YouTubeUtils?.onSectionActive && window.YouTubeUtils.onSectionActive("advanced", () => { try { Q(), H(); } catch (t) {} }), "function" == typeof window.YouTubeUtils?.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-finish", et, { passive: !0 }) : document.addEventListener("yt-navigate-finish", et, { passive: !0 }), window.addEventListener("beforeunload", X); })(), (function() { let t = !0; const e = e => { t = !1 !== e, t ? (F(), B()) : O(); }; if (t = window.YouTubeUtils?.loadFeatureEnabled?.("enablePlaylistSearch") ?? !0, window._playlistSearchInitialized) { return; } window._playlistSearchInitialized = !0; const o = window.YouTubeUtils, {$: r, $$: i, t: a, logger: s} = o?.helpers ?? {}, c = () => o.isYouTubeDomain() && (o.isWatchRoute() || "/playlist" === window.location.pathname), l = () => "/playlist" === window.location.pathname, d = () => { if (!c()) { return !1; } try { return new URLSearchParams(window.location.search).has("list"); } catch (t) { return !1; } }, u = o?.onDomReady || (t => { "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", t, { once: !0 }) : t(); }), p = o.debounce, y = o.throttle, m = { enabled: !0, storageKey: "youtube_playlist_search_settings", searchDebounceMs: 150, observerThrottleMs: 300, maxPlaylistItems: 1e4, maxQueryLength: 300, deleteDelay: 250 }, f = { searchInput: null, searchResults: null, originalItems: [], currentPlaylistId: null, observerFallbackTimerId: null, rafId: null, itemsCache: new Map, itemsContainer: null, itemSelector: null, itemTagName: null, playlistPanel: null, isPlaylistPage: !1, isDeleting: !1, deleteMode: !1, selectedItems: new Set, rootSubId: null }, b = new WeakMap, h = (() => { let t = !1; return () => { if (t) { return; } t = !0; const e = t => { t.classList.add("is-focused"); }, o = t => { t.classList.remove("is-focused"); }, r = t => { let e = b.get(t); e || (e = p(e => { if (e.length > m.maxQueryLength) { const o = e.substring(0, m.maxQueryLength); return t.value = o, void S(o); } S(e); }, m.searchDebounceMs), b.set(t, e)), e(t.value || ""); }, i = window.YouTubePlusEventDelegation; i?.on ? (i.on(document, "focusin", ".ytplus-playlist-search-input", (t, o) => { o && e(o); }), i.on(document, "focusout", ".ytplus-playlist-search-input", (t, e) => { e && o(e); }), i.on(document, "input", ".ytplus-playlist-search-input", (t, e) => { e && r(e); })) : (document.addEventListener("focusin", t => { const o = t.target instanceof Element ? t.target : null, r = o?.closest(".ytplus-playlist-search-input"); r && e(r); }, !0), document.addEventListener("focusout", t => { const e = t.target instanceof Element ? t.target : null, r = e?.closest(".ytplus-playlist-search-input"); r && o(r); }, !0), document.addEventListener("input", t => { const e = t.target instanceof Element ? t.target : null, o = e?.closest(".ytplus-playlist-search-input"); o && r(o); }, !0)); }; })(), g = () => { try { const t = new URLSearchParams(window.location.search).get("list"); return t && /^[a-zA-Z0-9_-]+$/.test(t) ? t : null; } catch (t) { return s?.warn?.("Playlist Search", "Failed to get playlist ID", t), null; } }, w = () => { if (l()) { const t = r("ytd-playlist-video-list-renderer"); if (!t) { return null; } const e = t.querySelector("#contents") || t.querySelector("ytd-playlist-video-list-renderer #contents"); return { panel: t, itemsContainer: e, itemSelector: "ytd-playlist-video-renderer", itemTagName: "YTD-PLAYLIST-VIDEO-RENDERER", isPlaylistPage: !0 }; } if (!0 === o?.isWatchPage?.()) { const t = r("ytd-playlist-panel-renderer"); if (!t) { return null; } const e = t.querySelector("#items") || t.querySelector(".playlist-items.style-scope.ytd-playlist-panel-renderer") || t.querySelector(".playlist-items"); return { panel: t, itemsContainer: e, itemSelector: "ytd-playlist-panel-video-renderer", itemTagName: "YTD-PLAYLIST-PANEL-VIDEO-RENDERER", isPlaylistPage: !1 }; } return null; }, v = () => { if (!m.enabled) { return; } if (!c()) { return; } const t = g(); if (!t) { return; } const e = w(); if (!e) { return; } const {panel: o, itemsContainer: i, itemSelector: l, itemTagName: d} = e; if (o.querySelector(".ytplus-playlist-search")) { return; } f.currentPlaylistId = t, f.itemsContainer = i || null, f.itemSelector = l, f.itemTagName = d, f.playlistPanel = o, f.isPlaylistPage = e.isPlaylistPage; const u = document.createElement("div"); u.className = "ytplus-playlist-search", setTimeout(() => { try { if (!f.isPlaylistPage) { return void Object.assign(u.style, { position: "sticky", top: "0", zIndex: "1", background: "transparent" }); } const t = f.playlistPanel || w()?.panel || null, e = f.isPlaylistPage ? 84 : 8; let o = t; for (;o && o !== document.body; ) { const t = window.getComputedStyle(o).overflowY; if (("auto" === t || "scroll" === t) && o.scrollHeight > o.clientHeight) { break; } o = o.parentElement; } if (o && o !== document.body) { Object.assign(u.style, { position: "sticky", top: `${e}px`, background: "var(--yt-spec-badge-chip-background)", backdropFilter: "blur(6px)", boxShadow: "var(--yt-shadow)" }); } else if (t) { const o = t.getBoundingClientRect(); Object.assign(u.style, { position: "fixed", top: `${e}px`, left: `${o.left}px`, width: `${o.width}px`, background: "var(--yt-spec-badge-chip-background)", backdropFilter: "blur(6px)", boxShadow: "0 6px 20px rgba(0,0,0,0.4)", zIndex: "9999" }); const r = p(() => { const e = t.getBoundingClientRect(); u.style.left = `${e.left}px`, u.style.width = `${e.width}px`; }, 120); window.addEventListener("resize", r, { passive: !0 }), window.addEventListener("scroll", r, { passive: !0 }); } else { u.style.position = "sticky", u.style.top = `${e}px`, u.style.background = "var(--yt-spec-badge-chip-background)"; } } catch (t) {} }, 100); const y = document.createElement("input"); y.type = "text"; const b = ((t, e) => { try { const e = [ "ytd-playlist-header-renderer #title", "ytd-playlist-header-renderer .title", ".title", "h3 a", "#header-title", "#title", ".playlist-title", "h1.title" ]; for (const o of e) { const e = t.querySelector(o) || r(o); if (e?.textContent?.trim()) { const t = e.textContent.trim(); return t.length > 100 ? `${t.substring(0, 100)}...` : t; } } const o = r('meta[name="title"]') || r('meta[property="og:title"]'); if (o?.content) { const t = o.content.trim(); return t.length > 100 ? `${t.substring(0, 100)}...` : t; } } catch (t) { s?.warn?.("Playlist Search", "Failed to get display name", t); } return e && "string" == typeof e ? e.substring(0, 50) : "playlist"; })(o, t); if (y.placeholder = a(f.isPlaylistPage ? "searchPlaceholderPlaylistPage" : "searchPlaceholder", { playlist: b }), y.className = "ytplus-playlist-search-input", h(), u.appendChild(y), f.searchInput = y, i) { const t = i.querySelector(l); t && t.parentElement === i ? i.insertBefore(u, t) : i.appendChild(u); } else { o.firstChild ? o.insertBefore(u, o.firstChild) : o.appendChild(u); } k(), H(u), x(); }, x = () => { f.rootSubId && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(f.rootSubId), f.rootSubId = null), f.observerFallbackTimerId && (clearInterval(f.observerFallbackTimerId), f.observerFallbackTimerId = null); const t = f.playlistPanel || w()?.panel; if (!(t && f.itemTagName && f.itemSelector)) { return; } let e = f.originalItems.length, r = !1; const i = f.itemTagName, a = f.itemSelector, s = f.itemsContainer || t, c = y(t => { r || t.some(t => { if ("childList" !== t.type) { return !1; } if (0 === t.addedNodes.length && 0 === t.removedNodes.length) { return !1; } for (let e = 0; e < t.addedNodes.length; e++) { const o = t.addedNodes[e]; if (1 === o.nodeType && o.tagName === i) { return !0; } } for (let e = 0; e < t.removedNodes.length; e++) { const o = t.removedNodes[e]; if (1 === o.nodeType && o.tagName === i) { return !0; } } return !1; }) && (r = !0, requestAnimationFrame(() => { const t = e, o = s ? s.querySelectorAll(a) : []; o.length !== t && (e = o.length, k(), f.searchInput?.value && S(f.searchInput.value)), r = !1; })); }, m.observerThrottleMs), l = window.YouTubePlusMutationCoordinator; l?.subscribeRoot ? f.rootSubId = l.subscribeRoot("playlist-search-items", c, { selector: a }) : f.observerFallbackTimerId = setInterval(() => { try { const e = f.itemsContainer || f.playlistPanel || t; if (!e || !f.itemSelector) { return; } e.querySelectorAll(f.itemSelector).length !== f.originalItems.length && (k(), f.searchInput?.value && S(f.searchInput.value)); } catch (t) { o.logSuppressed(t, "PlaylistSearch"); } }, m.observerThrottleMs); }, k = () => { const t = f.itemsContainer || f.playlistPanel; if (!t || !f.itemSelector) { return; } const e = t.querySelectorAll(f.itemSelector); e.length > m.maxPlaylistItems && s?.warn?.("Playlist Search", `Playlist has ${e.length} items, limiting to ${m.maxPlaylistItems}`); const o = new Set, r = Array.from(e).slice(0, m.maxPlaylistItems); f.originalItems = r.map((t, e) => { const r = t.getAttribute("video-id") || `item-${e}`; if (o.add(r), f.itemsCache.has(r)) { const e = f.itemsCache.get(r); if (e && e.element === t) { return e; } } const i = t.querySelector("#video-title") || t.querySelector("a#video-title"), a = t.querySelector("#byline") || t.querySelector("#channel-name") || t.querySelector("ytd-channel-name a"), s = i?.textContent || "", c = a?.textContent || "", l = { element: t, videoId: r, titleOriginal: s, channelOriginal: c, title: s.trim().toLowerCase(), channel: c.trim().toLowerCase() }; return f.itemsCache.set(r, l), l; }); for (const [t] of f.itemsCache) { o.has(t) || f.itemsCache.delete(t); } }, S = t => { if (f.rafId && cancelAnimationFrame(f.rafId), t && "string" != typeof t) { return void s?.warn?.("Playlist Search", "Invalid query type"); } if (t && t.length > m.maxQueryLength && (t = t.substring(0, m.maxQueryLength)), !t || "" === t.trim()) { return void (f.rafId = requestAnimationFrame(() => { f.originalItems.forEach(t => { t.element.style.display = ""; }), f.rafId = null; })); } const e = t.toLowerCase().trim(); let o = 0; f.rafId = requestAnimationFrame(() => { const t = []; f.originalItems.forEach(r => { r.title.includes(e) || r.channel.includes(e) ? ("none" === r.element.style.display && t.push({ element: r.element, display: "" }), o++) : "none" !== r.element.style.display && t.push({ element: r.element, display: "none" }); }), t.forEach(t => { t.element.style.display = t.display; }), T(o, f.originalItems.length), f.rafId = null; }); }, T = (t, e) => { o?.logger?.debug?.(`[Playlist Search] Showing ${t} of ${e} videos`); }, L = (t, e) => { const o = e instanceof Error ? e : new Error(String(e)); window.YouTubePlusErrorBoundary ? window.YouTubePlusErrorBoundary.logError(o, { context: t }) : s?.error?.("PlaylistSearch", t, e); }, M = (t, e) => window.YouTubePlusErrorBoundary?.withErrorBoundary ? window.YouTubePlusErrorBoundary.withErrorBoundary(t, "PlaylistSearch") : (...o) => { try { return t(...o); } catch (t) { return L(e, t), null; } }, C = M(() => { f.deleteMode = !f.deleteMode, f.selectedItems.clear(); const t = f.playlistPanel || w()?.panel; if (!t) { return; } const e = t.querySelector(".ytplus-playlist-delete-toggle"), o = t.querySelector(".ytplus-playlist-delete-bar"); if (f.deleteMode) { if (e) { const t = e; t.classList.add("active"), t.setAttribute("aria-pressed", "true"), t.title = a("playlistDeleteModeExit"); } o && o.classList.add("is-visible"), E(); } else { if (e) { const t = e; t.classList.remove("active"), t.setAttribute("aria-pressed", "false"), t.title = a("playlistDeleteMode"); } o && o.classList.remove("is-visible"), z(); } _(); }, "toggleDeleteMode"), E = M(() => { const t = f.itemsContainer || f.playlistPanel; t && f.itemSelector && t.querySelectorAll(f.itemSelector).forEach((t, e) => { if (t.querySelector(".ytplus-playlist-item-checkbox")) { return; } const o = document.createElement("input"); o.type = "checkbox", o.className = "ytplus-playlist-item-checkbox ytp-plus-settings-checkbox", o.setAttribute("aria-label", a("playlistSelectVideo")), o.dataset.index = String(e), o.addEventListener("change", () => { const r = t.getAttribute("video-id") || `item-${e}`; o.checked ? f.selectedItems.add(r) : f.selectedItems.delete(r), _(); }), o.addEventListener("click", t => t.stopPropagation()), t.style.position = "relative", t.insertBefore(o, t.firstChild); }); }, "addCheckboxesToItems"), z = M(() => { const t = f.itemsContainer || f.playlistPanel; t && (t.querySelectorAll(".ytplus-playlist-item-checkbox").forEach(t => t.remove()), f.selectedItems.clear()); }, "removeCheckboxesFromItems"), _ = M(() => { const t = f.playlistPanel || w()?.panel; if (!t) { return; } const e = t.querySelector(".ytplus-playlist-delete-selected"), o = t.querySelector(".ytplus-playlist-selected-count"); e && (e.disabled = 0 === f.selectedItems.size), o && (o.textContent = a("playlistSelectedCount", { count: f.selectedItems.size })); }, "updateDeleteBarState"), I = M(() => { const t = f.itemsContainer || f.playlistPanel; t && f.itemSelector && (t.querySelectorAll(".ytplus-playlist-item-checkbox").forEach(t => { const e = t.closest(f.itemSelector); if (e && "none" !== e.style.display) { t.checked = !0; const o = e.getAttribute("video-id") || `item-${t.dataset.index}`; f.selectedItems.add(o); } }), _()); }, "selectAllItems"), A = M(() => { const t = f.itemsContainer || f.playlistPanel; t && (t.querySelectorAll(".ytplus-playlist-item-checkbox").forEach(t => { t.checked = !1; }), f.selectedItems.clear(), _()); }, "clearAllItems"), P = t => new Promise(e => { try { const o = t.querySelector("button#button[aria-label]") || t.querySelector("yt-icon-button#button") || t.querySelector("ytd-menu-renderer button") || t.querySelector('[aria-haspopup="menu"]') || t.querySelector("button.yt-icon-button"); if (!o) { return s?.warn?.("Playlist Search", "Could not find menu button for item"), void e(!1); } o.click(), setTimeout(() => { try { const t = i("tp-yt-paper-listbox ytd-menu-service-item-renderer, ytd-menu-popup-renderer ytd-menu-service-item-renderer, tp-yt-iron-dropdown ytd-menu-service-item-renderer"); let o = null; for (const e of t) { const t = (e.textContent || "").toLowerCase(); if (t.includes("remove") || t.includes("удалить") || t.includes("supprimer") || t.includes("entfernen") || t.includes("eliminar") || t.includes("rimuovi") || t.includes("kaldır") || t.includes("削除") || t.includes("삭제") || t.includes("移除") || t.includes("oʻchirish") || t.includes("жою") || t.includes("өчүрүү") || t.includes("выдаліць") || t.includes("премахване") || t.includes("xóa")) { o = e; break; } } o ? (o.click(), setTimeout(() => { document.body.click(), e(!0); }, 100)) : (document.body.click(), s?.warn?.("Playlist Search", 'Could not find "Remove" option in menu'), e(!1)); } catch (t) { document.body.click(), L("removeItemViaMenu:findOption", t), e(!1); } }, 350); } catch (t) { L("removeItemViaMenu", t), e(!1); } }), j = M(async () => { if (f.isDeleting || 0 === f.selectedItems.size) { return; } if (!confirm(a("playlistDeleteConfirm", { count: f.selectedItems.size }))) { return; } f.isDeleting = !0; const t = f.itemsContainer || f.playlistPanel; if (!t || !f.itemSelector) { return void (f.isDeleting = !1); } const e = Array.from(t.querySelectorAll(f.itemSelector)).filter((t, e) => { const o = t.getAttribute("video-id") || `item-${e}`; return f.selectedItems.has(o); }); let r = 0, i = 0; for (const t of e) { await P(t) ? r++ : i++, await new Promise(t => setTimeout(t, m.deleteDelay)); } f.isDeleting = !1, f.selectedItems.clear(), setTimeout(() => { k(), f.deleteMode && E(), _(); }, 500); const s = i > 0 ? a("playlistDeletePartial", { success: r, fail: i }) : a("playlistDeleteSuccess", { count: r }); o?.logger?.debug?.(`[Playlist Search] ${s}`); }, "deleteSelectedItems"), H = t => { if (!t || t.querySelector(".ytplus-playlist-delete-toggle")) { return; } D(); const e = document.createElement("button"); e.type = "button", e.className = "ytplus-playlist-delete-toggle", e.setAttribute("aria-pressed", "false"), e.setAttribute("aria-label", a("playlistDeleteMode")), e.title = a("playlistDeleteMode"), o.renderTemplateClone(e, '\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none"\n stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <polyline points="3 6 5 6 21 6"/>\n <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>\n <line x1="10" y1="11" x2="10" y2="17"/>\n <line x1="14" y1="11" x2="14" y2="17"/>\n </svg>\n '), e.addEventListener("click", C); const r = document.createElement("div"); r.className = "ytplus-playlist-input-row"; const i = t.querySelector(".ytplus-playlist-search-input"); i && (i.parentNode && i.parentNode.insertBefore(r, i), r.appendChild(i), r.appendChild(e)); const s = document.createElement("div"); s.className = "ytplus-playlist-delete-bar"; const c = document.createElement("span"); c.className = "ytplus-playlist-selected-count", c.textContent = a("playlistSelectedCount", { count: 0 }); const l = (t, e, o) => { const r = document.createElement("button"); return r.type = "button", r.textContent = t, r.className = `ytplus-playlist-delete-action ${e}`, r.addEventListener("click", o), r; }, d = l(a("selectAll"), "ytplus-playlist-select-all", I), u = l(a("clearAll"), "ytplus-playlist-clear-all", A), p = l(a("deleteSelected"), "ytplus-playlist-delete-selected", j); p.disabled = !0, s.append(c, d, u, p), t.appendChild(s); }, D = () => { try { const t = o?.StyleManager; if (t && "function" == typeof t.add) { const e = window.YouTubePlusDesignSystem?.getStyle?.("ytplus-playlist-delete-styles") || ""; t.add("ytplus-playlist-delete-styles", e); } } catch (t) { s?.warn?.("PlaylistSearch", "Failed to inject delete styles", t); } }, O = () => { f.deleteMode && (z(), f.deleteMode = !1), f.isDeleting = !1, f.selectedItems.clear(); const t = r(".ytplus-playlist-search"); t && t.remove(), f.rootSubId && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(f.rootSubId), f.rootSubId = null), f.observerFallbackTimerId && (clearInterval(f.observerFallbackTimerId), f.observerFallbackTimerId = null), f.rafId && (cancelAnimationFrame(f.rafId), f.rafId = null), f.itemsCache.clear(), f.searchInput = null, f.originalItems = [], f.currentPlaylistId = null, f.itemsContainer = null, f.itemSelector = null, f.itemTagName = null, f.playlistPanel = null, f.isPlaylistPage = !1; }, B = p(() => { if (!t) { return void O(); } if (!c()) { return void O(); } const e = g(); if ((e !== f.currentPlaylistId || !r(".ytplus-playlist-search")) && (O(), e)) { const t = l() ? "ytd-playlist-video-list-renderer #contents" : "ytd-playlist-panel-renderer #items", e = o.waitForElement; if ("function" == typeof e) { e(t, 1500).finally(v); } else { const e = o?.createRetryScheduler; "function" == typeof e ? e({ label: "playlist-search-add-ui", interval: 160, maxAttempts: 10, check: () => !!document.querySelector(t) && (v(), Boolean(r(".ytplus-playlist-search"))) }) : v(); } } }, 250); let R = !1; const F = () => { if (R || !t || !d()) { return; } R = !0; const e = () => { (() => { try { const t = window.YouTubePlusSettingsStore, e = t && "function" == typeof t.load ? t.load() : (() => { const t = localStorage.getItem(o?.SETTINGS_KEY || "youtube_plus_settings"); return t ? JSON.parse(t) : null; })(); e && "object" == typeof e && "boolean" == typeof e.enablePlaylistSearch && (m.enabled = e.enablePlaylistSearch); const r = localStorage.getItem(m.storageKey); if (r) { const t = JSON.parse(r); o?.safeMerge ? o.safeMerge(m, t) : "boolean" == typeof t.enabled && (m.enabled = t.enabled); } } catch (t) { s?.warn?.("Playlist Search", "Failed to load settings", t); } })(), t && !1 !== m.enabled && v(); }; "function" == typeof window.requestIdleCallback ? window.requestIdleCallback(e, { timeout: 1500 }) : setTimeout(e, 0); }, N = () => { d() ? (F(), B()) : O(); }; o?.whenRelevant ? o.whenRelevant({ name: "playlist-search", isRelevant: d, onEnter: F }) : u(F), o?.cleanupManager && "function" == typeof o.cleanupManager.registerListener ? (o.cleanupManager.registerListener(document, "yt-navigate-finish", N, { passive: !0 }), o.cleanupManager.registerListener(window, "beforeunload", O, { passive: !0 })) : (document.addEventListener("yt-navigate-finish", N), window.addEventListener("beforeunload", O)), window.addEventListener("youtube-plus-settings-updated", r => { try { const o = r.detail, i = !1 !== o?.enablePlaylistSearch; if (i === t) { return; } e(i); } catch (t) { e(o?.loadFeatureEnabled?.("enablePlaylistSearch") ?? !0); } }); })(), (function() { function t() { return window.YouTubeUtils?.loadFeatureEnabled?.("enableThumbnail") ?? !0; } function e(t) { try { t.onload = null, t.onerror = null, t.src = "", t.parentNode && t.parentNode.removeChild(t); } catch (t) {} } function o(t) { try { if (!w()) { return; } if (!(function(t) { if (!t || "string" != typeof t) { return f?.error?.("Thumbnail", "Invalid URL provided to modal"), !1; } try { const e = new URL(t); return "https:" !== e.protocol ? (f?.error?.("Thumbnail", "Only HTTPS URLs are allowed"), !1) : !![ "ytimg.com", "youtube.com", "ggpht.com", "googleusercontent.com" ].some(t => h(e.hostname, t)) || (f?.error?.("Thumbnail", "Image domain not allowed", e.hostname), !1); } catch (t) { return f?.error?.("Thumbnail", "Invalid URL format", t), !1; } })(t)) { return; } p(".thumbnail-modal-overlay").forEach(t => t.remove()); const e = document.createElement("div"); e.className = "thumbnail-modal-overlay ytp-plus-modal-overlay", e.setAttribute("role", "dialog"), e.setAttribute("aria-modal", "true"), e.setAttribute("aria-label", "Thumbnail preview"); const o = document.createElement("div"); o.className = "thumbnail-modal-content ytp-plus-modal-content"; const r = (function(t) { const e = document.createElement("img"); return e.className = "thumbnail-modal-img", e.src = t, e.alt = m("thumbnailPreview"), e.title = "", e.style.cursor = "pointer", e.addEventListener("click", () => window.open(e.src, "_blank")), e; })(t), i = document.createElement("div"); i.className = "thumbnail-modal-options"; const a = (function(t) { const e = document.createElement("button"); return e.className = "thumbnail-modal-close thumbnail-modal-action-btn ytp-plus-settings-close", e.setAttribute("data-shared-close-button", "ytp-plus-close-settings"), window.YouTubeUtils.renderTemplateClone(e, '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 9.50002L9.5 14.5M9.49998 9.5L14.5 14.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>'), e.title = m("closeButton") || m("close"), e.setAttribute("aria-label", m("closeButton") || m("close")), e.addEventListener("click", e => { e.preventDefault(), e.stopPropagation(), t.remove(); }), e; })(e), s = (function(t) { const e = document.createElement("button"); return e.className = "thumbnail-modal-open thumbnail-modal-action-btn ytp-plus-settings-close", window.YouTubeUtils.renderTemplateClone(e, '\n <svg fill="currentColor" viewBox="0 0 24 24" width="18" height="18" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">\n <g id="SVGRepo_bgCarrier" stroke-width="0"></g>\n <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>\n <g id="SVGRepo_iconCarrier"><path d="M14.293,9.707a1,1,0,0,1,0-1.414L18.586,4H16a1,1,0,0,1,0-2h5a1,1,0,0,1,1,1V8a1,1,0,0,1-2,0V5.414L15.707,9.707a1,1,0,0,1-1.414,0ZM3,22H8a1,1,0,0,0,0-2H5.414l4.293-4.293a1,1,0,0,0-1.414-1.414L4,18.586V16a1,1,0,0,0-2,0v5A1,1,0,0,0,3,22Z"></path></g>\n </svg>\n '), e.title = m("clickToOpen"), e.setAttribute("aria-label", m("clickToOpen")), e.addEventListener("click", e => { e.preventDefault(), e.stopPropagation(), window.open(t.src, "_blank"); }), e; })(r), c = (function(t) { const e = document.createElement("button"); return e.className = "thumbnail-modal-download thumbnail-modal-action-btn ytp-plus-settings-close", window.YouTubeUtils.renderTemplateClone(e, '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity="0.5" d="M3 15C3 17.8284 3 19.2426 3.87868 20.1213C4.75736 21 6.17157 21 9 21H15C17.8284 21 19.2426 21 20.1213 20.1213C21 19.2426 21 17.8284 21 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M12 3V16M12 16L16 11.625M12 16L8 11.625" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>\n '), e.title = m("download"), e.setAttribute("aria-label", m("download")), e.addEventListener("click", async e => { e.preventDefault(), e.stopPropagation(); try { await (async function(t) { const e = new AbortController, o = b(() => e.abort(), 15e3); let r; try { r = await fetch(t, { signal: e.signal }); } finally { clearTimeout(o); } if (!r.ok) { throw new Error("Network response was not ok"); } const i = await r.blob(), a = URL.createObjectURL(i), s = document.createElement("a"); s.href = a; try { const e = new URL(t).pathname.split("/"); s.download = e[e.length - 1] || "thumbnail.jpg"; } catch (t) { s.download = "thumbnail.jpg"; } document.body.appendChild(s), s.click(), s.remove(), b(() => URL.revokeObjectURL(a), 1500); })(t.src); } catch (e) { window.open(t.src, "_blank"); } }), e; })(r); o.appendChild(r), o.appendChild(i); const l = document.createElement("div"); l.className = "thumbnail-modal-wrapper"; const d = document.createElement("div"); if (d.className = "thumbnail-modal-actions", d.appendChild(a), d.appendChild(s), d.appendChild(c), l.appendChild(o), l.appendChild(d), e.appendChild(l), e.addEventListener("click", ({target: t}) => { t === e && e.remove(); }), (function(t) { window.addEventListener("keydown", function e(o) { "Escape" === o.key && (t.remove(), window.removeEventListener("keydown", e, !0)); }, !0); })(e), (function(t, e) { t.addEventListener("error", () => { const t = document.createElement("div"); t.textContent = m("thumbnailLoadFailed"), t.style.color = "white", e.appendChild(t); }); })(r, o), document.body.appendChild(e), requestAnimationFrame(() => { const t = e.querySelector('button, [tabindex="0"]'); t && t.focus(); }), window.YouTubePlusModalHandlers?.createFocusTrap) { const t = window.YouTubePlusModalHandlers.createFocusTrap(e), o = window.YouTubePlusMutationCoordinator; o?.subscribeRoot && (T = "thumbnail::modalCleanup", o.subscribeRoot(T, () => { e.isConnected || (t(), o.unsubscribe(T), T = null); }, { childList: !0, attributes: !1, subtree: !0 })); } } catch (t) { f?.error?.("Thumbnail", "Error showing modal", t); } } function r() { const t = u("#movie_player") || u("ytd-player"); if (!t) { return I++, void (I < 10 ? b(r, 500) : I = 0); } let e = t.querySelector("#thumbnailPreview-player-overlay"); if (!e) { e = (function(t, e) { const o = i(t, e); return o.id = "thumbnailPreview-player-overlay", o.dataset.videoId = t, o.classList.add("thumbnail-player-overlay"), o; })(z, t), e.tabIndex = 0, e.setAttribute("role", "button"), e.setAttribute("aria-label", "Show thumbnail preview"), e.onmouseenter = () => { try { e.style.opacity = "0.5"; } catch (t) { d.logSuppressed(t, "Thumbnail"); } }, e.onmouseleave = () => { try { e.style.opacity = "0"; } catch (t) { d.logSuppressed(t, "Thumbnail"); } }, e.onfocus = () => { try { e.style.opacity = "0.5"; } catch (t) { d.logSuppressed(t, "Thumbnail"); } }, e.onblur = () => { try { e.style.opacity = "0"; } catch (t) { d.logSuppressed(t, "Thumbnail"); } }, e.addEventListener("keydown", t => { !t || "Enter" !== t.key && " " !== t.key || (t.preventDefault(), e.click()); }); const o = t; return "static" === getComputedStyle(o).position && (o.style.position = "relative"), void o.appendChild(e); } e.dataset.videoId !== z && (e.remove(), r()), I = 0; } function i(t, r) { const i = document.createElement("div"), a = document.createElementNS(C, "svg"); a.setAttribute("width", "16"), a.setAttribute("height", "16"), a.setAttribute("viewBox", "0 0 24 24"), a.setAttribute("fill", "none"), a.setAttribute("stroke", "white"), a.setAttribute("stroke-width", "2"), a.setAttribute("stroke-linecap", "round"), a.setAttribute("stroke-linejoin", "round"), a.style.transition = "stroke 0.2s ease"; const s = document.createElementNS(C, "rect"); s.setAttribute("width", "18"), s.setAttribute("height", "18"), s.setAttribute("x", "3"), s.setAttribute("y", "3"), s.setAttribute("rx", "2"), s.setAttribute("ry", "2"), a.appendChild(s); const c = document.createElementNS(C, "circle"); c.setAttribute("cx", "9"), c.setAttribute("cy", "9"), c.setAttribute("r", "2"), a.appendChild(c); const l = document.createElementNS(C, "path"); return l.setAttribute("d", "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"), a.appendChild(l), i.appendChild(a), i.classList.add("thumbnail-base-overlay"), i.onclick = async a => { a.preventDefault(), a.stopPropagation(); const s = r.closest("ytm-shorts-lockup-view-model") || r.closest(".shortsLockupViewModelHost") || r.closest('[class*="shortsLockupViewModelHost"]') || r.querySelector('a[href*="/shorts/"]'); await (async function(t, r, i) { try { if (!E(t)) { return void f?.error?.("Thumbnail", "Invalid video ID", t); } if (!(function(t) { return !!(t && t instanceof HTMLElement); })(i)) { return void f?.error?.("Thumbnail", "Invalid overlay element"); } const a = i.querySelector("svg"); if (!a) { return void f?.warn?.("Thumbnail", "No SVG found in overlay element"); } const s = (function(t, e) { const o = (function() { const t = document.createElementNS(C, "svg"); t.setAttribute("xmlns", C), t.setAttribute("width", "16"), t.setAttribute("height", "16"), t.setAttribute("viewBox", "0 0 24 24"), t.setAttribute("fill", "none"), t.setAttribute("stroke", "white"), t.setAttribute("stroke-width", "2"), t.setAttribute("stroke-linecap", "round"), t.setAttribute("stroke-linejoin", "round"); const e = document.createElementNS(C, "path"); return e.setAttribute("d", "M21 12a9 9 0 1 1-6.219-8.56"), t.appendChild(e), t.style.animation = "spin 1s linear infinite", t; })(); return t.replaceChild(o, e), o; })(i, a); try { await (async function(t, r) { const i = r ? (function(t) { return { primary: `https://i.ytimg.com/vi/${t}/oardefault.jpg`, fallback: `https://i.ytimg.com/vi/${t}/oar2.jpg` }; })(t) : (function(t) { return { primary: `https://i.ytimg.com/vi/${t}/maxresdefault.jpg`, fallback: `https://i.ytimg.com/vi/${t}/mqdefault.jpg` }; })(t); o(await (async function(t) { try { if (!(function(t) { return !(!t || "string" != typeof t) || (f?.warn?.("Thumbnail", "Invalid URL provided"), !1); })(t)) { return !1; } if (!(function(t) { try { const e = new URL(t); return (function(t) { return "https:" === t.protocol || (f?.warn?.("Thumbnail", "Only HTTPS URLs are allowed"), !1); })(e) && (function(t) { const {hostname: e} = t; return !(!h(e, "ytimg.com") && !h(e, "youtube.com") && (f?.warn?.("Thumbnail", "Only YouTube image domains are allowed"), 1)); })(e) ? e : null; } catch (t) { return f?.error?.("Thumbnail", "Invalid URL", t), null; } })(t)) { return !1; } const o = await (async function(t) { const e = new AbortController, o = b(() => e.abort(), 5e3); try { const r = await fetch(t, { method: "HEAD", signal: e.signal }).catch(() => null); return clearTimeout(o), !r || r.ok; } catch (t) { return clearTimeout(o), !1; } })(t); return null !== o ? o : await (function(t) { return new Promise(o => { const r = document.createElement("img"); r.style.display = "none"; const i = b(() => { e(r), o(!1); }, 3e3); window.YouTubeUtils?.cleanupManager?.registerTimeout && window.YouTubeUtils.cleanupManager.registerTimeout(i), r.onload = () => { clearTimeout(i), e(r), o(!0); }, r.onerror = () => { clearTimeout(i), e(r), o(!1); }, document.body.appendChild(r), r.src = t; }); })(t); } catch (t) { return f?.error?.("Thumbnail", "Error checking image", t), !1; } })(i.primary) ? i.primary : i.fallback); })(t, r); } finally { !(function(t, e, o) { try { e?.parentNode && t.replaceChild(o, e); } catch (t) { f?.error?.("Thumbnail", "Error restoring original SVG", t), e?.parentNode && e.parentNode.removeChild(e); } })(i, s, a); } } catch (t) { f?.error?.("Thumbnail", "Error opening thumbnail", t); } })(t, !!s, i); }, i; } function a(t) { if (!w()) { return; } if (t.querySelector(".thumb-overlay")) { return; } let {videoId: e, thumbnailContainer: o} = (function(t) { const e = t.querySelector('img[src*="ytimg.com"]'); if (!e?.src) { return { videoId: null, thumbnailContainer: null }; } const o = (function(t) { try { if (!t || "string" != typeof t) { return null; } const e = t.match(/\/vi\/([^/]+)\//), o = e ? e[1] : null; return o && !/^[a-zA-Z0-9_-]{11}$/.test(o) ? (f?.warn?.("Thumbnail", "Invalid video ID format", o), null) : o; } catch (t) { return f?.error?.("Thumbnail", "Error extracting video ID", t), null; } })(e.src), r = (function(t) { return t.closest("yt-thumbnail-view-model") || t.parentElement; })(e); return { videoId: o, thumbnailContainer: r }; })(t); if (e || ({videoId: e, thumbnailContainer: o} = (function(t) { const e = t.querySelector('a[href*="/shorts/"]'); return e?.href ? { videoId: (function(t) { try { if (!t || "string" != typeof t) { return null; } const e = t.match(/\/shorts\/([^/?]+)/), o = e ? e[1] : null; return o && !/^[a-zA-Z0-9_-]{11}$/.test(o) ? (f?.warn?.("Thumbnail", "Invalid shorts ID format", o), null) : o; } catch (t) { return f?.error?.("Thumbnail", "Error extracting shorts ID", t), null; } })(e.href), thumbnailContainer: (o = t.querySelector('img[src*="ytimg.com"]')) ? o.closest(".ytCoreImageHost") || o.closest('[class*="ThumbnailContainer"]') || o.closest('[class*="ImageHost"]') || o.parentElement : null } : { videoId: null, thumbnailContainer: null }; var o; })(t)), !e || !o) { return; } !(function(t) { "static" === getComputedStyle(t).position && (t.style.position = "relative"); })(o); const r = i(e, t); r.className = "thumbnail-base-overlay thumb-overlay", o.appendChild(r), (function(t, e) { t.onmouseenter = () => { e.style.opacity = "1"; }, t.onmouseleave = () => { e.style.opacity = "0"; }; })(o, r); } function s(t = 0) { if (A) { return; } const e = Date.now(), i = Math.max(t, Math.max(0, 350 - (e - P))); A = b(() => { A = null, P = Date.now(); try { if (!w()) { return; } w() && ((function() { const t = p("yt-thumbnail-view-model"); for (let e = 0; e < t.length; e++) { a(t[e]); } const e = p(".ytd-thumbnail"); for (let t = 0; t < e.length; t++) { a(e[t]); } const o = p("ytm-shorts-lockup-view-model"); for (let t = 0; t < o.length; t++) { a(o[t]); } const r = p(".shortsLockupViewModelHost"); for (let t = 0; t < r.length; t++) { a(r[t]); } const i = p('[class*="shortsLockupViewModelHost"]'); for (let t = 0; t < i.length; t++) { a(i[t]); } })(), [ "yt-avatar-shape img", "#avatar img", "ytd-channel-avatar-editor img", '.ytd-video-owner-renderer img[src*="yt"]', 'img[src*="yt3.ggpht.com"]', 'img[src*="yt4.ggpht.com"]' ].forEach(t => { p(t).forEach(t => { t.src && t.src.includes("yt") && (t.closest(".avatar-overlay") || (t.naturalWidth > 0 && t.naturalWidth === t.naturalHeight || t.src.includes("ggpht.com")) && (function(t) { if (!w()) { return; } const e = t.parentElement; if (!e) { return; } if (t.closest(".avatar-btn, #avatar-btn") || e.closest(".avatar-btn, #avatar-btn") || t.closest("button") || e.closest("button") || t.closest(".thumbnail-modal-wrapper") || e.closest(".thumbnail-modal-wrapper")) { return; } if (t.closest("ytm-shorts-lockup-view-model") || e.closest("ytm-shorts-lockup-view-model") || t.closest(".shortsLockupViewModelHost") || e.closest(".shortsLockupViewModelHost") || t.closest('[class*="shortsLockupViewModelHost"]') || e.closest('[class*="shortsLockupViewModelHost"]') || t.closest('[class*="shorts"]') || e.closest('[class*="shorts"]')) { return; } if (e.querySelector(".avatar-overlay")) { return; } "static" === getComputedStyle(e).position && (e.style.position = "relative"); const r = (function() { const t = document.createElement("div"), e = document.createElementNS(C, "svg"); e.setAttribute("width", "16"), e.setAttribute("height", "16"), e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "white"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round"), e.style.transition = "stroke 0.2s ease"; const o = document.createElementNS(C, "circle"); o.setAttribute("cx", "12"), o.setAttribute("cy", "8"), o.setAttribute("r", "5"), e.appendChild(o); const r = document.createElementNS(C, "path"); return r.setAttribute("d", "M20 21a8 8 0 0 0-16 0"), e.appendChild(r), t.appendChild(e), t.classList.add("thumbnail-base-overlay"), t; })(); r.className = "thumbnail-base-overlay avatar-overlay", r.onclick = e => { e.preventDefault(), e.stopPropagation(), o(t.src.replace(/=s\d+-c-k-c0x00ffffff-no-rj.*/, "=s0")); }, e.appendChild(r), e.onmouseenter = () => { r.style.opacity = "1"; }, e.onmouseleave = () => { r.style.opacity = "0"; }; })(t)); }); }), [ "yt-image-banner-view-model img", 'ytd-c4-tabbed-header-renderer img[src*="yt"]', '#channel-header img[src*="banner"]', 'img[src*="banner"]' ].forEach(t => { p(t).forEach(t => { t.src && (t.closest(".banner-overlay") || ((t.src.includes("banner") || t.src.includes("yt")) && t.naturalWidth > 2 * t.naturalHeight || t.src.includes("banner")) && (function(t) { if (!w()) { return; } const e = t.parentElement; if (e.querySelector(".banner-overlay")) { return; } "static" === getComputedStyle(e).position && (e.style.position = "relative"); const r = (function() { const t = document.createElement("div"), e = document.createElementNS(C, "svg"); e.setAttribute("width", "16"), e.setAttribute("height", "16"), e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "white"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round"), e.style.transition = "stroke 0.2s ease"; const o = document.createElementNS(C, "rect"); o.setAttribute("x", "3"), o.setAttribute("y", "3"), o.setAttribute("width", "18"), o.setAttribute("height", "18"), o.setAttribute("rx", "2"), o.setAttribute("ry", "2"), e.appendChild(o); const r = document.createElementNS(C, "circle"); r.setAttribute("cx", "9"), r.setAttribute("cy", "9"), r.setAttribute("r", "2"), e.appendChild(r); const i = document.createElementNS(C, "polyline"); return i.setAttribute("points", "21,15 16,10 5,21"), e.appendChild(i), t.appendChild(e), t.classList.add("thumbnail-base-overlay"), t; })(); r.className = "thumbnail-base-overlay banner-overlay", r.onclick = e => { e.preventDefault(), e.stopPropagation(), o(t.src.replace(/=w\d+-.*/, "=s0")); }, e.appendChild(r), e.onmouseenter = () => { r.style.opacity = "1"; }, e.onmouseleave = () => { r.style.opacity = "0"; }; })(t)); }); }), (function() { if (!w()) { return; } if (!window.YouTubeUtils?.isWatchPage?.(window.location.href)) { return; } const t = new URLSearchParams(window.location.search).get("v"); t !== z && (_ = !1, (function() { const t = u("#thumbnailPreview-player-overlay"); t && t.remove(); })()), (function(t) { return !t || t === z || _; })(t) || (z = t || "", r()); })()); } catch (t) { f?.error?.("Thumbnail", "processAll failed", t); } }, i); } function c() { if (x || k) { return; } if (!w()) { return; } if (!v()) { return; } k = !0; const t = () => { k = !1, (function() { if (!x && w()) { x = !0, (function() { if (!M) { try { const t = window.YouTubeUtils?.StyleManager; if (t && "function" == typeof t.add) { const e = window.YouTubePlusDesignSystem?.getStyle?.("thumbnail-viewer-styles") || ""; t.add("thumbnail-viewer-styles", e), M = !0; } } catch (t) { f?.warn?.("Thumbnail", "Failed to inject thumbnail styles", t); } } })(), L || (L = (function() { let t = location.href; const e = () => { b(() => { w() && location.href !== t && (t = location.href, s(250)); }, 100); }, o = () => { w() && (location.href !== t && (t = location.href), s(120)); }; return window.addEventListener("ytp-history-navigate", e), window.addEventListener("popstate", e), window.addEventListener("yt-navigate-finish", o), () => { try { window.removeEventListener("ytp-history-navigate", e), window.removeEventListener("popstate", e), window.removeEventListener("yt-navigate-finish", o); } catch (t) { d.logSuppressed(t, "Thumbnail"); } }; })()), (function() { if (S) { return; } const t = () => { const t = window.YouTubePlusMutationCoordinator; if (!t?.subscribeRoot) { return; } const e = u("#content") || u("#page-manager") || document.body; S = "thumbnail::routeObserver", t.subscribeRoot(S, () => { s(120); }, { selector: e instanceof Element ? void 0 : "#content, #page-manager", childList: !0, attributes: !1, subtree: e !== document.body }); }; document.body ? t() : document.addEventListener("DOMContentLoaded", t); })(), "function" == typeof requestIdleCallback ? requestIdleCallback(() => s(0), { timeout: 2e3 }) : s(400), b(() => s(0), 900), b(() => s(0), 1800); try { window.addEventListener("ytp:nav-refresh", () => { try { g && s(0); } catch {} }); } catch {} } })(); }; "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", () => b(t, 100), { once: !0 }) : b(t, 100); } function l(t) { g = !1 !== t, g ? c() : (function() { if (x) { x = !1; try { A && (clearTimeout(A), A = null); } catch (t) { d.logSuppressed(t, "Thumbnail"); } if ((function() { if (!S) { return; } const t = window.YouTubePlusMutationCoordinator; t?.unsubscribe && t.unsubscribe(S), S = null; })(), L) { try { L(); } catch (t) { d.logSuppressed(t, "Thumbnail"); } L = null; } !(function() { try { p(".thumbnail-modal-overlay").forEach(t => t.remove()); } catch (t) { d.logSuppressed(t, "Thumbnail"); } try { p(".thumb-overlay, .avatar-overlay, .banner-overlay").forEach(t => t.remove()); } catch (t) { d.logSuppressed(t, "Thumbnail"); } try { const t = u("#thumbnailPreview-player-overlay"); t && t.remove(); } catch (t) { d.logSuppressed(t, "Thumbnail"); } })(), (function() { try { window.YouTubeUtils?.StyleManager?.remove && window.YouTubeUtils.StyleManager.remove("thumbnail-viewer-styles"); } catch (t) { d.logSuppressed(t, "Thumbnail"); } const t = y("ytplus-thumbnail-styles"); if (t) { try { t.remove(); } catch (t) { d.logSuppressed(t, "Thumbnail"); } } M = !1; })(); } })(); } const d = window.YouTubeUtils, {$: u, $$: p, byId: y, t: m, logger: f, setTimeout_: b} = d?.helpers ?? {}, h = (t, e) => { const o = String(t || "").toLowerCase(), r = String(e || "").toLowerCase(); return o === r || o.endsWith(`.${r}`); }; let g = t(); const w = () => g, v = () => { const t = window.YouTubeUtils; return t.isYouTubeDomain() && (t.isWatchRoute() || t.isShortsRoute() || t.isChannelRoute()); }; let x = !1, k = !1, S = null, T = null, L = null, M = !1; const C = "http://www.w3.org/2000/svg", E = window.YouTubeSafeDOM?.isValidVideoId || (t => !(!t || "string" != typeof t || !/^[a-zA-Z0-9_-]{11}$/.test(t))); let z = "", _ = !1, I = 0, A = null, P = 0; window.YouTubeUtils?.whenRelevant ? window.YouTubeUtils.whenRelevant({ name: "thumbnail", isRelevant: v, onEnter: c }) : c(), window.addEventListener("youtube-plus-settings-updated", e => { try { const t = e.detail?.enableThumbnail; l(!1 !== t); } catch (e) { l(t()); } }); })(), (function() { const t = window.YouTubeUtils, {t: e, logger: o, $: r, setTimeout_: i} = t?.helpers ?? {}, a = { enabled: !0, get shortcuts() { return { seekBackward: { key: "ArrowLeft", get description() { return e("seekBackward"); } }, seekForward: { key: "ArrowRight", get description() { return e("seekForward"); } }, volumeUp: { key: "+", get description() { return e("volumeUp"); } }, volumeDown: { key: "-", get description() { return e("volumeDown"); } }, mute: { key: "m", get description() { return e("muteUnmute"); } }, toggleCaptions: { key: "c", get description() { return e("toggleCaptions"); } }, showHelp: { key: "?", get description() { return e("showHideHelp"); }, editable: !1 } }; }, storageKey: "youtube_shorts_keyboard_settings" }, s = { helpVisible: !1, lastAction: null, actionTimeout: null, editingShortcut: null, cachedVideo: null, downloadButton: null, downloadObserver: null, downloadEnsureQueued: !1, lastVideoCheck: 0, initialized: !1 }, c = (() => { const t = [ "ytd-reel-video-renderer[is-active] video", "#shorts-player video", "video" ]; return () => { const e = Date.now(); if (s.cachedVideo?.isConnected && e - s.lastVideoCheck < 100) { return s.cachedVideo; } for (const o of t) { const t = YouTubeUtils.querySelector ? YouTubeUtils.querySelector(o) : r(o); if (t) { return s.cachedVideo = t, s.lastVideoCheck = e, s.cachedVideo; } } return s.cachedVideo = null, null; }; })(), l = { isInShortsPage: () => location.pathname.startsWith("/shorts/"), isInputFocused: () => { const t = document.activeElement; return !(!t?.matches?.('input, textarea, [contenteditable="true"]') && !t?.isContentEditable); }, loadSettings: () => { try { const t = localStorage.getItem(a.storageKey); if (!t) { return; } const e = JSON.parse(t); if ("object" != typeof e || null === e) { return void o?.warn?.("Shorts", "Invalid settings format"); } if ("boolean" == typeof e.enabled && (a.enabled = e.enabled), e.shortcuts && "object" == typeof e.shortcuts) { const t = l.getDefaultShortcuts(); for (const [o, r] of Object.entries(e.shortcuts)) { const e = t; if (!e[o]) { continue; } if (!r || "object" != typeof r) { continue; } const {key: i, editable: s} = r; "string" == typeof i && i.length > 0 && i.length <= 20 && (a.shortcuts[o] = { key: i, description: e[o].description, editable: !1 !== s }); } } } catch (t) { o?.error?.("Shorts", "Error loading settings", t); } }, saveSettings: () => { try { localStorage.setItem(a.storageKey, JSON.stringify({ enabled: a.enabled, shortcuts: a.shortcuts })); } catch (t) { o?.error?.("Shorts", "Error saving settings", t); } }, getDefaultShortcuts: () => ({ seekBackward: { key: "ArrowLeft", get description() { return e("seekBackward"); } }, seekForward: { key: "ArrowRight", get description() { return e("seekForward"); } }, volumeUp: { key: "+", get description() { return e("volumeUp"); } }, volumeDown: { key: "-", get description() { return e("volumeDown"); } }, mute: { key: "m", get description() { return e("muteUnmute"); } }, toggleCaptions: { key: "c", get description() { return e("toggleCaptions"); } }, showHelp: { key: "?", get description() { return e("showHideHelp"); }, editable: !1 } }) }, d = (() => { let t = null; return { show: e => { s.lastAction = e, clearTimeout(s.actionTimeout ?? void 0); const o = t || (t = document.createElement("div"), t.id = "shorts-keyboard-feedback", document.body.appendChild(t), t.style.position = "fixed", t.style.top = "50%", t.style.left = "50%", t.style.transform = "translate(-50%,-50%)", t.style.background = "var(--yt-shorts-feedback-bg-dark)", t.style.backdropFilter = "blur(12px) saturate(180%)", t.style.border = "1px solid var(--yt-shorts-border-light)", t.style.borderRadius = "20px", t.style.color = "var(--yt-text-primary,#fff)", t.style.padding = "18px 32px", t.style.fontSize = "20px", t.style.fontWeight = "700", t.style.zIndex = "10000", t.style.opacity = "0", t.style.visibility = "hidden", t.style.pointerEvents = "none", t.style.transition = "all .3s cubic-bezier(.4,0,.2,1)", t.style.textAlign = "center", t.style.boxShadow = "0 8px 32px 0 var(--yt-shorts-shadow-blue)", t.style.setProperty("-webkit-backdrop-filter", "blur(12px) saturate(180%)"), t); o.textContent = e, requestAnimationFrame(() => { o.style.opacity = "1", o.style.visibility = "visible", o.style.transform = "translate(-50%,-50%) scale(1.05)"; }), s.actionTimeout = i(() => { o.style.opacity = "0", o.style.visibility = "hidden", o.style.transform = "translate(-50%,-50%) scale(0.95)"; }, 1500); } }; })(), u = { seekBackward: () => { const t = c(); t && (t.currentTime = Math.max(0, t.currentTime - 5), d.show("-5s")); }, seekForward: () => { const t = c(); t && (t.currentTime = Math.min(t.duration || Infinity, t.currentTime + 5), d.show("+5s")); }, toggleCaptions: () => { try { const t = (r("ytd-shorts-player-controls, ytd-reel-video-renderer, #shorts-player") || document).querySelectorAll("button[aria-label]"); for (const e of t) { const t = (e.getAttribute("aria-label") || "").toLowerCase(); if ((t.includes("subtit") || t.includes("caption") || t.includes("субтит") || t.includes("субтитр") || t.includes("cc")) && null !== e.offsetParent) { e.click(); break; } } } catch (t) {} const t = c(); if (t?.textTracks?.length) { const o = Array.from(t.textTracks).filter(t => "subtitles" === t.kind || "captions" === t.kind || !t.kind); if (o.length) { const t = o.some(t => "showing" === t.mode); return o.forEach(e => { e.mode = t ? "hidden" : "showing"; }), void d.show(e(t ? "captionsOff" : "captionsOn")); } } d.show(e("captionsUnavailable")); }, volumeUp: () => { const t = c(); t && (t.volume = Math.min(1, t.volume + .1), d.show(`${Math.round(100 * t.volume)}%`)); }, volumeDown: () => { const t = c(); t && (t.volume = Math.max(0, t.volume - .1), d.show(`${Math.round(100 * t.volume)}%`)); }, mute: () => { const t = c(); try { const t = (r("ytd-shorts-player-controls, ytd-reel-video-renderer, #shorts-player") || document).querySelectorAll("button[aria-label]"); for (const e of t) { const t = (e.getAttribute("aria-label") || "").toLowerCase(); if ((t.includes("mute") || t.includes("unmute") || t.includes("sound") || t.includes("volume") || t.includes("звук") || t.includes("громк")) && null !== e.offsetParent) { return e.click(), void setTimeout(() => { const t = c(); t && d.show(t.muted ? "🔇" : "🔊"); }, 60); } } } catch (t) {} t && (t.muted = !t.muted, d.show(t.muted ? "🔇" : "🔊")); }, showHelp: () => p.toggle() }, p = (() => { let o = null, r = null; return { show: () => { const i = (() => { if (o) { return o; } o = document.createElement("div"), o.id = "shorts-keyboard-help", o.className = "shorts-help-panel ytp-plus-shorts-overlay", o.setAttribute("role", "dialog"), o.setAttribute("aria-modal", "true"), o.tabIndex = -1; const i = () => { if (!o) { return; } const s = o; t.renderTemplateClone(s, `\n <div class="help-topbar">\n <div class="help-header ytp-plus-settings-title">${e("keyboardShortcuts")}</div>\n <button class="ytp-plus-settings-close help-close" data-shared-close-button="ytp-plus-close-settings" type="button" aria-label="${e("closeButton")}">\n <svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>\n </svg>\n </button>\n </div>\n <div class="help-body">\n <div class="help-content">\n ${Object.entries(a.shortcuts).map(([t, e]) => { const o = e, r = " " === e.key ? "Space" : e.key; return `<div class="help-item">\n <kbd data-action="${window.YouTubeSafeDOM.escapeHTML(t)}" ${!1 === o.editable ? 'class="non-editable"' : ""}>${window.YouTubeSafeDOM.escapeHTML(r)}</kbd>\n <span>${window.YouTubeSafeDOM.escapeHTML(e.description)}</span>\n </div>`; }).join("")}\n </div>\n <div class="help-actions">\n <button class="ytp-plus-button ytp-plus-button-primary reset-all-shortcuts">${e("resetAll")}</button>\n </div>\n </div>\n `); const c = s.querySelector(".help-close"); c && (c.onclick = () => p.hide()); const u = s.querySelector(".reset-all-shortcuts"); u && (u.onclick = () => { if (confirm(e("resetAllConfirm"))) { const t = l.getDefaultShortcuts(); Object.assign(a, { vt: t }), l.saveSettings(), d.show(e("shortcutsReset")), i(); } }), s.querySelectorAll("kbd[data-action]:not(.non-editable)").forEach(t => { const e = t; e.onclick = () => { const t = e.getAttribute("data-action") || "", o = a.shortcuts; y(t, o[t]?.key || ""); }; }), (t => { r?.abort(), r = new AbortController; const {signal: e} = r, o = t.querySelector(".help-content"); if (!(o instanceof HTMLElement)) { return; } let i = !1, a = 0, s = 0, c = 0, l = 0; const d = () => { i && (i = !1, t.classList.remove("is-dragging")); }, u = !!e && { signal: e }; o.addEventListener("pointerdown", e => { if (0 !== e.button) { return; } const o = e.target instanceof Element ? e.target : null; if (o?.closest("button,kbd,a,input,textarea,select,label")) { return; } const r = t.getBoundingClientRect(); t.style.left = `${r.left}px`, t.style.top = `${r.top}px`, t.style.transform = "none", a = e.clientX - r.left, s = e.clientY - r.top, c = t.offsetWidth, l = t.offsetHeight, i = !0, t.classList.add("is-dragging"); }, u), window.addEventListener("pointermove", e => { if (!i) { return; } const o = Math.max(0, window.innerWidth - c), r = Math.max(0, window.innerHeight - l), d = Math.min(Math.max(0, e.clientX - a), o), u = Math.min(Math.max(0, e.clientY - s), r); t.style.left = `${d}px`, t.style.top = `${u}px`; }, u), window.addEventListener("pointerup", d, u), window.addEventListener("blur", d, u); })(s); }; return i(), document.body.appendChild(o), o; })(); i.classList.add("visible"), s.helpVisible = !0, i.focus(); }, hide: () => { o && (o.classList.remove("visible"), s.helpVisible = !1); }, toggle: () => s.helpVisible ? p.hide() : p.show(), refresh: () => { r?.abort(), o && (o.remove(), o = null); } }; })(), y = (o, r) => { const i = document.createElement("div"); i.className = "glass-modal shortcut-edit-dialog ytp-plus-shortcut-modal", i.setAttribute("role", "dialog"), i.setAttribute("aria-modal", "true"); const c = a.shortcuts; t.renderTemplateClone(i, `\n <div class="glass-panel shortcut-edit-content">\n <h4>${window.YouTubeSafeDOM.escapeHTML(e("editShortcut"))}: ${window.YouTubeSafeDOM.escapeHTML(c[o]?.description || o)}</h4>\n <p>${window.YouTubeSafeDOM.escapeHTML(e("pressAnyKey"))}</p>\n <div class="current-shortcut">${window.YouTubeSafeDOM.escapeHTML(e("current"))}: <kbd>${window.YouTubeSafeDOM.escapeHTML(" " === r ? "Space" : r)}</kbd></div>\n <button class="ytp-plus-button ytp-plus-button-primary shortcut-cancel" type="button">${window.YouTubeSafeDOM.escapeHTML(e("cancel"))}</button>\n </div>\n `), document.body.appendChild(i), s.editingShortcut = o; const u = t => { if (t.preventDefault(), t.stopPropagation(), "Escape" === t.key) { return y(); } Object.keys(a.shortcuts).find(e => e !== o && a.shortcuts[e]?.key === t.key) ? d.show(e("keyAlreadyUsed", { key: t.key })) : (a.shortcuts[o].key = t.key, l.saveSettings(), d.show(e("shortcutUpdated")), p.refresh(), y()); }, y = () => { document.removeEventListener("keydown", u, !0), i.remove(), s.editingShortcut = null; }, m = i.querySelector(".shortcut-cancel"); m && (m.onclick = y), i.onclick = t => { t && t.target === i && y(); }, YouTubeUtils.cleanupManager.registerListener(document, "keydown", u, !0); }, m = () => { s.downloadButton?.isConnected && s.downloadButton.remove(), s.downloadButton = null; }, f = () => { if (!h()) { return void m(); } const o = window.youtubePlus?.settings; if (!1 === o?.enableDownload) { return void m(); } const i = () => r("ytd-reel-video-renderer[is-active]") || r('ytd-reel-video-renderer[is-active="true"]') || r("#shorts-player ytd-reel-video-renderer"), a = (() => { const t = i(), e = [ "ytwReelActionBarViewModelHostDesktop", "ytwReelActionBarViewModelHost", '[class*="ytwReelActionBarViewModelHostDesktop"]', '[class*="ytwReelActionBarViewModelHost"]', ".ytwReelActionBarViewModelHostDesktop", ".ytwReelActionBarViewModelHost", "reel-action-bar-view-model", "ytd-reel-player-overlay-renderer #actions", "#actions" ], o = t => { for (const o of e) { const e = t.querySelectorAll(o); for (const t of e) { if (t instanceof HTMLElement && null !== t.offsetParent) { return t; } } } return null; }; if (t instanceof Element) { const e = o(t); if (e) { return e; } } const r = o(document); if (r) { return r; } if (t instanceof Element) { for (const o of e) { const e = t.querySelector(o); if (e instanceof HTMLElement) { return e; } } } return null; })(), c = a ? (t => { if (!(t instanceof Element)) { return null; } const e = [ "like-button-view-model", "#like-button", 'button[aria-label*="Like" i]', 'button[aria-label*="Нравится" i]' ]; for (const o of e) { const e = t.querySelector(o); if (e instanceof HTMLElement) { return e; } } return null; })(a) : (() => { const t = [ "like-button-view-model", "#like-button", 'button[aria-label*="Like" i]', 'button[aria-label*="Нравится" i]' ], e = i(); if (e instanceof Element) { for (const o of t) { const t = e.querySelector(o); if (t instanceof HTMLElement && null !== t.offsetParent) { return t; } } } for (const e of t) { const t = document.querySelector(e); if (t instanceof HTMLElement && null !== t.offsetParent) { return t; } } return null; })(), l = c?.closest('like-button-view-model, #like-button, reel-action-view-model, ytw-reel-action-view-model, [class*="ReelActionViewModel"]') || c; if (!a && !l) { return; } if (s.downloadButton?.isConnected && l instanceof Element && s.downloadButton.nextElementSibling === l) { return; } s.downloadButton?.isConnected && (s.downloadButton.remove(), s.downloadButton = null); const u = document.createElement("button"); if (u.className = "ytp-plus-shorts-download", u.type = "button", u.setAttribute("aria-label", e("download")), u.setAttribute("title", e("downloadOptions") || e("download")), t.renderTemplateClone(u, '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path opacity="0.5" d="M3 15C3 17.8284 3 19.2426 3.87868 20.1213C4.75736 21 6.17157 21 9 21H15C17.8284 21 19.2426 21 20.1213 20.1213C21 19.2426 21 17.8284 21 15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3V16M12 16L16 11.625M12 16L8 11.625" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>'), u.addEventListener("click", t => { t.preventDefault(), t.stopPropagation(), "function" != typeof window.YouTubePlusDownload?.openModal ? d.show(e("directDownloadModuleNotAvailable") || e("downloadNotAvailable")) : window.YouTubePlusDownload.openModal(); }), l instanceof Element && l.parentElement) { l.insertAdjacentElement("beforebegin", u); } else { if (!a) { return; } a.prepend(u); } s.downloadButton = u; }, b = t => { if (!a.enabled || !l.isInShortsPage() || l.isInputFocused() || s.editingShortcut) { return; } let {key: e} = t; "NumpadAdd" === t.code ? e = "+" : "NumpadSubtract" === t.code && (e = "-"); const o = Object.keys(a.shortcuts).find(t => a.shortcuts[t]?.key === e); o && u[o] && (t.preventDefault(), t.stopPropagation(), u[o]()); }, h = () => location.pathname.startsWith("/shorts/"), g = () => { h() && (s.initialized || (s.initialized = !0, l.loadSettings(), (() => { const t = window.YouTubePlusDesignSystem?.getStyle?.("shorts-keyboard-styles") || "", e = YouTubeUtils?.StyleManager; e && "function" == typeof e.add && e.add("shorts-keyboard-styles", t); })(), f(), s.downloadObserver || (s.downloadObserver = new MutationObserver(() => { h() && (s.downloadEnsureQueued || (s.downloadEnsureQueued = !0, requestAnimationFrame(() => { s.downloadEnsureQueued = !1, f(); }))); }), s.downloadObserver.observe(document.body, { childList: !0, subtree: !0 }), YouTubeUtils.cleanupManager?.registerObserver && YouTubeUtils.cleanupManager.registerObserver(s.downloadObserver)), YouTubeUtils.cleanupManager.registerListener(document, "keydown", b, !0), YouTubeUtils.cleanupManager.registerListener(document, "click", t => { const e = t.target instanceof Element ? t.target : null; s.helpVisible && e?.closest && !e.closest("#shorts-keyboard-help") && p.hide(); }), YouTubeUtils.cleanupManager.registerListener(document, "keydown", t => { "Escape" === t.key && s.helpVisible && (t.preventDefault(), p.hide()); }))); }, w = () => { let t = location.pathname, e = h(); const o = () => { const o = location.pathname; if (o === t) { return; } t = o; const r = h(); r !== e ? (e = r, !r && s.initialized ? s.initialized && (s.helpVisible && p.hide(), s.actionTimeout && (clearTimeout(s.actionTimeout), s.actionTimeout = null), s.cachedVideo = null, s.downloadObserver && (s.downloadObserver.disconnect(), s.downloadObserver = null), s.downloadEnsureQueued = !1, m(), s.initialized = !1) : r && !s.initialized && g()) : r && f(); }; YouTubeUtils.cleanupManager?.registerListener ? (YouTubeUtils.cleanupManager.registerListener(window, "yt-navigate-finish", o), YouTubeUtils.cleanupManager.registerListener(window, "popstate", o)) : (window.addEventListener("yt-navigate-finish", o), window.addEventListener("popstate", o)); }; let v = !1; const x = () => { v || (v = !0, "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", () => { g(), w(); }, { once: !0 }) : (g(), w()), h() && !localStorage.getItem("shorts_keyboard_help_shown") && i(() => { h() && (d.show("Press ? for shortcuts"), localStorage.setItem("shorts_keyboard_help_shown", "true")); }, 2e3)); }; t?.whenRelevant ? t.whenRelevant({ name: "shorts", isRelevant: h, onEnter: x }) : h() && x(); })(), (function() { const t = window.YouTubeUtils; if (t?.StyleManager?.add?.("ytp-stats-styles", window.YouTubePlusDesignSystem?.getStyle?.("ytp-stats-styles") || ""), window.__ytpVideoStatsModuleInit) { return; } const e = () => t.isSettingsModalOpen(), o = () => { function o() { try { const t = window.location.href; let e = ""; return t.includes("/channel/") ? e = t.split("/channel/")[1].split("/")[0] : t.includes("/@") && (e = t.split("/@")[1].split("/")[0]), e && /^[a-zA-Z0-9_-]+$/.test(e) ? e : ""; } catch (e) { return t?.logError?.("Stats", "Failed to get channel identifier", e), ""; } } function r(t) { return t?.tabRenderer?.endpoint?.commandMetadata?.webCommandMetadata?.url || null; } function i(t, e) { return "string" == typeof t && e.test(t); } function a(t, e) { return t && e; } function s(t, e) { !e.hasStreams && (function(t) { return i(t, /\/streams$/); })(t) && (e.hasStreams = !0), !e.hasShorts && (function(t) { return i(t, /\/shorts$/); })(t) && (e.hasShorts = !0); } async function c(e) { if (!Y && (function(e) { if (!e || "string" != typeof e) { return !1; } try { const t = new URL(e); return "www.youtube.com" === t.hostname || "youtube.com" === t.hostname || (window.YouTubePlusLogger?.warn?.("Stats", "Invalid domain for channel check"), !1); } catch (e) { return t?.logError?.("Stats", "Invalid URL for channel check", e), !1; } })(e) && W.canRequest("checkChannelTabs")) { Y = !0; try { const o = await (async function(t) { try { const e = new URL(t).hostname.toLowerCase(); if ("www.youtube.com" !== e && "youtube.com" !== e && "m.youtube.com" !== e) { return window.YouTubePlusLogger?.warn?.("Stats", "Blocked fetch to non-YouTube URL:", e), null; } } catch (t) { return null; } const e = new AbortController, o = _(() => e.abort(), 1e4); try { const r = await fetch(t, { credentials: "same-origin", signal: e.signal, headers: { Accept: "text/html" } }); if (clearTimeout(o), !r.ok) { return window.YouTubePlusLogger?.warn?.("Stats", `HTTP ${r.status} when checking channel tabs`), null; } const i = await r.text(); return i.length > 5e6 ? (window.YouTubePlusLogger?.warn?.("Stats", "Response too large, skipping parse"), null) : i; } catch (t) { throw "AbortError" === t.name && window.YouTubePlusLogger?.warn?.("Stats", "Channel check timed out"), t; } })(e); if (!o) { return; } const i = (function(e) { const o = e.match(/var ytInitialData = (.+?);<\/script>/); if (!o?.[1]) { return null; } try { return JSON.parse(o[1]); } catch (e) { return t?.logError?.("Stats", "Failed to parse ytInitialData", e), null; } })(o); if (!i) { return; } const c = (function(t) { const e = t?.contents?.twoColumnBrowseResultsRenderer?.tabs || [], o = { hasStreams: !1, hasShorts: !1 }; for (const t of e) { const e = r(t); if (e && (s(e, o), a(o.hasStreams, o.hasShorts))) { break; } } return o; })(i); (c.hasStreams || c.hasShorts) && window.YouTubePlusLogger?.info?.("Stats", "Channel tabs:", { hasStreams: c.hasStreams, hasShorts: c.hasShorts }), (function() { const t = I(".stats-menu-container"); t && (t.remove(), M()); })(); } catch (e) { t?.logError?.("Stats", "Channel tab check failed", e); } finally { Y = !1; } } } function l(t, e, o, r, i) { const a = document.createElement("button-view-model"); a.className = `yt-spec-button-view-model ${r}-view-model`; const s = document.createElement("button"); s.className = `yt-spec-button-shape-next yt-spec-button-shape-next--outline yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--enable-backdrop-filter-experiment ${r}-button`, s.setAttribute("aria-disabled", "false"), s.setAttribute("aria-label", t), s.classList.add("ytp-stats-btn"), s.addEventListener("click", t => { t.preventDefault(), t.stopPropagation(), i(); }); const c = document.createElementNS("http://www.w3.org/2000/svg", "svg"); c.setAttribute("viewBox", o), c.classList.add("ytp-stats-icon"); const l = document.createElementNS("http://www.w3.org/2000/svg", "path"); l.setAttribute("d", e), c.appendChild(l); const d = document.createElement("div"); d.className = `yt-spec-button-shape-next__button-text-content ${r}-text`, d.textContent = t, d.classList.add("ytp-stats-btn-text"); const u = document.createElement("yt-touch-feedback-shape"); u.classList.add("ytp-stats-touch-feedback"); const p = document.createElement("div"); p.className = "yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response", p.setAttribute("aria-hidden", "true"); const y = document.createElement("div"); y.className = "yt-spec-touch-feedback-shape__stroke"; const m = document.createElement("div"); return m.className = "yt-spec-touch-feedback-shape__fill", p.appendChild(y), p.appendChild(m), u.appendChild(p), s.appendChild(c), s.appendChild(d), s.appendChild(u), a.appendChild(s), a; } function d() { try { if (void 0 !== window.ytcfg && "function" == typeof window.ytcfg.get) { const t = window.ytcfg.get("INNERTUBE_API_KEY"); if (t && "string" == typeof t) { return t; } } if (window.ytcfg?.data_?.INNERTUBE_API_KEY) { return window.ytcfg.data_.INNERTUBE_API_KEY; } if (window.yt?.config_?.INNERTUBE_API_KEY) { return window.yt.config_.INNERTUBE_API_KEY; } } catch (t) {} try { return window.atob(X); } catch (t) { return ""; } } function u() { try { if (void 0 !== window.ytcfg && "function" == typeof window.ytcfg.get) { const t = window.ytcfg.get("INNERTUBE_CLIENT_VERSION"); if (t && "string" == typeof t) { return t; } } if (window.ytcfg?.data_?.INNERTUBE_CLIENT_VERSION) { return window.ytcfg.data_.INNERTUBE_CLIENT_VERSION; } if (window.yt?.config_?.INNERTUBE_CLIENT_VERSION) { return window.yt.config_.INNERTUBE_CLIENT_VERSION; } } catch (t) {} return Q; } function p(t) { return { context: { client: { clientName: "WEB", clientVersion: u(), hl: "en", gl: "US" } }, videoId: t }; } function y(t) { const e = t.thumbnail?.thumbnails; return e?.[e.length - 1]?.url || null; } function m() { try { const t = window.YouTubeStatsHelpers || {}, e = { extractViews() { try { const t = I("yt-view-count-renderer, #count .view-count"), e = (t?.textContent ? t.textContent.trim() : "").replace(/[^0-9,.]/g, "").replace(/,/g, ""); return e ? { views: Number(e) || null } : {}; } catch (t) { return {}; } }, extractLikes() { try { const t = I("ytd-toggle-button-renderer[is-icon-button] yt-formatted-string") || I("#top-level-buttons-computed ytd-toggle-button-renderer:first-child yt-formatted-string"), e = (t?.textContent ? t.textContent.trim() : "").replace(/[^0-9,.]/g, "").replace(/,/g, ""); return e ? { likes: Number(e) || null } : {}; } catch (t) { return {}; } }, extractDislikes: () => ({}), extractComments() { try { const t = I("#count > ytd-comment-thread-renderer, ytd-comments-header-renderer #count"), e = (t?.textContent ? t.textContent.trim() : "").replace(/[^0-9,.]/g, "").replace(/,/g, ""); return e ? { comments: Number(e) || null } : {}; } catch (t) { return {}; } }, extractSubscribers() { try { const t = I("#owner-sub-count, #subscriber-count"), e = t?.textContent ? t.textContent.trim() : ""; return e ? { subscribers: e } : {}; } catch (t) { return {}; } }, extractThumbnail() { try { const t = I('link[rel="image_src"]') || I('meta[property="og:image"]'), e = t && (t.href || t.content) ? t.href || t.content : null; return e ? { thumbnail: e } : {}; } catch (t) { return {}; } }, extractTitle() { try { const t = I("h1.title yt-formatted-string") || I("h1"), e = t?.textContent ? t.textContent.trim() : ""; return e ? { title: e } : {}; } catch (t) { return {}; } }, extractAuthor() { try { const t = I("ytd-video-owner-renderer #channel-handle") || I("ytd-video-owner-renderer yt-formatted-string.ytd-channel-name a") || I("#owner ytd-channel-name a") || I("ytd-video-owner-renderer #owner-name a"), e = t?.textContent?.trim() || "", o = e.startsWith("@") ? e : null, r = I("ytd-video-owner-renderer #channel-name") || I("ytd-video-owner-renderer #owner-name"), i = r?.textContent?.trim() || null; return o || i ? { authorHandle: o, author: i } : {}; } catch (t) { return {}; } } }, o = t?.extractViews ? t : e, r = Object.assign({}, o.extractViews?.() || {}, o.extractLikes?.() || {}, o.extractDislikes?.() || {}, o.extractComments?.() || {}, o.extractSubscribers?.() || {}, o.extractThumbnail?.() || {}, o.extractTitle?.() || {}, o.extractAuthor?.() || {}); return Object.keys(r).length > 0 ? r : null; } catch (e) { return t?.logError?.("Stats", "Failed to read page stats", e), null; } } function f(t, e = "", o = { showValue: !0, showIcon: !0 }) { const {showValue: r, showIcon: i} = o; if (!r && !i) { return ""; } let a = ""; r && (a = t ?? j("unknown")); let s = "", c = ""; return i && (e && "string" == typeof e && e.indexOf("<") >= 0 ? s = e : e && "string" == typeof e && (c = ` ${e}`)), `\n <div class="stats-card">\n <div class="stats-icon${c}">${s}</div>\n <div class="stats-info">\n ${r ? `<div class="stats-value">${a}</div>` : ""}\n </div>\n </div>\n `; } function b(t) { if (!t || Number.isNaN(t)) { return "0"; } const e = Math.abs(t); return e >= 1e9 ? `${(t / 1e9).toFixed(1)}B` : e >= 1e6 ? `${(t / 1e6).toFixed(1)}M` : e >= 1e3 ? `${(t / 1e3).toFixed(1)}K` : t.toLocaleString(); } function h(t, e, o, r, i) { const a = null == e ? j("unknown") : b(e); let s = "—"; if (null != o) { const t = Number(o); s = Number.isNaN(t) ? String(o) : Math.floor(t).toLocaleString(); } return `\n <div class="stats-card">\n <div class="stats-icon ${r}">\n ${i}\n </div>\n <div class="stats-info">\n <div class="stats-label">${j(t)}</div>\n <div class="stats-value">${a}</div>\n <div class="stats-exact">${s}</div>\n </div>\n </div>\n `; } function g(t, ...e) { for (const o of e) { if (null != t?.[o]) { return t[o]; } } return null; } function w(t, e) { const o = t?.thumbnail; if (o) { try { const t = new URL(o), e = t.hostname; if ("https:" === t.protocol && ("ytimg.com" === e || e.endsWith(".ytimg.com") || "ggpht.com" === e || e.endsWith(".ggpht.com") || "googleusercontent.com" === e || e.endsWith(".googleusercontent.com") || "youtube.com" === e || e.endsWith(".youtube.com"))) { return o; } } catch (t) {} } return e ? `https://i.ytimg.com/vi/${e}/hqdefault.jpg` : ""; } function v(t, e) { const o = window.YouTubeStatsHelpers || {}, r = t?.duration ?? e?.duration ?? o.getDurationFromSources?.(t, e) ?? null, i = t?.country ?? e?.country ?? o.getCountryFromSources?.(t, e) ?? null; let a = null; return a = null != t?.monetized ? j(!0 === t.monetized ? "yes" : "no") : null != e?.monetized ? j(!0 === e.monetized ? "yes" : "no") : o.getMonetizationFromSources?.(t, e, j) ?? null, { duration: r, country: i, monetization: a }; } async function x(e, o) { if (!e || !o) { return void window.YouTubePlusLogger?.error?.("Stats", "Invalid parameters for modal"); } const r = A(".stats-modal-overlay"); for (let t = 0; t < r.length; t++) { try { r[t].remove(); } catch (t) {} } const i = document.createElement("div"); i.className = "stats-modal-overlay ytp-plus-modal-overlay"; const {body: a, container: s} = (function(t) { const e = document.createElement("div"); e.className = "stats-modal-container", e.setAttribute("role", "dialog"), e.setAttribute("aria-modal", "true"), e.setAttribute("aria-label", j("videoStats") || "Video Statistics"); const o = document.createElement("div"); o.className = "stats-modal-content ytp-plus-modal-content"; const r = document.createElement("div"); r.className = "stats-modal-body", r.appendChild((function() { const t = document.createElement("div"); return t.className = "stats-loader", z(t, `\n <svg class="stats-spinner" viewBox="0 0 50 50">\n <circle cx="25" cy="25" r="20" fill="none" stroke="currentColor" stroke-width="4"></circle>\n </svg>\n <p>${j("loadingStats")}</p>\n `), t; })()), o.appendChild(r); const i = document.createElement("div"); i.className = "thumbnail-modal-wrapper"; const a = document.createElement("div"); return a.className = "thumbnail-modal-actions", a.appendChild((function(t) { const e = document.createElement("button"); return e.className = "stats-modal-close thumbnail-modal-action-btn ytp-plus-settings-close", e.setAttribute("data-shared-close-button", "ytp-plus-close-settings"), z(e, '\n <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 9.50002L9.5 14.5M9.49998 9.5L14.5 14.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path></svg>\n '), e.title = j("closeButton") || j("close"), e.setAttribute("aria-label", j("closeButton") || j("close")), e.addEventListener("click", e => { e.preventDefault(), e.stopPropagation(), t.remove(); }), e; })(t)), i.appendChild(o), i.appendChild(a), e.appendChild(i), { body: r, container: e }; })(i); i.appendChild(s), (function(e) { const o = document.activeElement; if (e.addEventListener("click", r => { const {target: i} = r; if (i === e) { e.remove(); try { o && o.focus(); } catch (e) { t.logSuppressed(e, "Stats"); } } }), window.addEventListener("keydown", function r(i) { if ("Escape" === i.key) { e.remove(), window.removeEventListener("keydown", r, !0); try { o && o.focus(); } catch (e) { t.logSuppressed(e, "Stats"); } } }, !0), requestAnimationFrame(() => { const t = e.querySelector('button, [tabindex="0"]'); t && t.focus(); }), window.YouTubePlusModalHandlers?.createFocusTrap) { const t = window.YouTubePlusModalHandlers.createFocusTrap(e), o = window.YouTubePlusMutationCoordinator; if (o?.subscribeRoot) { const r = `stats::overlayTrap::${Date.now()}::${Math.random().toString(36).slice(2, 8)}`; o.subscribeRoot(r, () => { e.isConnected || (t(), o.unsubscribe(r)); }, { selector: null, childList: !0, attributes: !1, subtree: !0 }); } } })(i), document.body.appendChild(i); const c = await (async function(e, o) { if (!o) { return { ok: !1, status: 0, data: null }; } try { if ("video" === e) { const t = await (async function(t) { if (!t) { return null; } try { const e = `https://www.youtube.com/youtubei/v1/player?key=${d()}&prettyPrint=false`, o = await fetch(e, (function(t) { return { method: "POST", headers: { "Content-Type": "application/json", "X-YouTube-Client-Name": "1", "X-YouTube-Client-Version": u() }, body: JSON.stringify(p(t)) }; })(t)); if (!o.ok) { return window.YouTubePlusLogger?.warn?.("Stats", "InnerTube API failed:", o.status), null; } const r = (function(t) { const e = t.videoDetails || {}, o = t.microformat?.playerMicroformatRenderer || {}, r = (o.ownerProfileUrl || o.ownerUrls?.[0] || "").match(/\/@([\w.-]+)/); return { videoId: e.videoId, title: e.title, author: e.author || null, authorHandle: r ? `@${r[1]}` : null, views: e.viewCount ? parseInt(e.viewCount, 10) : null, likes: null, thumbnail: y(e), duration: e.lengthSeconds, country: null, monetized: void 0 !== o.isFamilySafe, channelId: e.channelId }; })(await o.json()); return r.channelId && (r.country = await (async function(t) { if (!t) { return null; } try { const e = `https://www.youtube.com/youtubei/v1/browse?key=${d()}&prettyPrint=false`, o = { browseId: t, context: { client: { clientName: "WEB", clientVersion: u(), hl: "en", gl: "US" } } }, r = await fetch(e, { method: "POST", headers: { "Content-Type": "application/json", "X-YouTube-Client-Name": "1", "X-YouTube-Client-Version": u() }, body: JSON.stringify(o) }); if (!r.ok) { return null; } const i = await r.json(); return i?.header?.c4TabbedHeaderRenderer?.country || i?.header?.pageHeaderRenderer?.content?.pageHeaderViewModel?.metadata?.contentMetadataViewModel?.metadataRows?.[0]?.metadataParts?.find?.(t => 2 === t?.text?.content?.length)?.text?.content || (() => { const t = i?.frameworkUpdates?.entityBatchUpdate?.mutations || []; for (const e of t) { const t = e?.payload?.channelHeaderMetadataEntityViewModel?.country || e?.payload?.channelBasicInfoEntityViewModel?.country; if (t) { return t; } } return null; })() || null; } catch (t) { return null; } })(r.channelId)), r; } catch (t) { return window.YouTubePlusLogger?.error?.("Stats", "InnerTube fetch error:", t), null; } })(o); if (!t) { return { ok: !1, status: 404, data: null }; } const e = await (async function(t) { if (!t) { return null; } await new Promise(t => { "function" == typeof requestIdleCallback ? requestIdleCallback(t, { timeout: 3e3 }) : setTimeout(t, 0); }); try { const e = await fetch(`https://returnyoutubedislikeapi.com/votes?videoId=${t}`); if (!e.ok) { return null; } const o = await e.json(); return { likes: o.likes || null, dislikes: o.dislikes || null, rating: o.rating || null }; } catch (t) { return window.YouTubePlusLogger?.error?.("Stats", "Failed to fetch dislikes:", t), null; } })(o); return e && (t.likes = e.likes, t.dislikes = e.dislikes, t.rating = e.rating), { ok: !0, status: 200, data: t }; } const t = `https://api.livecounts.io/youtube-live-subscriber-counter/stats/${o}`, r = await fetch(t, { method: "GET", headers: { Accept: "application/json" } }); if (!r.ok) { return window.YouTubePlusLogger?.warn?.("Stats", `Failed to fetch ${e} stats:`, r.status), { ok: !1, status: r.status, data: null, url: t }; } const i = await r.json(); return { ok: !0, status: r.status, data: i, url: t }; } catch (o) { return t?.logError?.("Stats", `Failed to fetch ${e} stats`, o), { ok: !1, status: 0, data: null }; } })(e, o); c?.ok ? (function(t, e, o, r) { if ("video" === e) { try { L(t, (function(t, e) { if (!e) { return t || {}; } const o = (...o) => { for (const e of o) { if (null != t?.[e]) { return t[e]; } } for (const t of o) { if (null != e?.[t]) { return e[t]; } } return null; }; return { ...t, views: o("views", "viewCount"), likes: o("likes", "likeCount"), dislikes: o("dislikes"), comments: o("comments", "commentCount"), thumbnail: o("thumbnail"), title: o("title"), liveViewer: o("liveViewer"), duration: o("duration"), country: o("country"), monetized: o("monetized", "isMonetized", "monetization"), author: o("author"), authorHandle: o("authorHandle") }; })(o, m()), r); } catch (e) { L(t, o, r); } } else { !(function(t, e) { const {liveSubscriber: o, liveViews: r, liveVideos: i} = e; z(t, `\n <div class="stats-grid">\n <div class="stats-card">\n <div class="stats-icon stats-icon-subscribers">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>\n <circle cx="9" cy="7" r="4"></circle>\n <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>\n <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>\n </svg>\n </div>\n <div class="stats-info">\n <div class="stats-label">${j("subscribers")}</div>\n <div class="stats-value">${b(o)}</div>\n <div class="stats-exact">${(o || 0).toLocaleString()}</div>\n </div>\n </div>\n\n <div class="stats-card">\n <div class="stats-icon stats-icon-views">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>\n <circle cx="12" cy="12" r="3"></circle>\n </svg>\n </div>\n <div class="stats-info">\n <div class="stats-label">${j("totalViews")}</div>\n <div class="stats-value">${b(r)}</div>\n <div class="stats-exact">${(r || 0).toLocaleString()}</div>\n </div>\n </div>\n\n <div class="stats-card">\n <div class="stats-icon stats-icon-videos">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <polygon points="23 7 16 12 23 17 23 7"></polygon>\n <rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect>\n </svg>\n </div>\n <div class="stats-info">\n <div class="stats-label">${j("totalVideos")}</div>\n <div class="stats-value">${b(i)}</div>\n <div class="stats-exact">${(i || 0).toLocaleString()}</div>\n </div>\n </div>\n </div>\n `); })(t, o); } })(a, e, c.data, o) : (function(t, e, o) { const r = m(); r ? (function(t, e, o) { const r = `<div class="stats-grid">${(function(t) { return [ { value: t.views, key: "views", icon: "stats-icon-views", svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>' }, { value: t.likes, key: "likes", icon: "stats-icon-likes", svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path></svg>' }, { value: t.dislikes, key: "dislikes", icon: "stats-icon-dislikes", svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"></path></svg>' }, { value: t.comments, key: "comments", icon: "stats-icon-comments", svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>' } ].map(t => { return null == (e = t.value) ? "" : `\n <div class="stats-card">\n <div class="stats-icon ${t.icon}">\n ${t.svg}\n </div>\n <div class="stats-info">\n <div class="stats-label">${j(t.key)}</div>\n <div class="stats-value">${b(Number(e))}</div>\n <div class="stats-exact">${(e || 0).toLocaleString()}</div>\n </div>\n </div>\n `; var e; }).filter(t => t); })(e).join("")}</div>`, i = e?.title || document.title || "", a = Z(i), s = a ? `<div class="stats-thumb-title-centered">${a}</div>` : "", c = w(e, o), l = v(null, e); z(t, c ? (function(t, e, o, r) { const i = (function(t) { const e = t.monetization || j("unknown"), o = t.country || j("unknown"), r = t.duration || j("unknown"); return `${f(e, "stats-icon-subscribers", { showValue: !1, showIcon: !0 })}${f(o, "stats-icon-views", { showValue: !1, showIcon: !0 })}${f(r, "stats-icon-videos", { showValue: !0, showIcon: !1 })}`; })(r); return `${t}<div class="stats-thumb-row"><div class="stats-thumb-left"><img class="stats-thumb-img" src="${e}" alt="thumbnail"><div class="stats-thumb-extras">${i}</div></div>${o}</div>`; })(s, c, r, l) : `${s}${r}`); })(t, r, o) : (function(t, e) { const o = e?.status ? ` (${e.status})` : "", r = e?.url ? `<div style="margin-top:8px;font-size:12px;opacity:0.8;word-break:break-all">${e.url}</div>` : ""; z(t, `\n <div class="stats-error">\n <svg class="stats-error-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <circle cx="12" cy="12" r="10"></circle>\n <line x1="12" y1="8" x2="12" y2="12"></line>\n <line x1="12" y1="16" x2="12.01" y2="16"></line>\n </svg>\n <p>${j("failedToLoadStats")}${o}</p>\n ${r}\n </div>\n `); })(t, e); })(a, c, o); } function k(t, e) { const o = t.monetization || j("unknown"); return `<div class="stats-card" style="padding:10px;"><div class="stats-icon stats-icon-subscribers">${t.monetization === j("yes") || !0 === e?.monetized ? '<svg viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path></svg>' : '<svg viewBox="0 0 24 24" fill="none" stroke="#ef4444" stroke-width="2"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>'}</div><div class="stats-info"><div class="stats-label" style="font-size:12px;">${j("monetization")}</div><div class="stats-value" style="font-size:16px;">${o}</div></div></div>`; } function S(t) { const e = Z(t.country || j("unknown")), o = t.country && t.country !== j("unknown") ? t.country.toUpperCase() : "", r = /^[A-Z]{2}$/.test(o) ? o : ""; return r ? `<div class="stats-card" style="padding:10px;"><div class="stats-icon stats-icon-views" data-fallback-icon="globe"><img class="country-flag" src="https://cdn.jsdelivr.net/gh/lipis/[email protected]/flags/4x3/${r.toLowerCase()}.svg" alt="${r}" width="32" height="24" style="border-radius:4px;"/></div><div class="stats-info"><div class="stats-label" style="font-size:12px;">${j("country")}</div><div class="stats-value" style="font-size:16px;">${r}</div></div></div>` : `<div class="stats-card" style="padding:10px;"><div class="stats-icon stats-icon-views"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg></div><div class="stats-info"><div class="stats-label" style="font-size:12px;">${j("country")}</div><div class="stats-value" style="font-size:16px;">${e}</div></div></div>`; } function T(t) { const e = t?.duration ?? null, o = (function(t) { function e(t) { return String(t).padStart(2, "0"); } function o(t) { t = Math.max(0, Math.floor(Number(t) || 0)); const o = Math.floor(t / 3600), r = Math.floor(t % 3600 / 60), i = t % 60; return o > 0 ? `${o}:${e(r)}:${e(i)}` : `${r}:${e(i)}`; } if (null == t) { return null; } if ("number" == typeof t && Number.isFinite(t)) { return o(t); } if ("string" == typeof t) { const r = t.trim(); if (/^\d+$/.test(r)) { return o(Number(r)); } if (r.length > 2 && "P" === r[0].toUpperCase() && "T" === r[1].toUpperCase()) { let t = 0, e = 0, i = 0, a = "", s = !0; for (let o = 2; o < r.length; o += 1) { const c = r[o]; if (c >= "0" && c <= "9") { a += c; continue; } if (!a) { s = !1; break; } const l = parseInt(a, 10); if (a = "", "H" === c || "h" === c) { t = l; } else if ("M" === c || "m" === c) { e = l; } else { if ("S" !== c && "s" !== c) { s = !1; break; } i = l; } } if (s && "" === a) { return o(3600 * t + 60 * e + i); } } const i = r.split(":"); if ((2 === i.length || 3 === i.length) && i.every(t => t.length > 0 && /^\d+$/.test(t)) && i.slice(1).every(t => t.length <= 2)) { const t = i.map(t => { const e = t.replace(/^0+/, ""); return "" === e ? "0" : e; }); if (2 === t.length) { const [o, r] = t; return `${Number(o)}:${e(Number(r))}`; } if (3 === t.length) { const [o, r, i] = t; return `${Number(o)}:${e(Number(r))}:${e(Number(i))}`; } } return r || null; } return null; })(e) || (e ? String(e) : null) || j("unknown"); return `<div class="stats-card" style="padding:10px;"><div class="stats-icon stats-icon-videos"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg></div><div class="stats-info"><div class="stats-label" style="font-size:12px;">${j("duration")}</div><div class="stats-value" style="font-size:16px;">${o}</div></div></div>`; } function L(t, e, o) { const r = (function(t, e) { return { views: g(t, "liveViews", "views", "viewCount"), likes: g(t, "liveLikes", "likes", "likeCount"), dislikes: g(t, "dislikes", "liveDislikes", "dislikeCount"), comments: g(t, "liveComments", "comments", "commentCount"), liveViewer: g(t, "liveViewer", "live_viewers"), title: t?.title || document.title || "", thumbUrl: w(t, e), country: g(t, "country"), monetized: t?.monetized ?? null, duration: g(t, "duration"), author: g(t, "author"), authorHandle: g(t, "authorHandle") }; })(e, o), {liveViewer: i, title: a, thumbUrl: s} = r, c = Z(a), l = c ? `<div class="stats-thumb-title-centered">${c}</div>` : "", d = (function(t) { const {views: e, likes: o, dislikes: r, comments: i} = t; return [ { label: "views", value: e, exact: e, iconClass: "stats-icon-views", iconSvg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>' }, { label: "likes", value: o, exact: o, iconClass: "stats-icon-likes", iconSvg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path></svg>' }, { label: "dislikes", value: r, exact: r, iconClass: "stats-icon-dislikes", iconSvg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"></path></svg>' }, { label: "comments", value: i, exact: i, iconClass: "stats-icon-comments", iconSvg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>' } ]; })(r), u = d.find(t => "views" === t.label), p = d.find(t => "likes" === t.label), y = d.find(t => "dislikes" === t.label), m = d.find(t => "comments" === t.label), f = u ? h(u.label, u.value, u.exact, u.iconClass, u.iconSvg) : "", b = p ? h(p.label, p.value, p.exact, p.iconClass, p.iconSvg) : "", x = y ? h(y.label, y.value, y.exact, y.iconClass, y.iconSvg) : "", L = m ? h(m.label, m.value, m.exact, m.iconClass, m.iconSvg) : "", M = b || x ? `<div class="stats-card-pair">${b}${x}</div>` : "", {author: C, authorHandle: E} = r, _ = C ? Z(String(C)) : "", I = E ? Z(String(E)) : "", P = I || _ ? `<div class="stats-author-big">${I ? `<a class="stats-author-handle-big" href="https://www.youtube.com/${encodeURIComponent(E)}" target="_blank" rel="noopener noreferrer">${I}</a>` : `<span class="stats-author-name-big">${_}</span>`}</div>` : "", j = [ f, M, L ].filter(Boolean), H = (function(t) { return null == t ? "" : h("liveViewers", t, t, "stats-icon-viewers", '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>'); })(i); H && j.push(H); const D = `<div class="stats-side-column"><div class="stats-grid">${j.join("")}</div>${P}</div>`; if (s) { const o = (function(t, e) { return [ k(e, t), S(e), T(e) ].filter(Boolean).join(""); })(e, v(e, null)); z(t, `${l}<div class="stats-thumb-row"><div class="stats-thumb-left"><img class="stats-thumb-img" src="${s}" alt="thumbnail">${o ? `<div class="stats-thumb-extras" style="display:flex;flex-wrap:wrap;gap:8px;margin-top:12px;">${o}</div>` : ""}</div>${D}</div>`); } else { z(t, `${l}${D}`); } !(function(t) { A(".country-flag", t).forEach(t => { t.addEventListener("error", function() { const t = this.parentElement; t && "globe" === t.dataset.fallbackIcon && (this.style.display = "none", z(t, '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>')); }, { once: !0 }); }); })(t); } function M() { if (!R) { return; } if (I(".stats-menu-container")) { return; } const t = document.createElement("div"); t.className = "yt-flexible-actions-view-model-wiz__action stats-menu-container"; const e = document.createElement("button-view-model"); e.className = "yt-spec-button-view-model main-stats-view-model"; const r = document.createElement("button"); r.className = "yt-spec-button-shape-next yt-spec-button-shape-next--outline yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--enable-backdrop-filter-experiment main-stats-button", r.setAttribute("aria-disabled", "false"), r.setAttribute("aria-label", j("stats")), r.style && (r.style.display = "flex", r.style.alignItems = "center", r.style.justifyContent = "center", r.style.gap = "8px"); const i = document.createElement("span"); z(i, '<svg viewBox="0 0 512 512" style="width:20px;height:20px;fill:currentColor"><path d="M500 89c13.8-11 16-31.2 5-45s-31.2-16-45-5L319.4 151.5 211.2 70.4c-11.7-8.8-27.8-8.5-39.2 .6L12 199c-13.8 11-16 31.2-5 45s31.2 16 45 5L192.6 136.5l108.2 81.1c11.7 8.8 27.8 8.5 39.2-.6L500 89zM160 256l0 192c0 17.7 14.3 32 32 32s32-14.3 32-32l0-192c0-17.7-14.3-32-32-32s-32 14.3-32 32zM32 352l0 96c0 17.7 14.3 32 32 32s32-14.3 32-32l0-96c0-17.7-14.3-32-32-32s-32 14.3-32 32zm288-64c-17.7 0-32 14.3-32 32l0 128c0 17.7 14.3 32 32 32s32-14.3 32-32l0-128c0-17.7-14.3-32-32-32zm96-32l0 192c0 17.7 14.3 32 32 32s32-14.3 32-32l0-192c0-17.7-14.3-32-32-32s-32 14.3-32 32z"/></svg>'); const a = i.firstElementChild, s = document.createElement("div"); s.className = "yt-spec-button-shape-next__button-text-content main-stats-text", s.textContent = j("stats"), s.style && (s.style.display = "flex", s.style.alignItems = "center"); const c = document.createElement("yt-touch-feedback-shape"); c.style && (c.style.borderRadius = "inherit"); const d = document.createElement("div"); d.className = "yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response", d.setAttribute("aria-hidden", "true"); const u = document.createElement("div"); u.className = "yt-spec-touch-feedback-shape__stroke"; const p = document.createElement("div"); p.className = "yt-spec-touch-feedback-shape__fill", d.appendChild(u), d.appendChild(p), c.appendChild(d), a && r.appendChild(a), r.appendChild(s), r.appendChild(c), e.appendChild(r), t.appendChild(e); const y = document.createElement("div"); y.className = "stats-horizontal-menu"; const m = document.createElement("div"); m.className = "stats-menu-button channel-stats-container"; const f = l(j("channel"), "M64 48c-8.8 0-16 7.2-16 16l0 288c0 8.8 7.2 16 16 16l512 0c8.8 0 16-7.2 16-16l0-288c0-8.8-7.2-16-16-16L64 48zM0 64C0 28.7 28.7 0 64 0L576 0c35.3 0 64 28.7 64 64l0 288c0 35.3-28.7 64-64 64L64 416c-35.3 0-64-28.7-64-64L0 64zM120 464l400 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-400 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z", "0 0 640 512", "channel-stats", () => { const t = o(); t && x("channel", t); }); if (m.appendChild(f), y.appendChild(m), G.hasStreams) { const t = document.createElement("div"); t.className = "stats-menu-button live-stats-container"; const e = l(j("live"), "M99.8 69.4c10.2 8.4 11.6 23.6 3.2 33.8C68.6 144.7 48 197.9 48 256s20.6 111.3 55 152.8c8.4 10.2 7 25.3-3.2 33.8s-25.3 7-33.8-3.2C24.8 389.6 0 325.7 0 256S24.8 122.4 66 72.6c8.4-10.2 23.6-11.6 33.8-3.2zm376.5 0c10.2-8.4 25.3-7 33.8 3.2c41.2 49.8 66 113.8 66 183.4s-24.8 133.6-66 183.4c-8.4 10.2-23.6 11.6-33.8 3.2s-11.6-23.6-3.2-33.8c34.3-41.5 55-94.7 55-152.8s-20.6-111.3-55-152.8c-8.4-10.2-7-25.3 3.2-33.8zM248 256a40 40 0 1 1 80 0 40 40 0 1 1 -80 0zm-61.1-78.5C170 199.2 160 226.4 160 256s10 56.8 26.9 78.5c8.1 10.5 6.3 25.5-4.2 33.7s-25.5 6.3-33.7-4.2c-23.2-29.8-37-67.3-37-108s13.8-78.2 37-108c8.1-10.5 23.2-12.3 33.7-4.2s12.3 23.2 4.2 33.7zM427 148c23.2 29.8 37 67.3 37 108s-13.8 78.2-37 108c-8.1 10.5-23.2 12.3-33.7 4.2s-12.3-23.2-4.2-33.7C406 312.8 416 285.6 416 256s-10-56.8-26.9-78.5c-8.1-10.5-6.3-25.5 4.2-33.7s25.5-6.3 33.7 4.2z", "0 0 576 512", "live-stats", () => { const t = o(); t && x("channel", t); }); t.appendChild(e), y.appendChild(t); } if (G.hasShorts) { const t = document.createElement("div"); t.className = "stats-menu-button shorts-stats-container"; const e = l(j("shorts"), "M80 48c-8.8 0-16 7.2-16 16l0 384c0 8.8 7.2 16 16 16l224 0c8.8 0 16-7.2 16-16l0-384c0-8.8-7.2-16-16-16L80 48zM16 64C16 28.7 44.7 0 80 0L304 0c35.3 0 64 28.7 64 64l0 384c0 35.3-28.7 64-64 64L80 512c-35.3 0-64-28.7-64-64L16 64zM160 400l64 0c8.8 0 16 7.2 16 16s-7.2 16-16 16l-64 0c-8.8 0-16-7.2-16-16s7.2-16 16-16z", "0 0 384 512", "shorts-stats", () => { const t = o(); t && x("channel", t); }); t.appendChild(e), y.appendChild(t); } t.appendChild(y); const b = (() => { const t = I("#owner #top-row #buttons, #top-row #owner #buttons, #buttons.ytd-video-owner-renderer"); if (t) { return t; } const e = I(".yt-flexible-actions-view-model-wiz__action:not(.stats-menu-container)"); return e?.parentElement ? e.parentElement : I("#subscribe-button + #buttons"); })(); return b && b.appendChild(t), t; } function C() { if (!R) { return; } const t = I("#owner #top-row #buttons, #top-row #owner #buttons, #buttons.ytd-video-owner-renderer, #subscribe-button + #buttons, .yt-flexible-actions-view-model-wiz__action:not(.stats-menu-container)"), e = I(".stats-menu-container"); t && !e && M(); } function E() { R && (function() { if (!R) { return; } let e = I("ytd-masthead.style-scope"); if (e || (e = I("ytd-masthead")), !e) { return; } let o = I("#end.style-scope.ytd-masthead", e); o || (o = I("#end", e)); const r = A(O); let i = P(D); !i && r.length > 0 && (i = r[0]), r.length > 1 && r.forEach(t => { if (t !== i) { try { t.remove(); } catch (t) {} } }), i ? (i.id = D, i.classList.add("videoStats"), i.setAttribute("data-ytp-stats-icon", "true")) : i = (function() { const e = document.createElement("div"); return e.className = "videoStats", e.id = D, e.setAttribute("data-ytp-stats-icon", "true"), z(e, '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22 22H2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path> <path opacity="0.5" d="M21 22V14.5C21 13.6716 20.3284 13 19.5 13H16.5C15.6716 13 15 13.6716 15 14.5V22" stroke="currentColor" stroke-width="1.5" " data-darkreader-inline-stroke=""></path> <path d="M15 22V5C15 3.58579 15 2.87868 14.5607 2.43934C14.1213 2 13.4142 2 12 2C10.5858 2 9.87868 2 9.43934 2.43934C9 2.87868 9 3.58579 9 5V22" stroke="currentColor" stroke-width="1.5"></path> <path opacity="0.5" d="M9 22V9.5C9 8.67157 8.32843 8 7.5 8H4.5C3.67157 8 3 8.67157 3 9.5V22" stroke="currentColor" stroke-width="1.5"></path></svg>'), e.addEventListener("click", e => { e.preventDefault(), e.stopPropagation(); const o = (function() { try { const t = window.location.href; return t.includes("youtube.com") ? (function() { const t = new URLSearchParams(window.location.search).get("v"); return J(t) ? `https://www.youtube.com/watch?v=${t}` : null; })() || (function(t) { const e = t.match(/\/shorts\/([^?]+)/); return e && J(e[1]) ? `https://www.youtube.com/shorts/${e[1]}` : null; })(t) : null; } catch (e) { return t?.logError?.("Stats", "Failed to get video URL", e), null; } })(); if (o) { const t = new URLSearchParams(new URL(o).search).get("v") || o.match(/\/shorts\/([^?]+)/)?.[1]; t && x("video", t); } }), e; })(), o ? i.parentNode === o && o.firstChild === i || o.insertBefore(i, o.firstChild) : i.parentNode !== e && e.appendChild(i); })(); } if (window.__ytpVideoStatsModuleInit) { return; } window.__ytpVideoStatsModuleInit = !0; const z = t.setSafeHTML, _ = setTimeout.bind(window), I = t.$, A = t.$$, P = t.byId, j = t.t, H = "youtube_stats_button_enabled", D = "ytp-stats-universal-icon", O = `#${D}, .videoStats[data-ytp-stats-icon="true"], .videoStats`, B = window.YouTubeUtils?.safeLS || { getItem: (t, e = null) => { try { return localStorage.getItem(t) ?? e; } catch (t) { return e; } }, setItem: (t, e) => { try { return localStorage.setItem(t, e), !0; } catch (t) { return !1; } }, removeItem: t => { try { localStorage.removeItem(t); } catch (t) {} } }; let R = "false" !== B.getItem(H); const F = () => { try { const t = document.getElementById("ytp-plus-setting-enableStatsButton"); if (!(t instanceof HTMLInputElement)) { return; } if (t.dataset.handlerAttached) { return; } t.dataset.handlerAttached = "true", t.checked = R, t.addEventListener("change", t => { R = t.target.checked, B.setItem(H, R ? "true" : "false"), A(`${O}, .stats-menu-container`).forEach(t => t.remove()), R && (E(), C()); }); } catch (t) {} }; e() && F(), t?.cleanupManager?.registerListener ? t.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", () => { F(); }) : document.addEventListener("youtube-plus-settings-modal-opened", () => { F(); }); let N = !1; const Z = window.YouTubeSafeDOM?.escapeHTML || window.YouTubeSecurityUtils?.escapeHtml || (t => { const e = document.createElement("div"); return e.textContent = t, e.innerHTML; }); let V = location.href, Y = !1, q = null; const G = { hasStreams: !1, hasShorts: !1 }, W = { requests: new Map, maxRequests: 10, maxKeys: 100, timeWindow: 6e4, canRequest: t => { const e = Date.now(), o = (W.requests.get(t) || []).filter(t => e - t < W.timeWindow); if (o.length >= W.maxRequests) { return window.YouTubePlusLogger?.warn?.("Stats", `Rate limit exceeded for ${t}. Max ${W.maxRequests} requests per minute.`), !1; } if (o.push(e), W.requests.set(t, o), W.requests.size > W.maxKeys) { const t = W.requests.keys().next().value; "string" == typeof t && W.requests.delete(t); } return !0; }, clear: () => { W.requests.clear(); } }, J = window.YouTubeSecurityUtils?.isValidVideoId || (t => !!t && /^[a-zA-Z0-9_-]{11}$/.test(t)), K = t?.debounce?.(() => { try { const e = location.href; e !== V && (V = e, t?.isChannelPage?.(e) && setTimeout(() => c(e), 500)); } catch (e) { t?.logError?.("Stats", "URL change check failed", e); } }, 300) || function() { try { const e = location.href; e !== V && (V = e, t?.isChannelPage?.(e) && setTimeout(() => c(e), 500)); } catch (t) { window.YouTubePlusLogger?.error?.("Stats", "URL change check failed:", t); } }, X = "QUl6YVN5QU9fRkoyU2xxVThRNFNURUhMR0NpbHdfWTlfMTFxY1c4", Q = "2.20250312.01.00", tt = t => { const {target: e} = t, o = e, r = o?.closest?.(".ytp-plus-settings-nav-item"); "experimental" === r?.dataset?.section && F(); }; t?.cleanupManager?.registerListener ? t.cleanupManager.registerListener(document, "youtube-plus-language-changed", () => { F(); }) : document.addEventListener("youtube-plus-language-changed", () => { F(); }), q || (t?.cleanupManager?.registerListener ? q = t.cleanupManager.registerListener(document, "click", tt, !0) : (document.addEventListener("click", tt, !0), q = "native-click-listener")); const et = () => { if (N || !(() => { try { const e = location.pathname || ""; return !("/watch" !== e && !e.startsWith("/shorts")) || (t?.isChannelPage?.(location.href) ?? !1); } catch (t) { return !1; } })()) { return; } N = !0; const e = () => { try { t?.isStudioPage?.() || (P("youtube-enhancer-styles") || t.StyleManager.add("youtube-enhancer-styles", "\n .videoStats{width:36px;height:36px;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;margin-left:8px;margin-right:8px;background:none;;border:none;transition:transform .18s ease,background .18s}\n html[dark] .videoStats{background:none;border:none}html:not([dark]) .videoStats{background:none;border:none}.videoStats:hover{transform:translateY(-2px)}.videoStats svg{width:18px;height:18px;fill:var(--yt-spec-text-primary,#030303)}html[dark] .videoStats svg{fill:var(--yt-text-primary)}html:not([dark]) .videoStats svg{fill:var(--yt-text-primary)}\n .shortsStats{display:flex;align-items:center;justify-content:center;margin-top:16px;margin-bottom:16px;width:48px;height:48px;border-radius:50%;cursor:pointer;background:var(--yt-stats-button-bg-light);box-shadow:0 12px 30px var(--yt-stats-shadow-deep);backdrop-filter:blur(10px) saturate(160%);-webkit-backdrop-filter:blur(10px) saturate(160%);border:1.25px solid var(--yt-stats-button-bg-light);transition:transform .22s ease}html[dark] .shortsStats{background:var(--yt-stats-button-bg-dark);border:1.25px solid var(--yt-stats-button-border-dark)}html:not([dark]) .shortsStats{background:var(--yt-stats-button-bg-light);border:1.25px solid var(--yt-stats-button-border-light)}\n .shortsStats:hover{transform:translateY(-3px)}.shortsStats svg{width:24px;height:24px;fill:var(--yt-text-primary)}html[dark] .shortsStats svg{fill:var(--yt-text-primary)}html:not([dark]) .shortsStats svg{fill:var(--yt-text-primary)}\n .stats-menu-container{position:relative;display:inline-block}.stats-horizontal-menu{position:absolute;display:flex;left:100%;top:0;height:100%;visibility:hidden;opacity:0;transition:visibility 0s,opacity 0.2s linear;z-index:100}.stats-menu-container:hover .stats-horizontal-menu{visibility:visible;opacity:1}.stats-menu-button{margin-left:8px;white-space:nowrap}\n /* Modal overlay and container with glassmorphism */\n .stats-modal-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--yt-modal-bg);z-index:var(--yt-z-modal);display:flex;align-items:center;justify-content:center;animation:fadeInModal .18s;backdrop-filter:var(--yt-glass-blur);-webkit-backdrop-filter:var(--yt-glass-blur)}\n .stats-modal-container{max-width:1100px;max-height:calc(100vh - 32px);display:flex;flex-direction:column}\n .stats-modal-content{position:relative;background:var(--yt-glass-bg);border-radius:var(--yt-radius-lg);box-shadow:0 18px 40px var(--yt-stats-modal-shadow);overflow:visible;display:flex;flex-direction:column;animation:scaleInModal .18s;border:1.5px solid var(--yt-glass-border);backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%)}\n /* Fix custom element display for Chrome */\n button-view-model{display:inline-flex;align-items:center;justify-content:center;}\n button-view-model.yt-spec-button-view-model{vertical-align:top;}\n /* Modal body */\n .stats-modal-body{position:relative;padding:24px 16px 16px;overflow:visible;flex:1;display:flex;flex-direction:column}\n /* Thumbnail preview */\n .stats-thumb-title-centered{position:absolute;top:-44px;left:50%;transform:translateX(-50%);z-index:3;display:block;width:fit-content;max-width:min(90%,760px);margin:0;padding:8px 16px;border-radius:18px;border:1px solid var(--yt-glass-border);background:var(--yt-glass-bg);font-size:14px;font-weight:500;color:var(--yt-text-primary);text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:default;transition:transform .25s cubic-bezier(.4,0,.2,1), background-color .25s cubic-bezier(.4,0,.2,1), border-color .25s cubic-bezier(.4,0,.2,1), color .25s cubic-bezier(.4,0,.2,1)}\n .stats-thumb-row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap}\n .stats-thumb-img{width:36vw;max-width:420px;height:auto;object-fit:cover;border-radius:8px;flex-shrink:0;outline:1px solid rgba(255,255,255,0.1);outline-offset:-1px;max-height:44vh;border:none;}\n html:not([dark]) .stats-thumb-img{outline:1px solid rgba(0,0,0,0.1);outline-offset:-1px;}\n /* ensure the grid takes remaining horizontal space */\n .stats-thumb-row .stats-grid{flex:1;min-width:0}\n .stats-side-column{flex:1;min-width:280px;display:flex;flex-direction:column}\n .stats-thumb-left{display:flex;flex-direction:column;align-items:center;gap:8px}\n .stats-thumb-left .stats-thumb-sub{font-size:13px;color:var(--yt-stats-text-secondary-dark)}\n html:not([dark]) .stats-thumb-left .stats-thumb-sub{color:var(--yt-stats-text-secondary-light)}\n /* extras row under thumbnail: inline, single line */\n .stats-thumb-extras{display:flex;flex-direction:row;gap:10px;align-items:center;margin-top:8px}\n .stats-thumb-extras .stats-card{padding:8px 10px}\n .stats-thumb-meta{display:flex;flex-direction:column;justify-content:center}\n .stats-thumb-sub{font-size:13px;color:var(--yt-stats-text-secondary-dark)}\n html:not([dark]) .stats-thumb-sub{color:var(--yt-stats-text-secondary-light)}\n /* Loading state */\n .stats-loader{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;color:var(--yt-stats-loader-text-dark)}\n html:not([dark]) .stats-loader{color:var(--yt-stats-loader-text-light)}\n .stats-spinner{width:60px;height:60px;animation:spin 1s linear infinite;margin-bottom:16px}\n .stats-spinner circle{stroke-dasharray:80;stroke-dashoffset:60;animation:dash 1.5s ease-in-out infinite} \n /* Error state */\n .stats-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;color:var(--yt-stats-error);text-align:center}\n .stats-error-icon{width:60px;height:60px;margin-bottom:16px;stroke:var(--yt-stats-error)}\n /* Stats grid */\n .stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px} \n /* Stats card */\n .stats-card{background:var(--yt-stats-card-bg-dark);border-radius:12px;padding:12px;display:flex;align-items:center;gap:12px;border:1px solid var(--yt-stats-card-border-dark);transition:transform .18s ease,box-shadow .18s ease}\n html:not([dark]) .stats-card{background:var(--yt-stats-card-bg-light);border:1px solid var(--yt-stats-card-border-light)}\n .stats-card:hover{transform:translateY(-2px);box-shadow:0 8px 20px var(--yt-stats-shadow-hover)}\n /* Stats icon */\n .stats-icon{width:48px;height:48px;border-radius:12px;display:flex;align-items:center;justify-content:center;flex-shrink:0}\n .stats-icon svg{width:24px;height:24px}\n .stats-icon-views{background:var(--yt-stats-icon-views-bg);color:var(--yt-stats-icon-views)}\n .stats-icon-likes{background:var(--yt-stats-icon-likes-bg);color:var(--yt-stats-icon-likes)}\n .stats-icon-dislikes{background:var(--yt-stats-icon-dislikes-bg);color:var(--yt-stats-icon-dislikes)}\n .stats-icon-comments{background:var(--yt-stats-icon-comments-bg);color:var(--yt-stats-icon-comments)}\n .stats-icon-viewers{background:var(--yt-stats-icon-viewers-bg);color:var(--yt-stats-icon-viewers)}\n .stats-icon-subscribers{background:var(--yt-stats-icon-subscribers-bg);color:var(--yt-stats-icon-subscribers)}\n .stats-icon-videos{background:var(--yt-stats-icon-videos-bg);color:var(--yt-stats-icon-videos)}\n /* Pair likes/dislikes into a single grid cell */\n .stats-card-pair{display:flex;gap:8px;align-items:stretch}\n .stats-card-pair .stats-card{flex:1;margin:0}\n @media(max-width:480px){.stats-card-pair{flex-direction:column}} \n /* Stats info */\n .stats-info{flex:1;min-width:0}\n .stats-label{font-size:13px;color:var(--yt-stats-text-label);margin-bottom:4px;font-weight:500}\n html:not([dark]) .stats-label{color:var(--yt-stats-text-secondary-light)}\n .stats-value{font-size:20px;font-weight:700;color:var(--yt-stats-text-value-dark);line-height:1.2;margin-bottom:2px}\n html:not([dark]) .stats-value{color:var(--yt-stats-text-value-light)}\n .stats-exact{font-size:13px;color:var(--yt-stats-text-exact-dark);font-weight:400}\n html:not([dark]) .stats-exact{color:var(--yt-stats-text-exact-light)}\n /* Animations — shared keyframes (fadeInModal, scaleInModal, spin, dash) defined in basic.js */\n /* Responsive */\n @media(max-width:768px){.stats-modal-container{width:95vw}.stats-grid{grid-template-columns:1fr}.stats-card{padding:16px}.stats-side-column{min-width:0;width:100%}}\n /* Centered large author handle (preferred) */\n .stats-author-big{display:block;text-align:center;margin-top:13px;padding-inline:8px}\n .stats-author-name-big{display:block;color:var(--yt-stats-author-name-bright);font-weight:600;font-size:16px}\n .stats-author-handle-big{display:inline-block;color:var(--yt-glass-border);font-weight:700;font-size:20px;text-decoration:none;padding:6px 10px;border-radius:6px}\n .stats-author-handle-big:hover{color:var(--yt-stats-link-hover);text-decoration:underline}\n html:not([dark]) .stats-author-name-big{color:var(--yt-stats-author-name-light)}\n html:not([dark]) .stats-author-handle-big{color:var(--yt-stats-link-color)}\n html:not([dark]) .stats-author-handle-big:hover{color:var(--yt-stats-link-hover-dark)}\n "), R && (E(), C()), t?.cleanupManager?.registerListener ? (t.cleanupManager.registerListener(window, "ytp-history-navigate", K), t.cleanupManager.registerListener(window, "popstate", K)) : (window.addEventListener("ytp-history-navigate", K), window.addEventListener("popstate", K)), t?.isChannelPage?.(location.href) && c(location.href)); } catch (t) { throw N = !1, t; } }; "function" == typeof requestIdleCallback ? requestIdleCallback(e, { timeout: 2e3 }) : setTimeout(e, 0); }; var nt; nt = et, "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", nt, { once: !0 }) : nt(); const ot = () => { et(), N && R && (E(), C(), t?.isChannelPage?.(location.href) && c(location.href)); }, rt = t?.cleanupManager; rt ? rt.registerListener(document, "yt-navigate-finish", ot, { passive: !0 }) : document.addEventListener("yt-navigate-finish", ot); const it = () => { try { N && R && (E(), C()); } catch (t) {} }; rt ? rt.registerListener(window, "ytp:nav-refresh", it, { passive: !0 }) : window.addEventListener("ytp:nav-refresh", it); const at = t => { et(), N && R && t.detail && "yt-reload-continuation-items-command" === t.detail.actionName && (E(), C()); }; rt ? rt.registerListener(document, "yt-action", at, { passive: !0 }) : document.addEventListener("yt-action", at); }; document.addEventListener("youtube-plus-settings-modal-opened", o, { once: !1 }), t?.whenRelevant ? t.whenRelevant({ name: "stats.video", isRelevant: () => (() => { try { const t = location.pathname || ""; return "/watch" === t || t.startsWith("/shorts") || t.startsWith("/@") || t.startsWith("/channel/") || t.startsWith("/c/"); } catch (t) { return !1; } })() || e(), onEnter: o }) : o(); })(), (function() { const t = window.YouTubeUtils; if (window.__ytpChannelStatsModuleInit) { return; } const e = () => t.isSettingsModalOpen(), o = () => { async function o(t) { const e = await (async function(t) { if (_.isChecking) { return null; } _.isChecking = !0; try { const e = await fetch(t, { credentials: "same-origin" }); if (!e.ok) { return null; } const o = (await e.text()).match(/var ytInitialData = (.+?);<\/script>/); return o?.[1] ? JSON.parse(o[1]) : null; } catch (t) { return P.warn("Failed to fetch channel data:", t), null; } finally { _.isChecking = !1; } })(t); if (!e) { return null; } try { return { channelName: e?.metadata?.channelMetadataRenderer?.title || C("unknown"), channelId: e?.metadata?.channelMetadataRenderer?.externalId || null }; } catch (t) { return null; } } function r() { const e = location.href; e !== _.previousUrl && (_.previousUrl = e, t?.isChannelPage?.(e) && setTimeout(() => o(e), 500)); } function i() { if (!t?.isStudioPage?.()) { try { if (P.log("Initializing YouTube Enhancer v1.6"), (function() { const t = document.createElement("link"); t.rel = "stylesheet", t.href = H, (document.head || document.documentElement).appendChild(t); })(), j.forEach(t => { null === E.getItem(`show-${t}`) && E.setItem(`show-${t}`, "true"); }), t.StyleManager.add("channel-stats-overlay", '\n .channel-banner-overlay{position:absolute;top:0;left:0;width:100%;height:100%;border-radius:12px;z-index:9;display:flex;justify-content:space-around;align-items:center;color:var(--yt-text-primary);font-family:var(--yt-stats-font-family,\'Rubik\',sans-serif);font-size:var(--yt-stats-font-size,24px);box-sizing:border-box;transition:background-color .3s ease;backdrop-filter:blur(2px)} \n .settings-button{position:absolute;top:12px;right:12px;width:32px;height:32px;border-radius:50%;cursor:pointer;z-index:11;transition:transform 0.2s cubic-bezier(0.2,0,0,1), opacity 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;display:flex;align-items:center;justify-content:center;background:var(--yt-stats-channel-button-bg);backdrop-filter:blur(4px);border:1px solid var(--yt-stats-channel-button-border);opacity:0.7}\n .channel-banner-overlay:hover .settings-button{opacity:1}\n .settings-button:hover{transform:rotate(30deg) scale(1.1);opacity:1;background:var(--yt-stats-channel-button-hover);border-color:var(--yt-stats-channel-button-hover-border)}\n .settings-button:active{transform:rotate(30deg) scale(0.96) !important;}\n .settings-button svg{width:18px;height:18px;fill:var(--yt-text-primary);filter:drop-shadow(0 1px 2px var(--yt-stats-channel-filter-shadow))} \n .settings-menu{position:absolute;top:52px;right:12px;background:var(--yt-stats-channel-menu-bg);padding:16px;border-radius:16px;z-index:12;display:flex;flex-direction:column;gap:12px;backdrop-filter:blur(16px) saturate(180%);border:1px solid var(--yt-stats-channel-menu-border);box-shadow:0 8px 32px rgba(0,0,0,0.6);min-width:320px;opacity:0;visibility:hidden;transform:translateY(-10px) scale(0.98);transition:opacity 0.2s cubic-bezier(0.2,0,0.2,1), transform 0.2s cubic-bezier(0.2,0,0.2,1), visibility 0.2s cubic-bezier(0.2,0,0.2,1);pointer-events:none}\n .settings-menu.show{opacity:1;visibility:visible;transform:translateY(0) scale(1);pointer-events:auto} \n .settings-menu .ytp-plus-settings-item{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-radius:8px;background:var(--yt-stats-channel-menu-item-bg);}\n .settings-menu .ytp-plus-settings-item + .ytp-plus-settings-item{margin-top:6px}\n .settings-menu .ytp-plus-settings-item .ytp-plus-settings-item-label{color:var(--yt-stats-channel-label-text);font-size:14px;font-weight:500}\n .settings-menu label{color:var(--yt-stats-channel-label-text)!important;font-size:14px!important;font-weight:500!important;margin-bottom:6px!important} \n .settings-menu input[type="range"]{-webkit-appearance:none;width:100%!important;height:4px;background:var(--yt-stats-channel-range-bg)!important;border-radius:2px;margin:12px 0 4px 0!important;cursor:pointer}\n .settings-menu input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;height:16px;width:16px;border-radius:50%;background:var(--yt-stats-channel-range-thumb);margin-top:-6px;box-shadow:0 2px 4px var(--yt-stats-channel-text-shadow);border:2px solid var(--yt-text-primary);transition:transform .1s;cursor:pointer}\n .settings-menu input[type="range"]::-webkit-slider-thumb:hover{transform:scale(1.2)} \n .settings-menu select{width:100%!important;background:var(--yt-stats-channel-input-bg)!important;border:1px solid var(--yt-stats-channel-input-bg)!important;color:var(--yt-text-primary)!important;padding:8px 12px!important;border-radius:6px!important;font-size:13px!important;margin-bottom:12px!important;cursor:pointer;outline:none}\n .settings-menu select:hover{background:var(--yt-stats-channel-input-hover)!important}\n .settings-menu select option{background:var(--yt-stats-channel-select-option-bg);color:var(--yt-text-primary)} \n /* Don\'t override the shared settings checkbox styling; only target non-shared inputs */\n .settings-menu input[type="checkbox"]:not(.ytp-plus-settings-checkbox){appearance:none;width:18px!important;height:18px!important;border:2px solid var(--yt-stats-channel-checkbox-border)!important;border-radius:4px!important;background:transparent!important;cursor:pointer;position:relative;margin-right:12px!important;vertical-align:middle;transition:background-color .2s ease, border-color .2s ease, transform .1s cubic-bezier(0.2,0,0,1)}\n .settings-menu input[type="checkbox"]:not(.ytp-plus-settings-checkbox):active{transform:scale(0.96) !important;}\n .settings-menu input[type="checkbox"]:not(.ytp-plus-settings-checkbox):checked{background:var(--yt-stats-channel-range-thumb)!important;border-color:var(--yt-stats-channel-range-thumb)!important}\n .settings-menu input[type="checkbox"]:not(.ytp-plus-settings-checkbox):checked::after{content:\'\';position:absolute;left:5px;top:1px;width:4px;height:10px;border:solid var(--yt-text-primary);border-width:0 2px 2px 0;transform:rotate(45deg)}\n .stat-container{display:flex;flex-direction:column;align-items:center;justify-content:center;visibility:hidden;width:33%;height:100%;padding:0 1rem;text-shadow:0 2px 4px var(--yt-stats-channel-text-shadow)}\n .number-container{display:flex;align-items:center;justify-content:center;font-weight:700;min-height:3rem}\n .label-container{display:flex;align-items:center;margin-top:.5rem;font-size:1.2rem;opacity:.9}\n .label-container svg{width:1.5rem;height:1.5rem;margin-right:.5rem;filter:drop-shadow(0 1px 2px var(--yt-stats-channel-text-shadow))}\n .difference{font-size:1.8rem;height:2rem;margin-bottom:.5rem;transition:opacity .3s}\n .spinner-container{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center}\n .spinner-container .stats-spinner{width:60px;height:60px;animation:spin 1s linear infinite}\n .spinner-container .stats-spinner circle{stroke-dasharray:80;stroke-dashoffset:60;animation:dash 1.5s ease-in-out infinite}\n /* @keyframes spin already defined in video stats CSS above */\n @media(max-width:768px){.channel-banner-overlay{flex-direction:column;padding:8px;min-height:160px}.settings-menu{width:280px!important;right:4px!important;top:48px!important}}\n .setting-group{margin-bottom:12px}\n .setting-group:last-child{margin-bottom:0}\n .setting-value{color:var(--yt-stats-channel-text-value);font-size:12px;margin-top:4px}\n '), _.enabled && (w(), v(), t?.isChannelPage?.(location.href))) { o(location.href); try { h(); } catch (t) { P.warn("Initial overlay attempt failed:", t); } } P.log("YouTube Enhancer initialized successfully"); } catch (t) { P.error("Failed to initialize YouTube Enhancer:", t); } } } function a(t, e) { const o = document.createElement("div"); Object.assign(o.style || {}, { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", visibility: "hidden", width: "33%", height: "100%", padding: "0 1rem" }); const r = document.createElement("div"); Object.assign(r.style || {}, { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }); const i = document.createElement("div"); i.classList.add(`${t}-difference`), Object.assign(i.style || {}, { fontSize: "2.5rem", height: "2.5rem", marginBottom: "1rem" }); const a = (function() { const t = document.createElement("div"); return Object.assign(t.style || {}, { display: "flex", justifyContent: "center", alignItems: "center", letterSpacing: "0.025em" }), t; })(); a.classList.add(`${t}-number`), Object.assign(a.style || {}, { fontSize: `${E.getItem("youtubeEnhancerFontSize") || "24"}px`, fontWeight: "bold", lineHeight: "1", height: "4rem", fontFamily: E.getItem("youtubeEnhancerFontFamily") || "Rubik, sans-serif", letterSpacing: "0.025em" }), r.appendChild(i), r.appendChild(a); const s = document.createElement("div"); Object.assign(s.style || {}, { display: "flex", alignItems: "center", marginTop: "0.5rem" }); const c = (function(t) { const e = document.createElementNS("http://www.w3.org/2000/svg", "svg"); e.setAttribute("viewBox", "0 0 640 512"), e.setAttribute("width", "2rem"), e.setAttribute("height", "2rem"), e.style && (e.style.marginRight = "0.5rem", e.style.display = "none"); const o = document.createElementNS("http://www.w3.org/2000/svg", "path"); return o.setAttribute("d", t), o.setAttribute("fill", "white"), e.appendChild(o), e; })(e); Object.assign(c.style || {}, { width: "2rem", height: "2rem", marginRight: "0.75rem" }); const l = document.createElement("div"); return l.classList.add(`${t}-label`), l.style.fontSize = "2rem", s.appendChild(c), s.appendChild(l), o.appendChild(r), o.appendChild(s), o; } function s() { const e = L(".channel-banner-overlay"); if (e) { try { e.remove(); } catch (t) { window.YouTubePlusLogger?.warn?.("Stats", "Failed to remove overlay"); } } if (_.intervalId) { try { _.intervalId.stop(); } catch (t) { window.YouTubePlusLogger?.warn?.("Stats", "Failed to clear interval"); } _.intervalId = null; } _.documentListenerKeys?.size && (_.documentListenerKeys.forEach(e => { try { t.cleanupManager.unregisterListener?.(e); } catch (t) { window.YouTubePlusLogger?.warn?.("Stats", "Failed to unregister listener"); } }), _.documentListenerKeys.clear()), _.lastSuccessfulStats && _.lastSuccessfulStats.clear(), _.previousStats && _.previousStats.clear(), _.currentChannelId = null, _.isUpdating = !1, _.overlay = null, P.log("Cleared existing overlay"); } function c() { const t = document.createElement("span"); return Object.assign(t.style || {}, { display: "inline-block", width: "0.6em", textAlign: "center", marginRight: "0.025em", marginLeft: "0.025em" }), t; } function l() { const t = document.createElement("span"); return t.textContent = ",", Object.assign(t.style || {}, { display: "inline-block", width: "0.3em", textAlign: "center" }), t; } function d(t, e) { const o = (function(t) { const e = []; for (let o = t.length - 1; o >= 0; o -= 3) { const r = Math.max(0, o - 2); e.unshift(t.slice(r, o + 1)); } return e; })(e.toString()); !(function(t) { for (;t.firstChild; ) { t.removeChild(t.firstChild); } })(t), (function(t, e) { for (let o = 0; o < e.length; o++) { const r = e[o]; for (let e = 0; e < r.length; e++) { const o = c(); o.textContent = r[e], t.appendChild(o); } o < e.length - 1 && t.appendChild(l()); } })(t, o), (function(t, e) { let o = 0; for (let r = 0; r < e.length; r++) { const i = e[r]; for (let e = 0; e < i.length; e++) { const r = t.children[o], a = parseInt(i[e], 10), s = parseInt(r.textContent || "0", 10); s !== a && u(r, s, a), o++; } r < e.length - 1 && o++; } })(t, o); } function u(t, e, o) { const r = performance.now(); requestAnimationFrame(function i(a) { const s = Math.min((a - r) / 1e3, 1), c = Math.round(e + (o - e) * (1 - (1 - s) ** 4)); t.textContent = String(c), s < 1 && requestAnimationFrame(i); }); } function p() { const t = L(".channel-banner-overlay"); if (!t) { return; } const e = t.querySelectorAll('div[style*="width"]'); if (!e.length) { return; } let o = 0; const r = []; e.forEach(t => { const e = t.querySelector('[class$="-number"]'); if (!e) { return; } const i = e.className.replace("-number", ""); "false" !== E.getItem(`show-${i}`) ? (t instanceof HTMLElement && t.style && (t.style.display = "flex"), o++, r.push(t)) : t instanceof HTMLElement && t.style && (t.style.display = "none"); }), r.forEach(t => { if (t instanceof HTMLElement && t.style) { switch (t.style.width = "", t.style.margin = "", o) { case 1: t.style.width = "100%"; break; case 2: t.style.width = "50%"; break; case 3: t.style.width = "33.33%"; break; default: t.style.display = "none"; } } }); const i = E.getItem("youtubeEnhancerFontSize") || "24", a = E.getItem("youtubeEnhancerFontFamily") || "Rubik, sans-serif"; t.querySelectorAll(".subscribers-number,.views-number,.videos-number").forEach(t => { t instanceof HTMLElement && t.style && (t.style.fontSize = `${i}px`, t.style.fontFamily = a); }), t.style && (t.style.display = "flex"); } function y(t, e, o, r, i) { const a = t.querySelector(`.${o}-number`), s = t.querySelector(`.${o}-difference`), c = t.querySelector(`.${o}-label`); if (a && d(a, r), s && _.previousStats.has(e)) { const t = (function(t, e) { const o = _.previousStats.get(t); return o ? "subscribers" === e ? o.followerCount : o.bottomOdos["views" === e ? 0 : 1] : null; })(e, o); null !== t && (function(t, e, o) { if (!o) { return; } const r = e - o; 0 !== r ? (t.textContent = `${r > 0 ? "+" : ""}${r.toLocaleString()}`, t.classList.add(r > 0 ? "ytp-stats-change-positive" : "ytp-stats-change-negative"), T(() => { t.textContent = ""; }, 1e3)) : t.textContent = ""; })(s, r, t); } c && (c.textContent = i); } async function m(t, e) { if ((function(t) { return !_.isUpdating && t === _.currentChannelName; })(e) && t?.isConnected && "hidden" !== document.visibilityState) { _.isUpdating = !0; try { const r = await (async function(t) { const e = t || _.currentChannelName || window.location.pathname; if (e && _.channelIdCache.has(e)) { return _.channelIdCache.get(e); } if (_.currentChannelId) { return _.currentChannelId; } if ("string" == typeof t && /^UC[\w-]{22}$/.test(t)) { return _.currentChannelId = t, e && A(_.channelIdCache, e, t), t; } const r = () => { const t = L('meta[itemprop="channelId"]'); if (t?.content) { return t.content; } const e = window.location.href.match(/channel\/(UC[\w-]+)/); if (e?.[1]) { return e[1]; } const o = window.ytInitialData, r = o?.metadata?.channelMetadataRenderer?.externalId || o?.header?.c4TabbedHeaderRenderer?.channelId; if (r && /^UC[\w-]{22}$/.test(r)) { return r; } if (window.ytcfg?.get) { const t = window.ytcfg.get("CHANNEL_ID"); if (t && /^UC[\w-]{22}$/.test(t)) { return t; } } return null; }; let i = r(); if (i || (i = await new Promise(t => { let e = 0; const o = () => { e += 1; const i = r(); return i ? t(i) : e >= 10 ? t(null) : void setTimeout(o, 100); }; o(); })), i) { return _.currentChannelId = i, e && A(_.channelIdCache, e, i), i; } const a = await o(window.location.href); return a?.channelId ? (_.currentChannelId = a.channelId, e && A(_.channelIdCache, e, a.channelId), a.channelId) : null; })(e); if (!r) { const o = Date.now(); return o - _.lastChannelIdWarnAt > 15e3 && (_.lastChannelIdWarnAt = o, P.warn("Skipping overlay update: channel ID is not available yet")), void setTimeout(() => { t?.isConnected && e === _.currentChannelName && m(t, e); }, 500); } _.currentChannelId = r; const i = await (async function(t) { const e = () => (function(t, e = {}) { const o = { Accept: "application/json", ...e }, r = window.GM_xmlhttpRequest; return "function" == typeof r ? new Promise((e, i) => { r({ method: "GET", url: t, headers: o, timeout: 1e4, onload: t => { if (t.status >= 200 && t.status < 300) { try { e(JSON.parse(t.responseText)); } catch (t) { const e = t instanceof Error ? t.message : String(t); i(new Error(`Failed to parse response: ${e}`)); } } else { i(new Error(`Failed to fetch: ${t.status}`)); } }, onerror: t => i(t), ontimeout: () => i(new Error("Request timed out")) }); }) : (P.warn("GM_xmlhttpRequest unavailable, falling back to fetch API"), fetch(t, { method: "GET", headers: o, credentials: "omit", mode: "cors" }).then(t => { if (!t.ok) { throw new Error(`Failed to fetch: ${t.status}`); } return t.json(); }).catch(t => { throw P.error("Fallback fetch failed:", t), t; })); })(`${D}${t}`, { origin: "https://livecounts.io", referer: "https://livecounts.io/" }); let o = null; for (let r = 0; r <= z.MAX_RETRIES; r++) { try { const o = await e(); if (o) { return _.lastSuccessfulStats.set(t, { stats: o, timestamp: Date.now() }), o; } } catch (t) { if (o = t, r < z.MAX_RETRIES) { const t = Math.min(1e3 * 2 ** r, 1e4); await new Promise(e => setTimeout(e, t)); } } } const r = _.lastSuccessfulStats.get(t); if (r && Date.now() - r.timestamp < z.CACHE_DURATION) { return r.stats; } let i = 0; try { const t = document.querySelector("#subscriber-count") || document.querySelector("yt-formatted-string#subscriber-count"); if (t?.textContent) { const e = t.textContent.replace(/[^0-9.KkMmBb]/g, ""); if (e) { const t = parseFloat(e); if (!Number.isNaN(t)) { const o = e.slice(-1).toLowerCase(); i = Math.round(t * ("k" === o ? 1e3 : "m" === o ? 1e6 : "b" === o ? 1e9 : 1)); } } } } catch (t) {} return o && P.error("Failed to fetch channel stats:", o), { followerCount: i, bottomOdos: [ 0, 0 ], error: !0, timestamp: Date.now() }; })(r); if (e !== _.currentChannelName) { return; } if (i.error) { return void (function(t, e) { t.querySelectorAll('[class$="-number"]').forEach(t => { t.classList.contains("subscribers-number") && e.followerCount > 0 ? d(t, e.followerCount) : t.textContent = "---"; }), P.warn("Using fallback stats due to API error"); })(t, i); } !(function(t, e, o) { y(t, e, "subscribers", o.followerCount, C("subscribers")), y(t, e, "views", o.bottomOdos[0], C("views")), y(t, e, "videos", o.bottomOdos[1], C("videos")); })(t, r, i), _.previousStats.has(r) || ((function(t) { const e = t.querySelector(".spinner-container"); e && e.remove(), t.querySelectorAll('div[style*="visibility: hidden"]').forEach(t => { t instanceof HTMLElement && t.style && (t.style.visibility = "visible"); }), t.querySelectorAll('svg[style*="display: none"]').forEach(t => { (t instanceof SVGElement || t instanceof HTMLElement) && t.style && (t.style.display = "block"); }); })(t), P.log("Displayed initial stats for channel:", e)), _.previousStats.set(r, i); } catch (e) { P.error("Failed to update overlay content:", e), (function(t) { t.querySelectorAll('[class$="-number"]').forEach(t => { t.textContent = "---"; }); })(t); } finally { _.isUpdating = !1; } } } function f(e) { const o = (r = window.location.pathname).startsWith("/@") ? r.split("/")[1].replace("@", "") : r.startsWith("/channel/") || r.startsWith("/c/") || r.startsWith("/user/") ? r.split("/")[2] : null; var r; !(function(t, e) { return !(t && !(t === _.currentChannelName && _.overlay?.isConnected && e && e.contains(_.overlay))); })(o, e) && o && (!_.overlay || _.overlay.isConnected && e.contains(_.overlay) || s(), (function(t) { t?.style && !t.style.position && (t.style.position = "relative"); })(e), _.currentChannelName = o, _.overlay = (function(e) { if (s(), !e) { return null; } const o = (function() { const t = document.createElement("div"); return t.classList.add("channel-banner-overlay"), Object.assign(t.style || {}, { position: "absolute", top: "0", left: "0", width: "100%", height: "100%", backgroundColor: `rgba(0, 0, 0, ${_.overlayOpacity})`, borderRadius: "15px", zIndex: "10", display: "flex", justifyContent: "space-around", alignItems: "center", color: "white", fontFamily: E.getItem("youtubeEnhancerFontFamily") || "Rubik, sans-serif", fontSize: `${E.getItem("youtubeEnhancerFontSize") || "24"}px`, boxSizing: "border-box", transition: "background-color 0.3s ease" }), t; })(); !(function(t) { t.setAttribute("role", "region"), t.setAttribute("aria-label", C("overlayAriaLabel")), t.setAttribute("tabindex", "-1"); })(o), (function(t) { window.innerWidth <= 768 && t.style && (t.style.flexDirection = "column", t.style.padding = "10px", t.style.minHeight = "200px"); })(o); const r = (function() { const t = (function() { const t = document.createElement("div"); return t.className = "settings-button", k(t, '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="white" d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"/></svg>'), t; })(); return t.setAttribute("tabindex", "0"), t.setAttribute("aria-label", C("settingsAriaLabel")), t.setAttribute("role", "button"), t; })(), i = (function() { const e = (function() { const e = document.createElement("div"); e.className = "settings-menu", e.classList.add("ytp-stats-channel-menu"), e.setAttribute("tabindex", "-1"), e.setAttribute("aria-modal", "true"); const o = (function() { const t = document.createElement("div"); t.style && (t.style.flex = "1"); const e = document.createElement("label"); return e.textContent = C("displayOptions"), e.classList.add("ytp-stats-display-label"), t.appendChild(e), t.addEventListener("change", t => { const e = t.target; if (e instanceof HTMLInputElement && "checkbox" === e.type && e.id.startsWith("show-")) { const t = e.id.replace("show-", ""); E.setItem(`show-${t}`, String(e.checked)), p(); } }), j.forEach(e => { const o = document.createElement("div"); o.className = "ytp-plus-settings-item"; const r = document.createElement("div"), i = document.createElement("label"); i.className = "ytp-plus-settings-item-label", i.htmlFor = `show-${e}`, i.textContent = C(e), r.appendChild(i); const a = document.createElement("input"); a.type = "checkbox", a.id = `show-${e}`, a.checked = "false" !== E.getItem(`show-${e}`), a.className = "ytp-plus-settings-checkbox", o.appendChild(r), o.appendChild(a), t.appendChild(o); }), t; })(), r = (function() { const e = document.createElement("div"); e.style && (e.style.flex = "1"), e.addEventListener("input", t => { const o = t.target; if (o instanceof HTMLElement && o.classList.contains("font-size-slider")) { const t = o, r = e.querySelector(".font-size-value"); r && (r.textContent = `${t.value}px`), E.setItem("youtubeEnhancerFontSize", t.value), _.overlay && _.overlay.querySelectorAll(".subscribers-number,.views-number,.videos-number").forEach(e => { e instanceof HTMLElement && e.style && (e.style.fontSize = `${t.value}px`); }); } if (o instanceof HTMLElement && o.classList.contains("interval-slider")) { const t = o, r = 1e3 * parseInt(t.value, 10), i = e.querySelector(".interval-value"); i && (i.textContent = `${t.value}s`), _.updateInterval = r, E.setItem("youtubeEnhancerInterval", String(r)), _.intervalId && (_.intervalId.stop(), _.intervalId = S(() => { m(_.overlay, _.currentChannelName); }, r)); } if (o instanceof HTMLElement && o.classList.contains("opacity-slider")) { const t = o, r = parseInt(t.value, 10) / 100, i = e.querySelector(".opacity-value"); i && (i.textContent = `${t.value}%`), _.overlayOpacity = r, E.setItem("youtubeEnhancerOpacity", String(r)), _.overlay && (_.overlay.style.backgroundColor = `rgba(0, 0, 0, ${r})`); } }); const o = document.createElement("label"); o.textContent = C("fontFamily"), o.classList.add("ytp-stats-font-label"); const r = [ { name: "Rubik", value: "Rubik, sans-serif" }, { name: "Impact", value: "Impact, Charcoal, sans-serif" }, { name: "Verdana", value: "Verdana, Geneva, sans-serif" }, { name: "Tahoma", value: "Tahoma, Geneva, sans-serif" } ], i = E.getItem("youtubeEnhancerFontFamily") || "Rubik, sans-serif", a = r.find(t => t.value === i)?.name || "Rubik", s = document.createElement("select"); s.className = "font-family-select", s.style.display = "none", r.forEach(t => { const e = document.createElement("option"); e.value = t.value, e.textContent = t.name, t.value === i && (e.selected = !0), s.appendChild(e); }); const c = document.createElement("div"); c.className = "glass-dropdown", c.id = "stats-font-dropdown", c.tabIndex = 0, c.setAttribute("role", "listbox"), c.setAttribute("aria-expanded", "false"), c.style.marginBottom = "12px", k(c, `\n <button class="glass-dropdown__toggle" type="button" aria-haspopup="listbox">\n <span class="glass-dropdown__label">${a}</span>\n <svg class="glass-dropdown__chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>\n </button>\n <ul class="glass-dropdown__list" role="presentation">\n ${r.map(t => `<li class="glass-dropdown__item" data-value="${t.value}" role="option"${t.value === i ? ' aria-selected="true"' : ""}>${t.name}</li>`).join("")}\n </ul>\n `), ("function" == typeof queueMicrotask ? queueMicrotask : t => Promise.resolve().then(t))(() => { const e = c.querySelector(".glass-dropdown__toggle"), o = c.querySelector(".glass-dropdown__list"), r = c.querySelector(".glass-dropdown__label"), i = () => { c.setAttribute("aria-expanded", "false"), o && (o.style.display = "none"); }; i(), e && e.addEventListener("click", t => { t.stopPropagation(), "true" === c.getAttribute("aria-expanded") ? i() : (c.setAttribute("aria-expanded", "true"), o && (o.style.display = "block")); }); const a = t => { const e = t.target; e instanceof Node && c.contains(e) || i(); }; t?.cleanupManager?.registerListener ? t.cleanupManager.registerListener(document, "click", a) : (document.addEventListener("click", a), _?.documentListenerKeys && _.documentListenerKeys.add("_docClickHandler")), o && o.addEventListener("click", t => { const e = t.target; if (!(e instanceof HTMLElement)) { return; } const o = e.closest(".glass-dropdown__item"); if (!o) { return; } const a = o.dataset?.value || ""; c.querySelectorAll(".glass-dropdown__item").forEach(t => t.removeAttribute("aria-selected")), o.setAttribute("aria-selected", "true"), r && (r.textContent = o.textContent), s.value = a, i(), E.setItem("youtubeEnhancerFontFamily", a), _.overlay && _.overlay.querySelectorAll(".subscribers-number,.views-number,.videos-number").forEach(t => { t instanceof HTMLElement && t.style && (t.style.fontFamily = a); }); }); }); const l = document.createElement("label"); l.textContent = C("fontSize"), l.classList.add("ytp-stats-font-label"); const d = document.createElement("input"); d.type = "range", d.min = "16", d.max = "72", d.value = E.getItem("youtubeEnhancerFontSize") || "24", d.step = "1", d.className = "font-size-slider"; const u = document.createElement("div"); u.className = "font-size-value", u.textContent = `${d.value}px`, u.classList.add("ytp-stats-font-value"); const p = document.createElement("label"); p.textContent = C("updateInterval"), p.classList.add("ytp-stats-font-label"); const y = document.createElement("input"); y.type = "range", y.min = "2", y.max = "10", y.value = String(_.updateInterval / 1e3), y.step = "1", y.className = "interval-slider"; const f = document.createElement("div"); f.className = "interval-value", f.textContent = `${y.value}s`, f.classList.add("ytp-stats-font-value"); const b = document.createElement("label"); b.textContent = C("backgroundOpacity"), b.classList.add("ytp-stats-font-label"); const h = document.createElement("input"); h.type = "range", h.min = "50", h.max = "90", h.value = String(100 * _.overlayOpacity), h.step = "5", h.className = "opacity-slider"; const g = document.createElement("div"); return g.className = "opacity-value", g.textContent = `${h.value}%`, g.classList.add("ytp-stats-font-value"), e.appendChild(o), e.appendChild(s), e.appendChild(c), e.appendChild(l), e.appendChild(d), e.appendChild(u), e.appendChild(p), e.appendChild(y), e.appendChild(f), e.appendChild(b), e.appendChild(h), e.appendChild(g), e; })(); return e.appendChild(o), e.appendChild(r), e; })(); return e.setAttribute("aria-label", C("settingsMenuAriaLabel")), e.setAttribute("role", "dialog"), e; })(); o.appendChild(r), o.appendChild(i), (function(e, o) { const r = t => { o.classList.toggle("show", t), e.setAttribute("aria-expanded", String(t)), t && o.focus(); }; e.addEventListener("click", t => { t.stopPropagation(), r(!o.classList.contains("show")); }), e.addEventListener("keydown", t => { "Enter" !== t.key && " " !== t.key || (t.preventDefault(), r(!o.classList.contains("show"))); }); const i = t.cleanupManager.registerListener(document, "click", t => { const i = t.target; o.contains(i) || e.contains(i) || r(!1); }), a = t.cleanupManager.registerListener(document, "keydown", t => { "Escape" === t.key && o.classList.contains("show") && (r(!1), e.focus()); }); _.documentListenerKeys.add(i), _.documentListenerKeys.add(a); })(r, i); const c = (function() { const t = document.createElement("div"); return t.classList.add("ytp-stats-spinner"), t.classList.add("spinner-container"), k(t, '<svg viewBox="0 0 50 50" class="stats-spinner"><circle cx="25" cy="25" r="20" fill="none" stroke="currentColor" stroke-width="4"></circle></svg>'), t; })(); return o.appendChild(c), (function(t) { const e = a("subscribers", "M144 160c-44.2 0-80-35.8-80-80S99.8 0 144 0s80 35.8 80 80s-35.8 80-80 80zm368 0c-44.2 0-80-35.8-80-80s35.8-80 80-80s80 35.8 80 80s-35.8 80-80 80zM0 298.7C0 239.8 47.8 192 106.7 192h42.7c15.9 0 31 3.5 44.6 9.7c-1.3 7.2-1.9 14.7-1.9 22.3c0 38.2 16.8 72.5 43.3 96c-.2 0-.4 0-.7 0H21.3C9.6 320 0 310.4 0 298.7zM405.3 320c-.2 0-.4 0-.7 0c26.6-23.5 43.3-57.8 43.3-96c0-7.6-.7-15-1.9-22.3c13.6-6.3 28.7-9.7 44.6-9.7h42.7C592.2 192 640 239.8 640 298.7c0 11.8-9.6 21.3-21.3 21.3H405.3zM416 224c0 53-43 96-96 96s-96-43-96-96s43-96 96-96s96 43 96 96zM128 485.3C128 411.7 187.7 352 261.3 352H378.7C452.3 352 512 411.7 512 485.3c0 14.7-11.9 26.7-26.7 26.7H154.7c-14.7 0-26.7-11.9-26.7-26.7z"), o = a("views", "M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"), r = a("videos", "M0 128C0 92.7 28.7 64 64 64H320c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128zM559.1 99.8c10.4 5.6 16.9 16.4 16.9 28.2V384c0 11.8-6.5 22.6-16.9 28.2s-23 5-32.9-1.6l-96-64L416 337.1V320 192 174.9l14.2-9.5 96-64c9.8-6.5 22.4-7.2 32.9-1.6z"); t.appendChild(e), t.appendChild(o), t.appendChild(r); })(o), e.appendChild(o), p(), o; })(e), _.overlay && (_.intervalId && (_.intervalId.stop(), _.intervalId = null), (function(t, e) { _.intervalId && _.intervalId.stop(); const o = (function(t, e) { let o = 0; return () => { if (!t?.isConnected) { return; } if ("hidden" === document.visibilityState) { return; } const r = Date.now(); r - o >= _.updateInterval - 100 && (m(t, e), o = r); }; })(t, e); _.intervalId = S(o, _.updateInterval); })(_.overlay, o), m(_.overlay, o), P.log("Added overlay for channel:", o))); } function b() { _.overlayEnsureScheduler?.stop && _.overlayEnsureScheduler.stop(), _.overlayEnsureScheduler = null; } function h(e = !0) { e && b(), _.overlayEnsureScheduler = (function(e) { const o = t?.createRetryScheduler; if ("function" == typeof o) { try { return o(e); } catch (e) { t?.logError?.("ChannelStats", "Retry scheduler factory failed", e); } } const {check: r, maxAttempts: i = 20, interval: a = 100} = e || {}; let s = 0, c = null, l = !1; const d = () => { if (!l) { s += 1; try { if ("function" == typeof r && r()) { return void (l = !0); } } catch (e) { t?.logError?.("ChannelStats", "Fallback retry check failed", e); } s >= i ? l = !0 : c = setTimeout(d, a); } }; return c = setTimeout(d, 0), { stop() { l = !0, c && clearTimeout(c), c = null; } }; })({ check: () => { if (!_.enabled) { return !0; } if (!t?.isChannelPage?.()) { return s(), _.currentChannelName = null, !0; } const e = (function() { let t = M("page-header-banner-sizer"); if (!(t instanceof HTMLElement)) { const e = L("#page-header-banner"); e instanceof HTMLElement && (t = e); } if (!(t instanceof HTMLElement)) { return null; } const e = t.getBoundingClientRect?.(); return e && (e.width < 8 || e.height < 8) ? null : t; })(); return !!e && ((function(t) { t.style && "relative" !== t.style.position && (t.style.position = "relative"); })(e), f(e), !!_.overlay?.isConnected); }, maxAttempts: 40, interval: 150 }); } function g() { if (!t?.isChannelPage?.()) { return s(), _.currentChannelName = null, void b(); } h(); } function w() { if (!_.enabled || _.pageObserversAttached) { return; } _.pageObserversAttached = !0; const e = t.debounce ? t.debounce(g, 150) : g; O?.registerListener ? (O.registerListener(document, "yt-navigate-finish", e), O.registerListener(document, "yt-page-data-updated", e)) : (document.addEventListener("yt-navigate-finish", e), document.addEventListener("yt-page-data-updated", e)); } function v() { if (!_.enabled || _.navigationListenerAttached) { return; } _.navigationListenerAttached = !0; const e = () => { t?.isChannelPage?.() ? (h(), P.log("Navigated to channel page")) : (s(), _.currentChannelName = null, b(), P.log("Navigated away from channel page")); }; O?.registerListener ? O.registerListener(document, "yt-navigate-finish", e) : document.addEventListener("yt-navigate-finish", e); try { window.addEventListener("ytp:nav-refresh", () => { try { e(); } catch (t) {} }); } catch (t) {} } function x() { s(), b(), P.log("Cleanup completed"); } if (window.__ytpChannelStatsModuleInit) { return; } window.__ytpChannelStatsModuleInit = !0; const k = t.setSafeHTML, S = t?.createVisibilityAwareInterval || ((t, e) => { const o = setInterval(() => { document.hidden || t(); }, e); return { stop() { clearInterval(o); }, pause() { clearInterval(o); }, resume() {}, get active() { return !0; } }; }), T = setTimeout.bind(window), L = t.$, M = t.byId, C = t.t, E = window.YouTubeUtils?.safeLS || { getItem: (t, e = null) => { try { return localStorage.getItem(t) ?? e; } catch (t) { return e; } }, setItem: (t, e) => { try { return localStorage.setItem(t, e), !0; } catch (t) { return !1; } }, removeItem: t => { try { localStorage.removeItem(t); } catch (t) {} } }, z = { OPTIONS: [ "subscribers", "views", "videos" ], FONT_LINK: "https://fonts.googleapis.com/css2?family=Rubik:wght@400;700&display=swap", STATS_API_URL: "https://api.livecounts.io/youtube-live-subscriber-counter/stats/", DEFAULT_UPDATE_INTERVAL: 5e3, DEFAULT_OVERLAY_OPACITY: .75, MAX_RETRIES: 3, CACHE_DURATION: 3e5, DEBOUNCE_DELAY: 100, STORAGE_KEY: "youtube_channel_stats_settings" }, _ = { overlay: null, isUpdating: !1, intervalId: null, currentChannelName: null, currentChannelId: null, enabled: "false" !== E.getItem(z.STORAGE_KEY), updateInterval: parseInt(E.getItem("youtubeEnhancerInterval") || "", 10) || z.DEFAULT_UPDATE_INTERVAL, overlayOpacity: parseFloat(E.getItem("youtubeEnhancerOpacity") || "") || z.DEFAULT_OVERLAY_OPACITY, lastSuccessfulStats: new Map, previousStats: new Map, channelIdCache: new Map, lastChannelIdWarnAt: 0, previousUrl: location.href, isChecking: !1, documentListenerKeys: new Set, overlayEnsureScheduler: null, pageObserversAttached: !1, navigationListenerAttached: !1 }, I = () => { try { const e = document.getElementById("ytp-plus-setting-enableChannelStats"); if (!(e instanceof HTMLInputElement)) { return; } if (e.dataset.handlerAttached) { return; } e.dataset.handlerAttached = "true", e.checked = _.enabled, e.addEventListener("change", e => { _.enabled = e.target.checked, E.setItem(z.STORAGE_KEY, _.enabled ? "true" : "false"), _.enabled ? (w(), v(), T(() => { const e = M("page-header-banner-sizer"); e instanceof HTMLElement && t?.isChannelPage?.() && f(e); }, 100)) : s(); }); } catch (t) {} }; e() && I(), t?.cleanupManager?.registerListener ? t.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", () => { I(); }) : document.addEventListener("youtube-plus-settings-modal-opened", () => { I(); }); const A = (t, e, o) => { if (t.size >= 50) { const e = t.keys().next().value; t.delete(e); } t.set(e, o); }, P = { log: (e, ...o) => { const r = t; r?.logger?.debug?.("[YouTube+][Stats]", e, ...o); }, warn: (t, ...e) => { window.console.warn("[YouTube+][Stats]", t, ...e); }, error: (t, ...e) => { window.console.error("[YouTube+][Stats]", t, ...e); }, debounce: t.debounce }, {OPTIONS: j} = z, {FONT_LINK: H} = z, {STATS_API_URL: D} = z, O = t?.cleanupManager; O?.registerListener ? (O.registerListener(document, "yt-navigate-finish", r, { passive: !0 }), O.registerListener(window, "popstate", r, { passive: !0 })) : (document.addEventListener("yt-navigate-finish", r, { passive: !0 }), window.addEventListener("popstate", r, { passive: !0 })); const B = t => { const {target: e} = t, o = e, r = o?.closest?.(".ytp-plus-settings-nav-item"); "experimental" === r?.dataset?.section && I(); }; if (O?.registerListener) { O.registerListener(document, "youtube-plus-language-changed", () => { I(); }); } else { const e = () => { I(); }; document.addEventListener("youtube-plus-language-changed", e); try { t?.cleanupManager?.register?.(() => document.removeEventListener("youtube-plus-language-changed", e)); } catch (e) { t.logSuppressed(e, "Stats"); } } if (O?.registerListener) { const t = O.registerListener(document, "click", B, !0); _.documentListenerKeys.add(t); } else { document.addEventListener("click", B, !0); try { t?.cleanupManager?.register?.(() => document.removeEventListener("click", B, !0)); } catch (e) { t.logSuppressed(e, "Stats"); } } O?.registerListener ? O.registerListener(window, "beforeunload", x) : window.addEventListener("beforeunload", x), "undefined" != typeof window && (window.YouTubeStats = { init: i, cleanup: x, version: "2.4.5" }), i(); }; document.addEventListener("youtube-plus-settings-modal-opened", o, { once: !1 }), t?.whenRelevant ? t.whenRelevant({ name: "stats.channel", isRelevant: () => (() => { try { const t = location.pathname || ""; return t.startsWith("/@") || t.startsWith("/channel/") || t.startsWith("/c/"); } catch (t) { return !1; } })() || e(), onEnter: o }) : "function" == typeof requestIdleCallback ? requestIdleCallback(o, { timeout: 2e3 }) : setTimeout(o, 0); })(), (function() { const t = window.YouTubeUtils, {t: e, logger: o} = t?.helpers ?? {}, r = { selectors: { deleteButtons: 'div[class^="VfPpkd-Bz112c-"], button[aria-label*="Delete"], button[aria-label*="Удалить"], button[aria-label*="Remove"]', menuButton: '[aria-haspopup="menu"]' }, classes: { checkbox: "comment-checkbox", checkboxAnchor: "comment-checkbox-anchor", checkboxFloating: "comment-checkbox-floating", container: "comment-controls-container", panel: "comment-controls-panel", header: "comment-controls-header", title: "comment-controls-title", actions: "comment-controls-actions", button: "comment-controls-button", buttonDanger: "comment-controls-button--danger", buttonPrimary: "comment-controls-button--primary", buttonSuccess: "comment-controls-button--success", close: "comment-controls-close", deleteButton: "comment-controls-button-delete" }, debounceDelay: 100, deleteDelay: 200, enabled: !0, storageKey: "youtube_comment_manager_settings" }, i = { observer: null, isProcessing: !1, settingsNavListenerKey: null, panelCollapsed: !1, initialized: !1, settingsIntegrationInitialized: !1, rootSubId: null, navSubId: null }, a = (() => { let e = "en"; try { e = t.getLanguage(); } catch (e) { t.logSuppressed(e, "Comment"); } return `https://myactivity.google.com/page?hl=${encodeURIComponent(e)}&utm_medium=web&utm_source=youtube&page=youtube_comments`; })(), s = () => { const t = String(location.hostname || "").toLowerCase(); return "myactivity.google.com" === t || t.endsWith(".myactivity.google.com"); }, c = (() => { try { return s(); } catch (t) { return !1; } })(), l = t.debounce, d = e => t.$(e), u = e => t.$$(e), p = (t, e) => window.YouTubePlusErrorBoundary?.withErrorBoundary ? window.YouTubePlusErrorBoundary.withErrorBoundary(t, "CommentManager") : (...r) => { try { return t(...r); } catch (t) { return ((t, e) => { const r = e instanceof Error ? e : new Error(String(e)); window.YouTubePlusErrorBoundary ? window.YouTubePlusErrorBoundary.logError(r, { context: t }) : o?.error?.("CommentManager", t, e); })(e, t), null; } }, y = p(() => { r.enabled && !i.isProcessing && u(r.selectors.deleteButtons).forEach(t => { const o = t.parentNode; if (t.closest(r.selectors.menuButton) || o?.querySelector?.(`.${r.classes.checkbox}`)) { return; } const i = t.closest('[class*="comment"]') || t.closest('[role="article"]') || o; i && i instanceof Element && (i.hasAttribute("data-comment-text") || i.setAttribute("data-comment-text", (i.textContent || "").toLowerCase())); const a = document.createElement("input"); a.type = "checkbox", a.className = `${r.classes.checkbox} ytp-plus-settings-checkbox`, a.setAttribute("aria-label", e("selectComment")), a.addEventListener("change", f), a.addEventListener("click", t => t.stopPropagation()); const s = i?.querySelector ? i.querySelector('[class*="date"],[class*="time"],time,[title*="20"],[aria-label*="ago"]') : null; s && s instanceof Element ? (s.classList.add(r.classes.checkboxAnchor), a.classList.add(r.classes.checkboxFloating), s.appendChild(a)) : o?.insertBefore && o.insertBefore(a, t); }); }, "addCheckboxes"), m = p(() => { if (!r.enabled || d(`.${r.classes.container}`)) { return; } const o = u(r.selectors.deleteButtons); if (!o.length) { return; } const a = o[0], s = a?.parentNode?.parentNode; if (!(s && s instanceof Element)) { return; } const c = document.createElement("div"); c.className = `${r.classes.container} ${r.classes.panel} glass-panel`, c.setAttribute("role", "region"), c.setAttribute("aria-label", e("commentManagerControls")); const l = document.createElement("div"); l.className = r.classes.header; const p = document.createElement("div"); p.className = r.classes.title, p.textContent = e("commentManager"); const y = document.createElement("button"); y.className = `${r.classes.close} ytp-plus-settings-close`, y.setAttribute("type", "button"), y.setAttribute("aria-expanded", String(!i.panelCollapsed)), y.setAttribute("aria-label", e("togglePanel")), t.renderTemplateClone(y, '\n <svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>\n </svg>\n '); const m = t => { i.panelCollapsed = t, l.classList.toggle("is-collapsed", t), h.classList.toggle("is-hidden", t), y.setAttribute("aria-expanded", String(!t)), c.classList.toggle("is-collapsed", t); }; y.addEventListener("click", () => { i.panelCollapsed = !i.panelCollapsed, m(i.panelCollapsed); }), l.append(p, y); const h = document.createElement("div"); h.className = r.classes.actions; const g = (t, e, o, i = {}) => { const a = document.createElement("button"); return a.type = "button", a.textContent = t, a.className = `${r.classes.button} ${e}`, i.id && (a.id = i.id), i.disabled && (a.disabled = !0), a.addEventListener("click", o), a; }, w = g(e("deleteSelected"), `${r.classes.buttonDanger} ${r.classes.deleteButton}`, b, { disabled: !0 }), v = g(e("selectAll"), r.classes.buttonPrimary, () => { u(`.${r.classes.checkbox}`).forEach(t => t.checked = !0), f(); }), x = g(e("clearAll"), r.classes.buttonSuccess, () => { u(`.${r.classes.checkbox}`).forEach(t => t.checked = !1), f(); }); h.append(w, v, x), m(i.panelCollapsed), c.append(l, h); const k = o[0]?.parentNode; k?.parentNode ? s.insertBefore(c, k) : s.appendChild(c); }, "addControlButtons"), f = p(() => { const t = d(`.${r.classes.deleteButton}`); if (!(t instanceof HTMLButtonElement)) { return; } const e = Array.from(u(`.${r.classes.checkbox}`)).some(t => t.checked); t.disabled = !e, t.style.opacity = e ? "1" : "0.6"; }, "updateDeleteButtonState"), b = p(() => { const t = Array.from(u(`.${r.classes.checkbox}`)).filter(t => t.checked); t.length && confirm(`Delete ${t.length} comment(s)?`) && (i.isProcessing = !0, t.forEach((t, e) => { setTimeout(() => { const e = t.nextElementSibling || t.parentElement?.querySelector(r.selectors.deleteButtons) || null; e?.click(); }, e * r.deleteDelay); }), setTimeout(() => i.isProcessing = !1, t.length * r.deleteDelay + 1e3)); }, "deleteSelectedComments"), h = p(() => { u(`.${r.classes.checkbox}`).forEach(t => t.remove()), d(`.${r.classes.container}`)?.remove(); }, "cleanup"), g = p(() => { r.enabled ? (y(), m(), f()) : h(); }, "initializeScript"), w = p(() => { (e => { try { const o = t?.StyleManager; o && "function" == typeof o.add && o.add("comment-delete-styles", e); } catch (t) { o?.warn?.("CommentManager", "Failed to inject comment delete styles", t); } })(`\n .${r.classes.checkboxAnchor}{position:relative;display:inline-flex;align-items:center;gap:8px;width:auto;}\n .${r.classes.checkboxFloating}{position:absolute;top:-4px;right:-32px;margin:0;}\n /* Panel styled to match shorts feedback: glassmorphism, rounded corners, soft shadow */\n .${r.classes.panel}{position:fixed;top:50%;right:24px;transform:translateY(-50%);display:flex;flex-direction:column;gap:14px;z-index:10000;padding:16px 18px;background:var(--yt-glass-bg);border:1.5px solid var(--yt-glass-border);border-radius:20px;box-shadow:var(--yt-glass-shadow);backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%);min-width:220px;max-width:300px;color:var(--yt-text-primary);transition:transform .22s cubic-bezier(.4,0,.2,1),opacity .22s,box-shadow .2s}\n html[data-ytp-theme="light"] .${r.classes.panel},html:not([dark]):not([data-ytp-theme="dark"]) .${r.classes.panel}{background:var(--yt-glass-bg);}\n .${r.classes.header}{display:flex;align-items:center;justify-content:space-between;gap:12px;}\n .${r.classes.panel}.is-collapsed{padding:14px 18px;}\n .${r.classes.panel}.is-collapsed .${r.classes.title}{font-weight:500;opacity:.85;}\n .${r.classes.panel}.is-collapsed .${r.classes.close}{transform:rotate(45deg);}\n .${r.classes.panel}.is-collapsed .${r.classes.actions}{display:none!important;}\n .${r.classes.title}{font-size:15px;font-weight:600;letter-spacing:.3px;}\n .${r.classes.close}{background:transparent;border:none;cursor:pointer;padding:6px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:var(--yt-text-primary);transition:transform .2s cubic-bezier(0.2,0,0,1),color .2s cubic-bezier(0.2,0,0,1);}\n .${r.classes.close}:hover{transform:rotate(90deg) scale(1.05);color:var(--yt-accent);}\n .${r.classes.close}:active{transform:rotate(90deg) scale(0.96) !important;}\n .${r.classes.actions}{display:flex;flex-direction:column;gap:10px;}\n .${r.classes.actions}.is-hidden{display:none!important;}\n .${r.classes.button}{padding:12px 16px;border-radius:var(--yt-radius-md);border:1px solid var(--yt-glass-border);cursor:pointer;font-size:13px;font-weight:500;background:var(--yt-button-bg);color:var(--yt-text-primary);transition:background-color .2s cubic-bezier(0.2,0,0,1),border-color .2s cubic-bezier(0.2,0,0,1),color .2s cubic-bezier(0.2,0,0,1),transform .1s cubic-bezier(0.2,0,0,1),box-shadow .2s cubic-bezier(0.2,0,0,1);text-align:center;}\n .${r.classes.button}:disabled{opacity:.5;cursor:not-allowed;}\n .${r.classes.button}:not(:disabled):hover{transform:translateY(-1px);box-shadow:var(--yt-shadow);}\n .${r.classes.button}:not(:disabled):active{transform:scale(0.96) !important;}\n .${r.classes.buttonDanger}{background:var(--yt-danger-soft);border-color:var(--yt-danger-border);color:var(--yt-danger-text);}\n .${r.classes.buttonPrimary}{background:var(--yt-primary-soft);border-color:var(--yt-primary-border);color:var(--yt-primary-text);}\n .${r.classes.buttonSuccess}{background:var(--yt-success-soft);border-color:var(--yt-success);color:var(--yt-success);}\n .${r.classes.buttonDanger}:not(:disabled):hover{background:var(--yt-danger-soft-hover);}\n .${r.classes.buttonPrimary}:not(:disabled):hover{background:var(--yt-primary-soft-hover);}\n .${r.classes.buttonSuccess}:not(:disabled):hover{background:var(--yt-success-soft-hover);}\n @media(max-width:1280px){\n .${r.classes.panel}{top:auto;bottom:24px;transform:none;right:16px;}\n }\n @media(max-width:768px){\n .${r.classes.panel}{position:fixed;left:16px;right:16px;bottom:16px;top:auto;transform:none;max-width:none;}\n .${r.classes.actions}{flex-direction:row;flex-wrap:wrap;}\n .${r.classes.button}{flex:1;min-width:140px;}\n }\n `); }, "addStyles"), v = () => { try { const t = document.getElementById("open-comment-history-page"); if (!t) { return; } if (t.dataset.handlerAttached) { return; } t.dataset.handlerAttached = "true", t.addEventListener("click", () => { window.open(a, "_blank"); }); } catch (t) {} }, x = () => { i.settingsIntegrationInitialized || (i.settingsIntegrationInitialized = !0, document.addEventListener("youtube-plus-settings-modal-opened", () => { v(); }), i.settingsNavListenerKey || (i.settingsNavListenerKey = ((e, o, r, i) => { try { if (t?.cleanupManager) { return t.cleanupManager.registerListener(e, o, r, i); } } catch (e) { t.logSuppressed(e, "Comment"); } try { e.addEventListener(o, r, i); } catch (e) { t.logSuppressed(e, "Comment"); } return null; })(document, "click", t => { const e = t.target, o = e?.closest?.(".ytp-plus-settings-nav-item"); "experimental" === o?.dataset?.section && v(); }, { passive: !0, capture: !0 }))); }, k = p(() => { if (i.initialized) { return; } (() => { try { const t = localStorage.getItem(r.storageKey); t && (r.enabled = JSON.parse(t).enabled ?? !0); } catch (e) { t.logSuppressed(e, "Comment"); } })(), w(); const e = window.YouTubePlusMutationCoordinator; e?.subscribeRoot ? i.rootSubId || (i.rootSubId = e.subscribeRoot("comment-manager-runtime", l(g, r.debounceDelay), { selector: "#comments, #content" })) : o?.warn?.("CommentManager", "MutationCoordinator unavailable"), "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", g) : g(), x(); }, "init"), S = () => (() => { try { return !!s() && "youtube_comments" === new URLSearchParams(location.search || "").get("page"); } catch (t) { return !1; } })(), T = () => { !i.initialized && S() && requestIdleCallback(() => { !i.initialized && S() && (k(), i.initialized = !0); }, { timeout: 2e3 }); }; if (x(), c) { const e = window.YouTubePlusMutationCoordinator; e?.subscribeRoot ? i.navSubId || (i.navSubId = e.subscribeRoot("comment-manager-navigation", l(() => { !i.initialized && S() && T(), i.initialized && i.navSubId && (e.unsubscribe(i.navSubId), i.navSubId = null); }, 300), { selector: "body" })) : o?.warn?.("CommentManager", "MutationCoordinator unavailable"), t?.whenRelevant ? t.whenRelevant({ name: "comment.manager", isRelevant: S, onEnter: T }) : T(); } })(), (function() { const t = window.YouTubeUtils, e = t?.t || (t => t), o = t?.logger || null, r = "ytp-comment-translate-btn", i = "data-ytp-translated", a = "data-ytp-original-text", s = t?.SETTINGS_KEY || "youtube_plus_settings", c = t?.setSafeHTML, l = setTimeout; let d = null; const u = e => t.$$(e), p = { ng: "en", "zh-CN": "zh-CN", "zh-TW": "zh-TW", ko: "ko", ja: "ja", nl: "nl", be: "be", bg: "bg", kk: "kk", ky: "ky", uz: "uz", uk: "uk", "zh-hans": "zh-CN", "zh-hant": "zh-TW", "zh-cn": "zh-CN", "zh-tw": "zh-TW", "zh-hk": "zh-TW", iw: "he", jv: "jw", "sr-latn": "sr", "pt-br": "pt", "pt-pt": "pt", ar: "ar", az: "az", cs: "cs", da: "da", de: "de", el: "el", en: "en", es: "es", fi: "fi", fr: "fr", hi: "hi", hr: "hr", hu: "hu", id: "id", it: "it", lt: "lt", lv: "lv", ms: "ms", no: "no", pl: "pl", ro: "ro", ru: "ru", sk: "sk", sl: "sl", sq: "sq", sv: "sv", th: "th", tr: "tr", vi: "vi" }, y = t => { if (!t) { return "en"; } const e = String(t).toLowerCase(); if (p[e]) { return p[e]; } const o = e.split("-")[0]; return p[o] || o || "en"; }, m = () => e("translateComment"), f = () => e("showOriginal"), b = (() => { let e = !1; return () => { if (e) { return; } e = !0; const i = `\n .${r}{\n display:inline-flex;align-items:center;gap:4px;\n background:none;border:none;cursor:pointer;\n color:var(--yt-text-secondary);\n font-size:1.2rem;line-height:1.8rem;font-weight:400;\n padding:4px 0;margin-top:4px;\n font-family:'Roboto','Arial',sans-serif;\n transition:color .2s;\n }\n .${r}:hover{color:var(--yt-text-primary);}\n .${r}[disabled]{opacity:.5;cursor:wait;}\n .${r} svg{flex-shrink:0;}\n `; try { const e = t?.StyleManager; e && "function" == typeof e.add && e.add("ytp-comment-translate-styles", i); } catch (t) { o?.warn?.("CommentTranslate", "Failed to inject translate styles", t); } }; })(), h = '<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12.87 15.07l-2.54-2.51.03-.03A17.52 17.52 0 0014.07 6H17V4h-7V2H8v2H1v2h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"/></svg>', g = (t = null) => { try { const e = t || window.youtubePlus?.settings || (() => { const t = window.YouTubePlusSettingsStore; if (t && "function" == typeof t.load) { return t.load(); } const e = JSON.parse(localStorage.getItem(s) || "{}"); return e && "object" == typeof e ? e : {}; })(); return !1 !== e?.enableCommentTranslate; } catch (t) { return !0; } }, w = () => { u(`.${r}`).forEach(t => t.remove()), u(`[${i}][${a}]`).forEach(t => { const e = t.getAttribute(a); e && (t.textContent = e), t.removeAttribute(i), t.removeAttribute(a); }); }, v = () => { d && (window.YouTubePlusMutationCoordinator?.unwatch?.(d), d = null); }, x = e => { if (e.querySelector(`.${r}`)) { return; } const s = e.querySelector("#content-text.ytd-comment-view-model, #content-text.ytd-comment-renderer, yt-attributed-string#content-text, yt-formatted-string#content-text, #content-text"); if (!s) { return; } const d = (s.textContent || "").trim(); if (!d || d.length < 2) { return; } const u = (() => { try { return y(t?.getLanguage?.()); } catch (t) { return y(navigator.language) || "en"; } })(), p = document.createElement("button"); p.className = r, p.type = "button", c?.(p, `${h} ${m()}`), p.setAttribute("aria-label", m()), p.addEventListener("click", async t => { if (t.preventDefault(), t.stopPropagation(), s.hasAttribute(i)) { const t = s.getAttribute(a); return void (t && (s.textContent = t, s.removeAttribute(i), c?.(p, `${h} ${m()}`), p.setAttribute("aria-label", m()))); } p.disabled = !0, c?.(p, `${h} ...`); const e = s.textContent || "", r = await (async (t, e) => { const r = new AbortController, i = l(() => r.abort(), 8e3); try { const o = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=${encodeURIComponent(e)}&dt=t&q=${encodeURIComponent(t)}`, i = await fetch(o, { signal: r.signal }); if (!i.ok) { throw new Error(`HTTP ${i.status}`); } const a = await i.json(); if (Array.isArray(a) && Array.isArray(a[0])) { return a[0].map(t => t?.[0] || "").join(""); } } catch (t) { "AbortError" !== t?.name && o?.warn?.("CommentTranslate", "Translation failed", t); } finally { clearTimeout(i); } return null; })(e, u); r && r !== e ? (s.setAttribute(a, e), s.setAttribute(i, "true"), s.textContent = r, c?.(p, `${h} ${f()}`), p.setAttribute("aria-label", f())) : (c?.(p, `${h} ${m()}`), p.setAttribute("aria-label", m())), p.disabled = !1; }); const b = e.querySelector("#action-buttons, ytd-comment-action-buttons-renderer, #toolbar"); b ? b.parentElement?.insertBefore(p, b) : s.after(p); }, k = () => { const t = [ "ytd-comment-view-model", "ytd-comment-renderer", "ytd-comment-thread-renderer" ]; for (const e of t) { u(e).forEach(t => { t instanceof Element && x(t); }); } }; let S = null; const T = (e = null) => { if (!g(e)) { return v(), void w(); } if (b(), k(), d) { return; } const o = t.$("#comments, #tab-comments, #content") || document.body, r = window.YouTubePlusMutationCoordinator; r?.watchTarget && (d = "comment::translateComments", r.watchTarget(d, o, t => { let e = !1; for (const o of t) { for (const t of o.addedNodes) { if (t instanceof Element && (t.matches?.("ytd-comment-view-model, ytd-comment-renderer, ytd-comment-thread-renderer") || t.querySelector?.("ytd-comment-view-model, ytd-comment-renderer, #content-text"))) { e = !0; break; } } if (e) { break; } } e && (S && clearTimeout(S), S = l(k, 300)); }, { childList: !0, attributes: !1, subtree: !0 })); }, L = () => { ("/watch" === location.pathname || location.pathname.startsWith("/shorts/")) && ("function" == typeof requestIdleCallback ? requestIdleCallback(() => T(), { timeout: 3e3 }) : l(T, 1500)); }; "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", L, { once: !0 }) : L(), window.addEventListener("yt-navigate-finish", L, { passive: !0 }), window.addEventListener("youtube-plus-settings-updated", t => { const e = t?.detail; g(e) ? T(e) : (v(), w()); }); })(), (function() { function t(t, e = {}, o = []) { const r = document.createElement(t); return Object.entries(e).forEach(([t, e]) => { "class" === t ? r.className = e : "html" === t ? window.YouTubeUtils?.setSafeHTML?.(r, e, !0) : t.startsWith("on") && "function" == typeof e ? r.addEventListener(t.substring(2).toLowerCase(), e) : r.setAttribute(t, String(e)); }), o.forEach(t => r.appendChild("string" == typeof t ? document.createTextNode(t) : t)), r; } function e(t) { if (window.YouTubeSafeDOM?.sanitizeHTML) { return window.YouTubeSafeDOM.sanitizeHTML(t); } if (s?.sanitizeHTML && "function" == typeof s.sanitizeHTML) { return s.sanitizeHTML(t); } if ("string" != typeof t) { return ""; } throw new Error("[report] sanitizeHTML called before YouTubeSafeDOM was ready"); } function o(t) { return !(!t || "string" != typeof t) && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t) && t.length <= 254; } function r() { try { return { version: window.YouTubePlusDebug?.version || "unknown", userAgent: navigator?.userAgent || "unknown", url: location?.href || "unknown", language: document.documentElement?.lang || navigator?.language || "unknown", settings: "object" == typeof s?.SettingsManager ? s.SettingsManager.load() : null }; } catch (t) { return s && "function" == typeof s.logError && s.logError("Report", "Failed to collect debug info", t), { version: "unknown", userAgent: "unknown", url: "unknown", language: "unknown", settings: null, error: "Failed to collect debug info" }; } } function i({type: t, title: e, description: o, email: i, includeDebug: a}) { const l = a ? r() : null, d = [], u = c("bug" === t ? "typeBug" : "feature" === t ? "typeFeature" : "typeOther"); if (d.push(`**Type:** ${u}`), i && d.push(`**Reporter email (optional):** ${i}`), d.push("\n**Description:**\n"), d.push(o || "(no description)"), l) { d.push("\n---\n**Debug info**\n"), d.push("```json"); try { d.push(JSON.stringify(l, null, 2)); } catch (t) { s && "function" == typeof s.logError && s.logError("Report", "Failed to stringify debug info", t); const e = { version: l.version || "unknown", userAgent: l.userAgent || "unknown", url: l.url || "unknown" }; try { d.push(JSON.stringify(e, null, 2)); } catch (t) { d.push('{ "error": "Failed to stringify debug info" }'); } } d.push("```"), d.push("\n_Please do not include sensitive personal data._"); } const p = d.join("\n"); return { title: `${"bug" === t ? "[Bug]" : "feature" === t ? "[Feature]" : "[Report]"} ${e || ""}`.trim(), body: p }; } const a = setTimeout, s = window.YouTubeUtils || {}, c = s.t || (t => t || ""); try { window.youtubePlusReport = window.youtubePlusReport || {}, window.youtubePlusReport.render = function(l) { function d() { const t = y.value, r = w.value.trim(), i = x.value.trim(), a = v.value.trim(), s = S.querySelector("input").checked, l = []; return r ? r.length < 5 && l.push(c("titleMin")) : l.push(c("titleRequired")), i ? i.length < 10 && l.push(c("descMin")) : l.push(c("descRequired")), a && !o(a) && l.push(c("invalidEmail")), { type: t, title: (u = r, u && "string" == typeof u ? e(u.trim().substring(0, 200)) : ""), description: (d = i, d && "string" == typeof d ? e(d.trim().substring(0, 5e3)) : ""), email: a && o(a) ? a : "", includeDebug: s, errors: l }; var d, u; } if (!l?.querySelector) { return; } const u = l.querySelector('.ytp-plus-settings-section[data-section="report"]'); if (!u) { return; } u.replaceChildren(); const p = t("div", { style: "display:flex;flex-direction:column;gap:var(--yt-space-sm);margin-top:var(--yt-space-md);" }), y = t("select", { style: "display:none;" }, []), m = [ { v: "bug", l: c("typeBug") }, { v: "feature", l: c("typeFeature") }, { v: "other", l: c("typeOther") } ]; m.forEach(e => { const o = t("option", { value: e.v }, [ e.l ]); y.appendChild(o); }); const f = t("div", { class: "glass-dropdown", id: "report-type-dropdown", tabindex: "0", role: "listbox", "aria-expanded": "false" }), b = t("button", { class: "glass-dropdown__toggle", type: "button", "aria-haspopup": "listbox" }, [ t("span", { class: "glass-dropdown__label" }, [ m[0].l ]) ]); b.appendChild(t("svg", { class: "glass-dropdown__chev", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, [ t("polyline", { points: "6 9 12 15 18 9" }, []) ])); const h = t("ul", { class: "glass-dropdown__list", role: "presentation" }, []); m.forEach((e, o) => { const r = t("li", { class: "glass-dropdown__item", "data-value": e.v, role: "option" }, [ e.l ]); 0 === o && r.setAttribute("aria-selected", "true"), h.appendChild(r); }), f.appendChild(b), f.appendChild(h); const g = "padding:var(--yt-space-sm);border-radius:var(--yt-radius-sm);background:var(--yt-input-bg);color:var(--yt-text-primary);border:1px solid var(--yt-glass-border);backdrop-filter:var(--yt-glass-blur-light);-webkit-backdrop-filter:var(--yt-glass-blur-light);font-size:14px;transition:var(--yt-transition);box-sizing:border-box;", w = t("input", { placeholder: c("shortTitle"), style: g }), v = t("input", { placeholder: c("emailOptional"), type: "email", style: g }), x = t("textarea", { placeholder: c("descriptionPlaceholder"), rows: 6, style: `${g}resize:vertical;font-family:inherit;` }), k = t("input", { type: "checkbox", class: "ytp-plus-settings-checkbox" }), S = t("label", { style: "font-size:13px;display:flex;gap:var(--yt-space-sm);align-items:center;color:var(--yt-text-primary);cursor:pointer;align-self:center;" }, [ k, ` ${c("includeDebug")}` ]), T = t("div", { style: "display:flex;gap:var(--yt-space-sm);margin-top:var(--yt-space-sm);flex-wrap:wrap;justify-content:center;" }), L = t("button", { class: "glass-button" }, [ c("openGitHub") ]), M = t("button", { class: "glass-button" }, [ c("copyReport") ]), C = t("button", { class: "glass-button" }, [ c("prepareEmail") ]); T.appendChild(L), T.appendChild(M), T.appendChild(C), p.appendChild(y), p.appendChild(f), p.appendChild(w), p.appendChild(v), p.appendChild(x), p.appendChild(S); const E = t("div", { class: "glass-card", style: "overflow:auto;max-height:240px;font-size:11px;display:none;margin-top:var(--yt-space-sm);padding:8px;box-sizing:border-box;" }, []); p.appendChild(E), p.appendChild(T); const z = t("div", { class: "ytp-plus-settings-item-description", style: "margin-top:var(--yt-space-sm);font-size:12px;color:var(--yt-text-secondary);" }, [ c("privacy") ]); u.appendChild(p), u.appendChild(z); try { window.YouTubePlusDesignSystem?.initGlassDropdown?.({ dropdown: f, hiddenSelect: y }); } catch (t) { s && "function" == typeof s.logError && s.logError("Report", "initReportTypeDropdown", t); } k.addEventListener("change", function() { try { if (k.checked) { const e = r(); E.replaceChildren(); const o = t("div", { style: "display:flex;flex-direction:column;gap:6px;margin-bottom:6px;" }, []); o.appendChild(t("div", {}, [ "Version: ", t("strong", {}, [ String(e.version || "unknown") ]) ])), o.appendChild(t("div", {}, [ "User agent: ", t("code", { style: "font-size:11px;color:var(--yt-text-secondary);" }, [ String(e.userAgent || "") ]) ])); const i = String(e.url || "unknown"); let a = t("span", {}, [ i ]); try { /^https?:\/\//i.test(i) && (a = t("a", { href: i, target: "_blank", rel: "noopener noreferrer", style: "color:var(--yt-accent);word-break:break-all;" }, [ i ])); } catch (e) { s && "function" == typeof s.logError && s.logError("Report", "URL link creation failed", e), a = t("span", {}, [ String(i) ]); } if (o.appendChild(t("div", {}, [ "URL: ", a ])), o.appendChild(t("div", {}, [ "Language: ", t("code", {}, [ String(e.language || "") ]) ])), E.appendChild(o), e.settings) { const o = t("details", {}, [ t("summary", {}, [ "Settings" ]) ]); o.appendChild(t("pre", { style: "white-space:pre-wrap;margin:6px 0 0 0;font-size:11px;" }, [ JSON.stringify(e.settings, null, 2) ])), E.appendChild(o); } const c = t("details", {}, [ t("summary", {}, [ "Full debug JSON" ]) ]); c.appendChild(t("pre", { style: "white-space:pre-wrap;margin:6px 0 0 0;font-size:11px;" }, [ JSON.stringify(e, null, 2) ])), E.appendChild(c), E.style.display = "block"; } else { E.replaceChildren(), E.style.display = "none"; } } catch (t) { s && "function" == typeof s.logError && s.logError("Report", "updateDebugPreview failed", t); } }), L.addEventListener("click", t => { if (t.preventDefault(), !L.disabled) { try { const t = d(); if (t.errors && t.errors.length > 0) { const e = c("fixErrorsPrefix") + t.errors.join("\n• "); return void (s.NotificationManager && "function" == typeof s.NotificationManager.show ? s.NotificationManager.show(e, { duration: 4e3, type: "error" }) : window.YouTubeUtils?.logger?.warn?.("Report", "Validation errors", t.errors)); } const e = L.textContent; L.disabled = !0, L.textContent = c("opening"), L.style.opacity = "0.6", (function(t, e) { try { const o = "diorhc", r = "YTP", i = "feature" === e ? `https://github.com/${o}/${r}/discussions/new?category=ideas&title=${encodeURIComponent(t.title)}&body=${encodeURIComponent(t.body)}` : `https://github.com/${o}/${r}/issues/new?title=${encodeURIComponent(t.title)}&body=${encodeURIComponent(t.body)}`; window.open(i, "_blank"); } catch (t) { throw s && "function" == typeof s.logError && s.logError("Report", "Failed to open GitHub issue", t), t; } })(i(t), "feature" === t.type ? "feature" : "other" === t.type ? "other" : "bug"), s.NotificationManager && "function" == typeof s.NotificationManager.show && s.NotificationManager.show(c("openingGithubNotification"), { duration: 2500 }), a(() => { L.disabled = !1, L.textContent = e, L.style.opacity = "1"; }, 2e3); } catch (t) { s.logError && s.logError("Report", "Failed to open GitHub issue", t), s.NotificationManager && "function" == typeof s.NotificationManager.show && s.NotificationManager.show(c("failedOpenGithub"), { duration: 3e3, type: "error" }), L.disabled = !1, L.textContent = c("openGitHub"), L.style.opacity = "1"; } } }), M.addEventListener("click", t => { var e; if (t.preventDefault(), !M.disabled) { try { const t = d(); if (t.errors && t.errors.length > 0) { const e = c("fixErrorsPrefix") + t.errors.join("\n• "); return void (s.NotificationManager && "function" == typeof s.NotificationManager.show ? s.NotificationManager.show(e, { duration: 4e3, type: "error" }) : window.YouTubeUtils?.logger?.warn?.("Report", "Validation errors", t.errors)); } const o = M.textContent; M.disabled = !0, M.textContent = c("copying"), M.style.opacity = "0.6"; const r = i(t); (e = `Title: ${r.title}\n\n${r.body}`, navigator.clipboard?.writeText ? navigator.clipboard.writeText(e) : new Promise((t, o) => { const r = document.createElement("textarea"); r.value = e, r.style.position = "fixed", r.style.left = "-9999px", r.style.opacity = "0", document.body.appendChild(r); try { r.select(), r.setSelectionRange(0, e.length); const i = document.execCommand("copy"); document.body.removeChild(r), i ? t() : o(new Error("execCommand failed")); } catch (t) { document.body.removeChild(r), o(t); } })).then(() => { s.NotificationManager && "function" == typeof s.NotificationManager.show && s.NotificationManager.show(c("reportCopied"), { duration: 2e3 }), M.textContent = c("copied"), M.style.opacity = "1", a(() => { M.disabled = !1, M.textContent = o; }, 2e3); }).catch(t => { s && "function" == typeof s.logError && s.logError("Report", "copy failed", t), s?.NotificationManager && "function" == typeof s.NotificationManager.show ? s.NotificationManager.show(c("copyFailed"), { duration: 3e3, type: "error" }) : window.YouTubeUtils?.logger?.warn?.("Report", "Copy failed; please copy manually", t), M.disabled = !1, M.textContent = o, M.style.opacity = "1"; }); } catch (t) { s.logError && s.logError("Report", "Failed to copy report", t), M.disabled = !1, M.textContent = c("copyReport"), M.style.opacity = "1"; } } }), C.addEventListener("click", t => { if (t.preventDefault(), !C.disabled) { try { const t = d(); if (t.errors && t.errors.length > 0) { const e = c("fixErrorsPrefix") + t.errors.join("\n• "); return void (s.NotificationManager && "function" == typeof s.NotificationManager.show ? s.NotificationManager.show(e, { duration: 4e3, type: "error" }) : window.YouTubeUtils?.logger?.warn?.("Report", "Validation errors", t.errors)); } const e = C.textContent; C.disabled = !0, C.textContent = c("opening"), C.style.opacity = "0.6"; const o = i(t), r = `mailto:?subject=${encodeURIComponent(o.title)}&body=${encodeURIComponent(o.body)}`; window.location.href = r, a(() => { C.disabled = !1, C.textContent = e, C.style.opacity = "1"; }, 2e3); } catch (t) { s.logError && s.logError("Report", "Failed to prepare email", t), C.disabled = !1, C.textContent = c("prepareEmail"), C.style.opacity = "1"; } } }); }; } catch (t) { s.logError && s.logError("Report", "Failed to attach report module to window", t); } })(), (function() { function t(t, e) { const o = d(), r = Math.abs(Number(t)) || 0; if ("ru" === o) { const t = (function(t) { return { day: [ "день", "дня", "дней" ], hour: [ "час", "часа", "часов" ], minute: [ "минута", "минуты", "минут" ] }[t] || [ "дней", "дней", "дней" ]; })(e), o = (function(t) { const e = t % 10, o = t % 100; return 1 === e && 11 !== o ? 0 : e >= 2 && e <= 4 && !(o >= 12 && o <= 14) ? 1 : 2; })(r); return `${r} ${t[o]}`; } const i = (function(t) { return { day: [ "day", "days" ], hour: [ "hour", "hours" ], minute: [ "minute", "minutes" ] }[t] || [ "minutes", "minutes" ]; })(e); return `${r} ${1 === r ? i[0] : i[1]}`; } const e = setTimeout.bind(window), o = (t, e) => { const o = window.YouTubeUtils?.StyleManager; if (o && "function" == typeof o.add) { return void o.add(t, e); } let r = document.getElementById(t); r || (r = document.createElement("style"), r.id = t, (document.head || document.documentElement).appendChild(r)), r.textContent = e; }, r = [ "M21.5 2v6h-6M2.5 22v-6h6", "M19.13 11.48A10 10 0 0 0 12 2C6.48 2 2 6.48 2 12c0 .34.02.67.05 1M4.87 12.52A10 10 0 0 0 12 22c5.52 0 10-4.48 10-10 0-.34-.02-.67-.05-1" ], i = (t, e, o) => { t instanceof HTMLElement && t.replaceChildren((t => { const e = document.createElementNS("http://www.w3.org/2000/svg", "svg"); e.setAttribute("width", "16"), e.setAttribute("height", "16"), e.setAttribute("viewBox", "0 0 24 24"), e.setAttribute("fill", "none"), e.setAttribute("stroke", "currentColor"), e.setAttribute("stroke-width", "2"), e.setAttribute("stroke-linecap", "round"), e.setAttribute("stroke-linejoin", "round"), e.style.display = "inline-block", e.style.flexShrink = "0", e.style.verticalAlign = "middle", t && (e.style.animation = "spin .8s linear infinite"); for (const t of r) { const o = document.createElementNS("http://www.w3.org/2000/svg", "path"); o.setAttribute("d", t), e.appendChild(o); } return e; })(o), document.createTextNode(e)); }, a = window.YouTubeUtils?.t || (t => t || ""), s = window.YouTubeUtils?.logger || null, c = window.YouTubeUtils, l = window.YouTubeUtils.byId, d = () => window.YouTubeUtils.getLanguage(), u = { enabled: !0, checkInterval: 864e5, updateUrl: "https://update.greasyfork.org/scripts/537017/YouTube%20%2B.meta.js", currentVersion: "2.5.2", storageKey: "youtube_plus_update_check", notificationDuration: 8e3, autoInstallUrl: "https://update.greasyfork.org/scripts/537017/YouTube%20%2B.user.js", autoInstallOnCheck: !1, showNotificationIcon: !1 }, p = "undefined" == typeof window ? null : window, y = p?.GM || null, m = p?.GM_info || null, f = (() => { if (p) { if ("function" == typeof p.GM_openInTab) { return p.GM_openInTab.bind(p); } if (y?.openInTab) { return y.openInTab.bind(y); } } return null; })(); m?.script?.version && (u.currentVersion = m.script.version); const b = { lastCheck: 0, lastVersion: u.currentVersion, updateAvailable: !1, checkInProgress: !1, updateDetails: null }, h = t => { const e = String(t || "").trim(); if (!e) { return !1; } const o = e.split("."); return !(o.length < 1 || o.length > 3) && o.every(t => t.length > 0 && Array.from(t).every(t => t >= "0" && t <= "9")); }, g = (t, e) => { const o = `@${e} `, r = String(t || "").replace(/\r/g, "").split("\n"); for (const t of r) { const e = t.trimStart().replace(/^\/\/\s*/, "").replace(/^\/\*\s*/, ""); if (e.startsWith(o)) { return e.slice(o.length).trim(); } } return ""; }, w = t => { if (null == t || "" === t) { return { version: null, description: "", downloadUrl: u.autoInstallUrl }; } if ("string" != typeof t) { if ("string" != typeof t?.responseText) { return s?.debug?.("Update", "Skipping non-string metadata payload: " + typeof t), { version: null, description: "", downloadUrl: u.autoInstallUrl }; } t = t.responseText; } if (t.length > 1e5) { return s?.debug?.("Update", `Skipping oversized metadata payload: ${t.length}`), { version: null, description: "", downloadUrl: u.autoInstallUrl }; } const e = String(t || "").replace(/\r/g, ""); if (!e.includes("==UserScript==") && !e.includes("@version")) { return s?.debug?.("Update", "Skipping non-userscript metadata response"), { version: null, description: "", downloadUrl: u.autoInstallUrl }; } let o = g(e, "version"); const r = g(e, "description"), i = g(e, "downloadURL") || u.autoInstallUrl; return o && (o = o.replace(/^v/i, "").trim(), !h(o)) ? (s?.error?.("Update", `Invalid version format in metadata: ${o}`), { version: null, description: "", downloadUrl: u.autoInstallUrl }) : { version: o, description: r.substring(0, 500), downloadUrl: i }; }, v = (t, e = "info", o = 3e3) => { try { YouTubeUtils.NotificationManager.show(t, { type: e, duration: o }); } catch (o) { window.YouTubeUtils && YouTubeUtils.logger?.debug?.(`[YouTube+] ${e.toUpperCase()}:`, t, o); } }, x = t => { if (t?.version && "string" == typeof t.version) { try { sessionStorage.setItem("update_dismissed", t.version); } catch (t) { s?.error?.("Update", "Failed to persist dismissal state", t); } } }, k = (t = b.updateDetails) => { const e = t?.downloadUrl || u.autoInstallUrl, o = (t => { if (!t || "string" != typeof t) { return { valid: !1, error: "Invalid download URL for installation" }; } try { const e = new URL(t); return "https:" !== e.protocol ? { valid: !1, error: "Only HTTPS URLs allowed for updates" } : [ "update.greasyfork.org", "greasyfork.org" ].includes(e.hostname) ? { valid: !0, error: null } : { valid: !1, error: `Update URL domain not in allowlist: ${e.hostname}` }; } catch (t) { return { valid: !1, error: `Invalid URL format: ${t.message}` }; } })(e); if (!o.valid) { return s?.error?.("Update", o.error || "Update URL validation failed"), !1; } const r = (t => { if (f) { try { return f(t, { active: !0, insert: !0, setParent: !0 }), !0; } catch (t) { s?.error?.("Update", "GM_openInTab update install failed", t); } } try { if (window.open(t, "_blank", "noopener")) { return !0; } } catch (t) { s?.error?.("Update", "window.open update install failed", t); } try { return window.location.assign(t), !0; } catch (t) { s?.error?.("Update", "Navigation to update URL failed", t); } return !1; })(e); return r && x(t), r; }, S = async (t = u.updateUrl) => (async t => { if ("undefined" != typeof GM_xmlhttpRequest) { return new Promise((o, r) => { const i = e(() => r(new Error("Update check timeout")), 1e4); GM_xmlhttpRequest({ method: "GET", url: t, timeout: 1e4, headers: { Accept: "text/plain", "User-Agent": "YouTube+ UpdateChecker" }, onload: t => { clearTimeout(i), t.status >= 200 && t.status < 300 ? o(t.responseText) : r(new Error(`HTTP ${t.status}: ${t.statusText}`)); }, onerror: t => { clearTimeout(i), r(new Error(`Network error: ${t}`)); }, ontimeout: () => { clearTimeout(i), r(new Error("Update check timeout")); } }); }); } const o = new AbortController, r = e(() => o.abort(), 1e4); try { const e = await fetch(t, { method: "GET", cache: "no-cache", signal: o.signal, headers: { Accept: "text/plain", "User-Agent": "YouTube+ UpdateChecker" } }); if (!e.ok) { throw new Error(`HTTP ${e.status}: ${e.statusText}`); } return await e.text(); } finally { clearTimeout(r); } })(t), T = async (t = !1, r = 0) => { const i = Date.now(); if (((t, e) => !(!u.enabled || b.checkInProgress) && (t || e - b.lastCheck >= u.checkInterval))(t, i)) { b.checkInProgress = !0; try { (() => { try { return (t => { const e = new URL(t); if ("https:" !== e.protocol) { throw new Error("Update URL must use HTTPS"); } if (!e.hostname.includes("greasyfork.org")) { throw new Error("Update URL must be from greasyfork.org"); } })(u.updateUrl), !0; } catch (t) { throw s?.error?.("Update", "Invalid update URL configuration", t), t; } })(); const r = await (async () => { let t = await S(u.updateUrl), o = w(t); if (!o.version) { try { const e = await S(u.autoInstallUrl), r = w(e); r.version && (o = r, t = e); } catch (t) { s?.warn?.("Update", `Fallback metadata fetch failed: ${t.message}`); } } if (o.version) { try { const t = await (async t => { try { const o = `https://greasyfork.org/${d()}/scripts/537017-youtube/versions`, r = async t => { if ("undefined" != typeof GM_xmlhttpRequest) { return new Promise((o, r) => { const i = e(() => r(new Error("Changelog fetch timeout")), 1e4); GM_xmlhttpRequest({ method: "GET", url: t, timeout: 1e4, headers: { Accept: "text/html" }, onload: t => { clearTimeout(i), t.status >= 200 && t.status < 300 ? o(t.responseText) : r(new Error(`HTTP ${t.status}`)); }, onerror: () => { clearTimeout(i), r(new Error("Network error")); }, ontimeout: () => { clearTimeout(i), r(new Error("Timeout")); } }); }); } const o = new AbortController, r = e(() => o.abort(), 1e4); try { const e = await fetch(t, { method: "GET", cache: "no-cache", signal: o.signal, headers: { Accept: "text/html" } }); if (!e.ok) { throw new Error(`HTTP ${e.status}`); } return await e.text(); } finally { clearTimeout(r); } }, i = await r(o), a = "function" == typeof window.DOMParser ? new window.DOMParser : null; if (a) { try { const e = a.parseFromString(i, "text/html"), o = String(t || "").trim(), r = Array.from(e.querySelectorAll("a")).find(t => { const e = String(t.textContent || "").trim(); return e === o || e === `v${o}` || e.includes(o); }), s = r?.closest("li, article, section, div") || r?.parentElement || null, c = s?.querySelector(".version-changelog") || (r?.nextElementSibling?.matches?.(".version-changelog") ? r.nextElementSibling : null), l = String(c?.textContent || "").trim(); if (l) { return l.split("\n").map(t => t.trim()).filter(t => t.length > 0).join("\n"); } } catch (t) {} } return ""; } catch (t) { return s?.warn?.("Update", `Failed to fetch changelog: ${t.message}`), ""; } })(o.version); o.changelog = "string" == typeof t && t.length > 0 ? t : ""; } catch (t) { s?.warn?.("Update", `Failed to fetch changelog: ${t.message}`), o.changelog = ""; } } else { o.changelog = ""; } return o; })(); r.version ? ((t, r, i) => { b.lastCheck = i, b.lastVersion = t.version, b.updateDetails = t; const d = ((t, e) => { if ("string" != typeof t || "string" != typeof e) { return s?.error?.("Update", "Invalid version format - must be strings"), 0; } const o = t => t.replace(/[^\d.]/g, "").split(".").map(t => parseInt(t, 10) || 0), [r, i] = [ o(t), o(e) ], a = Math.max(r.length, i.length); for (let t = 0; t < a; t++) { const e = (r[t] || 0) - (i[t] || 0); if (0 !== e) { return e; } } return 0; })(u.currentVersion, t.version); if (b.updateAvailable = d < 0, ((t, r) => { if (b.updateAvailable && (r || sessionStorage.getItem("update_dismissed") !== t.version)) { return (t => { const r = u.showNotificationIcon ? '<div class="update-notification-icon-wrap">\n <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M21 12c0 1-1 2-1 2s-1-1-1-2 1-2 1-2 1 1 1 2z"/>\n <path d="m21 12-5-5v3H8v4h8v3l5-5z"/>\n </svg>\n </div>' : "", i = document.createElement("div"); i.className = "youtube-enhancer-notification update-notification update-notification-card", i.setAttribute("role", "alertdialog"), i.setAttribute("aria-label", a("updateAvailableTitle")), o("yt-plus-update-notification-styles", "\n .update-notification-card{z-index:10001;max-width:360px;background:var(--yt-notification-bg);padding:16px 18px;border-radius:var(--yt-radius-lg);color:var(--yt-text-primary);box-shadow:var(--yt-shadow);border:1px solid var(--yt-glass-border);-webkit-backdrop-filter:var(--yt-glass-blur);backdrop-filter:var(--yt-glass-blur);animation:slideInFromBottom .4s ease-out}\n .update-notification-layout{position:relative;display:flex;align-items:flex-start;gap:12px}\n .update-notification-icon-wrap{background:var(--yt-glass-bg);border-radius:var(--yt-radius-xs);padding:10px;flex-shrink:0;border:1px solid var(--yt-glass-border);backdrop-filter:var(--yt-glass-blur);-webkit-backdrop-filter:var(--yt-glass-blur)}\n .update-notification-content{flex:1;min-width:0}\n .update-notification-title{font-weight:600;font-size:15px;margin-bottom:4px}\n .update-notification-version{font-size:13px;opacity:.9;margin-bottom:8px}\n .update-changelog-line{font-size:12px;opacity:.85;margin-bottom:6px}\n .update-changelog-header{font-size:12px;font-weight:600;opacity:.95;margin-bottom:6px}\n .update-changelog-box{font-size:12px;line-height:1.4;max-height:120px;overflow-y:auto;padding:8px;background:var(--yt-overlay-deep);border-radius:6px;border:1px solid var(--yt-surface-overlay-border);white-space:normal}\n .update-changelog-fallback{font-size:12px;opacity:.85;margin-bottom:12px}\n .update-notification-actions{display:flex;gap:8px}\n .update-install-btn{background:var(--yt-accent);color:#fff;border:none;padding:8px 16px;border-radius:var(--yt-radius-xs);cursor:pointer;font-size:13px;font-weight:700;transition:transform .15s ease;box-shadow:0 6px 18px var(--yt-danger-ghost);backdrop-filter:var(--yt-glass-blur)}\n .update-install-btn:active{transform:scale(0.96) !important;}\n .update-dismiss-btn{background:var(--yt-button-bg);color:var(--yt-text-primary);border:1px solid var(--yt-glass-border);padding:8px 12px;border-radius:var(--yt-radius-xs);cursor:pointer;font-size:13px;transition:background-color .12s ease, transform .12s ease, border-color .12s ease, color .12s ease;}\n .update-dismiss-btn:active{transform:scale(0.96) !important;}\n .update-close-btn{position:absolute;top:-8px;right:-8px;width:28px;height:28px;border-radius:50%;border:1px solid var(--yt-glass-border);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px;line-height:1;background:var(--yt-button-bg);color:var(--yt-text-primary);transition:background-color .18s ease, transform .18s ease;}\n .update-close-btn:active{transform:scale(0.96) !important;}\n " + (window.YouTubePlusStyleResources?.update || "")), window.YouTubeUtils.renderTemplateClone(i, `\n <div class="update-notification-layout">\n ${r}\n <div class="update-notification-content">\n <div class="update-notification-title">${a("updateAvailableTitle")}</div>\n <div class="update-notification-version">\n ${a("version")} ${t.version}\n </div>\n ${t.changelog || t.description ? (function() { const e = a("changelogHeader"), o = window.YouTubeSafeDOM, r = String(t.changelog && t.changelog.length > 0 ? t.changelog : t.description || "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|li)>/gi, "\n").replace(/\r\n?/g, "\n"), i = t => "function" == typeof o?.escapeHTML ? o.escapeHTML(t) : ""; return `<div class="update-changelog-header">${i(e)}</div><div class="update-changelog-box">${r.split(/\n+/).map(t => t.trim()).filter(Boolean).map(t => `<div class="update-changelog-line">${i(t)}</div>`).join("")}</div>`; })() : `<div class="update-changelog-fallback">${a("newFeatures")}</div>`}\n <div class="update-notification-actions">\n <button id="update-install-btn" class="update-install-btn" type="button">${a("installUpdate")}</button>\n <button id="update-dismiss-btn" class="update-dismiss-btn" type="button">${a("later")}</button>\n </div>\n </div>\n <button id="update-close-btn" class="update-close-btn" aria-label="${a("dismiss")}">×</button>\n </div>\n `); const s = "youtube-enhancer-notification-container"; let c = l(s); if (!c) { c = document.createElement("div"), c.id = s, c.className = "youtube-enhancer-notification-container"; try { document.body.appendChild(c); } catch (t) { document.body.appendChild(i); } } try { c.insertBefore(i, c.firstChild); } catch (t) { document.body.appendChild(i); } const d = () => { i.style.animation = "slideOutToBottom 0.35s ease-in forwards", e(() => i.remove(), 360); }, p = i.querySelector("#update-install-btn"); p && p.addEventListener("click", () => { k(t) ? (d(), e(() => v(a("installing")), 500)) : (v(a("manualInstallHint"), "error", 5e3), window.open("https://greasyfork.org/en/scripts/537017-youtube", "_blank")); }); const y = i.querySelector("#update-dismiss-btn"); y && y.addEventListener("click", () => { t?.version && sessionStorage.setItem("update_dismissed", t.version), d(); }); const m = i.querySelector("#update-close-btn"); m && m.addEventListener("click", () => { t?.version && sessionStorage.setItem("update_dismissed", t.version), d(); }), e(() => { i.isConnected && d(); }, u.notificationDuration); })(t), void (window.YouTubeUtils && YouTubeUtils.logger?.debug?.(`YouTube + Update available: ${t.version}`)); } if (r) { const e = b.updateAvailable ? a("updateAvailableMsg").replace("{version}", t.version) : a("upToDateMsg").replace("{version}", u.currentVersion); v(e); } })(t, r), (() => { try { localStorage.setItem(u.storageKey, JSON.stringify({ lastCheck: b.lastCheck, lastVersion: b.lastVersion, updateAvailable: b.updateAvailable, updateDetails: b.updateDetails })); } catch (t) { s?.error?.("Update", "Failed to save update settings", t); } })(), b.updateAvailable && u.autoInstallOnCheck) { try { if (sessionStorage.getItem("update_dismissed") !== t.version) { if (k(t)) { x(t); try { v(a("installing")); } catch (t) { c.logSuppressed(t, "Update"); } } else { s?.warn?.("Update", `Auto-install could not be initiated for ${t.downloadUrl}`); } } } catch (t) { s?.error?.("Update", "Auto-installation failed", t); } } })(r, t, i) : (t => { b.updateAvailable = !1, t && v(a("updateCheckFailed").replace("{msg}", a("noUpdateInfo")), "error", 4e3); })(t); } catch (o) { await (async (t, o, r) => { if ((t => !("AbortError" !== t.name && "NetworkError" !== t.name && !t.message?.includes("fetch") && !t.message?.includes("network")))(t) && r < 2) { return s?.warn?.("Update", `Retry ${r + 1}/2 after error: ${t.message}`), await new Promise(t => e(t, 2e3 * 2 ** r)), T(o, r + 1); } s?.error?.("Update", "Check failed after retries", t), o && v(a("updateCheckFailed").replace("{msg}", t.message), "error", 4e3); })(o, t, r); } finally { b.checkInProgress = !1; } } }, L = () => { const r = document.querySelector('.ytp-plus-settings-section[data-section="about"]'); if (!(r instanceof HTMLElement)) { return; } if (r.querySelector(".update-settings-container")) { return; } const s = document.createElement("div"); s.className = "update-settings-container update-settings-card"; const d = (e => { if (!e) { return a("never"); } const o = Date.now() - e, r = Math.floor(o / 864e5), i = Math.floor(o / 36e5), s = Math.floor(o / 6e4); return r > 0 ? t(r, "day") : i > 0 ? t(i, "hour") : s > 0 ? t(s, "minute") : a("justNow"); })(b.lastCheck); o("yt-plus-update-settings-styles", "\n .update-settings-card{padding:16px;margin-top:20px;border-radius:12px;background:var(--yt-surface-overlay-subtle);border:1px solid var(--yt-surface-overlay-border);-webkit-backdrop-filter:blur(10px) saturate(120%);backdrop-filter:blur(10px) saturate(120%);box-shadow:0 6px 20px var(--yt-update-card-shadow)}\n .update-settings-header{display:flex;align-items:center;gap:12px;margin-bottom:12px}\n .update-settings-title{margin:0;font-size:16px;font-weight:600;color:var(--yt-spec-text-primary)}\n .update-settings-status-card{display:grid;grid-template-columns:1fr auto;gap:16px;align-items:center;padding:16px;background:var(--yt-surface-overlay-subtle);border-radius:10px;margin-bottom:16px}\n .update-settings-version-row{display:flex;align-items:center;gap:8px;margin-bottom:4px}\n .update-settings-label{font-size:14px;font-weight:600;color:var(--yt-spec-text-primary)}\n .update-settings-pill{font-size:13px;font-weight:600;color:var(--yt-spec-text-primary);padding:3px 10px;background:var(--yt-surface-overlay-soft);border-radius:12px;border:1px solid var(--yt-glass-border)}\n .update-settings-meta{font-size:12px;color:var(--yt-spec-text-secondary)}\n .update-settings-meta-strong{font-weight:500}\n .update-settings-latest{color:var(--yt-update-available-text);font-weight:600}\n .update-status-col{display:flex;flex-direction:column;align-items:flex-end;gap:8px}\n .update-status-badge{display:flex;align-items:center;gap:8px;padding:6px 12px;border-radius:20px}\n .update-status-badge--available{background:linear-gradient(135deg,var(--yt-danger-soft),var(--yt-danger-border));border:1px solid var(--yt-danger-card-border)}\n .update-status-badge--ok{background:linear-gradient(135deg,var(--yt-success-soft),var(--yt-success-soft-hover));border:1px solid var(--yt-success-accent-soft)}\n .update-status-dot{width:6px;height:6px;border-radius:50%}\n .update-status-dot--available{background:var(--yt-update-available-dot);animation:pulse 2s infinite}\n .update-status-dot--ok{background:var(--yt-success-accent)}\n .update-status-text{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.5px}\n .update-status-text--available{color:var(--yt-update-available-text)}\n .update-status-text--ok{color:var(--yt-success-accent)}\n .update-install-inline-btn{background:linear-gradient(135deg,var(--yt-update-install-bg-start),var(--yt-update-install-bg-end));color:#fff;border:none;padding:8px 16px;border-radius:8px;cursor:pointer;font-size:12px;font-weight:600;transition:background-color .3s ease, transform .15s cubic-bezier(0.2,0,0,1), box-shadow .3s ease;box-shadow:0 4px 12px var(--yt-update-install-shadow)}\n .update-install-inline-btn:active{transform:scale(0.96) !important;}\n .update-settings-actions{display:flex;gap:12px}\n .update-check-btn{flex:1;padding:12px;font-size:13px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;gap:6px}\n .update-refresh-icon{display:inline-block;vertical-align:middle;flex-shrink:0}\n " + (window.YouTubePlusStyleResources?.update || "")), window.YouTubeUtils.renderTemplateClone(s, `\n <div class="update-settings-header">\n <h3 class="update-settings-title">\n ${a("enhancedExperience")}\n </h3>\n </div>\n\n <div class="update-settings-status-card">\n <div>\n <div class="update-settings-version-row">\n <span class="update-settings-label">${a("currentVersion")}</span>\n <span class="update-settings-pill">${u.currentVersion}</span>\n </div>\n <div class="update-settings-meta">\n ${a("lastChecked")}: <span class="update-settings-meta-strong">${d}</span>\n ${b.lastVersion && b.lastVersion !== u.currentVersion ? `<br>${a("latestAvailable")}: <span class="update-settings-latest">${b.lastVersion}</span>` : ""}\n </div>\n </div>\n\n ${b.updateAvailable ? `\n <div class="update-status-col">\n <div class="update-status-badge update-status-badge--available">\n <div class="update-status-dot update-status-dot--available"></div>\n <span class="update-status-text update-status-text--available">\n ${a("updateAvailable")}\n </span>\n </div>\n <button id="install-update-btn" class="update-install-inline-btn">${a("installUpdate")}</button>\n </div>\n ` : `\n <div class="update-status-badge update-status-badge--ok">\n <div class="update-status-dot update-status-dot--ok"></div>\n <span class="update-status-text update-status-text--ok">\n ${a("upToDate")}\n </span>\n </div>\n `}\n </div>\n\n <div class="update-settings-actions">\n <button class="ytp-plus-button ytp-plus-button-primary update-check-btn" id="manual-update-check">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="update-refresh-icon">\n <path d="M21.5 2v6h-6M2.5 22v-6h6M19.13 11.48A10 10 0 0 0 12 2C6.48 2 2 6.48 2 12c0 .34.02.67.05 1M4.87 12.52A10 10 0 0 0 12 22c5.52 0 10-4.48 10-10 0-.34-.02-.67-.05-1"/>\n </svg>\n ${a("checkForUpdates")}\n </button>\n <button class="ytp-plus-button update-open-page-btn" id="open-update-page">\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>\n <polyline points="15,3 21,3 21,9"/>\n <line x1="10" y1="14" x2="21" y2="3"/>\n </svg>\n </button>\n </div>\n `), r.appendChild(s); try { const t = r.querySelector(".ytp-plus-about-actions"), e = r.querySelector(".ytp-plus-about-footer"); t && r.appendChild(t), e && r.appendChild(e); } catch (t) { c.logSuppressed(t, "Update"); } const p = (t, e) => { const o = l(t); o && YouTubeUtils.cleanupManager.registerListener(o, "click", e); }; p("manual-update-check", async t => { const o = t.currentTarget instanceof HTMLElement ? t.currentTarget : t.target instanceof Element ? t.target.closest("#manual-update-check") : null; o && (i(o, a("checkingForUpdates"), !0), o.disabled = !0, await T(!0), e(() => { i(o, a("checkForUpdates"), !1), o.disabled = !1; }, 1e3)); }), p("install-update-btn", () => { k() ? v(a("installing")) : (v(a("manualInstallHint"), "error", 5e3), window.open("https://greasyfork.org/en/scripts/537017-youtube", "_blank")); }), p("open-update-page", () => { v(a("updatePageFallback")), window.open("https://greasyfork.org/en/scripts/537017-youtube", "_blank"); }); }; let M = !1; const C = () => { M || (M = !0, (() => { try { const t = localStorage.getItem(u.storageKey); if (!t) { return; } const e = JSON.parse(t); if ("object" != typeof e || null === e) { return void s?.error?.("Update", "Invalid settings structure"); } if ("number" == typeof e.lastCheck && e.lastCheck >= 0 && (b.lastCheck = e.lastCheck), "string" == typeof e.lastVersion) { const t = e.lastVersion.replace(/^v/i, "").trim(); h(t) && (b.lastVersion = t); } "boolean" == typeof e.updateAvailable && (b.updateAvailable = e.updateAvailable), e.updateDetails && "object" == typeof e.updateDetails && "string" == typeof e.updateDetails.version && h(e.updateDetails.version) && (b.updateDetails = e.updateDetails); } catch (t) { s?.error?.("Update", "Failed to load update settings", t); } })(), (() => { e(() => T(), 3e3); const t = "undefined" != typeof window ? window : globalThis, o = t.xt; o && (clearInterval(o), YouTubeUtils.cleanupManager?.unregisterInterval && YouTubeUtils.cleanupManager.unregisterInterval(o)); const r = setInterval(() => T(), u.checkInterval); t.xt = r, YouTubeUtils.cleanupManager.registerInterval(r), YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(window, "beforeunload", () => clearInterval(r)) : window.addEventListener("beforeunload", () => clearInterval(r)); })(), (() => { const t = () => { e(L, 100); }; YouTubeUtils.cleanupManager?.registerListener ? YouTubeUtils.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", t) : document.addEventListener("youtube-plus-settings-modal-opened", t); })(), YouTubeUtils.cleanupManager.registerListener(document, "click", t => { const o = t.target.closest(".ytp-plus-settings-nav-item"); "about" === o?.dataset?.section && e(L, 50); }, { passive: !0, capture: !0 }), document.querySelector('.ytp-plus-settings-section[data-section="about"]') && e(L, 0), (() => { try { window.YouTubeUtils && YouTubeUtils.logger?.debug && YouTubeUtils.logger.debug("YouTube + Update Checker initialized", { version: u.currentVersion, enabled: u.enabled, lastCheck: new Date(b.lastCheck).toLocaleString(), updateAvailable: b.updateAvailable }); } catch (t) { c.logSuppressed(t, "Update"); } })()); }, E = () => { "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", C, { once: !0 }) : C(); }; document.addEventListener("youtube-plus-settings-modal-opened", () => { M ? e(L, 100) : C(); }), window.YouTubeUtils?.onSectionActive ? window.YouTubeUtils.onSectionActive("about", E) : "undefined" != typeof window && E(); })(), /** * YouTube Music Enhancement Module * Provides UI improvements and features for YouTube Music * @module music * @version 2.3 * * Features: * - Scroll-to-top button with smart container detection * - Enhanced navigation styles (centered search, immersive mode) * - Sidebar hover effects and player enhancements * - Health monitoring and automatic recovery * - SPA navigation support with debounced updates */ (function() { function t() { const t = "undefined" != typeof window ? window.YouTubePlusSettingsStore : null; return t && "function" == typeof t.getMusicSettings ? t.getMusicSettings() : { enableMusic: !0, immersiveSearchStyles: !0, hoverStyles: !0, playerSidebarStyles: !0, centeredPlayerStyles: !0, playerBarStyles: !0, centeredPlayerBarStyles: !0, miniPlayerStyles: !0, scrollToTopStyles: !0 }; } function e(t) { return !!t?.enableMusic; } function o() { if (!d?.isMusicDomain?.()) { return; } const e = f || t(); if (!e.enableMusic) { return; } const o = [ "\n /* Remove borders and shadows from nav/guide when bauhaus sidenav is enabled */\n ytmusic-app-layout[is-bauhaus-sidenav-enabled] #nav-bar-background.ytmusic-app-layout { border-bottom: none !important; box-shadow: none !important; }\n ytmusic-app-layout[is-bauhaus-sidenav-enabled] #nav-bar-divider.ytmusic-app-layout { border-top: none !important; }\n ytmusic-app-layout[is-bauhaus-sidenav-enabled] #mini-guide-background.ytmusic-app-layout { border-right: 0 !important; }\n ytmusic-nav-bar, ytmusic-app-layout[is-bauhaus-sidenav-enabled] .ytmusic-nav-bar { border: none !important; box-shadow: none !important; }\n /* Center the settings button in the top nav bar (fixes it being rendered at the bottom) */\n ytmusic-settings-button.style-scope.ytmusic-nav-bar, ytmusic-nav-bar ytmusic-settings-button.style-scope.ytmusic-nav-bar {position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; bottom: auto !important; margin: 0 !important; z-index: 1000 !important;}\n /* Center the search box in the top nav bar */\n ytmusic-search-box, ytmusic-nav-bar ytmusic-search-box, ytmusic-searchbox, ytmusic-nav-bar ytmusic-searchbox {position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; margin: 0 !important; max-width: 75% !important; width: auto !important; z-index: 900 !important;}\n " ]; e.immersiveSearchStyles && o.push("ytmusic-search-box:has(input:focus),ytmusic-searchbox:has(input:focus),ytmusic-search-box:focus-within,ytmusic-searchbox:focus-within{position:fixed !important;left:50% !important;top:12vh !important;transform:translateX(-50%) !important;height:auto !important;max-width:900px !important;width:min(90vw,900px) !important;z-index:1200 !important;display:block !important;}@media only screen and (min-width:1400px){ytmusic-search-box:has(input:focus),ytmusic-searchbox:has(input:focus){top:10vh !important;max-width:1000px !important;transform:translateX(-50%) scale(1.05) !important;}}ytmusic-search-box:has(input:focus) input,ytmusic-searchbox:has(input:focus) input,ytmusic-search-box:focus-within input,ytmusic-searchbox:focus-within input{background-color:var(--yt-bg-primary) !important;box-shadow:black 0 0 30px !important;}@media (prefers-color-scheme:dark){ytmusic-search-box:has(input:focus) input,ytmusic-searchbox:has(input:focus) input{background-color:var(--yt-modal-bg) !important;}}ytmusic-app-layout:has(ytmusic-search-box:has(input:focus)) #main-panel,ytmusic-app-layout:has(ytmusic-searchbox:has(input:focus)) #main-panel{filter:blur(18px) !important;transform:scale(1.03) !important;}"), e.hoverStyles && o.push("\n .ytmusic-guide-renderer {opacity: 0.01 !important; transition: opacity 0.5s ease-in-out !important;}\n .ytmusic-guide-renderer:hover { opacity: 1 !important;}\n ytmusic-app[is-bauhaus-sidenav-enabled] #guide-wrapper.ytmusic-app {background-color: transparent !important; border: none !important;}\n "), e.playerSidebarStyles && o.push('#side-panel{width:40em !important;height:80vh !important;padding:0 2em !important;right:-30em !important;top:10vh !important;opacity:0 !important;position:absolute !important;transition:all 0.3s ease-in-out !important;backdrop-filter:blur(5px) !important;background-color:var(--yt-panel-overlay-subtle) !important;border-radius:1em !important;box-shadow:var(--yt-shadow-deep-1) 0px -36px 30px inset,var(--yt-shadow-deep-2) 0px -79px 40px inset,var(--yt-shadow-deep-3) 0px 2px 1px,var(--yt-shadow-deep-4) 0px 4px 2px,var(--yt-shadow-deep-4) 0px 8px 4px,var(--yt-shadow-deep-4) 0px 16px 8px,var(--yt-shadow-deep-4) 0px 32px 16px !important;}#side-panel tp-yt-paper-tabs{transition:height 0.3s ease-in-out !important;height:0 !important;}#side-panel:hover{right:0 !important;opacity:1 !important;}#side-panel:hover tp-yt-paper-tabs{height:4em !important;}#side-panel:has(ytmusic-tab-renderer[page-type="MUSIC_PAGE_TYPE_TRACK_LYRICS"]):not(:has(ytmusic-message-renderer:not([style="display:none;"]))){right:0 !important;opacity:1 !important;}#side-panel{min-width:auto !important;}#side-panel .ytmusic-top-button{opacity:1 !important;visibility:visible !important;pointer-events:auto !important;}#side-panel .ytmusic-top-button{position:absolute !important;bottom:20px !important;right:20px !important;z-index:1200 !important;}'), e.centeredPlayerStyles && o.push('\n ytmusic-app-layout:not([player-ui-state="FULLSCREEN"]) #main-panel {position: absolute !important; height: 70vh !important; max-width: 70vw !important; aspect-ratio: 1 !important; top: 50vh !important; left: 50vw !important; transform: translate(-50%, -50%) !important;}\n #player-page {padding: 0 !important; margin: 0 !important; left: 0 !important; top: 0 !important; height: 100% !important; width: 100% !important;}\n '), e.playerBarStyles && o.push('\n ytmusic-player-bar, #player-bar-background {margin: 1vw !important; width: 98vw !important; border-radius: 1em !important; overflow: hidden !important; transition: all 0.5s ease-in-out !important; background-color: var(--yt-panel-overlay-weak) !important; box-shadow: var(--yt-shadow-deep-1) 0px -36px 30px inset, var(--yt-shadow-deep-2) 0px -79px 40px inset, var(--yt-shadow-deep-3) 0px 2px 1px, var(--yt-shadow-deep-4) 0px 4px 2px, var(--yt-shadow-deep-4) 0px 8px 4px, var(--yt-shadow-deep-4) 0px 16px 8px, var(--yt-shadow-deep-4) 0px 32px 16px !important;}\n #layout:not([player-ui-state="PLAYER_PAGE_OPEN"]) #player-bar-background {background-color: var(--yt-panel-overlay-subtle) !important;}\n '), e.centeredPlayerBarStyles && o.push("\n #left-controls {position: absolute !important; left: 49vw !important; bottom: 15px !important; transform: translateX(-50%) !important; width: fit-content !important; order: 1 !important;}\n .time-info {position: absolute !important; bottom: -10px !important; left: 0 !important; width: 100% !important; text-align: center !important; padding: 0 !important; margin: 0 !important;}\n .middle-controls {position: absolute !important; left: 1vw !important; bottom: 15px !important; max-width: 30vw !important; order: 0 !important;}\n "), e.miniPlayerStyles && o.push('\n #main-panel:has(ytmusic-player[player-ui-state="MINIPLAYER"]) {position: fixed !important; width: 100vw !important; height: 100vh !important; top: -100vh !important; left: 0 !important; margin: 0 !important; padding: 0 !important; transform: none !important; max-width: 100vw !important;}\n ytmusic-player[player-ui-state="MINIPLAYER"] {position: fixed !important; bottom: calc(100vh + 120px) !important; right: 30px !important; width: 350px !important; height: fit-content !important;}\n #av-id:has(ytmusic-av-toggle) {position: absolute !important; left: 50% !important; transform: translateX(-50%) !important; top: -4em !important; opacity: 0 !important; transition: all 0.3s ease-in-out !important;}\n #av-id:has(ytmusic-av-toggle):hover {opacity: 1 !important;}\n #player[player-ui-state="MINIPLAYER"] {display: none !important;}\n /* Chrome-specific robustness: ensure the AV toggle container is above overlays\n and can receive hover even if :has() behaves differently. Also provide a\n non-:has fallback so the element is hoverable regardless of child matching. */\n /* Use absolute positioning (keeps internal menu alignment) but promote\n stacking and rendering to ensure it sits above overlays and receives clicks. */\n #av-id {position: absolute !important; left: 50% !important; transform: translateX(-50%) translateZ(0) !important; top: -4em !important; z-index: 10000 !important; pointer-events: auto !important; display: block !important; visibility: visible !important; width: auto !important; height: auto !important; will-change: transform, opacity !important;}\n #av-id ytmusic-av-toggle {pointer-events: auto !important;}\n #av-id:hover {opacity: 1 !important;}\n /* Prevent overlapping overlays from stealing clicks when hovering the toggle.\n This is a conservative rule; if a specific overlay still steals clicks we\n can target it explicitly later. */\n #av-id:hover, #av-id:active { filter: none !important; }\n '); const r = `\n${o.join("\n")}\n`; if (!(function(t) { try { const e = d?.StyleManager; if (!e || "function" != typeof e.add) { return !1; } if (e.add("youtube-plus-music-styles", t), b?.isConnected) { try { b.remove(); } catch (t) {} } b = null; try { document.querySelectorAll("#youtube-plus-music-styles").forEach(t => t.remove()); } catch (t) {} return d?.logger?.debug?.("[YouTube+][Music]", "Styles applied via StyleManager"), !0; } catch (t) { return !1; } })(r)) { if (b?.isConnected) { return b.textContent = r, void d?.logger?.debug?.("[YouTube+][Music]", "Styles updated"); } try { if ("undefined" != typeof GM_addStyle) { const t = GM_addStyle(r); if (t && "STYLE" === t.tagName) { b = t; try { b.id = "youtube-plus-music-styles"; } catch (t) {} } } } catch (t) {} if (!b?.isConnected) { const t = document.createElement("style"); t.id = "youtube-plus-music-styles", t.textContent = r, document.head.appendChild(t), b = t; } d?.logger?.debug?.("[YouTube+][Music]", "Styles applied"); } } function r(t, e, o, r) { try { !(function(t, e, o, r) { if (o.setupScrollToTop) { return void o.setupScrollToTop(t, e); } const i = t => { let e = t; for (;e && e !== document.body; ) { try { if (e.scrollHeight > e.clientHeight + 10) { return e; } } catch (t) {} e = e.parentElement; } return null; }; t.addEventListener("click", o => { try { o.preventDefault?.(); } catch (t) {} try { o.stopPropagation?.(); } catch (t) {} let a = e; a && a.scrollHeight > a.clientHeight + 1 || (a = r && i(r)), a || (a = i(t.parentElement)), a || (a = document.scrollingElement || document.documentElement || document.body); try { const t = { chosen: a && (a.id || a.tagName || "(window)"), scrollTop: a && "scrollTop" in a ? a.scrollTop : null, scrollHeight: a && "scrollHeight" in a ? a.scrollHeight : null, clientHeight: a && "clientHeight" in a ? a.clientHeight : null }; try { window.YouTubeMusic = window.YouTubeMusic || {}, window.YouTubeMusic._lastClickDebug = t; } catch (t) {} d?.logger?.debug?.("[YouTube+][Music]", "ScrollToTop click target", t); } catch (t) {} const s = t => { if (!t) { return !1; } try { if ("function" == typeof t.scrollTo) { return t.scrollTo({ top: 0, behavior: "smooth" }), !0; } if ("scrollTop" in t) { return t.scrollTop = 0, !0; } } catch (t) {} return !1; }; let c = !1; if (c = s(a) || c, e && e !== a && (c = s(e) || c), c = s(document.scrollingElement || document.documentElement || document.body) || c, !c) { try { window.scrollTo(0, 0); } catch (t) { d?.logger?.debug?.("[YouTube+][Music]", "Final scroll fallback failed", t); } } }, { passive: !1 }); })(t, o, r, e); const i = !!e; if ((function(t, e, o, r = {}) { o.setupButtonStyles ? o.setupButtonStyles(t, e, r) : (t.classList.add(r.insideSidePanel && e ? "ytp-music-fab-side-panel" : "ytp-music-fab"), d?.logger?.debug?.("[YouTube+][Music]", "Button positioned:", { position: t.style.position, bottom: t.style.bottom, right: t.style.right, zIndex: t.style.zIndex, insideSidePanel: !!r.insideSidePanel })); })(t, e, r, { insideSidePanel: i }), i) { try { e.appendChild(t); } catch (e) { document.body.appendChild(t), d?.logger?.debug?.("[YouTube+][Music]", "Appending to sidePanel failed, appended to body", e); } } else { document.body.appendChild(t); } !(function(t, e, o) { if (window.YouTubePlusScrollManager?.addScrollListener) { try { const o = window.YouTubePlusScrollManager.addScrollListener(e, () => { const o = e.scrollTop > 100; t.classList.toggle("visible", o), d?.logger?.debug?.("[YouTube+][Music]", `Scroll position: ${e.scrollTop}px, button visible: ${o}`); }, { debounce: 100, runInitial: !0 }); return t.ft = o, void d?.logger?.debug?.("[YouTube+][Music]", "Using ScrollManager for scroll handling"); } catch (t) { m?.error?.("Music", "ScrollManager failed, using fallback", t); } } if (o.setupScrollVisibility) { return void o.setupScrollVisibility(t, e, 100); } let r = !document.hidden, i = null; const a = () => { i && cancelAnimationFrame(i), i = requestAnimationFrame(() => { if (!r) { return; } const o = e.scrollTop || 0, i = o > 100, a = t.classList.contains("visible"); t.classList.toggle("visible", i), i !== a && d?.logger?.debug?.("[YouTube+][Music]", `Button visibility changed: ${i ? "SHOWN" : "HIDDEN"} (scroll: ${o}px)`); }); }, s = (0, d.debounce)(a, 100), c = () => { r = !document.hidden, r && a(); }; e.addEventListener("scroll", s, { passive: !0 }), document.addEventListener("visibilitychange", c), setTimeout(a, 100), setTimeout(a, 500), t.ft = () => { i && cancelAnimationFrame(i), e.removeEventListener("scroll", s), document.removeEventListener("visibilitychange", c); }, d?.logger?.debug?.("[YouTube+][Music]", "Using fallback scroll handler"); })(t, o, r); const a = o.scrollTop || 0; a > 100 && (t.classList.add("visible"), d?.logger?.debug?.("[YouTube+][Music]", `Button shown immediately (scroll: ${a}px)`)), d?.logger?.debug?.("[YouTube+][Music]", "Scroll to top button created successfully", { buttonId: t.id, scrollContainer: o.tagName, scrollContainerId: o.id || "no-id", scrollHeight: o.scrollHeight, clientHeight: o.clientHeight, scrollTop: a, position: t.style.position, computedDisplay: (() => { const e = window.getComputedStyle(t); return { display: e.display, opacity: e.opacity, visibility: e.visibility }; })() }); } catch (t) { m?.error?.("Music", "attachButton error", t); } } function i() { try { if (!d?.isMusicDomain?.()) { return; } const t = y("ytmusic-side-panel-top-button"); if (t) { if (document.body.contains(t) && t.ft) { return void d?.logger?.debug?.("[YouTube+][Music]", "Button already exists and is properly attached"); } d?.logger?.debug?.("[YouTube+][Music]", "Removing orphaned button"), t.remove(); } const e = Date.now(); if (e - S.lastAttempt < S.minInterval) { return void d?.logger?.debug?.("[YouTube+][Music]", "Rate limited, skipping button creation"); } if (S.attempts++, S.lastAttempt = e, S.attempts > S.maxAttempts) { return void d?.logger?.debug?.("[YouTube+][Music]", `Max attempts (${S.maxAttempts}) reached, stopping retries`); } d?.logger?.debug?.("[YouTube+][Music]", `Creating button (attempt ${S.attempts}/${S.maxAttempts})`); const o = p("#side-panel"), a = window.YouTubePlusMusicUtils || {}, s = (function() { const t = document.createElement("button"); return t.id = "ytmusic-side-panel-top-button", t.className = "ytmusic-top-button top-button", t.title = x("scrollToTop"), t.setAttribute("aria-label", x("scrollToTop")), d.renderTemplateClone(t, '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>'), t.setAttribute("data-ytmusic-scroll-button", "true"), d?.logger?.debug?.("[YouTube+][Music]", "Button element created", { id: t.id, className: t.className }), t; })(); if (!o) { d?.logger?.debug?.("[YouTube+][Music]", "No side-panel found, checking for main content or queue"); const t = p("ytmusic-queue-renderer"); if (t) { const e = t.querySelector("#contents"); if (e) { return r(s, t, e, a), void (S.attempts = 0); } } const e = p("ytmusic-browse"); if (e) { const t = e.querySelector("ytmusic-section-list-renderer"); if (t) { return r(s, e, t, a), void (S.attempts = 0); } } return void l(function() { i(); }, 1e3); } const c = (function(t, e) { if (k.has(t)) { const e = k.get(t); if (e && document.body.contains(e) && e.scrollHeight > e.clientHeight + 10) { return e; } k.delete(t); } if (e.findScrollContainer) { const o = e.findScrollContainer(t); return o && k.set(t, o), o; } const o = [ 'ytmusic-tab-renderer[tab-identifier="FEmusic_queue"] #contents', 'ytmusic-tab-renderer[tab-identifier="FEmusic_up_next"] #contents', 'ytmusic-tab-renderer[tab-identifier="FEmusic_lyrics"] #contents', "ytmusic-tab-renderer[selected] #contents", "ytmusic-tab-renderer #contents", "ytmusic-queue-renderer #contents", "ytmusic-playlist-shelf-renderer #contents", "#side-panel #contents", "#contents.ytmusic-tab-renderer", ".ytmusic-section-list-renderer", '[role="tabpanel"]', ".ytmusic-player-queue", "ytmusic-tab-renderer", ".scroller", "[scroll-container]" ]; for (const e of o) { const o = t?.querySelector(e); if (o) { const r = o.scrollHeight, i = o.clientHeight, a = r > i + 10; if (d?.logger?.debug?.("[YouTube+][Music]", `Checking ${e}: scrollHeight=${r}, clientHeight=${i}, isScrollable=${a}`), a) { return d?.logger?.debug?.("[YouTube+][Music]", `✓ Found scroll container: ${e}`), k.set(t, o), o; } } } if (t && t.scrollHeight > t.clientHeight + 10) { return d?.logger?.debug?.("[YouTube+][Music]", "✓ Using side-panel as scroll container"), k.set(t, t), t; } if (t) { const e = [ "div[id]", "div[class]", '[role="tabpanel"]', '[role="list"]', '[role="listbox"]' ]; let o = null, r = 0; for (const i of e) { try { const e = t.querySelectorAll(i); for (const t of e) { const e = (t.scrollHeight || 0) - (t.clientHeight || 0); e > 10 && e > r && (r = e, o = t); } } catch (t) {} } if (o) { const e = o.tagName.toLowerCase(), r = o.id ? `#${o.id}` : ""; return d?.logger?.debug?.("[YouTube+][Music]", `✓ Best scroll container chosen: ${e}${r}`, { scrollHeight: o.scrollHeight, clientHeight: o.clientHeight }), k.set(t, o), o; } } return d?.logger?.debug?.("[YouTube+][Music]", "✗ No scroll container found in side-panel"), null; })(o, a); if (!c) { d?.logger?.debug?.("[YouTube+][Music]", "No scroll container found, will retry with backoff"); const t = Math.min(500 * S.attempts, 3e3); return void l(function() { i(); }, t); } r(s, o, c, a), S.attempts = 0, d?.logger?.debug?.("[YouTube+][Music]", "✓ Button created successfully"); } catch (t) { m?.error?.("Music", "Error creating scroll to top button", t), S.attempts < S.maxAttempts && l(function() { i(); }, 1e3); } } function a() { try { const t = y("ytmusic-side-panel-top-button"); if (t) { if (t.ft && document.body.contains(t)) { return void d?.logger?.debug?.("[YouTube+][Music]", "Button is healthy, no action needed"); } if (d?.logger?.debug?.("[YouTube+][Music]", "Cleaning up orphaned/detached button"), t.ft) { try { t.ft(); } catch (t) {} } if (t.kt) { try { t.kt(); } catch (t) {} } t.remove(); } const e = p("#side-panel"), o = p("ytmusic-browse"), r = p("ytmusic-queue-renderer"), a = p("ytmusic-tab-renderer[tab-identifier]"); e || o || r || a ? (d?.logger?.debug?.("[YouTube+][Music]", "Found container, scheduling button creation"), setTimeout(function() { i(); }, 300)) : d?.logger?.debug?.("[YouTube+][Music]", "No suitable container found yet"); } catch (t) { m?.error?.("Music", "Error in checkAndCreateButton", t); } } function s() { try { if (null != w && (w.stop(), w = null), h && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(h), h = null), g && (g.stop(), g = null), v) { try { v(); } catch (t) {} v = null; } const t = y("ytmusic-side-panel-top-button"); if (t?.ft) { try { t.ft(); } catch (t) {} } if (t?.kt) { try { t.kt(); } catch (t) {} } t && t.remove(); } catch (t) { m?.error?.("Music", "stopScrollToTopRuntime error", t); } } function c() { if (f = t(), e(f)) { d?.isMusicDomain?.() && (o(), s()); } else { s(); try { d?.StyleManager?.remove?.("youtube-plus-music-styles"); } catch (t) {} b?.isConnected && b.remove(); try { document.querySelectorAll("#youtube-plus-music-styles").forEach(t => t !== b && t.remove()); } catch (t) {} b = null; } } const l = setTimeout.bind(window), d = window.YouTubeUtils, u = d?.createVisibilityAwareInterval; if ("undefined" != typeof location && "music.youtube.com" !== location.hostname) { return; } const p = d.$, y = d.byId, m = d?.logger || null; d?.StyleManager?.add?.("ytp-music-fab-styles", window.YouTubePlusDesignSystem?.getStyle?.("ytp-music-fab-styles") || ""); let f = t(), b = null, h = null, g = null, w = null, v = null; const x = d?.t || (t => t || ""), k = new WeakMap, S = { attempts: 0, maxAttempts: 5, lastAttempt: 0, minInterval: 500 }; "undefined" != typeof window && (window.YouTubeMusic = { observeDocumentBodySafely: () => { if (h || g) { return; } const t = (0, d.debounce)(a, 200), e = window.YouTubePlusMutationCoordinator; if (e?.subscribeRoot) { return h = "music::sidePanelObserver", e.subscribeRoot(h, e => { const o = Date.now(), r = y("ytmusic-side-panel-top-button"); if (r && document.body.contains(r) && r.ft) { return; } const i = e.some(t => 0 !== t.addedNodes.length && Array.from(t.addedNodes).some(t => { if (1 !== t.nodeType) { return !1; } const e = t; if ("side-panel" === e.id || "contents" === e.id) { return !0; } const o = e.tagName; return "YTMUSIC-BROWSE" === o || "YTMUSIC-PLAYER-PAGE" === o || "YTMUSIC-QUEUE-RENDERER" === o || "YTMUSIC-TAB-RENDERER" === o || null != e.querySelector?.("#side-panel, #contents, ytmusic-browse, ytmusic-queue-renderer, ytmusic-tab-renderer"); })), a = e.some(t => "attributes" === t.type && "selected" === t.attributeName && t.target instanceof Element && t.target.matches?.("ytmusic-tab-renderer, tp-yt-paper-tab")); i || a ? (d?.logger?.debug?.("[YouTube+][Music]", "Detected relevant DOM change, checking button"), t()) : o % 2 == 0 && t(); }, { selector: "#side-panel, #contents, ytmusic-browse, ytmusic-player-page, ytmusic-queue-renderer, ytmusic-tab-renderer", childList: !0, subtree: !0, attributes: !0, attributeFilter: [ "selected", "tab-identifier", "page-type" ] }), void d?.logger?.debug?.("[YouTube+][Music]", "✓ Coordinator watcher started"); } g = u(() => { a(); }, 500); }, checkAndCreateButton: a, createScrollToTopButton: i, saveSettings: function(e) { f = e && "object" == typeof e ? { ...f, ...e } : t(); }, applySettingsChanges: c, version: "2.4.5" }); let T = !1; d?.whenRelevant?.({ name: "music", isRelevant: () => (d?.isMusicDomain?.() ?? !1) && e(f), onEnter: () => { if (!T) { T = !0, window.addEventListener("beforeunload", () => { try { s(); try { d?.StyleManager?.remove?.("youtube-plus-music-styles"); } catch (t) {} b?.isConnected && b.remove(), b = null, d?.logger?.debug?.("[YouTube+][Music]", "Cleanup completed"); } catch (t) { m?.error?.("Music", "Cleanup error", t); } }), d?.isMusicDomain?.() && (f = t(), e(f) && ("loading" === document.readyState ? document.addEventListener("DOMContentLoaded", o, { once: !0 }) : o())); try { "undefined" != typeof GM_addValueChangeListener && GM_addValueChangeListener("youtube-plus-music-settings", () => { try { f = t(); } catch (t) { m?.warn?.("Music", "Settings listener read failed", t); } c(); }); } catch (t) { m?.warn?.("Music", "Settings listener registration error", t); } d?.logger?.debug?.("[YouTube+][Music]", "Module loaded (lazy)", { version: "2.4.5", hostname: d?.getHostname?.() ?? "", enabled: (d?.isMusicDomain?.() ?? !1) && e(f) }); } } }); })(), (function() { const {$: t, $$: e} = window.YouTubeUtils || {}, o = window.YouTubeUtils, r = o?.onDomReady || (t => { "loading" !== document.readyState ? t() : document.addEventListener("DOMContentLoaded", t, { once: !0 }); }), i = { enabled: !0, storageKey: "youtube_endscreen_settings", selectors: ".ytp-ce-element-show,.ytp-ce-element,.ytp-endscreen-element,.ytp-ce-covering-overlay,.ytp-cards-teaser,.teaser-carousel,.ytp-cards-button,.iv-drawer,.iv-branding,.video-annotations,.ytp-cards-teaser-text", debounceMs: 32, batchSize: 20 }, a = { observerSubId: null, styleEl: null, isActive: !1, removeCount: 0, lastCheck: 0, ytNavigateListenerKey: null, settingsNavListenerKey: null }, s = o.debounce, c = { load: () => { try { const t = localStorage.getItem(i.storageKey); i.enabled = !t || (JSON.parse(t).enabled ?? !0); } catch (t) { i.enabled = !0; } }, save: () => { try { localStorage.setItem(i.storageKey, JSON.stringify({ enabled: i.enabled })); } catch (t) { o.logSuppressed(t, "Endscreen"); } c.apply(); }, apply: () => i.enabled ? p() : u() }, l = () => { if (!i.enabled) { return; } const t = performance.now(); if (t - a.lastCheck < i.debounceMs) { return; } a.lastCheck = t; const r = e(i.selectors); r.length && (t => { const e = Math.min(t.length, i.batchSize); for (let r = 0; r < e; r++) { const e = t[r]; if (e?.isConnected) { e.style.display = "none", e.style.visibility = "hidden"; try { e.remove(), a.removeCount++; } catch (t) { o.logSuppressed(t, "Endscreen"); } } } })(r); }, d = t => { if (!(t instanceof Element)) { return !1; } const e = (t => "string" == typeof t.className ? t.className : t.className && "object" == typeof t.className && "baseVal" in t.className ? t.className.baseVal : "")(t); return e.includes("ytp-") || t.querySelector?.(".ytp-ce-element"); }, u = () => { if (a.observerSubId && window.YouTubePlusMutationCoordinator?.unsubscribe && window.YouTubePlusMutationCoordinator.unsubscribe(a.observerSubId), a.observerSubId = null, a.styleEl) { try { const t = YouTubeUtils?.StyleManager; t && "function" == typeof t.remove && t.remove(a.styleEl); } catch (t) { o.logSuppressed(t, "Endscreen"); } } a.styleEl = null, a.isActive = !1; }, p = () => { !a.isActive && i.enabled && (a.isActive = !0, (() => { if (a.styleEl || !i.enabled) { return; } const t = `${i.selectors}{display:none!important;opacity:0!important;visibility:hidden!important;pointer-events:none!important;transform:scale(0)!important}`, e = YouTubeUtils?.StyleManager; e && "function" == typeof e.add && e.add("end-screen-remover", t), a.styleEl = "end-screen-remover"; })(), l(), (() => { if (a.observerSubId || !i.enabled) { return; } const t = s(l, i.debounceMs), e = window.YouTubePlusMutationCoordinator; e?.subscribeRoot && (a.observerSubId = "endscreen::observer", e.subscribeRoot(a.observerSubId, e => { (t => { for (const {addedNodes: e} of t) { for (const t of e) { if (d(t)) { return !0; } } } return !1; })(e) && t(); }, { selector: "#movie_player, .ytp-ce-element, .ytp-endscreen-element, .ytp-cards-teaser, .ytp-cards-button, .iv-drawer, .iv-branding, .video-annotations", childList: !0, attributes: !0, subtree: !0, attributeFilter: [ "class", "style" ] }), YouTubeUtils.cleanupManager.register(() => { a.observerSubId && (e.unsubscribe(a.observerSubId), a.observerSubId = null); }), t()); })()); }, y = (() => { let t = !1; return () => { if (t) { return; } t = !0; const e = window.YouTubePlusEventDelegation, r = (t, e) => { e && e.classList?.contains("ytp-plus-settings-checkbox") && e.closest?.(".endscreen-settings") && (i.enabled = e.checked, c.save()); }; if (e?.on) { e.on(document, "change", ".endscreen-settings .ytp-plus-settings-checkbox", r, { passive: !0 }); } else { const t = t => { const e = t.target?.closest?.(".ytp-plus-settings-checkbox"); e && r(0, e); }; o && YouTubeUtils.cleanupManager ? YouTubeUtils.cleanupManager.registerListener(document, "change", t, { passive: !0, capture: !0 }) : document.addEventListener("change", t, { passive: !0, capture: !0 }); } }; })(), m = () => { const e = t(".endscreen-settings-slot"), r = t(".enhanced-submenu .glass-card"), s = e || r; if (!s || t(".endscreen-settings", s)) { return; } const c = document.createElement("div"); c.className = "ytp-plus-settings-item endscreen-settings", o.renderTemplateClone(c, `\n <div>\n <label class="ytp-plus-settings-item-label">${YouTubeUtils.t("endscreenHideLabel")}</label>\n <div class="ytp-plus-settings-item-description">${YouTubeUtils.t("endscreenHideDesc")}${a.removeCount ? ` (${a.removeCount} ${YouTubeUtils.t("removedSuffix").replace("{n}", "").trim()})` : ""}</div>\n </div>\n <input type="checkbox" class="ytp-plus-settings-checkbox" ${i.enabled ? "checked" : ""}>\n `), e ? e.replaceWith(c) : s.appendChild(c), y(); }, f = s(() => { "/watch" === location.pathname && (u(), requestIdleCallback ? requestIdleCallback(p) : setTimeout(p, 1)); }, 50); let b = !1; const h = () => { b || (b = !0, c.load(), r(p), a.ytNavigateListenerKey || (a.ytNavigateListenerKey = YouTubeUtils.cleanupManager.registerListener(document, "yt-navigate-finish", f, { passive: !0 })), YouTubeUtils.cleanupManager.registerListener(document, "youtube-plus-settings-modal-opened", () => setTimeout(m, 25)), a.settingsNavListenerKey || (a.settingsNavListenerKey = YouTubeUtils.cleanupManager.registerListener(document, "click", t => { const {target: e} = t; "advanced" === e?.dataset?.section && setTimeout(m, 10); }, { passive: !0, capture: !0 }))); }; document.addEventListener("youtube-plus-settings-modal-opened", () => { b || h(), setTimeout(m, 25); }), o?.whenRelevant ? o.whenRelevant({ name: "endscreen", isRelevant: () => "/watch" === (window.location.pathname || ""), onEnter: h }) : "/watch" === (window.location.pathname || "") && h(); })(), (async function() { const t = setTimeout.bind(window), e = window.YouTubeUtils.createHTML, o = "ytp-random"; let r = !0, i = null, a = null, s = null; const c = t => { t && ("number" != typeof t ? "function" != typeof t.stop ? "function" == typeof t.cancel && t.cancel() : t.stop() : clearTimeout(t)); }, l = t => { if (r = !1 !== t, r) { try { D(); } catch (t) {} try { "function" == typeof a && a(); } catch (t) {} } else { try { O(); } catch (t) {} try { s && c(s), s = null; } catch (t) {} try { "function" == typeof i && i(); } catch (t) {} } }; r = window.YouTubeUtils?.loadFeatureEnabled?.("enablePlayAll") ?? !0; const d = window.YouTubeUtils.$, u = window.YouTubeUtils.$$, p = window.YouTubeUtils?.logger || null, y = window.YouTubeUtils?.cleanupManager, m = (() => { let t = "loading" !== document.readyState; const e = []; return t || document.addEventListener("DOMContentLoaded", () => { for (t = !0; e.length; ) { const t = e.shift(); try { t && t(); } catch (t) { p?.warn?.("Play All", "DOMReady callback error", t); } } }, { once: !0 }), o => { t ? o() : e.push(o); }; })(), f = window.YouTubeUtils?.t || (t => t || ""), b = () => { if ((() => { try { if (window.YouTubePlusI18n?.hasTranslation) { return window.YouTubePlusI18n.hasTranslation("playAllButton"); } } catch (t) {} return !1; })()) { const t = f("playAllButton"); if (t && "playAllButton" !== t) { return t; } } return "Play All"; }, h = () => { const t = f("enablePlayAllLabel"); return t && "enablePlayAllLabel" !== t ? t : b(); }, g = (globalThis?.GM_info ?? null) || (window?.GM_info ?? null), w = g?.script?.version ?? null; if (w && /-(alpha|beta|dev|test)$/.test(w)) { try { window.YouTubeUtils?.logger?.info?.("%cytp - YouTube Play All\n", "color: var(--yt-playall-accent-purple); font-size: 32px; font-weight: bold", "You are currently running a test version:", w); } catch (t) {} } var v; v = () => { try { const t = window.YouTubeUtils?.StyleManager; if (t && "function" == typeof t.add) { const e = window.YouTubePlusDesignSystem?.getStyle?.("ytp-play-all-styles") || ""; t.add("ytp-play-all-styles", e); } } catch (t) { p?.warn?.("Play All", "Failed to inject Play All styles via StyleManager", t); } }, "function" == typeof requestIdleCallback ? requestIdleCallback(v, { timeout: 2e3 }) : setTimeout(v, 200); const x = t => window.YouTubeUtils?.getVideoIdFromUrl?.(t) ?? null, k = t => { const e = d(t); return e instanceof HTMLElement ? e : null; }, S = () => d("#movie_player"), T = () => { const t = window.location.pathname || ""; return /^\/(?:@[^/]+|channel\/[^/]+|c\/[^/]+|user\/[^/]+)(?:\/(videos|shorts|streams))?\/?$/.test(t) || /\/(videos|shorts|streams)\/?$/.test(t); }; let L = "", M = null; const C = (e, o) => { t(e, o); }, E = (t, e, o) => { if (t >= 12) { return; } const r = window.YouTubeUtils?.waitFor || window.YouTubeUtils?.waitForElement; "function" != typeof r ? C(() => z(t + 1), 80) : r(e, o).then(() => z(t + 1)).catch(() => z(t + 1)); }, z = (t = 0) => { if (p?.warn?.("Play All", "apply() start", { id: L, retryCount: t, path: location.pathname }), "" === L) { return p?.warn?.("Play All", "apply() id empty, scheduling addButton retry"), void C(() => { "" === L && j(); }, 200); } let o = null, r = null, i = null; if ("m.youtube.com" === location.host) { o = k("ytm-feed-filter-chip-bar-renderer .chip-bar-contents, ytm-feed-filter-chip-bar-renderer > div"); } else { const t = [ "ytd-rich-grid-renderer chip-bar-view-model.ytChipBarViewModelHost", "ytd-rich-grid-renderer chip-bar-view-model", "ytm-rich-grid-renderer chip-bar-view-model.ytChipBarViewModelHost", "ytm-rich-grid-renderer chip-bar-view-model", "ytd-two-column-browse-results-renderer chip-bar-view-model", "ytd-browse chip-bar-view-model", "chip-bar-view-model.ytChipBarViewModelHost", "chip-bar-view-model", "ytd-feed-filter-chip-bar-renderer iron-selector#chips", "ytd-feed-filter-chip-bar-renderer #chips-wrapper", "ytd-feed-filter-chip-bar-renderer", "yt-chip-cloud-renderer #chips", "yt-chip-cloud-renderer .yt-chip-cloud-renderer", "ytd-tabbed-page-header chip-bar-view-model" ]; for (const e of t) { const t = d(e); if (t instanceof HTMLElement) { if ("CHIP-BAR-VIEW-MODEL" === t.tagName && t.closest("ytd-engagement-panel-section-list-renderer, ytd-engagement-panel-title-header-renderer, ytd-miniplayer, ytd-live-chat-frame")) { continue; } if ("CHIP-BAR-VIEW-MODEL" === t.tagName) { r = t; const a = r.shadowRoot; if (a instanceof ShadowRoot) { o = a, p?.warn?.("Play All", "Using chip-bar shadow root", { selector: e }); } else { const t = r.parentElement; t instanceof HTMLElement ? (o = t, i = r, p?.warn?.("Play All", "Using chip-bar host parent", { selector: e, parentTag: t.tagName })) : (o = r, p?.warn?.("Play All", "Using chip-bar host directly", { selector: e, noParent: !0 })); } } else { o = t, p?.warn?.("Play All", "Found parent via selector", e); } break; } } } if (null === o) { p?.warn?.("Play All", "No chip bar parent, looking for grid"); const a = k("ytd-rich-grid-renderer, ytm-rich-grid-renderer, div.ytChipBarViewModelChipWrapper"); if (!a) { return p?.warn?.("Play All", "Grid not found, scheduling retry", { retryCount: t }), void E(t, "ytd-rich-grid-renderer, ytm-rich-grid-renderer, div.ytChipBarViewModelChipWrapper", 1500); } const s = a.querySelector("chip-bar-view-model.ytChipBarViewModelHost, chip-bar-view-model, ytd-feed-filter-chip-bar-renderer iron-selector#chips, ytd-feed-filter-chip-bar-renderer #chips-wrapper, yt-chip-cloud-renderer #chips"); if (s instanceof HTMLElement) { if ("CHIP-BAR-VIEW-MODEL" === s.tagName) { r = s; const t = r.shadowRoot; if (t instanceof ShadowRoot) { o = t, p?.warn?.("Play All", "Found chip-bar-view-model inside grid, using shadow root"); } else { const t = r.parentElement; t instanceof HTMLElement ? (o = t, i = r, p?.warn?.("Play All", "Found chip-bar-view-model inside grid, using host parent", { parentTag: t.tagName })) : (o = r, p?.warn?.("Play All", "Found chip-bar-view-model inside grid, using host directly")); } } else { r = s, o = r.shadowRoot || r, p?.warn?.("Play All", "Found chip bar inside grid", { inShadowRoot: !!r.shadowRoot }); } } else { if (t < 8) { return p?.warn?.("Play All", "Chip bar not in grid, scheduling retry", { retryCount: t }), void E(t, "chip-bar-view-model.ytChipBarViewModelHost, ytd-feed-filter-chip-bar-renderer iron-selector#chips, ytd-feed-filter-chip-bar-renderer #chips-wrapper, yt-chip-cloud-renderer #chips", 1200); } { p?.warn?.("Play All", "Using grid fallback container"); let t = a.querySelector(".ytp-button-container"); t || (a.insertAdjacentHTML("afterbegin", e('<div class="ytp-button-container"></div>')), t = a.querySelector(".ytp-button-container")), o = t instanceof HTMLElement ? t : null; } } } if (null === o && "m.youtube.com" !== location.host) { const t = d('[role="tablist"], ytd-tabbed-page-header #tabsContainer, ytd-tabbed-page-header'); t instanceof HTMLElement && (o = t, p?.warn?.("Play All", "Using tab container fallback")); } if (!o) { return void p?.warn?.("Play All", "Could not find parent container"); } if (r?.querySelector(".ytp-play-all-btn") || o.querySelector(".ytp-play-all-btn")) { try { p?.warn?.("Play All", "Button already exists, skipping"); } catch (t) {} return; } const a = window.location.pathname || "", [s] = a.endsWith("/shorts") ? [ "UUSH" ] : a.endsWith("/streams") ? [ "UULV" ] : [ "UULF" ], c = `/playlist?list=${s}${L.startsWith("UC") ? L.substring(2) : L}&playnext=1&ytp-random=random&ytp-random-initial=1`; p?.warn?.("Play All", "Creating button", { playlist: s, id: L, href: c }); const l = document.createElement("a"); if (l.className = "ytp-btn ytp-play-all-btn", l.href = c, l.title = h(), l.setAttribute("aria-label", h()), l.textContent = b(), l.addEventListener("click", t => { t.preventDefault(), t.stopPropagation(), window.location.href = c; }), A(), o instanceof ShadowRoot) { const t = window.YouTubePlusDesignSystem?.getStyle?.("ytp-play-all-styles"); if (t && !o.querySelector("style[data-ytp-play-all-styles]")) { const e = document.createElement("style"); e.setAttribute("data-ytp-play-all-styles", ""), e.textContent = t, o.appendChild(e); } o.insertBefore(l, o.firstChild), p?.warn?.("Play All", "Button inserted into chip-bar shadow root"); } else { i && i.parentElement === o ? (o.insertBefore(l, i), o.classList.add("ytp-play-all-parent"), p?.warn?.("Play All", "Button inserted before chip bar", { parentSelector: o.tagName + (o.className ? `.${o.className}` : "") })) : (o.appendChild(l), p?.warn?.("Play All", "Button appended", { parentSelector: o.tagName + (o.className ? `.${o.className}` : "") })); } C(() => P(d("ytd-rich-grid-renderer") || d("chip-bar-view-model.ytChipBarViewModelHost") || d("ytm-feed-filter-chip-bar-renderer .iron-selected, ytm-feed-filter-chip-bar-renderer .chip-bar-contents .selected")), 0); }; let _ = 0; const I = () => { _ = 0, r && (A(), O(), z()); }, A = () => { M && window.YouTubePlusMutationCoordinator?.unsubscribe && (window.YouTubePlusMutationCoordinator.unsubscribe(M), M = null); }, P = t => { if (A(), !r || !t) { return; } const e = window.YouTubePlusMutationCoordinator; e?.watchTarget && (M = "playall::observer", e.watchTarget(M, t, () => { r && (_ || (_ = "function" != typeof requestAnimationFrame ? setTimeout(I, 16) : requestAnimationFrame(I))); }, { attributes: !0, childList: !0, subtree: !0 })); }, j = async () => { if (A(), p?.warn?.("Play All", "addButton() start", { featureEnabled: r, path: location.pathname, supported: T() }), !r) { return void p?.warn?.("Play All", "addButton() feature disabled"); } if (!T()) { return void p?.warn?.("Play All", "addButton() path not supported"); } const e = d("ytd-rich-grid-renderer") || d("chip-bar-view-model.ytChipBarViewModelHost") || d("ytm-feed-filter-chip-bar-renderer .iron-selected, ytm-feed-filter-chip-bar-renderer .chip-bar-contents .selected"); if (P(e), d(".ytp-play-all-btn")) { return; } const o = await ((t = 10, e = 120) => new Promise(o => { let r = 0; const i = () => { r += 1; const a = (() => { try { const t = d('meta[itemprop="channelId"]'), e = t?.getAttribute("content"); if (e && /^UC[a-zA-Z0-9_-]{22}$/.test(e)) { return e; } const o = d('link[rel="canonical"]'), r = (o?.getAttribute("href") || "").match(/\/channel\/(UC[a-zA-Z0-9_-]{22})/); if (r?.[1]) { return r[1]; } const i = d('ytd-browse[page-subtype="channels"]'), a = i?.getAttribute?.("channel-id") || i?.getAttribute?.("external-id"); if (a && /^UC[a-zA-Z0-9_-]{22}$/.test(a)) { return a; } const s = d('ytd-channel-name a[href*="/channel/UC"], #channel-name a[href*="/channel/UC"], a[href^="/channel/UC"]'), c = (s?.getAttribute?.("href") || "").match(/\/channel\/(UC[a-zA-Z0-9_-]{22})/); if (c?.[1]) { return c[1]; } const l = location.href.match(/\/channel\/(UC[a-zA-Z0-9_-]{22})/); if (l?.[1]) { return l[1]; } const u = window.ytInitialData, p = u?.metadata?.channelMetadataRenderer?.externalId || u?.header?.c4TabbedHeaderRenderer?.channelId || u?.header?.pageHeaderRenderer?.content?.pageHeaderViewModel?.metadata?.contentMetadataViewModel?.metadataRows?.[0]?.metadataParts?.find?.(t => /^UC[a-zA-Z0-9_-]{22}$/.test(t?.text?.content || ""))?.text?.content; if (p && /^UC[a-zA-Z0-9_-]{22}$/.test(p)) { return p; } if (window.ytcfg?.get) { const t = window.ytcfg.get("CHANNEL_ID"); if (t && /^UC[a-zA-Z0-9_-]{22}$/.test(t)) { return t; } } } catch (t) { p?.warn?.("Play All", "Failed to resolve channel ID from DOM", t); } return null; })(); return a ? o(a) : r >= t ? o(null) : void C(i, e); }; i(); }))(12, 100); if (p?.warn?.("Play All", "resolveChannelIdWithRetry result", { resolvedFromDom: o }), o) { return L = o, void z(); } try { const e = location.href, o = new URL(e); if ("www.youtube.com" !== o.hostname && "youtube.com" !== o.hostname && "m.youtube.com" !== o.hostname) { return void p?.warn?.("Play All", "Skipping fetch for non-YouTube URL"); } const r = new AbortController, i = t(function() { r.abort(); }, 1e4); let a; try { a = await fetch(e, { signal: r.signal }); } finally { clearTimeout(i); } const s = await a.text(), c = s.match(/<link rel="canonical" href="https:\/\/www\.youtube\.com\/channel\/(UC[a-zA-Z0-9_-]{22})"/); if (c?.[1]) { L = c[1]; } else { const t = s.match(/"channelId":"(UC[a-zA-Z0-9_-]{22})"/); t?.[1] && (L = t[1]); } L ? (z(), p?.warn?.("Play All", "Channel ID resolved via fetch, button applied")) : p?.warn?.("Play All", "Could not extract channel ID"); } catch (t) { p?.error?.("Play All", "Error fetching channel data", t); } }, H = () => { s && c(s), s = null; }, D = (t = !0) => { if ("m.youtube.com" === location.host) { return void j(); } t && H(); const e = window.YouTubeUtils?.createRetryScheduler?.({ label: "playall-add-button", interval: 120, maxAttempts: 80, check: () => !r || !T() || (j(), !!d(".ytp-play-all-btn")) }); e ? s = e : j(); }, O = () => { u(".ytp-play-all-btn, .ytp-random-badge, .ytp-random-notice").forEach(t => t.remove()); }; let B = !1; const R = () => { try { H(), O(), L = "", "function" == typeof i && i(); } catch (t) {} }, F = () => { if (p?.warn?.("Play All", "startPlayAllRuntime()", { runtimeStarted: B, path: location.pathname }), B && R(), B = !0, "m.youtube.com" === location.host) { let t = location.href; const e = () => { location.href !== t && (t = location.href, j()); }, o = () => C(e, 50); y?.registerListener ? (y.registerListener(window, "ytp-history-navigate", o, { passive: !0 }), y.registerListener(window, "popstate", e, { passive: !0 })) : (window.addEventListener("ytp-history-navigate", o, { passive: !0 }), window.addEventListener("popstate", e, { passive: !0 })), j(); } else { const t = () => { H(), O(), L = ""; }, e = () => { D(); }, o = () => C(() => D(), 120), r = () => { "visible" === document.visibilityState && D(); }; y?.registerListener ? (y.registerListener(document, "yt-navigate-start", t), y.registerListener(document, "yt-navigate-finish", e), y.registerListener(document, "yt-page-data-updated", e), y.registerListener(document, "yt-page-data-fetched", e), y.registerListener(window, "pageshow", o), y.registerListener(document, "visibilitychange", r)) : (document.addEventListener("yt-navigate-start", t), document.addEventListener("yt-navigate-finish", e), document.addEventListener("yt-page-data-updated", e), document.addEventListener("yt-page-data-fetched", e), window.addEventListener("pageshow", o), document.addEventListener("visibilitychange", r)); try { m(() => D(!1)), C(() => D(!1), 120); } catch (t) {} try { window.addEventListener("ytp:nav-refresh", function() { try { D(!1); } catch {} }); } catch {} } const t = t => { try { const e = t instanceof CustomEvent ? t : null, o = !1 !== e?.detail?.enablePlayAll; if (o === r) { return; } l(o); } catch (t) { l(window.YouTubeUtils?.loadFeatureEnabled?.("enablePlayAll") ?? !0); } }; y?.registerListener ? y.registerListener(window, "youtube-plus-settings-updated", t) : window.addEventListener("youtube-plus-settings-updated", t), (() => { if ("m.youtube.com" === location.host) { return; } const t = t => { try { return JSON.parse(localStorage.getItem(t) || "{}"); } catch (t) { return {}; } }, s = (e, o) => t(e)[o], c = (e, o) => { localStorage.setItem(e, JSON.stringify({ ...t(e), [o]: !0 })), document.querySelectorAll("#wc-endpoint[href*=zsA3X40nz9w]").forEach(t => t.parentElement?.setAttribute("hidden", "")); }, l = (e, o = !1) => { const r = S(); r && "function" == typeof r.pauseVideo && r.pauseVideo(); const i = Object.entries(t(e.storageKey)).filter(([t, e]) => !e), a = new URLSearchParams(window.location.search); if (0 === i.length) { return; } let s = Math.floor(Math.random() * i.length); if (s < 0 && (s = 0), s >= i.length && (s = i.length - 1), o) { a.set("v", i[s][0]), a.set("ytp-random", e.mode), a.delete("t"), a.delete("index"), a.delete("ytp-random-initial"), window.location.href = `${window.location.pathname}?${a.toString()}`; } else { try { const t = a.get("list") || ""; ((t, e, o = null) => { if ("m.youtube.com" === location.host) { window.location.href = `/watch?v=${t}&list=${e}${null !== o ? `&ytp-random=${o}` : ""}`; } else { try { const r = d("ytd-playlist-panel-renderer #items"); if (r) { const i = document.createElement("a"); i.className = "yt-simple-endpoint style-scope ytd-playlist-panel-video-renderer", i.setAttribute("hidden", ""), i.data = { commandMetadata: { webCommandMetadata: { url: `/watch?v=${t}&list=${e}${null !== o ? `&ytp-random=${o}` : ""}`, webPageType: "WEB_PAGE_TYPE_WATCH", rootVe: 3832 } }, watchEndpoint: { videoId: t, playlistId: e } }, r.append(i), i.click(); } else { const r = `/watch?v=${t}&list=${e}${null !== o ? `&ytp-random=${o}` : ""}`; window.location.href = r; } } catch (r) { window.location.href = `/watch?v=${t}&list=${e}${null !== o ? `&ytp-random=${o}` : ""}`; } } })(i[s][0], t, e.mode); } catch (t) { p?.error?.("Play All", "Error using redirect(), falling back to manual redirect", t); const o = document.createElement("a"); o.className = "yt-simple-endpoint style-scope ytd-playlist-panel-video-renderer", o.setAttribute("hidden", ""), o.data = { commandMetadata: { webCommandMetadata: { url: `/watch?v=${i[s][0]}&list=${a.get("list")}&ytp-random=${e.mode}`, webPageType: "WEB_PAGE_TYPE_WATCH", rootVe: 3832 } }, watchEndpoint: { videoId: i[s][0], playlistId: a.get("list") } }; const r = d("ytd-playlist-panel-renderer #items"); if (r instanceof HTMLElement) { r.append(o); } else { const t = document.body || document.documentElement; t && t.appendChild(o); } o.click(); } } }; let u = null, m = !1; i = () => { u && ("number" == typeof u ? clearTimeout(u) : u.stop()), u = null, m = !1; }, a = () => { if (!r) { return; } if (i?.(), !window.location.pathname.endsWith("/watch")) { return; } const a = window.YouTubeUtils?.createRetryScheduler?.({ check: () => { const i = (() => { const t = new URLSearchParams(window.location.search), e = t.get(o); if (!e || "0" === e) { return null; } const r = t.get("list") || ""; return r ? { params: t, mode: "random", list: r, storageKey: `ytp-random-${r}` } : null; })(); if (!i) { return !1; } try { const t = localStorage.getItem(i.storageKey); t && Array.isArray(JSON.parse(t)) && localStorage.removeItem(i.storageKey); } catch (t) { localStorage.removeItem(i.storageKey); } return (i => { if (!r) { return; } if (!window.location.pathname.endsWith("/watch")) { return; } const a = d("#secondary ytd-playlist-panel-renderer"); if (null === a) { return; } if (a.hasAttribute("ytp-random")) { return; } a.setAttribute("ytp-random", "applied"); const u = a.querySelector("#header"); u && !u.querySelector(".ytp-random-notice") && u.insertAdjacentHTML("beforeend", e(`<span class="ytp-random-notice">${f("playAllMode")}</span>`)); const p = t(i.storageKey), b = []; [ "#wc-endpoint", "ytd-playlist-panel-video-renderer a#wc-endpoint", "ytd-playlist-panel-video-renderer a", "a#video-title", '#secondary ytd-playlist-panel-renderer a[href*="/watch?"]' ].forEach(t => { a.querySelectorAll(t).forEach(t => { t instanceof Element && "A" === t.tagName && b.push(t); }); }); const h = [], g = new Set; b.forEach(t => { const e = t.href || t.getAttribute("href") || ""; g.has(e) || (g.add(e), h.push(t)); }), h.forEach(t => { let e = null; try { e = new URL(t.href, window.location.origin).searchParams.get("v"); } catch (o) { e = new URLSearchParams(t.search || "").get("v"); } if (!e) { return; } s(i.storageKey, e) || (p[e] = !1); try { const e = new URL(t.href, window.location.origin); e.searchParams.set(o, i.mode), t.href = e.toString(); } catch (t) {} t.setAttribute("data-ytp-random-link", "true"); const r = x(t.href); r && s(i.storageKey, r) && t.parentElement?.setAttribute("hidden", ""); }), a && !a.hasAttribute("data-ytp-random-delegated") && (a.setAttribute("data-ytp-random-delegated", "true"), a.addEventListener("click", t => { const e = t.target instanceof Element ? t.target : null, o = e?.closest?.("a[data-ytp-random-link]") ?? null; o?.href && (t.preventDefault(), window.location.href = o.href); })), localStorage.setItem(i.storageKey, JSON.stringify(p)); const w = x(location.href); if ("1" === i.params.get("ytp-random-initial") || w && s(i.storageKey, w)) { return void l(i); } const v = a.querySelector("h3 a"); if (v && "A" === v.tagName) { const t = v; t.insertAdjacentHTML("beforeend", e(' <span class="ytp-badge ytp-random-badge">Play All <span class="ytp-random-badge-close">×</span></span>')), t.href = "#"; const o = t.querySelector(".ytp-random-badge"); o && o.addEventListener("click", t => { t.preventDefault(), localStorage.removeItem(i.storageKey); const e = new URLSearchParams(location.search); e.delete("ytp-random"), window.location.href = `${window.location.pathname}?${e.toString()}`; }); } const k = t => { if (t instanceof KeyboardEvent && t.shiftKey && "n" === t.key.toLowerCase()) { t.stopImmediatePropagation(), t.preventDefault(); const e = x(location.href); e && c(i.storageKey, e), l(i, !0); } }; if (y?.registerListener ? y.registerListener(document, "keydown", k, !0) : document.addEventListener("keydown", k, !0), m) { return; } const T = d("video"); T && (T.addEventListener("timeupdate", () => { const t = x(location.href), e = new URLSearchParams(location.search); e.set("ytp-random", i.mode), window.history.replaceState({}, "", `${window.location.pathname}?${e.toString()}`); const o = S(); if (!o || "function" != typeof o.getProgressState) { return; } const r = o.getProgressState(); if (!r || "number" != typeof r.current || "number" != typeof r.duration) { return; } d(".ad-interrupting") || (r.current / r.duration >= .9 && t && c(i.storageKey, t), r.current >= r.duration - 2 && ("function" == typeof o.pauseVideo && o.pauseVideo(), "function" == typeof o.seekTo && o.seekTo(0), l(i))); const a = d('#ytd-player .ytp-next-button.ytp-button:not([ytp-random="applied"])'); if (a instanceof HTMLElement) { const e = document.createElement("span"); e.className = a.className, window.YouTubeUtils.renderTemplateClone(e, a.innerHTML), a.replaceWith(e), e.setAttribute("ytp-random", "applied"), e.addEventListener("click", () => { t && c(i.storageKey, t), l(i); }); } }, { passive: !0 }), m = !0); })(i), !!d("#secondary ytd-playlist-panel-renderer[ytp-random]"); }, maxAttempts: 30, interval: 250 }); a && (u = a); }; const b = () => { r ? (i?.(), a?.()) : i?.(); }; b(); const h = () => setTimeout(b, 200); y?.registerListener ? y.registerListener(document, "yt-navigate-finish", h) : document.addEventListener("yt-navigate-finish", h); })(); }; window.YouTubeUtils?.whenRelevant ? window.YouTubeUtils.whenRelevant({ name: "playall", isRelevant: () => { try { return !window.location.search.includes("list=") && T(); } catch (t) { return !1; } }, onEnter: F, onLeave: R }) : F(); })().catch(t => (window.YouTubeUtils?.logger || null)?.error?.("Play All", "Module bootstrap failure", t)), (function() { function t() { try { localStorage.setItem(E.storageKey, JSON.stringify({ enabled: E.enabled, pointA: E.pointA, pointB: E.pointB })); } catch (t) { s()?.warn?.("Time", "Failed to save loop state", t); } } function e() { if (E.timeUpdateListener) { const t = document.querySelector("video"); if (t) { try { t.removeEventListener("timeupdate", E.timeUpdateListener); } catch (t) {} } E.timeUpdateListener = null; } } function o(t) { e(); const o = I(); o && (E.timeUpdateListener = () => { E.enabled && t.currentTime >= o.end && (t.currentTime = o.start); }, t.addEventListener("timeupdate", E.timeUpdateListener)); } function r() { if (null === E.pointA && null === E.pointB) { const t = document.querySelector(".ytp-plus-loop-indicator"); return void (t && t.remove()); } const t = document.querySelector("video"); if (!t?.duration) { return; } let e = document.querySelector(".ytp-progress-bar-container") || document.querySelector(".ytp-scrubber-container") || document.querySelector('[role="slider"][aria-label*="video"]') || document.querySelector(".html5-progress-bar"); if (!e) { const t = document.querySelector(".html5-video-player"); t && (e = t.querySelector('[role="slider"]')); } if (!e) { return; } let o = document.querySelector(".ytp-plus-loop-indicator"); if (!o) { o = document.createElement("div"), o.className = "ytp-plus-loop-indicator"; try { const t = window.getComputedStyle(e); t && "static" !== t.position || (e.style.position = "relative"); } catch (t) {} e.appendChild(o), o.style.position = "absolute", o.style.top = "0", o.style.height = "100%", o.style.pointerEvents = "none", o.style.zIndex = "1000"; } if (null !== E.pointA && null === E.pointB) { return o.style.left = E.pointA / t.duration * 100 + "%", o.style.width = "2px", o.style.background = "linear-gradient(90deg,var(--yt-accent-secondary),var(--yt-accent-secondary-light))", o.style.borderLeft = "2px solid var(--yt-accent-secondary)", o.style.borderRight = "2px solid var(--yt-accent-secondary)", void (o.style.display = "block"); } if (null !== E.pointB && null === E.pointA) { return o.style.left = E.pointB / t.duration * 100 + "%", o.style.width = "2px", o.style.background = "linear-gradient(90deg,var(--yt-accent-secondary),var(--yt-accent-secondary-light))", o.style.borderLeft = "2px solid var(--yt-accent-secondary)", o.style.borderRight = "2px solid var(--yt-accent-secondary)", void (o.style.display = "block"); } const r = I(); if (!r) { return; } const i = r.start / t.duration * 100, a = r.end / t.duration * 100; o.style.left = `${i}%`, o.style.width = `${Math.max(.2, a - i)}%`, o.style.background = "linear-gradient(90deg,var(--yt-accent-secondary-ghost) 0%,var(--yt-accent-secondary-light-ghost) 50%,var(--yt-accent-secondary-ghost) 100%)", o.style.borderLeft = "2px solid var(--yt-accent-secondary)", o.style.borderRight = "2px solid var(--yt-accent-secondary)", o.style.display = "block"; } function i() { const t = document.querySelector("video"); if (t) { if (e(), !z() || !E.enabled) { return t.loop = !1, void r(); } I() ? (t.loop = !1, o(t)) : t.loop = !0, r(); } } if (window.__ytpTimeInitDone__) { return; } window.__ytpTimeInitDone__ = !0; const a = window.YouTubeUtils, s = () => window.YouTubePlusLogger || a?.logger || null, c = () => a?.cleanupManager || window.YouTubePlusCleanupManager || null; let l = !0, d = null; const u = t => { if (l = !1 !== t, l) { try { T(); } catch (t) { s()?.warn?.("Time", "initResume threw on enable", t); } } else { const t = m(w); if (t) { try { t.remove(); } catch (t) { s()?.warn?.("Time", "Failed to remove resume overlay on disable", t); } } if ("function" == typeof d) { try { d(); } catch (t) { s()?.warn?.("Time", "Active cleanup threw on disable", t); } d = null; } } }; l = a?.loadFeatureEnabled?.("enableResumeTime") ?? !0; const p = a?.setTimeout_ || setTimeout, {$: y, byId: m} = a || {}, f = a?.onDomReady || (t => { "loading" !== document.readyState ? t() : document.addEventListener("DOMContentLoaded", t, { once: !0 }); }), b = () => { try { const t = a?.StyleManager; if (!t || "function" != typeof t.add) { return; } const e = window.YouTubePlusDesignSystem?.getStyle?.("ytp-resume-overlay-styles") || ""; if (!e) { return; } t.add("ytp-resume-overlay-styles", e); } catch (t) { s()?.warn?.("Time", "Failed to pre-register resume overlay styles", t); } }, h = (() => { let t = !1; return () => { if (t) { return; } t = !0; const e = window.YouTubePlusEventDelegation, o = (t, e) => { const o = e?.getAttribute("data-ytp-resume-action"); if (!o || !e) { return; } const r = e.closest(".ytp-resume-overlay"); r && ("resume" === o ? r.dispatchEvent(new CustomEvent("ytp:resume", { bubbles: !0 })) : "restart" === o && r.dispatchEvent(new CustomEvent("ytp:restart", { bubbles: !0 }))); }; if (e?.on) { e.on(document, "click", ".ytp-resume-btn", o), e.on(document, "keydown", ".ytp-resume-btn", (t, e) => { "Enter" !== t.key && " " !== t.key || (t.preventDefault(), o(0, e)); }); } else { const t = t => { const e = t.target?.closest?.(".ytp-resume-btn"); e && o(0, e); }, e = t => { const e = t.target?.closest?.(".ytp-resume-btn"); e && ("Enter" !== t.key && " " !== t.key || (t.preventDefault(), o(0, e))); }; a?.cleanupManager?.registerListener ? (a.cleanupManager.registerListener(document, "click", t, !0), a.cleanupManager.registerListener(document, "keydown", e, !0)) : (document.addEventListener("click", t, !0), document.addEventListener("keydown", e, !0)); } }; })(), g = "youtube_resume_times_v1", w = "yt-resume-overlay", v = (t, e = {}) => { if (a?.t) { return a.t(t, e); } const o = t; if (!e || 0 === Object.keys(e).length) { return o; } let r = o; for (const [t, o] of Object.entries(e)) { r = r.split(`{${t}}`).join(String(o)); } return r; }, x = () => { try { const t = localStorage.getItem(g), e = t ? JSON.parse(t) : {}; return e && "object" == typeof e ? e : {}; } catch (t) { return s()?.warn?.("Time", "Failed to parse resume storage", t), {}; } }, k = () => { try { const t = window.YouTubeUtils?.getVideoIdFromLocation?.(); if (t) { return t; } const e = y('link[rel="canonical"]'); if (e?.href) { const t = new URL(e.href), o = t.searchParams.get("v"); if (o) { return o; } const r = t.pathname.match(/\/(watch|shorts)\/([^/?]+)/); if (r?.[2]) { return r[2]; } } const o = window.ytInitialPlayerResponse, r = o?.videoDetails?.videoId; if ("string" == typeof r && r) { return r; } const i = window.location.pathname.match(/\/(watch|shorts)\/([^/?]+)/); return i?.[2] ? i[2] : null; } catch (t) { return null; } }, S = a.formatTime || (t => { const e = Number.isFinite(t) && t > 0 ? t : 0, o = Math.floor(e % 60).toString().padStart(2, "0"), r = Math.floor(e / 60 % 60).toString(), i = Math.floor(e / 3600); return i ? `${i}:${r.padStart(2, "0")}:${o}` : `${r}:${o}`; }), T = () => { if (!l) { const t = m(w); if (t) { try { t.remove(); } catch (t) { s()?.warn?.("Time", "Failed to remove overlay on init", t); } } return; } if ("/watch" !== window.location.pathname) { const t = m(w); if (t) { try { t.remove(); } catch (t) { a.logSuppressed(t, "Time"); } } return; } const t = k(), e = m(w); if (e) { try { e.dataset && e.getAttribute("data-vid") === t || e.remove(); } catch (t) { try { e.remove(); } catch (t) { s()?.warn?.("Time", "Overlay removal failed twice", t); } } } const o = (() => { const t = [ "video.html5-main-video", "video.video-stream", "#movie_player video", "video" ]; for (const e of t) { const t = y(e); if (t && "VIDEO" === t.tagName) { return t; } } return null; })(); if (o) { return void (t => { if (!l) { return null; } if ("VIDEO" !== t?.tagName) { return void s()?.warn?.("Time", "Invalid video element for resume handlers"); } if (t.St) { return; } t.St = !0; const e = () => k(), o = e(); if (!o) { return; } const r = x()[o]; let i = null, u = 0; if (r && r > 5 && !m(w)) { const e = ((t, e, o, r) => { if (m(w)) { return null; } const i = document.createElement("div"); i.id = w, i.setAttribute("role", "alertdialog"), i.setAttribute("aria-label", v("resumePlayback")), r && i.setAttribute("data-vid", r), b(), i.className = "ytp-resume-overlay ytp-plus-resume-overlay", i.style.position = "absolute", i.style.left = "50%", i.style.bottom = "5%", i.style.transform = "translate(-50%,-50%)", i.style.zIndex = "2147483647", i.style.pointerEvents = "auto"; const l = y("#player-container"); if (l instanceof HTMLElement) { try { "static" === window.getComputedStyle(l).position && (l.style.position = "relative"); } catch (t) {} l.appendChild(i); } else { const t = y("#movie_player"); if (t instanceof HTMLElement) { try { "static" === window.getComputedStyle(t).position && (t.style.position = "relative"); } catch (t) {} t.appendChild(i); } else { i.style.position = "fixed", i.style.bottom = "8%", (document.body || document.documentElement).appendChild(i); } } const d = document.createElement("div"); d.className = "ytp-resume-title", d.textContent = `${v("resumePlayback")} (${S(t)})`; const u = document.createElement("button"); u.className = "ytp-resume-btn primary", u.textContent = v("resume"), u.setAttribute("aria-label", `${v("resume")} at ${S(t)}`), u.tabIndex = 0, u.setAttribute("data-ytp-resume-action", "resume"); const p = document.createElement("button"); p.className = "ytp-resume-btn ghost", p.textContent = v("startOver"), p.setAttribute("aria-label", v("startOver")), p.tabIndex = 0, p.setAttribute("data-ytp-resume-action", "restart"); const f = (t, e) => { try { t(); } catch (t) { s()?.error?.("Time", `${e} error`, t); } try { i.remove(); } catch (t) { a.logSuppressed(t, "Time"); } }; h(), i.addEventListener("ytp:resume", () => f(e, "Resume"), { once: !0 }), i.addEventListener("ytp:restart", () => f(o, "Restart"), { once: !0 }); const g = document.createElement("div"); g.className = "ytp-resume-actions", g.appendChild(u), g.appendChild(p), i.appendChild(d), i.appendChild(g); try { requestAnimationFrame(() => { u.focus(); }); } catch (t) { a.logSuppressed(t, "Time"); } let x = setTimeout(() => { x = null; try { i.remove(); } catch (t) { a.logSuppressed(t, "Time"); } }, 1e4); const k = () => { x && clearTimeout(x), x = null; }, T = c(); return T && "function" == typeof T.register && T.register(() => { try { k(); } catch (t) { a.logSuppressed(t, "Time"); } try { i.remove(); } catch (t) { a.logSuppressed(t, "Time"); } }), k; })(r, () => { try { t.currentTime = r, t.play(); } catch (t) { s()?.error?.("Time", "Failed to resume playback", t); } }, () => { try { t.currentTime = 0, t.play(); } catch (t) { s()?.error?.("Time", "Failed to start over", t); } }, o), i = c(); i && "function" == typeof i.register && e && i.register(e); } const p = () => (() => { if (i) { return; } i = () => { try { const o = e(); if (!o) { return; } const r = Math.floor(t.currentTime || 0), i = Date.now(); if (r && (!u || i - u > 800)) { const t = x(); t[o] = r, (t => { try { localStorage.setItem(g, JSON.stringify(t)); } catch (t) { s()?.warn?.("Time", "Failed to save resume time", t); } })(t), u = i; } } catch (t) { s()?.warn?.("Time", "Error saving playback time", t); } }, t.addEventListener("timeupdate", i, { passive: !0 }); const o = c(); o && "function" == typeof o.register && o.register(() => { try { i && t.removeEventListener("timeupdate", i); } catch (t) {} }); })(), f = () => (() => { if (i) { try { t.removeEventListener("timeupdate", i); } catch (t) {} i = null, u = 0; } })(); t.addEventListener("play", p, { passive: !0 }), t.addEventListener("pause", f, { passive: !0 }); const T = () => { try { t.removeEventListener("play", p), t.removeEventListener("pause", f), i && t.removeEventListener("timeupdate", i), delete t.St; } catch (t) { s()?.error?.("Time", "Resume cleanup error", t); } }, L = c(); L && "function" == typeof L.register && L.register(T), d = T; })(o); } const r = a?.waitForElement || a?.waitFor; "function" == typeof r ? r("video", 1200).then(() => { try { T(); } catch (t) { s()?.warn?.("Time", "initResume after waitFor threw", t); } }) : requestAnimationFrame(T); }, L = () => setTimeout(T, 150); if (f(() => { b(), T(); }), window?.document) { const t = c(); t && "function" == typeof t.registerListener ? t.registerListener(document, "yt-navigate-finish", L, { passive: !0 }) : document.addEventListener("yt-navigate-finish", L, { passive: !0 }); } const M = t => { try { const e = !1 !== t?.detail?.enableResumeTime; if (e === l) { return; } u(e); } catch (t) { u(a?.loadFeatureEnabled?.("enableResumeTime") ?? !0); } }, C = c(); C && "function" == typeof C.registerListener ? C.registerListener(window, "youtube-plus-settings-updated", M) : window.addEventListener("youtube-plus-settings-updated", M); const E = { enabled: !1, pointA: null, pointB: null, storageKey: "youtube_loop_state", timeUpdateListener: null }, z = () => !1 !== a?.loadFeatureEnabled?.("enableLoop"), _ = a?.t || (t => t), I = () => { const t = E.pointA, e = E.pointB; return null === t || null === e ? null : { start: Math.min(t, e), end: Math.max(t, e) }; }; window.YouTubePlusTimeLoop = { toggleLoop: function() { if (!z()) { return; } E.enabled = !E.enabled; const i = document.querySelector("video"); i ? (E.enabled ? (null === E.pointA && null === E.pointB ? i.loop = !0 : (i.loop = !1, o(i)), a?.NotificationManager.show(_("loopEnabled"), { duration: 1500, type: "success" })) : (i.loop = !1, e(), a?.NotificationManager.show(_("loopDisabled"), { duration: 1500, type: "info" })), r(), t()) : t(); }, setLoopPoint: function(e) { if (!z()) { return; } const i = document.querySelector("video"); if (!i) { return; } const s = i.currentTime; "A" === e ? (E.pointA = s, a?.NotificationManager.show(`${_("loopPointASet")}: ${S(s)}`, { duration: 1500, type: "success" })) : "B" === e && (E.pointB = s, a?.NotificationManager.show(`${_("loopPointBSet")}: ${S(s)}`, { duration: 1500, type: "success" })), E.enabled && I() && (i.loop = !1, o(i)), r(), t(); }, resetLoopPoints: function() { if (z()) { if (E.pointA = null, E.pointB = null, E.enabled) { const t = document.querySelector("video"); t && (t.loop = !0, e()); } a?.NotificationManager.show(_("loopPointsReset"), { duration: 1500, type: "info" }), r(), t(); } }, applyLoopStateToCurrentVideo: i }, z() && p(function() { try { const t = localStorage.getItem(E.storageKey); if (t) { const e = JSON.parse(t); E.enabled = Boolean(e?.enabled), E.pointA = "number" == typeof e?.pointA && Number.isFinite(e.pointA) ? e.pointA : null, E.pointB = "number" == typeof e?.pointB && Number.isFinite(e.pointB) ? e.pointB : null, p(() => i(), 1e3); } } catch (t) { s()?.warn?.("Time", "Failed to load loop state", t); } }, 1e3); })(), (function() { const t = setTimeout.bind(window), e = window.YouTubeUtils, o = () => e.isWatchRoute() || e.isShortsRoute(), r = () => { function r() { try { const t = localStorage.getItem(h); if (!t) { return { zoom: w, panX: 0, panY: 0 }; } const e = JSON.parse(t); return { zoom: Number(e?.zoom) || w, panX: Number(e?.panX) || 0, panY: Number(e?.panY) || 0 }; } catch (t) { return { zoom: w, panX: 0, panY: 0 }; } } function i(t, e, o) { try { const r = { zoom: Number(t) || w, panX: Number(e) || 0, panY: Number(o) || 0 }; localStorage.setItem(h, JSON.stringify(r)); } catch (t) { b?.warn?.("Zoom", "Failed to save zoom/pan settings", t); } } function a(t) { try { const e = Object.assign({ time: (new Date).toISOString() }, t); try { const t = sessionStorage.getItem(g), o = t ? JSON.parse(t) : []; o.push(e), o.length > 200 && o.splice(0, o.length - 200), sessionStorage.setItem(g, JSON.stringify(o)); } catch (t) {} ("undefined" != typeof window && window.YTP_DEBUG || window.YouTubePlusConfig?.debug) && b?.warn?.("Zoom", "Zoom restore", e); } catch (t) { e.logSuppressed(t, "Zoom"); } } function s() { function o(t) { try { if (E) { return; } for (const o of t) { if ("attributes" === o.type && "style" === o.attributeName) { const t = g?.style?.transform || "", o = r().zoom || parseFloat(p.value) || w, i = `translate(${B.toFixed(2)}px, ${R.toFixed(2)}px) scale(${o.toFixed(3)})`; o !== w && t !== i && t !== C && requestAnimationFrame(() => { try { z(g, o, B, R); try { a({ action: "restore_transform", currentTransform: t, expectedTransform: i, zoom: o, panX: B, panY: R }); } catch (t) { e.logSuppressed(t, "Zoom"); } } catch (t) { e.logSuppressed(t, "Zoom"); } }); } } } catch (t) { e.logSuppressed(t, "Zoom"); } } function s() { N && (F?.unwatch?.(N), N = null), g && F?.watchTarget && (N = "zoom::videoStyle", F.watchTarget(N, g, o, { attributes: !0, childList: !1, subtree: !1, attributeFilter: [ "style" ] })); } const c = m("#movie_player"); if (!c) { return null; } if (f("ytp-zoom-control")) { return f("ytp-zoom-control"); } if (!f("ytp-zoom-styles")) { const t = document.createElement("style"); t.id = "ytp-zoom-styles", t.textContent = "\n /* Compact control bar matching YouTube control style */\n #ytp-zoom-control{position: absolute; left: 12px; bottom: 70px; z-index: 2200; display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 24px; background: var(--yt-glass-bg); color: var(--yt-text-primary); font-size: 12px; box-shadow: 0 2px 8px var(--yt-shadow-flyout); backdrop-filter: blur(6px);}\n #ytp-zoom-control input[type=range]{width: 120px; -webkit-appearance: none; background: transparent; height: 24px;}\n /* WebKit track */\n #ytp-zoom-control input[type=range]::-webkit-slider-runnable-track{height: 4px; background: var(--yt-button-bg); border-radius: 3px;}\n #ytp-zoom-control input[type=range]::-webkit-slider-thumb{-webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: var(--yt-text-primary); box-shadow: 0 0 0 6px var(--yt-button-bg); margin-top: -4px;}\n /* Firefox */\n #ytp-zoom-control input[type=range]::-moz-range-track{height: 4px; background: var(--yt-button-bg); border-radius: 3px;}\n #ytp-zoom-control input[type=range]::-moz-range-thumb{width: 12px; height: 12px; border-radius: 50%; background: var(--yt-text-primary); border: none;}\n #ytp-zoom-control .zoom-label{min-width:36px;text-align:center;font-size:11px;padding:0 6px;user-select:none}\n #ytp-zoom-control::after{content:'Shift + Wheel to zoom';position:absolute;bottom:100%;right:0;padding:4px 8px;background:var(--yt-notification-bg);color:var(--yt-text-primary);font-size:10px;border-radius:4px;white-space:nowrap;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .2s,transform .2s}\n #ytp-zoom-control:hover::after{opacity:1;transform:translateY(-4px)}\n #ytp-zoom-control .zoom-reset{background: var(--yt-button-bg); border: none; color: inherit; padding: 4px; display: flex; align-items: center; justify-content: center; border-radius: 50%; cursor: pointer; width: 28px; height: 28px;}\n #ytp-zoom-control .zoom-reset:hover{background: var(--yt-hover-bg)}\n #ytp-zoom-control .zoom-reset svg{display:block;width:14px;height:14px}\n /* Hidden state to mirror YouTube controls autohide */\n #ytp-zoom-control.ytp-hidden,\n .ytp-autohide #ytp-zoom-control,\n .ytp-hide-controls #ytp-zoom-control{opacity:0 !important;transform:translateY(6px) !important;pointer-events:none !important}\n #ytp-zoom-control{transition:opacity .18s ease, transform .18s ease}\n ", (document.head || document.documentElement).appendChild(t); } const u = document.createElement("div"); u.id = "ytp-zoom-control"; const p = document.createElement("input"); p.type = "range", p.min = String(v), p.max = String(x), p.step = String(k); const y = document.createElement("div"); y.className = "zoom-label", y.setAttribute("role", "status"), y.setAttribute("aria-live", "polite"), y.setAttribute("aria-label", "Current zoom level"); const h = document.createElement("button"); h.className = "zoom-reset", h.type = "button", h.setAttribute("aria-label", "Reset zoom"), h.title = "Reset zoom", e.renderTemplateClone(h, '\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">\n <path d="M12 4V1l-5 5 5 5V7a7 7 0 1 1-7 7" stroke="currentColor" stroke-width="2" fill="none"/>\n </svg>\n '), u.appendChild(p), u.appendChild(y), u.appendChild(h); let g = M(); const _ = r().zoom, I = Number.isFinite(_) && !Number.isNaN(_) ? _ : w, A = t => { const e = Math.min(x, Math.max(v, Number(t))); p.value = String(e); const o = Math.round(100 * e); y.textContent = `${o}%`, y.setAttribute("aria-label", `Current zoom level ${o} percent`), g && (J(e), requestAnimationFrame(() => { try { z(g, e, B, R); try { g.style.cursor = e > 1 ? "grab" : ""; } catch (t) {} } catch (t) { b?.error?.("Zoom", "Apply zoom error", t); } })); try { i(e, B, R); } catch (t) { b?.error?.("Zoom", "Save zoom error", t); } }; p.addEventListener("input", t => { const e = t.target; A(e ? e.value : w); }), h.addEventListener("click", () => { try { B = 0, R = 0, A(w); try { i(w, 0, 0); } catch (t) { b?.warn?.("Zoom", "Failed to persist zoom reset", t); } h.style.transform = "scale(0.9)", t(() => { h.style.transform = ""; }, 150); } catch (t) { b?.error?.("Zoom", "Reset zoom error", t); } }); let P = null, j = null; const H = () => { try { j && clearTimeout(j), j = t(() => { try { i(parseFloat(p.value) || r().zoom || w, B, R); } catch (t) { b?.error?.("Zoom", "Save pan error", t); } j = null; }, 220); } catch (t) { b?.error?.("Zoom", "Schedule save pan error", t); } }, D = e => { try { if (!l) { return; } if (!e.shiftKey) { return; } if (e.preventDefault(), P) { return; } P = t(() => { P = null; }, 50); const o = e.deltaY > 0 ? -k : k, i = (r().zoom || w) + o; i >= v && i <= x && A(i); } catch (t) { b?.error?.("Zoom", "Wheel zoom error", t); } }; if (c.addEventListener("wheel", D, { passive: !1 }), g) { try { g.addEventListener("wheel", D, { passive: !1 }); } catch (t) { b?.error?.("Zoom", "Failed to attach wheel handler to video", t); } } const O = t => { try { if (!l) { return; } const e = document.activeElement; if (e && ("INPUT" === e.tagName || "TEXTAREA" === e.tagName || e.isContentEditable)) { return; } if ("+" === t.key || "=" === t.key) { t.preventDefault(); const e = r().zoom || w; A(Math.min(x, e + k)); } else if ("-" === t.key) { t.preventDefault(); const e = r().zoom || w; A(Math.max(v, e - k)); } } catch (t) { b?.error?.("Zoom", "Keyboard zoom error", t); } }; window.addEventListener("keydown", O); let B = 0, R = 0; const F = window.YouTubePlusMutationCoordinator; let N = null; const Z = "zoom::playerVideoSwap"; let V = !1, Y = 0, q = 0, G = 0, W = 0; const J = (t = r().zoom) => { try { if (!g) { return; } const e = g.parentElement || g; if (!e) { return; } const o = e.getBoundingClientRect(); if (!o || 0 === o.width || 0 === o.height) { return; } const r = g.videoWidth || g.offsetWidth || o.width, i = g.videoHeight || g.offsetHeight || o.height; if (!(r && i && Number.isFinite(r) && Number.isFinite(i))) { return; } const a = i * t, s = Math.max(0, (r * t - o.width) / 2), c = Math.max(0, (a - o.height) / 2); Number.isFinite(s) && Number.isFinite(B) && (B = Math.max(-s, Math.min(s, B))), Number.isFinite(c) && Number.isFinite(R) && (R = Math.max(-c, Math.min(c, R))); } catch (t) { b?.error?.("Zoom", "Clamp pan error", t); } }, K = new Map; let X = null, Q = null, tt = null; const et = (t, e) => Math.hypot(t.x - e.x, t.y - e.y), nt = t => { try { if (!l) { return; } K.set(t.pointerId, { x: t.clientX, y: t.clientY }); try { const e = t.target; e?.setPointerCapture && e.setPointerCapture(t.pointerId); } catch (t) {} try { const o = parseFloat(p.value) || r().zoom || w; if ("mouse" === t.pointerType && 0 === t.button && K.size <= 1 && g && o > 1) { V = !0, Y = t.clientX, q = t.clientY, G = B, W = R; try { g.style.cursor = "grabbing"; } catch (t) { e.logSuppressed(t, "Zoom"); } } } catch (t) { e.logSuppressed(t, "Zoom"); } if (2 === K.size) { const t = Array.from(K.values()); X = et(t[0], t[1]), Q = r().zoom, tt = c.style.touchAction; try { c.style.touchAction = "none"; } catch (t) { e.logSuppressed(t, "Zoom"); } } } catch (t) { e.logSuppressed(t, "Zoom"); } }, ot = t => { try { if (!l) { return; } if (K.has(t.pointerId) && K.set(t.pointerId, { x: t.clientX, y: t.clientY }), V && "mouse" === t.pointerType && g) { return B = G + (t.clientX - Y), R = W + (t.clientY - q), J(), z(g, parseFloat(p.value) || w, B, R), H(), void t.preventDefault(); } if (2 === K.size && X && null != Q) { const e = Array.from(K.values()), o = et(e[0], e[1]); if (o <= 0) { return; } const r = Math.min(x, Math.max(v, Q * (o / X))); A(r), t.preventDefault(); } } catch (t) { e.logSuppressed(t, "Zoom"); } }, rt = t => { try { if (!l) { return; } K.delete(t.pointerId); try { const e = t.target; e?.releasePointerCapture && e.releasePointerCapture(t.pointerId); } catch (t) { e.logSuppressed(t, "Zoom"); } try { if (V && "mouse" === t.pointerType) { V = !1; try { g && (g.style.cursor = parseFloat(p.value) > 1 ? "grab" : ""); } catch (t) { e.logSuppressed(t, "Zoom"); } } } catch (t) { e.logSuppressed(t, "Zoom"); } if (K.size < 2 && (X = null, Q = null, null != tt)) { try { c.style.touchAction = tt; } catch (t) { e.logSuppressed(t, "Zoom"); } tt = null; } } catch (t) { e.logSuppressed(t, "Zoom"); } }; c.addEventListener("pointerdown", nt, { passive: !0 }), c.addEventListener("pointermove", ot, { passive: !1 }), c.addEventListener("pointerup", rt, { passive: !0 }), c.addEventListener("pointercancel", rt, { passive: !0 }); let it = !1, at = 0, st = 0, ct = 0, lt = 0, dt = null, ut = null; const pt = (t, e) => Math.hypot(t.clientX - e.clientX, t.clientY - e.clientY), yt = t => { try { if (!l) { return; } if (!g) { return; } if (1 === t.touches.length) { (parseFloat(p.value) || r().zoom || w) > 1 && (it = !0, at = t.touches[0].clientX, st = t.touches[0].clientY, ct = B, lt = R, t.preventDefault()); } else if (2 === t.touches.length) { dt = pt(t.touches[0], t.touches[1]), ut = parseFloat(p.value) || r().zoom || w; try { tt = c.style.touchAction, c.style.touchAction = "none"; } catch (t) { e.logSuppressed(t, "Zoom"); } t.preventDefault(); } } catch (t) { b?.error?.("Zoom", "touchStart error", t); } }, mt = t => { try { if (!l) { return; } if (!g) { return; } if (1 === t.touches.length && it) { return B = ct + (t.touches[0].clientX - at), R = lt + (t.touches[0].clientY - st), J(), z(g, parseFloat(p.value) || w, B, R), H(), void t.preventDefault(); } if (2 === t.touches.length && dt && null != ut) { const e = pt(t.touches[0], t.touches[1]); if (e <= 0) { return; } const o = Math.min(x, Math.max(v, ut * (e / dt))); A(o), t.preventDefault(); } } catch (t) { b?.error?.("Zoom", "touchMove error", t); } }, ft = t => { try { if (!l) { return; } if (it && 0 === t.touches.length && (it = !1), t.touches.length < 2 && (dt = null, ut = null, null != tt)) { try { c.style.touchAction = tt; } catch (t) { e.logSuppressed(t, "Zoom"); } tt = null; } } catch (t) { b?.error?.("Zoom", "touchEnd error", t); } }; try { c.addEventListener("touchstart", yt, { passive: !1 }), c.addEventListener("touchmove", mt, { passive: !1 }), c.addEventListener("touchend", ft, { passive: !0 }), c.addEventListener("touchcancel", ft, { passive: !0 }); } catch (t) { b?.error?.("Zoom", "Failed to attach touch handlers", t); } const bt = t => { try { if (!l) { return; } if (0 !== t.button || !g) { return; } if ((parseFloat(p.value) || r().zoom || w) <= 1) { return; } V = !0, Y = t.clientX, q = t.clientY, G = B, W = R; try { g.style.cursor = "grabbing"; } catch (t) { e.logSuppressed(t, "Zoom"); } t.preventDefault(); } catch (t) { e.logSuppressed(t, "Zoom"); } }, ht = t => { try { if (!l) { return; } if (!V || !g) { return; } if (B = G + (t.clientX - Y), R = W + (t.clientY - q), J(), g && !g.Tt) { const t = g; t.Tt = requestAnimationFrame(() => { z(t, parseFloat(p.value) || w, B, R), H(), t.Tt = null; }); } t.preventDefault(); } catch (t) { b?.error?.("Zoom", "Mouse move error", t); } }, gt = () => { try { if (!l) { return; } if (V) { V = !1; try { g && (g.style.cursor = parseFloat(p.value) > 1 ? "grab" : ""); } catch (t) { e.logSuppressed(t, "Zoom"); } } } catch (t) { e.logSuppressed(t, "Zoom"); } }; if (g) { try { g.addEventListener("mousedown", bt); } catch (t) { e.logSuppressed(t, "Zoom"); } try { window.addEventListener("mousemove", ht); } catch (t) { e.logSuppressed(t, "Zoom"); } try { window.addEventListener("mouseup", gt); } catch (t) { e.logSuppressed(t, "Zoom"); } try { s(); } catch (t) { e.logSuppressed(t, "Zoom"); } } const wt = () => { try { const t = M(); if (t && t !== g) { try { g && (g.removeEventListener("mousedown", bt), g.removeEventListener("wheel", D), g.Tt && (cancelAnimationFrame(g.Tt), g.Tt = null)); } catch (t) { b?.error?.("Zoom", "Error detaching from old video", t); } g = t; try { s(); } catch (t) { b?.error?.("Zoom", "Error attaching style observer to new video", t); } try { const t = r().zoom || w; J(t), z(g, t, B, R); } catch (t) { b?.error?.("Zoom", "Error applying zoom to new video", t); } try { g.addEventListener("mousedown", bt); } catch (t) { b?.error?.("Zoom", "Error attaching mousedown to new video", t); } try { g.addEventListener("wheel", D, { passive: !1 }); } catch (t) { b?.error?.("Zoom", "Error attaching wheel to new video", t); } } } catch (t) { b?.error?.("Zoom", "Player observer error", t); } }; let vt = !1; try { F?.watchTarget && (F.watchTarget(Z, c, wt, { childList: !0, subtree: !0, attributes: !1 }), vt = !0, e?.ObserverRegistry?.track && e.ObserverRegistry.track()); } catch (t) { b?.error?.("Zoom", "Failed to observe player for video changes", t); } const xt = () => { try { const o = r().zoom || w; t(() => { try { let r = 0; const i = () => { try { const a = M(); let s = !1; if (a && a !== g) { try { g && g.removeEventListener("wheel", D); } catch (t) { e.logSuppressed(t, "Zoom"); } g = a, s = !0; try { g.addEventListener("wheel", D, { passive: !1 }); } catch (t) { e.logSuppressed(t, "Zoom"); } } J(o), g && z(g, o, B, R, !1, !0), s || g && !(r < T) || (r += 1, t(i, L)); } catch (t) { b?.error?.("Zoom", "Fullscreen apply attempt error", t); } }; i(); } catch (t) { b?.error?.("Zoom", "Fullscreen inner apply error", t); } }, S); } catch (t) { b?.error?.("Zoom", "Fullscreen handler error", t); } }; [ "fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange" ].forEach(t => { document.addEventListener(t, xt), e?.cleanupManager?.registerListener && e.cleanupManager.registerListener(document, t, xt); }); try { try { const t = r(); Number.isFinite(t.panX) && (B = t.panX), Number.isFinite(t.panY) && (R = t.panY), J(I); } catch (t) { b?.error?.("Zoom", "Restore pan error", t); } } catch (t) { b?.error?.("Zoom", "Initial zoom setup error", t); } try { const t = `translate(${B.toFixed(2)}px, ${R.toFixed(2)}px) scale(${I.toFixed(3)})`; C = t; } catch (t) { e.logSuppressed(t, "Zoom"); } A(I); const kt = () => { try { const t = c.querySelector(".ytp-chrome-bottom"); u.style.bottom = t?.offsetHeight ? `${t.offsetHeight + 8}px` : ""; } catch (t) {} }; kt(); const St = new ResizeObserver(() => { try { "undefined" != typeof window && "function" == typeof window.requestAnimationFrame ? requestAnimationFrame(() => { try { kt(); } catch (t) { try { e?.logError?.("Enhanced", "updateZoomPosition failed", t instanceof Error ? t : new Error(String(t))); } catch (t) { e.logSuppressed(t, "Zoom"); } } }) : kt(); } catch (t) { try { e?.logError?.("Enhanced", "ResizeObserver callback error", t instanceof Error ? t : new Error(String(t))); } catch (t) { e.logSuppressed(t, "Zoom"); } } }); try { e?.cleanupManager && e.cleanupManager.registerObserver(St); } catch (t) { e.logSuppressed(t, "Zoom"); } try { const t = c.querySelector(".ytp-chrome-bottom"); t && St.observe(t); } catch (t) { try { e?.logError?.("Enhanced", "Failed to observe chrome element", t instanceof Error ? t : new Error(String(t))); } catch (t) { e.logSuppressed(t, "Zoom"); } } try { window.addEventListener("resize", kt, { passive: !0 }), e?.cleanupManager && e.cleanupManager.registerListener(window, "resize", kt); } catch (t) { e.logSuppressed(t, "Zoom"); } [ "fullscreenchange", "webkitfullscreenchange", "mozfullscreenchange", "MSFullscreenChange" ].forEach(t => { try { document.addEventListener(t, kt), e?.cleanupManager && e.cleanupManager.registerListener(document, t, kt); } catch (t) { e.logSuppressed(t, "Zoom"); } }), c.appendChild(u); const Tt = () => { try { if (P && (clearTimeout(P), P = null), j && (clearTimeout(j), j = null), g?.Tt && (cancelAnimationFrame(g.Tt), g.Tt = null), c.removeEventListener("wheel", D), c.removeEventListener("pointerdown", nt), c.removeEventListener("pointermove", ot), c.removeEventListener("pointerup", rt), c.removeEventListener("pointercancel", rt), window.removeEventListener("keydown", O), g) { try { g.removeEventListener("mousedown", bt); } catch (t) { e.logSuppressed(t, "Zoom"); } try { g.removeEventListener("wheel", D); } catch (t) { e.logSuppressed(t, "Zoom"); } try { window.removeEventListener("mousemove", ht); } catch (t) { e.logSuppressed(t, "Zoom"); } try { window.removeEventListener("mouseup", gt); } catch (t) { e.logSuppressed(t, "Zoom"); } try { g.style.cursor = "", g.style.transform = "", g.style.willChange = "auto", g.style.transition = ""; } catch (t) { e.logSuppressed(t, "Zoom"); } } if (N && (F?.unwatch?.(N), N = null), vt) { F?.unwatch?.(Z), vt = !1; try { e?.ObserverRegistry?.untrack?.(); } catch (t) { e.logSuppressed(t, "Zoom"); } } try { document.removeEventListener("fullscreenchange", xt); } catch (t) { e.logSuppressed(t, "Zoom"); } u.remove(); } catch (t) { b?.error?.("Zoom", "Cleanup error", t); } }; return e?.cleanupManager && e.cleanupManager.register(Tt), d = Tt, u; } function c() { try { if (!y()) { return void u(); } const e = () => { if (!y()) { return void u(); } const o = m("#movie_player"); o ? o.closest("ytd-miniplayer") ? u() : s() : t(e, 400); }; if (e(), !_) { _ = !0; const e = () => { try { i(w, 0, 0), u(); } catch {} t(() => { try { y() ? s() : u(); } catch {} }, 300); }; window.addEventListener("yt-navigate-finish", e), window.addEventListener("ytp:nav-refresh", e); } } catch (t) { b?.error?.("Zoom", "initZoom error", t); } } let l = !0, d = null; const u = () => { if (d) { try { d(); } catch (t) {} d = null; } try { const t = f("ytp-zoom-control"); t && t.remove(); } catch (t) { e.logSuppressed(t, "Zoom"); } try { const t = f("ytp-zoom-styles"); t && t.remove(); } catch (t) { e.logSuppressed(t, "Zoom"); } try { const t = M(); t && (t.style.transform = "", t.style.willChange = "", t.style.transition = "", t.style.cursor = ""); } catch (t) { e.logSuppressed(t, "Zoom"); } }, p = t => { if (l = !1 !== t, l) { try { c(); } catch (t) { e.logSuppressed(t, "Zoom"); } } else { u(); } }, y = () => { try { return l && o() && !(() => { try { const t = document.querySelector("ytd-miniplayer[active], ytd-miniplayer[enabled]"); if (t && t instanceof HTMLElement) { if (null !== t.offsetParent) { return !0; } if (t.getClientRects().length > 0) { return !0; } } const e = document.querySelector("ytd-watch-flexy[is-miniplayer], ytd-watch-flexy[miniplayer-is-active]"); return Boolean(e); } catch (t) { return !1; } })(); } catch (t) { return !1; } }; l = e?.loadFeatureEnabled?.("enableZoom") ?? !0; const {$: m, byId: f} = e || {}, b = e?.logger || null, h = "ytp_zoom_pan", g = "ytp_zoom_restore_log", w = 1, v = .5, x = 2.5, k = .05, S = 80, T = 4, L = 120, M = () => { const t = [ "#movie_player video", "video.video-stream", "video" ]; for (const e of t) { const t = m(e); if (t && "VIDEO" === t.tagName) { return t; } } return null; }; let C = "", E = !1; const z = (e, o, r = 0, i = 0, a = !1, s = !1) => { if (!e) { return; } const c = e.parentElement || e; try { if (a || (E = !0), c.style.overflow = "visible", c.style.position && "static" !== c.style.position || (c.style.position = "relative"), e.style.transformOrigin = "center center", 1 === o && 0 === r && 0 === i) { e.style.transform = "", e.style.willChange = "auto", a || (C = ""); } else { const t = `translate(${r.toFixed(2)}px, ${i.toFixed(2)}px) scale(${o.toFixed(3)})`; e.style.transform = t, a || (C = t), e.style.willChange = "transform"; } e.style.transition = s ? "none" : "transform .08s ease-out", a || t(() => { E = !1; }, 100); } catch (t) { b?.error?.("Zoom", "applyZoomToVideo error", t), E = !1; } }; let _ = !1; window.addEventListener("youtube-plus-settings-updated", t => { try { const e = t.detail, o = !1 !== e?.enableZoom; if (o === l) { return; } p(o); } catch (t) { p(e?.loadFeatureEnabled?.("enableZoom") ?? !0); } }); try { c(); } catch (t) { e.logSuppressed(t, "Zoom"); } }; e?.whenRelevant ? e.whenRelevant({ name: "zoom", isRelevant: o, onEnter: r }) : r(); })(), (function() { function t(t) { const e = R(), o = F(); if (!(e instanceof HTMLElement && o instanceof HTMLElement)) { return; } const r = o.getBoundingClientRect(), i = Math.min(440, Math.floor(.34 * window.innerWidth)), a = 12; !(function(t) { const e = R(); e instanceof HTMLElement && ((function() { if (null !== B) { return; } const t = R(); if (!(t instanceof HTMLElement)) { return; } const e = parseFloat(window.getComputedStyle(t).marginLeft || "0"); B = Number.isFinite(e) ? e : 0; })(), e.style.marginLeft = `${Math.round((B || 0) + t)}px`); })(window.innerWidth - r.right >= i + a ? -Math.round((i + a) / 2) : Math.round((i + a) / 2)); const s = F(); if (!(s instanceof HTMLElement)) { return; } const c = s.getBoundingClientRect(), l = window.innerWidth - c.right; let d = c.right + a; l < i + a && (d = Math.max(8, c.left - i - a)), t.style.left = `${Math.max(8, d)}px`, t.style.top = `${Math.max(8, c.top)}px`, t.style.height = `${Math.max(260, c.height)}px`; } function e() { const t = R(); t instanceof HTMLElement ? (null !== B ? t.style.marginLeft = `${Math.round(B)}px` : t.style.removeProperty("margin-left"), B = null) : B = null; } function o(t, e) { t && t.querySelectorAll(".ytp-plus-vote-btn, .ytp-plus-vote-bar-btn").forEach(t => { e ? (t.setAttribute("aria-disabled", "true"), t.style.pointerEvents = "none", t.style.opacity = "0.7") : (t.removeAttribute("aria-disabled"), t.style.pointerEvents = "", t.style.opacity = ""); }); } function r() { let t = localStorage.getItem("ytp_voting_user_id"); if (!t) { const e = new Uint8Array(16); void 0 !== globalThis.crypto && globalThis.crypto.getRandomValues ? globalThis.crypto.getRandomValues(e) : e.forEach((t, e, o) => { o[e] = 256 * Math.random() | 0; }), t = `user_${Array.from(e, t => t.toString(16).padStart(2, "0")).join("")}_${Date.now().toString(36)}`, localStorage.setItem("ytp_voting_user_id", t); } return t; } function i(t) { const e = Number(t); return 1 === e ? 1 : -1 === e ? -1 : 0; } async function a(t, e = {}) { const o = `https://ldpccocxlrdsyejfhrvc.supabase.co/rest/v1/${t}`, r = { apikey: A, Authorization: `Bearer ${A}`, "Content-Type": "application/json", Prefer: e.prefer || "return=representation" }; try { const t = await fetch(o, { ...e, headers: { ...r, ...e.headers } }); if (!t.ok) { const e = await t.json().catch(() => ({})); throw new Error(e.message || `HTTP ${t.status}`); } return { data: await t.json().catch(() => null), error: null }; } catch (t) { return { data: null, error: t instanceof Error ? t.message : String(t) }; } } async function s() { const {data: t, error: e} = await a("ytplus_feature_requests?select=*&order=created_at.desc"); return e ? (window.YouTubePlusLogger?.error?.("Voting", "Error fetching features:", e), []) : t || []; } async function c() { const {data: t, error: e} = await a("ytplus_feature_votes?select=feature_id,vote_type,ip_address"); if (e) { return window.YouTubePlusLogger?.error?.("Voting", "Error fetching votes:", e), {}; } const o = {}; return (t || []).forEach(t => { o[t.feature_id] || (o[t.feature_id] = { upvotes: 0, downvotes: 0 }); const e = i(t.vote_type); 1 === e ? o[t.feature_id].upvotes++ : -1 === e && o[t.feature_id].downvotes++; }), o; } async function l() { const t = r(), {data: e, error: o} = await a(`ytplus_feature_votes?select=feature_id,vote_type&ip_address=eq.${t}`); if (o) { return window.YouTubePlusLogger?.error?.("Voting", "Error fetching user votes:", o), {}; } const s = {}; return (e || []).forEach(t => { const e = i(t.vote_type); e && (s[t.feature_id] = e); }), s; } async function d(t, e) { const o = r(), {data: i} = await a(`ytplus_feature_votes?feature_id=eq.${t}&ip_address=eq.${o}&select=id`); if (i && i.length > 0) { const t = i[0]; return 0 === e ? (await a(`ytplus_feature_votes?id=eq.${t.id}`, { method: "DELETE" }), { success: !0, action: "removed" }) : (await a(`ytplus_feature_votes?id=eq.${t.id}`, { method: "PATCH", body: JSON.stringify({ vote_type: e }) }), { success: !0, action: "updated" }); } if (0 === e) { return { success: !0, action: "none" }; } const {error: s} = await a("ytplus_feature_votes", { method: "POST", body: JSON.stringify({ feature_id: t, vote_type: e, ip_address: o }) }); return s ? (window.YouTubePlusLogger?.error?.("Voting", "Vote error:", s), { success: !1, error: s }) : { success: !0, action: "added" }; } async function u(t, e) { const o = t => V(t).toLocaleLowerCase(); if (t = V(t).slice(0, 200), e = V(e).slice(0, 2e3), !t) { return { success: !1, error: "Title is required" }; } if (o(t) === P.toLocaleLowerCase()) { return { success: !1, error: "This title is reserved" }; } const i = await s(), c = o(t); if ((i || []).find(t => o(String(t?.title || "")) === c)) { return { success: !1, error: "Feature already exists" }; } const l = r(), {error: d} = await a("ytplus_feature_requests", { method: "POST", body: JSON.stringify({ title: t, description: e, author_ip: l }) }); return d ? (window.YouTubePlusLogger?.error?.("Voting", "Submit error:", d), { success: !1, error: d }) : { success: !0 }; } async function p(t) { const e = (t || []).filter(Boolean); if (0 === e.length) { return {}; } const o = e.join(","), {data: r, error: i} = await a(`ytplus_feature_comments?select=id,feature_id,comment,author_ip,created_at&feature_id=in.(${o})&order=created_at.asc`); if (i) { return window.YouTubePlusLogger?.error?.("Voting", "Error fetching comments:", i), {}; } const s = {}; return (r || []).forEach(t => { const e = String(t?.feature_id || ""); e && (s[e] || (s[e] = []), s[e].push(t)); }), s; } function y(t) { return String(t?.title || "").trim() === P; } function m(t) { return V(String(t?.title || "")); } async function f(t) { const e = Array.isArray(t) ? t.find(y) : null; if (e) { return e; } const o = r(), {data: i, error: c} = await a("ytplus_feature_requests", { method: "POST", body: JSON.stringify({ title: P, description: "Internal row for ytp-plus-voting-preview", status: "proposed", author_ip: o }) }); if (c) { window.YouTubePlusLogger?.error?.("Voting", "Error creating preview row:", c); const t = encodeURIComponent(P), {data: e} = await a(`ytplus_feature_requests?select=id,title,description,status&title=eq.${t}&limit=1`); return Array.isArray(e) && e[0] ? e[0] : null; } return Array.isArray(i) && i[0] ? i[0] : (await s()).find(y) || null; } function b() { if (C("ytp-plus-comments-panel")) { return !0; } if (!document.body || !document.head) { return !1; } const o = document.createElement("div"); if (o.id = "ytp-plus-comments-panel", o.className = "ytp-plus-comments-sidepanel", I(o, `\n <div class="ytp-plus-comments-header">\n <div class="ytp-plus-comments-title" id="ytp-plus-comments-title">${Z("comments", "Comments")}</div>\n <button class="ytp-plus-comments-close" data-comments-close="1" type="button">×</button>\n </div>\n <div class="ytp-plus-comments-list" id="ytp-plus-comments-list"></div>\n <div class="ytp-plus-comments-form">\n <textarea id="ytp-plus-comments-input" maxlength="1000" placeholder="${Z("addCommentPlaceholder", "Add a comment...")}"></textarea>\n <button id="ytp-plus-comments-submit" type="button">${Z("submit", "Submit")}</button>\n </div>\n `), document.body.appendChild(o), !C("ytp-plus-comments-modal-style")) { const t = document.createElement("style"); t.id = "ytp-plus-comments-modal-style", t.textContent = "\n .ytp-plus-comments-sidepanel{position:fixed;top:10vh;left:calc(50% + 390px);width:min(440px,34vw);max-width:92vw;height:60vh;background:var(--yt-glass-bg);border:1.5px solid var(--yt-glass-border);border-radius:24px;display:none;z-index:100001;box-shadow:0 12px 40px var(--yt-timecode-panel-shadow);overflow:hidden;backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%);contain:layout style paint;font-family:system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}\n .ytp-plus-comments-sidepanel.open{display:flex;flex-direction:column}\n .ytp-plus-comments-header{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid var(--yt-stats-card-border-dark)}\n .ytp-plus-comments-title{font-size:16px;font-weight:500;color:var(--yt-text-primary);font-family:inherit;text-wrap:balance;}\n .ytp-plus-comments-close{border:0;background:transparent;color:var(--yt-text-secondary);font-size:24px;cursor:pointer;line-height:1;transition:color .2s cubic-bezier(0.2,0,0,1),transform .1s cubic-bezier(0.2,0,0,1);}\n .ytp-plus-comments-close:active{transform:scale(0.96) !important;}\n .ytp-plus-comments-list{flex:1;overflow:auto;padding:12px 16px;display:flex;flex-direction:column;gap:10px}\n .ytp-plus-comments-item{border:1px solid var(--yt-stats-card-border-dark);background:var(--yt-surface-overlay-faint);border-radius:10px;padding:10px}\n .ytp-plus-comments-item-text{color:var(--yt-text-primary);white-space:pre-wrap;word-break:break-word;font-size:small;text-wrap:pretty;}\n .ytp-plus-comments-item-meta{margin-top:6px;color:var(--yt-text-secondary);font-size:12px}\n .ytp-plus-comments-form{padding:12px 16px;border-top:1px solid var(--yt-stats-card-border-dark);display:flex;gap:8px;align-items:center}\n #ytp-plus-comments-input{flex:1;min-height:15px;max-height:160px;resize:vertical;background:var(--yt-glass-bg);color:var(--yt-text-primary);border:1px solid var(--yt-glass-border);border-radius:10px;padding:10px}\n #ytp-plus-comments-submit{border:1px solid var(--yt-glass-border);background:var(--yt-accent);color:var(--yt-text-primary);border-radius:10px;padding:10px 14px;cursor:pointer;transition:background-color .2s cubic-bezier(0.2,0,0,1),border-color .2s cubic-bezier(0.2,0,0,1),transform .1s cubic-bezier(0.2,0,0,1),box-shadow .2s cubic-bezier(0.2,0,0,1);}\n #ytp-plus-comments-submit:active{transform:scale(0.96) !important;}\n .ytp-plus-voting-item-status-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px}\n .ytp-plus-voting-comments-icon{border:1px solid var(--yt-glass-border);background:var(--yt-button-bg);color:var(--yt-text-secondary);border-radius:999px;min-width:28px;height:28px;padding:0 10px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;line-height:1;transition:background-color .2s cubic-bezier(0.2,0,0,1),color .2s cubic-bezier(0.2,0,0,1),border-color .2s cubic-bezier(0.2,0,0,1),transform .1s cubic-bezier(0.2,0,0,1)}\n .ytp-plus-voting-comments-icon:hover{background:var(--yt-hover-bg);color:var(--yt-text-primary)}\n .ytp-plus-voting-comments-icon:active{transform:scale(0.96) !important;}\n .ytp-plus-voting-comments-icon svg{width:14px;height:14px;display:block;fill:currentColor}\n .ytp-plus-comments-sidepanel textarea,\n .ytp-plus-comments-sidepanel button,\n .ytp-plus-comments-sidepanel .ytp-plus-comments-item,\n .ytp-plus-comments-sidepanel .ytp-plus-comments-item-text,\n .ytp-plus-comments-sidepanel .ytp-plus-comments-item-meta,\n .ytp-plus-comments-sidepanel .ytp-plus-voting-empty{font-family:inherit}\n ", document.head.appendChild(t); } const r = () => { const e = C("ytp-plus-comments-panel"); e instanceof HTMLElement && e.classList.contains("open") && t(e); }; T?.cleanupManager ? (T.cleanupManager.registerListener(window, "resize", r), T.cleanupManager.registerListener(window, "scroll", r, !0)) : (window.addEventListener("resize", r), window.addEventListener("scroll", r, !0)), o.dataset.repositionBound = "1"; const i = () => { h(), e(); }; return T?.cleanupManager ? T.cleanupManager.registerListener(document, "youtube-plus-settings-modal-closed", i) : document.addEventListener("youtube-plus-settings-modal-closed", i), !0; } function h() { const t = C("ytp-plus-comments-panel"); t && t.classList.remove("open"), e(); } function g(e) { if (!b()) { return; } const o = C("ytp-plus-comments-panel"), r = C("ytp-plus-comments-title"), i = C("ytp-plus-comments-list"), a = C("ytp-plus-comments-input"), s = C("ytp-plus-comments-submit"); if (!(o && r && i && a && s)) { return; } const c = O[e], l = D[e] || []; o.setAttribute("data-feature-id", e), r.textContent = String(c?.title || "").trim() || Z("comments", "Comments"), I(i, l.length ? l.map(t => `\n <div class="ytp-plus-comments-item">\n <div class="ytp-plus-comments-item-text">${v(String(t.comment || ""))}</div>\n <div class="ytp-plus-comments-item-meta">${v((function(t) { try { const e = new Date(t); return Number.isNaN(e.getTime()) ? "" : e.toLocaleString(); } catch (t) { return ""; } })(String(t.created_at || "")))}</div>\n </div>\n `).join("") : '<div class="ytp-plus-voting-empty">No comments yet</div>'), a.value = "", s.disabled = !1, o.classList.add("open"), o instanceof HTMLElement && t(o); } async function w() { const t = C("ytp-plus-voting-list"); if (!t) { return; } const e = await s(), r = await f(e), i = new Set, a = (e || []).filter(t => { if (!(function(t) { const e = m(t); return Boolean(e) && e !== P; })(t) || y(t)) { return !1; } const e = m(t).toLocaleLowerCase(); return !(!e || i.has(e) || (i.add(e), 0)); }), [u, b, h] = await Promise.all([ c(), l(), p(a.map(t => String(t.id || ""))) ]), g = [ ...a ]; if (D = h, O = {}, g.forEach(t => { O[String(t.id || "")] = t; }), 0 === g.length) { return L(t, `<div class="ytp-plus-voting-empty">${Z("noFeatures", "No feature requests yet")}</div>`), void x(u, b, r?.id || null); } I(t, g.map(t => { const e = u[t.id] || { upvotes: 0, downvotes: 0 }, o = b[t.id] || 0, r = h[t.id] || [], i = e.upvotes + e.downvotes, a = i > 0 ? Math.round(e.upvotes / i * 100) : 50, s = (function(t) { const e = String(t || "").toLowerCase(); return "completed" === e ? { className: "completed", label: Z("statusCompleted", "Completed") } : "in_progress" === e ? { className: "in-progress", label: Z("statusInProgress", "In progress") } : { className: "proposed", label: Z("statusProposed", "Proposed") }; })(t.status), c = m(t), l = (d = t, V(String(d?.description || ""))); var d; return `\n <div class="ytp-plus-voting-item" data-feature-id="${t.id}">\n <div class="ytp-plus-voting-item-content">\n <div class="ytp-plus-voting-item-title">${v(c)}</div>\n <div class="ytp-plus-voting-item-desc">${v(l)}</div>\n <div class="ytp-plus-voting-item-status-row">\n <div class="ytp-plus-voting-item-status ${s.className}">${v(s.label)}</div>\n <button class="ytp-plus-voting-comments-icon" data-comments-open="1" type="button" title="${Z("comments", "Comments")} (${r.length})" aria-label="${Z("comments", "Comments")} (${r.length})"><svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"> <path opacity="0.5" d="M13.0867 21.3877L13.7321 21.7697L13.0867 21.3877ZM13.6288 20.4718L12.9833 20.0898L13.6288 20.4718ZM10.3712 20.4718L9.72579 20.8539H9.72579L10.3712 20.4718ZM10.9133 21.3877L11.5587 21.0057L10.9133 21.3877ZM13.5 2.75C13.9142 2.75 14.25 2.41421 14.25 2C14.25 1.58579 13.9142 1.25 13.5 1.25V2.75ZM22.75 10.5C22.75 10.0858 22.4142 9.75 22 9.75C21.5858 9.75 21.25 10.0858 21.25 10.5H22.75ZM2.3806 15.9134L3.07351 15.6264V15.6264L2.3806 15.9134ZM7.78958 18.9915L7.77666 19.7413L7.78958 18.9915ZM5.08658 18.6194L4.79957 19.3123H4.79957L5.08658 18.6194ZM21.6194 15.9134L22.3123 16.2004V16.2004L21.6194 15.9134ZM16.2104 18.9915L16.1975 18.2416L16.2104 18.9915ZM18.9134 18.6194L19.2004 19.3123H19.2004L18.9134 18.6194ZM4.38751 2.7368L3.99563 2.09732V2.09732L4.38751 2.7368ZM2.7368 4.38751L2.09732 3.99563H2.09732L2.7368 4.38751ZM9.40279 19.2098L9.77986 18.5615L9.77986 18.5615L9.40279 19.2098ZM13.7321 21.7697L14.2742 20.8539L12.9833 20.0898L12.4412 21.0057L13.7321 21.7697ZM9.72579 20.8539L10.2679 21.7697L11.5587 21.0057L11.0166 20.0898L9.72579 20.8539ZM12.4412 21.0057C12.2485 21.3313 11.7515 21.3313 11.5587 21.0057L10.2679 21.7697C11.0415 23.0767 12.9585 23.0767 13.7321 21.7697L12.4412 21.0057ZM10.5 2.75H13.5V1.25H10.5V2.75ZM21.25 10.5V11.5H22.75V10.5H21.25ZM2.75 11.5V10.5H1.25V11.5H2.75ZM1.25 11.5C1.25 12.6546 1.24959 13.5581 1.29931 14.2868C1.3495 15.0223 1.45323 15.6344 1.68769 16.2004L3.07351 15.6264C2.92737 15.2736 2.84081 14.8438 2.79584 14.1847C2.75041 13.5189 2.75 12.6751 2.75 11.5H1.25ZM7.8025 18.2416C6.54706 18.2199 5.88923 18.1401 5.37359 17.9265L4.79957 19.3123C5.60454 19.6457 6.52138 19.7197 7.77666 19.7413L7.8025 18.2416ZM1.68769 16.2004C2.27128 17.6093 3.39066 18.7287 4.79957 19.3123L5.3736 17.9265C4.33223 17.4951 3.50486 16.6678 3.07351 15.6264L1.68769 16.2004ZM21.25 11.5C21.25 12.6751 21.2496 13.5189 21.2042 14.1847C21.1592 14.8438 21.0726 15.2736 20.9265 15.6264L22.3123 16.2004C22.5468 15.6344 22.6505 15.0223 22.7007 14.2868C22.7504 13.5581 22.75 12.6546 22.75 11.5H21.25ZM16.2233 19.7413C17.4786 19.7197 18.3955 19.6457 19.2004 19.3123L18.6264 17.9265C18.1108 18.1401 17.4529 18.2199 16.1975 18.2416L16.2233 19.7413ZM20.9265 15.6264C20.4951 16.6678 19.6678 17.4951 18.6264 17.9265L19.2004 19.3123C20.6093 18.7287 21.7287 17.6093 22.3123 16.2004L20.9265 15.6264ZM10.5 1.25C8.87781 1.25 7.6085 1.24921 6.59611 1.34547C5.57256 1.44279 4.73445 1.64457 3.99563 2.09732L4.77938 3.37628C5.24291 3.09223 5.82434 2.92561 6.73809 2.83873C7.663 2.75079 8.84876 2.75 10.5 2.75V1.25ZM2.75 10.5C2.75 8.84876 2.75079 7.663 2.83873 6.73809C2.92561 5.82434 3.09223 5.24291 3.37628 4.77938L2.09732 3.99563C1.64457 4.73445 1.44279 5.57256 1.34547 6.59611C1.24921 7.6085 1.25 8.87781 1.25 10.5H2.75ZM3.99563 2.09732C3.22194 2.57144 2.57144 3.22194 2.09732 3.99563L3.37628 4.77938C3.72672 4.20752 4.20752 3.72672 4.77938 3.37628L3.99563 2.09732ZM11.0166 20.0898C10.8136 19.7468 10.6354 19.4441 10.4621 19.2063C10.2795 18.9559 10.0702 18.7304 9.77986 18.5615L9.02572 19.8582C9.07313 19.8857 9.13772 19.936 9.24985 20.0898C9.37122 20.2564 9.50835 20.4865 9.72579 20.8539L11.0166 20.0898ZM7.77666 19.7413C8.21575 19.7489 8.49387 19.7545 8.70588 19.7779C8.90399 19.7999 8.98078 19.832 9.02572 19.8582L9.77986 18.5615C9.4871 18.3912 9.18246 18.3215 8.87097 18.287C8.57339 18.2541 8.21375 18.2487 7.8025 18.2416L7.77666 19.7413ZM14.2742 20.8539C14.4916 20.4865 14.6287 20.2564 14.7501 20.0898C14.8622 19.936 14.9268 19.8857 14.9742 19.8582L14.2201 18.5615C13.9298 18.7304 13.7204 18.9559 13.5379 19.2063C13.3646 19.4441 13.1864 19.7468 12.9833 20.0898L14.2742 20.8539ZM16.1975 18.2416C15.7862 18.2487 15.4266 18.2541 15.129 18.287C14.8175 18.3215 14.5129 18.3912 14.2201 18.5615L14.9742 19.8582C15.0192 19.832 15.096 19.7999 15.2941 19.7779C15.5061 19.7545 15.7842 19.7489 16.2233 19.7413L16.1975 18.2416Z" fill="currentColor"></path> <circle cx="19" cy="5" r="3" stroke="currentColor" stroke-width="1.5"></circle> </svg></button>\n </div>\n </div>\n <div class="ytp-plus-voting-item-votes">\n <div class="ytp-plus-voting-score">\n <span class="ytp-plus-vote-total">${i} ${Z("votes", "votes")}</span>\n </div>\n <div class="ytp-plus-voting-buttons">\n <div class="ytp-plus-voting-buttons-track" style="background:linear-gradient(to right, var(--yt-success) ${a}%, var(--yt-danger) ${a}%);"></div>\n <button class="ytp-plus-vote-btn ${1 === o ? "active" : ""}" data-vote="1" title="${Z("like", "Like")}" type="button" aria-label="${Z("like", "Like")}">\n <svg class="ytp-plus-vote-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20.9751 12.1852L20.2361 12.0574L20.9751 12.1852ZM20.2696 16.265L19.5306 16.1371L20.2696 16.265ZM6.93776 20.4771L6.19055 20.5417H6.19055L6.93776 20.4771ZM6.1256 11.0844L6.87281 11.0198L6.1256 11.0844ZM13.9949 5.22142L14.7351 5.34269V5.34269L13.9949 5.22142ZM13.3323 9.26598L14.0724 9.38725V9.38725L13.3323 9.26598ZM6.69813 9.67749L6.20854 9.10933H6.20854L6.69813 9.67749ZM8.13687 8.43769L8.62646 9.00585H8.62646L8.13687 8.43769ZM10.518 4.78374L9.79207 4.59542L10.518 4.78374ZM10.9938 2.94989L11.7197 3.13821L11.7197 3.13821L10.9938 2.94989ZM12.6676 2.06435L12.4382 2.77841L12.4382 2.77841L12.6676 2.06435ZM12.8126 2.11093L13.0419 1.39687L13.0419 1.39687L12.8126 2.11093ZM9.86194 6.46262L10.5235 6.81599V6.81599L9.86194 6.46262ZM13.9047 3.24752L13.1787 3.43584V3.43584L13.9047 3.24752ZM11.6742 2.13239L11.3486 1.45675L11.3486 1.45675L11.6742 2.13239ZM20.2361 12.0574L19.5306 16.1371L21.0086 16.3928L21.7142 12.313L20.2361 12.0574ZM13.245 21.25H8.59634V22.75H13.245V21.25ZM7.68497 20.4125L6.87281 11.0198L5.37839 11.149L6.19055 20.5417L7.68497 20.4125ZM19.5306 16.1371C19.0238 19.0677 16.3813 21.25 13.245 21.25V22.75C17.0712 22.75 20.3708 20.081 21.0086 16.3928L19.5306 16.1371ZM13.2548 5.10015L12.5921 9.14472L14.0724 9.38725L14.7351 5.34269L13.2548 5.10015ZM7.18772 10.2456L8.62646 9.00585L7.64728 7.86954L6.20854 9.10933L7.18772 10.2456ZM11.244 4.97206L11.7197 3.13821L10.2678 2.76157L9.79207 4.59542L11.244 4.97206ZM12.4382 2.77841L12.5832 2.82498L13.0419 1.39687L12.897 1.3503L12.4382 2.77841ZM10.5235 6.81599C10.8354 6.23198 11.0777 5.61339 11.244 4.97206L9.79207 4.59542C9.65572 5.12107 9.45698 5.62893 9.20041 6.10924L10.5235 6.81599ZM12.5832 2.82498C12.8896 2.92342 13.1072 3.16009 13.1787 3.43584L14.6306 3.05921C14.4252 2.26719 13.819 1.64648 13.0419 1.39687L12.5832 2.82498ZM11.7197 3.13821C11.7547 3.0032 11.8522 2.87913 11.9998 2.80804L11.3486 1.45675C10.8166 1.71309 10.417 2.18627 10.2678 2.76157L11.7197 3.13821ZM11.9998 2.80804C12.1345 2.74311 12.2931 2.73181 12.4382 2.77841L12.897 1.3503C12.3872 1.18655 11.8312 1.2242 11.3486 1.45675L11.9998 2.80804ZM14.1537 10.9842H19.3348V9.4842H14.1537V10.9842ZM14.7351 5.34269C14.8596 4.58256 14.824 3.80477 14.6306 3.0592L13.1787 3.43584C13.3197 3.97923 13.3456 4.54613 13.2548 5.10016L14.7351 5.34269ZM8.59634 21.25C8.12243 21.25 7.726 20.887 7.68497 20.4125L6.19055 20.5417C6.29851 21.7902 7.34269 22.75 8.59634 22.75V21.25ZM8.62646 9.00585C9.30632 8.42 10.0391 7.72267 10.5235 6.81599L9.20041 6.10924C8.85403 6.75767 8.30249 7.30493 7.64728 7.86954L8.62646 9.00585ZM21.7142 12.313C21.9695 10.8365 20.8341 9.4842 19.3348 9.4842V10.9842C19.9014 10.9842 20.3332 11.4959 20.2361 12.0574L21.7142 12.313ZM12.5921 9.14471C12.4344 10.1076 13.1766 10.9842 14.1537 10.9842V9.4842C14.1038 9.4842 14.0639 9.43901 14.0724 9.38725L12.5921 9.14471ZM6.87281 11.0198C6.84739 10.7258 6.96474 10.4378 7.18772 10.2456L6.20854 9.10933C5.62021 9.61631 5.31148 10.3753 5.37839 11.149L6.87281 11.0198Z" fill="currentColor"></path> <path opacity="0.5" d="M3.9716 21.4709L3.22439 21.5355L3.9716 21.4709ZM3 10.2344L3.74721 10.1698C3.71261 9.76962 3.36893 9.46776 2.96767 9.48507C2.5664 9.50239 2.25 9.83274 2.25 10.2344L3 10.2344ZM4.71881 21.4063L3.74721 10.1698L2.25279 10.299L3.22439 21.5355L4.71881 21.4063ZM3.75 21.5129V10.2344H2.25V21.5129H3.75ZM3.22439 21.5355C3.2112 21.383 3.33146 21.2502 3.48671 21.2502V22.7502C4.21268 22.7502 4.78122 22.1281 4.71881 21.4063L3.22439 21.5355ZM3.48671 21.2502C3.63292 21.2502 3.75 21.3686 3.75 21.5129H2.25C2.25 22.1954 2.80289 22.7502 3.48671 22.7502V21.2502Z" fill="currentColor"></path> </svg>\n </button>\n <button class="ytp-plus-vote-btn ${-1 === o ? "active" : ""}" data-vote="-1" title="${Z("dislike", "Dislike")}" type="button" aria-label="${Z("dislike", "Dislike")}">\n <svg class="ytp-plus-vote-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20.9751 11.8148L20.2361 11.9426L20.9751 11.8148ZM20.2696 7.73505L19.5306 7.86285L20.2696 7.73505ZM6.93776 3.52293L6.19055 3.45832H6.19055L6.93776 3.52293ZM6.1256 12.9156L6.87281 12.9802L6.1256 12.9156ZM13.9949 18.7786L14.7351 18.6573V18.6573L13.9949 18.7786ZM13.3323 14.734L14.0724 14.6128V14.6128L13.3323 14.734ZM6.69813 14.3225L6.20854 14.8907H6.20854L6.69813 14.3225ZM8.13687 15.5623L8.62646 14.9942H8.62646L8.13687 15.5623ZM10.518 19.2163L9.79207 19.4046L10.518 19.2163ZM10.9938 21.0501L11.7197 20.8618L11.7197 20.8618L10.9938 21.0501ZM12.6676 21.9356L12.4382 21.2216L12.4382 21.2216L12.6676 21.9356ZM12.8126 21.8891L13.0419 22.6031L13.0419 22.6031L12.8126 21.8891ZM9.86194 17.5374L10.5235 17.184V17.184L9.86194 17.5374ZM13.9047 20.7525L13.1787 20.5642V20.5642L13.9047 20.7525ZM11.6742 21.8676L11.3486 22.5433L11.3486 22.5433L11.6742 21.8676ZM20.2361 11.9426L19.5306 7.86285L21.0086 7.60724L21.7142 11.687L20.2361 11.9426ZM13.245 2.75H8.59634V1.25H13.245V2.75ZM7.68497 3.58754L6.87281 12.9802L5.37839 12.851L6.19055 3.45832L7.68497 3.58754ZM19.5306 7.86285C19.0238 4.93226 16.3813 2.75 13.245 2.75V1.25C17.0712 1.25 20.3708 3.91895 21.0086 7.60724L19.5306 7.86285ZM13.2548 18.8998L12.5921 14.8553L14.0724 14.6128L14.7351 18.6573L13.2548 18.8998ZM7.18772 13.7544L8.62646 14.9942L7.64728 16.1305L6.20854 14.8907L7.18772 13.7544ZM11.244 19.0279L11.7197 20.8618L10.2678 21.2384L9.79207 19.4046L11.244 19.0279ZM12.4382 21.2216L12.5832 21.175L13.0419 22.6031L12.897 22.6497L12.4382 21.2216ZM10.5235 17.184C10.8354 17.768 11.0777 18.3866 11.244 19.0279L9.79207 19.4046C9.65572 18.8789 9.45698 18.3711 9.20041 17.8908L10.5235 17.184ZM12.5832 21.175C12.8896 21.0766 13.1072 20.8399 13.1787 20.5642L14.6306 20.9408C14.4252 21.7328 13.819 22.3535 13.0419 22.6031L12.5832 21.175ZM11.7197 20.8618C11.7547 20.9968 11.8522 21.1209 11.9998 21.192L11.3486 22.5433C10.8166 22.2869 10.417 21.8137 10.2678 21.2384L11.7197 20.8618ZM11.9998 21.192C12.1345 21.2569 12.2931 21.2682 12.4382 21.2216L12.897 22.6497C12.3872 22.8135 11.8312 22.7758 11.3486 22.5433L11.9998 21.192ZM14.1537 13.0158H19.3348V14.5158H14.1537V13.0158ZM14.7351 18.6573C14.8596 19.4174 14.824 20.1952 14.6306 20.9408L13.1787 20.5642C13.3197 20.0208 13.3456 19.4539 13.2548 18.8998L14.7351 18.6573ZM8.59634 2.75C8.12243 2.75 7.726 3.11302 7.68497 3.58754L6.19055 3.45832C6.29851 2.20975 7.34269 1.25 8.59634 1.25V2.75ZM8.62646 14.9942C9.30632 15.58 10.0391 16.2773 10.5235 17.184L9.20041 17.8908C8.85403 17.2423 8.30249 16.6951 7.64728 16.1305L8.62646 14.9942ZM21.7142 11.687C21.9695 13.1635 20.8341 14.5158 19.3348 14.5158V13.0158C19.9014 13.0158 20.3332 12.5041 20.2361 11.9426L21.7142 11.687ZM12.5921 14.8553C12.4344 13.8924 13.1766 13.0158 14.1537 13.0158V14.5158C14.1038 14.5158 14.0639 14.561 14.0724 14.6128L12.5921 14.8553ZM6.87281 12.9802C6.84739 13.2742 6.96474 13.5622 7.18772 13.7544L6.20854 14.8907C5.62021 14.3837 5.31148 13.6247 5.37839 12.851L6.87281 12.9802Z" fill="currentColor"></path> <path opacity="0.5" d="M3.9716 2.52911L3.22439 2.4645L3.9716 2.52911ZM3 13.7656L3.74721 13.8302C3.71261 14.2304 3.36893 14.5322 2.96767 14.5149C2.5664 14.4976 2.25 14.1673 2.25 13.7656L3 13.7656ZM4.71881 2.59372L3.74721 13.8302L2.25279 13.701L3.22439 2.4645L4.71881 2.59372ZM3.75 2.48709V13.7656H2.25V2.48709H3.75ZM3.22439 2.4645C3.2112 2.61704 3.33146 2.74983 3.48671 2.74983V1.24983C4.21268 1.24983 4.78122 1.87192 4.71881 2.59372L3.22439 2.4645ZM3.48671 2.74983C3.63292 2.74983 3.75 2.63139 3.75 2.48709H2.25C2.25 1.80457 2.80289 1.24983 3.48671 1.24983V2.74983Z" fill="currentColor"></path> </svg>\n </button>\n </div>\n </div>\n </div>\n `; }).join("")), t.querySelectorAll(".ytp-plus-vote-btn").forEach(e => { e.addEventListener("click", async () => { if (H) { return; } const r = e.closest(".ytp-plus-voting-item"), i = r?.dataset?.featureId, a = parseInt(e.dataset?.vote || "0", 10); if (!i) { return; } let s = a; (b[i] || 0) === a && (s = 0); try { H = !0, o(t.closest(".ytp-plus-settings-section, .ytp-plus-voting") || t, !0), (await d(i, s)).success && await w(); } finally { H = !1, o(t.closest(".ytp-plus-settings-section, .ytp-plus-voting") || t, !1); } }); }), x(u, b, r?.id || null); } function v(t) { if (!t) { return ""; } if (window.YouTubeSafeDOM?.escapeHTML) { return window.YouTubeSafeDOM.escapeHTML(t); } if (window.YouTubeSecurityUtils?.escapeHtml) { return window.YouTubeSecurityUtils.escapeHtml(t); } const e = document.createElement("div"); return e.textContent = t, e.innerHTML; } function x(t, e, o) { const r = C("ytp-plus-vote-bar-fill"), i = C("ytp-plus-vote-bar-count"), a = C("ytp-plus-vote-bar-up"), s = C("ytp-plus-vote-bar-down"); if (!r || !i) { return; } const c = o && t[o] || { upvotes: 0, downvotes: 0 }, l = c.upvotes || 0, d = l + (c.downvotes || 0), u = d > 0 ? Math.round(l / d * 100) : 50; r.style.background = `linear-gradient(to right, var(--yt-success) ${u}%, var(--yt-danger) ${u}%)`, i.textContent = d > 0 ? `${d}` : "0"; const p = o && e[o] || 0; a && a.classList.toggle("active", 1 === p), s && s.classList.toggle("active", -1 === p); } function k(t = !1) { if (!t && !z()) { return; } if (j) { return; } if (j = !0, !b()) { const t = () => { b(); }; "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", t, { once: !0 }) : S(t, 0); } const e = async t => { const e = t.target?.closest?.(".ytp-plus-vote-bar-btn"); if (e) { if (H) { return; } const t = await s(), r = await f(t); if (!r?.id) { return; } const i = await l(), a = parseInt(e.dataset.vote, 10), c = (i[r.id] || 0) === a ? 0 : a, u = e.closest(".ytp-plus-settings-section, .ytp-plus-voting") || document.body; try { H = !0, o(u, !0), await d(r.id, c), await w(); } finally { H = !1, o(u, !1); } } }, i = t => { const e = t.target?.closest?.("#ytp-plus-show-add-feature"), o = t.target?.closest?.("#ytp-plus-cancel-feature"), r = t.target?.closest?.("#ytp-plus-submit-feature"); if (e) { const t = C("ytp-plus-voting-add-form"), e = C("ytp-plus-show-add-feature"); t && (t.style.display = "block"), e && (e.style.display = "none"); } if (o) { const t = C("ytp-plus-voting-add-form"), e = C("ytp-plus-show-add-feature"), o = C("ytp-plus-feature-title"), r = C("ytp-plus-feature-desc"); t && (t.style.display = "none"), e && (e.style.display = "block"), o && (o.value = ""), r && (r.value = ""); } if (r) { const t = C("ytp-plus-feature-title"), e = C("ytp-plus-feature-desc"), o = t?.value?.trim?.() || "", i = e?.value?.trim?.() || ""; if (t instanceof HTMLInputElement && t.setCustomValidity(""), !o && t instanceof HTMLInputElement) { return t.setCustomValidity(Z("featureTitleRequired", "Feature title is required")), void t.reportValidity(); } r.disabled = !0, r.textContent = Z("loading", "Loading..."), u(o, i).then(o => { if (r.disabled = !1, r.textContent = Z("submit", "Submit"), o.success) { if (o.success) { const o = C("ytp-plus-voting-add-form"), r = C("ytp-plus-show-add-feature"); o && (o.style.display = "none"), r && (r.style.display = "block"), t && (t.value = ""), e && (e.value = ""), w(); } } else { t instanceof HTMLInputElement && (t.setCustomValidity(String(o.error || "")), t.reportValidity()); } }); } }, c = t => { const e = t.target?.closest?.(".ytp-plus-settings-nav-item"); if (e) { const t = String(e.dataset?.section || ""); t && "voting" !== t && h(); } const o = t.target?.closest?.('[data-comments-close="1"]'); if (o) { return void h(); } const i = t.target?.closest?.('[data-comments-open="1"]'); if (i) { const t = i.closest(".ytp-plus-voting-item"), e = t?.dataset?.featureId || ""; return void (e && g(e)); } const s = t.target?.closest?.("#ytp-plus-comments-submit"); if (!s) { return; } const c = C("ytp-plus-comments-panel"), l = c?.getAttribute("data-feature-id") || "", d = C("ytp-plus-comments-input"), u = String(d?.value || "").trim(); l && u && (s.disabled = !0, (async function(t, e) { const o = V(e).slice(0, 1e3); if (!o) { return { success: !1, error: "Comment is required" }; } const i = r(), {error: s} = await a("ytplus_feature_comments", { method: "POST", body: JSON.stringify({ feature_id: t, comment: o, author_ip: i }) }); return s ? (window.YouTubePlusLogger?.error?.("Voting", "Add comment error:", s), { success: !1, error: s }) : { success: !0 }; })(l, u).then(t => t.success ? (d && (d.value = ""), w().then(() => g(l))) : null).finally(() => { s.disabled = !1; })); }; T?.cleanupManager ? (T.cleanupManager.registerListener(document, "click", e), T.cleanupManager.registerListener(document, "click", i), T.cleanupManager.registerListener(document, "click", c)) : (document.addEventListener("click", e), document.addEventListener("click", i), document.addEventListener("click", c)); } const S = setTimeout.bind(window), T = window.YouTubeUtils, L = T.setSafeHTML, M = window._ytpDefaults?.createHTML || (t => t), C = T?.byId || (t => document.getElementById(t)), E = T?.$ || ((t, e) => (e || document).querySelector(t)); if ("undefined" == typeof window) { return; } const z = () => !!T.isSettingsModalOpen() || T.isYouTubeDomain() && (T.isWatchRoute() || T.isShortsRoute() || T.isChannelRoute()), _ = (t, e = document) => { const o = window.YouTubePlusDOMCache; return o && "function" == typeof o.querySelector ? o.querySelector(t, e || document) : (e || document).querySelector(t); }, I = (t, e) => { if (!(t instanceof Element)) { return; } const o = document.createElement("template"), r = document.createRange(), i = document.body || document.documentElement; i && r.selectNode(i), o.content.append(r.createContextualFragment(M(e))), t.replaceChildren(o.content.cloneNode(!0)); }, A = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImxkcGNjb2N4bHJkc3llamZocnZjIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzIyMTAyNDYsImV4cCI6MjA4Nzc4NjI0Nn0.QfwrAG4SMJBPLoP-Mcq3hETQXt0ezinoi0CpN57Zn90", P = "__ytp_preview_vote__"; let j = !1, H = !1, D = {}, O = {}, B = null; const R = () => _(".ytp-plus-settings-shell"), F = () => _(".ytp-plus-settings-panel"), N = T.t, Z = (t, e, o = {}) => { try { const e = N(t, o); if ("string" == typeof e && e && e !== t) { return e; } } catch (t) { T.logSuppressed(t, "Voting"); } return e || t || ""; }, V = t => { const e = String(t || "").normalize("NFKC").replace(/[\u0000-\u001F\u007F]+/g, " ").trim(), o = window.YouTubeSecurityUtils?.sanitizeText; return ("function" == typeof o ? o(e) : e).split(/\s+/).join(" ").trim(); }, Y = { init: k, createUI: function(t) { for (;t.firstChild; ) { t.removeChild(t.firstChild); } I(t, `\n <div class="ytp-plus-voting">\n <div class="ytp-plus-voting-header">\n <h3>${Z("featureRequests", "Feature Requests")}</h3>\n <button class="ytp-plus-voting-add-btn" id="ytp-plus-show-add-feature">\n + ${Z("addFeature", "Add Feature")}\n </button>\n </div>\n <div class="ytp-plus-voting-list" id="ytp-plus-voting-list">\n <div class="ytp-plus-voting-loading">${Z("loading", "Loading...")}</div>\n </div>\n <div class="ytp-plus-voting-add-form" id="ytp-plus-voting-add-form" style="display:none;">\n <input type="text" id="ytp-plus-feature-title" placeholder="${Z("featureTitle", "Feature title")}" />\n <textarea id="ytp-plus-feature-desc" placeholder="${Z("featureDescription", "Description")}"></textarea>\n <div class="ytp-plus-voting-form-actions">\n <button class="ytp-plus-voting-cancel" id="ytp-plus-cancel-feature">${Z("cancel", "Cancel")}</button>\n <button class="ytp-plus-voting-submit" id="ytp-plus-submit-feature">${Z("submit", "Submit")}</button>\n </div>\n </div>\n </div>\n `); }, loadFeatures: w, getFeatures: s, vote: d, submitFeature: u, initSlider: function() { function t(t, e = !1) { const o = Math.max(2, Math.min(98, t)); a.style.clipPath = `inset(0 0 0 ${o}%)`, e && (s.style.left = `${o}%`), s.setAttribute("aria-valuenow", String(Math.round(o))); } function e(t) { const e = i.getBoundingClientRect(); return (t - e.left) / e.width * 100; } function o() { s.classList.remove("autoplay"), d && (cancelAnimationFrame(d), d = null), l && clearTimeout(l), l = S(() => { s.classList.add("autoplay"), r(); }, 3e3); } function r() { d || (d = requestAnimationFrame(function e() { if (!s.classList.contains("autoplay")) { return void (d = null); } const o = i.getBoundingClientRect(), r = s.getBoundingClientRect(); t((r.left + r.width / 2 - o.left) / o.width * 100, !1), d = requestAnimationFrame(e); })); } const i = E(".ytp-plus-ba-container"); if (!i || i.dataset.sliderInit) { return; } i.dataset.sliderInit = "1"; const a = i.querySelector(".ytp-plus-ba-after"), s = i.querySelector(".ytp-plus-ba-divider"); if (!a || !s) { return; } let c = !1, l = null, d = null; i.addEventListener("mousedown", r => { c = !0, o(), t(e(r.clientX), !0), r.preventDefault(); }); const u = o => { c && t(e(o.clientX), !0); }, p = () => { c = !1; }; T?.cleanupManager ? (T.cleanupManager.registerListener(window, "mousemove", u), T.cleanupManager.registerListener(window, "mouseup", p)) : (window.addEventListener("mousemove", u), window.addEventListener("mouseup", p)), i.addEventListener("touchstart", r => { c = !0, o(), t(e(r.touches[0].clientX), !0); }, { passive: !0 }); const y = o => { c && t(e(o.touches[0].clientX), !0); }, m = () => { c = !1; }; T?.cleanupManager ? (T.cleanupManager.registerListener(window, "touchmove", y, { passive: !0 }), T.cleanupManager.registerListener(window, "touchend", m)) : (window.addEventListener("touchmove", y, { passive: !0 }), window.addEventListener("touchend", m)), s.addEventListener("keydown", e => { o(); const r = parseFloat(s.getAttribute("aria-valuenow") || "50"); "ArrowLeft" === e.key && (t(r - 2, !0), e.preventDefault()), "ArrowRight" === e.key && (t(r + 2, !0), e.preventDefault()); }), t(50, !0), S(() => { s.classList.add("autoplay"), r(); }, 400); }, updateVoteBar: x }; void 0 === window.YouTubePlus && (window.YouTubePlus = {}), window.YouTubePlus.Voting = Y, T?.whenRelevant ? T.whenRelevant({ name: "voting.runtime", isRelevant: () => { if (T.isSettingsModalOpen()) { return !1; } const t = window.YouTubeUtils?.getHostname?.() || ""; if (!t.endsWith("youtube.com") || "music.youtube.com" === t) { return !1; } const e = window.location.pathname || ""; return "/watch" === e || e.startsWith("/shorts") || e.startsWith("/channel/"); }, onEnter: k }) : z() && k(), T?.onSectionActive && T.onSectionActive("voting", () => { try { k(!0); } catch (t) {} try { const t = C("ytp-plus-voting-container"); t && (Y.createUI(t), Y.loadFeatures()); } catch (t) {} T.safeRequestAnimationFrame?.(() => { Y.initSlider(); }); }), T?.cleanupManager ? T.cleanupManager.registerListener(window, "yt-navigate-start", () => { h(); }) : window.addEventListener("yt-navigate-start", () => { h(); }); })();