YouTube - Force rounded corners + tweaks included

This script forces the rounded version of the layout (which includes some fewer tweaks applied, which also improves bugs).

Від 09.07.2025. Дивіться остання версія.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

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

(У мене вже є менеджер скриптів, дайте мені встановити його!)

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

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

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

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

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

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

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         YouTube - Force rounded corners + tweaks included
// @version      2025.07.09
// @description  This script forces the rounded version of the layout (which includes some fewer tweaks applied, which also improves bugs).
// @author       Joey_JTS (original author: xX_LegendCraftd_Xx)
// @license MIT
// @match        *://www.youtube.com/*
// @match        *://m.youtube.com/*
// @namespace    https://greatest.deepsurf.us/en/users/933798
// @icon         https://www.youtube.com/favicon.ico
// @run-at       document-idle
// @grant        none
// ==/UserScript==
 
// Attributes to remove from <html>
const ATTRS = [
    "darker-dark-theme",
    "darker-dark-theme-deprecate"
];
 
// Regular config keys.
const CONFIGS = {
    BUTTON_REWORK: true
}
 
// Experiment flags.
const EXPFLAGS = {
    /* Force rounded corners */
    web_button_rework: true,
    web_button_rework_with_live: true,
    web_darker_dark_theme: true,
    web_filled_subscribed_button: true,
    web_guide_ui_refresh: true,
    web_modern_ads: true,
    web_modern_buttons: true,
    web_modern_chips: true,
    web_modern_dialogs: true,
    web_modern_playlists: true,
    web_modern_subscribe: true,
    web_rounded_containers: true,
    web_rounded_thumbnails: true,
    web_searchbar_style: "rounded_corner_borders_light_btn",
    web_segmented_like_dislike_button: true,
    web_sheets_ui_refresh: true,
    web_snackbar_ui_refresh: true,
    /* Force rounded watch layout and few tweaks to be included (such as disabling the useless 'watch grid' UI */
    kevlar_watch_metadata_refresh: true,
    kevlar_watch_metadata_refresh_attached_subscribe: true,
    kevlar_watch_metadata_refresh_clickable_description: true,
    kevlar_watch_metadata_refresh_compact_view_count: true,
    kevlar_watch_metadata_refresh_description_info_dedicated_line: true,
    kevlar_watch_metadata_refresh_description_inline_expander: true,
    kevlar_watch_metadata_refresh_description_primary_color: true,
    kevlar_watch_metadata_refresh_for_live_killswitch: true,
    kevlar_watch_metadata_refresh_full_width_description: true,
    kevlar_watch_metadata_refresh_narrower_item_wrap: true,
    kevlar_watch_metadata_refresh_relative_date: true,
    kevlar_watch_metadata_refresh_top_aligned_actions: true,
    kevlar_watch_modern_metapanel: true,
    kevlar_watch_modern_panels: true,
    kevlar_watch_panel_height_matches_player: true,
    kevlar_watch_grid: false,
    kevlar_watch_grid_hide_chips: false,
    small_avatars_for_comments: false,
    small_avatars_for_comments_ep: false,
    web_watch_compact_comments: false,
    web_watch_compact_comments_ep: false,
    web_watch_theater_chat: false,
    web_watch_theater_fixed_chat: false,
    live_chat_over_engagement_panels: false,
    live_chat_scaled_height: false,
    live_chat_smaller_min_height: false,
    wn_grid_max_item_width: 0,
    wn_grid_min_item_width: 0,
    kevlar_set_internal_player_size: false,
    kevlar_watch_flexy_metadata_height: "136",
    kevlar_watch_max_player_width: "1280",
    web_watch_rounded_player_large: false,
    desktop_delay_player_resizing: false,
    /* Additional tweaks (which includes disabling ambient lighting and reverting new UI changes except for both web_modern_tabs and web_enable_youtab configs ) */
    kevlar_refresh_on_theme_change: false,
    smartimation_background: false,
    web_animated_actions: false,
    web_animated_like: false,
    web_animated_like_lazy_load: false,
    enable_channel_page_header_profile_section: false,
    kevlar_modern_sd_v2: false,
    web_modern_collections_v2: false,
    web_modern_tabs: false,
    web_modern_typography: true,
    web_enable_youtab: true,
    kevlar_measure_ambient_mode_idle: false,
    kevlar_watch_cinematics_invisible: false,
    web_cinematic_theater_mode: false,
    web_cinematic_fullscreen: false,
    enable_cinematic_blur_desktop_loading: false,
    kevlar_watch_cinematics: false,
    web_cinematic_masthead: false,
    web_watch_cinematics_preferred_reduced_motion_default_disabled: false
}
 
// Player flags
// !!! USE STRINGS FOR VALUES !!!
// For example: "true" instead of true
const PLYRFLAGS = {
    web_rounded_containers: "true",
    web_rounded_thumbnails: "true"
}
 
class YTP {
    static observer = new MutationObserver(this.onNewScript);
 
    static _config = {};
 
    static isObject(item) {
        return (item && typeof item === "object" && !Array.isArray(item));
    }
 
    static mergeDeep(target, ...sources) {
        if (!sources.length) return target;
        const source = sources.shift();
 
        if (this.isObject(target) && this.isObject(source)) {
            for (const key in source) {
                if (this.isObject(source[key])) {
                    if (!target[key]) Object.assign(target, { [key]: {} });
                    this.mergeDeep(target[key], source[key]);
                } else {
                    Object.assign(target, { [key]: source[key] });
                }
            }
        }
 
        return this.mergeDeep(target, ...sources);
    }
 
 
    static onNewScript(mutations) {
        for (var mut of mutations) {
            for (var node of mut.addedNodes) {
                YTP.bruteforce();
            }
        }
    }
 
    static start() {
        this.observer.observe(document, {childList: true, subtree: true});
    }
 
    static stop() {
        this.observer.disconnect();
    }
 
    static bruteforce() {
        if (!window.yt) return;
        if (!window.yt.config_) return;
 
        this.mergeDeep(window.yt.config_, this._config);
    }
 
    static setCfg(name, value) {
        this._config[name] = value;
    }
 
    static setCfgMulti(configs) {
        this.mergeDeep(this._config, configs);
    }
 
    static setExp(name, value) {
        if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
 
        this._config.EXPERIMENT_FLAGS[name] = value;
    }
 
    static setExpMulti(exps) {
        if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
 
        this.mergeDeep(this._config.EXPERIMENT_FLAGS, exps);
    }
 
    static decodePlyrFlags(flags) {
        var obj = {},
            dflags = flags.split("&");
 
        for (var i = 0; i < dflags.length; i++) {
            var dflag = dflags[i].split("=");
            obj[dflag[0]] = dflag[1];
        }
 
        return obj;
    }
 
    static encodePlyrFlags(flags) {
        var keys = Object.keys(flags),
            response = "";
 
        for (var i = 0; i < keys.length; i++) {
            if (i > 0) {
                response += "&";
            }
            response += keys[i] + "=" + flags[keys[i]];
        }
 
        return response;
    }
 
    static setPlyrFlags(flags) {
        if (!window.yt) return;
        if (!window.yt.config_) return;
        if (!window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS) return;
        var conCfgs = window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS;
        if (!("WEB_PLAYER_CONTEXT_CONFIGS" in this._config)) this._config.WEB_PLAYER_CONTEXT_CONFIGS = {};
 
        for (var cfg in conCfgs) {
            var dflags = this.decodePlyrFlags(conCfgs[cfg].serializedExperimentFlags);
            this.mergeDeep(dflags, flags);
            this._config.WEB_PLAYER_CONTEXT_CONFIGS[cfg] = {
                serializedExperimentFlags: this.encodePlyrFlags(dflags)
            }
        }
    }
}
 
window.addEventListener("yt-page-data-updated", function tmp() {
    YTP.stop();
    for (i = 0; i < ATTRS.length; i++) {
        document.getElementsByTagName("html")[0].removeAttribute(ATTRS[i]);
    }
    window.removeEventListener("yt-page-date-updated", tmp);
});
 
YTP.start();
 
YTP.setCfgMulti(CONFIGS);
YTP.setExpMulti(EXPFLAGS);
YTP.setPlyrFlags(PLYRFLAGS);
 
function $(q) {
    return document.querySelector(q);
}
 
(function() {
let css = `
/* Add rounded corners under the player */
div#ytp-id-17.ytp-popup.ytp-settings-menu,
div#ytp-id-18.ytp-popup.ytp-settings-menu {
border-radius: 12px !important
}
 
div.branding-context-container-inner.ytp-rounded-branding-context {
border-radius: 8px !important
}
 
.iv-card {
border-radius: 8px !important
}
 
.ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-overlay-image img, .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-text-overlay, .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-enhanced-overlay {
border-radius: 8px !important
}
 
.ytp-tooltip.ytp-text-detail.ytp-preview .ytp-tooltip-bg {
border-top-left-radius: 12px !important;
border-bottom-left-radius: 12px !important
}
 
.ytp-tooltip.ytp-text-detail.ytp-preview {
border-radius: 12px !important
}
 
.ytp-ce-video.ytp-ce-medium, .ytp-ce-playlist.ytp-ce-medium, .ytp-ce-medium .ytp-ce-expanding-overlay-background {
border-radius: 8px !important
}
 
.ytp-autonav-endscreen-upnext-thumbnail {
border-radius: 8px !important
}
 
.ytp-autonav-endscreen-upnext-button {
border-radius: 18px !important
}
 
.ytp-videowall-still-image {
border-radius: 8px !important
}
 
.ytp-sb-subscribe, .ytp-sb-unsubscribe {
border-radius: 18px !important
}
 
/* Watch page tweaks (including the 'Revert video list' CSS) */
ytd-watch-flexy[rounded-player-large]:not([fullscreen]):not([theater]) #ytd-player.ytd-watch-flexy, ytd-watch-flexy[rounded-player] #ytd-player.ytd-watch-flexy {
border-radius: 0px !important
}
 
#actions.ytd-watch-metadata {
min-width: auto !important
}
 
ytd-watch-flexy[default-layout][reduced-top-margin] #primary.ytd-watch-flexy, ytd-watch-flexy[default-layout][reduced-top-margin] #secondary.ytd-watch-flexy {
padding-top: var(--ytd-margin-6x) !important
}
 
ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata, ytd-watch-metadata[title-headline-m] h1.ytd-watch-metadata {
font-family: "YouTube Sans","Roboto",sans-serif !important;
font-weight: 600 !important;
font-size: 2rem !important;
line-height: 2.8rem !important
}

ytd-comments-header-renderer[compact-header] #title.ytd-comments-header-renderer {
margin-bottom: 24px !important
}

ytd-comments-header-renderer[modern-typography][compact-header] .count-text.ytd-comments-header-renderer {
font-size: 2rem !important;
line-height: 2.8rem !important;
font-weight: 700 !important;
max-height: 2.8rem !important;
display: flex !important;
flex-direction: row-reverse !important
}

[compact-header] .count-text.ytd-comments-header-renderer {
display: flex !important;
flex-direction: row-reverse !important
}

[compact-header] .count-text.ytd-comments-header-renderer span {
margin-right: 6px !important
}
 
ytd-watch-flexy #comment-teaser.ytd-watch-metadata {
display: none
}

ytd-watch-flexy ytd-rich-item-renderer[rendered-from-rich-grid] {
--ytd-rich-item-row-usable-width: 100% !important
}

ytd-watch-flexy ytd-rich-item-renderer[rendered-from-rich-grid][is-in-first-column] {
margin-left: 0
}

ytd-watch-flexy ytd-rich-item-renderer ytd-menu-renderer .ytd-menu-renderer[style-target=button] {
width: 24px !important;
height: 24px !important
}

ytd-watch-flexy #dismissible.ytd-rich-grid-media {
flex-direction: row
}
 
ytd-watch-flexy #attached-survey.ytd-rich-grid-media,
ytd-watch-flexy #avatar-link.ytd-rich-grid-media,
ytd-watch-flexy #avatar-container.ytd-rich-grid-media {
display: none
}
 
ytd-watch-flexy ytd-thumbnail.ytd-rich-grid-media,
ytd-watch-flexy ytd-playlist-thumbnail.ytd-rich-grid-media {
margin-right: 8px;
height: 94px;
width: 168px
}
 
ytd-watch-flexy ytd-thumbnail[size=large] a.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large]:before,
ytd-watch-flexy ytd-thumbnail[size=large][large-margin] a.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin]:before {
border-radius: 8px
}
 
ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-time-status-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-toggle-button-renderer.ytd-thumbnail,
ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-time-status-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-toggle-button-renderer.ytd-thumbnail {
margin: 4px
}
 
ytd-watch-flexy ytd-rich-item-renderer,
ytd-watch-flexy ytd-rich-grid-row #contents.ytd-rich-grid-row {
margin: 0
}
 
ytd-watch-flexy ytd-rich-item-renderer[reduced-bottom-margin] {
margin-top: 8px;
margin-bottom: 0
}
 
ytd-watch-flexy ytd-rich-grid-renderer[reduced-top-margin] #contents.ytd-rich-grid-renderer {
padding-top: 0px
}
 
ytd-watch-flexy ytd-rich-grid-media {
margin-bottom: 8px
}
 
ytd-watch-flexy #details.ytd-rich-grid-media {
width: 100%;
min-width: 0
}
 
ytd-watch-flexy ytd-video-meta-block[rich-meta] #metadata-line.ytd-video-meta-block,
ytd-watch-flexy #channel-name.ytd-video-meta-block {
font-family: "Roboto", "Arial", sans-serif;
font-size: 1.2rem;
line-height: 1.8rem;
font-weight: 400
}
 
ytd-watch-flexy #video-title.ytd-rich-grid-media {
margin: 0 0 4px 0;
display: block;
font-family: "Roboto", "Arial", sans-serif;
font-size: 1.4rem;
line-height: 2rem;
font-weight: 500;
overflow: hidden;
display: block;
max-height: 4rem;
-webkit-line-clamp: 2;
display: box;
display: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
white-space: normal
}
 
ytd-watch-flexy h3.ytd-rich-grid-media {
margin: 0
}
 
ytd-watch-flexy .title-badge.ytd-rich-grid-media, ytd-watch-flexy .video-badge.ytd-rich-grid-media {
margin-top: 0
}
 
ytd-watch-flexy ytd-rich-section-renderer.style-scope.ytd-rich-grid-renderer {
display: none
}
 
ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar] ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer, ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar-on-watch] ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer, ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar-on-home] #header.ytd-rich-grid-renderer ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer {
display: flex;
height: 51px;
margin-bottom: 8px
}
 
ytd-watch-flexy #chips-wrapper.ytd-feed-filter-chip-bar-renderer {
position: relative;
top: 0
}
 
ytd-watch-flexy ytd-feed-filter-chip-bar-renderer[fluid-width] #chips-content.ytd-feed-filter-chip-bar-renderer {
padding: 0
}
 
ytd-watch-flexy yt-chip-cloud-chip-renderer.ytd-feed-filter-chip-bar-renderer, ytd-watch-flexy yt-chip-cloud-chip-renderer.ytd-feed-filter-chip-bar-renderer:first-of-type {
margin: 8px;
margin-left: 0
}
 
ytd-watch-flexy ytd-button-renderer.ytd-feed-filter-chip-bar-renderer {
margin: 0;
padding: 0 8px
}
 
/* More tweaks to be applied (including removal of annoyances) */
#buttons.ytd-c4-tabbed-header-renderer {
flex-direction: row-reverse !important
}

ytd-channel-tagline-renderer {
display: block !important;
padding: 0 !important
}

#content.ytd-channel-tagline-renderer::before {
content: "More about this channel";
font-weight: 500 !important
}

#content.ytd-channel-tagline-renderer {
max-width: 162px !important
}

ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-description {
margin-top: 0px !important;
max-width: 236px !important
}

ytd-browse[page-subtype="channels"] yt-description-preview-view-model .truncated-text-wiz__truncated-text-content:before {
content: "More about this channel >   ";
font-weight: 500 !important
}

ytd-browse[page-subtype="channels"] button.truncated-text-wiz__absolute-button {
display: none !important
}

#avatar.ytd-c4-tabbed-header-renderer, .yt-spec-avatar-shape__button--button-giant {
width: 80px !important;
height: 80px !important;
margin: 0 24px 0 0 !important;
flex: none !important;
overflow: hidden !important
}

.yt-spec-avatar-shape__button--button-giant, .yt-spec-avatar-shape--avatar-size-giant, .yt-spec-avatar-shape__button--button-extra-extra-large, .yt-spec-avatar-shape--avatar-size-extra-extra-large {
width: 80px !important;
height: 80px !important;
margin-right: 0px !important;
}

#avatar-editor.ytd-c4-tabbed-header-renderer {
--ytd-channel-avatar-editor-size: 80px !important
}

#channel-name.ytd-c4-tabbed-header-renderer {
margin-bottom: 0 !important
}

#channel-header-container.ytd-c4-tabbed-header-renderer {
padding-top: 0 !important;
align-items: center !important
}

#inner-header-container.ytd-c4-tabbed-header-renderer {
margin-top: 0 !important;
align-items: center !important
}

.yt-content-metadata-view-model-wiz--inline .yt-content-metadata-view-model-wiz__metadata-row {
margin-top: 0 !important
}

yt-formatted-string#channel-pronouns.style-scope.ytd-c4-tabbed-header-renderer, #videos-count {
display: none !important
}

.meta-item.ytd-c4-tabbed-header-renderer {
display: block !important
}

div#channel-header-links.style-scope.ytd-c4-tabbed-header-renderer,
.page-header-view-model-wiz__page-header-attribution {
display: none !important
}

ytd-c4-tabbed-header-renderer[use-page-header-style] #channel-name.ytd-c4-tabbed-header-renderer,
[page-subtype="channels"] .page-header-view-model-wiz__page-header-title--page-header-title-large {
font-size: 2.4em !important;
font-weight: 400 !important;
line-height: var(--yt-channel-title-line-height, 3rem) !important;
margin: 0 !important
}

span.delimiter.style-scope.ytd-c4-tabbed-header-renderer, .yt-content-metadata-view-model-wiz__delimiter {
display: none !important
}

div#meta.style-scope.ytd-c4-tabbed-header-renderer {
width: auto !important
}

ytd-c4-tabbed-header-renderer[use-page-header-style] #inner-header-container.ytd-c4-tabbed-header-renderer {
flex-direction: row !important
}

div.page-header-banner.style-scope.ytd-c4-tabbed-header-renderer {
margin-left: 0px !important;
margin-right: 8px !important;
border-radius: 0px !important
}

[has-inset-banner] #page-header-banner.ytd-tabbed-page-header {
padding-left: 0 !important;
padding-right: 0 !important
}

ytd-c4-tabbed-header-renderer[use-page-header-style] .page-header-banner.ytd-c4-tabbed-header-renderer,
.yt-image-banner-view-model-wiz--inset {
border-radius: 0px !important
}

.yt-content-metadata-view-model-wiz__metadata-text {
margin-right: 8px !important
}

.yt-content-metadata-view-model-wiz__metadata-text, .truncated-text-wiz, .truncated-text-wiz__absolute-button {
font-size: 1.4rem !important
}

.yt-tab-shape-wiz {
padding: 0 32px !important;
margin-right: 0 !important
}

.yt-tab-shape-wiz__tab {
font-size: 14px !important;
font-weight: 500 !important;
letter-spacing: var(--ytd-tab-system-letter-spacing) !important;
text-transform: uppercase !important
}

.yt-tab-group-shape-wiz__slider {
display: none !important
}

ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-row--metadata-row-inline {
display: flex
}

ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-text:last-of-type {
display: none
}

ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-text:first-of-type {
display: flex
}

ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz--inline {
flex-direction: row-reverse
}

ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-flexible-actions {
margin-top: -56px
}

ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz__action-row {
margin-top: 60px
}

ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz__action {
padding-right: 8px
}

ytd-browse[page-subtype="channels"] span.yt-core-attributed-string--link-inherit-color {
font-weight: 400 !important
}

ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-headline-info {
margin-bottom: 8px
}

#title.ytd-playlist-sidebar-primary-info-renderer,
ytd-inline-form-renderer[component-style=INLINE_FORM_STYLE_TITLE] #text-displayed.ytd-inline-form-renderer {
font-family: YouTube Sans !important;
font-weight: 700 !important
}

div#end.style-scope.ytd-masthead .yt-spec-icon-badge-shape--style-overlay.yt-spec-icon-badge-shape--type-cart-refresh .yt-spec-icon-badge-shape__badge {
color: #fff !important
}

ytd-button-renderer.ytd-feed-filter-chip-bar-renderer {
background-color: transparent !important
}

#left-arrow-button.ytd-feed-filter-chip-bar-renderer,
#right-arrow-button.ytd-feed-filter-chip-bar-renderer {
background-color: var(--yt-spec-base-background) !important
}

#left-arrow.ytd-feed-filter-chip-bar-renderer:after {
background: linear-gradient(to right, var(--yt-spec-base-background) 20%, rgba(255, 255, 255, 0) 80%) !important
}

#right-arrow.ytd-feed-filter-chip-bar-renderer:before {
background: linear-gradient(to left, var(--yt-spec-base-background) 20%, rgba(255, 255, 255, 0) 80%) !important
}

#background.ytd-masthead, #frosted-glass.ytd-app {
background: var(--yt-spec-base-background) !important;
backdrop-filter: none !important
}

.ytp-cairo-refresh-signature-moments .ytp-play-progress, .ytp-play-progress, .html5-play-progress, ytd-thumbnail-overlay-resume-playback-renderer[enable-refresh-signature-moments-web] #progress.ytd-thumbnail-overlay-resume-playback-renderer, .YtThumbnailOverlayProgressBarHostWatchedProgressBarSegmentModern, .YtChapteredProgressBarChapteredPlayerBarChapterRefresh, .YtChapteredProgressBarChapteredPlayerBarFillRefresh, .YtProgressBarLineProgressBarPlayedRefresh, yt-page-navigation-progress[enable-refresh-signature-moments-web] #progress.yt-page-navigation-progress, ytd-progress-bar-line[enable-refresh-signature-moments-web] .progress-bar-played.ytd-progress-bar-line, #logo-icon > .yt-spec-icon-shape.yt-icon.style-scope.yt-icon-shape > div > svg > g:first-of-type > path:first-of-type {
background: #ff0000 !important
}

.ytp-progress-bar .ytp-scrubber-button {
opacity: 0 !important
}

.ytp-progress-bar:hover .ytp-scrubber-button {
opacity: 1 !important
}

[d*="M18 4v15.06l-5.42-3.87-.58-.42-.58.42L6 19.06V4h12m1-1H5v18l7-5 7 5V3z"] {
d: path("M22 13h-4v4h-2v-4h-4v-2h4V7h2v4h4v2zm-8-6H2v1h12V7zM2 12h8v-1H2v1zm0 4h8v-1H2v1z")
}

ytd-action-companion-ad-renderer, ytd-display-ad-renderer, ytd-video-masthead-ad-advertiser-info-renderer, ytd-video-masthead-ad-primary-video-renderer, ytd-in-feed-ad-layout-renderer, ytd-ad-slot-renderer, yt-about-this-ad-renderer, yt-mealbar-promo-renderer, ytd-ad-slot-renderer, ytd-in-feed-ad-layout-renderer, .ytd-video-masthead-ad-v3-renderer, div#root.style-scope.ytd-display-ad-renderer.yt-simple-endpoint, div#sparkles-container.style-scope.ytd-promoted-sparkles-web-renderer, div#main-container.style-scope.ytd-promoted-video-renderer, #player-ads, .ytwPanelAdHeaderImageLockupViewModelHost, ad-slot-renderer, ytm-promoted-sparkles-web-renderer, masthead-ad, #masthead-ad, ytd-video-quality-promo-renderer, #yt-lang-alert-container, .YtmPaidContentOverlayHost, .ytd-primetime-promo-renderer, ytd-brand-video-singleton-renderer, #yt-feedback, #yt-hitchhiker-feedback, ytd-merch-shelf-renderer, ytd-enforcement-message-view-model, div[is-shared-heimdall], tp-yt-iron-overlay-backdrop.opened {
display: none !important;
}

#movie_player.ad-showing video {
  filter: blur(100px) opacity(0.25) grayscale(0.5);
}

#movie_player.ad-showing .ytp-title,
#movie_player.ad-showing .ytp-title-channel,
.ytp-visit-advertiser-link,
.ytp-ad-visit-advertiser-button,
ytmusic-app:has(#movie_player.ad-showing)
  ytmusic-player-bar
  :is(.title, .subtitle) {
  filter: blur(4px) opacity(0.5) grayscale(0.5);
  transition: 0.05s filter linear;
}

:is(#movie_player.ad-showing .ytp-title,#movie_player.ad-showing .ytp-title-channel,.ytp-visit-advertiser-link,.ytp-ad-visit-advertiser-button,ytmusic-app:has(#movie_player.ad-showing) ytmusic-player-bar :is(.title,.subtitle)):is(:hover,:focus-within) {
    filter: none;
}

.ytp-suggested-action-badge {
  visibility: hidden !important;
}
 
ytd-watch-metadata.ytd-watch-flexy {
padding-bottom: 36px !important;
}

ytd-search-header-renderer .yt-spec-button-shape-next--size-m {
flex-direction: row-reverse;
}

ytd-search-header-renderer .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-trailing .yt-spec-button-shape-next__icon {
margin-left: -6px;
margin-right: 6px;
}

/* For YT Mobile */
html[dark] {
--yt-spec-base-background: #0f0f0f !important
}

html:not([dark]) {
--yt-spec-base-background: #fff !important
}

ytm-mobile-topbar-renderer.frosted-glass,
ytm-pivot-bar-renderer.frosted-glass,
ytm-feed-filter-chip-bar-renderer.frosted-glass {
background: var(--yt-spec-base-background) !important;
-webkit-backdrop-filter: none !important;
backdrop-filter: none !important
}`;
if (typeof GM_addStyle !== "undefined") {
  GM_addStyle(css);
} else {
  let styleNode = document.createElement("style");
  styleNode.appendChild(document.createTextNode(css));
  (document.querySelector("head") || document.documentElement).appendChild(styleNode);
}
})();
 
// Integrate 'YouTube Video Resize Fix' script (special thanks to CY Fung)
/* jshint esversion:8 */
 
((__CONTEXT01__) => {
  'use strict';
 
 
  const win = this instanceof Window ? this : window;
 
  // Create a unique key for the script and check if it is already running
  const hkey_script = 'ahceihvpbosz';
  if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
  win[hkey_script] = true;
 
  const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
  const indr = o => insp(o).$ || o.$ || 0;
 
  /** @type {globalThis.PromiseConstructor} */
  const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
  const cleanContext = async (win) => {
    const waitFn = requestAnimationFrame; // shall have been binded to window
    try {
      let mx = 16; // MAX TRIAL
      const frameId = 'vanillajs-iframe-v1'
      let frame = document.getElementById(frameId);
      let removeIframeFn = null;
      if (!frame) {
        frame = document.createElement('iframe');
        frame.id = frameId;
        const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
        frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
        let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
        n.appendChild(frame);
        while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
        const root = document.documentElement;
        root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
        if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
 
        removeIframeFn = (setTimeout) => {
          const removeIframeOnDocumentReady = (e) => {
            e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
            e = n;
            n = win = removeIframeFn = 0;
            setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
          }
          if (!setTimeout || document.readyState !== 'loading') {
            removeIframeOnDocumentReady();
          } else {
            win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
          }
        }
      }
      while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
      const fc = frame.contentWindow;
      if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
      try {
        const { requestAnimationFrame, setTimeout, clearTimeout } = fc;
        const res = { requestAnimationFrame, setTimeout, clearTimeout };
        for (let k in res) res[k] = res[k].bind(win); // necessary
        if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
        return res;
      } catch (e) {
        if (removeIframeFn) removeIframeFn();
        return null;
      }
    } catch (e) {
      console.warn(e);
      return null;
    }
  };
 
  const isWatchPageURL = (url) => {
    url = url || location;
    return location.pathname === '/watch' || location.pathname.startsWith('/live/')
  };
 
  cleanContext(win).then(__CONTEXT02__ => {
    if (!__CONTEXT02__) return null;
 
    const { ResizeObserver } = __CONTEXT01__;
    const { requestAnimationFrame, setTimeout, clearTimeout } = __CONTEXT02__;
    const elements = {};
    let rid1 = 0;
    let rid2 = 0;
    /** @type {MutationObserver | null} */
    let attrObserver = null;
    /** @type {ResizeObserver | null} */
    let resizeObserver = null;
    let isHTMLAttrApplied = false;
    const core = {
      begin() {
        document.addEventListener('yt-player-updated', core.hanlder, true);
        document.addEventListener('ytd-navigate-finish', core.hanlder, true);
      },
      hanlder: () => {
        rid1++;
        if (rid1 > 1e9) rid1 = 9;
        const tid = rid1;
        requestAnimationFrame(() => {
          if (tid !== rid1) return;
          core.runner();
        })
      },
      async runner() {
        if (!location.href.startsWith('https://www.youtube.com/')) return;
        if (!isWatchPageURL()) return;
 
        elements.ytdFlexy = document.querySelector('ytd-watch-flexy');
        elements.video = document.querySelector('ytd-watch-flexy #movie_player video, ytd-watch-flexy #movie_player audio.video-stream.html5-main-video');
        if (elements.ytdFlexy && elements.video) { } else return;
        elements.moviePlayer = elements.video.closest('#movie_player');
        if (!elements.moviePlayer) return;
 
        // resize Video
        let { ytdFlexy } = elements;
        if (!ytdFlexy.ElYTL) {
          ytdFlexy.ElYTL = 1;
          const ytdFlexyCnt = insp(ytdFlexy);
          if (typeof ytdFlexyCnt.calculateNormalPlayerSize_ === 'function') {
            ytdFlexyCnt.calculateNormalPlayerSize_ = core.resizeFunc(ytdFlexyCnt.calculateNormalPlayerSize_, 1);
          } else {
            console.warn('ytdFlexyCnt.calculateNormalPlayerSize_ is not a function.')
          }
          if (typeof ytdFlexyCnt.calculateCurrentPlayerSize_ === 'function') {
            ytdFlexyCnt.calculateCurrentPlayerSize_ = core.resizeFunc(ytdFlexyCnt.calculateCurrentPlayerSize_, 0);
          } else {
            console.warn('ytdFlexyCnt.calculateCurrentPlayerSize_ is not a function.')
          }
        }
        ytdFlexy = null;
 
        // when video is fetched
        elements.video.removeEventListener('canplay', core.triggerResizeDelayed, false);
        elements.video.addEventListener('canplay', core.triggerResizeDelayed, false);
 
        // when video is resized
        if (resizeObserver) {
          resizeObserver.disconnect();
          resizeObserver = null;
        }
        if (typeof ResizeObserver === 'function') {
          resizeObserver = new ResizeObserver(core.triggerResizeDelayed);
          resizeObserver.observe(elements.moviePlayer);
        }
 
        // MutationObserver:[collapsed] @ ytd-live-chat-frame#chat
        if (attrObserver) {
          attrObserver.takeRecords();
          attrObserver.disconnect();
          attrObserver = null;
        }
        let chat = document.querySelector('ytd-watch-flexy ytd-live-chat-frame#chat');
        if (chat) {
          // resize due to DOM update
          attrObserver = new MutationObserver(core.triggerResizeDelayed);
          attrObserver.observe(chat, { attributes: true, attributeFilter: ["collapsed"] });
          chat = null;
        }
 
        // resize on idle
        Promise.resolve().then(core.triggerResizeDelayed);
      },
      resizeFunc(originalFunc, kb) {
        return function () {
          rid2++;
          if (!isHTMLAttrApplied) {
            isHTMLAttrApplied = true;
            Promise.resolve(0).then(() => {
              document.documentElement.classList.add('youtube-video-resize-fix');
            }).catch(console.warn);
          }
          if (document.fullscreenElement === null) {
 
            // calculateCurrentPlayerSize_ shall be always return NaN to make correct positioning of toolbars
            if (!kb) return { width: NaN, height: NaN };
 
            let ret = core.calculateSize();
            if (ret.height > 0 && ret.width > 0) {
              return ret;
            }
          }
          return originalFunc.apply(this, arguments);
        }
      },
      calculateSize_() {
        const { moviePlayer, video } = elements;
        const rect1 = { width: video.videoWidth, height: video.videoHeight }; // native values independent of css rules
        if (rect1.width > 0 && rect1.height > 0) {
          const rect2 = moviePlayer.getBoundingClientRect();
          const aspectRatio = rect1.width / rect1.height;
          let h2 = rect2.width / aspectRatio;
          let w2 = rect2.height * aspectRatio;
          return { rect2, h2, w2 };
        }
        return null;
      },
      calculateSize() {
        let rs = core.calculateSize_();
        if (!rs) return { width: NaN, height: NaN };
        const { rect2, h2, w2 } = rs;
        if (h2 > rect2.height) {
          return { width: w2, height: rect2.height };
        } else {
          return { width: rect2.width, height: h2 };
        }
      },
      triggerResizeDelayed: () => {
        rid2++;
        if (rid2 > 1e9) rid2 = 9;
        const tid = rid2;
        requestAnimationFrame(() => {
          if (tid !== rid2) return;
          const { ytdFlexy } = elements;
          let r = false;
          const ytdFlexyCnt = insp(ytdFlexy);
          const windowSize_ = ytdFlexyCnt.windowSize_;
          if (windowSize_ && typeof ytdFlexyCnt.onWindowResized_ === 'function') {
            try {
              ytdFlexyCnt.onWindowResized_(windowSize_);
              r = true;
            } catch (e) { }
          }
          if (!r) window.dispatchEvent(new Event('resize'));
        })
      }
    };
    core.begin();
 
 
 
 
 
 
 
    // YouTube Watch Page Reflect (WPR)
 
 
 
    // This script enhances the functionality of YouTube pages by reflecting changes in the page state.
 
    (async function youTubeWPR() {
 
      let checkPageVisibilityChanged = false;
 
      // A WeakSet to keep track of elements being monitored for mutations.
      const monitorWeakSet = new WeakSet();
 
      /** @type {globalThis.PromiseConstructor} */
      const Promise = (async () => { })().constructor;
 
      // Function to reflect the current state of the YouTube page.
      async function _reflect() {
        await Promise.resolve();
 
        const youtubeWpr = document.documentElement.getAttribute("youtube-wpr");
        let s = '';
 
        // Check if the current page is the video watch page.
        if (isWatchPageURL()) {
          let watch = document.querySelector("ytd-watch-flexy");
          let chat = document.querySelector("ytd-live-chat-frame#chat");
 
          if (watch) {
            // Determine the state of the chat and video player on the watch page and generate a state string.
            s += !chat ? 'h0' : (chat.hasAttribute('collapsed') || !document.querySelector('iframe#chatframe')) ? 'h1' : 'h2';
            s += watch.hasAttribute('is-two-columns_') ? 's' : 'S';
            s += watch.hasAttribute('fullscreen') ? 'F' : 'f';
            s += watch.hasAttribute('theater') ? 'T' : 't';
          }
        }
 
        // Update the reflected state if it has changed.
        if (s !== youtubeWpr) {
          document.documentElement.setAttribute("youtube-wpr", s);
        }
 
      }
 
      // Function to reflect changes in specific attributes of monitored elements.
      async function reflect(nodeName, attrNames, forced) {
        await Promise.resolve();
 
        if (!forced) {
          let skip = true;
          for (const attrName of attrNames) {
            if (nodeName === 'ytd-live-chat-frame') {
              if (attrName === 'collapsed') skip = false;
            } else if (nodeName === 'ytd-watch-flexy') {
              if (attrName === 'is-two-columns_') skip = false;
              else if (attrName === 'fullscreen') skip = false;
              else if (attrName === 'theater') skip = false;
            }
          }
          if (skip) return;
        }
 
        // Log the mutated element and its attributes.
        // console.log(nodeName, attrNames);
 
        // Call _reflect() to update the reflected state.
        _reflect();
      }
 
      // Callback function for the MutationObserver that tracks mutations in monitored elements.
      function callback(mutationsList) {
        const attrNames = new Set();
        let nodeName = null;
        for (const mutation of mutationsList) {
          if (nodeName === null && mutation.target) nodeName = mutation.target.nodeName.toLowerCase();
          attrNames.add(mutation.attributeName);
        }
        reflect(nodeName, attrNames, false);
      }
 
      function getParent(element) {
        return element.__shady_native_parentNode || element.__shady_parentNode || element.parentNode;
      }
 
      let lastPageTypeChanged = 0;
      function chatContainerMutationHandler() {
        if (Date.now() - lastPageTypeChanged < 800) _reflect();
      }
 
      // Function to start monitoring an element for mutations.
      function monitor(element) {
        if (!element) return;
        if (monitorWeakSet.has(element)) {
          return;
        }
 
        monitorWeakSet.add(element);
 
        const observer = new MutationObserver(callback);
        observer.observe(element, { attributes: true });
 
        if (element.id === 'chat') {
          const parentNode = getParent(element);
          if (parentNode instanceof Element && parentNode.id === 'chat-container' && !monitorWeakSet.has(parentNode)) {
            monitorWeakSet.add(parentNode);
            const observer = new MutationObserver(chatContainerMutationHandler);
            observer.observe(parentNode, { childList: true, subtree: false });
          }
        }
 
        return 1;
      }
 
      let timeout = 0;
 
      // Function to monitor relevant elements and update the reflected state.
      let g = async (forced) => {
        await Promise.resolve();
        let b = 0;
        b = b | monitor(document.querySelector("ytd-watch-flexy"));
        b = b | monitor(document.querySelector("ytd-live-chat-frame#chat"));
        if (b || forced) {
          _reflect();
        }
      }
      // let renderId = 0;
      // Event handler function that triggers when the page finishes navigation or page data updates.
      let eventHandlerFunc = async (evt) => {
        checkPageVisibilityChanged = true;
        timeout = Date.now() + 800;
        g(1);
        if (evt.type === 'yt-navigate-finish') {
          // delay required when page type is changed for #chat (home -> watch).
          setTimeout(() => {
            g(1);
          }, 80);
        } else if (evt.type === 'yt-page-type-changed') {
          lastPageTypeChanged = Date.now();
          // setTimeout(() => {
          //   if (renderId > 1e9) renderId = 9;
          //   const t = ++renderId;
          //   requestAnimationFrame(() => {
          //     if (t !== renderId) return;
          //     g(1);
          //   });
          // }, 180);
          if (typeof requestIdleCallback === 'function') {
            requestIdleCallback(() => {
              g(1);
            });
          }
        }
      }
 
      let loadState = 0;
 
      // Function to initialize the script and start monitoring the page.
      async function actor() {
        if (loadState === 0) {
          if (!document.documentElement.hasAttribute("youtube-wpr")) {
            loadState = 1;
            document.documentElement.setAttribute("youtube-wpr", "");
            document.addEventListener("yt-navigate-finish", eventHandlerFunc, false);
            document.addEventListener("yt-page-data-updated", eventHandlerFunc, false);
            document.addEventListener("yt-page-type-changed", eventHandlerFunc, false);
          } else {
            loadState = -1;
            document.removeEventListener("yt-page-data-fetched", actor, false);
            return;
          }
        }
        if (loadState === 1) {
          timeout = Date.now() + 800;
          // Function to continuously monitor elements and update the reflected state.
          let pf = () => {
            g(0);
            if (Date.now() < timeout) requestAnimationFrame(pf);
          };
          pf();
        }
      }
 
      // Event listener that triggers when page data is fetched.
      document.addEventListener("yt-page-data-fetched", actor, false);
 
      // Update after visibility changed (looks like there are bugs due to inactive tab)
      document.addEventListener('visibilitychange', () => {
        if (document.visibilityState !== 'visible') return;
        if (checkPageVisibilityChanged) {
          checkPageVisibilityChanged = false;
          setTimeout(() => {
            g(1);
          }, 100);
          requestAnimationFrame(() => {
            g(1);
          });
        }
      }, false);
 
 
    })();
 
  });
 
})({ ResizeObserver });

 
// Auto skip ads and prevent video autopausing
(() => {
 
  let popupState = 0;
  let popupElement = null;
 
  const rate = 1;
 
  const Promise = (async () => { })().constructor;
 
  const PromiseExternal = ((resolve_, reject_) => {
    const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
    return class PromiseExternal extends Promise {
      constructor(cb = h) {
        super(cb);
        if (cb === h) {
          /** @type {(value: any) => void} */
          this.resolve = resolve_;
          /** @type {(reason?: any) => void} */
          this.reject = reject_;
        }
      }
    };
  })();
 
  const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
 
  let vload = null;
 
  const fastSeekFn = HTMLVideoElement.prototype.fastSeek || null;
  const addEventListenerFn = HTMLElement.prototype.addEventListener;
  if (!addEventListenerFn) return;
  const removeEventListenerFn = HTMLElement.prototype.removeEventListener;
  if (!removeEventListenerFn) return;
 
  const ytPremiumPopupSelector = 'yt-mealbar-promo-renderer.style-scope.ytd-popup-container:not([hidden])';
 
  const DEBUG = 0;
 
  const rand = (a, b) => a + Math.random() * (b - a);
  const log = DEBUG ? console.log.bind(console) : () => 0;
 
  //$0.$['dismiss-button'].click()
  const ytPremiumPopupClose = function () {
    const popup = document.querySelector(ytPremiumPopupSelector);
    if (popup instanceof HTMLElement) {
      if (HTMLElement.prototype.closest.call(popup, '[hidden]')) return;
      const cnt = insp(popup);
      const btn = cnt.$ ? cnt.$['dismiss-button'] : 0;
      if (btn instanceof HTMLElement && HTMLElement.prototype.closest.call(btn, '[hidden]')) return;
      btn && btn.click();
    }
  }
 
  //div.video-ads.ytp-ad-module
  const clickSkip = function () {
    // ytp-ad-skip-button
    const isAdsContainerContainsButton = document.querySelector('.video-ads.ytp-ad-module button');
    if (isAdsContainerContainsButton) {
 
      const btnFilter = e => HTMLElement.prototype.matches.call(e, ".ytp-ad-overlay-close-button, .ytp-ad-skip-button-modern, .ytp-ad-skip-button") && !HTMLElement.prototype.closest.call(e, '[hidden]');
      const btns = [...document.querySelectorAll('.video-ads.ytp-ad-module button[class*="ytp-ad-"]')].filter(btnFilter);
      console.log('# of ads skip btns', btns.length);
      if (btns.length !== 1) return;
      const btn = btns[0];
      if (btn instanceof HTMLElement) {
        btn.click();
      }
 
    }
  };
 
  const adsEndHandlerHolder = function (evt) {
 
    adsEndHandler && adsEndHandler(evt);
 
  }
 
  let adsEndHandler = null;
 
 
  const videoPlayingHandler = async function (evt) {
    try {
 
      if (!evt || !evt.target || !evt.isTrusted || !(evt instanceof Event)) return;
      const video = evt.target;
 
      const checkPopup = popupState === 1;
      popupState = 0;
 
      const popupElementValue = popupElement;
      popupElement = null;
 
      if (video.duration < 0.8) return;
 
      await vload.then();
      if (!video.isConnected) return;
 
      const ytplayer = HTMLElement.prototype.closest.call(video, 'ytd-player, ytmusic-player');
      if (!ytplayer || !ytplayer.is) return;
 
      const ytplayerCnt = insp(ytplayer);
      const player_ = await (ytplayerCnt.player_ || ytplayer.player_ || ytplayerCnt.playerApi || ytplayer.playerApi || 0);
      if (!player_) return;
 
      if (typeof ytplayerCnt.getPlayer === 'function' && !ytplayerCnt.getPlayer()) {
        await new Promise(r => setTimeout(r, 40));
      }
      const playerController = await ytplayerCnt.getPlayer() || player_;
      if (!video.isConnected) return;
 
      if ('getPresentingPlayerType' in playerController && 'getDuration' in playerController) {
 
        const ppType = await playerController.getPresentingPlayerType();
 
        log('m02a', ppType);
        if (ppType === 1 || typeof ppType !== 'number') return; // ads shall be ppType === 2
        // const progressState = player_.getProgressState();
        // log('m02b', progressState);
        // if(!progressState) return;
        // const q = progressState.duration;
 
        // if (popupState === 1) console.debug('m05b:ytPremiumPopup', document.querySelector(ytPremiumPopupSelector))
 
        const q = video.duration;
 
        const ytDuration = await playerController.getDuration();
        log('m02c', q, ytDuration, Math.abs(ytDuration - q));
 
        if (q > 0.8 && ytDuration > 2.5 && Math.abs(ytDuration - q) > 1.4) {
          try {
            log('m02s', 'fastSeek', q);
            video.muted = true;
            const w = Math.round(rand(582, 637) * rate);
            const sq = q - w / 1000;
 
            adsEndHandler = null;
 
            const expired = Date.now() + 968;
 
            removeEventListenerFn.call(video, 'ended', adsEndHandlerHolder, false);
            removeEventListenerFn.call(video, 'suspend', adsEndHandlerHolder, false);
            removeEventListenerFn.call(video, 'durationchange', adsEndHandlerHolder, false);
            addEventListenerFn.call(video, 'ended', adsEndHandlerHolder, false);
            addEventListenerFn.call(video, 'suspend', adsEndHandlerHolder, false);
            addEventListenerFn.call(video, 'durationchange', adsEndHandlerHolder, false);
 
            adsEndHandler = async function (evt) {
              adsEndHandler = null;
 
              removeEventListenerFn.call(video, 'ended', adsEndHandlerHolder, false);
              removeEventListenerFn.call(video, 'suspend', adsEndHandlerHolder, false);
              removeEventListenerFn.call(video, 'durationchange', adsEndHandlerHolder, false);
 
              if (Date.now() < expired) {
 
                const delay = Math.round(rand(92, 117));
                await new Promise(r => setTimeout(r, delay));
 
                Promise.resolve().then(() => {
                  clickSkip();
                }).catch(console.warn);
 
                checkPopup && Promise.resolve().then(() => {
                  const currentPopup = document.querySelector(ytPremiumPopupSelector);
                  if (popupElementValue ? currentPopup === popupElementValue : currentPopup) {
                    ytPremiumPopupClose();
                  }
                }).catch(console.warn);
              }
 
            };
 
            if (fastSeekFn) fastSeekFn.call(video, sq);
            else video.currentTime = sq;
 
          } catch (e) {
            console.warn(e);
          }
        }
 
      }
 
    } catch (e) {
      console.warn(e);
    }
 
  };
 
  document.addEventListener('loadedmetadata', async function (evt) {
    try {
 
      if (!evt || !evt.target || !evt.isTrusted || !(evt instanceof Event)) return;
 
      const video = evt.target;
      if (video.nodeName !== "VIDEO") return;
      if (video.duration < 0.8) return;
      if (!video.matches('.video-stream.html5-main-video')) return;
 
      popupState = 0;
 
      vload = new PromiseExternal();
 
      popupElement = document.querySelector(ytPremiumPopupSelector);
 
      removeEventListenerFn.call(video, 'playing', videoPlayingHandler, { passive: true, capture: false });
 
      addEventListenerFn.call(video, 'playing', videoPlayingHandler, { passive: true, capture: false });
 
      popupState = 1;
 
      let trial = 6;
 
      await new Promise(resolve => {
 
        let io = new IntersectionObserver(entries => {
          if (trial-- <= 0 || (entries && entries.length >= 1 && video.matches('ytd-player video, ytmusic-player video'))) {
            resolve();
            io.disconnect();
            io = null;
          }
        });
        io.observe(video);
 
      });
 
      vload.resolve();
 
    } catch (e) {
      console.warn(e);
    }
 
  }, true);
 
})();
 
Object.defineProperties(document, { /*'hidden': {value: false},*/ 'webkitHidden': {value: false}, 'visibilityState': {value: 'visible'}, 'webkitVisibilityState': {value: 'visible'} });
 
setInterval(function(){
    document.dispatchEvent( new KeyboardEvent( 'keyup', { bubbles: true, cancelable: true, keyCode: 143, which: 143 } ) );
}, 60000);