YouTube Layout Plus

Home: collapse guide, fixed hero layout for the first 5 videos, then 4/5 col grid below, hide Shorts. Flat chip bar. Watch: hide recommendations sidebar and center the player/content, while preserving live chat on streams/replays and engagement panels. Adds topbar theme and home grid switchers.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         YouTube Layout Plus
// @namespace    https://qazwsx123.uk/
// @version      0.7.0
// @description  Home: collapse guide, fixed hero layout for the first 5 videos, then 4/5 col grid below, hide Shorts. Flat chip bar. Watch: hide recommendations sidebar and center the player/content, while preserving live chat on streams/replays and engagement panels. Adds topbar theme and home grid switchers.
// @author       Codex
// @match        https://www.youtube.com/*
// @run-at       document-idle
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  // ============================================================================
  // 模块1: 常量定义
  // ============================================================================
  const Constants = {
    // ID 常量
    STYLE_ID: 'tm-youtube-layout-plus-style',
    STYLE_VERSION: '0.7.0',
    THEME_SWITCHER_ID: 'tm-youtube-layout-plus-theme-switcher',
    HOME_GRID_SWITCHER_ID: 'tm-youtube-layout-plus-home-grid-switcher',
    THEME_STATUS_ID: 'tm-youtube-layout-plus-theme-status',

    // CSS 类名
    Classes: {
      REPLAY_HIDE: 'tm-youtube-layout-plus-hide-replay-prompt',
      WATCH_PANEL_OPEN: 'tm-youtube-layout-plus-watch-panel-open',
      WATCH_THEATER: 'tm-youtube-layout-plus-watch-theater',
      WATCH_VERTICAL: 'tm-youtube-layout-plus-watch-vertical',
      ROUTE_TRANSITION: 'tm-youtube-layout-plus-route-transition',
      HERO_MIX: 'tm-youtube-layout-plus-hero-mix',
      WATCH_CHAT_OPEN: 'tm-youtube-layout-plus-watch-chat-open',
      WATCH_CHAT_COLLAPSED: 'tm-youtube-layout-plus-watch-chat-collapsed',
      LAYOUT_MODES: [
        'tm-youtube-layout-plus-home',
        'tm-youtube-layout-plus-watch',
        'tm-youtube-layout-plus-watch-chat',
        'tm-youtube-layout-plus-watch-plain',
      ],
    },

    // 属性名
    WATCH_READY_ATTR: 'data-tm-watch-ready',

    // 存储键
    Storage: {
      THEME_MODE: 'tm-youtube-layout-plus-theme-mode',
      HOME_GRID_COLUMNS: 'tm-youtube-layout-plus-home-grid-columns',
    },

    // 主题配置
    THEME_MODES: [
      { mode: 'auto', label: 'Auto', actionName: 'yt-signal-action-toggle-dark-theme-device' },
      { mode: 'light', label: 'Light', actionName: 'yt-signal-action-toggle-dark-theme-off' },
      { mode: 'dark', label: 'Dark', actionName: 'yt-signal-action-toggle-dark-theme-on' },
    ],

    // 布局配置
    Layout: {
      HOME_GRID_COLUMN_OPTIONS: [4, 5],
      HOME_GRID_TRACK_COUNT: 20,
      HOME_MAX_LAYOUT_WIDTH: 3000,
      MAX_LAYOUT_WIDTH: 1300,
      HOME_SIDE_CARDS_STACK_MEDIA: '(max-width: 1340px)',
      HOME_SIDE_CARD_THUMB_DEFAULT: 'clamp(96px, 10vw, 180px)',
      HOME_SIDE_CARD_TEXT_WIDTH_RATIO: 0.52,
      HOME_SIDE_CARD_WIDE_THUMB_CAP: 460,
      HOME_SIDE_CARD_ULTRAWIDE_THUMB_CAP: 520,
    },

    // 定时器配置
    Timing: {
      OBSERVER_APPLY_DEBOUNCE_MS: 150,
      ROUTE_POLL_INTERVAL_MS: 3000,
      WATCH_BOOTSTRAP_DELAYS: [0, 80, 200, 500, 1200],
    },

    // Cookie 位掩码
    PREF_F6_PREF_BIT: 0x80,
    PREF_F6_DARK_BIT: 0x400,
    PREF_F6_LIGHT_BIT: 0x80000,
  };

  // ============================================================================
  // 模块2: 状态管理
  // ============================================================================
  const State = {
    // URL 状态
    currentUrl: location.href,

    // 动画帧
    applyFrame: 0,
    resizeFrame: 0,

    // 定时器
    timers: {
      applyDelay: null,
      route: null,
      resize: null,
      routeTransition: null,
      watchBootstrap: null,
      watchChatState: null,
      themeStatusHide: null,
    },

    // 观察者
    observers: {
      body: null,
      watchFlexyAttr: null,
      watchFlexyObservedElement: null,
    },

    // 布局状态
    layout: {
      lastWatchChatExpanded: null,
      lastEngagementPanelOpen: null,
      lastTheaterMode: null,
      lastPlayerSyncKey: '',
      lastAutoCollapsedHomeUrl: '',
      lastAutoCollapsedWatchChatKey: '',
      watchBootstrapStep: 0,
    },

    // 主题状态
    theme: {
      currentMode: null,
      switchInFlight: false,
      pendingMode: null,
      lastRenderedMode: null,
      lastRenderedDisabled: null,
      lastPersistedMode: null,
    },

    // 网格状态
    grid: {
      currentColumns: 5,
      lastRenderedColumns: null,
    },

    // 缓存
    elementDataCache: new WeakMap(),
  };

  // ============================================================================
  // 模块3: 工具函数
  // ============================================================================
  const Utils = {
    /**
     * 延迟执行
     */
    delay(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    },

    /**
     * 防抖函数
     */
    debounce(fn, ms) {
      let timer = null;
      return function (...args) {
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), ms);
      };
    },

    /**
     * 检查元素是否可见
     */
    isVisible(element) {
      if (!element || element.hidden) return false;
      const style = window.getComputedStyle(element);
      if (style.display === 'none' || style.visibility === 'hidden') return false;
      const rect = element.getBoundingClientRect();
      return rect.width > 0 && rect.height > 0;
    },

    /**
     * 安全获取数值样式
     */
    getNumericStyle(style, property) {
      const value = parseFloat(style.getPropertyValue(property));
      return Number.isFinite(value) ? value : 0;
    },

    /**
     * 从 URL 提取视频 ID
     */
    extractVideoId(value) {
      const text = String(value || '');
      const directMatch = text.match(/(?:\/vi(?:_webp)?\/|[?&]v=)([a-zA-Z0-9_-]{11})/);
      if (directMatch) return directMatch[1];

      try {
        const url = new URL(text, location.origin);
        return url.searchParams.get('v');
      } catch {
        return null;
      }
    },

    /**
     * 从 Cookie 获取主题模式
     */
    getThemeModeFromCookie() {
      const prefEntries = document.cookie
        .split('; ')
        .filter(entry => entry.startsWith('PREF='));
      const lastEntry = prefEntries[prefEntries.length - 1];
      if (!lastEntry) return null;

      try {
        const pref = decodeURIComponent(lastEntry.slice(5));
        const f6Match = pref.match(/(?:^|&)f6=([0-9a-fA-F]+)/);
        if (!f6Match) return null;

        const f6 = parseInt(f6Match[1], 16);
        if (!Number.isFinite(f6)) return null;

        if ((f6 & Constants.PREF_F6_LIGHT_BIT) !== 0) return 'light';
        if ((f6 & Constants.PREF_F6_DARK_BIT) !== 0) return 'dark';
        if ((f6 & Constants.PREF_F6_PREF_BIT) !== 0) return 'auto';
        return null;
      } catch {
        return null;
      }
    },

    /**
     * 从文档推断主题模式
     */
    inferThemeMode() {
      return document.documentElement.hasAttribute('dark') ? 'dark' : 'light';
    },

    /**
     * 获取观察到的主题模式
     */
    getObservedThemeMode() {
      return this.getThemeModeFromCookie() || this.inferThemeMode();
    },
  };

  // ============================================================================
  // 模块4: 存储管理
  // ============================================================================
  const Storage = {
    /**
     * 加载主题模式
     */
    loadThemeMode() {
      try {
        const mode = localStorage.getItem(Constants.Storage.THEME_MODE);
        return Constants.THEME_MODES.some(item => item.mode === mode) ? mode : null;
      } catch {
        return null;
      }
    },

    /**
     * 保存主题模式
     */
    saveThemeMode(mode) {
      if (State.theme.lastPersistedMode === mode) return;
      try {
        if (Constants.THEME_MODES.some(item => item.mode === mode)) {
          localStorage.setItem(Constants.Storage.THEME_MODE, mode);
        } else {
          localStorage.removeItem(Constants.Storage.THEME_MODE);
        }
        State.theme.lastPersistedMode = mode;
      } catch {
        // 忽略存储失败
      }
    },

    /**
     * 加载首页网格列数
     */
    loadHomeGridColumns() {
      try {
        const value = localStorage.getItem(Constants.Storage.HOME_GRID_COLUMNS);
        return this.normalizeGridColumns(value);
      } catch {
        return 5;
      }
    },

    /**
     * 保存首页网格列数
     */
    saveHomeGridColumns(columns) {
      try {
        localStorage.setItem(Constants.Storage.HOME_GRID_COLUMNS, String(this.normalizeGridColumns(columns)));
      } catch {
        // 忽略存储失败
      }
    },

    /**
     * 标准化网格列数
     */
    normalizeGridColumns(value) {
      const columns = Number(value);
      return Constants.Layout.HOME_GRID_COLUMN_OPTIONS.includes(columns) ? columns : 5;
    },
  };

  // ============================================================================
  // 模块5: DOM 查询助手
  // ============================================================================
  const DOM = {
    /**
     * 页面类型判断
     */
    isHomePage() {
      return location.pathname === '/';
    },

    isWatchPage() {
      return location.pathname === '/watch';
    },

    /**
     * 获取观看页面键
     */
    getWatchPageKey() {
      if (!this.isWatchPage()) return location.pathname;
      const params = new URLSearchParams(location.search);
      const videoId = params.get('v');
      return videoId ? `/watch?v=${videoId}` : location.pathname;
    },

    /**
     * 获取页面元素
     */
    getApp() {
      return document.querySelector('ytd-app');
    },

    getWatchFlexy() {
      return document.querySelector('ytd-watch-flexy');
    },

    getRichGrid() {
      return document.querySelector('ytd-rich-grid-renderer');
    },

    getRichGridItems() {
      return Array.from(document.querySelectorAll('#contents.ytd-rich-grid-renderer > ytd-rich-item-renderer'));
    },

    getLogoRenderer() {
      return document.querySelector('ytd-topbar-logo-renderer');
    },

    /**
     * 获取观看预告文本
     */
    getWatchTeaserText() {
      const teaser = document.querySelector('ytd-watch-metadata #teaser-carousel');
      return (teaser?.innerText || teaser?.textContent || '').trim();
    },

    /**
     * 检查直播/回放提示
     */
    hasLiveWatchPrompt(teaserText) {
      return /join the conversation to interact with the creator and others watching this live stream/i.test(teaserText)
        || (/watching now/i.test(document.body.innerText) && /started streaming/i.test(document.body.innerText));
    },

    hasReplayWatchPrompt(teaserText) {
      return /live chat replay/i.test(teaserText)
        || /see what others said about this video while it was live/i.test(teaserText);
    },

    /**
     * 检查侧边聊天
     */
    hasWatchSidebarChat(watchFlexy) {
      if (!watchFlexy) return false;

      if (
        watchFlexy.hasAttribute('is-live') ||
        watchFlexy.hasAttribute('is-live-content') ||
        watchFlexy.hasAttribute('live-chat-collapsed')
      ) {
        return true;
      }

      const liveBadge = watchFlexy.querySelector(
        'ytd-badge-supported-renderer[system-icons][icon="LIVE"], ' +
        'ytd-thumbnail-overlay-time-status-renderer[overlay-style="LIVE"], ' +
        'yt-icon[icon="yt-icons:live"]'
      );
      if (liveBadge && Utils.isVisible(liveBadge)) return true;

      const teaserText = this.getWatchTeaserText();
      if (this.hasLiveWatchPrompt(teaserText)) return true;

      const chatFrame = watchFlexy.querySelector(
        'ytd-live-chat-frame#chat, #chat ytd-live-chat-frame, #chat-container ytd-live-chat-frame'
      );
      const chatHost = chatFrame?.closest('#chat') || watchFlexy.querySelector('#chat, #chat-container');
      const hasStampedChat = watchFlexy.hasAttribute('should-stamp-chat') || !!chatFrame || !!chatHost;

      if (this.hasReplayWatchPrompt(teaserText) && hasStampedChat) return true;
      if (!chatFrame || chatFrame.hasAttribute('hidden')) return false;
      if (chatFrame.hasAttribute('collapsed')) return hasStampedChat;

      return Utils.isVisible(chatFrame) || Utils.isVisible(chatHost);
    },

    /**
     * 检查互动面板
     */
    hasOpenEngagementPanel(watchFlexy) {
      const host = watchFlexy || this.getWatchFlexy();
      if (!host) return false;
      return !!host.querySelector(
        'ytd-engagement-panel-section-list-renderer[visibility="ENGAGEMENT_PANEL_VISIBILITY_EXPANDED"]'
      );
    },

    /**
     * 检查剧院模式
     */
    isTheaterModeActive(watchFlexy) {
      if (!this.isWatchPage()) return false;
      const flexy = watchFlexy || this.getWatchFlexy();
      return !!(flexy && flexy.hasAttribute('theater'));
    },

    /**
     * 检查全屏
     */
    isFullscreenActive() {
      if (document.fullscreenElement) return true;
      const flexy = this.getWatchFlexy();
      return !!(flexy && flexy.hasAttribute('fullscreen'));
    },

    /**
     * 检查是否为 Mix 卡片
     */
    isHomeHeroMixCard(item) {
      if (!item) return false;

      if (item.querySelector('yt-collection-thumbnail-view-model, .ytCollectionThumbnailViewModelHost')) {
        return true;
      }

      const titleElement = item.querySelector('#video-title, yt-formatted-string#video-title, a[title], h3');
      const title = (titleElement?.getAttribute('title') || titleElement?.innerText || titleElement?.textContent || '').trim();

      return /^mix\b/i.test(title);
    },

    /**
     * 获取侧边卡片容器
     */
    getHomeSideCardShell(item) {
      return item.querySelector(
        'ytd-rich-grid-media, yt-lockup-view-model, ytd-ad-slot-renderer, ytd-in-feed-ad-layout-renderer'
      ) || item.querySelector(':scope > #content') || item;
    },

    /**
     * 查找打开面板按钮
     */
    findOpenPanelButton() {
      return Array.from(document.querySelectorAll('button, yt-button-shape button, tp-yt-paper-button')).find(
        button => /open panel/i.test((button.innerText || button.textContent || '').trim())
      ) || null;
    },

    /**
     * 安全获取 iframe 文档
     */
    safeGetIframeDocument(frame) {
      try {
        return frame?.contentDocument || null;
      } catch {
        return null;
      }
    },
  };

  // ============================================================================
  // 模块6: 样式管理
  // ============================================================================
  const StyleManager = {
    /**
     * 确保样式存在
     */
    ensure() {
      let style = document.getElementById(Constants.STYLE_ID);
      if (style?.dataset.version === Constants.STYLE_VERSION) return;

      if (!style) {
        style = document.createElement('style');
        style.id = Constants.STYLE_ID;
        document.head.appendChild(style);
      }

      style.dataset.version = Constants.STYLE_VERSION;
      style.textContent = this.generateCSS();
    },

    /**
     * 生成 CSS
     */
    generateCSS() {
      const { Classes, Layout } = Constants;
      const { HOME_MAX_LAYOUT_WIDTH, MAX_LAYOUT_WIDTH, HOME_SIDE_CARDS_STACK_MEDIA, HOME_SIDE_CARD_THUMB_DEFAULT } = Layout;

      return `
        /* 首页变量 */
        html.tm-youtube-layout-plus-home {
          --tm-guide-collapsed-width: 72px;
          --tm-home-page-gutter: clamp(14px, 2.1vw, 28px);
          --tm-home-available-width: calc(100vw - var(--tm-guide-collapsed-width));
          --tm-home-layout-width: min(${HOME_MAX_LAYOUT_WIDTH}px, var(--tm-home-available-width));
          --tm-hero-mix-object-position: center 82%;
          --tm-card-bg: #f8f9fa;
          --tm-card-border: rgba(15, 15, 15, 0.06);
          --tm-card-shadow: 0 1px 2px rgba(15, 15, 15, 0.04), 0 6px 18px rgba(15, 15, 15, 0.05);
          --tm-text-primary: #0f0f0f;
          --tm-text-secondary: rgba(15, 15, 15, 0.62);
          --tm-meta-secondary: rgba(15, 15, 15, 0.55);
          --tm-chip-bg: rgba(15, 15, 15, 0.05);
          --tm-chip-bg-hover: rgba(15, 15, 15, 0.09);
          --tm-chip-bg-active: #0f0f0f;
          --tm-chip-text: #0f0f0f;
          --tm-chip-text-active: #ffffff;
          --tm-font: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Display',
                     'Segoe UI', 'Helvetica Neue', Roboto, Arial, sans-serif;
        }

        /* 暗色模式变量 */
        html[dark].tm-youtube-layout-plus-home {
          --tm-card-bg: #1f1f1f;
          --tm-card-border: rgba(255, 255, 255, 0.08);
          --tm-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 18px rgba(0, 0, 0, 0.18);
          --tm-text-primary: #f1f1f1;
          --tm-text-secondary: rgba(255, 255, 255, 0.72);
          --tm-meta-secondary: rgba(255, 255, 255, 0.6);
          --tm-chip-bg: rgba(255, 255, 255, 0.08);
          --tm-chip-bg-hover: rgba(255, 255, 255, 0.14);
          --tm-chip-bg-active: #ffffff;
          --tm-chip-text: rgba(255, 255, 255, 0.92);
          --tm-chip-text-active: #0f0f0f;
        }

        /* 隐藏重播提示 */
        .${Classes.REPLAY_HIDE} {
          display: none !important;
        }

        /* 主题切换器样式 */
        #${Constants.THEME_SWITCHER_ID} {
          position: relative;
          display: flex;
          align-items: center;
          gap: 0;
          margin-left: 12px;
          padding: 4px 6px;
          border: 1px solid var(--yt-spec-10-percent-layer, rgba(0, 0, 0, 0.1));
          border-radius: 999px;
          background: var(--yt-spec-badge-chip-background, rgba(0, 0, 0, 0.05));
        }

        #${Constants.THEME_STATUS_ID} {
          position: fixed;
          top: 72px;
          right: 24px;
          z-index: 2200;
          max-width: 320px;
          padding: 10px 14px;
          border: 1px solid rgba(190, 60, 60, 0.28);
          border-radius: 14px;
          background: rgba(126, 28, 28, 0.92);
          color: #fff;
          font: 500 13px/1.4 Roboto, Arial, sans-serif;
          box-shadow: 0 10px 24px rgba(0, 0, 0, 0.24);
          opacity: 0;
          transform: translateY(-6px);
          pointer-events: none;
          transition: opacity 160ms ease, transform 160ms ease;
        }

        #${Constants.THEME_STATUS_ID}[data-visible="true"] {
          opacity: 1;
          transform: translateY(0);
        }

        #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-track {
          display: inline-flex;
          align-items: center;
          gap: 4px;
        }

        #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option {
          display: inline-flex;
          align-items: center;
          justify-content: center;
          min-width: 52px;
          height: 28px;
          padding: 0 10px;
          border: 0;
          border-radius: 999px;
          background: transparent;
          color: var(--yt-spec-text-primary, #0f0f0f);
          cursor: pointer;
          font: 600 12px/1 'Inter', -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
          letter-spacing: 0;
          transition: background 140ms ease, color 140ms ease, box-shadow 140ms ease;
        }

        #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option:hover {
          background: var(--yt-spec-badge-chip-background-hover, rgba(0, 0, 0, 0.08));
        }

        #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option[data-active="true"] {
          background: var(--yt-spec-brand-background-solid, rgba(15, 15, 15, 0.92));
          color: var(--yt-spec-static-brand-white, #fff);
          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
        }

        html[dark] #${Constants.THEME_SWITCHER_ID} {
          border-color: rgba(255, 255, 255, 0.14);
          background: rgba(255, 255, 255, 0.04);
        }

        html[dark] #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option {
          color: rgba(255, 255, 255, 0.92);
        }

        html[dark] #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option[data-active="true"] {
          background: rgba(255, 255, 255, 0.14);
          color: #fff;
          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.32);
        }

        /* 网格切换器样式 */
        #${Constants.HOME_GRID_SWITCHER_ID} {
          position: relative;
          display: inline-flex;
          align-items: center;
          gap: 6px;
          margin-left: 8px;
          padding: 4px 6px;
          border: 1px solid var(--yt-spec-10-percent-layer, rgba(0, 0, 0, 0.1));
          border-radius: 999px;
          background: var(--yt-spec-badge-chip-background, rgba(0, 0, 0, 0.05));
        }

        #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option {
          display: inline-flex;
          align-items: center;
          justify-content: center;
          width: 28px;
          height: 28px;
          border: 0;
          border-radius: 999px;
          background: transparent;
          color: var(--yt-spec-text-primary, #0f0f0f);
          cursor: pointer;
          font: 700 12px/1 'Inter', -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;
          transition: background 140ms ease, color 140ms ease, box-shadow 140ms ease;
        }

        #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option:hover {
          background: var(--yt-spec-badge-chip-background-hover, rgba(0, 0, 0, 0.08));
        }

        #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option[data-active="true"] {
          background: var(--yt-spec-brand-background-solid, rgba(15, 15, 15, 0.92));
          color: var(--yt-spec-static-brand-white, #fff);
          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
        }

        html[dark] #${Constants.HOME_GRID_SWITCHER_ID} {
          border-color: rgba(255, 255, 255, 0.14);
          background: rgba(255, 255, 255, 0.04);
        }

        html[dark] #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option {
          color: rgba(255, 255, 255, 0.92);
        }

        html[dark] #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option[data-active="true"] {
          background: rgba(255, 255, 255, 0.14);
          color: #fff;
          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.32);
        }

        /* 剧院模式下的切换器样式 */
        html.${Classes.WATCH_THEATER} #${Constants.THEME_SWITCHER_ID},
        html.${Classes.WATCH_THEATER} #${Constants.HOME_GRID_SWITCHER_ID} {
          border-color: rgba(255, 255, 255, 0.18) !important;
          background: rgba(255, 255, 255, 0.06) !important;
        }

        html.${Classes.WATCH_THEATER} #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option,
        html.${Classes.WATCH_THEATER} #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option {
          color: rgba(255, 255, 255, 0.92) !important;
        }

        html.${Classes.WATCH_THEATER} #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option:hover,
        html.${Classes.WATCH_THEATER} #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option:hover {
          background: rgba(255, 255, 255, 0.1) !important;
        }

        html.${Classes.WATCH_THEATER} #${Constants.THEME_SWITCHER_ID} .tm-theme-switch-option[data-active="true"],
        html.${Classes.WATCH_THEATER} #${Constants.HOME_GRID_SWITCHER_ID} .tm-home-grid-option[data-active="true"] {
          background: rgba(255, 255, 255, 0.22) !important;
          color: #fff !important;
          box-shadow: 0 1px 2px rgba(0, 0, 0, 0.42) !important;
        }

        /* 首页芯片栏样式 */
        html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) ytd-feed-filter-chip-bar-renderer,
        html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) #chips-wrapper {
          left: var(--tm-guide-collapsed-width) !important;
          width: calc(100vw - var(--tm-guide-collapsed-width)) !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #chips-wrapper {
          top: 66px !important;
        }

        html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) ytd-page-manager {
          margin-left: var(--tm-guide-collapsed-width) !important;
          width: calc(100% - var(--tm-guide-collapsed-width)) !important;
        }

        html.tm-youtube-layout-plus-home ytd-browse {
          overflow: visible !important;
        }

        html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) ytd-two-column-browse-results-renderer {
          margin-left: 0 !important;
          width: 100% !important;
          min-width: 0 !important;
          max-width: 100% !important;
          box-sizing: border-box !important;
        }

        html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) ytd-rich-grid-renderer {
          width: min(100%, var(--tm-home-layout-width)) !important;
          max-width: var(--tm-home-layout-width) !important;
          min-width: 0 !important;
          margin-left: auto !important;
          margin-right: auto !important;
          box-sizing: border-box !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer {
          padding: 20px 24px 6px !important;
          background: transparent !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #chips-wrapper,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #chips {
          align-items: center !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #chips-content {
          position: static !important;
          overflow: visible !important;
          isolation: auto !important;
          padding: 0 !important;
          margin: 0 !important;
          border: 0 !important;
          border-radius: 0 !important;
          background: transparent !important;
          backdrop-filter: none !important;
          -webkit-backdrop-filter: none !important;
          box-shadow: none !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #chips-content::before,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #chips-content::after {
          content: none !important;
          display: none !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer {
          position: relative !important;
          margin: 0 8px 0 0 !important;
          padding: 0 !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer + yt-chip-cloud-chip-renderer::before {
          display: none !important;
          content: none !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer button.ytChipShapeButtonReset {
          border-radius: 999px !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer .ytChipShapeChip {
          position: relative !important;
          min-height: 34px !important;
          padding: 0 14px !important;
          border: 1px solid transparent !important;
          border-radius: 999px !important;
          background: var(--tm-chip-bg) !important;
          color: var(--tm-chip-text) !important;
          font-family: var(--tm-font) !important;
          font-weight: 500 !important;
          letter-spacing: 0 !important;
          backdrop-filter: none !important;
          -webkit-backdrop-filter: none !important;
          box-shadow: none !important;
          transition: background 140ms ease, color 140ms ease !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer .ytChipShapeChip > div {
          font-size: 14px !important;
          line-height: 32px !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer:hover .ytChipShapeChip,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer button:focus-visible .ytChipShapeChip {
          background: var(--tm-chip-bg-hover) !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer[selected] .ytChipShapeChip,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer .ytChipShapeChip.ytChipShapeActive {
          background: var(--tm-chip-bg-active) !important;
          color: var(--tm-chip-text-active) !important;
          border-color: transparent !important;
          box-shadow: none !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer yt-touch-feedback-shape,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer .yt-spec-touch-feedback-shape__stroke,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer yt-chip-cloud-chip-renderer .yt-spec-touch-feedback-shape__fill {
          border-radius: 999px !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #right-arrow.ytd-feed-filter-chip-bar-renderer,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #left-arrow.ytd-feed-filter-chip-bar-renderer {
          top: 0 !important;
          margin-top: 0 !important;
        }

        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #right-arrow button,
        html.tm-youtube-layout-plus-home ytd-feed-filter-chip-bar-renderer #left-arrow button {
          border: 0 !important;
          border-radius: 999px !important;
          background: var(--tm-chip-bg) !important;
          backdrop-filter: none !important;
          -webkit-backdrop-filter: none !important;
          box-shadow: none !important;
          transform: none !important;
        }

        /* 首页网格布局 */
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer {
          display: grid !important;
          grid-template-columns: repeat(20, minmax(0, 1fr)) !important;
          grid-template-rows: repeat(4, minmax(0, 1fr)) !important;
          grid-auto-rows: min-content !important;
          gap: 8px 16px !important;
          width: min(100%, var(--tm-home-layout-width)) !important;
          max-width: var(--tm-home-layout-width) !important;
          margin: 0 auto !important;
          padding: 5px var(--tm-home-page-gutter) 40px var(--tm-home-page-gutter) !important;
          box-sizing: border-box !important;
          font-family: var(--tm-font) !important;
          align-items: stretch !important;
          min-width: 0 !important;
          overflow-x: clip !important;
        }

        html.tm-youtube-layout-plus-home ytd-rich-grid-renderer {
          --ytd-rich-grid-items-per-row: var(--tm-home-grid-items-per-row, 5) !important;
          --ytd-rich-grid-posts-per-row: var(--tm-home-grid-items-per-row, 5) !important;
          width: min(100%, var(--tm-home-layout-width)) !important;
          max-width: var(--tm-home-layout-width) !important;
          min-width: 0 !important;
          margin: -20px auto 0 !important;
          box-sizing: border-box !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer {
          width: auto !important;
          min-width: 0 !important;
          max-width: 100% !important;
          margin: 0 !important;
          padding: 0 !important;
          box-sizing: border-box !important;
          transform-origin: center top !important;
          transition: transform 160ms ease, box-shadow 160ms ease !important;
          will-change: transform !important;
        }

        html.tm-youtube-layout-plus-home ytd-rich-section-renderer,
        html.tm-youtube-layout-plus-home ytd-rich-shelf-renderer,
        html.tm-youtube-layout-plus-home ytd-reel-shelf-renderer {
          display: none !important;
        }

        /* 首页 Hero 布局 */
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) {
          grid-column: 1 / 13 !important;
          grid-row: 1 / span 4 !important;
          align-self: stretch !important;
          height: auto !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) > #content {
          height: auto !important;
          min-height: 0 !important;
          max-height: none !important;
          background: var(--tm-card-bg) !important;
          border: 1px solid var(--tm-card-border) !important;
          border-radius: 20px !important;
          box-shadow: var(--tm-card-shadow) !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) ytd-rich-grid-media,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) yt-lockup-view-model {
          height: auto !important;
          max-height: none !important;
          min-height: 0 !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) ytd-rich-grid-media #dismissible,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) yt-lockup-view-model > div,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytLockupViewModelHost,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .yt-lockup-view-model-wiz {
          display: grid !important;
          grid-template-columns: minmax(0, 1fr) !important;
          grid-template-rows: auto auto !important;
          gap: 10px !important;
          align-items: stretch !important;
          height: auto !important;
          min-height: 0 !important;
          max-height: none !important;
          overflow: visible !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) ytd-thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) #thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) yt-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) yt-collection-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytCollectionThumbnailViewModelHost,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytLockupViewModelContentImage,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .yt-lockup-view-model-wiz__content-image {
          grid-column: 1 !important;
          grid-row: 1 !important;
          width: 100% !important;
          max-width: 100% !important;
          height: auto !important;
          min-height: 0 !important;
          max-height: none !important;
          aspect-ratio: 16 / 9 !important;
          margin: 0 !important;
          border-radius: 18px !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) ytd-thumbnail a,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) #thumbnail a,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) ytd-thumbnail img,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) #thumbnail img,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) yt-thumbnail-view-model a,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) yt-thumbnail-view-model img,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) .ytLockupViewModelContentImage > *,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) .ytLockupViewModelContentImage img,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) .yt-lockup-view-model-wiz__content-image a,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:not(.${Classes.HERO_MIX}):nth-of-type(1) .yt-lockup-view-model-wiz__content-image img {
          width: 100% !important;
          height: 100% !important;
          object-fit: cover !important;
          object-position: var(--tm-hero-mix-object-position) !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) ytd-thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) #thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) yt-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) yt-collection-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) .ytCollectionThumbnailViewModelHost,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) .ytLockupViewModelContentImage,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) .yt-lockup-view-model-wiz__content-image {
          aspect-ratio: auto !important;
          overflow: visible !important;
          border-radius: 0 !important;
          margin-top: 12px !important;
          margin-left: 0 !important;
          margin-right: 0 !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) yt-collection-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer.${Classes.HERO_MIX}:nth-of-type(1) .ytCollectionThumbnailViewModelHost {
          width: 100% !important;
          height: auto !important;
          max-width: none !important;
          max-height: none !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) #details,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytLockupViewModelMetadata,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .yt-lockup-view-model-wiz__metadata,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) yt-lockup-metadata-view-model {
          grid-column: 1 !important;
          grid-row: 2 !important;
          display: block !important;
          min-width: 0 !important;
          width: 100% !important;
          max-width: 100% !important;
          min-height: 0 !important;
          margin: 0 !important;
          padding: 2px 10px 6px !important;
          background: transparent !important;
          box-sizing: border-box !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) yt-lockup-metadata-view-model {
          display: grid !important;
          grid-template-columns: auto minmax(0, 1fr) auto !important;
          grid-template-rows: auto auto !important;
          column-gap: 12px !important;
          row-gap: 2px !important;
          align-items: start !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytLockupMetadataViewModelTextContainer {
          grid-column: 2 !important;
          grid-row: 1 / span 2 !important;
          min-width: 0 !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytLockupMetadataViewModelAvatar {
          grid-column: 1 !important;
          grid-row: 1 / span 2 !important;
          align-self: start !important;
          margin: 0 !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) .ytLockupMetadataViewModelMenuButton {
          grid-column: 3 !important;
          grid-row: 1 / span 2 !important;
          align-self: start !important;
          margin-top: -4px !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) #details::after {
          content: none !important;
          display: none !important;
        }

        /* 侧边卡片布局 */
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(2) { grid-column: 13 / 21 !important; grid-row: 1 !important; }
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(3) { grid-column: 13 / 21 !important; grid-row: 2 !important; }
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(4) { grid-column: 13 / 21 !important; grid-row: 3 !important; }
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(5) { grid-column: 13 / 21 !important; grid-row: 4 !important; }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) {
          position: relative !important;
          align-self: stretch !important;
          height: 100% !important;
          min-height: 0 !important;
          padding: 0 !important;
          margin: 0 !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) > #content {
          position: absolute !important;
          top: 0 !important;
          left: 0 !important;
          right: 0 !important;
          bottom: 0 !important;
          width: 100% !important;
          height: 100% !important;
          min-height: 0 !important;
          margin: 0 !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-rich-grid-media,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model > div,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-ad-slot-renderer,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer {
          height: 100% !important;
          min-height: 0 !important;
          margin: 0 !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-rich-grid-media,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-ad-slot-renderer,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer {
          background: var(--tm-card-bg) !important;
          border: 1px solid var(--tm-card-border) !important;
          border-radius: 16px !important;
          padding: 12px !important;
          box-shadow: var(--tm-card-shadow) !important;
          box-sizing: border-box !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-rich-grid-media #dismissible,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelHost,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model > div,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-ad-slot-renderer #dismissible,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #dismissible,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer > div {
          display: flex !important;
          flex-direction: row !important;
          gap: 12px !important;
          align-items: center !important;
          height: 100% !important;
          min-height: 0 !important;
          background: transparent !important;
          border: 0 !important;
          border-radius: 0 !important;
          padding: 0 !important;
          box-shadow: none !important;
          box-sizing: border-box !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-collection-thumbnail-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytCollectionThumbnailViewModelHost,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelContentImage,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__content-image,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__content,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #thumbnail {
          grid-column: 1 !important;
          grid-row: 1 !important;
          width: var(--tm-side-card-thumb-width, ${HOME_SIDE_CARD_THUMB_DEFAULT}) !important;
          min-width: var(--tm-side-card-thumb-width, 96px) !important;
          max-width: var(--tm-side-card-thumb-width, 180px) !important;
          flex: 0 0 var(--tm-side-card-thumb-width, ${HOME_SIDE_CARD_THUMB_DEFAULT}) !important;
          aspect-ratio: 16 / 9 !important;
          height: auto !important;
          align-self: center !important;
          margin: 0 !important;
          border-radius: 12px !important;
          overflow: hidden !important;
          box-sizing: border-box !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #avatar-link,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #avatar,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #avatar-container,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #channel-thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-channel-name yt-img-shadow {
          display: none !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #details,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #meta,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelMetadata,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__metadata,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-metadata-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #details,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #meta {
          padding: 0 !important;
          margin: 0 !important;
          min-width: 0 !important;
          max-width: 100% !important;
          grid-column: 2 !important;
          grid-row: 1 !important;
          flex: 1 1 auto !important;
          display: flex !important;
          flex-direction: column !important;
          justify-content: center !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #video-title,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-formatted-string#video-title,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__title,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) h3,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__title yt-core-attributed-string,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__title .yt-core-attributed-string,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__title yt-formatted-string {
          --yt-core-attributed-string-font-size: clamp(10px, 0.7vw, 12px) !important;
          --yt-core-attributed-string-line-height: 1.3 !important;
          --yt-endpoint-font-size: clamp(12px, 0.8vw, 14px) !important;
          font-family: var(--tm-font) !important;
          font-size: clamp(10px, 0.8vw, 12px) !important;
          font-weight: 700 !important;
          line-height: 1.3 !important;
          letter-spacing: 0 !important;
          margin: 0 0 4px 0 !important;
          color: var(--tm-text-primary) !important;
          display: -webkit-box !important;
          -webkit-line-clamp: 2 !important;
          -webkit-box-orient: vertical !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-channel-name #text,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-channel-name a,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #metadata-line,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #metadata-line span,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-metadata-view-model-wiz__text-block,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-metadata-view-model-wiz__text-block yt-core-attributed-string,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-metadata-view-model-wiz__text-block .yt-core-attributed-string,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-metadata-view-model-wiz__text-block yt-formatted-string,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-content-metadata-view-model,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-content-metadata-view-model span {
          --yt-core-attributed-string-font-size: clamp(10px, 0.7vw, 12px) !important;
          --yt-core-attributed-string-line-height: 1.35 !important;
          --yt-endpoint-font-size: clamp(10px, 0.7vw, 12px) !important;
          font-family: var(--tm-font) !important;
          font-size: clamp(10px, 0.7vw, 12px) !important;
          line-height: 1.35 !important;
          color: var(--tm-meta-secondary) !important;
        }

        /* 常规网格布局 */
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) {
          grid-column: span var(--tm-home-grid-card-span, 4) !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) ytd-thumbnail,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) #thumbnail {
          border-radius: 12px !important;
          overflow: hidden !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) #video-title,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) yt-formatted-string#video-title {
          font-family: var(--tm-font) !important;
          font-weight: 600 !important;
          letter-spacing: 0 !important;
          color: var(--tm-text-primary) !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) ytd-channel-name #text,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) #metadata-line {
          font-family: var(--tm-font) !important;
          color: var(--tm-meta-secondary) !important;
        }

        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:hover,
        html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:focus-within {
          transform: translateY(-2px) !important;
          z-index: 4 !important;
        }

        /* 响应式布局 */
        @media ${HOME_SIDE_CARDS_STACK_MEDIA} {
          html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) ytd-rich-grid-renderer,
          html.tm-youtube-layout-plus-home ytd-app[mini-guide-visible]:not([guide-persistent-and-visible]) #contents.ytd-rich-grid-renderer {
            width: min(100%, var(--tm-home-available-width)) !important;
            max-width: var(--tm-home-available-width) !important;
            min-width: 0 !important;
            box-sizing: border-box !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer {
            grid-template-rows: auto !important;
            align-items: start !important;
            width: 100% !important;
            min-width: 0 !important;
            max-width: 100% !important;
            overflow-x: clip !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1) {
            grid-column: 1 / 21 !important;
            grid-row: auto !important;
            align-self: start !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(2),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(3),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(4),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(5) {
            grid-column: 1 / 21 !important;
            grid-row: auto !important;
            align-self: start !important;
            height: auto !important;
            width: 100% !important;
            min-width: 0 !important;
            max-width: 100% !important;
            overflow: hidden !important;
            box-sizing: border-box !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) > #content {
            position: relative !important;
            width: 100% !important;
            min-width: 0 !important;
            max-width: 100% !important;
            height: auto !important;
            overflow: hidden !important;
            box-sizing: border-box !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-rich-grid-media,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model > div,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-ad-slot-renderer,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer {
            width: 100% !important;
            min-width: 0 !important;
            max-width: 100% !important;
            height: auto !important;
            box-sizing: border-box !important;
            overflow: hidden !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-rich-grid-media #dismissible,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelHost,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-view-model > div,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-ad-slot-renderer #dismissible,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #dismissible,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer > div {
            width: 100% !important;
            min-width: 0 !important;
            max-width: 100% !important;
            height: auto !important;
            overflow: hidden !important;
            box-sizing: border-box !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-thumbnail,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #thumbnail,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-thumbnail-view-model,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-collection-thumbnail-view-model,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytCollectionThumbnailViewModelHost,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelContentImage,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__content-image,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__content,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #thumbnail {
            width: clamp(128px, 22vw, 220px) !important;
            min-width: 0 !important;
            max-width: 220px !important;
            flex: 0 1 clamp(128px, 22vw, 220px) !important;
            box-sizing: border-box !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #details,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #meta,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelMetadata,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__metadata,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-lockup-metadata-view-model,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #details,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #meta,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupMetadataViewModelTextContainer,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-metadata-view-model-wiz__text-block,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-content-metadata-view-model {
            min-width: 0 !important;
            max-width: 100% !important;
            overflow: hidden !important;
            box-sizing: border-box !important;
          }
        }

        @media (max-width: 760px) {
          html.tm-youtube-layout-plus-home {
            --tm-home-page-gutter: 14px;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer {
            padding: 12px var(--tm-home-page-gutter) 32px var(--tm-home-page-gutter) !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(1),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(2),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(3),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(4),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(5),
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+6) {
            grid-column: 1 / 21 !important;
            grid-row: auto !important;
          }

          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-thumbnail,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) #thumbnail,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-thumbnail-view-model,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) yt-collection-thumbnail-view-model,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytCollectionThumbnailViewModelHost,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .ytLockupViewModelContentImage,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__content-image,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) .yt-lockup-view-model-wiz__content,
          html.tm-youtube-layout-plus-home #contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5) ytd-in-feed-ad-layout-renderer #thumbnail {
            width: clamp(108px, 34vw, 160px) !important;
            flex: 0 1 clamp(108px, 34vw, 160px) !important;
          }
        }

        /* 观看页面变量 */
        html.tm-youtube-layout-plus-watch,
        html.${Classes.ROUTE_TRANSITION} {
          --tm-watch-edge-gutter: clamp(16px, 2.4vw, 40px);
          --tm-watch-content-width: min(${MAX_LAYOUT_WIDTH}px, calc(100vw - var(--tm-watch-edge-gutter) - var(--tm-watch-edge-gutter)));
          --tm-watch-vertical-content-width: min(760px, var(--tm-watch-content-width));
          --tm-watch-vertical-player-width: min(460px, var(--tm-watch-content-width));
        }

        html.tm-youtube-layout-plus-watch,
        html.tm-youtube-layout-plus-watch body,
        html.tm-youtube-layout-plus-watch ytd-app,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy #columns,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy #primary,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy #primary-inner,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy #below {
          overflow-x: hidden !important;
          overscroll-behavior-x: none !important;
          max-width: 100% !important;
        }

        html.tm-youtube-layout-plus-watch ytd-watch-flexy[fullscreen],
        html.tm-youtube-layout-plus-watch ytd-watch-flexy[fullscreen] #columns,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy[fullscreen] #primary,
        html.tm-youtube-layout-plus-watch ytd-watch-flexy[fullscreen] #primary-inner {
          overflow-x: visible !important;
          max-width: none !important;
        }

        /* 隐藏推荐侧边栏 */
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat)
          ytd-watch-flexy #related,
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat)
          ytd-watch-next-secondary-results-renderer,
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat)
          ytd-playlist-panel-renderer,
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat)
          yt-playlist-panel-renderer,
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat)
          ytd-radio-renderer,
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat)
          ytd-compact-radio-renderer {
          display: none !important;
        }

        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy #related,
        html.${Classes.ROUTE_TRANSITION} ytd-watch-next-secondary-results-renderer,
        html.${Classes.ROUTE_TRANSITION} ytd-playlist-panel-renderer,
        html.${Classes.ROUTE_TRANSITION} yt-playlist-panel-renderer,
        html.${Classes.ROUTE_TRANSITION} ytd-radio-renderer,
        html.${Classes.ROUTE_TRANSITION} ytd-compact-radio-renderer,
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy :is(#secondary, #secondary-inner) {
          display: none !important;
        }

        html.${Classes.ROUTE_TRANSITION} ytd-mini-guide-renderer,
        html.${Classes.ROUTE_TRANSITION} tp-yt-app-drawer#guide {
          display: none !important;
        }

        html.${Classes.ROUTE_TRANSITION} ytd-page-manager {
          margin-left: 0 !important;
          width: 100% !important;
        }

        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy :is(
          ytd-watch-metadata,
          #above-the-fold,
          #bottom-row,
          #below,
          #comments,
          #teaser-carousel,
          ytd-comments,
          ytd-comment-thread-renderer
        ) {
          visibility: hidden !important;
          pointer-events: none !important;
        }

        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) :is(#secondary, #secondary-inner) {
          display: none !important;
        }

        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) #primary,
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) #primary {
          max-width: none !important;
          width: var(--tm-watch-content-width) !important;
          margin-left: auto !important;
          margin-right: auto !important;
          box-sizing: border-box !important;
        }

        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) #columns,
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) #columns {
          display: block !important;
          width: 100% !important;
          max-width: 100% !important;
          margin-left: 0 !important;
          margin-right: 0 !important;
        }

        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) :is(#primary-inner, #above-the-fold, #below, ytd-watch-metadata, #comments),
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) :is(#primary-inner, #above-the-fold, #below, ytd-watch-metadata, #comments) {
          width: var(--tm-watch-content-width) !important;
          max-width: var(--tm-watch-content-width) !important;
          min-width: 0 !important;
          margin-left: auto !important;
          margin-right: auto !important;
          box-sizing: border-box !important;
        }

        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) :is(#player-theater-container, #player-full-bleed-container, #player-container-outer),
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) :is(#player-theater-container, #player-full-bleed-container, #player-container-outer) {
          width: var(--tm-watch-content-width) !important;
          max-width: var(--tm-watch-content-width) !important;
          min-width: 0 !important;
          margin-left: auto !important;
          margin-right: auto !important;
          box-sizing: border-box !important;
        }

        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) :is(#player-container-inner, #player-container, #player, #player-api, #movie_player, .html5-video-player),
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) :is(#player-container-inner, #player-container, #player, #player-api, #movie_player, .html5-video-player) {
          width: 100% !important;
          max-width: 100% !important;
          min-width: 0 !important;
          margin-left: 0 !important;
          margin-right: 0 !important;
          box-sizing: border-box !important;
        }

        /* 竖屏视频布局 */
        html.${Classes.WATCH_VERTICAL}:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) :is(#primary, #primary-inner, #above-the-fold, #below, ytd-watch-metadata, #comments),
        html.${Classes.WATCH_VERTICAL}.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) :is(#primary, #primary-inner, #above-the-fold, #below, ytd-watch-metadata, #comments) {
          width: var(--tm-watch-vertical-content-width) !important;
          max-width: var(--tm-watch-vertical-content-width) !important;
          margin-left: auto !important;
          margin-right: auto !important;
        }

        html.${Classes.WATCH_VERTICAL}:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not(.${Classes.WATCH_PANEL_OPEN})
          ytd-watch-flexy:not([fullscreen]) :is(#player-theater-container, #player-full-bleed-container, #player-container-outer),
        html.${Classes.WATCH_VERTICAL}.${Classes.ROUTE_TRANSITION} ytd-watch-flexy:not([fullscreen]) :is(#player-theater-container, #player-full-bleed-container, #player-container-outer) {
          width: var(--tm-watch-vertical-player-width) !important;
          max-width: var(--tm-watch-vertical-player-width) !important;
          min-width: 0 !important;
          margin-left: auto !important;
          margin-right: auto !important;
        }

        /* 路由过渡锁定 */
        html.${Classes.ROUTE_TRANSITION} ytd-watch-flexy [data-tm-watch-transition-lock="true"] {
          position: fixed !important;
          top: var(--tm-watch-transition-player-top, auto) !important;
          left: var(--tm-watch-transition-player-left, auto) !important;
          width: var(--tm-watch-transition-player-width, var(--tm-watch-content-width)) !important;
          height: var(--tm-watch-transition-player-height, auto) !important;
          max-width: none !important;
          min-width: 0 !important;
          margin: 0 !important;
          z-index: 2 !important;
          box-sizing: border-box !important;
          overflow: hidden !important;
        }

        /* 隐藏未准备好的内容 */
        html:is(.tm-youtube-layout-plus-watch-plain, .tm-youtube-layout-plus-watch-chat-collapsed):not([${Constants.WATCH_READY_ATTR}])
          ytd-watch-flexy:not([fullscreen]) :is(#below, ytd-watch-metadata, #comments) {
          visibility: hidden !important;
        }
      `;
    },
  };

  // ============================================================================
  // 模块7: 首页布局管理
  // ============================================================================
  const HomeLayout = {
    /**
     * 应用首页布局
     */
    apply() {
      const richGrid = DOM.getRichGrid();
      if (!richGrid) {
        this.setLayoutClasses([]);
        return;
      }

      this.setLayoutClasses(['tm-youtube-layout-plus-home']);
      this.applyGridColumns();
      this.applyHeroInlineLayout();

      if (State.layout.lastAutoCollapsedHomeUrl !== location.href) {
        this.collapseGuide();
        State.layout.lastAutoCollapsedHomeUrl = location.href;
      }
    },

    /**
     * 设置布局类名
     */
    setLayoutClasses(targetClasses) {
      const target = new Set(targetClasses);
      const root = document.documentElement;
      for (const cls of Constants.Classes.LAYOUT_MODES) {
        const shouldHave = target.has(cls);
        const hasIt = root.classList.contains(cls);
        if (shouldHave && !hasIt) root.classList.add(cls);
        else if (!shouldHave && hasIt) root.classList.remove(cls);
      }
    },

    /**
     * 应用网格列数
     */
    applyGridColumns() {
      const columns = Storage.normalizeGridColumns(State.grid.currentColumns);
      document.documentElement.style.setProperty('--tm-home-grid-items-per-row', String(columns));
      document.documentElement.style.setProperty('--tm-home-grid-card-span', String(Constants.Layout.HOME_GRID_TRACK_COUNT / columns));
    },

    /**
     * 应用 Hero 内联布局
     */
    applyHeroInlineLayout() {
      const items = DOM.getRichGridItems();
      if (items.length < 5) return;

      const stackSideCards = window.matchMedia(Constants.Layout.HOME_SIDE_CARDS_STACK_MEDIA).matches;
      const heroIsMix = DOM.isHomeHeroMixCard(items[0]);

      items[0].classList.toggle(Constants.Classes.HERO_MIX, heroIsMix);
      items[0].style.setProperty('grid-column', stackSideCards ? '1 / 21' : '1 / 13', 'important');
      items[0].style.setProperty('grid-row', stackSideCards ? 'auto' : '1 / span 4', 'important');

      for (let i = 1; i < 5; i++) {
        items[i].style.setProperty('grid-column', stackSideCards ? '1 / 21' : '13 / 21', 'important');
        items[i].style.setProperty('grid-row', stackSideCards ? 'auto' : String(i), 'important');
      }

      this.upgradeHeroThumbnail();
      this.scheduleSideCardThumbnailFit();
    },

    /**
     * 升级 Hero 缩略图
     */
    upgradeHeroThumbnail() {
      const item = document.querySelector('#contents.ytd-rich-grid-renderer > ytd-rich-item-renderer');
      if (!item) return;

      const heroIsMix = DOM.isHomeHeroMixCard(item);
      item.classList.toggle(Constants.Classes.HERO_MIX, heroIsMix);

      const link = item.querySelector('a#thumbnail[href], a[href*="/watch?v="]');
      const img = item.querySelector('img[src*="ytimg.com"]');
      const videoId = Utils.extractVideoId(link?.href) || Utils.extractVideoId(img?.src);
      if (!videoId) return;

      const images = Array.from(item.querySelectorAll('img[src*="ytimg.com"], img'));
      if (!images.length) return;

      const key = `${heroIsMix ? 'mix' : 'video'}:${videoId}`;
      const currentThumbUrl = item.dataset.tmHeroThumbUrl || '';

      if (
        item.dataset.tmHeroThumbKey === key &&
        currentThumbUrl &&
        images.some(img => img.src === currentThumbUrl || img.srcset.includes(currentThumbUrl))
      ) {
        return;
      }

      const candidates = heroIsMix
        ? [
          `https://i.ytimg.com/vi_webp/${videoId}/maxresdefault.webp`,
          `https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg`,
          `https://i.ytimg.com/vi_webp/${videoId}/hq720.webp`,
          `https://i.ytimg.com/vi/${videoId}/hq720.jpg`,
          `https://i.ytimg.com/vi_webp/${videoId}/sddefault.webp`,
          `https://i.ytimg.com/vi/${videoId}/sddefault.jpg`,
          `https://i.ytimg.com/vi_webp/${videoId}/hqdefault.webp`,
          `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`,
        ]
        : [
          `https://i.ytimg.com/vi/${videoId}/maxresdefault.jpg`,
          `https://i.ytimg.com/vi/${videoId}/hq720.jpg`,
          `https://i.ytimg.com/vi/${videoId}/sddefault.jpg`,
          `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`,
        ];

      const minimumWidth = heroIsMix ? 320 : 640;

      const applyCandidate = (url, width) => {
        item.dataset.tmHeroThumbKey = key;
        item.dataset.tmHeroThumbUrl = url;
        for (const image of images) {
          image.src = url;
          image.srcset = `${url} ${width || 1280}w`;
          image.sizes = '(min-width: 1180px) 60vw, 100vw';
          image.loading = 'eager';
          image.fetchPriority = 'high';
          image.decoding = 'async';
        }
      };

      const tryCandidate = (index = 0) => {
        const url = candidates[index];
        if (!url) return;

        const probe = new Image();
        probe.onload = () => {
          if (probe.naturalWidth >= minimumWidth || index === candidates.length - 1) {
            applyCandidate(url, probe.naturalWidth);
          } else {
            tryCandidate(index + 1);
          }
        };
        probe.onerror = () => tryCandidate(index + 1);
        probe.src = url;
      };

      tryCandidate();
    },

    /**
     * 计算侧边卡片缩略图宽度
     */
    calculateSideCardThumbnailWidth(cardShell) {
      const rect = cardShell.getBoundingClientRect();
      if (rect.width <= 0 || rect.height <= 0) return null;

      const style = window.getComputedStyle(cardShell);
      const hPadding = Utils.getNumericStyle(style, 'padding-left') + Utils.getNumericStyle(style, 'padding-right');
      const vPadding = Utils.getNumericStyle(style, 'padding-top') + Utils.getNumericStyle(style, 'padding-bottom');

      const availableHeight = Math.max(54, rect.height - vPadding - 2);
      const availableWidth = Math.max(160, rect.width - hPadding - 2);
      const widthByHeight = availableHeight * (16 / 9);
      const widthByTextReserve = availableWidth * (1 - Constants.Layout.HOME_SIDE_CARD_TEXT_WIDTH_RATIO);
      const widthCap = window.innerWidth >= 1900
        ? Constants.Layout.HOME_SIDE_CARD_ULTRAWIDE_THUMB_CAP
        : Constants.Layout.HOME_SIDE_CARD_WIDE_THUMB_CAP;
      const minimumWidth = Math.min(180, Math.max(120, availableWidth * 0.22));

      return Math.round(Math.max(minimumWidth, Math.min(widthByHeight, widthByTextReserve, widthCap)));
    },

    /**
     * 应用侧边卡片缩略图适配
     */
    applySideCardThumbnailFit() {
      if (!DOM.isHomePage()) {
        this.clearSideCardThumbnailFit();
        return;
      }

      const items = Array.from(document.querySelectorAll(
        '#contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5)'
      ));
      if (!items.length) return;

      if (window.matchMedia(Constants.Layout.HOME_SIDE_CARDS_STACK_MEDIA).matches) {
        this.clearSideCardThumbnailFit(items);
        return;
      }

      for (const item of items) {
        const cardShell = DOM.getHomeSideCardShell(item);
        const width = this.calculateSideCardThumbnailWidth(cardShell);
        if (width) {
          item.style.setProperty('--tm-side-card-thumb-width', `${width}px`);
        }
      }
    },

    /**
     * 清除侧边卡片缩略图适配
     */
    clearSideCardThumbnailFit(items) {
      const targetItems = items || Array.from(document.querySelectorAll(
        '#contents.ytd-rich-grid-renderer > ytd-rich-item-renderer:nth-of-type(n+2):nth-of-type(-n+5)'
      ));
      for (const item of targetItems) {
        item.style.removeProperty('--tm-side-card-thumb-width');
      }
    },

    /**
     * 调度侧边卡片缩略图适配
     */
    scheduleSideCardThumbnailFit() {
      if (!DOM.isHomePage()) return;
      requestAnimationFrame(() => {
        this.applySideCardThumbnailFit();
        requestAnimationFrame(() => this.applySideCardThumbnailFit());
      });
    },

    /**
     * 折叠侧边栏
     */
    collapseGuide() {
      const app = DOM.getApp();
      if (app) {
        app.removeAttribute('guide-persistent-and-visible');
        app.setAttribute('mini-guide-visible', '');
      }

      const drawer = document.querySelector('tp-yt-app-drawer#guide');
      if (drawer) {
        drawer.removeAttribute('opened');
        drawer.style.width = '';
        drawer.style.minWidth = '';
        drawer.style.visibility = '';
      }

      const guideRenderer = document.querySelector('ytd-guide-renderer');
      if (guideRenderer) {
        guideRenderer.style.display = '';
        guideRenderer.style.width = '';
        guideRenderer.style.minWidth = '';
      }
    },
  };

  // ============================================================================
  // 模块8: 观看页面布局管理
  // ============================================================================
  const WatchLayout = {
    /**
     * 应用观看页面布局
     */
    apply() {
      const watchFlexy = DOM.getWatchFlexy();
      if (!watchFlexy) {
        HomeLayout.setLayoutClasses([]);
        this.resetState();
        return;
      }

      this.syncPlayerSize();
      this.attachObservers();
      this.updateEngagementPanelState(watchFlexy);
      this.updateTheaterModeState(watchFlexy);

      if (DOM.hasWatchSidebarChat(watchFlexy)) {
        HomeLayout.setLayoutClasses([
          'tm-youtube-layout-plus-watch',
          'tm-youtube-layout-plus-watch-chat',
        ]);
        this.updateChatPanelState(watchFlexy);
        this.autoCollapseLiveChatPanel(watchFlexy);
        return;
      }

      HomeLayout.setLayoutClasses([
        'tm-youtube-layout-plus-watch',
        'tm-youtube-layout-plus-watch-plain',
      ]);
      this.hideReplayPrompt();
    },

    /**
     * 重置状态
     */
    resetState({ clearSizing = true, preserveTransitionLayout = false } = {}) {
      const root = document.documentElement;

      State.layout.lastWatchChatExpanded = null;
      State.layout.lastEngagementPanelOpen = null;
      State.layout.lastTheaterMode = null;
      State.layout.lastPlayerSyncKey = '';

      root.removeAttribute(Constants.WATCH_READY_ATTR);
      root.classList.remove(
        Constants.Classes.WATCH_PANEL_OPEN,
        Constants.Classes.WATCH_THEATER,
        Constants.Classes.WATCH_CHAT_OPEN,
        Constants.Classes.WATCH_CHAT_COLLAPSED
      );

      if (!preserveTransitionLayout) {
        root.classList.remove(Constants.Classes.WATCH_VERTICAL);
      }

      if (clearSizing) {
        root.style.removeProperty('--tm-watch-content-width');
        root.style.removeProperty('--tm-watch-vertical-player-width');
        this.clearRouteTransitionPlayerLock();
      }
    },

    /**
     * 更新视频方向
     */
    updateVideoOrientation() {
      if (!DOM.isWatchPage()) {
        document.documentElement.classList.remove(Constants.Classes.WATCH_VERTICAL);
        return false;
      }

      const video = document.querySelector(
        '#movie_player video.html5-main-video, .html5-video-player video.html5-main-video, video.html5-main-video'
      );
      if (!video) {
        document.documentElement.classList.remove(Constants.Classes.WATCH_VERTICAL);
        return false;
      }

      if (video.dataset.tmYlpOrientationListener !== '1') {
        const resync = () => {
          this.updateVideoOrientation();
          this.syncPlayerSize();
        };
        video.addEventListener('loadedmetadata', resync, { passive: true });
        video.addEventListener('resize', resync, { passive: true });
        video.dataset.tmYlpOrientationListener = '1';
      }

      const width = Number(video.videoWidth) || 0;
      const height = Number(video.videoHeight) || 0;
      const isVertical = width > 0 && height > 0 && height / width >= 1.12;
      document.documentElement.classList.toggle(Constants.Classes.WATCH_VERTICAL, isVertical);
      return isVertical;
    },

    /**
     * 同步播放器尺寸
     */
    syncPlayerSize() {
      if (!DOM.isWatchPage()) {
        this.resetState();
        return;
      }

      const isVertical = this.updateVideoOrientation();
      const gutter = Math.min(40, Math.max(16, window.innerWidth * 0.024));
      const width = Math.min(Constants.Layout.MAX_LAYOUT_WIDTH, Math.max(320, Math.round(window.innerWidth - gutter * 2)));
      const verticalPlayerWidth = Math.min(460, width);
      const key = `${width}:${verticalPlayerWidth}:${isVertical ? 'v' : 'h'}`;

      if (State.layout.lastPlayerSyncKey === key) {
        if (!document.documentElement.hasAttribute(Constants.WATCH_READY_ATTR)) {
          document.documentElement.setAttribute(Constants.WATCH_READY_ATTR, '1');
        }
        return;
      }

      State.layout.lastPlayerSyncKey = key;
      document.documentElement.style.setProperty('--tm-watch-content-width', `${width}px`);
      document.documentElement.style.setProperty('--tm-watch-vertical-player-width', `${verticalPlayerWidth}px`);
      document.documentElement.setAttribute(Constants.WATCH_READY_ATTR, '1');
    },

    /**
     * 附加观察者
     */
    attachObservers() {
      if (!DOM.isWatchPage()) {
        this.detachObservers();
        return;
      }

      const watchFlexy = DOM.getWatchFlexy();
      if (watchFlexy && watchFlexy !== State.observers.watchFlexyObservedElement) {
        State.observers.watchFlexyAttr?.disconnect();
        State.observers.watchFlexyAttr = new MutationObserver(() => {
          const flexy = DOM.getWatchFlexy();
          if (!flexy) return;
          this.syncPlayerSize();
          this.updateTheaterModeState(flexy);
          this.updateEngagementPanelState(flexy);
          if (document.documentElement.classList.contains('tm-youtube-layout-plus-watch-chat')) {
            this.updateChatPanelState(flexy);
          }
        });

        try {
          State.observers.watchFlexyAttr.observe(watchFlexy, {
            attributes: true,
            attributeFilter: [
              'theater', 'is-two-columns_', 'live-chat-collapsed',
              'is-live', 'is-live-content', 'fullscreen', 'hidden',
            ],
          });
          State.observers.watchFlexyObservedElement = watchFlexy;
        } catch {
          State.observers.watchFlexyObservedElement = null;
        }
      }
    },

    /**
     * 分离观察者
     */
    detachObservers() {
      State.observers.watchFlexyAttr?.disconnect();
      State.observers.watchFlexyAttr = null;
      State.observers.watchFlexyObservedElement = null;
    },

    /**
     * 更新互动面板状态
     */
    updateEngagementPanelState(watchFlexy) {
      const open = DOM.isWatchPage() && DOM.hasOpenEngagementPanel(watchFlexy);
      document.documentElement.classList.toggle(Constants.Classes.WATCH_PANEL_OPEN, open);
      State.layout.lastEngagementPanelOpen = open;
    },

    /**
     * 更新剧院模式状态
     */
    updateTheaterModeState(watchFlexy) {
      const inTheater = DOM.isTheaterModeActive(watchFlexy);
      document.documentElement.classList.toggle(Constants.Classes.WATCH_THEATER, inTheater);
      State.layout.lastTheaterMode = inTheater;
    },

    /**
     * 更新聊天面板状态
     */
    updateChatPanelState(watchFlexy) {
      const chatFrame = watchFlexy.querySelector('ytd-live-chat-frame#chat');
      const openPanelButton = DOM.findOpenPanelButton();
      const chatVisible = !!chatFrame && Utils.isVisible(chatFrame);
      const panelExpanded = chatVisible || !!(openPanelButton && openPanelButton.disabled);

      document.documentElement.classList.toggle(Constants.Classes.WATCH_CHAT_OPEN, panelExpanded);
      document.documentElement.classList.toggle(Constants.Classes.WATCH_CHAT_COLLAPSED, !panelExpanded);
      State.layout.lastWatchChatExpanded = panelExpanded;
    },

    /**
     * 停止聊天状态同步
     */
    stopChatStateSync() {
      if (!State.timers.watchChatState) return;
      clearInterval(State.timers.watchChatState);
      State.timers.watchChatState = null;
    },

    /**
     * 启动聊天状态同步
     */
    startChatStateSync() {
      this.stopChatStateSync();
      if (!DOM.isWatchPage()) return;

      State.timers.watchChatState = setInterval(() => {
        if (!DOM.isWatchPage()) {
          this.stopChatStateSync();
          return;
        }

        const watchFlexy = DOM.getWatchFlexy();
        if (!watchFlexy) return;

        this.updateEngagementPanelState(watchFlexy);
        this.updateTheaterModeState(watchFlexy);

        const hasSidebarChat = DOM.hasWatchSidebarChat(watchFlexy);
        const hasWatchChatClass = document.documentElement.classList.contains('tm-youtube-layout-plus-watch-chat');

        if (hasSidebarChat && !hasWatchChatClass) {
          Scheduler.scheduleApply();
          return;
        }

        if (!hasSidebarChat || !hasWatchChatClass) return;
        this.updateChatPanelState(watchFlexy);
      }, 500);
    },

    /**
     * 自动折叠直播聊天面板
     */
    autoCollapseLiveChatPanel(watchFlexy) {
      const watchPageKey = DOM.getWatchPageKey();
      if (State.layout.lastAutoCollapsedWatchChatKey === watchPageKey) return;

      const chatFrameHost = watchFlexy.querySelector('ytd-live-chat-frame#chat');
      const openPanelButton = DOM.findOpenPanelButton();

      if (openPanelButton && !openPanelButton.disabled) {
        State.layout.lastAutoCollapsedWatchChatKey = watchPageKey;
        return;
      }

      if (chatFrameHost?.hasAttribute('collapsed')) {
        State.layout.lastAutoCollapsedWatchChatKey = watchPageKey;
        return;
      }

      const hostToggleButton = chatFrameHost?.querySelector(
        '#show-hide-button button, #show-hide-button yt-button-shape button, #show-hide-button tp-yt-paper-button'
      );

      if (hostToggleButton) {
        hostToggleButton.click();
        State.layout.lastAutoCollapsedWatchChatKey = watchPageKey;
        setTimeout(() => Scheduler.scheduleApply(), 80);
        return;
      }

      const chatFrame = watchFlexy.querySelector(
        'ytd-live-chat-frame#chat #chatframe, ytd-live-chat-frame#chat iframe, #chatframe'
      );
      const chatDoc = DOM.safeGetIframeDocument(chatFrame);
      if (!chatDoc) return;

      const closeButton = Array.from(chatDoc.querySelectorAll('button')).find(
        button => /close/i.test(button.getAttribute('aria-label') || '')
      );

      if (closeButton) {
        closeButton.click();
        State.layout.lastAutoCollapsedWatchChatKey = watchPageKey;
        setTimeout(() => Scheduler.scheduleApply(), 80);
      }
    },

    /**
     * 隐藏重播提示
     */
    hideReplayPrompt() {
      const teaserCarousel = document.querySelector('ytd-watch-metadata #teaser-carousel');
      if (!teaserCarousel) return;

      const teaserText = DOM.getWatchTeaserText();
      if (DOM.hasLiveWatchPrompt(teaserText)) {
        teaserCarousel.classList.remove(Constants.Classes.REPLAY_HIDE);
        return;
      }

      const watchFlexy = DOM.getWatchFlexy();
      if (watchFlexy && DOM.hasReplayWatchPrompt(teaserText) && DOM.hasWatchSidebarChat(watchFlexy)) {
        teaserCarousel.classList.remove(Constants.Classes.REPLAY_HIDE);
        return;
      }

      const replayPrompt = Array.from(
        teaserCarousel.querySelectorAll('yt-video-metadata-carousel-view-model')
      ).find(card => {
        const text = (card.innerText || card.textContent || '').trim();
        return /live chat replay/i.test(text) || /see what others said about this video while it was live/i.test(text);
      });

      if (!replayPrompt) {
        teaserCarousel.classList.remove(Constants.Classes.REPLAY_HIDE);
      } else {
        teaserCarousel.classList.add(Constants.Classes.REPLAY_HIDE);
      }
    },

    /**
     * 清除隐藏的重播提示
     */
    clearHiddenReplayPrompts() {
      for (const el of document.querySelectorAll('.' + Constants.Classes.REPLAY_HIDE)) {
        el.classList.remove(Constants.Classes.REPLAY_HIDE);
      }
    },

    /**
     * 获取播放器锁定元素
     */
    getPlayerLockElement() {
      const selectors = [
        'ytd-watch-flexy #player-theater-container',
        'ytd-watch-flexy #player-full-bleed-container',
        'ytd-watch-flexy #player-container-outer',
        'ytd-watch-flexy #player-container',
        'ytd-watch-flexy #player',
      ];

      return selectors
        .map(selector => document.querySelector(selector))
        .find(element => {
          if (!element) return false;
          const rect = element.getBoundingClientRect();
          return rect.width >= 240 && rect.height >= 120;
        }) || null;
    },

    /**
     * 锁定路由过渡播放器
     */
    lockRouteTransitionPlayer() {
      if (DOM.isFullscreenActive()) return;

      const player = this.getPlayerLockElement();
      if (!player) return;

      const rect = player.getBoundingClientRect();
      const rootStyle = document.documentElement.style;

      rootStyle.setProperty('--tm-watch-transition-player-top', `${Math.round(rect.top)}px`);
      rootStyle.setProperty('--tm-watch-transition-player-left', `${Math.round(rect.left)}px`);
      rootStyle.setProperty('--tm-watch-transition-player-width', `${Math.round(rect.width)}px`);
      rootStyle.setProperty('--tm-watch-transition-player-height', `${Math.round(rect.height)}px`);

      player.dataset.tmWatchTransitionLock = 'true';
    },

    /**
     * 清除路由过渡播放器锁定
     */
    clearRouteTransitionPlayerLock() {
      const rootStyle = document.documentElement.style;
      rootStyle.removeProperty('--tm-watch-transition-player-top');
      rootStyle.removeProperty('--tm-watch-transition-player-left');
      rootStyle.removeProperty('--tm-watch-transition-player-width');
      rootStyle.removeProperty('--tm-watch-transition-player-height');

      for (const element of document.querySelectorAll('[data-tm-watch-transition-lock="true"]')) {
        delete element.dataset.tmWatchTransitionLock;
      }
    },

    /**
     * 启动引导
     */
    startBootstrap() {
      this.stopBootstrap();
      if (!DOM.isWatchPage()) return;

      State.layout.watchBootstrapStep = 0;

      const run = () => {
        if (!DOM.isWatchPage()) {
          this.stopBootstrap();
          return;
        }

        Scheduler.scheduleApply();
        this.attachObservers();
        this.syncPlayerSize();

        const measured = !!State.layout.lastPlayerSyncKey;
        const observersReady = !!State.observers.watchFlexyObservedElement;

        if (measured && observersReady) {
          this.stopBootstrap();
          return;
        }

        if (State.layout.watchBootstrapStep >= Constants.Timing.WATCH_BOOTSTRAP_DELAYS.length - 1) {
          this.stopBootstrap();
          return;
        }

        State.layout.watchBootstrapStep += 1;
        State.timers.watchBootstrap = setTimeout(run, Constants.Timing.WATCH_BOOTSTRAP_DELAYS[State.layout.watchBootstrapStep]);
      };

      run();
    },

    /**
     * 停止引导
     */
    stopBootstrap() {
      if (!State.timers.watchBootstrap) return;
      clearTimeout(State.timers.watchBootstrap);
      State.timers.watchBootstrap = null;
    },
  };

  // ============================================================================
  // 模块9: 主题管理
  // ============================================================================
  const ThemeManager = {
    /**
     * 初始化
     */
    init() {
      State.theme.currentMode = Storage.loadThemeMode();
      State.theme.lastPersistedMode = State.theme.currentMode;
    },

    /**
     * 获取主题动作名
     */
    getActionName(mode) {
      return Constants.THEME_MODES.find(item => item.mode === mode)?.actionName || null;
    },

    /**
     * 派发主题信号
     */
    dispatchSignal(mode) {
      const actionName = this.getActionName(mode);
      if (!actionName) return false;

      const target = DOM.getApp() || document.documentElement;
      try {
        target.dispatchEvent(new CustomEvent('yt-action', {
          detail: {
            actionName,
            args: [],
            optionalAction: false,
            returnValue: [],
          },
          bubbles: true,
          cancelable: false,
          composed: true,
        }));
        return true;
      } catch (error) {
        console.debug('YouTube Layout Plus theme dispatch failed:', error);
        return false;
      }
    },

    /**
     * 验证主题模式
     */
    async verifyMode(mode, { attempts = 10, intervalMs = 120 } = {}) {
      const expectedDarkAttr = mode === 'dark';
      let lastResult = null;

      for (let attempt = 0; attempt < attempts; attempt++) {
        const cookieMode = Utils.getThemeModeFromCookie();
        const hasDark = document.documentElement.hasAttribute('dark');
        const actualMode = cookieMode || Utils.inferThemeMode();
        const cookieConsistent = cookieMode ? cookieMode === mode : true;
        const darkConsistent = mode === 'auto' ? true : hasDark === expectedDarkAttr;

        lastResult = {
          ok: cookieConsistent && darkConsistent,
          actualMode,
          cookieMode,
          hasDark,
        };

        if (lastResult.ok) return lastResult;
        await Utils.delay(intervalMs);
      }

      return lastResult || {
        ok: false,
        actualMode: Utils.getObservedThemeMode(),
        cookieMode: Utils.getThemeModeFromCookie(),
        hasDark: document.documentElement.hasAttribute('dark'),
      };
    },

    /**
     * 设置主题模式
     */
    async setMode(mode) {
      if (State.theme.switchInFlight) return;
      if (!Constants.THEME_MODES.some(item => item.mode === mode)) return;

      const previousMode = State.theme.currentMode || Storage.loadThemeMode() || Utils.getThemeModeFromCookie() || Utils.inferThemeMode();
      const expectedDarkAttr = mode === 'dark' || (mode === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches);

      if (previousMode === mode && document.documentElement.hasAttribute('dark') === expectedDarkAttr) {
        State.theme.currentMode = mode;
        Storage.saveThemeMode(mode);
        State.theme.pendingMode = null;
        this.updateSwitcherUI();
        return;
      }

      State.theme.switchInFlight = true;
      State.theme.pendingMode = mode;

      try {
        this.updateSwitcherUI();

        if (!this.dispatchSignal(mode)) {
          State.theme.currentMode = previousMode;
          Storage.saveThemeMode(previousMode);
          this.showStatus(`Theme switch failed: unable to dispatch ${mode}.`);
          return;
        }

        State.theme.currentMode = mode;
        Storage.saveThemeMode(mode);
        this.updateSwitcherUI();

        let verification = await this.verifyMode(mode);
        if (!verification.ok) {
          this.dispatchSignal(mode);
          verification = await this.verifyMode(mode, { attempts: 14, intervalMs: 140 });
        }

        if (!verification.ok) {
          State.theme.currentMode = verification.actualMode || previousMode;
          Storage.saveThemeMode(State.theme.currentMode);
          this.showStatus(`Theme switch failed: expected ${mode}, actual ${State.theme.currentMode || 'unknown'}.`);
          return;
        }

        State.theme.currentMode = verification.actualMode || mode;
        Storage.saveThemeMode(State.theme.currentMode);
        this.hideStatus();
      } finally {
        State.theme.switchInFlight = false;
        State.theme.pendingMode = null;
        State.theme.currentMode = State.theme.currentMode || Storage.loadThemeMode() || Utils.getThemeModeFromCookie() || previousMode;
        this.updateSwitcherUI();
      }
    },

    /**
     * 更新切换器 UI
     */
    updateSwitcherUI({ force = false } = {}) {
      const switcher = document.getElementById(Constants.THEME_SWITCHER_ID);
      if (!switcher) return;

      if (!State.theme.pendingMode) {
        const observedMode = Utils.getObservedThemeMode();
        if (observedMode && observedMode !== State.theme.currentMode) {
          State.theme.currentMode = observedMode;
          Storage.saveThemeMode(observedMode);
        }
      } else if (!State.theme.currentMode) {
        State.theme.currentMode = Storage.loadThemeMode() || Utils.inferThemeMode();
      }

      const visibleMode = State.theme.pendingMode || State.theme.currentMode;
      const disabled = State.theme.switchInFlight;

      if (!force && State.theme.lastRenderedMode === visibleMode && State.theme.lastRenderedDisabled === disabled) {
        return;
      }

      State.theme.lastRenderedMode = visibleMode;
      State.theme.lastRenderedDisabled = disabled;

      const optionButtons = switcher.querySelectorAll('.tm-theme-switch-option[data-mode]');
      for (const button of optionButtons) {
        const isActive = button.dataset.mode === visibleMode;
        button.dataset.active = String(isActive);
        button.setAttribute('aria-pressed', String(isActive));
        button.disabled = disabled;
      }
    },

    /**
     * 显示状态消息
     */
    showStatus(message) {
      let status = document.getElementById(Constants.THEME_STATUS_ID);
      if (!status) {
        status = document.createElement('div');
        status.id = Constants.THEME_STATUS_ID;
        status.dataset.visible = 'false';
        document.body.appendChild(status);
      }

      status.textContent = message;
      status.dataset.visible = 'true';

      if (State.timers.themeStatusHide) clearTimeout(State.timers.themeStatusHide);
      State.timers.themeStatusHide = setTimeout(() => {
        status.dataset.visible = 'false';
        State.timers.themeStatusHide = null;
      }, 2600);
    },

    /**
     * 隐藏状态消息
     */
    hideStatus() {
      const status = document.getElementById(Constants.THEME_STATUS_ID);
      if (status) status.dataset.visible = 'false';
      if (State.timers.themeStatusHide) {
        clearTimeout(State.timers.themeStatusHide);
        State.timers.themeStatusHide = null;
      }
    },

    /**
     * 确保切换器存在
     */
    ensureSwitcher() {
      const logoRenderer = DOM.getLogoRenderer();
      if (!logoRenderer) return;

      let switcher = document.getElementById(Constants.THEME_SWITCHER_ID);
      let justCreated = false;

      if (!switcher) {
        const track = document.createElement('div');
        track.className = 'tm-theme-switch-track';
        track.setAttribute('role', 'group');
        track.setAttribute('aria-label', 'Theme switcher');

        switcher = document.createElement('div');
        switcher.id = Constants.THEME_SWITCHER_ID;

        for (const item of Constants.THEME_MODES) {
          const button = document.createElement('button');
          button.type = 'button';
          button.className = 'tm-theme-switch-option';
          button.dataset.mode = item.mode;
          button.dataset.active = 'false';
          button.textContent = item.label;
          button.setAttribute('aria-pressed', 'false');
          button.addEventListener('click', async (event) => {
            event.preventDefault();
            event.stopPropagation();
            await this.setMode(item.mode);
          });
          track.appendChild(button);
        }

        switcher.append(track);
        logoRenderer.insertAdjacentElement('afterend', switcher);
        justCreated = true;
      } else if (switcher.previousElementSibling !== logoRenderer) {
        logoRenderer.insertAdjacentElement('afterend', switcher);
      }

      this.updateSwitcherUI({ force: justCreated });
    },
  };

  // ============================================================================
  // 模块10: 网格切换器管理
  // ============================================================================
  const GridSwitcher = {
    /**
     * 更新切换器 UI
     */
    updateUI({ force = false } = {}) {
      const switcher = document.getElementById(Constants.HOME_GRID_SWITCHER_ID);
      if (!switcher) return;

      const activeColumns = Storage.normalizeGridColumns(State.grid.currentColumns);
      if (!force && State.grid.lastRenderedColumns === activeColumns) return;
      State.grid.lastRenderedColumns = activeColumns;

      for (const button of switcher.querySelectorAll('.tm-home-grid-option[data-columns]')) {
        const isActive = Number(button.dataset.columns) === activeColumns;
        button.dataset.active = String(isActive);
        button.setAttribute('aria-pressed', String(isActive));
      }
    },

    /**
     * 设置列数
     */
    setColumns(columns) {
      const normalized = Storage.normalizeGridColumns(columns);
      if (normalized === State.grid.currentColumns) return;

      State.grid.currentColumns = normalized;
      Storage.saveHomeGridColumns(normalized);
      HomeLayout.applyGridColumns();
      this.updateUI();

      if (DOM.isHomePage()) {
        Scheduler.scheduleApply();
      }
    },

    /**
     * 确保切换器存在
     */
    ensureSwitcher() {
      const anchor = document.getElementById(Constants.THEME_SWITCHER_ID) || DOM.getLogoRenderer();
      if (!anchor) return;

      let switcher = document.getElementById(Constants.HOME_GRID_SWITCHER_ID);
      let justCreated = false;

      if (!switcher) {
        switcher = document.createElement('div');
        switcher.id = Constants.HOME_GRID_SWITCHER_ID;
        switcher.setAttribute('role', 'group');
        switcher.setAttribute('aria-label', 'Home grid columns');

        for (const columns of Constants.Layout.HOME_GRID_COLUMN_OPTIONS) {
          const button = document.createElement('button');
          button.type = 'button';
          button.className = 'tm-home-grid-option';
          button.dataset.columns = String(columns);
          button.dataset.active = 'false';
          button.textContent = String(columns);
          button.setAttribute('aria-pressed', 'false');
          button.addEventListener('click', (event) => {
            event.preventDefault();
            event.stopPropagation();
            this.setColumns(columns);
          });
          switcher.appendChild(button);
        }

        anchor.insertAdjacentElement('afterend', switcher);
        justCreated = true;
      } else if (switcher.previousElementSibling !== anchor) {
        anchor.insertAdjacentElement('afterend', switcher);
      }

      this.updateUI({ force: justCreated });
    },
  };

  // ============================================================================
  // 模块11: 调度器
  // ============================================================================
  const Scheduler = {
    /**
     * 应用布局
     */
    applyLayout() {
      StyleManager.ensure();
      HomeLayout.applyGridColumns();

      try {
        ThemeManager.ensureSwitcher();
        GridSwitcher.ensureSwitcher();
      } catch (error) {
        console.error('YouTube Layout Plus switcher insertion failed:', error);
      }

      if (DOM.isHomePage()) {
        HomeLayout.apply();
        return;
      }

      if (DOM.isWatchPage()) {
        WatchLayout.apply();
        return;
      }

      HomeLayout.setLayoutClasses([]);
      HomeLayout.clearSideCardThumbnailFit();
      WatchLayout.resetState();
    },

    /**
     * 队列应用
     */
    queueApply() {
      if (State.applyFrame) return;
      State.applyFrame = requestAnimationFrame(() => {
        State.applyFrame = 0;
        this.applyLayout();
      });
    },

    /**
     * 调度应用
     */
    scheduleApply(delay = 0) {
      if (delay > 0) {
        clearTimeout(State.timers.applyDelay);
        State.timers.applyDelay = setTimeout(() => {
          State.timers.applyDelay = null;
          this.queueApply();
        }, delay);
        return;
      }

      if (State.timers.applyDelay) {
        clearTimeout(State.timers.applyDelay);
        State.timers.applyDelay = null;
      }

      this.queueApply();
    },
  };

  // ============================================================================
  // 模块12: 路由管理
  // ============================================================================
  const Router = {
    /**
     * 开始路由过渡
     */
    startTransition() {
      if (!DOM.isWatchPage() && !DOM.getWatchFlexy()) return;

      if (State.timers.routeTransition) {
        clearTimeout(State.timers.routeTransition);
        State.timers.routeTransition = null;
      }

      if (DOM.isWatchPage()) {
        WatchLayout.syncPlayerSize();
        WatchLayout.lockRouteTransitionPlayer();
      }

      document.documentElement.classList.add(Constants.Classes.ROUTE_TRANSITION);
    },

    /**
     * 完成路由过渡
     */
    finishTransition(delay = 220, attempts = 6) {
      if (State.timers.routeTransition) {
        clearTimeout(State.timers.routeTransition);
      }

      State.timers.routeTransition = setTimeout(() => {
        if (!DOM.isWatchPage() && DOM.getWatchFlexy() && attempts > 0) {
          State.timers.routeTransition = null;
          this.finishTransition(100, attempts - 1);
          return;
        }

        State.timers.routeTransition = null;
        document.documentElement.classList.remove(Constants.Classes.ROUTE_TRANSITION);
        WatchLayout.clearRouteTransitionPlayerLock();

        if (!DOM.isWatchPage()) {
          WatchLayout.resetState();
        }
      }, delay);
    },

    /**
     * 处理路由变化
     */
    handleChange(force = false) {
      const nextUrl = location.href;
      if (!force && nextUrl === State.currentUrl) {
        this.finishTransition();
        return;
      }

      State.currentUrl = nextUrl;
      WatchLayout.clearHiddenReplayPrompts();

      if (!DOM.isHomePage()) {
        State.layout.lastAutoCollapsedHomeUrl = '';
      }

      if (!DOM.isWatchPage()) {
        State.layout.lastAutoCollapsedWatchChatKey = '';
        WatchLayout.stopBootstrap();
        WatchLayout.stopChatStateSync();
        WatchLayout.detachObservers();
        WatchLayout.resetState({
          clearSizing: !document.documentElement.classList.contains(Constants.Classes.ROUTE_TRANSITION),
          preserveTransitionLayout: document.documentElement.classList.contains(Constants.Classes.ROUTE_TRANSITION),
        });
      } else {
        WatchLayout.resetState({ clearSizing: false });
        WatchLayout.detachObservers();
        WatchLayout.startBootstrap();
        WatchLayout.startChatStateSync();
      }

      // 动态管理 bodyObserver
      if (DOM.isHomePage()) {
        ObserverManager.startBody();
      } else {
        ObserverManager.stopBody();
      }

      Scheduler.scheduleApply();
      this.finishTransition();
    },

    /**
     * 启动路由监听
     */
    startWatching() {
      if (State.timers.route) return;

      State.timers.route = setInterval(() => {
        if (location.href === State.currentUrl) return;
        this.handleChange();
      }, Constants.Timing.ROUTE_POLL_INTERVAL_MS);
    },
  };

  // ============================================================================
  // 模块13: 观察者管理
  // ============================================================================
  const ObserverManager = {
    /**
     * 启动 body 观察者
     */
    startBody() {
      if (State.observers.body) return;

      State.observers.body = new MutationObserver((mutations) => {
        if (DOM.isWatchPage()) return;

        const hasRelevantMutation = mutations.some((mutation) => {
          const target = mutation.target instanceof Element ? mutation.target : mutation.target?.parentElement;
          if (!target) return false;
          if (target.closest('#movie_player, .html5-video-player, #chatframe')) return false;
          return true;
        });

        if (hasRelevantMutation) {
          Scheduler.scheduleApply(Constants.Timing.OBSERVER_APPLY_DEBOUNCE_MS);
        }
      });

      State.observers.body.observe(document.body, {
        childList: true,
        subtree: true,
      });
    },

    /**
     * 停止 body 观察者
     */
    stopBody() {
      if (!State.observers.body) return;
      State.observers.body.disconnect();
      State.observers.body = null;
    },
  };

  // ============================================================================
  // 模块14: 事件监听器
  // ============================================================================
  const EventListeners = {
    /**
     * 启动导航监听
     */
    startNavigation() {
      document.addEventListener('yt-navigate-start', () => Router.startTransition(), true);
      document.addEventListener('yt-navigate-finish', () => Router.handleChange(), true);
      window.addEventListener('popstate', () => {
        Router.startTransition();
        Router.handleChange();
      }, true);
    },

    /**
     * 启动窗口监听
     */
    startWindow() {
      window.addEventListener('resize', (event) => {
        if (event && event.isTrusted === false) return;

        if (State.timers.resize) clearTimeout(State.timers.resize);
        if (State.resizeFrame) cancelAnimationFrame(State.resizeFrame);

        State.resizeFrame = requestAnimationFrame(() => {
          State.resizeFrame = 0;
        });

        State.timers.resize = setTimeout(() => {
          State.timers.resize = null;
          if (DOM.isWatchPage()) WatchLayout.syncPlayerSize();
          if (DOM.isHomePage()) HomeLayout.scheduleSideCardThumbnailFit();
          Scheduler.scheduleApply();
        }, 80);
      }, true);

      document.addEventListener('fullscreenchange', () => {
        if (!DOM.isWatchPage()) return;
        const watchFlexy = DOM.getWatchFlexy();
        if (watchFlexy) {
          WatchLayout.updateTheaterModeState(watchFlexy);
          WatchLayout.updateEngagementPanelState(watchFlexy);
        }
        WatchLayout.syncPlayerSize();
        Scheduler.scheduleApply();
      }, true);

      window.addEventListener('beforeunload', () => this.cleanupAll(), { once: true });
    },

    /**
     * 启动交互监听
     */
    startInteraction() {
      document.addEventListener('click', (event) => {
        const trigger = event.target instanceof Element
          ? event.target.closest('button, yt-button-shape button, tp-yt-paper-button')
          : null;
        if (!trigger) return;

        const text = (trigger.innerText || trigger.textContent || '').trim();
        if (/open panel/i.test(text) && DOM.isWatchPage()) {
          State.layout.lastAutoCollapsedWatchChatKey = DOM.getWatchPageKey();
          Scheduler.scheduleApply(80);
        }

        if (DOM.isWatchPage()) {
          setTimeout(() => {
            const watchFlexy = DOM.getWatchFlexy();
            if (watchFlexy) {
              WatchLayout.updateEngagementPanelState(watchFlexy);
              WatchLayout.updateTheaterModeState(watchFlexy);
            }
            WatchLayout.syncPlayerSize();
          }, 120);

          setTimeout(() => {
            if (DOM.isWatchPage()) WatchLayout.syncPlayerSize();
          }, 360);
        }
      }, true);

      document.addEventListener('keyup', (event) => {
        if (!DOM.isWatchPage()) return;
        if (event.key !== 't' && event.key !== 'T' && event.key !== 'f' && event.key !== 'F') return;

        const target = event.target;
        if (target instanceof HTMLElement) {
          const tag = target.tagName;
          if (tag === 'INPUT' || tag === 'TEXTAREA' || target.isContentEditable) return;
        }

        setTimeout(() => {
          const watchFlexy = DOM.getWatchFlexy();
          if (watchFlexy) WatchLayout.updateTheaterModeState(watchFlexy);
          WatchLayout.syncPlayerSize();
        }, 80);
      }, true);
    },

    /**
     * 清理所有资源
     */
    cleanupAll() {
      // 清理定时器
      Object.values(State.timers).forEach(timer => {
        if (timer) clearTimeout(timer);
      });
      Object.keys(State.timers).forEach(key => {
        State.timers[key] = null;
      });

      // 清理观察者
      ObserverManager.stopBody();
      WatchLayout.detachObservers();
      WatchLayout.stopBootstrap();
      WatchLayout.stopChatStateSync();

      // 清理动画帧
      if (State.applyFrame) {
        cancelAnimationFrame(State.applyFrame);
        State.applyFrame = 0;
      }
      if (State.resizeFrame) {
        cancelAnimationFrame(State.resizeFrame);
        State.resizeFrame = 0;
      }

      // 清理缓存
      State.elementDataCache.clear();
    },
  };

  // ============================================================================
  // 模块15: 初始化
  // ============================================================================
  const App = {
    /**
     * 初始化应用
     */
    init() {
      ThemeManager.init();
      StyleManager.ensure();
      Router.handleChange(true);
      EventListeners.startNavigation();
      EventListeners.startWindow();
      EventListeners.startInteraction();
      Router.startWatching();
    },
  };

  // 启动应用
  App.init();
})();