Youtube Tools All in one local download mp3 mp4 HIGT QUALITY return dislikes and more

Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name Youtube Tools All in one local download mp3 mp4 HIGT QUALITY return dislikes and more
// @name:zh-TW  Youtube 工具 多合一本地下載 MP4、MP3
// @name:zh-HK  Youtube 工具 多合一本地下載 MP4、MP3
// @name:zh-CN  Youtube 工具 多合一本地下載 MP4、MP3
// @name:ja Youtube ツール オールインワンのローカル ダウンロード MP4、MP3
// @name:kr Youtube 도구 올인원 로컬 다운로드 외부 서비스 없이 MP4, MP3
// @name:ar Youtube Tools All in one local download mp3 mp4 HIGT QUALITY return dislikes and more
// @name:bg Youtube-Tools Alles in einem lokalen Download von MP4, MP3.
// @name:cs Nástroje YouTube Vše v jednom místní Stahujte MP4, MP3
// @name:da Youtube-værktøjer Alt i én lokal Download MP4, MP3
// @name:de Youtube-Tools Alles in einem lokalen Download von MP4, MP3
// @name:tel Youtube టూల్స్ అన్నీ ఒకే లోకల్ డౌన్‌లోడ్ MP4, Mp3
// @name:es Youtube Custom Todo en uno Descarga local MP4, MP3.
// @name:en Youtube Tools All in one local download mp3 mp4.
// @name:fr Outils Youtube Tout-en-un local Téléchargez MP4, MP3.
// @name:fr-CA Outils Youtube Tout-en-un local Téléchargez MP4, MP3.
// @name:he כלים של YouTube הכל במקום אחד מקומי הורדה MP4, MP3 באיכות גבוהה ללא שירות חיצוני ועוד.
// @name:hu Youtube Eszközök Minden egy helyen Letöltés MP4, MP3.
// @name:id Alat Youtube Semua dalam satu lokal Unduh MP4, MP3.
// @name:it Strumenti Youtube Tutto in uno Scarica locale MP4, MP3.
// @name:ko Youtube 도구 올인원 로컬 외부 서비스 없이 MP4, MP3
// @name:nb Youtube-verktøy Alt i ett lokalt Last ned MP4, MP3
// @name:nl Youtube Tools Alles in één lokaal Download MP4, MP3
// @name:pl Narzędzia YouTube Wszystko w jednym lokalnym. Pobierz MP4, MP3
// @name:pt-BR Ferramentas do Youtube Tudo em um local Baixe MP4, MP3 DE ALTA QUALIDAD.
// @name:ro YInstrumente Youtube Toate într-un singur local Descărcați MP4, MP3.
// @name:ru Инструменты Youtube Все в одном локальном формате. Загрузите MP4, MP3.
// @name:sk Nástroje YouTube Všetko v jednom miestne Stiahnite si MP4, MP3
// @name:sr Иоутубе алати Све у једном локалном Преузми МП4, МП3
// @name:sv Youtube-verktyg Allt i ett lokalt Ladda ner MP4, MP3
// @name:th เครื่องมือ Youtube ทั้งหมดในที่เดียว ดาวน์โหลด MP4, MP3
// @name:tr Youtube Araçları Hepsi bir arada yerel Harici hizmet olmadan MP4, MP3
// @name:uk Інструменти Youtube Все в одному локальному завантаженні MP4, MP3
// @name:ug Youtube قوراللىرى ھەممىسى بىر يەرلىك چۈشۈرۈش MP4,mp3
// @name:vi Công cụ Youtube Tất cả trong một cục bộ Tải xuống MP4, MP3
// @description:zh-TW Youtube 工具 多合一本地下載 mp4、MP3
// @description:zh-HK Youtube 工具 多合一本地下載 mp4、MP3
// @description:zh-CN Youtube 工具 多合一本地下載 mp4、MP3
// @description:ja    Youtube ツール オールインワン ローカル ダウンロード mp4、MP3 、
// @description:kr    Youtube 도구 올인원 로컬 다운로드 mp4, MP3
// @description:ar    Herramientas de YouTube Todo en uno Descarga local mp4, MP3
// @description:bg    Инструменти за Youtube Всичко в едно локално изтегляне mp4,
// @description:cs    Nástroje YouTube Vše v jednom místní Stahování mp4, MP3
// @description:da    Youtube-værktøjer Alt i ét lokalt Download mp4, MP3
// @description:de    YouTube-Tools Alles in einem lokalen Laden Sie MP4, MP3
// @description:tel   Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY,
// @description:es Youtube tools todo en uno personlizada youtube a tu estilo y descarga MP4 y MP3
// @description:fr Outils Youtube Tout-en-un local Téléchargez des mp4, des MP3
// @description:fr-CA Outils Youtube Tout-en-un local Téléchargez des mp4, des MP3
// @description:he  כלים של YouTube הכל במקום אחד מקומי הורד mp4, MP3
// @description:hu  Youtube Eszközök Minden egyben helyi Letöltés mp4, MP3
// @description:id  Alat Youtube Semua dalam satu lokal Unduh mp4, MP3
// @description:it Strumenti Youtube Tutto in uno locale Scarica mp4, MP3
// @description:ko  Youtube 도구 올인원 로컬 다운로드 mp4, MP3
// @description:nb  YoYoutube-verktøy Alt i ett lokalt Last ned mp4, MP3
// @description:nl    YouTube-tools Alles in één lokaal Download mp4, MP3
// @description:pl    Narzędzia Youtube Wszystko w jednym miejscu Pobierz mp4, MP3
// @description:pt-BR Ferramentas do YouTube Tudo em um só local Baixe mp4, MP3
// @description:ro    Instrumente Youtube Toate într-un singur local Descărcați mp4, MP3
// @description:ru    Инструменты Youtube Все в одном, локально. Загрузите mp4, MP3
// @description:sk    Nástroje YouTube Všetko v jednom miestnom Sťahujte mp4, MP3
// @description:sr    Иоутубе алати Све у једном локалном Преузми мп4, МП3
// @description:sv    Youtube-verktyg Allt i ett lokalt Ladda ner mp4, MP3
// @description:th เครื่องมือ Youtube ทั้งหมดในที่เดียว ดาวน์โหลด mp4, MP3
// @description:tr Youtube Araçları Hepsi bir arada yerel Harici hizmet olmadan mp4, MP3
// @description:uk Інструменти Youtube Все в одному локальному завантаженні mp4, MP3
// @description:ug Youtube قورالىنىڭ ھەممىسى بىر يەرلىك چۈشۈرۈشتە mp4, MP3 HIGH QUAقنى قا
// @description:vi Công cụ Youtube Tất cả trong một cục bộ Tải xuống mp4, MP3
// @description:en Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY
// @description Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY
// @homepage     https://github.com/DeveloperMDCM/
// @version      2.4.3.2
// @author       DeveloperMDCM
// @match        *://www.youtube.com/*
// @exclude      *://music.youtube.com/*
// @exclude      *://*.music.youtube.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant        GM_info
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        unsafeWindow
// @run-at       document-end
// @grant        GM_registerMenuCommand
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/js/iziToast.min.js
// @compatible chrome
// @compatible firefox
// @compatible opera
// @compatible safari
// @compatible edge
// @license MIT
// @namespace https://github.com/DeveloperMDCM/
// @keywords youtube, tools, download, mp3, mp4, hi-quality, return, dislikes, audio free, download mp3, download mp4, audio mp3, audio mp4, audio download, audio, free download, free audio, download audio, download free, hi quality, high quality, best quality, best audio quality, best free audio quality, best free quality, best audio free quality, best audio free, best free audio, best free
// ==/UserScript==

(function () {
  'use strict';
  let validoUrl = document.location.href;
  const $e = (el) => document.querySelector(el); // any element
  const $id = (el) => document.getElementById(el); // element by id
  const $m = (el) => document.querySelectorAll(el); // multiple all elements
  const $cl = (el, pty) => document.createElement(el); // create element
  const $sp = (el, pty) => document.documentElement.style.setProperty(el, pty); // set property variable css
  const $ap = (el) => document.body.appendChild(el); // append element
  const apiDislikes = "https://returnyoutubedislikeapi.com/Votes?videoId="; // Api dislikes
  const apiGoogleTranslate = "https://translate.googleapis.com/translate_a/t"; // Api google translate
  let selectedBgColor = "#252525"; // Background color menu default
  let selectedTextColor = "#ffffff"; // Text color menu default
  let selectedBgAccentColor = "#ff0000"; // Accent color menu default
  const urlSharedCode = "https://greasyfork.org/es/scripts/460680-youtube-tools-all-in-one-local-download-mp3-mp4-higt-quality-return-dislikes-and-more";
  const API_URL_AUDIO_VIDEO = "https://p.savenow.to/ajax/download.php?copyright=0&allow_extended_duration=1&" // API URL AUDIO VIDEO
  const API_KEY_DEVELOPERMDCM = 'dfcb6d76f2f6a9894gjkege8a4ab232222';  // API KEY FOR DOWNLOAD AUDIO VIDEO
  // Download API fallbacks (region/session issues)
  const DOWNLOAD_API_FALLBACK_BASES = [
    "https://p.savenow.to",
    "https://p.lbserver.xyz",
  ];
  // Alternative provider fallback
  const DUBS_START_ENDPOINT = "https://dubs.io/wp-json/tools/v1/download-video";
  const DUBS_STATUS_ENDPOINT = "https://dubs.io/wp-json/tools/v1/status-video";

  // for translate comments video
  const languagesTranslate = {
    "af": "Afrikaans",
    "sq": "Albanian",
    "am": "Amharic",
    "ar": "Arabic",
    "hy": "Armenian",
    "az": "Azerbaijani",
    "eu": "Basque",
    "be": "Belarusian",
    "bn": "Bengali",
    "bs": "Bosnian",
    "bg": "Bulgarian",
    "ca": "Catalan",
    "ceb": "Cebuano",
    "zh-CN": "Chinese (Simplified)",
    "zh-TW": "Chinese (Traditional)",
    "co": "Corsican",
    "hr": "Croatian",
    "cs": "Czech",
    "da": "Danish",
    "nl": "Dutch",
    "en": "English",
    "eo": "Esperanto",
    "et": "Estonian",
    "fi": "Finnish",
    "fr": "French",
    "fy": "Frisian",
    "gl": "Galician",
    "ka": "Georgian",
    "de": "German",
    "el": "Greek",
    "gu": "Gujarati",
    "ht": "Haitian Creole",
    "ha": "Hausa",
    "haw": "Hawaiian",
    "iw": "Hebrew",
    "hi": "Hindi",
    "hmn": "Hmong",
    "hu": "Hungarian",
    "is": "Icelandic",
    "ig": "Igbo",
    "id": "Indonesian",
    "ga": "Irish",
    "it": "Italian",
    "ja": "Japanese",
    "jw": "Javanese",
    "kn": "Kannada",
    "kk": "Kazakh",
    "km": "Khmer",
    "ko": "Korean",
    "ku": "Kurdish",
    "ky": "Kyrgyz",
    "lo": "Lao",
    "la": "Latin",
    "lv": "Latvian",
    "lt": "Lithuanian",
    "lb": "Luxembourgish",
    "mk": "Macedonian",
    "mg": "Malagasy",
    "ms": "Malay",
    "ml": "Malayalam",
    "mt": "Maltese",
    "mi": "Maori",
    "mr": "Marathi",
    "mn": "Mongolian",
    "my": "Myanmar (Burmese)",
    "ne": "Nepali",
    "no": "Norwegian",
    "ny": "Nyanja (Chichewa)",
    "ps": "Pashto",
    "fa": "Persian",
    "pl": "Polish",
    "pt": "Portuguese",
    "pa": "Punjabi",
    "ro": "Romanian",
    "ru": "Russian",
    "sm": "Samoan",
    "gd": "Scots Gaelic",
    "sr": "Serbian",
    "st": "Sesotho",
    "sn": "Shona",
    "sd": "Sindhi",
    "si": "Sinhala",
    "sk": "Slovak",
    "sl": "Slovenian",
    "so": "Somali",
    "es": "Spanish",
    "su": "Sundanese",
    "sw": "Swahili",
    "sv": "Swedish",
    "tl": "Tagalog (Filipino)",
    "tg": "Tajik",
    "ta": "Tamil",
    "te": "Telugu",
    "th": "Thai",
    "tr": "Turkish",
    "uk": "Ukrainian",
    "ur": "Urdu",
    "uz": "Uzbek",
    "vi": "Vietnamese",
    "cy": "Welsh",
    "xh": "Xhosa",
    "yi": "Yiddish",
    "yo": "Yoruba",
    "zu": "Zulu"
  }


   // var for wave
  let currentVideo = null;

  let waveStyle = 'dinamica';
  let audioCtx = null;
  let analyser = null;
  let source = null;
  let animationId = null;
  let canvas = null;
  let ctx = null;
  let controlPanel = null;
  let bufferLength = 0;
  let dataArray = null;
  let smoothedData = [];
  let isSetup = false;
  const smoothingFactor = 0.05;
  const canvasHeight = 240;
  const scale = canvasHeight / 90;

  const PROCESSED_FLAG = 'wave_visualizer_processed';

  // ------------------------------
  // PERF: runtime guards + dynamic style (avoid style/event/interval leaks)
  // ------------------------------
  const __ytToolsRuntime = {
    dynamicStyleEl: null,
    dynamicCssLast: '',
    settingsLoaded: false,
    bookmarkClickHandlerInitialized: false,
    bookmarksPanelOpen: false,
    continueWatching: {
      enabled: false,
      map: null,
      flushT: null,
      boundVideo: null,
      boundVideoId: null,
      lastSaveAt: 0,
      lastSavedTime: -1,
      lastKnownVideoId: null,
      navHandlerInitialized: false,
      panelOpen: false,
      clickHandlerInitialized: false,
      pagehideHandlerInitialized: false,
      handlers: null,
    },
    shortsChannelName: {
      enabled: false,
      observer: null,
      io: null,
      scanT: null,
      cache: new Map(),        // videoId -> channelName
      inflight: new Map(),     // videoId -> Promise<string>
      fetchChain: Promise.resolve(),
    },
    dislikesCache: {
      videoId: null,
      dislikes: null,
      ts: 0,
    },
    downloadClickHandlerInitialized: false,
    shortsObserver: null,
    statsObserver: null,
    statsIntervalId: null,
    lockupCachedStatsObserver: null,
    lockupCachedStatsObserveTarget: null,
    lockupCachedStatsIntervalId: null,
    updateShortsViewsButton: function () {},
    updateShortsRatingButton: function () {},
  };

  function setDynamicCss(cssText = '') {
    if (!__ytToolsRuntime.dynamicStyleEl) {
      const style = document.createElement('style');
      style.id = 'yt-tools-mdcm-dynamic-style';
      document.head.appendChild(style);
      __ytToolsRuntime.dynamicStyleEl = style;
    }
    if (__ytToolsRuntime.dynamicCssLast === cssText) return;
    __ytToolsRuntime.dynamicCssLast = cssText;
    __ytToolsRuntime.dynamicStyleEl.textContent = cssText;
  }

  const scheduleApplySettings = (() => {
    let t = null;
    return () => {
      // Prevent overwriting saved config with defaults before loadSettings finishes.
      if (!__ytToolsRuntime.settingsLoaded) return;
      clearTimeout(t);
      t = setTimeout(() => {
        try {
          applySettings();
        } catch (err) {
          console.error('applySettings error:', err);
        }
      }, 120);
    };
  })();

  function hideCanvas() {

    const canvas = $id('wave-visualizer-canvas');
    if (canvas) {
        canvas.style.opacity = '0';
        if (controlPanel) {
            controlPanel.style.opacity = '0';
        }
    }
  }

    function showCanvas() {
    const canvas = $id('wave-visualizer-canvas');
    if (audioCtx && audioCtx.state === 'suspended') {
        audioCtx.resume();
    }
    if (canvas) {
        canvas.style.opacity = '1';
        if (controlPanel) controlPanel.style.opacity = '1';
    }
}


  function Notify(type = 'info', message = '', title = '') {
    const defaultTitles = {
        success: 'Success',
        error: 'Error',
        info: 'Information',
        warning: 'Warning',
    };

    iziToast[type]({
        title: title || defaultTitles[type] || 'Notification',
        message: message,
        position: 'bottomLeft',
      });
  }

  async function startDownloadVideoOrAudio(format, container) {
    const videoURL = window.location.href;
    // Notify('info', 'Starting download...');

    // Check if already downloading
    if (container.dataset.downloading === 'true') {
      return;
    }

    // Stop any previous poller (avoid leaks on retry)
    try {
      if (container.__ytDownloadPoll) {
        clearInterval(container.__ytDownloadPoll);
        container.__ytDownloadPoll = null;
      }
    } catch (e) {}

    // Get UI elements from the container
    const downloadBtn = container.querySelector('.download-btn');
    const retryBtn = container.querySelector('.retry-btn');
    const progressRetryBtn = container.querySelector('.progress-retry-btn');
    const downloadAgainBtn = container.querySelector('.download-again-btn');
    const progressContainer = container.querySelector('.progress-container');
    const progressFill = container.querySelector('.progress-fill');
    const progressText = container.querySelector('.progress-text');
    const downloadText = container.querySelector('.download-text');

    // Set downloading flag
    container.dataset.downloading = 'true';
    container.dataset.urlOpened = 'false';
    container.dataset.lastDownloadUrl = '';

    // Update UI to show progress
    downloadBtn.style.display = 'none';
    retryBtn.style.display = 'none';
    progressRetryBtn.style.display = 'block';
    if (downloadAgainBtn) downloadAgainBtn.style.display = 'none';
    progressContainer.style.display = 'flex';
    progressFill.style.width = '0%';
    progressText.textContent = '0%';

    const fetchJsonWithTimeout = async (url, timeoutMs = 20000) => {
      const ctrl = new AbortController();
      const t = setTimeout(() => ctrl.abort(), timeoutMs);
      try {
        const res = await fetch(url, { signal: ctrl.signal });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return await res.json();
      } finally {
        clearTimeout(t);
      }
    };

    const setErrorState = () => {
      retryBtn.style.display = 'block';
      progressContainer.style.display = 'none';
      progressRetryBtn.style.display = 'none';
      if (downloadAgainBtn) downloadAgainBtn.style.display = 'none';
      container.dataset.downloading = 'false';
      container.dataset.urlOpened = 'false';
      container.dataset.lastDownloadUrl = '';
    };

    const markCompleteAndOpen = (downloadUrl) => {
      if (!downloadUrl) {
        setErrorState();
        return;
      }
      // Save for the \"download again\" button
      container.dataset.lastDownloadUrl = String(downloadUrl);
      // Check if URL was already opened
      if (container.dataset.urlOpened === 'true') return;
      // Mark URL as opened
      container.dataset.urlOpened = 'true';
      // Update UI to show completion
      container.classList.add('completed');
      container.classList.remove('video', 'audio');
      downloadText.textContent = 'Download Complete!';
      progressFill.style.width = '100%';
      progressText.textContent = '100%';
      progressRetryBtn.style.display = 'none';
      if (downloadAgainBtn) downloadAgainBtn.style.display = 'flex';
      container.dataset.downloading = 'false';
      try {
        window.open(downloadUrl);
      } catch (e) {
        console.warn('Could not open download URL:', e);
      }
    };

    const pollProgressUrl = (progressURL) => {
      container.__ytDownloadPoll = setInterval(async () => {
        try {
          const progressData = await fetchJsonWithTimeout(progressURL, 15000);

          const progress = Math.min((Number(progressData.progress) || 0) / 10, 100);
          progressFill.style.width = `${progress}%`;
          progressText.textContent = `${Math.round(progress)}%`;

          if (Number(progressData.progress) >= 1000 && progressData.download_url) {
            clearInterval(container.__ytDownloadPoll);
            container.__ytDownloadPoll = null;
            markCompleteAndOpen(progressData.download_url);
          }
        } catch (e) {
          console.error('Error in progress:', e);
          clearInterval(container.__ytDownloadPoll);
          container.__ytDownloadPoll = null;
          setErrorState();
        }
      }, 3000);
    };

    const trySaveNowProvider = async (baseUrl) => {
      const url = new URL('/ajax/download.php', baseUrl);
      url.searchParams.set('copyright', '0');
      url.searchParams.set('allow_extended_duration', '1');
      url.searchParams.set('format', String(format));
      url.searchParams.set('url', videoURL);
      url.searchParams.set('api', API_KEY_DEVELOPERMDCM);
      const data = await fetchJsonWithTimeout(url.toString(), 25000);
      if (!data?.success || !data?.progress_url) {
        throw new Error('SaveNow provider did not return success/progress_url');
      }
      return data;
    };

    const tryDubsProvider = async () => {
      const videoId = paramsVideoURL();
      if (!videoId) throw new Error('Missing videoId');

      const startUrl = new URL(DUBS_START_ENDPOINT);
      startUrl.searchParams.set('id', videoId);
      startUrl.searchParams.set('format', String(format));

      const startData = await fetchJsonWithTimeout(startUrl.toString(), 25000);
      if (!startData?.success || !startData?.progressId) {
        throw new Error('Dubs provider did not return success/progressId');
      }

      const statusUrl = new URL(DUBS_STATUS_ENDPOINT);
      statusUrl.searchParams.set('id', startData.progressId);

      container.__ytDownloadPoll = setInterval(async () => {
        try {
          const st = await fetchJsonWithTimeout(statusUrl.toString(), 20000);
          const rawProgress = Number(st?.progress) || 0; // 0..1000
          const progress = Math.min(rawProgress / 10, 100);
          progressFill.style.width = `${progress}%`;
          progressText.textContent = `${Math.round(progress)}%`;

          if (st?.finished && st?.downloadUrl) {
            clearInterval(container.__ytDownloadPoll);
            container.__ytDownloadPoll = null;
            markCompleteAndOpen(st.downloadUrl);
          }
        } catch (e) {
          console.error('❌ Error polling dubs status:', e);
          clearInterval(container.__ytDownloadPoll);
          container.__ytDownloadPoll = null;
          setErrorState();
        }
      }, 3000);
    };

    try {
        let started = null;
        let lastErr = null;

        for (const base of DOWNLOAD_API_FALLBACK_BASES) {
          try {
            started = await trySaveNowProvider(base);
            break;
          } catch (e) {
            lastErr = e;
          }
        }

        if (started?.success && started?.progress_url) {
          pollProgressUrl(started.progress_url);
          return;
        }

        console.warn('SaveNow providers failed, falling back to dubs.io', lastErr);
        await tryDubsProvider();
    } catch (error) {
        setErrorState();
        console.error('❌ Error starting download:', error);
    }
}


  const UPDATE_INTERVAL = 1000;
    const STORAGE = {
        USAGE: 'YT_TOTAL_USAGE',
        VIDEO: 'YT_VIDEO_TIME',
        SHORTS: 'YT_SHORTS_TIME'
    };

    let usageTime = GM_getValue(STORAGE.USAGE, 0);
    let videoTime = GM_getValue(STORAGE.VIDEO, 0);
    let shortsTime = GM_getValue(STORAGE.SHORTS, 0);
    let lastUpdate = Date.now();
    let activeVideo = null;
    let activeType = null;

    // Inicializar almacenamiento
    GM_setValue(STORAGE.USAGE, usageTime);
    GM_setValue(STORAGE.VIDEO, videoTime);
    GM_setValue(STORAGE.SHORTS, shortsTime);

  function FormatterNumber(num, digits) {
    const lookup = [
      {
        value: 1,
        symbol: '',
      },
      {
        value: 1e3,
        symbol: ' K',
      },
      {
        value: 1e6,
        symbol: ' M',
      },
    ];
    const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
    const item = lookup
      .slice()
      .reverse()
      .find((item) => {
        return num >= item.value;
      });
    return item
      ? (num / item.value).toFixed(digits).replace(rx, '$1') + item.symbol
      : '0';
  }

  function paramsVideoURL() {
    const parametrosURL = new URLSearchParams(window.location.search); // Url parametros
    return parametrosURL.get('v');
  }

  // ------------------------------
  // Feature helpers: videoId / channelId / storage
  // ------------------------------
  const STORAGE_KEYS_MDCM = {
    BOOKMARKS: 'ytBookmarksMDCM',
    CONTINUE_WATCHING: 'ytContinueWatchingMDCM',
    SHORTS_CHANNEL_CACHE: 'ytShortsChannelCacheMDCM',
    LIKES_DISLIKES_CACHE: 'ytLikesDislikesCacheMDCM',
    VERSION_CHECK_LAST: 'ytVersionCheckLastMDCM',
  };

  const UPDATE_META_URL = 'https://update.greasyfork.org/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.meta.js';
  const VERSION_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // once per day

  const SHORTS_CHANNEL_TTL_MS = 24 * 24 * 60 * 60 * 1000;   // 7 days
  const LIKES_DISLIKES_TTL_MS = 7 * 24 * 60 * 60 * 1000;        // 7 days
  const PERSISTED_CACHE_MAX_ENTRIES = 500;

  function getShortsChannelFromPersistedCache(videoId) {
    try {
      const map = readJsonGM(STORAGE_KEYS_MDCM.SHORTS_CHANNEL_CACHE, {});
      const entry = map?.[videoId];
      if (!entry || typeof entry.channelName !== 'string') return null;
      const age = Date.now() - (Number(entry.ts) || 0);
      if (age > SHORTS_CHANNEL_TTL_MS) return null;
      return entry.channelName;
    } catch (e) { return null; }
  }

  function setShortsChannelToPersistedCache(videoId, channelName) {
    if (!videoId || typeof channelName !== 'string') return;
    try {
      const map = readJsonGM(STORAGE_KEYS_MDCM.SHORTS_CHANNEL_CACHE, {});
      map[videoId] = { channelName, ts: Date.now() };
      const entries = Object.entries(map).sort((a, b) => (Number(b[1]?.ts) || 0) - (Number(a[1]?.ts) || 0));
      const pruned = Object.fromEntries(entries.slice(0, PERSISTED_CACHE_MAX_ENTRIES));
      writeJsonGM(STORAGE_KEYS_MDCM.SHORTS_CHANNEL_CACHE, pruned);
    } catch (e) {}
  }

  function getLikesDislikesFromPersistedCache(videoId) {
    try {
      const map = readJsonGM(STORAGE_KEYS_MDCM.LIKES_DISLIKES_CACHE, {});
      const entry = map?.[videoId];
      if (!entry) return null;
      const age = Date.now() - (Number(entry.ts) || 0);
      if (age > LIKES_DISLIKES_TTL_MS) return null;
      const dislikes = Number(entry.dislikes);
      const likes = Number(entry.likes);
      const viewCount = Number(entry.viewCount);
      const rating = Number(entry.rating);
      return {
        likes: Number.isFinite(likes) ? likes : null,
        dislikes: Number.isFinite(dislikes) ? dislikes : null,
        viewCount: Number.isFinite(viewCount) ? viewCount : null,
        rating: Number.isFinite(rating) && rating >= 0 && rating <= 5 ? rating : null,
      };
    } catch (e) { return null; }
  }

  function setLikesDislikesToPersistedCache(videoId, likes, dislikes, viewCount, rating) {
    if (!videoId) return;
    try {
      const map = readJsonGM(STORAGE_KEYS_MDCM.LIKES_DISLIKES_CACHE, {});
      map[videoId] = { likes: likes ?? null, dislikes: dislikes ?? null, viewCount: viewCount ?? null, rating: rating ?? null, ts: Date.now() };
      const entries = Object.entries(map).sort((a, b) => (Number(b[1]?.ts) || 0) - (Number(a[1]?.ts) || 0));
      const pruned = Object.fromEntries(entries.slice(0, Math.min(PERSISTED_CACHE_MAX_ENTRIES, 300)));
      writeJsonGM(STORAGE_KEYS_MDCM.LIKES_DISLIKES_CACHE, pruned);
    } catch (e) {}
  }

  function getCurrentVideoId() {
    try {
      if (location.pathname.startsWith('/shorts/')) {
        const parts = location.pathname.split('/').filter(Boolean);
        return parts[1] || null;
      }
      if (location.href.includes('youtube.com/watch')) {
        return paramsVideoURL();
      }
      return null;
    } catch (e) {
      return null;
    }
  }


  function readJsonGM(key, fallback) {
    try {
      const raw = GM_getValue(key, '');
      if (!raw) return fallback;
      return JSON.parse(raw);
    } catch (e) {
      return fallback;
    }
  }

  function writeJsonGM(key, value) {
    try {
      GM_setValue(key, JSON.stringify(value));
    } catch (e) {
      console.error('writeJsonGM error:', e);
    }
  }

  function isVersionNewer(latestStr, currentStr) {
    if (!latestStr || !currentStr) return false;
    const parse = (s) => String(s).trim().split('.').map((n) => parseInt(n, 10) || 0);
    const a = parse(latestStr);
    const b = parse(currentStr);
    const len = Math.max(a.length, b.length);
    for (let i = 0; i < len; i++) {
      const x = a[i] || 0;
      const y = b[i] || 0;
      if (x > y) return true;
      if (x < y) return false;
    }
    return false;
  }

  async function checkNewVersion() {
    try {
      const last = GM_getValue(STORAGE_KEYS_MDCM.VERSION_CHECK_LAST, 0);
      if (Date.now() - last < VERSION_CHECK_INTERVAL_MS) return;
      GM_setValue(STORAGE_KEYS_MDCM.VERSION_CHECK_LAST, Date.now());

      const res = await fetch(UPDATE_META_URL, { cache: 'no-store' });
      if (!res.ok) return;
      const text = await res.text();
      const m = text.match(/@version\s+([\d.]+)/);
      if (!m) return;
      const latestVer = m[1].trim();
      const currentVer = (typeof GM_info !== 'undefined' && GM_info.script && GM_info.script.version)
        ? String(GM_info.script.version).trim()
        : '';
      if (!currentVer || !isVersionNewer(latestVer, currentVer)) return;

      const updateUrl = 'https://update.greasyfork.org/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.user.js';
       iziToast.show({
         title: 'New Update',
         message: 'A new version YoutubeTools is available.',
         buttons: [
             ['<button>View Now</button>', function (instance, toast) {
                 window.open(updateUrl, '_blank');
                 instance.hide({ transitionOut: 'fadeOut' }, toast, 'button');
             }, true] // true = focus
         ]
     });
    } catch (e) {
      // silent: network or parse error
    }
  }

  function formatTimeShort(sec) {
    const s = Math.max(0, Math.floor(Number(sec) || 0));
    const h = Math.floor(s / 3600);
    const m = Math.floor((s % 3600) / 60);
    const r = s % 60;
    return h > 0 ? `${h}:${String(m).padStart(2, '0')}:${String(r).padStart(2, '0')}` : `${m}:${String(r).padStart(2, '0')}`;
  }




  // ------------------------------
  // Feature: History / Continue watching (per video)
  // ------------------------------
  function getMainVideoEl() {
    return (
      document.querySelector('#movie_player video.video-stream.html5-main-video') ||
      document.querySelector('ytd-player video.video-stream.html5-main-video') ||
      document.querySelector('video.video-stream.html5-main-video') ||
      document.querySelector('video')
    );
  }

  function getCurrentVideoMeta() {
    try {
      // DOM first (updates earlier on SPA navigation)
      const domTitle =
        $e('ytd-watch-metadata h1 yt-formatted-string')?.textContent?.trim() ||
        $e('h1.ytd-watch-metadata yt-formatted-string')?.textContent?.trim() ||
        '';
      const domAuthor =
        $e('#owner ytd-channel-name a, ytd-video-owner-renderer ytd-channel-name a, #text-container.ytd-channel-name a')?.textContent?.trim() ||
        $e('#owner a[href^="/@"], #owner a[href^="/channel/"]')?.textContent?.trim() ||
        '';
      const titleFromDom = (domTitle || document.title || '').replace(/\s*-\s*YouTube\s*$/i, '').trim();
      const authorFromDom = (domAuthor || '').trim();

      const w = (typeof unsafeWindow !== 'undefined' && unsafeWindow) ? unsafeWindow : window;
      const pr = w?.ytInitialPlayerResponse || window.ytInitialPlayerResponse;
      const vd = pr?.videoDetails || null;
      const title = (titleFromDom || vd?.title || document.title || '').replace(/\s*-\s*YouTube\s*$/i, '').trim();
      const author = (authorFromDom || vd?.author || '').trim();
      const thumbs = vd?.thumbnail?.thumbnails;
      const thumb = Array.isArray(thumbs) ? (thumbs[thumbs.length - 1]?.url || '') : '';
      return { title, author, thumb };
    } catch (e) {
      return { title: '', author: '', thumb: '' };
    }
  }

  function ensureContinueWatchingMapLoaded() {
    const rt = __ytToolsRuntime.continueWatching;
    if (!rt.map) rt.map = readJsonGM(STORAGE_KEYS_MDCM.CONTINUE_WATCHING, {});
    if (typeof rt.map !== 'object' || !rt.map) rt.map = {};
    return rt.map;
  }

  function pruneContinueWatchingMap(map, maxEntries = 200) {
    try {
      const entries = Object.entries(map || {}).filter(([, v]) => v && typeof v === 'object');
      entries.sort((a, b) => (Number(b[1].updatedAt) || 0) - (Number(a[1].updatedAt) || 0));
      const keep = entries.slice(0, maxEntries);
      const next = {};
      for (const [k, v] of keep) next[k] = v;
      return next;
    } catch (e) {
      return map || {};
    }
  }

  function scheduleContinueWatchingFlush() {
    const rt = __ytToolsRuntime.continueWatching;
    clearTimeout(rt.flushT);
    rt.flushT = setTimeout(() => {
      try {
        if (!rt.map) return;
        rt.map = pruneContinueWatchingMap(rt.map, 200);
        writeJsonGM(STORAGE_KEYS_MDCM.CONTINUE_WATCHING, rt.map);
      } catch (e) {}
    }, 800);
  }

  function clearContinueWatchingForVideo(videoId) {
    if (!videoId) return;
    const rt = __ytToolsRuntime.continueWatching;
    const map = ensureContinueWatchingMapLoaded();
    if (map && Object.prototype.hasOwnProperty.call(map, videoId)) {
      delete map[videoId];
      rt.map = map;
      scheduleContinueWatchingFlush();
    }
  }

  function setContinueWatchingForVideo(videoId, seconds, durationSec) {
    if (!videoId) return;
    const rt = __ytToolsRuntime.continueWatching;
    const map = ensureContinueWatchingMapLoaded();
    const t = Math.max(0, Math.floor(Number(seconds) || 0));
    const d = Math.max(0, Math.floor(Number(durationSec) || 0));
    const prev = map[videoId] && typeof map[videoId] === 'object' ? map[videoId] : {};
    const meta = getCurrentVideoMeta();
    map[videoId] = {
      t,
      d,
      updatedAt: Date.now(),
      title: meta.title || prev.title || '',
      author: meta.author || prev.author || '',
      thumb: meta.thumb || prev.thumb || '',
    };
    rt.map = map;
    scheduleContinueWatchingFlush();
  }

  function getContinueWatchingTime(videoId) {
    if (!videoId) return null;
    const map = ensureContinueWatchingMapLoaded();
    const entry = map?.[videoId];
    const t = Number(entry?.t);
    return Number.isFinite(t) ? t : null;
  }

  function updateContinueWatchingButton() {
    const rt = __ytToolsRuntime.continueWatching;
    const enabled = !!rt.enabled;
    if (!enabled || !isWatchPage()) return;

    const videoId = getCurrentVideoId();
    if (!videoId) return;

    const v = getMainVideoEl();
    const t = getContinueWatchingTime(videoId);
    const dur = Number(v?.duration);
    const hasDur = Number.isFinite(dur) && dur > 0;

    if (!t || t < 5) return;

    if (hasDur && t >= (dur - 5)) {
      clearContinueWatchingForVideo(videoId);
      return;
    }
  }

  function updateContinueWatchingHistoryUi() {
    const rt = __ytToolsRuntime.continueWatching;
    const btn = $id('yt-cw-history-toggle');
    const panel = $id('yt-continue-watching-panel');
    if (!btn || !panel) return;

    const enabled = !!rt.enabled;
    if (!enabled || !isWatchPage()) {
      btn.style.display = 'none';
      panel.style.display = 'none';
      return;
    }

    btn.style.display = 'inline-flex';
    panel.style.display = rt.panelOpen ? 'block' : 'none';
  }

  function cssEscapeLite(s) {
    const str = String(s || '');
    if (typeof CSS !== 'undefined' && CSS.escape) return CSS.escape(str);
    // minimal escape for attribute selector
    return str.replace(/["\\]/g, '\\$&');
  }

  function updateContinueWatchingPanelRow(videoId) {
    try {
      const rt = __ytToolsRuntime.continueWatching;
      if (!rt.enabled || !rt.panelOpen || !isWatchPage()) return false;
      const panel = $id('yt-continue-watching-panel');
      if (!panel) return false;

      const key = cssEscapeLite(videoId);
      const row = panel.querySelector(`.yt-cw-item[data-video-id="${key}"]`);
      if (!row) return false;

      const entry = ensureContinueWatchingMapLoaded()?.[videoId];
      const t = Number(entry?.t);
      if (!Number.isFinite(t)) return false;

      const meta = row.querySelector('.yt-cw-meta');
      if (!meta) return false;
      const author = String(entry?.author || '').trim();
      meta.textContent = `${formatTimeShort(t)}${author ? ` • ${author}` : ''}`;
      return true;
    } catch (e) {
      return false;
    }
  }

  function navigateToWatchSpa(videoId, seconds) {
    const t = Number(seconds);
    const url = `/watch?v=${encodeURIComponent(videoId)}${Number.isFinite(t) ? `&t=${Math.max(0, Math.floor(t))}s` : ''}`;
    try {
      const a = document.createElement('a');
      a.href = url;
      a.target = '_self';
      a.rel = 'noopener';
      a.style.display = 'none';
      document.body.appendChild(a);
      a.click();
      a.remove();
      return;
    } catch (e) {}
    location.href = url;
  }

  function renderContinueWatchingPanel() {
    const panel = $id('yt-continue-watching-panel');
    if (!panel) return;

    const rt = __ytToolsRuntime.continueWatching;
    if (!rt.enabled || !rt.panelOpen || !isWatchPage()) {
      panel.style.display = 'none';
      return;
    }

    const map = pruneContinueWatchingMap(ensureContinueWatchingMapLoaded(), 200);
    rt.map = map;
    const currentVid = getCurrentVideoId();

    const entries = Object.entries(map)
      .map(([videoId, v]) => ({ videoId, ...v }))
      .filter((e) => e.videoId && Number.isFinite(Number(e.t)) && Number(e.t) >= 5)
      .sort((a, b) => (Number(b.updatedAt) || 0) - (Number(a.updatedAt) || 0))
      .slice(0, 25);

    panel.replaceChildren();

    const header = document.createElement('div');
    header.className = 'yt-cw-header';

    const hTitle = document.createElement('div');
    hTitle.className = 'yt-cw-header-title';
    hTitle.textContent = 'Continue watching';

    const clearAll = document.createElement('button');
    clearAll.type = 'button';
    clearAll.className = 'yt-cw-clear';
    clearAll.textContent = 'Clear';
    clearAll.dataset.cwAction = 'clearAll';

    header.appendChild(hTitle);
    header.appendChild(clearAll);
    panel.appendChild(header);

    if (!entries.length) {
      const empty = document.createElement('div');
      empty.className = 'yt-cw-empty';
      empty.textContent = 'No history yet. Watch a bit, then reopen any video.';
      panel.appendChild(empty);
      return;
    }

    for (const e of entries) {
      const item = document.createElement('div');
      item.className = 'yt-cw-item';
      item.dataset.videoId = e.videoId;

      const thumbWrap = document.createElement('div');
      thumbWrap.className = 'yt-cw-thumb-wrap';
      const img = document.createElement('img');
      img.className = 'yt-cw-thumb';
      img.loading = 'lazy';
      img.decoding = 'async';
      img.alt = '';
      const thumbSrc = (e.thumb || '').trim() || `https://i.ytimg.com/vi/${encodeURIComponent(e.videoId)}/hqdefault.jpg`;
      img.src = thumbSrc;
      thumbWrap.appendChild(img);

      const info = document.createElement('div');
      info.className = 'yt-cw-info';

      const title = document.createElement('div');
      title.className = 'yt-cw-title';
      const safeTitle = (e.title || '').trim();
      title.textContent = safeTitle ? safeTitle : e.videoId;

      const meta = document.createElement('div');
      meta.className = 'yt-cw-meta';
      const author = (e.author || '').trim();
      meta.textContent = `${formatTimeShort(e.t)}${author ? ` • ${author}` : ''}`;

      info.appendChild(title);
      info.appendChild(meta);

      const actions = document.createElement('div');
      actions.className = 'yt-cw-actions';

      const tSec = Math.max(0, Math.floor(Number(e.t) || 0));
      let go = null;
      if (currentVid && currentVid === e.videoId) {
        const seek = document.createElement('button');
        seek.type = 'button';
        seek.className = 'yt-cw-go';
        seek.textContent = 'Resume';
        seek.dataset.cwAction = 'seek';
        seek.dataset.t = String(tSec);
        go = seek;
      } else {
        const a = document.createElement('a');
        a.className = 'yt-simple-endpoint yt-cw-go';
        a.textContent = 'Resume';
        a.href = `/watch?v=${encodeURIComponent(e.videoId)}&t=${tSec}s`;
        a.target = '_self';
        a.rel = 'noopener';
        go = a;
      }

      const del = document.createElement('button');
      del.type = 'button';
      del.className = 'yt-cw-del';
      del.textContent = '✕';
      del.title = 'Delete';
      del.dataset.cwAction = 'del';
      del.dataset.videoId = e.videoId;

      actions.appendChild(go);
      actions.appendChild(del);

      item.appendChild(thumbWrap);
      item.appendChild(info);
      item.appendChild(actions);
      panel.appendChild(item);
    }
  }

  function setupContinueWatchingFeature(enabled) {
    const rt = __ytToolsRuntime.continueWatching;
    rt.enabled = !!enabled;

    // Keep UI in sync across YouTube SPA navigations
    if (!rt.navHandlerInitialized) {
      rt.navHandlerInitialized = true;
      const onNav = () => {
        try {
          const vid = getCurrentVideoId();
          if (rt.lastKnownVideoId !== vid) {
            rt.lastKnownVideoId = vid;
            // reset throttles so new video can save properly
            rt.lastSaveAt = 0;
            rt.lastSavedTime = -1;
            rt.boundVideoId = vid;
            updateContinueWatchingButton();
            updateContinueWatchingHistoryUi();
            if (rt.panelOpen) renderContinueWatchingPanel();
          } else {
            updateContinueWatchingButton();
            updateContinueWatchingHistoryUi();
            if (rt.panelOpen) renderContinueWatchingPanel();
          }
        } catch (e) {}
      };
      window.addEventListener('yt-navigate-finish', onNav, true);
      window.addEventListener('popstate', onNav, true);
      window.addEventListener('hashchange', onNav, true);
    }

    // Ensure click handler only once
    if (!rt.clickHandlerInitialized) {
      rt.clickHandlerInitialized = true;
      document.addEventListener('click', (e) => {
        const target = e.target;
        if (!(target instanceof Element)) return;
        const historyBtn = target.closest('#yt-cw-history-toggle');
        const cwActionBtn = target.closest('[data-cw-action]');

        if (historyBtn) {
          e.preventDefault();
          e.stopPropagation();
          rt.panelOpen = !rt.panelOpen;
          updateContinueWatchingHistoryUi();
          if (rt.panelOpen) renderContinueWatchingPanel(); // render only when opened
          return;
        }

        if (cwActionBtn) {
          const action = cwActionBtn.getAttribute('data-cw-action');
          if (!action) return;
          e.preventDefault();
          e.stopPropagation();
          if (action === 'clearAll') {
            rt.map = {};
            writeJsonGM(STORAGE_KEYS_MDCM.CONTINUE_WATCHING, {});
            renderContinueWatchingPanel();
            updateContinueWatchingButton();
            try { Notify('success', 'History cleared'); } catch (e2) {}
            return;
          }
          if (action === 'del') {
            const vid = cwActionBtn.getAttribute('data-video-id') || '';
            if (vid) clearContinueWatchingForVideo(vid);
            renderContinueWatchingPanel();
            updateContinueWatchingButton();
            return;
          }
          if (action === 'seek') {
            const t = Number(cwActionBtn.getAttribute('data-t'));
            const v = getMainVideoEl();
            if (!v || !Number.isFinite(t)) return;
            v.currentTime = Math.max(0, t);
            v.play?.().catch(() => {});
            try { Notify('success', `Resume: ${formatTimeShort(t)}`); } catch (e2) {}
            updateContinueWatchingButton();
            return;
          }
        }
      }, true);
    }

    // Save on tab close / navigation (once)
    if (!rt.pagehideHandlerInitialized) {
      rt.pagehideHandlerInitialized = true;
      window.addEventListener('pagehide', () => {
        try {
          if (!rt.enabled) return;
          if (!isWatchPage()) return;
          const vid = getCurrentVideoId();
          const v = getMainVideoEl();
          if (!vid || !v) return;
          const t = Number(v.currentTime);
          const d = Number(v.duration);
          if (Number.isFinite(t) && t >= 5) setContinueWatchingForVideo(vid, t, d);
          // best-effort immediate flush
          if (rt.flushT) {
            clearTimeout(rt.flushT);
            rt.flushT = null;
          }
          if (rt.map) writeJsonGM(STORAGE_KEYS_MDCM.CONTINUE_WATCHING, pruneContinueWatchingMap(rt.map, 200));
        } catch (e) {}
      }, { capture: true });
    }

    const historyBtn = $id('yt-cw-history-toggle');
    const panel = $id('yt-continue-watching-panel');
    if (historyBtn && !rt.enabled) historyBtn.style.display = 'none';
    if (panel && !rt.enabled) panel.style.display = 'none';

    // Not on watch page: detach video listeners and hide
    if (!rt.enabled || !isWatchPage()) {
      try {
        if (rt.boundVideo && rt.handlers) {
          rt.boundVideo.removeEventListener('timeupdate', rt.handlers.timeupdate);
          rt.boundVideo.removeEventListener('pause', rt.handlers.pause);
          rt.boundVideo.removeEventListener('ended', rt.handlers.ended);
          rt.boundVideo.removeEventListener('loadedmetadata', rt.handlers.loadedmetadata);
          rt.boundVideo.removeEventListener('seeked', rt.handlers.seeked);
        }
      } catch (e) {}
      rt.boundVideo = null;
      rt.boundVideoId = null;
      rt.handlers = null;
      updateContinueWatchingButton();
      updateContinueWatchingHistoryUi();
      return;
    }

    const v = getMainVideoEl();
    const videoId = getCurrentVideoId();
    if (!v || !videoId) {
      updateContinueWatchingButton();
      updateContinueWatchingHistoryUi();
      return;
    }

    // VideoId can change while YouTube reuses the same <video> element
    if (rt.boundVideoId !== videoId) {
      rt.boundVideoId = videoId;
      rt.lastSaveAt = 0;
      rt.lastSavedTime = -1;
    }

    // If video element changed, rebind listeners (avoid leaks)
    if (rt.boundVideo && rt.boundVideo !== v && rt.handlers) {
      try {
        rt.boundVideo.removeEventListener('timeupdate', rt.handlers.timeupdate);
        rt.boundVideo.removeEventListener('pause', rt.handlers.pause);
        rt.boundVideo.removeEventListener('ended', rt.handlers.ended);
        rt.boundVideo.removeEventListener('loadedmetadata', rt.handlers.loadedmetadata);
        rt.boundVideo.removeEventListener('seeked', rt.handlers.seeked);
      } catch (e) {}
      rt.boundVideo = null;
      rt.boundVideoId = null;
      rt.handlers = null;
    }

    rt.boundVideo = v;
    rt.boundVideoId = videoId;

    if (!rt.handlers) {
      rt.handlers = {
        timeupdate: () => {
          try {
            if (!rt.enabled) return;
            const vid = getCurrentVideoId();
            if (!vid) return;
            const now = Date.now();
            if (now - rt.lastSaveAt < 5000) return; // throttle
            if (v.paused) return;
            const t = Number(v.currentTime);
            const d = Number(v.duration);
            if (!Number.isFinite(t)) return;
            if (Math.abs(t - rt.lastSavedTime) < 2) return;
            rt.lastSaveAt = now;
            rt.lastSavedTime = t;
            if (t < 5) return;
            setContinueWatchingForVideo(vid, t, d);
            updateContinueWatchingButton();
            // Avoid re-rendering the whole panel every few seconds.
            // If panel is open and row exists, just update its text.
            if (rt.panelOpen) {
              if (!updateContinueWatchingPanelRow(vid)) renderContinueWatchingPanel();
            }
          } catch (e) {}
        },
        pause: () => {
          try {
            if (!rt.enabled) return;
            const vid = getCurrentVideoId();
            if (!vid) return;
            const t = Number(v.currentTime);
            const d = Number(v.duration);
            if (!Number.isFinite(t)) return;
            if (t < 5) {
              clearContinueWatchingForVideo(vid);
            } else {
              setContinueWatchingForVideo(vid, t, d);
            }
            updateContinueWatchingButton();
            if (rt.panelOpen) {
              if (!updateContinueWatchingPanelRow(vid)) renderContinueWatchingPanel();
            }
          } catch (e) {}
        },
        ended: () => {
          try {
            const vid = getCurrentVideoId();
            if (vid) clearContinueWatchingForVideo(vid);
            updateContinueWatchingButton();
            if (rt.panelOpen) renderContinueWatchingPanel();
          } catch (e) {}
        },
        loadedmetadata: () => {
          updateContinueWatchingButton();
          if (rt.panelOpen) renderContinueWatchingPanel();
        },
        seeked: () => {
          updateContinueWatchingButton();
          const vid = getCurrentVideoId();
          if (rt.panelOpen && vid) updateContinueWatchingPanelRow(vid);
        },
      };

      v.addEventListener('timeupdate', rt.handlers.timeupdate, { passive: true });
      v.addEventListener('pause', rt.handlers.pause, { passive: true });
      v.addEventListener('ended', rt.handlers.ended, { passive: true });
      v.addEventListener('loadedmetadata', rt.handlers.loadedmetadata, { passive: true });
      v.addEventListener('seeked', rt.handlers.seeked, { passive: true });
    }

    updateContinueWatchingButton();
    updateContinueWatchingHistoryUi();
  }

  // ------------------------------
  // Feature: Show channel name on Shorts list (Home / feeds)
  // Adapted from: @𝖢𝖸 𝖥𝗎𝗇𝗀
  // ------------------------------
  function setupShortsChannelNameFeature(enabled) {
    __ytToolsRuntime.shortsChannelName.enabled = !!enabled;
    document.documentElement.dataset.mdcmShortsChannelName = enabled ? '1' : '0';

    // Disable: stop observers to reduce overhead
    if (!enabled) {
      try { __ytToolsRuntime.shortsChannelName.observer?.disconnect?.(); } catch (e) {}
      try { __ytToolsRuntime.shortsChannelName.io?.disconnect?.(); } catch (e) {}
      __ytToolsRuntime.shortsChannelName.observer = null;
      __ytToolsRuntime.shortsChannelName.io = null;
      clearTimeout(__ytToolsRuntime.shortsChannelName.scanT);
      __ytToolsRuntime.shortsChannelName.scanT = null;
      return;
    }

    const rt = __ytToolsRuntime.shortsChannelName;

    const getShortsVideoIdFromItem = (item) => {
      const a = item.querySelector('a[href^="/shorts/"]');
      const href = a?.getAttribute('href') || '';
      const m = href.match(/\/shorts\/([^/?]+)/);
      return m?.[1] || null;
    };

    const findSubhead = (item) => {
      return item.querySelector(
        '.ShortsLockupViewModelHostOutsideMetadataSubhead,' +
        ' .shortsLockupViewModelHostOutsideMetadataSubhead,' +
        ' .ShortsLockupViewModelHostMetadataSubhead,' +
        ' .shortsLockupViewModelHostMetadataSubhead'
      );
    };

    const ensureLabel = (subhead) => {
      const parent = subhead?.parentElement;
      if (!parent) return null;
      let el = parent.querySelector('.yt-tools-shorts-channel-name');
      if (!el) {
        el = document.createElement('div');
        el.className = 'yt-tools-shorts-channel-name';
        el.textContent = '';
        parent.insertBefore(el, subhead);
      }
      return el;
    };

    const tryExtractChannelNameFromDom = (item) => {
      const a = item.querySelector('a[href^="/@"], a[href^="/channel/"]');
      const name = (a?.textContent || a?.getAttribute('title') || '').trim();
      return name || null;
    };

    const fetchChannelNameFromWatch = (videoId) => {
      rt.fetchChain = rt.fetchChain.then(async () => {
        if (rt.cache.has(videoId)) return rt.cache.get(videoId);
        let res = null;
        try {
          res = await fetch(`/watch?v=${videoId}`, {
            method: 'GET',
            credentials: 'same-origin',
            cache: 'force-cache',
          });
        } catch (e) {
          return '';
        }
        if (!res?.ok) return '';
        const html = await res.text();

        const idx = html.indexOf('itemprop="author"');
        if (idx < 0) return '';
        const start = html.lastIndexOf('<span', idx);
        const end = html.indexOf('</span>', idx);
        if (start < 0 || end < 0) return '';
        const chunk = html.slice(start, end + 7);

        const doc = new DOMParser().parseFromString(chunk, 'text/html');
        const link = doc.querySelector('link[itemprop="name"]');
        return (link?.getAttribute('content') || '').trim();
      });
      return rt.fetchChain;
    };

    const getChannelName = (videoId, item) => {
      const cached = rt.cache.get(videoId);
      if (cached) return Promise.resolve(cached);

      const persisted = getShortsChannelFromPersistedCache(videoId);
      if (persisted) {
        rt.cache.set(videoId, persisted);
        return Promise.resolve(persisted);
      }

      const domName = tryExtractChannelNameFromDom(item);
      if (domName) {
        rt.cache.set(videoId, domName);
        setShortsChannelToPersistedCache(videoId, domName);
        return Promise.resolve(domName);
      }

      const inflight = rt.inflight.get(videoId);
      if (inflight) return inflight;

      const p = fetchChannelNameFromWatch(videoId)
        .then((name) => {
          const finalName = (name || '').trim();
          if (finalName) {
            rt.cache.set(videoId, finalName);
            setShortsChannelToPersistedCache(videoId, finalName);
          }
          return finalName;
        })
        .finally(() => {
          rt.inflight.delete(videoId);
        });
      rt.inflight.set(videoId, p);
      return p;
    };

    const processItem = (item) => {
      if (!(item instanceof Element)) return;
      if (item.dataset.ytToolsShortsChannelProcessed === '1') return;

      const subhead = findSubhead(item);
      if (!subhead) return;

      const videoId = getShortsVideoIdFromItem(item);
      if (!videoId) return;

      item.dataset.ytToolsShortsChannelProcessed = '1';
      item.dataset.ytToolsShortsVideoId = videoId;

      const label = ensureLabel(subhead);
      if (!label) return;
      label.textContent = '';

      rt.io?.observe(item);
    };

    if (!rt.io) {
      rt.io = new IntersectionObserver((entries) => {
        for (const entry of entries) {
          if (!entry.isIntersecting) continue;
          const item = entry.target;
          const videoId = item?.dataset?.ytToolsShortsVideoId;
          const subhead = findSubhead(item);
          const label = subhead?.parentElement?.querySelector?.('.yt-tools-shorts-channel-name');

          if (!videoId || !label) {
            rt.io.unobserve(item);
            continue;
          }

          getChannelName(videoId, item)
            .then((name) => {
              if (name) label.textContent = name;
            })
            .finally(() => {
              rt.io.unobserve(item);
            });
        }
      }, { threshold: 0.15 });
    }

    const scan = () => {
      clearTimeout(rt.scanT);
      rt.scanT = setTimeout(() => {
        document
          .querySelectorAll('ytm-shorts-lockup-view-model, ytm-shorts-lockup-view-model-v2')
          .forEach(processItem);
      }, 120);
    };

    if (!rt.observer) {
      rt.observer = new MutationObserver(scan);
      rt.observer.observe(document.body, { childList: true, subtree: true });
    }

    scan();
  }

  // ------------------------------
  // Feature: Show cached rating/likes/dislikes on video cards (watch related + home/search)
  // ------------------------------
  function getVideoIdFromLockup(lockup) {
    const a = lockup.querySelector('a[href*="watch?v="]');
    if (a) {
      const m = (a.getAttribute('href') || '').match(/[?&]v=([^&]+)/);
      if (m) return m[1];
    }
    const el = lockup.querySelector('[class*="content-id-"]');
    if (el) {
      const m = el.className.match(/content-id-([A-Za-z0-9_-]+)/);
      if (m) return m[1];
    }
    return null;
  }

  function createSvgIconFromString(svgString, sizePx) {
    const div = document.createElement('div');
    div.innerHTML = svgString.trim();
    const svg = div.firstElementChild;
    if (!svg) return null;
    svg.setAttribute('width', String(sizePx || 14));
    svg.setAttribute('height', String(sizePx || 14));
    svg.style.display = 'inline-block';
    svg.style.verticalAlign = 'middle';
    svg.style.marginRight = '2px';
    return svg;
  }

  const LOCKUP_RATING_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-star"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 17.75l-6.172 3.245l1.179 -6.873l-5 -4.867l6.9 -1l3.086 -6.253l3.086 6.253l6.9 1l-5 4.867l1.179 6.873l-6.158 -3.245" /></svg>';
  const LOCKUP_LIKE_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-thumb-up"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3" /></svg>';
  const LOCKUP_DISLIKE_SVG = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-thumb-down"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3" /></svg>';

  function injectLockupCachedStats() {
    if (!window.location.href.includes('youtube.com')) return;
    document.querySelectorAll('yt-lockup-view-model').forEach((lockup) => {
      if (lockup.hasAttribute('data-yt-tools-lockup-stats')) return;
      const videoId = getVideoIdFromLockup(lockup);
      if (!videoId) return;
      const cached = getLikesDislikesFromPersistedCache(videoId);
      if (!cached) return;
      const hasRating = cached.rating != null;
      const hasLikes = cached.likes != null;
      const hasDislikes = cached.dislikes != null;
      if (!hasRating && !hasLikes && !hasDislikes) return;
      const meta = lockup.querySelector('yt-content-metadata-view-model');
      if (!meta) return;
      const row = document.createElement('div');
      row.className = 'yt-content-metadata-view-model__metadata-row';
      row.setAttribute('data-yt-tools-lockup-stats-row', '1');
      const wrap = document.createElement('span');
      wrap.className = 'yt-core-attributed-string yt-content-metadata-view-model__metadata-text yt-core-attributed-string--white-space-pre-wrap yt-core-attributed-string--link-inherit-color';
      wrap.setAttribute('dir', 'auto');
      wrap.setAttribute('role', 'text');
      const sep = () => { const s = document.createTextNode(' · '); return s; };
      if (hasRating) {
        const ratingIcon = createSvgIconFromString(LOCKUP_RATING_SVG, 14);
        if (ratingIcon) wrap.appendChild(ratingIcon);
        wrap.appendChild(document.createTextNode(' ' + cached.rating.toFixed(1)));
        if (hasLikes || hasDislikes) wrap.appendChild(sep());
      }
      if (hasLikes) {
        const likeIcon = createSvgIconFromString(LOCKUP_LIKE_SVG, 14);
        if (likeIcon) wrap.appendChild(likeIcon);
        wrap.appendChild(document.createTextNode(' ' + FormatterNumber(cached.likes, 0)));
        if (hasDislikes) wrap.appendChild(sep());
      }
      if (hasDislikes) {
        const dislikeIcon = createSvgIconFromString(LOCKUP_DISLIKE_SVG, 14);
        if (dislikeIcon) wrap.appendChild(dislikeIcon);
        wrap.appendChild(document.createTextNode(' ' + FormatterNumber(cached.dislikes, 0)));
      }
      row.appendChild(wrap);
      meta.appendChild(row);
      lockup.setAttribute('data-yt-tools-lockup-stats', videoId);
    });
  }

  function getVideoIdFromShortsLockup(item) {
    if (item.dataset.ytToolsShortsVideoId) return item.dataset.ytToolsShortsVideoId;
    var a = item.querySelector('a[href^="/shorts/"]');
    if (!a) return null;
    var m = (a.getAttribute('href') || '').match(/\/shorts\/([^/?]+)/);
    return m ? m[1] : null;
  }

  function injectShortsLockupCachedStats() {
    if (!window.location.href.includes('youtube.com')) return;
    // Process inner lockup (has metadata); v2 wraps it and would duplicate
    document.querySelectorAll('ytm-shorts-lockup-view-model').forEach(function (item) {
      if (item.hasAttribute('data-yt-tools-shorts-stats')) return;
      var videoId = getVideoIdFromShortsLockup(item);
      if (!videoId) return;
      var cached = getLikesDislikesFromPersistedCache(videoId);
      if (!cached) return;
      var hasLikes = cached.likes != null;
      var hasDislikes = cached.dislikes != null;
      if (!hasLikes && !hasDislikes) return;
      var subhead = item.querySelector(
        '.ShortsLockupViewModelHostOutsideMetadataSubhead,' +
        '.shortsLockupViewModelHostOutsideMetadataSubhead,' +
        '.ShortsLockupViewModelHostMetadataSubhead,' +
        '.shortsLockupViewModelHostMetadataSubhead'
      );
      if (!subhead || !subhead.parentElement) return;
      var wrap = document.createElement('span');
      wrap.className = 'yt-core-attributed-string yt-content-metadata-view-model__metadata-text yt-core-attributed-string--white-space-pre-wrap yt-core-attributed-string--link-inherit-color yt-tools-shorts-stats-row';
      wrap.setAttribute('dir', 'auto');
      wrap.setAttribute('role', 'text');
      wrap.setAttribute('style', 'color: #aaa !important;');
      var sep = function () { return document.createTextNode(' \u00b7 '); };
      if (hasLikes) {
        var likeIcon = createSvgIconFromString(LOCKUP_LIKE_SVG, 12);
        if (likeIcon) { likeIcon.style.setProperty('color', '#aaa', 'important'); wrap.appendChild(likeIcon); }
        wrap.appendChild(document.createTextNode(' ' + FormatterNumber(cached.likes, 0)));
        if (hasDislikes) wrap.appendChild(sep());
      }
      if (hasDislikes) {
        var dislikeIcon = createSvgIconFromString(LOCKUP_DISLIKE_SVG, 12);
        if (dislikeIcon) { dislikeIcon.style.setProperty('color', '#aaa', 'important'); wrap.appendChild(dislikeIcon); }
        wrap.appendChild(document.createTextNode(' ' + FormatterNumber(cached.dislikes, 0)));
      }
      var row = document.createElement('div');
      row.className = 'yt-tools-shorts-stats-wrap';
      row.setAttribute('style', 'color: #aaa !important;');
      row.appendChild(wrap);
      subhead.parentElement.appendChild(row);
      item.setAttribute('data-yt-tools-shorts-stats', videoId);
    });
  }

  function createLockupStatsObserver(target) {
    var lockupStatsDebounceT = null;
    var lockupStatsScheduled = false;
    var obs = new MutationObserver(function () {
      if (lockupStatsScheduled) return;
      lockupStatsScheduled = true;
      clearTimeout(lockupStatsDebounceT);
      lockupStatsDebounceT = setTimeout(function () {
        lockupStatsScheduled = false;
        if (!window.location.href.includes('youtube.com')) return;
        injectLockupCachedStats();
        injectShortsLockupCachedStats();
        // Extra passes for late-rendered lockups (infinite scroll / related column / SPA)
        [500, 1100, 2000].forEach(function (delay) {
          setTimeout(function () {
            if (!window.location.href.includes('youtube.com')) return;
            injectLockupCachedStats();
            injectShortsLockupCachedStats();
          }, delay);
        });
      }, 280);
    });
    obs.observe(target, { childList: true, subtree: true });
    return obs;
  }

  function retargetLockupStatsObserverIfNeeded() {
    if (!window.location.href.includes('youtube.com/watch')) return;
    var secondary = document.getElementById('secondary') || document.querySelector('ytd-watch-next-secondary-results-renderer');
    if (!secondary || !secondary.parentNode) return;
    if (__ytToolsRuntime.lockupCachedStatsObserveTarget === secondary) return;
    var obs = __ytToolsRuntime.lockupCachedStatsObserver;
    if (!obs) return;
    obs.disconnect();
    __ytToolsRuntime.lockupCachedStatsObserver = createLockupStatsObserver(secondary);
    __ytToolsRuntime.lockupCachedStatsObserveTarget = secondary;
  }

  function hasUnprocessedLockups() {
    var normal = document.querySelectorAll('yt-lockup-view-model:not([data-yt-tools-lockup-stats])').length > 0;
    var shorts = document.querySelectorAll('ytm-shorts-lockup-view-model:not([data-yt-tools-shorts-stats])').length > 0;
    return normal || shorts;
  }

  function runLockupCachedStatsCatchUp() {
    if (!window.location.href.includes('youtube.com')) return;
    if (document.visibilityState !== 'visible') return;
    if (!hasUnprocessedLockups()) return;
    injectLockupCachedStats();
    injectShortsLockupCachedStats();
  }

  function setupLockupCachedStats() {
    if (!window.location.href.includes('youtube.com')) return;
    injectLockupCachedStats();
    injectShortsLockupCachedStats();
    var secondary = document.getElementById('secondary') || document.querySelector('ytd-watch-next-secondary-results-renderer');
    var observeTarget = secondary && secondary.parentNode ? secondary : document.body;
    if (__ytToolsRuntime.lockupCachedStatsObserver) {
      if (observeTarget !== __ytToolsRuntime.lockupCachedStatsObserveTarget) {
        __ytToolsRuntime.lockupCachedStatsObserver.disconnect();
        __ytToolsRuntime.lockupCachedStatsObserver = createLockupStatsObserver(observeTarget);
        __ytToolsRuntime.lockupCachedStatsObserveTarget = observeTarget;
      }
      return;
    }
    __ytToolsRuntime.lockupCachedStatsObserver = createLockupStatsObserver(observeTarget);
    __ytToolsRuntime.lockupCachedStatsObserveTarget = observeTarget;
    // Catch-up interval: apply stats to any new cards (scroll, filters, SPA) every 1.8s when there are unprocessed lockups
    if (!__ytToolsRuntime.lockupCachedStatsIntervalId) {
      __ytToolsRuntime.lockupCachedStatsIntervalId = setInterval(runLockupCachedStatsCatchUp, 1800);
    }
  }

  // ------------------------------
  // Feature: Bookmarks per video (persisted)
  // ------------------------------
  function getBookmarksForVideo(videoId) {
    const all = readJsonGM(STORAGE_KEYS_MDCM.BOOKMARKS, {});
    const list = Array.isArray(all[videoId]) ? all[videoId] : [];
    return { all, list };
  }

  function saveBookmark(videoId, seconds, label) {
    const { all, list } = getBookmarksForVideo(videoId);
    const t = Math.max(0, Math.floor(Number(seconds) || 0));
    const exists = list.some(b => b && b.t === t);
    const item = { t, label: (label || formatTimeShort(t)).trim(), createdAt: Date.now() };
    const nextList = exists ? list.map(b => (b.t === t ? item : b)) : [...list, item];
    nextList.sort((a, b) => a.t - b.t);
    all[videoId] = nextList;
    writeJsonGM(STORAGE_KEYS_MDCM.BOOKMARKS, all);
  }

  function deleteBookmark(videoId, seconds) {
    const { all, list } = getBookmarksForVideo(videoId);
    const t = Math.max(0, Math.floor(Number(seconds) || 0));
    all[videoId] = list.filter(b => b && b.t !== t);
    writeJsonGM(STORAGE_KEYS_MDCM.BOOKMARKS, all);
  }

  function renderBookmarksPanel(videoId) {
    const panel = $id('yt-bookmarks-panel');
    if (!panel) return;

    const { list } = getBookmarksForVideo(videoId);
    if (!list.length) {
      panel.innerHTML = `<div class="yt-bm-empty">No bookmarks yet. Click ★ to save one.</div>`;
      return;
    }

    panel.innerHTML = list
      .map((b) => {
        const time = formatTimeShort(b.t);
        const safeLabel = (b.label || time).replace(/</g, '&lt;').replace(/>/g, '&gt;');
        return `
          <div class="yt-bm-item">
            <button type="button" class="yt-bm-go" data-action="go" data-t="${b.t}" title="Go to ${time}">${time}</button>
            <div class="yt-bm-label" title="${safeLabel}">${safeLabel}</div>
            <button type="button" class="yt-bm-del" data-action="del" data-t="${b.t}" title="Delete">✕</button>
          </div>
        `;
      })
      .join('');
  }

  function applyBookmarksIfEnabled(settings) {
    const addBtn = $id('yt-bookmark-add');
    const toggleBtn = $id('yt-bookmark-toggle');
    const panel = $id('yt-bookmarks-panel');

    if (!addBtn || !toggleBtn || !panel) return;

    const enabled = !!settings?.bookmarks;
    addBtn.style.display = enabled ? 'inline-flex' : 'none';
    toggleBtn.style.display = enabled ? 'inline-flex' : 'none';
    panel.style.display = enabled && __ytToolsRuntime.bookmarksPanelOpen ? 'block' : 'none';

    if (!enabled) return;

    const videoId = getCurrentVideoId();
    if (!videoId) return;
    renderBookmarksPanel(videoId);

    if (__ytToolsRuntime.bookmarkClickHandlerInitialized) return;
    __ytToolsRuntime.bookmarkClickHandlerInitialized = true;

    document.addEventListener('click', (e) => {
      const target = e.target;
      if (!(target instanceof Element)) return;

      const add = target.closest('#yt-bookmark-add');
      const tog = target.closest('#yt-bookmark-toggle');
      const actionBtn = target.closest('[data-action][data-t]');

      if (add) {
        e.preventDefault();
        e.stopPropagation();
        const v = $e('video');
        const vid = getCurrentVideoId();
        if (!v || !vid) return;
        const t = Math.floor(v.currentTime || 0);
        const defaultLabel = formatTimeShort(t);
        const label = prompt('Bookmark name (optional):', defaultLabel) || defaultLabel;
        saveBookmark(vid, t, label);
        __ytToolsRuntime.bookmarksPanelOpen = true;
        panel.style.display = 'block';
        renderBookmarksPanel(vid);
        Notify('success', `Bookmark saved at ${defaultLabel}`);
        return;
      }

      if (tog) {
        e.preventDefault();
        e.stopPropagation();
        __ytToolsRuntime.bookmarksPanelOpen = !__ytToolsRuntime.bookmarksPanelOpen;
        panel.style.display = __ytToolsRuntime.bookmarksPanelOpen ? 'block' : 'none';
        const vid = getCurrentVideoId();
        if (vid && __ytToolsRuntime.bookmarksPanelOpen) renderBookmarksPanel(vid);
        return;
      }

      if (actionBtn) {
        e.preventDefault();
        e.stopPropagation();
        const action = actionBtn.getAttribute('data-action');
        const t = Number(actionBtn.getAttribute('data-t'));
        const v = $e('video');
        const vid = getCurrentVideoId();
        if (!v || !vid) return;
        if (action === 'go') {
          v.currentTime = Math.max(0, t || 0);
          v.play?.().catch(() => {});
        } else if (action === 'del') {
          deleteBookmark(vid, t);
          renderBookmarksPanel(vid);
        }
      }
    });
  }

  // ------------------------------
  // Feature: Like vs Dislike bar
  // ------------------------------
  function parseCountText(text) {
    if (!text) return null;
    const s0 = String(text).trim().toLowerCase();
    if (!s0) return null;
    let mult = 1;
    let s = s0.replace(/\s+/g, '');
    if (s.includes('mil')) {
      mult = 1000;
      s = s.replace('mil', '');
    } else if (s.includes('k')) {
      mult = 1000;
      s = s.replace('k', '');
    } else if (s.includes('m')) {
      mult = 1000000;
      s = s.replace('m', '');
    }
    // normalize decimal separators
    s = s.replace(/[^\d.,]/g, '');
    if (!s) return null;
    // If both separators exist, assume last is decimal
    const lastDot = s.lastIndexOf('.');
    const lastComma = s.lastIndexOf(',');
    let nStr = s;
    if (lastDot !== -1 && lastComma !== -1) {
      const dec = Math.max(lastDot, lastComma);
      const intPart = s.slice(0, dec).replace(/[.,]/g, '');
      const decPart = s.slice(dec + 1);
      nStr = `${intPart}.${decPart}`;
    } else {
      // Use dot as decimal
      nStr = s.replace(',', '.');
    }
    const num = Number.parseFloat(nStr);
    if (!Number.isFinite(num)) return null;
    return Math.round(num * mult);
  }

  async function ensureDislikesForCurrentVideo() {
    const videoId = getCurrentVideoId();
    if (!videoId) return null;
    const now = Date.now();
    if (__ytToolsRuntime.dislikesCache.videoId === videoId && __ytToolsRuntime.dislikesCache.dislikes != null && (now - __ytToolsRuntime.dislikesCache.ts) < 10 * 60 * 1000) {
      return __ytToolsRuntime.dislikesCache.dislikes;
    }
    const persisted = getLikesDislikesFromPersistedCache(videoId);
    if (persisted && persisted.dislikes != null) {
      __ytToolsRuntime.dislikesCache = { videoId, dislikes: persisted.dislikes, ts: now };
      return persisted.dislikes;
    }
    try {
      const res = await fetch(`${apiDislikes}${videoId}`);
      const data = await res.json();
      const dislikes = Number(data?.dislikes);
      const viewCount = Number(data?.viewCount);
      const rating = Number(data?.rating);
      if (Number.isFinite(dislikes)) {
        __ytToolsRuntime.dislikesCache = { videoId, dislikes, ts: now };
        const likes = getLikesFromDom();
        setLikesDislikesToPersistedCache(videoId, likes != null ? likes : undefined, dislikes, Number.isFinite(viewCount) ? viewCount : undefined, (Number.isFinite(rating) && rating >= 0 && rating <= 5) ? rating : undefined);
        return dislikes;
      }
    } catch (e) {}
    return null;
  }

  function getLikesFromDom() {
    // Try grab visible like count (YouTube UI varies a lot)
    const likeBtn =
      $e('#top-level-buttons-computed like-button-view-model button-view-model button') ||
      $e('#top-level-buttons-computed like-button-view-model button') ||
      $e('#top-level-buttons-computed ytd-toggle-button-renderer:nth-child(1)') ||
      $e('segmented-like-dislike-button-view-model like-button-view-model');
    if (!likeBtn) return null;

    // Prefer visible counter first; aria-label can include locale thousands separators (17.606) that are ambiguous.
    const candidates = [
      likeBtn.querySelector?.('.yt-spec-button-shape-next__button-text-content')?.textContent,
      likeBtn.textContent,
      likeBtn.getAttribute?.('aria-label'),
    ].filter(Boolean);

    for (const txt of candidates) {
      const n = parseCountText(txt);
      if (n != null) return n;
    }
    return null;
  }

  function updateLikeDislikeBar(likes, dislikes) {
    // Prefer placing it above the "copy description" button (as requested).
    const copyDesc = $id('button_copy_description');
    const host =
      $e('#top-level-buttons-computed') ||
      $e('ytd-watch-metadata #top-level-buttons-computed');
    if (!host && !copyDesc) return;

    let bar = $id('yt-like-dislike-bar-mdcm');
    if (!bar) {
      bar = document.createElement('div');
      bar.id = 'yt-like-dislike-bar-mdcm';
      bar.innerHTML = `<div class="like"></div><div class="dislike"></div>`;
      if (copyDesc) {
        copyDesc.insertAdjacentElement('beforebegin', bar);
      } else {
        host.appendChild(bar);
      }
    } else if (copyDesc && bar.previousElementSibling !== copyDesc) {
      // Keep it near the copy description area if the DOM changed
      try { copyDesc.insertAdjacentElement('beforebegin', bar); } catch (e) {}
    }

    if (!Number.isFinite(likes) || !Number.isFinite(dislikes) || likes + dislikes <= 0) {
      bar.style.display = 'none';
      return;
    }

    const total = likes + dislikes;
    const likePct = Math.max(0, Math.min(100, (likes / total) * 100));
    const dislikePct = 100 - likePct;
    bar.style.display = 'block';
    const likeEl = bar.querySelector('.like');
    const dislikeEl = bar.querySelector('.dislike');
    likeEl.style.width = `${likePct}%`;
    dislikeEl.style.width = `${dislikePct}%`;
    bar.title = `Likes: ${likes.toLocaleString()} | Dislikes: ${dislikes.toLocaleString()}`;
  }

  async function applyLikeDislikeBarIfEnabled(settings) {
    if (!settings?.likeDislikeBar) {
      const existing = $id('yt-like-dislike-bar-mdcm');
      if (existing) existing.style.display = 'none';
      return;
    }
    if (!window.location.href.includes('youtube.com/watch')) return;
    const videoId = getCurrentVideoId();
    if (!videoId) return;
    const dislikes = await ensureDislikesForCurrentVideo();
    let likes = getLikesFromDom();
    if (likes == null) {
      const persisted = getLikesDislikesFromPersistedCache(videoId);
      if (persisted?.likes != null) likes = persisted.likes;
    }
    if (dislikes == null || likes == null) return;
    updateLikeDislikeBar(likes, dislikes);
  }

  // Retry helper (YT often renders likes late; keep it lightweight)
  function scheduleLikeBarUpdate(settings, attempts = 4) {
    if (!settings?.likeDislikeBar) return;
    let i = 0;
    const tick = async () => {
      i += 1;
      await applyLikeDislikeBarIfEnabled(settings);
      const bar = $id('yt-like-dislike-bar-mdcm');
      if (bar && bar.style.display !== 'none') return;
      if (i < attempts) setTimeout(tick, 800);
    };
    setTimeout(tick, 300);
  }

//   Dislikes video
  async function videoDislike() {

    validoUrl = document.location.href;

    const validoVentana = $e('#below > ytd-watch-metadata > div');
    if (validoVentana != undefined && document.location.href.split('?v=')[0].includes('youtube.com/watch')) {
        validoUrl = paramsVideoURL();
        let dislikes = null;
        const persisted = getLikesDislikesFromPersistedCache(validoUrl);
        if (persisted && persisted.dislikes != null) {
          dislikes = persisted.dislikes;
        } else {
          const urlShorts = `${apiDislikes}${validoUrl}`;
          try {
            const respuesta = await fetch(urlShorts);
            const datosShort = await respuesta.json();
            dislikes = Number(datosShort?.dislikes);
            if (Number.isFinite(dislikes)) {
              const likes = getLikesFromDom();
              const viewCount = Number(datosShort?.viewCount);
              const rating = Number(datosShort?.rating);
              setLikesDislikesToPersistedCache(validoUrl, likes != null ? likes : undefined, dislikes, Number.isFinite(viewCount) ? viewCount : undefined, (Number.isFinite(rating) && rating >= 0 && rating <= 5) ? rating : undefined);
            }
          } catch (error) {
            console.log(error);
          }
        }
        if (dislikes != null) {
          const dislikes_content = $e('#top-level-buttons-computed > segmented-like-dislike-button-view-model > yt-smartimation > div > div > dislike-button-view-model > toggle-button-view-model > button-view-model > button');
          if (dislikes_content !== undefined) {
            dislikes_content.style = 'width: 90px';
            dislikes_content.innerHTML = `
              <svg class="svg-dislike-icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3" /></svg>
              ${FormatterNumber(dislikes, 0)}`;
          }
          __ytToolsRuntime.dislikesCache = { videoId: validoUrl, dislikes, ts: Date.now() };
          try {
            const st = JSON.parse(GM_getValue('ytSettingsMDCM', '{}'));
            scheduleLikeBarUpdate(st, 5);
          } catch (e) {}
        }
    }
  }

  // dislikes shorts + views button (viewCount from Return YouTube Dislike API)
  async function shortDislike() {
    validoUrl = document.location.href;
    const validoVentanaShort = $m(
      "#button-bar > reel-action-bar-view-model > dislike-button-view-model > toggle-button-view-model > button-view-model > label > div > span"
    );

    if (validoVentanaShort != undefined && document.location.href.split('/')[3] === 'shorts') {
      validoUrl = document.location.href.split('/')[4];
      let dislikes = null;
      let viewCount = null;
      let rating = null;
      const persisted = getLikesDislikesFromPersistedCache(validoUrl);
      if (persisted && persisted.dislikes != null) {
        dislikes = persisted.dislikes;
        viewCount = persisted.viewCount ?? null;
        rating = persisted.rating ?? null;
      } else {
        const urlShorts = `${apiDislikes}${validoUrl}`;
        try {
          const respuesta = await fetch(urlShorts);
          const datosShort = await respuesta.json();
          dislikes = Number(datosShort?.dislikes);
          viewCount = Number(datosShort?.viewCount);
          rating = Number(datosShort?.rating);
          if (Number.isFinite(dislikes)) setLikesDislikesToPersistedCache(validoUrl, undefined, dislikes, Number.isFinite(viewCount) ? viewCount : undefined, (Number.isFinite(rating) && rating >= 0 && rating <= 5) ? rating : undefined);
        } catch (error) {
          console.log(error);
        }
      }
      if (dislikes != null) {
        for (let i = 0; i < validoVentanaShort.length; i++) {
          validoVentanaShort[i].textContent = `${FormatterNumber(dislikes, 0)}`;
        }
      }
      if (__ytToolsRuntime.updateShortsViewsButton) __ytToolsRuntime.updateShortsViewsButton(validoUrl, viewCount);
      if (__ytToolsRuntime.updateShortsRatingButton) __ytToolsRuntime.updateShortsRatingButton(validoUrl, rating);
    }
  }

  // Url change in second load
  let prevUrl;
  let showDislikes = false;

  setInterval(() => {
    const svgDislike = $e('.svg-dislike-ico'); // Check svg in dom
    const currUrl = window.location.href;
    if (prevUrl !== undefined && currUrl !== prevUrl && !svgDislike && showDislikes) {
      setTimeout(async() => {
            await videoDislike();
            await shortDislike();
      },2000)
    }
    prevUrl = currUrl;
  }, 1000);



  // Create a Trusted Types policy
  let policy = null;
  try {
    const tt = (typeof unsafeWindow !== 'undefined' ? unsafeWindow.trustedTypes : window.trustedTypes);
    if (tt) {
      policy = tt.defaultPolicy;
      if (!policy) {
        try {
          policy = tt.createPolicy('default', { createHTML: (s) => s });
        } catch (e) {
          policy = tt.defaultPolicy || null;
        }
      }
    }
  } catch (e) {
    policy = null;
  }

  // Styles for our enhancement panel
  GM_addStyle(`
       @import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");
      @import url("https://cdn.jsdelivr.net/npm/[email protected]/dist/css/iziToast.min.css");
      :root {
              --primary-custom: #ff0000 !important;
              --bg-dark-custom: #1a1a1a !important;
              --bg-card-custom: #252525 !important;
              --text-custom: #ffffff !important;
              --text-custom-secondary: #9e9e9e !important;
              --accent-custom: #ff4444 !important;
          }
        body .container-mdcm {
              font-family: "Inter", -apple-system, sans-serif;
              color: var(--yt-enhance-menu-text, --text-custom);
        }
        #toggle-button:hover {
          background-color: rgba(255,255,255,0.1);
          border-radius: 50%;
          opacity: 1 !important;
          }
        .container-mdcm {
            width: 420px;
            max-width: 420px;
            background-color: var(--yt-enhance-menu-bg, #252525);
            border-radius: 16px 16px 0 0;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            backdrop-filter: blur(15px);
            border: 1px solid rgba(255, 255, 255, 0.1);
            display: flex;
            flex-direction: column;
            max-height: 80vh;
            overflow-y: auto;
            overflow-x: hidden;
            height: auto;
        }

        #shareDropdown {
        display: none;
        position: absolute;
        top: 50px;
        right: 100px;
        background-color: var(--yt-enhance-menu-bg, #252525);
        border-radius: 6px;
        padding: 10px;
        box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 12px;
        z-index: 11;
        }
        #shareDropdown a {
        color: var(--text-custom);
        text-decoration: none;
        line-height: 2;
        font-size: 14px;
        }
        #shareDropdown a:hover {
        color: var(--primary-custom);
        }
        .header-mdcm {
            padding: 12px 16px;
            border-bottom: 1px solid rgba(255,255,255,0.1);
            position: sticky;
            top: 0;
            background-color: var(--yt-enhance-menu-bg, #252525);
            border-radius: 16px 16px 0 0;
            z-index: 10;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .header-mdcm h1 {
            font-size: 16px;
            margin: 0;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 8px;
        }


        .header-mdcm i {
         color: var(--primary-custom)
        }


        .icons-mdcm {
            display: flex;
            gap: 4px;
        }
        .icons-mdcm i {
          color: var(--yh-enhance-menu-accent, var(--text-custom));
        }


        .icon-btn-mdcm {
            background: rgba(255,255,255,0.1);
            border: none;
            color: var(--text-custom);
            width: 28px;
            height: 28px;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.3s;
        }

        .icon-btn-mdcm:hover {
            background: rgba(255,255,255,0.2);
            transform: translateY(-2px);
        }

        .icon-btn-mdcm i {
         color: var(--text-custom);
         outline: none;
         text-decoration: none;
        }

        .tabs-mdcm {
            padding: 10px 12px;
            margin: 10px 0;
            position: sticky;
            top: 50px;
            background-color: var(--yt-enhance-menu-bg, #252525);
            z-index: 10;
            display: flex;
            gap: 8px;
            -ms-overflow-style: none;
            padding-bottom: 8px;
        }



        .tabs-mdcm::-webkit-scrollbar {
            height: 0px;
            background-color: transparent;
        }

        .tabs-mdcm:hover::-webkit-scrollbar {
            height: 6px;
        }

        .tabs-mdcm::-webkit-scrollbar-thumb {
            background-color: rgba(255, 0, 0, 0.5);
            border-radius: 3px;
        }

        .tabs-mdcm::-webkit-scrollbar-track {
            background-color: transparent;
        }

        .tab-mdcm {
            padding: 6px 10px;
            border: none;
            background: rgba(255,255,255,0.05);
            cursor: pointer;
            font-size: 12px;
            color: var(--text-custom-secondary);
            border-radius: 6px;
            transition: all 0.3s;
            flex: 1;
            display: flex;
            align-items: center;
            gap: 6px;
            flex-shrink: 0;
            justify-content: center;
            white-space: nowrap;
        }

        .tab-mdcm svg {
            width: 14px;
            height: 14px;
            fill: currentColor;
        }

        .tab-mdcm.active {
            background: var(--yt-enhance-menu-accent, --primary-custom) !important;
            color: var(--text-custom);
            font-weight: 500;
            box-shadow: 0 4px 12px rgba(255,0,0,0.2);
        }

        .tab-mdcm:hover:not(.active) {
            background: rgba(255,255,255,0.1);
            transform: translateY(-1px);
        }

        .options-mdcm {
            flex: 1;
            overflow-y: auto;
            padding: 0 16px 0;
            scrollbar-width: thin;
            scrollbar-color: var(--primary-custom) var(--bg-dark-custom);
            max-height: 300px;
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 8px;
        }

        .options-settings-mdcm {
            flex: 1;
            overflow-y: auto;
            padding: 0 16px 0;
            scrollbar-width: thin;
            scrollbar-color: var(--primary-custom) var(--bg-dark-custom);
            max-height: 300px;
            display: grid;
            gap: 8px;
        }

         .card-items-end {
          display: flex;
          justify-content: space-between;
          align-items: center;
          width: 175px;
        }

         .radio-mdcm {
            width: 14px;
            height: 14px;
            accent-color: var(--primary-custom);
        }

        .color-picker-mdcm {
            width: 50px;
            height: 24px;
            border: 1px solid rgba(255, 255, 255, 0.2);
            background: rgba(255, 255, 255, 0.1);
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.3s;
        }

        .color-picker-mdcm:hover {
            background: rgba(255, 255, 255, 0.2);
        }

        .options-mdcm::-webkit-scrollbar, .options-settings-mdcm::-webkit-scrollbar {
            width: 6px;
        }

        .options-mdcm::-webkit-scrollbar-track, .options-settings-mdcm::-webkit-scrollbar-track {
            background: var(--bg-dark-custom);
            border-radius: 3px;
        }

        .options-mdcm::-webkit-scrollbar-thumb, .options-settings-mdcm::-webkit-scrollbar-thumb {
            background: var(--primary-custom);
            border-radius: 3px;
        }

        .options-mdcm::-webkit-scrollbar-thumb:hover, .options-settings-mdcm::-webkit-scrollbar-thumb:hover {
            background: var(--accent-custom);
        }

        .options-mdcm::after, .options-settings-mdcm::after {
            content: '';
            display: block;
        }

        .option-mdcm {
            display: grid;
            grid-template-columns: auto 1fr;
            align-items: center;
            margin-bottom: 0;
            padding: 5px;
            background: rgba(255,255,255,0.05);
            border-radius: 6px;
            transition: all 0.3s;
            border: 1px solid rgba(255,255,255,0.05);
            color: var(--yt-)
            gap: 6px;
        }

        .option-mdcm:hover {
            background: rgba(255,255,255,0.08);
            border-color: rgba(255,255,255,0.1);
        }
        .option-settings-mdcm {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 0;
          padding: 6px;
          background: rgba(255, 255, 255, 0.05);
          border-radius: 6px;
          transition: all 0.3s;
          border: 1px solid rgba(255, 255, 255, 0.05);
          gap: 6px;
        }

        .option-settings-mdcm:hover {
            background: rgba(255,255,255,0.08);
            border-color: rgba(255,255,255,0.1);
        }
            .tab-content {
            display: none;
        }
            .tab-content.active {
                display: block;
                margin-bottom: 10px;
            }

        .checkbox-mdcm {
            width: 14px;
            height: 14px;
            accent-color: var(--yt-enhance-menu-accent, --primary-custom) !important;
        }

        label {
            font-size: 12px;
            color: var(--text-custom);
        }

        .slider-container-mdcm {
            background: rgba(255,255,255,0.05);
            padding: 10px;
            border-radius: 6px;
        }

        .slider-mdcm {
            width: 100%;
            height: 3px;
            accent-color: var(--yt-enhance-menu-accent, --primary-custom) !important;
            margin: 10px 0;
        }

        .reset-btn-mdcm {
            padding: 5px 10px;
            border: 1px solid rgba(255,255,255,0.2);
            background: rgba(255,255,255,0.1);
            color: var(--text-custom);
            border-radius: 4px;
            cursor: pointer;
            font-size: 11px;
            transition: all 0.3s;
        }

        .reset-btn-mdcm:hover {
            background: rgba(255,255,255,0.2);
        }

        .quality-selector-mdcm select {
            position: relative;
            padding: 3px;
            outline: none;
            border-radius: 4px;
            border: 1px solid rgba(255,255,255,0.2);
            background: var(--yt-enhance-menu-accent, --primary-custom) !important;
            color: var(--text-custom);
            width: fit-content;
            appearance: none;
            cursor: pointer;
            font-size: 11px;
        }


        .quality-selector-mdcm {
            background: rgba(255,255,255,0.05);
            padding: 10px;
            border-radius: 6px;
        }

        .select-wrapper-mdcm {
          position: relative;
          display: inline-block;
        }

        .select-wrapper-mdcm select {
          -webkit-appearance: auto;
          -moz-appearance: auto;
        }

        .actions-mdcm {
            position: sticky;
            top: 0;
            padding: 12px 16px;
            backdrop-filter: blur(15px);
            background-color: var(--yt-enhance-menu-bg, #252525);
            display: flex;
            gap: 6px;
            width: 390px;
            border-radius: 0 0 16px 16px;
            justify-content: space-between;
            align-items: center;
        }

        .action-buttons-mdcm {
            display: flex;
            gap: 6px;
        }

        .action-btn-mdcm {
            flex: 1;
            padding: 8px;
            border: none;
            border-radius: 6px;
            background: var(--primary-custom);
            color: var(--text-custom);
            cursor: pointer;
            font-size: 12px;
            font-weight: 500;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 4px;
            box-shadow: 0 4px 12px rgba(255,0,0,0.2);
        }

        .action-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 16px rgba(255,0,0,0.3);
        }

        textarea.textarea-mdcm {
            width: 100%;
            height: 50px;
            margin-top: 10px;
            margin-bottom: 12px;
            padding: 8px;
            background: rgba(255,255,255,0.05);
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 6px;
            color: var(--text-custom);
            font-size: 11px;
            resize: none;
            transition: all 0.3s;
        }

        textarea.textarea-mdcm:focus {
            outline: none;
            border-color: var(--primary-custom);
            background: rgba(255,255,255,0.08);
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .container-mdcm {
            animation: fadeIn 0.3s ease-out;
        }

        .developer-mdcm {
            font-size: 10px;
            color: var(--text-custom-secondary);
        }

        .developer-mdcm a {
            color: var(--primary-custom);
            text-decoration: none;
        }

        /* Styles for the import/export area */
        #importExportArea {
            display: none;
            padding: 16px;
            margin: 0px;
            background-color: var(--yt-enhance-menu-bg, #252525);
            border-radius: 16px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
        }

        #importExportArea.active {
            display: block;
            margin-top: 10px;
        }

        /* Style the textarea */
        #importExportArea textarea {
            width: 370px;
            height: 20px;
            margin-bottom: 10px;
            padding: 8px;
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 6px;
            background-color: rgba(255, 255, 255, 0.05);
            color: var(--text-custom);
            font-size: 12px;
            resize: vertical;
        }

        /* Style the buttons */
        #importExportArea .action-buttons-mdcm  {
            display: flex;
            justify-content: space-between;
            gap: 10px;
        }

        #importExportArea .action-btn-mdcm {
            flex: 1;
            padding: 10px 16px;
            border: none;
            border-radius: 6px;
            background-color: var(--primary-custom);
            color: var(--text-custom);
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        #importExportArea .action-btn-mdcm:hover {
            background-color: var(--accent-custom);
        }

      #yt-stats {
      position: fixed;
      top: 60px;
      right: 20px;
      background: #1a1a1a;
      color: white;
      padding: 15px;
      border-radius: 10px;
      width: 320px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.4);
      font-family: Arial, sans-serif;
      display: none;
      }
  #yt-stats-toggle {
      font-size: 12px;
      color: #fff;
      padding: 12px 20px;
      border-radius: 5px;
      cursor: pointer;
  }
  .stat-row {
      margin: 15px 0;
  }
  .progress {
      height: 6px;
      overflow: hidden;
      background: #333;
      border-radius: 3px;
      margin: 8px 0;
  }
  .progress-bar {
      height: 100%;
      transition: width 0.3s;
  }
  .total-bar { background: #44aaff !important; }
  .video-bar { background: #00ff88 !important; }
  .shorts-bar { background: #ff4444 !important; }
  #cinematics {
    position: absolute !important;
    width: 90vw !important;
    height: 100vh ;
  }
    #cinematics div {
        position: fixed;
      inset: 0px;
      pointer-events: none;
      transform: scale(1.5, 2);
  }
      #cinematics > div > div > canvas:nth-child(1), #cinematics > div > div > canvas:nth-child(2) {
   position: absolute !important;
    width: 90vw !important;
    height: 100vh ;
      }

    // .html5-video-player.unstarted-mode {
    //  background-image: url('https://avatars.githubusercontent.com/u/54366580?v=4');
    // background-repeat: no-repeat;
    // background-position: 50% 50%;
    // display: flex;
    // justify-content: center;
    // align-items: center;
    // }

        #yt-enhancement-panel {
            position: fixed;
            top: 60px;
            right: 20px;
            z-index: 9999;
        }

        .color-picker {
            width: 100%;
            margin: 0;
            padding: 0;
            border: none;
            background: none;
        }
        .slider {
            width: 100%;
        }
         #toggle-panel {
            z-index: 10000;
            color: white;
            padding: 5px;
            border: none;
            cursor: pointer;
            display: flex;
            justify-content: center;
            transition: all 0.5s ease;
            width: 43px;
            border-radius: 100px;
        }

        #icon-menu-settings {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        padding: 7px;
        font-size: 20px;
        color: var(--yt-spec-icon-inactive);
        cursor: pointer;
        user-select: none;
        filter: drop-shadow(2px 4px 6px black);
        }

        .theme-option {
            margin-bottom: 15px;
        }
        .theme-option label {
            display: flex;
            align-items: center;
        }
       .theme-option {
    position: relative;
    width: auto;
    margin-bottom: 10px;
    padding: 10px;
    border-radius: 4px;
    cursor: pointer;
}

.theme-preview {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border-radius: 10px;
    border: 1px solid #000;
    z-index: 1;
}

.theme-option input[type="radio"] {
    position: relative;
    z-index: 2;
    margin-right: 10px;
    cursor: pointer;
}

.theme-name {
    position: relative;
    z-index: 2;
    font-size: 15px;
    color: #fff;
}

.theme-option label {
    display: flex;
    align-items: center;
    width: 100%;
    position: relative;
    z-index: 2;
}

  .buttons-tranlate, .select-traductor {
        background: #000;
        font-size: 10px;
        border: none;
        color: #fbf4f4 !important;
        padding: 3px 0;
        margin-left: 10px;
        width: 70px;
        border-radius: 10px;
        }
        .buttons-tranlate:hover {
        cursor: pointer;
        background-color: #6b6b6b;
        }
         button.botones_div {
         margin: 0;
         padding: 0;
         }
         button.botones_div:hover {
         cursor: pointer;
         color: #6b6b6b !important;
         }

        .tab-button:hover {
          background-color: #ec3203 !important;
          color: #ffffff !important;
          cursor: pointer;
        }

        .traductor-container {
            display: inline-block;
            align-items: center;
            gap: 8px;
            margin-top: 4px;
          }

        #eyes {
      opacity: 0;
      position: absolute;
      height: 24px;
      left: 0;
      width: 24px;
    }

    /* width */
    ::-webkit-scrollbar {
      width: 4px;
      height: 10px;
    }

    /* Track */
    ::-webkit-scrollbar-track {
      background: ##d5d5d5;

    }

    /* Handle */
    ::-webkit-scrollbar-thumb {
      background: #000;

    }

    .color-boxes {
      display: flex;
      gap: 8px;
    }
    .color-box {
      width: 20px;
      height: 20px;
      border: 1px solid rgb(221 221 221 / 60%);
      border-radius: 4px;
      cursor: pointer;
    }
    .color-box.selected {
      border: 2px solid var(--primary-custom);
      filter: drop-shadow(0px 1px 6px red);
    }

    .containerButtons {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-wrap: wrap;
      gap: 10px;
    }
    .containerButtons > button:hover {
      cursor: pointer;
    }

        /* Download Container Styles */
        .download-container {
          width: 50%;
          padding: 12px;
          border-radius: 8px;
          margin-top: 8px;
          transition: all 0.3s ease;
        }

        .download-container.video {
          background: linear-gradient(135deg, #ff4444, #cc0000);
          color: white;
        }

        .download-container.audio {
          background: linear-gradient(135deg, #00cc44, #009933);
          color: white;
        }

        .download-info {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 8px;
        }

        .download-text {
          font-weight: 600;
          font-size: 14px;
        }

        .download-quality {
          font-size: 12px;
          opacity: 0.9;
        }

        .progress-container {
          display: flex;
          align-items: center;
          gap: 10px;
          margin-bottom: 6px;
        }

        .progress-bar {
          flex: 1;
          height: 6px;
          background: rgba(255, 255, 255, 0.3);
          border-radius: 3px;
          overflow: hidden;
        }

        .progress-fill {
          height: 100%;
          background: rgba(255, 255, 255, 0.8);
          border-radius: 3px;
          width: 0%;
          transition: width 0.3s ease;
        }

        .progress-text {
          font-size: 12px;
          font-weight: 500;
          min-width: 30px;
        }

        .download-footer {
          font-size: 10px;
          opacity: 0.7;
          text-align: center;
        }
        .download-footer a {
          text-decoration: none;
          color: #fff;
        }

        .download-container.completed {
          color: #fff;
          background: linear-gradient(135deg, #00cc44, #009933) !important;
        }

        .download-container.completed .download-text {
          font-weight: 700;
        }

      /* Bookmarks panel (under video buttons) */
      .yt-bookmarks-panel {
        margin-top: 10px;
        background: rgba(255,255,255,0.06);
        border: 1px solid rgba(255,255,255,0.12);
        border-radius: 10px;
        padding: 8px;
      }
      .yt-bm-empty {
        font-size: 12px;
        color: var(--text-custom-secondary);
      }
      .yt-bm-item {
        display: grid;
        grid-template-columns: auto 1fr auto;
        gap: 8px;
        align-items: center;
        padding: 6px;
        border-radius: 8px;
      }
      .yt-bm-item:hover {
        background: rgba(255,255,255,0.06);
      }
      .yt-bm-go {
        border: none;
        border-radius: 6px;
        padding: 4px 8px;
        background: rgba(34,197,94,0.2);
        color: #fff;
        cursor: pointer;
        font-size: 12px;
        white-space: nowrap;
      }
      .yt-bm-label {
        font-size: 12px;
        color: var(--text-custom);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .yt-bm-del {
        border: none;
        border-radius: 6px;
        padding: 4px 8px;
        background: rgba(239,68,68,0.2);
        color: #fff;
        cursor: pointer;
        font-size: 12px;
      }

      /* Continue watching panel (under video buttons) */
      .yt-continue-watching-panel {
        margin-top: 10px;
        background: rgba(255,255,255,0.06);
        border: 1px solid rgba(255,255,255,0.12);
        border-radius: 10px;
        padding: 8px;
      }
      .yt-cw-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 10px;
        margin-bottom: 8px;
      }
      .yt-cw-header-title {
        font-size: 12px;
        font-weight: 600;
        color: var(--text-custom, #fff);
      }
      .yt-cw-clear {
        border: none;
        border-radius: 6px;
        padding: 4px 8px;
        background: rgba(239,68,68,0.18);
        color: #fff;
        cursor: pointer;
        font-size: 12px;
      }
      .yt-cw-empty {
        font-size: 12px;
        color: var(--text-custom-secondary, #aaa);
      }
      .yt-cw-item {
        display: grid;
        grid-template-columns: auto 1fr auto;
        gap: 10px;
        align-items: center;
        padding: 8px;
        border-radius: 10px;
      }
      .yt-cw-item:hover {
        background: rgba(255,255,255,0.06);
      }
      .yt-cw-thumb-wrap {
        width: 72px;
        height: 40px;
        border-radius: 8px;
        overflow: hidden;
        background: rgba(255,255,255,0.08);
        flex: none;
      }
      .yt-cw-thumb {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
      }
      .yt-cw-title {
        font-size: 12px;
        font-weight: 600;
        color: var(--text-custom, #fff);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        max-width: 520px;
      }
      .yt-cw-meta {
        font-size: 12px;
        color: var(--text-custom-secondary, #aaa);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .yt-cw-actions {
        display: flex;
        align-items: center;
        gap: 8px;
      }
      .yt-cw-go {
        border: none;
        border-radius: 6px;
        padding: 4px 8px;
        background: rgba(34,197,94,0.2);
        color: #fff;
        cursor: pointer;
        font-size: 12px;
        white-space: nowrap;
      }
      .yt-cw-del {
        border: none;
        border-radius: 6px;
        padding: 4px 8px;
        background: rgba(239,68,68,0.2);
        color: #fff;
        cursor: pointer;
        font-size: 12px;
      }

      /* Shorts channel name label (Home/feed Shorts lockups) */
      html:not([data-mdcm-shorts-channel-name="1"]) .yt-tools-shorts-channel-name {
        display: none !important;
      }
      .yt-tools-shorts-channel-name {
        font-size: 12px;
        line-height: 1.2;
        color: var(--yt-spec-text-secondary, #aaa);
        margin-bottom: 2px;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .yt-tools-shorts-stats-wrap {
        margin-top: 4px;
        font-size: 11px;
        line-height: 1.2;
        color: var(--yt-spec-text-secondary, #aaa);
      }
      .yt-tools-shorts-stats-wrap .yt-tools-shorts-stats-row {
        display: inline-flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 2px;
      }

      /* Like vs dislike bar (under likes/dislikes) */
      #yt-like-dislike-bar-mdcm {
        height: 6px;
        border-radius: 999px;
        overflow: hidden;
        margin-top: 6px;
        background: rgba(255,255,255,0.12);
        max-width: 305px;
      }
      #yt-like-dislike-bar-mdcm .like {
        height: 100%;
        background: #22c55e;
        float: left;
      }
      #yt-like-dislike-bar-mdcm .dislike {
        height: 100%;
        background: #ef4444;
        float: left;
      }

        .progress-retry-btn {
          position: absolute;
          top: 116px;
          right: 50%;
          width: 24px;
          height: 24px;
          border: none;
          border-radius: 50%;
          background: rgba(255, 255, 255, 0.2);
          color: white;
          cursor: pointer;
          display: flex;
          align-items: center;
          justify-content: center;
          font-size: 12px;
          transition: all 0.3s ease;
        }

        .progress-retry-btn:hover {
          background: rgba(255, 255, 255, 0.3);
          transform: scale(1.1);
        }

        .download-again-btn {
          position: absolute;
          top: 116px;
          left: 50%;
          width: 24px;
          height: 24px;
          border: none;
          border-radius: 50%;
          background: rgba(34, 197, 94, 0.35);
          color: white;
          cursor: pointer;
          display: flex;
          align-items: center;
          justify-content: center;
          font-size: 12px;
          transition: all 0.3s ease;
        }

        .download-again-btn:hover {
          background: rgba(34, 197, 94, 0.5);
          transform: scale(1.1);
        }

        .download-container {
          position: relative;
        }

        .download-actions {
          display: flex;
          gap: 8px;
          margin-bottom: 8px;
        }

        .download-btn {
          flex: 1;
          padding: 8px 16px;
          border: none;
          border-radius: 4px;
          font-weight: 600;
          font-size: 12px;
          cursor: pointer;
          transition: all 0.3s ease;
          color: white;
        }

        .download-btn.video-btn {
          background: linear-gradient(135deg, #ff6666, #ff4444);
        }

        .download-btn.audio-btn {
          background: linear-gradient(135deg, #00dd55, #00cc44);
        }

        .download-btn:hover {
          transform: translateY(-1px);
          box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }

        .download-btn:disabled {
          opacity: 0.6;
          cursor: not-allowed;
          transform: none;
        }

        .retry-btn {
          padding: 8px 16px;
          border: none;
          border-radius: 4px;
          font-weight: 600;
          font-size: 12px;
          cursor: pointer;
          transition: all 0.3s ease;
          background: linear-gradient(135deg, #ffaa00, #ff8800);
          color: white;
        }

        .retry-btn:hover {
          transform: translateY(-1px);
          box-shadow: 0 4px 8px rgba(0,0,0,0.2);
    }

      body {
      padding: 0;
      margin: 0;
      overflow-y: scroll;
      overflow-x: hidden;
      }
      .style-scope.ytd-comments {
      overflow-y: auto;
      overflow-x: hidden;
      height: auto;
      }
      ytd-comment-view-model[is-reply] #author-thumbnail.ytd-comment-view-model yt-img-shadow.ytd-comment-view-model, ytd-comment-view-model[is-creator-reply] #author-thumbnail.ytd-comment-view-model yt-img-shadow.ytd-comment-view-model {
        width: 40px;
        height: 40px;
        border-radius: 50%;
      }
        img.yt-img-shadow {
        border-radius: 50% !important;
        }
        #author-thumbnail.ytd-comment-view-model yt-img-shadow.ytd-comment-view-model {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          overflow: visible;
        }
      ytd-item-section-renderer.ytd-watch-next-secondary-results-renderer {
        --ytd-item-section-item-margin: 8px;
        overflow-y: auto;
        overflow-x: hidden;
        height: auto;
      }
      .right-section.ytcp-header {
      display: flex;
      flex: 1;
      align-items: center;
      gap: 45px;
      justify-content: end;
    }
      #meta.ytd-playlist-panel-video-renderer {
    min-width: 0;
    padding: 0 8px;
    display: flexbox;
    display: flex;
    flex-direction: column-reverse;
    flex: 1;
    flex-basis: 0.000000001px;
}

    .containerall {
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      padding-bottom: 30px;
      max-width: 800px;
      margin: auto;
    }
    }
    .container .botoncalidades {
      margin: 3px 2px;
      width: 24.6%;
    }

    .botoncalidades:first-child {
      background-color: #0af;
    }

    .botoncalidades:last-child {
      background-color: red;
      width: 100px;
    }

    .selectcalidades,
    .botoncalidades,
    .selectcalidadesaudio {
      width: 50%;
      height: 27.8px;
      background-color: #fff;
      color: #000;
      font-size: 25px;
      text-align: center;
      border: 1px solid black;
      border-radius: 10px;
      border: none;
      font-size: 20px;
      margin: 2px 2px;
    }

    .botoncalidades {
      width: 70px;
      height: 30px;
      background-color: rgb(4, 156, 22);
      border: 0px solid #000;
      color: #fff;
      font-size: 20px;
      border-radius: 10px;
      margin: 2px 2px;
    }

    .botoncalidades:hover,
    .bntcontainer:hover {
      cursor: pointer;
    }

   .ocultarframe,
    .ocultarframeaudio {
      display: none;
    }
      .checked_updates {
      cursor: pointer;
      }

      #export-config, #import-config {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        background-color: var(--yt-enhance-menu-accent, --primary-custom) !important;;
        color: #ffffff;
        border: none;
        padding: 5px;
      }
        #export-config:hover, #import-config:hover {
          background-color: #ff0000;
          color: #ffffff;
          cursor: pointer;
        }

        .yt-image-avatar-download {
          position: absolute;
          bottom: -10px;
          right: -14px;
          border: none;
          z-index: 1000;
          background: transparent;
          filter: drop-shadow(1px 0 6px red);
          color: var(--ytcp-text-primary);
          cursor: pointer;
        }

        .custom-classic-btn {
          display: flex;
          align-items: center;
          justify-content: center;
          background-color: rgba(255,255,255,0.1);
          border-radius: 50%;
          border: none;
          width: 48px;
          height: 48px;
          color: var(--yt-spec-icon-inactive);
          font-size: 24px;
          margin: 0px 8px;
          cursor: pointer;
        }
        .custom-classic-btn:hover {
          background-color: rgba(255,255,255,0.2);
        }
        .background-image-container {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 8px;
        margin: 10px 0;
      }

      .background-image-preview {
        width: 160px;
        height: 90px;
        border-radius: 10px;
        background-size: cover;
        background-position: center;
        border: 2px solid #444;
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: box-shadow 0.2s;
        box-shadow: 0 2px 8px rgba(0,0,0,0.08);
        overflow: hidden;
      }

      .background-image-preview:hover .background-image-overlay {
        opacity: 1;
      }

      .background-image-overlay {
        position: absolute;
        top: 0; left: 0; right: 0; bottom: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        color: #fff;
        background: rgba(0,0,0,0.35);
        font-size: 18px;
        opacity: 0;
        transition: opacity 0.2s;
        pointer-events: none;
      }

      .background-image-preview:hover .background-image-overlay,
      .background-image-preview:focus .background-image-overlay {
        opacity: 1;
      }

      .background-image-overlay i {
        font-size: 28px;
        margin-bottom: 4px;
      }

      .background-image-text {
        font-size: 13px;
        font-weight: 500;
        text-shadow: 0 1px 4px #000;
      }

      .remove-background-image {
        position: absolute;
        top: 6px;
        right: 6px;
        background: #e74c3c;
        color: #fff;
        border: none;
        border-radius: 50%;
        width: 26px;
        height: 26px;
        font-size: 18px;
        cursor: pointer;
        z-index: 2;
        display: none;
        align-items: center;
        justify-content: center;
        padding: 0;
        line-height: 1;
        box-shadow: 0 2px 8px rgba(0,0,0,0.15);
        transition: background 0.2s;
      }
      .remove-background-image:hover {
        background: #c0392b;
      }
      .background-image-preview.has-image .remove-background-image {
        display: flex;
      }

      ytd-feed-filter-chip-bar-renderer[not-sticky] #chips-wrapper.ytd-feed-filter-chip-bar-renderer {
        padding: 10px;
      }
      .text-description-download {
        font-size: 12px;
        text-align: center;
        margin-top: 10px;
        }
    `);


  // botons bottom video player

  const thumbnailVideo = `
  <button title="Image video" class="botones_div" type="button" id="imagen">

  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-photo-down" width="24"
    height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
    stroke-linecap="round" stroke-linejoin="round">
    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
    <path d="M15 8h.01"></path>
    <path d="M12.5 21h-6.5a3 3 0 0 1 -3 -3v-12a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v6.5"></path>
    <path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l4 4"></path>
    <path d="M14 14l1 -1c.653 -.629 1.413 -.815 2.13 -.559"></path>
    <path d="M19 16v6"></path>
    <path d="M22 19l-3 3l-3 -3"></path>
  </svg>
</button>
  `;


  const filterEyes = `
  <div style="position:relative; ">
  <button title="Filter eyes" class="botones_div" type="button">
    <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brightness-half"
      width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"
      fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
      <path d="M12 9a3 3 0 0 0 0 6v-6z"></path>
      <path
        d="M6 6h3.5l2.5 -2.5l2.5 2.5h3.5v3.5l2.5 2.5l-2.5 2.5v3.5h-3.5l-2.5 2.5l-2.5 -2.5h-3.5v-3.5l-2.5 -2.5l2.5 -2.5z">
      </path>
    </svg>
    <input id="eyes" list="presetColors" type="color" value="#ffffff">
  <datalist id="presetColors">
    <option value="#000000" />
    <option value="#fbff00" />
    <option value="#ff0000" />
    <option value="#00ff00" />
    <option value="#0000ff" />
  </datalist>
  <div id="ojosprotect"
  style="position: fixed; pointer-events: none; width: 100%; height: 100%; left: 0px; top: 0px; opacity: 0.2; z-index: 10; display: block;">
  </div>
</div>
</button>
  `;

  const resetButton = `
  <button title="reset" class="botones_div" type="button" id="reset_button">
  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-power" width="24"
    height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
    stroke-linecap="round" stroke-linejoin="round">
    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
    <path d="M7 6a7.75 7.75 0 1 0 10 0"></path>
    <path d="M12 4l0 8"></path>
  </svg>
</button>
  `;

  const repeatVideo = `
  <button title="Repeat video" class="botones_div" type="button" id="repeatvideo">

  <svg  xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-repeat" width="24"
    height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
    stroke-linecap="round" stroke-linejoin="round">
    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
    <path d="M4 12v-3a3 3 0 0 1 3 -3h13m-3 -3l3 3l-3 3"></path>
    <path d="M20 12v3a3 3 0 0 1 -3 3h-13m3 3l-3 -3l3 -3"></path>
  </svg>
</button>
  `;

  const downloadMp4Mp3 = `
  <button title="MP4" type="button" class="btn1 botones_div">
  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-file-download"
    width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
    stroke-linecap="round" stroke-linejoin="round">
    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
    <path d="M14 3v4a1 1 0 0 0 1 1h4"></path>
    <path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z"></path>
    <path d="M12 17v-6"></path>
    <path d="M9.5 14.5l2.5 2.5l2.5 -2.5"></path>
  </svg>
</button>
<button title="MP3" type="button" class="btn2 botones_div">

  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-file-music" width="24"
    height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
    stroke-linecap="round" stroke-linejoin="round">
    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
    <path d="M14 3v4a1 1 0 0 0 1 1h4"></path>
    <path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z"></path>
    <path d="M11 16m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path>
    <path d="M12 16l0 -5l2 1"></path>
  </svg>
</button>
<button title="Close" type="button" class="btn3 botones_div">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-circle-x" width="24"
  height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  stroke-linecap="round" stroke-linejoin="round">
  <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  <path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0"></path>
  <path d="M10 10l4 4m0 -4l-4 4"></path>
</svg>
</button>
  `;

  const donwloadExternal = `

  <button title="External Download" type="button" class="external_link botones_div">

  <svg class="icon icon-tabler icon-tabler-external-link" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
      <path d="M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6"></path>
      <path d="M11 13l9 -9"></path>
      <path d="M15 4h5v5"></path>
   </svg>
</button>

  `;
  const viewExternalVideo = `

  <button title="view External no cookie" type="button" class="view_external_link botones_div">

  <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 16m0 1a1 1 0 0 1 1 -1h3a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-3a1 1 0 0 1 -1 -1z" /><path d="M4 12v-6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-6" /><path d="M12 8h4v4" /><path d="M16 8l-5 5" /></svg>
</button>

  `;

  const pictureToPicture = `
  <button title="Picture to picture" type="button" class="video_picture_to_picture botones_div">

  <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4" /><path d="M14 14m0 1a1 1 0 0 1 1 -1h5a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1 -1z" /></svg>
</button>

  `;
  const screenShot = `
  <button title="Screenshot video" type="button" class="screenshot_video botones_div">
  <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 8h.01" /><path d="M6 13l2.644 -2.644a1.21 1.21 0 0 1 1.712 0l3.644 3.644" /><path d="M13 13l1.644 -1.644a1.21 1.21 0 0 1 1.712 0l1.644 1.644" /><path d="M4 8v-2a2 2 0 0 1 2 -2h2" /><path d="M4 16v2a2 2 0 0 0 2 2h2" /><path d="M16 4h2a2 2 0 0 1 2 2v2" /><path d="M16 20h2a2 2 0 0 0 2 -2v-2" /></svg>
</button>

  `;

  const checkUpdates = `
  <button title="Check new updates" type="button" class="checked_updates botones_div">
  <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" /><path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" /></svg>
</button>
  `;

  const bookmarkAddBtn = `
  <button title="Add bookmark" type="button" id="yt-bookmark-add" class="botones_div">
    <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
      <path d="M7 4h10a2 2 0 0 1 2 2v14l-7 -4l-7 4v-14a2 2 0 0 1 2 -2z" />
      <path d="M12 7v6" />
      <path d="M9 10h6" />
    </svg>
  </button>
  `;

  const bookmarkToggleBtn = `
  <button title="Show bookmarks" type="button" id="yt-bookmark-toggle" class="botones_div">
    <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
      <path d="M9 6h11" />
      <path d="M9 12h11" />
      <path d="M9 18h11" />
      <path d="M5 6h.01" />
      <path d="M5 12h.01" />
      <path d="M5 18h.01" />
    </svg>
  </button>
  `;

  const continueWatchingHistoryBtn = `
  <button title="History" type="button" id="yt-cw-history-toggle" class="botones_div" style="display:none;">
    <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
      <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
      <path d="M12 8v4l3 3" />
      <path d="M3 12a9 9 0 1 0 3 -6.7" />
      <path d="M3 4v4h4" />
    </svg>
  </button>
  `;

  const bufferVideo = `
  <button title="Buffer video" type="button" class="buffer_video botones_div">
 <svg width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="icon icon-tabler icons-tabler-outline icon-tabler-align-box-right-stretch"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 17h2" /><path d="M3 5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-14z" /><path d="M11 12h6" /><path d="M13 7h4" /></svg>
</button>
  `;


  const menuBotones = `
    <main>
    <div class="container">
    <form>
      <div class="containerButtons">
      ${thumbnailVideo}
      ${bufferVideo}
      ${filterEyes}
      ${resetButton}
      ${repeatVideo}
      ${bookmarkAddBtn}
      ${bookmarkToggleBtn}
      ${continueWatchingHistoryBtn}
      ${downloadMp4Mp3}
      ${donwloadExternal}
      ${viewExternalVideo}
      ${pictureToPicture}
      ${screenShot}
      ${checkUpdates}
      </div>
      <div id="yt-bookmarks-panel" class="yt-bookmarks-panel" style="display:none;"></div>
      <div id="yt-continue-watching-panel" class="yt-continue-watching-panel" style="display:none;"></div>
      <div>
      </div>
    </form>

    </div>
    <div class="content_collapsible_colors" style="margin-top: 10px">

    <form class="formulariodescarga ocultarframe" action="">
    <div class="containerall">
    <select class="selectcalidades ocultarframe" required>
      <option selected disabled>Calidad del video / Quality video</option>
      <option value="144">144p Mp4</option>
      <option value="240">240p Mp4</option>
      <option value="360">360p Mp4</option>
      <option value="480">480p Mp4</option>
      <option value="720">720p HD Mp4 Default</option>
      <option value="1080">1080p FULL HD Mp4</option>
      <option value="4k">2160p 4K WEBM</option>
      <option value="8k">4320p 8K WEBM</option>
      </select>
      <div id="descargando" class="download-container ocultarframe">
        <button class="progress-retry-btn" title="Retry" style="display: none;">
        <i class="fa-solid fa-rotate-right"></i>
        </button>
        <button class="download-again-btn" title="Download again" style="display: none;">
        <i class="fa-solid fa-download"></i>
        </button>
        <div class="download-info">
          <span class="download-text">Download Video And Please Wait...</span>
          <span class="download-quality"></span>
        </div>
        <div class="download-actions">
          <button class="download-btn video-btn">Download</button>
          <button class="retry-btn" style="display: none;">Retry</button>
        </div>
        <div class="progress-container" style="display: none;">
          <div class="progress-bar">
            <div class="progress-fill"></div>
          </div>
          <span class="progress-text">0%</span>
        </div>
        <div class="download-footer">
          <a href="https://github.com/DeveloperMDCM/" target="_blank"> <i class="fa-brands fa-github"></i> by: DeveloperMDCM</a>
        </div>
        <h1 class="text-description-download">
          <span >Enable pop-ups on YouTube to download audio or video</span>
        </h1>
      </div>
    </div>
    </form>
    <form class="formulariodescargaaudio ocultarframe" action="">
    <div class="containerall">
    <select class="selectcalidadesaudio ocultarframeaudio" required>
      <option selected disabled>Calidad del Audio / Quality Audio</option>
      <option value="flac">Audio FLAC UHQ</option>
      <option value="wav">Audio WAV UHQ</option>
      <option value="webm">Audio WEBM UHQ</option>
      <option value="mp3">Audio MP3 Default</option>
      <option value="m4a">Audio M4A</option>
      <option value="aac">Audio AAC</option>
      <option value="opus">Audio OPUS</option>
      <option value="ogg">Audio OGG</option>
      </select>
      <div id="descargandomp3" class="download-container ocultarframeaudio">
        <button class="progress-retry-btn" title="Retry" style="display: none;">
        <i class="fa-solid fa-rotate-right"></i>
        </button>
        <button class="download-again-btn" title="Download again" style="display: none;">
        <i class="fa-solid fa-download"></i>
        </button>
        <div class="download-info">
          <span class="download-text">Download Audio And Please Wait...</span>
          <span class="download-quality"></span>
        </div>
        <div class="download-actions">
          <button class="download-btn audio-btn">Download</button>
          <button class="retry-btn" style="display: none;">Retry</button>
        </div>
        <div class="progress-container" style="display: none;">
          <div class="progress-bar">
            <div class="progress-fill"></div>
          </div>
          <span class="progress-text">0%</span>
        </div>
         <div class="download-footer">
          <a href="https://github.com/DeveloperMDCM/" target="_blank"><i class="fa-brands fa-github"></i> by: DeveloperMDCM</a>
        </div>
         <h1 class="text-description-download">
          <span >Enable pop-ups on YouTube to download audio or video</span>
        </h1>
      </div>
    </div>
    </form>
      </main>
  `;



  // Define themes
  const themes = [
    {
      name: 'Default / Reload',
      gradient: '',
      textColor: '',
      raised: '',
      btnTranslate: '',
      CurrentProgressVideo: '',
      videoDuration: '',
      colorIcons: '',
      textLogo: '',
      primaryColor: '',
      secondaryColor: '',
    },
    {
      name: 'Midnight Blue',
      gradient: 'linear-gradient(135deg, #1e3a8a, #3b82f6)',
      textColor: '#ffffff',
      raised: '#f00',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Forest Green',
      gradient: 'linear-gradient(135deg, #14532d, #22c55e)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Sunset Orange',
      gradient: 'linear-gradient(135deg, #7c2d12, #f97316)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Royal Purple',
      gradient: 'linear-gradient(135deg, #4c1d95, #8b5cf6)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Cherry Blossom',
      gradient: 'linear-gradient(135deg, #a9005c, #fc008f)',
      textColor: '#ffffff',
      raised: '#fc008f',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Red Dark',
      gradient: 'linear-gradient(135deg, #790909, #f70131)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Raind ',
      gradient: 'linear-gradient(90deg, #3f5efb 0%, #fc466b) 100%',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Neon',
      gradient: 'linear-gradient(273deg, #ee49fd 0%, #6175ff 100%)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Azure',
      gradient: 'linear-gradient(273deg, #0172af 0%, #74febd 100%)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Butterfly',
      gradient: 'linear-gradient(273deg, #ff4060 0%, #fff16a 100%)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
    {
      name: 'Colombia',
      gradient:
        'linear-gradient(174deg, #fbf63f  0%, #0000bb 45%, #ff0000 99%)',
      textColor: '#ffffff',
      raised: '#303131',
      btnTranslate: '#000',
      CurrentProgressVideo: '#0f0',
      videoDuration: '#fff',
      colorIcons: '#fff',
      textLogo: '#f00',
    },
  ];

  // Create our enhancement panel
  const panel = $cl('div');

  panel.id = 'yt-enhancement-panel';

  // Generate theme options HTML
  const themeOptionsHTML = themes
    .map(
      (theme, index) => `
        <label >
          <div class="theme-option">
          <div class="theme-preview" style="background: ${theme.gradient};"></div>
          <input type="radio" name="theme" value="${index}" ${
              index === 0 ? 'checked' : ''
            }>
              <span style="${theme.name === 'Default / Reload Page' ? 'color: red; ' : '' }" class="theme-name">${theme.name}</span>
              </div>
        </label>
    `
    )
    .join('');

    const languageOptionsHTML = Object.entries(languagesTranslate)
    .map(([code, name]) => {
      const selected = code === languagesTranslate ? 'selected' : '';
      return `<option value="${code}" ${selected}>${name}</option>`;
    })
    .join('');



   function checkDarkModeActive() {
      const prefCookie = document.cookie.split('; ').find(c => c.startsWith('PREF='));
      if (!prefCookie) return 'light';

      const prefValue = prefCookie.substring(5);
      const params = new URLSearchParams(prefValue);

      const f6Value = params.get('f6');
      const darkModes = ['400', '4000000', '40000400', '40000000'];

      return darkModes.includes(f6Value) ? 'dark' : 'light';
    }


    let isDarkModeActive = checkDarkModeActive();


  // Use Trusted Types to set innerHTML
  const menuHTML = `
   <div class="container-mdcm">
    <div class="header-mdcm">
      <h1> <i class="fa-brands fa-youtube"></i> YouTube Tools</h1>
      <div class="icons-mdcm">
        <a href="https://update.greasyfork.org/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.user.js"
          target="_blank">
          <button class="icon-btn-mdcm">
            <i class="fa-solid fa-arrows-rotate"></i>
          </button>
        </a>
        <a href="https://github.com/DeveloperMDCM" target="_blank">
          <button class="icon-btn-mdcm">
            <i class="fa-brands fa-github"></i>
          </button>
        </a>
        <button class="icon-btn-mdcm" id="shareBtn-mdcm">
          <i class="fa-solid fa-share-alt"></i>
        </button>
        <button class="icon-btn-mdcm" id="importExportBtn">
          <i class="fa-solid fa-file-import"></i>
        </button>
        <button id="menu-settings-icon" class="icon-btn-mdcm tab-mdcm" data-tab="menu-settings">
          <i class="fa-solid fa-gear"></i>
        </button>
        <button class="icon-btn-mdcm close_menu_settings">
          <i class="fa-solid fa-xmark"></i>
        </button>
      </div>
    </div>

    <div class="tabs-mdcm">
      <button class="tab-mdcm active" data-tab="general">
        <i class="fa-solid fa-shield-halved"></i>
        General
      </button>
      <button class="tab-mdcm" data-tab="themes">
        <i class="fa-solid fa-palette"></i>
        Themes
      </button>
      <button class="tab-mdcm" data-tab="stats">
        <i class="fa-solid fa-square-poll-vertical"></i>
        Stats
      </button>
      <button class="tab-mdcm" data-tab="headers">
        <i class="fa-regular fa-newspaper"></i>
        Header
      </button>
    </div>


    <div id="general" class="tab-content active">

      <div class="options-mdcm">
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="hide-comments-toggle"> Hide Comments
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="hide-sidebar-toggle"> Hide Sidebar
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="autoplay-toggle"> Disable Autoplay
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="subtitles-toggle"> Disable Subtitles
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" checked id="dislikes-toggle"> Show Dislikes
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="like-dislike-bar-toggle"> Like vs Dislike bar
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="bookmarks-toggle"> Bookmarks (timestamps)
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="continue-watching-toggle"> Continue watching
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="shorts-channel-name-toggle"> Shorts: show channel name
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="themes-toggle"> Active Themes
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="translation-toggle"> Translate comments
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="avatars-toggle"> Download avatars
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="reverse-mode-toggle"> Reverse mode
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="cinematic-lighting-toggle"> Cinematic Mode
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" checked id="wave-visualizer-toggle"> Wave visualizer Beta
          </div>
        </label>
        <label>
          <div class="option-mdcm">
            <input type="checkbox" class="checkbox-mdcm" id="sync-cinematic-toggle"> Sync Ambient Mode YT
          </div>
        </label>
        <div class="quality-selector-mdcm" style="grid-column: span 2;">
          <div class="select-wrapper-mdcm">
            <label>Effect wave visualizer:
              <select class="tab-button-active" id="select-wave-visualizer-select">
                <option value="linea">Line smooth</option>
                <option value="barras">Vertical bars</option>
                <option value="curva">Curved</option>
                <option value="picos">Smooth peaks</option>
                <option value="solida">Solid wave</option>
                <option value="dinamica">Dynamic wave</option>
                <option value="montana">Smooth mountain</option>
              </select>
            </label>
          </div>
        </div>
        <div class="quality-selector-mdcm" style="grid-column: span 2;">
          <div class="select-wrapper-mdcm">
            <label>Default video player quality:
              <select class="tab-button-active" id="select-video-qualitys-select">
                <option value="user">User Default</option>
                <option value="">Auto</option>
                <option value="144">144</option>
                <option value="240">240</option>
                <option value="360">360</option>
                <option value="480">480</option>
                <option value="720">720</option>
                <option value="1080">1080</option>
                <option value="1440">1440</option>
                <option value="2160">2160</option>
              </select>
            </label>
          </div>
        </div>
        <div class="quality-selector-mdcm" style="grid-column: span 2;">
          <div class="select-wrapper-mdcm">
            <label>Language for translate comments:
              <select class="tab-button-active" id="select-languages-comments-select">
              ${languageOptionsHTML}
              </select>
            </label>
          </div>
        </div>
        <div class="slider-container-mdcm" style="grid-column: span 2;">
          <label>Video Player Size: <span id="player-size-value">100</span>%</label>
          <input type="range" id="player-size-slider" class="slider-mdcm" min="50" max="150" value="100">
          <button class="reset-btn-mdcm" id="reset-player-size">Reset video size</button>
        </div>
      </div>
    </div>

    <div id="themes" class="tab-content">
     <div id="background-image-container" class="background-image-container">
     <h4>Background Image</h4>
  <input type="file" id="background_image" accept="image/png, image/jpeg" style="display:none;" />
  <div id="background-image-preview" class="background-image-preview">
    <span class="background-image-overlay">
      <i class="fa fa-camera"></i>
      <span class="background-image-text">Select image</span>
    </span>
    <button id="remove-background-image" class="remove-background-image" title="Quitar fondo">&times;</button>
  </div>
</div>
      <div class="themes-hidden">
        <div class="options-mdcm" style="margin-bottom: 10px;">
          <div>
            <h4>Choose a Theme</h4>
            <p>Disable Mode Cinematic on General</p>
            ${isDarkModeActive === 'dark' ? '' : '<p style="color: red; margin: 10px 0;font-size: 11px;">Activate dark mode to use this option</p>'}
          </div>
        </div>
        <div class="options-mdcm">
          <label>
            <div class="theme-option option-mdcm">
              <input type="radio" class="radio-mdcm" name="theme" value="custom" checked>
              <span class="theme-name">Custom</span>
            </div>
          </label>
          <label>
            <div class="theme-option option-mdcm theme-selected-normal">
              <input type="radio" class="radio-mdcm" name="theme" value="normal">
              <span class="theme-name">Selected Themes</span>
            </div>
          </label>
        </div>
        <div class="themes-options">
          <div class="options-mdcm">
            ${themeOptionsHTML}
          </div>
        </div>
        <div class="theme-custom-options">
          <div class="options-mdcm">
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Progressbar Video:</label>
                <input type="color" id="progressbar-color-picker" class="color-picker-mdcm" value="#ff0000">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Background Color:</label>
                <input type="color" id="bg-color-picker" class="color-picker-mdcm" value="#000000">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Primary Color:</label>
                <input type="color" id="primary-color-picker" class="color-picker-mdcm" value="#ffffff">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Secondary Color:</label>
                <input type="color" id="secondary-color-picker" class="color-picker-mdcm" value="#ffffff">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Header Color:</label>
                <input type="color" id="header-color-picker" class="color-picker-mdcm" value="#000000">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Icons Color:</label>
                <input type="color" id="icons-color-picker" class="color-picker-mdcm" value="#ffffff">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Menu Color:</label>
                <input type="color" id="menu-color-picker" class="color-picker-mdcm" value="#000000">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Line Color Preview:</label>
                <input type="color" id="line-color-picker" class="color-picker-mdcm" value="#ff0000">
              </div>
            </div>
            <div class="option-mdcm">
              <div class="card-items-end">
                <label>Time Color Preview:</label>
                <input type="color" id="time-color-picker" class="color-picker-mdcm" value="#ffffff">
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div id="stats" class="tab-content">
      <div id="yt-stats-toggle">
        <div class="stat-row">
          <div>Foreground Time</div>
          <div class="progress">
            <div class="progress-bar total-bar" id="usage-bar"></div>
          </div>
          <div id="total-time">0h 0m 0s</div>
        </div>
        <div class="stat-row">
          <div>Video Time</div>
          <div class="progress">
            <div class="progress-bar video-bar" id="video-bar"></div>
          </div>
          <div id="video-time">0h 0m 0s</div>
        </div>
        <div class="stat-row">
          <div>Shorts Time</div>
          <div class="progress">
            <div class="progress-bar shorts-bar" id="shorts-bar"></div>
          </div>
          <div id="shorts-time">0h 0m 0s</div>
        </div>
      </div>
    </div>

    <div id="headers" class="tab-content">
      <div class="options-mdcm">
        <label>Available in next update</label>
      </div>
    </div>


    <div id="menu-settings" class="tab-content">
      <div class="options-mdcm">
        <h4 style="margin: 10px 0">Menu Appearance</h4>
      </div>
      <div class="options-settings-mdcm">
        <div class="option-settings-mdcm">
          <label>Backgrounds:</label>
          <div class="color-boxes" id="bg-color-options">
            <div class="color-box" data-type="bg" data-value="#252525" style="background-color: #252525;"></div>
            <div class="color-box" data-type="bg" data-value="#1e1e1e" style="background-color: #1e1e1e;"></div>
            <div class="color-box" data-type="bg" data-value="#3a3a3a" style="background-color: #3a3a3a;"></div>
            <div class="color-box" data-type="bg" data-value="#4a4a4a" style="background-color: #4a4a4a;"></div>
            <div class="color-box" data-type="bg" data-value="#000000" style="background-color: #000000;"></div>
            <div class="color-box" data-type="bg" data-value="#00000000" style="background-color: #00000000;"></div>
            <div class="color-box" data-type="bg" data-value="#2d2d2d" style="background-color: #2d2d2d;"></div>
            <div class="color-box" data-type="bg" data-value="#444" style="background-color: #444;"></div>
          </div>
        </div>

        <div class="option-settings-mdcm">
          <label>Accent Colors:</label>
          <div class="color-boxes" id="bg-accent-color-options">
            <div class="color-box" data-type="accent" data-value="#ff0000" style="background-color: #ff0000;"></div>
            <div class="color-box" data-type="accent" data-value="#000000" style="background-color: #000000;"></div>
            <div class="color-box" data-type="accent" data-value="#009c37 " style="background-color: #009c37 ;"></div>
            <div class="color-box" data-type="accent" data-value="#0c02a0 " style="background-color: #0c02a0 ;"></div>
          </div>
        </div>

        <div class="option-settings-mdcm">
          <label>Titles Colors:</label>
          <div class="color-boxes" id="text-color-options">
            <div class="color-box" data-type="color" data-value="#ffffff" style="background-color: #ffffff;"></div>
            <div class="color-box" data-type="color" data-value="#cccccc" style="background-color: #cccccc;"></div>
            <div class="color-box" data-type="color" data-value="#b3b3b3" style="background-color: #b3b3b3;"></div>
            <div class="color-box" data-type="color" data-value="#00ffff" style="background-color: #00ffff;"></div>
            <div class="color-box" data-type="color" data-value="#00ff00" style="background-color: #00ff00;"></div>
            <div class="color-box" data-type="color" data-value="#ffff00" style="background-color: #ffff00;"></div>
            <div class="color-box" data-type="color" data-value="#ffcc00" style="background-color: #ffcc00;"></div>
            <div class="color-box" data-type="color" data-value="#ff66cc" style="background-color: #ff66cc;"></div>
          </div>
        </div>
      </div>
    </div>

    <div id="importExportArea">
      <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
        <h3>Import / Export Settings</h3>
        <button class="icon-btn-mdcm" id="closeImportExportBtn">
          <i class="fa-solid fa-xmark"></i>
        </button>
      </div>
      <textarea id="config-data" placeholder="Paste configuration here to import"></textarea>
      <div class="action-buttons-mdcm">
        <button id="export-config" class="action-btn-mdcm">Export</button>
        <button id="import-config" class="action-btn-mdcm">Import</button>
      </div>
    </div>

    <div id="shareDropdown">
      <a href="https://www.facebook.com/sharer/sharer.php?u=${urlSharedCode}" target="_blank" data-network="facebook"
        class="share-link"><i class="fa-brands fa-facebook"></i> Facebook</a><br>
      <a href="https://twitter.com/intent/tweet?url=${urlSharedCode}" target="_blank" data-network="twitter"
        class="share-link"><i class="fa-brands fa-twitter"></i> Twitter</a><br>
      <a href="https://api.whatsapp.com/send?text=${urlSharedCode}" target="_blank" data-network="whatsapp"
        class="share-link"><i class="fa-brands fa-whatsapp"></i> WhatsApp</a><br>
      <a href="https://www.linkedin.com/sharing/share-offsite/?url=${urlSharedCode}" target="_blank"
        data-network="linkedin" class="share-link"><i class="fa-brands fa-linkedin"></i> LinkedIn</a><br>
    </div>


  </div>
  <div class="actions-mdcm">
    <div class="developer-mdcm">
      Developed by <a href="https://github.com/DeveloperMDCM" target="_blank"> <i class="fa-brands fa-github"></i> DeveloperMDCM</a>
    </div>
    <span style="color: #fff" ;>v2.4.3.2</span>
  </div>
  `;
  const panelHTML = policy?.createHTML
  ? policy.createHTML(`${menuHTML}`)
  : `${menuHTML}`;

  panel.innerHTML = panelHTML;

  $ap(panel);


  function addIcon() {
    const topBar = $e('ytd-topbar-menu-button-renderer');
    if (!topBar || $id('icon-menu-settings')) return;

    const toggleButton = $cl('div');
    toggleButton.id = 'toggle-button';

    const icon = $cl('i');
    icon.id = 'icon-menu-settings';
    icon.classList.add('fa-solid', 'fa-gear');

    toggleButton.appendChild(icon);
    topBar.parentElement.insertBefore(toggleButton, topBar);
      // Toggle panel visibility
    let openMenu = false;
    toggleButton.addEventListener('click', () => {
      openMenu = !openMenu;
      // openMenu
      //   ? (toggleButton.style.backgroundColor = '#f00')
      //   : (toggleButton.style.backgroundColor = 'transparent');
      panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
    });


    }


  addIcon();
  let openMenu = false;

  const close_menu_settings = $e('.close_menu_settings');
    close_menu_settings.addEventListener('click', () => {
      openMenu = !openMenu;
      panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
    });

  // $ap(toggleButton);




  // Tab functionality
  const tabButtons = $m('.tab-mdcm');
  const tabContents = $m('.tab-content');

  tabButtons.forEach((button) => {
    button.addEventListener('click', () => {
      const tabName = button.getAttribute('data-tab');
      tabButtons.forEach((btn) => btn.classList.remove('active'));
      tabContents.forEach((content) => content.classList.remove('active'));
      button.classList.add('active');
      $id(tabName).classList.add('active');
    });
  });

  // Function to save settings
  function saveSettings() {
    const settings = {
      theme: $e('input[name="theme"]:checked').value,
      bgColorPicker: $id('bg-color-picker').value,
      progressbarColorPicker: $id('progressbar-color-picker').value,
      primaryColorPicker: $id('primary-color-picker').value,
      secondaryColorPicker: $id('secondary-color-picker').value,
      headerColorPicker: $id('header-color-picker').value,
      iconsColorPicker: $id('icons-color-picker').value,
      menuColorPicker: $id('menu-color-picker').value,
      lineColorPicker: $id('line-color-picker').value,
      timeColorPicker: $id('time-color-picker').value,
      dislikes: $id('dislikes-toggle').checked,
      likeDislikeBar: $id('like-dislike-bar-toggle').checked,
      bookmarks: $id('bookmarks-toggle').checked,
      continueWatching: $id('continue-watching-toggle').checked,
      shortsChannelName: $id('shorts-channel-name-toggle').checked,
      themes: $id('themes-toggle').checked,
      translation: $id('translation-toggle').checked,
      avatars: $id('avatars-toggle').checked,
      reverseMode: $id('reverse-mode-toggle').checked,
      waveVisualizer: $id('wave-visualizer-toggle').checked,
      waveVisualizerSelected: $id('select-wave-visualizer-select').value,
      hideComments: $id('hide-comments-toggle').checked,
      hideSidebar: $id('hide-sidebar-toggle').checked,
      disableAutoplay: $id('autoplay-toggle').checked,
      cinematicLighting: $id('cinematic-lighting-toggle').checked,
      syncCinematic: $id('sync-cinematic-toggle').checked, // NUEVO SETTING
      disableSubtitles: $id('subtitles-toggle').checked,
      // fontSize: $id('font-size-slider').value,
      playerSize: $id('player-size-slider').value,
      selectVideoQuality: $id('select-video-qualitys-select').value,
      languagesComments: $id('select-languages-comments-select').value,
      // menuBgColor: $id('menu-bg-color-picker').value,
      // menuTextColor: $id('menu-text-color-picker').value,
      menu_developermdcm: {
        bg: selectedBgColor,
        color: selectedTextColor,
        accent: selectedBgAccentColor
      }
      // menuFontSize: $id('menu-font-size-slider').value,
    };

    GM_setValue('ytSettingsMDCM', JSON.stringify(settings));
  }



  // Function to load settings
  function loadSettings() {
    const settings = JSON.parse(GM_getValue('ytSettingsMDCM', '{}'));
    // Mark as loaded early so applySettings/saveSettings don't overwrite persisted values with defaults.
    __ytToolsRuntime.settingsLoaded = true;

    if (settings.theme) {
      $e(`input[name="theme"][value="${settings.theme}"]`).checked = true;
    }
    settings.menu_developermdcm = settings.menu_developermdcm || {
      bg: "#252525",
      color: "#ffffff",
      accent: "#ff0000"
    };
    $id('bg-color-picker').value = settings.bgColorPicker || '#000000';
    $id('progressbar-color-picker').value = settings.progressbarColorPicker || '#ff0000';
    $id('primary-color-picker').value = settings.primaryColorPicker || '#ffffff';
    $id('secondary-color-picker').value = settings.secondaryColorPicker || '#ffffff';
    $id('header-color-picker').value = settings.headerColorPicker || '#000';
    $id('icons-color-picker').value = settings.iconsColorPicker || '#ffffff';
    $id('menu-color-picker').value = settings.menuColorPicker || '#000';
    $id('line-color-picker').value = settings.lineColorPicker || '#ff0000';
    $id('time-color-picker').value = settings.timeColorPicker || '#ffffff';
    $id('dislikes-toggle').checked = settings.dislikes || false;
    $id('like-dislike-bar-toggle').checked = settings.likeDislikeBar || false;
    $id('bookmarks-toggle').checked = settings.bookmarks || false;
    $id('continue-watching-toggle').checked = settings.continueWatching || false;
    $id('shorts-channel-name-toggle').checked = settings.shortsChannelName || false;
    $id('themes-toggle').checked = settings.themes || false;
    $id('translation-toggle').checked = settings.translation || false;
    $id('avatars-toggle').checked = settings.avatars || false;
    $id('reverse-mode-toggle').checked = settings.reverseMode || false;
    $id('wave-visualizer-toggle').checked = settings.waveVisualizer || false;
    $id('select-wave-visualizer-select').value = settings.waveVisualizerSelected || 'dinamica';
    $id('hide-comments-toggle').checked = settings.hideComments || false;
    $id('hide-sidebar-toggle').checked = settings.hideSidebar || false;
    $id('autoplay-toggle').checked = settings.disableAutoplay || false;
    $id('cinematic-lighting-toggle').checked = settings.cinematicLighting || false;
    $id('sync-cinematic-toggle').checked = settings.syncCinematic || false;
    $id('subtitles-toggle').checked = settings.disableSubtitles || false;
    // $id('font-size-slider').value = settings.fontSize || 16;
    $id('player-size-slider').value = settings.playerSize || 100;
    $id('select-video-qualitys-select').value = settings.selectVideoQuality || 'user';
    $id('select-languages-comments-select').value = settings.languagesComments || 'en';
    // $id('menu-bg-color-picker').value = settings.menuBgColor || '#000000';
    // $id('menu-text-color-picker').value = settings.menuTextColor || '#ffffff';
    // $id('menu-font-size-slider').value = settings.menuFontSize || 14;
    // Asegurar existencia de menu_developermdcm


    selectedBgColor = settings.menu_developermdcm.bg;
    selectedTextColor = settings.menu_developermdcm.color;
    selectedBgAccentColor = settings.menu_developermdcm.accent;


    $m('#bg-color-options .color-box').forEach(el => {
      el.classList.toggle('selected', el.dataset.value === selectedBgColor);
    });

    $m('#text-color-options .color-box').forEach(el => {
      el.classList.toggle('selected', el.dataset.value === selectedTextColor);
    });

    $m('#bg-accent-color-options .color-box').forEach(el => {
      el.classList.toggle('selected', el.dataset.value === selectedBgAccentColor);
    });

    // Apply menu colors
    $sp('--yt-enhance-menu-bg', selectedBgColor);
    $sp('--yt-enhance-menu-text', selectedTextColor);
    $sp('--yt-enhance-menu-accent', selectedBgAccentColor);
    updateSliderValues();

    setTimeout(() => {
      applySettings();
      if(settings.dislikes) {
          videoDislike();
          shortDislike();
          showDislikes = true;
      }

      if (window.location.href.includes('youtube.com/watch?v=')) {
        detectInitialCinematicState();
      }
    }, 500);
  }

  // Check if the video is in cinematic mode
  async function detectInitialCinematicState() {
    return new Promise((resolve) => {
      const waitForVideo = () => {
        const video = $e('video');
        const cinematicDiv = $id('cinematics');

        if (!video || !cinematicDiv || isNaN(video.duration) || video.duration === 0) {
          setTimeout(waitForVideo, 500);
          return;
        }

        const settings = JSON.parse(GM_getValue('ytSettingsMDCM', '{}'));
        if (!settings.syncCinematic) {
          // apply cinematic toggle
          const cinematicToggle = $id('cinematic-lighting-toggle');
          if (cinematicToggle && cinematicDiv) {
            cinematicDiv.style.display = cinematicToggle.checked ? 'block' : 'none';
          }
          resolve(false);
          return;
        }

        const startTime = video.currentTime;
        const checkPlayback = () => {
          if (video.currentTime >= startTime + 1) {
            const isActive = isCinematicActive();

            const cinematicToggle = $id('cinematic-lighting-toggle');
            if (cinematicToggle && cinematicToggle.checked !== isActive) {
              cinematicToggle.checked = isActive;
              saveSettings();
            }

            resolve(isActive);
          } else {
            setTimeout(checkPlayback, 300);
          }
        };

        checkPlayback();
      };

      waitForVideo();
    });
  }

  $m('.color-box').forEach(box => {
    box.addEventListener('click', () => {
      const type = box.dataset.type;
      const value = box.dataset.value;

      if (type === 'bg') {
        selectedBgColor = value;
        $sp('--yt-enhance-menu-bg', value);
        $m('#bg-color-options .color-box').forEach(el => {
          el.classList.remove('selected');
        });
        box.classList.add('selected');
      } else if (type === 'color') {
        selectedTextColor = value;
        $sp('--yt-enhance-menu-text', value);
        $m('#text-color-options .color-box').forEach(el => {
          el.classList.remove('selected');
        });
        box.classList.add('selected');
      }
       else if (type === 'accent') {
        selectedBgAccentColor = value;
        $sp('--yt-enhance-menu-accent', value);
        $m('#bg-accent-color-options .color-box').forEach(el => {
          el.classList.remove('selected');
        });
        box.classList.add('selected');
      }
      saveSettings();
    });
  });


  function updateSliderValues() {
    $id('player-size-value').textContent = $id('player-size-slider').value;

  }

  $id('reset-player-size').addEventListener('click', () => {
    $id('player-size-slider').value = 100;
    updateSliderValues();
    applySettings();
  });

   // Initialize header buttons once
  function initializeHeaderButtons() {
    const shareBtn = $id('shareBtn-mdcm');
    const importExportBtn = $id('importExportBtn');
    const closeImportExportBtn = $id('closeImportExportBtn');

    if (shareBtn && !shareBtn.dataset.initialized) {
      shareBtn.dataset.initialized = 'true';
      shareBtn.addEventListener('click', function(event) {
        event.stopPropagation();
        const dropdown = $id('shareDropdown');
        if (dropdown) {
          dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
        }
      });
    }

    if (importExportBtn && !importExportBtn.dataset.initialized) {
      importExportBtn.dataset.initialized = 'true';
      importExportBtn.addEventListener('click', function() {
        const importExportArea = $id('importExportArea');
        if (importExportArea) {
          importExportArea.classList.toggle('active');
        }
      });
    }

    if (closeImportExportBtn && !closeImportExportBtn.dataset.initialized) {
      closeImportExportBtn.dataset.initialized = 'true';
      closeImportExportBtn.addEventListener('click', function() {
        const importExportArea = $id('importExportArea');
        if (importExportArea) {
          importExportArea.classList.remove('active');
        }
      });
    }
  }

  // Cinematic Lighting Control Functions
  function isWatchPage() {
    return window.location.href.includes('youtube.com/watch?v=');
  }

  function isCinematicActive() {
    const cinematicDiv = document.getElementById('cinematics');
    if (!cinematicDiv) {
      return false;
    }

    const hasContent = cinematicDiv.innerHTML.trim() !== '';
    const hasCanvas = cinematicDiv.querySelector('canvas') !== null;
    const hasChildren = cinematicDiv.children.length > 0;

    const hasCinematicElements = cinematicDiv.querySelector('div[style*="position: fixed"]') !== null;

    return hasContent || hasCanvas || hasChildren || hasCinematicElements;
  }

  function toggleCinematicLighting() {
    const settingsButton = $e('.ytp-button.ytp-settings-button');
    if (!settingsButton) {
      console.log('Settings button not found');
      return;
    }


    settingsButton.click();


    const observer = new MutationObserver((mutations) => {
      const menuItems = $m('.ytp-menuitem');

      for (let item of menuItems) {
        const text = item.textContent?.toLowerCase();
        const icon = item.querySelector('.ytp-menuitem-icon svg path');


        if (text && (text.includes('cinematic') || text.includes('lighting') || text.includes('cinema'))) {
          console.log('Found cinematic lighting option:', text);
          item.click();


          setTimeout(() => {
            const menu = $e('.ytp-settings-menu');
            if (menu) {
              document.body.click();
            }
          }, 100);

          observer.disconnect();
          return;
        }


        if (icon && (icon.getAttribute('d')?.includes('M21 7v10H3V7') ||
                    icon.getAttribute('d')?.includes('M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z'))) {
          console.log('Found cinematic lighting option by SVG path');
          item.click();

          setTimeout(() => {
            const menu = $e('.ytp-settings-menu');
            if (menu) {
              document.body.click();
            }
          }, 100);

          observer.disconnect();
          return;
        }
      }
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['class']
    });
    setTimeout(() => {
      observer.disconnect();
      const menu = $e('.ytp-settings-menu');
      if (menu) {
        document.body.click();
      }
    }, 5000);
  }

  // Function to apply settings
  function applySettings() {
    const formulariodescarga = $e('.formulariodescarga');
    const formulariodescargaaudio = $e('.formulariodescargaaudio');
      if (formulariodescarga != undefined) {
        formulariodescarga.classList.add('ocultarframe');
        formulariodescargaaudio.classList.add('ocultarframe');
      }
    const settings = {
      theme: $e('input[name="theme"]:checked').value,
      bgColorPicker: $id('bg-color-picker').value,
      progressbarColorPicker: $id('progressbar-color-picker').value,
      primaryColorPicker: $id('primary-color-picker').value,
      secondaryColorPicker: $id('secondary-color-picker').value,
      headerColorPicker: $id('header-color-picker').value,
      iconsColorPicker: $id('icons-color-picker').value,
      menuColorPicker: $id('menu-color-picker').value,
      lineColorPicker: $id('line-color-picker').value,
      timeColorPicker: $id('time-color-picker').value,
      dislikes: $id('dislikes-toggle').checked,
      likeDislikeBar: $id('like-dislike-bar-toggle').checked,
      bookmarks: $id('bookmarks-toggle').checked,
      continueWatching: $id('continue-watching-toggle').checked,
      shortsChannelName: $id('shorts-channel-name-toggle').checked,
      themes: $id('themes-toggle').checked,
      translation: $id('translation-toggle').checked,
      avatars: $id('avatars-toggle').checked,
      reverseMode: $id('reverse-mode-toggle').checked,
      waveVisualizer: $id('wave-visualizer-toggle').checked,
      waveVisualizerSelected: $id('select-wave-visualizer-select').value,
      hideComments: $id('hide-comments-toggle').checked,
      hideSidebar: $id('hide-sidebar-toggle').checked,
      disableAutoplay: $id('autoplay-toggle').checked,
      cinematicLighting: $id('cinematic-lighting-toggle').checked,
      syncCinematic: $id('sync-cinematic-toggle').checked, // NUEVO SETTING
      disableSubtitles: $id('subtitles-toggle').checked,
      // fontSize: $id('font-size-slider').value,
      playerSize: $id('player-size-slider').value,
      selectVideoQuality: $id('select-video-qualitys-select').value,
      languagesComments: $id('select-languages-comments-select').value,
      // menuBgColor: $id('menu-bg-color-picker').value,
      // menuTextColor: $id('menu-text-color-picker').value,
      menu_developermdcm: {
        bg: selectedBgColor,
        color: selectedTextColor,
        accent: selectedBgAccentColor
      }
      // menuFontSize: $id('menu-font-size-slider').value,
    };
    $sp('--yt-enhance-menu-bg', settings.menu_developermdcm.bg);
    $sp('--yt-enhance-menu-text', settings.menu_developermdcm.color);
    $sp('--yt-enhance-menu-accent', settings.menu_developermdcm.accent);

    renderizarButtons();


        // Initialize header buttons
    initializeHeaderButtons();




    // Hide comments
    const commentsSection = $id('comments');
    if (commentsSection) {
      commentsSection.style.display = settings.hideComments ? 'none' : 'block';
    }

     // Active inactive Themes
     const themesMenuSection = $e('.themes-hidden');
     if (themesMenuSection) {
      themesMenuSection.style.display = settings.themes ? 'block' : 'none';
     }

    // Hide sidebar
    const sidebarSection = $e('#secondary > #secondary-inner');

    if (sidebarSection) {
      sidebarSection.classList.add('side-moi');
    const sidebarSection2 = $e('.side-moi');

    sidebarSection2.style.display = settings.hideSidebar ? 'none' : 'block';
    }

    // Disable autoplay
    const autoplayToggle = $e('.ytp-autonav-toggle-button');
    if (autoplayToggle) {
      const isCurrentlyOn =
        autoplayToggle.getAttribute('aria-checked') === 'true';
      if (settings.disableAutoplay && isCurrentlyOn) {
        autoplayToggle.click();
      } else if (!settings.disableAutoplay && !isCurrentlyOn) {
        autoplayToggle.click();
      }
    }
    // Disable subtitles
    const subtitleToggle = $e('.ytp-subtitles-button');
    if (subtitleToggle) {
      const isCurrentlyOn =
        subtitleToggle.getAttribute('aria-pressed') === 'true';
      if (settings.disableSubtitles && isCurrentlyOn) {
        subtitleToggle.click();
      } else if (!settings.disableSubtitles && !isCurrentlyOn) {
        subtitleToggle.click();
      }
    }
    // Apply cinematic lighting setting
    if (isWatchPage()) {
      setTimeout(() => {
        const isCurrentlyActive = isCinematicActive();
        // Si la sincronización está activa, funciona como antes
        if (settings.syncCinematic) {
          if (settings.cinematicLighting && !isCurrentlyActive) {
            toggleCinematicLighting();
          } else if (!settings.cinematicLighting && isCurrentlyActive) {
            toggleCinematicLighting();
          }
        } else {
          // Si NO está activa, solo mostrar/ocultar #cinematics
          const cinematicDiv = $id('cinematics');
          if (cinematicDiv) {
            cinematicDiv.style.display = settings.cinematicLighting ? 'block' : 'none';
          }
        }
      }, 1000);
    }

    // Adjust font size
    // $e('body').style.fontSize = `${settings.fontSize}px`;

    // Adjust player size
    const player = $e('video');
    if (player) {
      player.style.transform = `scale(${settings.playerSize / 100})`;
    }

    // selected video quality
    const video = $e('div#movie_player');
    let ytPlayerQuality = localStorage.getItem('yt-player-quality');

    // only force quality if the user didn't select "user"
    if (video != undefined && settings.selectVideoQuality !== "user") {
      if (ytPlayerQuality) {
        let qualitySettings = JSON.parse(ytPlayerQuality);
        qualitySettings.data = JSON.stringify({ quality: settings.selectVideoQuality, previousQuality: 240 });
        localStorage.setItem('yt-player-quality', JSON.stringify(qualitySettings));

      } else {
        let defaultQualitySettings = {
          data: JSON.stringify({ quality: 720, previousQuality: 240 }),
          expiration: Date.now() + (365 * 24 * 60 * 60 * 1000),
          creation: Date.now()
        };
        localStorage.setItem('yt-player-quality', JSON.stringify(defaultQualitySettings));
      }
    }

    // Apply menu appearance settings
    // $sp('--yt-enhance-menu-bg', settings.menuBgColor);
    // $sp('--yt-enhance-menu-text', settings.menuTextColor);
    // $sp('--yt-enhance-menu-font-size', `${settings.menuFontSize}px`);

    // Apply theme
    const selectedTheme = themes[settings.theme];
    const isThemeCustom = $e(`input[name="theme"][value="custom"]`).checked;
    const isThemeNormal = $e(`input[name="theme"][value="normal"]`).checked;
    const themeCustomOptions = $e('.theme-custom-options');
    const themeNormal = $e('.theme-selected-normal');
    // Dynamic CSS (avoid GM_addStyle accumulating thousands of style tags)
    let dynamicCss = '';
    const addDynamicCss = (css) => {
      if (!css) return;
      dynamicCss += `\n${css}\n`;
    };
    if(isThemeCustom != undefined) {
      themeNormal.style.display = "flex"
      themeCustomOptions.style.display = "flex";
      $e('.themes-options').style.display = "none";
    }
    if(isThemeNormal) {
      $e(`input[name="theme"][value="custom"]`).checked = false;
    }




    function checkDarkMode() {

      if(settings.themes) {

        if (isDarkModeActive === 'dark' && !isThemeCustom) {
          // Apply theme
          $e('.themes-options').style.display = "block";
          themeNormal.style.display = "none";
          themeCustomOptions.style.display = "none";

          if(settings.theme === '0') {
            addDynamicCss(`
              .botones_div {
               background-color: transparent;
               border: none;
               color: #ccc !important;
               user-select: none;
             }
               `);
            return;
          }

            $sp('--yt-spec-base-background', selectedTheme.gradient);
            $sp('--yt-spec-text-primary', selectedTheme.textColor);
            $sp('--yt-spec-text-secondary', selectedTheme.textColor);
            $sp('--yt-spec-menu-background', selectedTheme.gradient);
            $sp('--yt-spec-icon-inactive', selectedTheme.textColor);
            $sp('--yt-spec-brand-icon-inactive', selectedTheme.textColor);
            $sp('--yt-spec-brand-icon-active', selectedTheme.gradient);
            $sp('--yt-spec-static-brand-red', selectedTheme.gradient); // line current time
            $sp('--yt-spec-raised-background', selectedTheme.raised);
            $sp('--yt-spec-static-brand-red', selectedTheme.CurrentProgressVideo);
            $sp('--yt-spec-static-brand-white', selectedTheme.textColor);
            $sp('--ytd-searchbox-background', selectedTheme.gradient);
            $sp('--ytd-searchbox-text-color', selectedTheme.textColor);
            $sp('--ytcp-text-primary', settings.textColor);
            addDynamicCss(`
              .botones_div {
              background-color: transparent;
              border: none;
              color: #999999;
              user-select: none;
            }
              .ytp-menuitem[aria-checked=true] .ytp-menuitem-toggle-checkbox {
              background:  ${selectedTheme.gradient} !important;
              }
            #background.ytd-masthead { background: ${selectedTheme.gradient}  !important; }
            .ytp-swatch-background-color {
            background: ${
              selectedTheme.gradient
            } !important;
          }
          #shorts-container, #page-manager.ytd-app {
            background: ${selectedTheme.gradient.replace(/(#[0-9a-fA-F]{6})/g, `$1${36}`)};
          }
            ytd-engagement-panel-title-header-renderer[shorts-panel] #header.ytd-engagement-panel-title-header-renderer {
            background: ${selectedTheme.gradient}  !important;}
            .buttons-tranlate {
            background: ${selectedTheme.btnTranslate} !important;
            }
            .badge-shape-wiz--thumbnail-default {
            color: ${selectedTheme.videoDuration} !important;
            background: ${selectedTheme.gradient} !important;
            }
            #logo-icon {
            color:  ${selectedTheme.textLogo} !important;
          }
          .yt-spec-button-shape-next--overlay.yt-spec-button-shape-next--text {
            color:  ${selectedTheme.iconsColor} !important;
          }
          .ytd-topbar-menu-button-renderer #button.ytd-topbar-menu-button-renderer {
            color:  ${selectedTheme.iconsColor} !important;
          }
          .yt-spec-icon-badge-shape--style-overlay .yt-spec-icon-badge-shape__icon {
            color:  ${selectedTheme.iconsColor} !important;
          }
          .ytp-svg-fill {
            fill:  ${selectedTheme.iconsColor} !important;
          }
          #ytp-id-30,#ytp-id-17,#ytp-id-19,#ytp-id-20{
            fill:  ${selectedTheme.iconsColor} !important;
          }


            `);

        } else if(isDarkModeActive === 'dark' && isThemeCustom) {
          $sp('--yt-spec-base-background', settings.bgColorPicker);
          $sp('--yt-spec-text-primary', settings.primaryColorPicker);
          $sp('--yt-spec-text-secondary', settings.secondaryColorPicker);
          $sp('--yt-spec-menu-background', settings.menuColorPicker);
          $sp('--yt-spec-icon-inactive', settings.iconsColorPicker);
          $sp('--yt-spec-brand-icon-inactive', settings.primaryColorPicker);
          $sp('--yt-spec-brand-icon-active', settings.primaryColorPicker);
          $sp('--yt-spec-raised-background', settings.headerColorPicker);
          $sp('--yt-spec-static-brand-red', settings.lineColorPicker);
          $sp('--yt-spec-static-brand-white', settings.timeColorPicker);
          $sp('--ytd-searchbox-background', settings.primaryColorPicker);
          $sp('--ytd-searchbox-text-color', settings.secondaryColorPicker);
          $sp('--ytcp-text-primary', settings.primaryColorPicker);
          addDynamicCss(`
            .html5-video-player {
                color: ${settings.primaryColorPicker} !important;
              }
                .ytProgressBarLineProgressBarPlayed {
                background: linear-gradient(to right, ${settings.progressbarColorPicker} 80%, ${settings.progressbarColorPicker} 100%);

                }
              .ytp-menuitem .ytp-menuitem-icon svg path{
                fill: ${settings.iconsColorPicker} !important;
                }
                .ytThumbnailOverlayProgressBarHostWatchedProgressBarSegment {
                  background: linear-gradient(to right, ${settings.lineColorPicker} 80%, ${settings.lineColorPicker} 100%) !important;
                }
                .yt-badge-shape--thumbnail-default {
                  color: ${settings.timeColorPicker} !important;
                }
                a svg > path, .ytp-button svg path  {
                  fill: ${settings.iconsColorPicker} !important;
              }
                svg.path{
                 fill: ${settings.iconsColorPicker} !important;
                }

              svg {
                color: ${settings.iconsColorPicker} !important;
                }
              .ytp-volume-slider-handle:before, .ytp-volume-slider-handle, .ytp-tooltip.ytp-preview:not(.ytp-text-detail) {
                background-color: ${settings.iconsColorPicker} !important;
              }
                .ytp-autonav-toggle-button[aria-checked=true] {
                  background-color: ${settings.iconsColorPicker} !important;
                }
                  .tp-yt-iron-icon {
                   fill: ${settings.iconsColorPicker} !important;
                  }

             .botones_div {
            background-color: transparent;
            border: none;
            color: ${settings.iconsColorPicker} !important;
            user-select: none;
          }
              #container.ytd-searchbox {
              color: red !important;
              }
            .ytp-menuitem[aria-checked=true] .ytp-menuitem-toggle-checkbox {
            background:  ${settings.primaryColorPicker} !important;
            }
            .yt-spec-icon-shape {
              display: flex;
              align-items: center;
              justify-content: center;
              width: 100%;
              height: 100%;
              color: ${settings.iconsColorPicker} !important;
          }
            .ytp-time-current, .ytp-time-separator, .ytp-time-duration {
              color: ${settings.iconsColorPicker} !important;
            }
            #background.ytd-masthead { background: ${settings.headerColorPicker}  !important; }
            .ytp-swatch-background-color {
            background: ${
              settings.progressbarColorPicker
            } !important;
          }
        #shorts-container, #page-manager.ytd-app {
            background: ${settings.bgColorPicker}36;
            }
            ytd-engagement-panel-title-header-renderer[shorts-panel] #header.ytd-engagement-panel-title-header-renderer {
            background: ${settings.bgColorPicker}  !important;}

            .badge-shape-wiz--thumbnail-default {
            color: ${settings.timeColorPicker} !important;
             background: ${settings.secondaryColor} !important;
            }
             #logo-icon {
             color:  ${settings.primaryColorPicker} !important;
          }
          .yt-spec-button-shape-next--overlay.yt-spec-button-shape-next--text {
            color:  ${settings.iconsColorPicker} !important;
          }
          .ytd-topbar-menu-button-renderer #button.ytd-topbar-menu-button-renderer {
            color:  ${settings.iconsColorPicker} !important;
          }
          .yt-spec-icon-badge-shape--style-overlay .yt-spec-icon-badge-shape__icon {
            color:  ${settings.iconsColorPicker} !important;
          }
          .ytp-svg-fill {
            fill:  ${settings.iconsColorPicker} !important;
          }
          #ytp-id-30,#ytp-id-17,#ytp-id-19,#ytp-id-20{
            fill:  ${settings.iconsColorPicker} !important;
          }
            `);
        } else {
          addDynamicCss(`
            .botones_div {
             background-color: transparent;
             border: none;
             color: #000 !important;
             user-select: none;
           }
             `);
        }

      } else {
        addDynamicCss(`
          .botones_div {
           background-color: transparent;
           border: none;
           color: #ccc !important;
           user-select: none;
         }
           `);
      }

    }


    addDynamicCss(`
      #columns.style-scope.ytd-watch-flexy {
        flex-direction: ${settings.reverseMode ? 'row-reverse' : 'row'} !important;
        padding-left: ${settings.reverseMode ? '20px' : '0'} !important;
        }
        #secondary.style-scope.ytd-watch-flexy {display: ${settings.hideSidebar ? 'none' : 'block'} !important;}


        #icon-menu-settings {
         color: ${settings.iconsColorPicker} !important;
        }


      `);

    checkDarkMode();
    // Apply dynamic CSS once per settings update
    setDynamicCss(dynamicCss);

    // Apply new features (safe, no heavy loops)
    applyBookmarksIfEnabled(settings);
    setupContinueWatchingFeature(settings.continueWatching);
    scheduleLikeBarUpdate(settings, 5);
    setupShortsChannelNameFeature(settings.shortsChannelName);
    setupLockupCachedStats();
   function checkForVideo() {
    if (!settings.waveVisualizer) {
      cleanup(true); // Limpieza completa
      return;
    }
    const video = $e('video');
    const miniPlayer = $e('.ytp-miniplayer-ui');
    if ((video && document.location.href.includes('watch')) || miniPlayer) {

      // Solo si el video cambió o no está configurado
      if (video !== currentVideo || !isSetup) {
        cleanup(true); // Limpieza completa antes de crear uno nuevo
        setupAudioAnalyzer(video);
      } else if (controlPanel && video.paused === false) {
        showCanvas();
      }
    }
  }


  checkForVideo();

    function downloadDescriptionVideo() {
      if (!window.location.href.includes('youtube.com/watch')) return;
      if ($e('#button_copy_description')) return;

      const containerDescription = $e('#bottom-row.style-scope.ytd-watch-metadata');
      if (!containerDescription) return;

      const buttomHTML = `
        <div id="button_copy_description" style="display: flex; justify-content: end; align-items: center;margin-top: 10px;" >
          <button id="copy-description" title="Copy description" class="botones_div" type="button" style="cursor: pointer;">
            <i style="font-size: 20px;" class="fa-solid fa-copy"></i>
          </button>
        </div>
      `;

      containerDescription.insertAdjacentHTML('beforebegin', buttomHTML);

      $id('copy-description').addEventListener('click', () => {
        const ldJson = [...$m('script[type="application/ld+json"]')];
        for (let script of ldJson) {
          try {
            const data = JSON.parse(script.innerText);
            if (data['@type'] === 'VideoObject') {
              const description =
                `📅 Date published: ${data.uploadDate || 'No disponible'}\n` +
                `Author: ${data.author || 'No disponible'}\n` +
                `🎬 Name video: ${data.name || 'No disponible'}\n` +
                `🖼️ Thumbnail: ${Array.isArray(data.thumbnailUrl) ? data.thumbnailUrl.join(', ') : data.thumbnailUrl || 'No disponible'}\n` +
                `📝 Description: ${data.description || 'No disponible'}\n\n\n` +
                `🎭 Category: ${data.genre || 'No disponible'}\n`;

              navigator.clipboard.writeText(description);
            }
          } catch (e) {
            Notify('error', 'Error parsing JSON-LD');
          } finally {
            Notify('success', 'Description copied');
          }
        }
      });
    }

    downloadDescriptionVideo();


    async function traductor() {
      const texto = $m('#content-text');
      if ($e('.buttons-tranlate')) return;

      const languages = languagesTranslate;
      const idiomaDestino = $id('select-languages-comments-select').value;

      for (let i = 0; i < texto.length; i++) {

        const optionsHTML = Object.entries(languages)
          .map(([code, name]) => {
            const selected = code === idiomaDestino ? 'selected' : '';
            return `<option value="${code}" ${selected}>${name}</option>`;
          })
          .join('');

        const controlsHTML = `
          <div class="traductor-container" data-index="${i}">
          <button class="buttons-tranlate" id="btn${i}"> Translate <i class="fa-solid fa-language"></i></button>
          <select class="select-traductor" id="select${i}">
           ${optionsHTML}
          </select>
          </div>
        `;

        texto[i].insertAdjacentHTML('afterend', controlsHTML);
      }

      const botones = $m('.buttons-tranlate');
      const selects = $m('.select-traductor');

      botones.forEach((boton, i) => {
        boton.addEventListener('click', () => {
          const selectedLang = selects[i].value;
          const urlLista = `?client=dict-chrome-ex&sl=auto&tl=${selectedLang}&q=` + texto[i].textContent;

          fetch(apiGoogleTranslate + urlLista)
            .then((response) => response.json())
            .then((datos) => {
              texto[i].textContent = datos[0][0];
              botones[i].textContent = 'Translated';
            })
            .catch((err) => {
              console.error('Error en la traducción:', err);
            });
        });
      });
    }



    function limpiarHTML(selector) {
      $m(selector).forEach((button) => button.remove());
    }

    function checkScroll () {
      const avatars = $m('#author-thumbnail-button #img.style-scope.yt-img-shadow');

      if (avatars.length > 0 && settings.avatars) {
        limpiarHTML('.yt-image-avatar-download');
        agregarBotonesDescarga();
      }

      const divEl = $e('#content-text');
      const divEl2 = $e('ytd-item-section-renderer[static-comments-header] #contents');

      if (settings.translation) {
        if (divEl !== undefined || divEl2 !== undefined) {
          limpiarHTML('.buttons-tranlate');
          limpiarHTML('.select-traductor');
          traductor();
        }
      }

    }

    window.onscroll = () => {
      checkScroll();
    }


  const contentScrollable = $e('.anchored-panel.style-scope.ytd-shorts #contents.style-scope.ytd-item-section-renderer.style-scope.ytd-item-section-renderer');
  if (contentScrollable) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          contentScrollable.addEventListener('scroll', () => {
            checkScroll();
          });
        }
      });
    }, { threshold: 0.1 });

    observer.observe(contentScrollable);
  }

    function agregarBotonesDescarga() {
      const avatars = $m('#author-thumbnail-button #img.style-scope.yt-img-shadow');


      avatars.forEach((img) => {

        if (img.parentElement.querySelector('.yt-image-avatar-download')) return;

        const button = $cl('button');
        button.innerHTML = '<i class="fa fa-download"></i>';
        button.classList.add('yt-image-avatar-download');

        button.onclick = async function () {
          try {
            const imageUrl = img.src.split('=')[0];
            const response = await fetch(imageUrl);
            const blob = await response.blob();
            const blobUrl = URL.createObjectURL(blob);

            const parentComment = img.closest('ytd-comment-thread-renderer, ytd-comment-renderer');
            const nameElement = parentComment?.querySelector('#author-text');
            let authorName = nameElement ? nameElement.textContent.trim() : 'avatar';
            authorName = authorName.replace(/[\/\\:*?"<>|]/g, '');

            const link = $cl('a');
            link.href = blobUrl;
            link.download = `${authorName}_avatar.jpg` || 'avatar.jpg';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            URL.revokeObjectURL(blobUrl);
          } catch (error) {
            console.error('Error al descargar la imagen:', error);
          }
        };

        img.parentElement.style.position = 'relative';
        img.parentElement.appendChild(button);
      });
    }

    const redirectToClassic = () => {
      const videoId = window.location.pathname.split('/').pop();
      const classicUrl = `https://www.youtube.com/watch?v=${videoId}`;
      window.open(classicUrl, '_blank');
      $e('video.video-stream.html5-main-video').pause();
    };

    // Update the Shorts "views" button label (same bar as Classic). Call with viewCount from API/cache.
    function updateShortsViewsButton(videoId, viewCount) {
      const bar = $e('reel-action-bar-view-model');
      if (!bar) return;
      const viewsWrap = bar.querySelector('[data-yt-tools-shorts-views]');
      if (!viewsWrap) return;
      const labelSpan = viewsWrap.querySelector('.yt-spec-button-shape-with-label__label span, [role="text"]');
      if (!labelSpan) return;
      labelSpan.textContent = Number.isFinite(viewCount) && viewCount >= 0 ? FormatterNumber(viewCount, 0) : '—';
    }

    // Update the Shorts "rating" button label (rating 0–5 from API/cache, shown as e.g. "4.9").
    function updateShortsRatingButton(videoId, rating) {
      const bar = $e('reel-action-bar-view-model');
      if (!bar) return;
      const ratingWrap = bar.querySelector('[data-yt-tools-shorts-rating]');
      if (!ratingWrap) return;
      const labelSpan = ratingWrap.querySelector('.yt-spec-button-shape-with-label__label span, [role="text"]');
      if (!labelSpan) return;
      labelSpan.textContent = (Number.isFinite(rating) && rating >= 0 && rating <= 5) ? rating.toFixed(1) : '—';
    }

    // Build one YT-style button for the reel action bar (same structure as like/dislike/comments).
    function createReelBarButton(opts) {
      const wrap = document.createElement('div');
      wrap.className = 'button-view-model ytSpecButtonViewModelHost';
      if (opts.dataAttr) wrap.setAttribute(opts.dataAttr, '1');
      wrap.innerHTML = `
        <label class="yt-spec-button-shape-with-label">
          <button type="button" class="yt-spec-button-shape-next yt-spec-button-shape-next--tonal yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-l yt-spec-button-shape-next--icon-button yt-spec-button-shape-next--enable-backdrop-filter-experiment yt-spec-button-shape-next--enable-drop-shadow-experiment" title="${opts.title || ''}" aria-label="${opts.ariaLabel || ''}">
            <div class="yt-spec-button-shape-next__icon" aria-hidden="true">
              <span class="yt-icon-shape ytSpecIconShapeHost">${opts.iconSvg || ''}</span>
            </div>
          </button>
          <div class="yt-spec-button-shape-with-label__label" aria-hidden="false">
            <span class="yt-core-attributed-string yt-core-attributed-string--white-space-pre-wrap yt-core-attributed-string--text-alignment-center yt-core-attributed-string--word-wrapping" role="text">${opts.labelText || ''}</span>
          </div>
        </label>
      `;
      const btn = wrap.querySelector('button');
      if (opts.onclick) btn.addEventListener('click', opts.onclick);
      return wrap;
    }

    const eyeIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-eye"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /><path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" /></svg>';
    const classicIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-device-tv"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 9a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v9a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2l0 -9" /><path d="M16 3l-4 4l-4 -4" /></svg>';
    const starIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>';

    function insertReelBarButtons() {
      const isShortsPage = document.location.pathname.startsWith('/shorts');
      const bar = $e('reel-action-bar-view-model');
      if (!isShortsPage || !bar) {
        document.querySelectorAll('[data-yt-tools-shorts-classic], [data-yt-tools-shorts-views], [data-yt-tools-shorts-rating]').forEach(el => el.remove());
        return;
      }
      if (bar.querySelector('[data-yt-tools-shorts-classic]')) return;

      const classicBtn = createReelBarButton({
        dataAttr: 'data-yt-tools-shorts-classic',
        title: 'Classic mode',
        ariaLabel: 'Classic mode',
        iconSvg: classicIconSvg,
        labelText: 'Clásico',
        onclick: redirectToClassic,
      });
      const viewsBtn = createReelBarButton({
        dataAttr: 'data-yt-tools-shorts-views',
        title: 'Vistas',
        ariaLabel: 'Vistas',
        iconSvg: eyeIconSvg,
        labelText: '—',
        onclick: function () {},
      });
      const ratingBtn = createReelBarButton({
        dataAttr: 'data-yt-tools-shorts-rating',
        title: 'Rating (likes/dislikes)',
        ariaLabel: 'Rating',
        iconSvg: starIconSvg,
        labelText: '—',
        onclick: function () {},
      });

      bar.insertBefore(ratingBtn, bar.firstChild);
      bar.insertBefore(viewsBtn, bar.firstChild);
      bar.insertBefore(classicBtn, bar.firstChild);

      const videoId = (document.location.pathname.split('/').filter(Boolean))[1];
      if (videoId) {
        const persisted = getLikesDislikesFromPersistedCache(videoId);
        if (persisted && persisted.viewCount != null) updateShortsViewsButton(videoId, persisted.viewCount);
        if (persisted && persisted.rating != null) updateShortsRatingButton(videoId, persisted.rating);
      }
      __ytToolsRuntime.updateShortsViewsButton = updateShortsViewsButton;
      __ytToolsRuntime.updateShortsRatingButton = updateShortsRatingButton;
    }

    const insertButtons = () => {
      insertReelBarButtons();
    };

  const observeDOM = () => {
      if (__ytToolsRuntime.shortsObserver) return;
      const observer = new MutationObserver(() => {
          insertButtons();
          addIcon();
          // obs.disconnect();
      });
      observer.observe(document.body, {
          childList: true,
          subtree: true
      });
      __ytToolsRuntime.shortsObserver = observer;
  };

    if (!__ytToolsRuntime.shortsObserver) {
      insertButtons();
      observeDOM();
    }


    const targetNode = $e('body');

    if (targetNode != undefined) {
      const element = $e('ytd-item-section-renderer[static-comments-header] #contents');
      if(element != undefined && settings.theme !== 'custom') {
        const observerElementDom = (elem) => {
          const observer = new IntersectionObserver(entries => {

              if(entries[0].isIntersecting) {

                element.style.background = `${selectedTheme.gradient ?? ''}`;
              } else {return}
          })

          return observer.observe($e(`${elem}`))

        }
        observerElementDom('ytd-item-section-renderer[static-comments-header] #contents')
      }
    }

    // Stats

    function formatTime(seconds) {
      if (isNaN(seconds)) return '0h 0m 0s';
      seconds = Math.floor(seconds);
      const h = Math.floor(seconds / 3600);
      const m = Math.floor((seconds % 3600) / 60);
      const s = seconds % 60;
      return `${h}h ${m}m ${s}s`;
    }

  function updateUI() {
      $id('total-time').textContent = formatTime(usageTime);
      $id('video-time').textContent = formatTime(videoTime);
      $id('shorts-time').textContent = formatTime(shortsTime);

      const maxTime = 86400; // 24 hours
      $id('usage-bar').style.width =
          `${(usageTime / maxTime) * 100}%`;
      $id('video-bar').style.width =
          `${(videoTime / maxTime) * 100}%`;
      $id('shorts-bar').style.width =
          `${(shortsTime / maxTime) * 100}%`;
  }

  function detectContentType(videoElement) {
      if (/\/shorts\//.test(window.location.pathname)) return 'shorts';

      let parent = videoElement;
      while ((parent = parent.parentElement) !== null) {
          if (parent.classList.contains('shorts-container') ||
              parent.classList.contains('reel-video') ||
              parent.tagName === 'YTD-REEL-VIDEO-RENDERER') {
              return 'shorts';
          }
      }


      if (videoElement.closest('ytd-watch-flexy') ||
          videoElement.closest('#primary-inner')) {
          return 'video';
      }
      if (videoElement.closest('ytd-thumbnail') ||
          videoElement.closest('ytd-rich-item-renderer')) {
          return 'video';
      }

      return null;
    }

    function findActiveVideo() {
        const videos = $m('video');
        for (const video of videos) {
            if (!video.paused && !video.ended && video.readyState > 2) {
                return video;
            }
        }
        return null;
    }


   function cleanup(fullCleanup = false) {
      if (fullCleanup && animationId) {
        cancelAnimationFrame(animationId);
        animationId = null;
      }
      if (currentVideo) {
        currentVideo.removeEventListener('play', showCanvas);
        currentVideo.removeEventListener('pause', hideCanvas);
        currentVideo.removeEventListener('ended', hideCanvas);
      }
      if (fullCleanup) {
        if (canvas && canvas.parentNode) {
          canvas.parentNode.removeChild(canvas);
          canvas = null;
          ctx = null;
        }
        if (controlPanel && controlPanel.parentNode) {
          controlPanel.parentNode.removeChild(controlPanel);
          controlPanel = null;
        }
        if (source) {
          try { source.disconnect(); } catch (err) {}
          source = null;
        }
        if (audioCtx) {
          try { audioCtx.close(); } catch (err) {}
          audioCtx = null;
        }
        if (currentVideo && currentVideo[PROCESSED_FLAG]) {
          delete currentVideo[PROCESSED_FLAG];
        }
        currentVideo = null;
        isSetup = false;
      } else {
        if (canvas) canvas.style.opacity = '0';
        if (controlPanel) controlPanel.style.opacity = '0';
      }
  }



    function createCanvasOverlay() {
        if (canvas) return;
        const parent = document.body;
        canvas = document.createElement('canvas');
        canvas.id = 'wave-visualizer-canvas';
        canvas.width = window.innerWidth;
        canvas.height = canvasHeight;
        canvas.style.position = 'fixed';
        canvas.style.left = '0';
        canvas.style.top = '0';
        canvas.style.width = '100%';
        canvas.style.pointerEvents = 'none';
        canvas.style.backgroundColor = 'transparent';
        canvas.style.zIndex = '10000';
        canvas.style.opacity = '0';
        canvas.style.transition = 'opacity 0.3s';

        parent.appendChild(canvas);
        ctx = canvas.getContext('2d');
    }


    function createControlPanelWave() {
      if (controlPanel) return;

      controlPanel = $cl('div');
      controlPanel.id = 'wave-visualizer-control';
      const selectAppend = $id('select-wave-visualizer-select');
      waveStyle = settings.waveVisualizerSelected;

      selectAppend.addEventListener('change', (e) => {
          waveStyle = e.target.value;
          selectAppend.value = e.target.value;
          saveSettings();
      });

  }




    // setting Audio y Analyser
    function setupAudioAnalyzer(video) {
      if (!video || video[PROCESSED_FLAG]) return;
      video[PROCESSED_FLAG] = true;
      cleanup(false);
      currentVideo = video;
      createCanvasOverlay();
      createControlPanelWave();

      if (audioCtx) {
        try { audioCtx.close(); } catch (e) {}
        audioCtx = null;
      }
      const AudioContext = window.AudioContext || window.webkitAudioContext;
      audioCtx = new AudioContext();

      analyser = audioCtx.createAnalyser();
      analyser.fftSize = 2048;
      analyser.smoothingTimeConstant = 0.85;
      bufferLength = analyser.fftSize;
      dataArray = new Uint8Array(bufferLength);
      smoothedData = new Array(bufferLength).fill(128);

      try {
        source = audioCtx.createMediaElementSource(video);
        source.connect(analyser);
        analyser.connect(audioCtx.destination);
      } catch (e) {
        Notify('error', "MediaElementSource or error:", e);
        cleanup(true);
        return;
      }

      video.removeEventListener('play', showCanvas);
      video.removeEventListener('pause', hideCanvas);
      video.removeEventListener('ended', hideCanvas);

      video.addEventListener('play', showCanvas);
      video.addEventListener('pause', hideCanvas);
      video.addEventListener('ended', hideCanvas);

      const updateCanvasSize = () => {
        if (canvas) {
          canvas.width = window.innerWidth;
          canvas.height = canvasHeight;
        }
      };

      window.removeEventListener('resize', updateCanvasSize);
      window.addEventListener('resize', updateCanvasSize);

      draw();
      isSetup = true;
    }
      function draw() {
          animationId = requestAnimationFrame(draw);

          if (parseFloat(canvas.style.opacity) <= 0) return;

          analyser.getByteTimeDomainData(dataArray);
          for (let i = 0; i < bufferLength; i++) {
              smoothedData[i] += smoothingFactor * (dataArray[i] - smoothedData[i]);
          }
          ctx.clearRect(0, 0, canvas.width, canvas.height);

          let sliceWidth = canvas.width / bufferLength;

          switch(waveStyle) {

          case 'linea': {
              ctx.lineWidth = 2;
              ctx.strokeStyle = 'lime';
              ctx.beginPath();
              let x = 0;
              for (let i = 0; i < bufferLength; i++) {
                  let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
                  if (i === 0) ctx.moveTo(x, amplitude);
                  else ctx.lineTo(x, amplitude);
                  x += sliceWidth;
              }
              ctx.stroke();
              break;
          }
          case 'barras': {
              let x = 0;
              for (let i = 0; i < bufferLength; i += 5) {
                  let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
                  ctx.fillStyle = 'cyan';
                  ctx.fillRect(x, 0, sliceWidth * 4, amplitude);
                  x += sliceWidth * 5;
              }
              break;
          }
          case 'curva': {
              ctx.lineWidth = 2;
              ctx.strokeStyle = 'yellow';
              ctx.beginPath();
              ctx.moveTo(0, Math.max(0, smoothedData[0] - 128) * scale);
              for (let i = 0; i < bufferLength - 1; i++) {
                  let x0 = i * sliceWidth;
                  let x1 = (i + 1) * sliceWidth;
                  let y0 = Math.max(0, smoothedData[i] - 128) * scale;
                  let y1 = Math.max(0, smoothedData[i + 1] - 128) * scale;
                  let cp1x = x0 + sliceWidth / 3;
                  let cp1y = y0;
                  let cp2x = x1 - sliceWidth / 3;
                  let cp2y = y1;
                  ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x1, y1);
              }
              ctx.stroke();
              break;
          }
          case 'picos': {
              ctx.fillStyle = 'magenta';
              let x = 0;
              for (let i = 0; i < bufferLength; i += 5) {
                  let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
                  ctx.beginPath();
                  ctx.arc(x, amplitude, 2, 0, Math.PI * 2);
                  ctx.fill();
                  x += sliceWidth * 5;
              }
              break;
          }
          case 'solida': {
              ctx.beginPath();
              let x = 0;
              ctx.moveTo(0, 0);
              for (let i = 0; i < bufferLength; i++) {
                  let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
                  ctx.lineTo(x, amplitude);
                  x += sliceWidth;
              }
              ctx.lineTo(canvas.width, 0);
              ctx.closePath();
              ctx.fillStyle = 'rgba(0,255,0,0.3)';
              ctx.fill();
              break;
          }
          case 'dinamica': {
              let gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
              gradient.addColorStop(0, 'red');
              gradient.addColorStop(0.5, 'purple');
              gradient.addColorStop(1, 'blue');
              ctx.lineWidth = 3;
              ctx.strokeStyle = gradient;
              ctx.beginPath();
              let x = 0;
              for (let i = 0; i < bufferLength; i++) {
                  let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
                  if (i === 0) ctx.moveTo(x, amplitude);
                  else ctx.lineTo(x, amplitude);
                  x += sliceWidth;
              }
              ctx.stroke();
              break;
          }
          case 'montana': {
              ctx.beginPath();
              let x = 0;
              ctx.moveTo(0, 0);
              for (let i = 0; i < bufferLength; i++) {
                  let amp = (smoothedData[i] - 128) * scale * 0.8;
                  ctx.lineTo(x, amp);
                  x += sliceWidth;
              }
              ctx.lineTo(canvas.width, 0);
              ctx.closePath();
              ctx.fillStyle = 'rgba(128,128,255,0.4)';
              ctx.fill();
              break;
          }

          default:
              break;
          }
      }



  if (!__ytToolsRuntime.statsObserver) {
    const observer = new MutationObserver(() => {
        const newVideo = findActiveVideo();
        if (newVideo !== activeVideo) {
            activeVideo = newVideo;
            if (activeVideo) {
                activeType = detectContentType(activeVideo);
            }
        }
    });
    observer.observe(document.body, {
        childList: true,
        subtree: true,
        attributes: true
    });
    __ytToolsRuntime.statsObserver = observer;
  }

        checkForVideo();

  if (!__ytToolsRuntime.statsIntervalId) {
    __ytToolsRuntime.statsIntervalId = setInterval(() => {

        const now = Date.now();
        // checkForVideo();
        const delta = (now - lastUpdate) / 1000;
        if (document.visibilityState === 'visible') {
            usageTime += delta;
        }

        if (activeVideo && !activeVideo.paused) {
            if (activeType === 'video') {
                videoTime += delta;
            } else if (activeType === 'shorts') {
                shortsTime += delta;
            }
        }
        lastUpdate = now;
        // save stats
        GM_setValue(STORAGE.USAGE, usageTime);
        GM_setValue(STORAGE.VIDEO, videoTime);
        GM_setValue(STORAGE.SHORTS, shortsTime);
        updateUI();
    }, UPDATE_INTERVAL);
  }






  updateUI();

  // end stats
  if (__ytToolsRuntime.settingsLoaded) {
    saveSettings();
  }

  }

  let validoBotones = true;
  function renderizarButtons() {
    const addButton = $e('.style-scope .ytd-watch-metadata');
    const addButton2 = $e('#contents');

    if (addButton != undefined && validoBotones) {
        validoBotones = false;
        const isVisible = !!(
          addButton.offsetWidth ||
          addButton.offsetHeight ||
          addButton.getClientRects().length
        );
        if (isVisible) {
          addButton.insertAdjacentHTML("beforebegin", menuBotones);
        } else if (addButton2 != undefined) {
          addButton.insertAdjacentHTML("beforebegin", menuBotones);
        }
    }

    const formulariodescarga      = $e('.formulariodescarga');
    const formulariodescargaaudio = $e('.formulariodescargaaudio');
    const btn1mp4               = $e('.btn1');
    const btn2mp3               = $e('.btn2');
    const btn3cancel            = $e('.btn3');
    const selectcalidades       = $e('.selectcalidades');
    const selectcalidadesaudio  = $e('.selectcalidadesaudio');

    [formulariodescarga, formulariodescargaaudio].forEach(form => {
      if (!form) return;
      if (form.dataset.ytToolsPreventDefault === '1') return;
      form.addEventListener('click', e => e.preventDefault());
      form.dataset.ytToolsPreventDefault = '1';
    });

    if (selectcalidades && selectcalidades.dataset.ytToolsBound !== '1') {
      selectcalidades.dataset.ytToolsBound = '1';
      selectcalidades.addEventListener('change', e => {
      const quality = e.target.value;
      if (!quality) return; // Don't proceed if no quality selected

      const downloadContainer = $id('descargando');
      const downloadText = downloadContainer.querySelector('.download-text');
      const downloadQuality = downloadContainer.querySelector('.download-quality');
      const downloadBtn = downloadContainer.querySelector('.download-btn');
      const retryBtn = downloadContainer.querySelector('.retry-btn');
      const progressContainer = downloadContainer.querySelector('.progress-container');

      // Update UI
      downloadContainer.classList.add('video');
      downloadContainer.classList.remove('ocultarframe');
      downloadText.textContent = `Download ${quality.toUpperCase()} And Please Wait...`;
      downloadQuality.textContent = `${quality}p`;

      // Show download button, hide progress
      downloadBtn.style.display = 'block';
      retryBtn.style.display = 'none';
      progressContainer.style.display = 'none';

      // Store quality for later use
      downloadContainer.dataset.quality = quality;
      downloadContainer.dataset.type = 'video';
      });
    }

    if (selectcalidadesaudio && selectcalidadesaudio.dataset.ytToolsBound !== '1') {
      selectcalidadesaudio.dataset.ytToolsBound = '1';
      selectcalidadesaudio.addEventListener('change', e => {
      const format = e.target.value;
      if (!format) return; // Don't proceed if no format selected

      const downloadContainer = $id('descargandomp3');
      const downloadText = downloadContainer.querySelector('.download-text');
      const downloadQuality = downloadContainer.querySelector('.download-quality');
      const downloadBtn = downloadContainer.querySelector('.download-btn');
      const retryBtn = downloadContainer.querySelector('.retry-btn');
      const progressContainer = downloadContainer.querySelector('.progress-container');

      // Update UI
      downloadContainer.classList.add('audio');
      downloadContainer.classList.remove('ocultarframeaudio');
      downloadText.textContent = `Download ${format.toUpperCase()} And Please Wait...`;
      downloadQuality.textContent = format.toUpperCase();

      // Show download button, hide progress
      downloadBtn.style.display = 'block';
      retryBtn.style.display = 'none';
      progressContainer.style.display = 'none';

      // Store format for later use
      downloadContainer.dataset.quality = format;
      downloadContainer.dataset.type = 'audio';
      });
    }

    if (btn3cancel && btn3cancel.dataset.ytToolsBound !== '1') {
      btn3cancel.dataset.ytToolsBound = '1';
      btn3cancel.addEventListener('click', () => {
      // Hide all selects
      selectcalidades?.classList.add('ocultarframe');
      selectcalidadesaudio?.classList.add('ocultarframeaudio');

      // Hide all download containers
      const videoContainer = $id('descargando');
      const audioContainer = $id('descargandomp3');

      if (videoContainer) {
        videoContainer.classList.add('ocultarframe');
        videoContainer.classList.remove('video', 'audio', 'completed');
        videoContainer.removeAttribute('data-quality');
        videoContainer.removeAttribute('data-type');
        videoContainer.removeAttribute('data-downloading');
        videoContainer.removeAttribute('data-url-opened');
        videoContainer.removeAttribute('data-last-download-url');
        videoContainer.querySelector?.('.download-again-btn')?.style && (videoContainer.querySelector('.download-again-btn').style.display = 'none');
      }

      if (audioContainer) {
        audioContainer.classList.add('ocultarframeaudio');
        audioContainer.classList.remove('video', 'audio', 'completed');
        audioContainer.removeAttribute('data-quality');
        audioContainer.removeAttribute('data-type');
        audioContainer.removeAttribute('data-downloading');
        audioContainer.removeAttribute('data-url-opened');
        audioContainer.removeAttribute('data-last-download-url');
        audioContainer.querySelector?.('.download-again-btn')?.style && (audioContainer.querySelector('.download-again-btn').style.display = 'none');
      }

      // Hide all forms
      formulariodescarga?.classList.add('ocultarframe');
      formulariodescargaaudio?.classList.add('ocultarframe');

      // Reset forms
      formulariodescarga?.reset();
      formulariodescargaaudio?.reset();
      });
    }

      // Add event listeners for download buttons (only once)
  if (!__ytToolsRuntime.downloadClickHandlerInitialized) {
    __ytToolsRuntime.downloadClickHandlerInitialized = true;
    document.addEventListener('click', (e) => {
      const target = e.target;
      if (!(target instanceof Element)) return;

      const clicked =
        target.closest('.download-btn') ||
        target.closest('.retry-btn') ||
        target.closest('.progress-retry-btn') ||
        target.closest('.download-again-btn');
      if (!clicked) return;

      const container = clicked.closest('.download-container');
      if (!container) return;

      const quality = container.dataset.quality;
      const type = container.dataset.type;
      // download-again just re-opens the last URL (no restart)
      if (clicked.classList.contains('download-again-btn')) {
        const url = container.dataset.lastDownloadUrl;
        if (url) window.open(url);
        return;
      }
      if (!quality || !type) return;

      if (clicked.classList.contains('progress-retry-btn')) {
        container.dataset.downloading = 'false';
        container.dataset.urlOpened = 'false';
        container.dataset.lastDownloadUrl = '';
        container.querySelector?.('.download-again-btn')?.style && (container.querySelector('.download-again-btn').style.display = 'none');
      }
      startDownloadVideoOrAudio(quality, container);
    });
  }



    if (btn1mp4 && btn1mp4.dataset.ytToolsBound !== '1') {
      btn1mp4.dataset.ytToolsBound = '1';
      btn1mp4.addEventListener('click', () => {
      // Show video select, hide audio select
      selectcalidades?.classList.remove('ocultarframe');
      selectcalidadesaudio?.classList.add('ocultarframeaudio');

      // Hide all download containers
      const videoContainer = $id('descargando');
      const audioContainer = $id('descargandomp3');

      if (videoContainer) {
        videoContainer.classList.add('ocultarframe');
        videoContainer.classList.remove('video', 'audio', 'completed');
        videoContainer.removeAttribute('data-quality');
        videoContainer.removeAttribute('data-type');
        videoContainer.removeAttribute('data-downloading');
        videoContainer.removeAttribute('data-url-opened');
      }

      if (audioContainer) {
        audioContainer.classList.add('ocultarframeaudio');
        audioContainer.classList.remove('video', 'audio', 'completed');
        audioContainer.removeAttribute('data-quality');
        audioContainer.removeAttribute('data-type');
        audioContainer.removeAttribute('data-downloading');
        audioContainer.removeAttribute('data-url-opened');
      }

      // Show video form
      formulariodescarga?.classList.remove('ocultarframe');
      formulariodescarga.style.display = '';
      formulariodescargaaudio?.classList.add('ocultarframe');

      // Reset forms
      formulariodescarga?.reset();
      formulariodescargaaudio?.reset();
      });
    }

    if (btn2mp3 && btn2mp3.dataset.ytToolsBound !== '1') {
      btn2mp3.dataset.ytToolsBound = '1';
      btn2mp3.addEventListener('click', () => {
      // Show audio select, hide video select
      selectcalidadesaudio?.classList.remove('ocultarframeaudio');
      selectcalidades?.classList.add('ocultarframe');

      // Hide all download containers
      const videoContainer = $id('descargando');
      const audioContainer = $id('descargandomp3');

      if (videoContainer) {
        videoContainer.classList.add('ocultarframe');
        videoContainer.classList.remove('video', 'audio', 'completed');
        videoContainer.removeAttribute('data-quality');
        videoContainer.removeAttribute('data-type');
        videoContainer.removeAttribute('data-downloading');
        videoContainer.removeAttribute('data-url-opened');
      }

      if (audioContainer) {
        audioContainer.classList.add('ocultarframeaudio');
        audioContainer.classList.remove('video', 'audio', 'completed');
        audioContainer.removeAttribute('data-quality');
        audioContainer.removeAttribute('data-type');
        audioContainer.removeAttribute('data-downloading');
        audioContainer.removeAttribute('data-url-opened');
      }

      // Show audio form
      formulariodescargaaudio?.classList.remove('ocultarframe');
      formulariodescargaaudio.style.display = '';
      formulariodescarga?.classList.add('ocultarframe');

      // Reset forms
      formulariodescargaaudio?.reset();
      formulariodescarga?.reset();
      });
    }
      // Invertir contenido




      const btnImagen = $e('#imagen');
      const formularioButtons = $e('#eyes');

      function initClickEvent() {
        const bufferVideo = $e('.buffer_video');

        if (!bufferVideo) {

          return;
        }

        // Evita duplicar el evento
        if (!bufferVideo.dataset.listenerAdded) {
          bufferVideo.addEventListener("click", () => {
            const video = $e("video.video-stream.html5-main-video");

            if (!video) {
              console.log("No se encontró el video en la página.");
              return;
            }

            const event = new MouseEvent("contextmenu", {
              bubbles: true,
              cancelable: true
            });

            video.dispatchEvent(event);

            setTimeout(() => {
              const option = $e("body > div.ytp-popup.ytp-contextmenu > div > div > div:nth-child(7)");
              if (option) {
                option.click();
              } else {
                console.log("Opción no encontrada, intenta aumentar el tiempo de espera.");
              }
            }, 1000);
          });

          bufferVideo.dataset.listenerAdded = "true";
        }
      }

      // Run once; renderizarButtons() may run multiple times and we guard with dataset.listenerAdded
      initClickEvent();



      // valido modo oscuro y venta de video
      // Repeat video button
      let countRepeat = 0; // count
      const repeat = $e('#repeatvideo'); // Repeat button
      const imarepeat = $e('.icon-tabler-repeat'); // img repeat
      const videoFull = $e(
        '#movie_player > div.html5-video-container > video'
      );
      if(repeat != undefined) {

        repeat.onclick = () => {
          if (
            $e('#cinematics > div') != undefined ||
            videoFull != undefined
          ) {
            countRepeat += 1;
            switch (countRepeat) {
              case 1:
                document
                  .querySelector('#movie_player > div.html5-video-container > video')
                  ?.setAttribute('loop', 'true');
                imarepeat.innerHTML = `  <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-repeat-off" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
                    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
                    <path d="M4 12v-3c0 -1.336 .873 -2.468 2.08 -2.856m3.92 -.144h10m-3 -3l3 3l-3 3"></path>
                    <path d="M20 12v3a3 3 0 0 1 -.133 .886m-1.99 1.984a3 3 0 0 1 -.877 .13h-13m3 3l-3 -3l3 -3"></path>
                    <path d="M3 3l18 18"></path>
                 </svg> `; // img repeat
                break;
              case 2:
                countRepeat = 0;
                document
                  .querySelector('#movie_player > div.html5-video-container > video')
                  ?.removeAttribute('loop');
                imarepeat.innerHTML = ` <svg  xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-repeat" width="24"
                    height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
                    stroke-linecap="round" stroke-linejoin="round">
                    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
                    <path d="M4 12v-3a3 3 0 0 1 3 -3h13m-3 -3l3 3l-3 3"></path>
                    <path d="M20 12v3a3 3 0 0 1 -3 3h-13m3 3l-3 -3l3 -3"></path>
                  </svg>`;
                break;
            }
          }
          }
      }

      // Background transparent

      const cinematica = $e('#cinematics > div');
      if (cinematica != undefined) {
        cinematica.style =
          'position: fixed; inset: 0px; pointer-events: none; transform: scale(1.5, 2)';
      }
      const btnReset = $e('#reset_button'); // Reset button
      if (btnReset != undefined) {
        btnReset.addEventListener('click', function () {
          if (localStorage.getItem('colores') != null) {
            localStorage.removeItem('colores');
            $e('#ojosprotect').style.backgroundColor =
              'transparent';
            setTimeout(() => {
              location.reload();
            }, 400);
          }
        });
      }

      if (btnImagen != undefined) {
        btnImagen.onclick = () => {
          if (
            $e('#cinematics > div') != undefined ||
            videoFull != undefined
          ) {
            const parametrosURL = new URLSearchParams(window.location.search);
            let enlace = parametrosURL.get('v');

            const imageUrl = `https://i.ytimg.com/vi/${enlace}/maxresdefault.jpg`;

            fetch(imageUrl)
              .then((response) => {
                if (!response.ok) {
                  throw new Error(`HTTP error! Status: ${response.status}`);
                }
                return response.blob();
              })
              .then((blob) => {
                const imageSizeKB = blob.size / 1024;

                if (imageSizeKB >= 20) {
                  window.open(
                    `https://i.ytimg.com/vi/${enlace}/maxresdefault.jpg`,
                    'popUpWindow',
                    'height=500,width=400,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no, status=yes'
                  );
                  const imageUrlObject = URL.createObjectURL(blob);

                  const enlaceDescarga = $cl('a');
                  enlaceDescarga.href = imageUrlObject;
                  const titleVideo = $e(
                    'h1.style-scope.ytd-watch-metadata'
                  ).innerText;
                  enlaceDescarga.download = `${titleVideo}_maxresdefault.jpg`;
                  enlaceDescarga.click();

                  URL.revokeObjectURL(imageUrlObject);
                } else {
                  console.log(
                    'La imagen no excede los 20 KB. No se descargará.'
                  );
                }
              })
              .catch((error) => {
                alert('No found image');
                console.error('Error al obtener la imagen:', error);
              });
          }
        };
      }
      // for background image file photo higt quality
      // for background image file photo higt quality
      const fileInput = $id('background_image');
      const backgroundDiv = $e('ytd-app');

      const storedImage = localStorage.getItem('backgroundImage');
      if (storedImage) {
        backgroundDiv.style = `
        background-size: cover;
        background-position: center;
        background-attachment: fixed;

        background-image: url(${storedImage}) !important`;
      }

      fileInput.addEventListener('change', (event) => {
        const file = event.target.files[0];
        if (file) {
          const reader = new FileReader();
          reader.onload = function (e) {
            const imageUrl = e.target.result;
            localStorage.setItem('backgroundImage', imageUrl);
            backgroundDiv.style.backgroundImage = `url(${imageUrl})`;
          };
          reader.readAsDataURL(file);
        }
      });


      const externalLink = $e('.external_link');
      if (externalLink != undefined) {
        externalLink.onclick = () => {
          const parametrosURL = new URLSearchParams(window.location.search); // Url parametros
          let enlace;
          enlace = parametrosURL.get('v');
          window.open(
            `https://ssyoutube.com/watch?v=${enlace}&t=2s`,
            'popUpWindow',
            'height=800,width=1000,left=50%,top=100,resizable=no,scrollbars=yes,toolbar=no,menubar=yes,location=no,directories=yes, status=no'
          );
        };
      }
      const viewExternalLink = $e('.view_external_link');
      if (viewExternalLink != undefined) {
        viewExternalLink.onclick = () => {
          $e('video').click();
          const parametrosURL = new URLSearchParams(window.location.search); // Url parametros
          let enlace;
          enlace = parametrosURL.get('v');
          window.open(
            `https://www.youtube.com/embed/${enlace}?rel=0&controls=2&color=white&iv_load_policy=3&showinfo=0&modestbranding=1&autoplay=1`
          );
        };
      }
      const viewPictureToPicture = $e(
        '.video_picture_to_picture'
      );
      if (viewPictureToPicture != undefined) {
        viewPictureToPicture.onclick = () => {
          const video = $e('video');
          if ('pictureInPictureEnabled' in document) {
            if (!document.pictureInPictureElement) {

              video
                .requestPictureInPicture()
                .then(() => {
                })
                .catch((error) => {
                  console.error(
                    'Error al activar el modo Picture-in-Picture:',
                    error
                  );
                });
            } else {
              // video picture
            }
          } else {
            alert('Picture-in-Picture not supported');
          }
        };

        // Filtro de pantalla
        if (formularioButtons != undefined) {
          formularioButtons.addEventListener('input', function () {
            if (
              $e('#cinematics > div') != undefined ||
              videoFull != undefined
            ) {
              $e('#ojosprotect').style.backgroundColor =
                formularioButtons.value;
            }
          });
        }
        clearInterval(renderizarButtons);
      }

      const checked_updates = $e('.checked_updates');

      if (checked_updates != undefined) {
        checked_updates.onclick = () => {
          window.open(
            `https://update.greasyfork.org/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.user.js`
          );
        };
      }

      const screenShotVideo = $e('.screenshot_video');
      if (screenShotVideo != undefined) {
        screenShotVideo.onclick = () => {
          const video = $e('video');
          const canvas = $cl('canvas');
          canvas.width = video.videoWidth;
          canvas.height = video.videoHeight;
          const context = canvas.getContext('2d');
          context.drawImage(video, 0, 0, canvas.width, canvas.height);
          const imagenURL = canvas.toDataURL('image/png');
          const enlaceDescarga = $cl('a');
          enlaceDescarga.href = imagenURL;
          const titleVideo = $e(
            'h1.style-scope.ytd-watch-metadata'
          ).innerText;
          enlaceDescarga.download = `${video.currentTime.toFixed(
            0
          )}s_${titleVideo}.png`;
          enlaceDescarga.click();
        };
      } else {
        const containerButtons = $e('.containerButtons');

        if (containerButtons != undefined) {
          containerButtons.innerHTML = '';
        }
      }
      clearInterval(renderizarButtons);
    }




  console.log('Script en ejecución by: DeveloperMDCM');
  const HEADER_STYLE = 'color: #F00; font-size: 24px; font-family: sans-serif;';
  const MESSAGE_STYLE = 'color: #00aaff; font-size: 16px; font-family: sans-serif;';
  const CODE_STYLE = 'font-size: 14px; font-family: monospace;';

  console.log(
    '%cYoutube Tools Extension NEW UI\n' +
      '%cRun %c(v2.4.3.2)\n' +
      'By: DeveloperMDCM.',
    HEADER_STYLE,
    CODE_STYLE,
    MESSAGE_STYLE
  );

  if (!localStorage.getItem('notification-developerMDCM')) {
    Notify('info', 'Youtube Tools by: DeveloperMDCM :)');
    localStorage.setItem('notification-developerMDCM', true);
  }






  // Add event listeners to all inputs
  const inputs = $m('input');
  inputs.forEach((input) => {
    input.addEventListener('change', scheduleApplySettings);
    if (input.type === 'range') {
      input.addEventListener('change', () => {
        updateSliderValues();
        scheduleApplySettings();
      });
    }
  });

  // Some settings are controlled by <select> elements; ensure they persist and apply without duplicating listeners.
  function bindSelectOnce(id) {
    const el = $id(id);
    if (!el) return;
    if (el.dataset.ytToolsBound === '1') return;
    el.dataset.ytToolsBound = '1';
    el.addEventListener('change', () => {
      // Persist immediately
      try {
        saveSettings();
      } catch (e) {
        console.error('saveSettings error:', e);
      }
      // Apply with debounce
      scheduleApplySettings();
    });
  }

  bindSelectOnce('select-video-qualitys-select');
  bindSelectOnce('select-languages-comments-select');
  bindSelectOnce('select-wave-visualizer-select');

  // Export configuration

//   Settings saved
//   const settings = GM_getValue('ytSettingsMDCM', '{}');
//   $id('config-data').value = settings;

  $id('export-config').addEventListener('click', () => {
    const settings = GM_getValue('ytSettingsMDCM', '{}');
    $id('config-data').value = settings;
    const configData = settings;
    try {
      JSON.parse(configData); // Validate JSON
      GM_setValue('ytSettingsMDCM', configData);
      setTimeout(() => {
        Notify('success', 'Configuration export successfully!');
      }, 1000);
    } catch (e) {
      Notify('error', 'Invalid configuration data. Please check and try again.');
    }
  });
  // Import configuration
  $id('import-config').addEventListener('click', () => {
    const configData = $id('config-data').value;
    try {
      JSON.parse(configData); // Validate JSON
      GM_setValue('ytSettingsMDCM', configData);
      setTimeout(() => {
        Notify('success', 'Configuration imported successfully!');
        window.location.reload();
      }, 1000);
      window.location.reload();
    } catch (e) {
      Notify('error', 'Invalid configuration data. Please check and try again.');
    }
  });
  panel.style.display = 'none';

  // var for wave

  // Load saved settings
  // Visible element DOM
  function checkElement(selector, callback) {
    const interval = setInterval(() => {
      if ($e(selector)) {
        clearInterval(interval);
        callback();
      }
    }, 100);
  }

  const checkActiveWave = $id('wave-visualizer-toggle');
  checkActiveWave.addEventListener('change', () => {
    const waveVisualizer = $e('#wave-visualizer-toggle');
    if (waveVisualizer.checked) {
      Notify('success', 'Wave visualizer enabled');
    } else {
      hideCanvas();
      Notify('success', 'Wave visualizer disabled realod page');
      setTimeout(() => {
        window.location.reload();
      }, 1000);
    }
  });

  // Cinematic lighting toggle event listener
  const checkCinematicLighting = $id('cinematic-lighting-toggle');
  if (checkCinematicLighting) {
    checkCinematicLighting.addEventListener('change', () => {
      const cinematicToggle = $e('#cinematic-lighting-toggle');
      const syncToggle = $e('#sync-cinematic-toggle');
      const cinematicDiv = $id('cinematics');

      if (cinematicToggle.checked) {
        Notify('success', 'Cinematic mode enabled');
      } else {
        Notify('success', 'Cinematic mode disabled');
      }

      // Aplicar el comportamiento según el estado de sincronización
      if (syncToggle.checked) {
        // Si hay sincronización, usar toggleCinematicLighting
        setTimeout(() => {
          toggleCinematicLighting();
        }, 300);
      } else {
        // Si no hay sincronización, aplicar display inmediatamente
        if (cinematicDiv) {
          cinematicDiv.style.display = cinematicToggle.checked ? 'block' : 'none';
        }
      }
    });
  }

  // Sync cinematic toggle event listener
  const checkSyncCinematic = $id('sync-cinematic-toggle');
  if (checkSyncCinematic) {
    checkSyncCinematic.addEventListener('change', () => {
      const syncToggle = $e('#sync-cinematic-toggle');
      const cinematicToggle = $e('#cinematic-lighting-toggle');
      const cinematicDiv = $id('cinematics');

      if (syncToggle.checked) {
        Notify('success', 'Sync with YouTube enabled');
        // Si se activa la sincronización y el modo cinematic está activado, sincronizar con YouTube
        if (cinematicToggle.checked) {
          setTimeout(() => {
            toggleCinematicLighting();
          }, 500);
        }
      } else {
        Notify('success', 'Sync with YouTube disabled');
        // Si se desactiva la sincronización, aplicar inmediatamente el estado del toggle
        if (cinematicDiv) {
          cinematicDiv.style.display = cinematicToggle.checked ? 'block' : 'none';
        }
      }
    });
  }

  checkElement('ytd-topbar-menu-button-renderer', () => {
    loadSettings();
    initializeHeaderButtons();
    setTimeout(checkNewVersion, 3000);
  });
  // validate change url SPA youtube

  document.addEventListener('fullscreenchange', () => {
    if (document.fullscreenElement !== null) {
      hideCanvas();
    } else {
      showCanvas();
    }
  });

  document.addEventListener('yt-navigate-finish', () => {
    if (!document.location.href.includes('watch')) {
      hideCanvas();
    }
    scheduleApplySettings();
    if (!document.location.href.includes('youtube.com')) return;
    // Re-inject lockup stats when landing on watch (related column often renders late when coming from home)
    if (document.location.href.includes('youtube.com/watch')) {
      [300, 600, 1200, 2200, 3500].forEach((ms) => setTimeout(() => {
        injectLockupCachedStats();
        injectShortsLockupCachedStats();
        retargetLockupStatsObserverIfNeeded();
      }, ms));
    } else {
      // Re-inject when landing on home (feed often renders after SPA nav from watch/shorts)
      [300, 700, 1500, 2800].forEach((ms) => setTimeout(() => {
        injectLockupCachedStats();
        injectShortsLockupCachedStats();
      }, ms));
    }
  });
    GM_registerMenuCommand('Update Script by: DeveloperMDCM', function() {
      window.open('https://update.greasyfork.org/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.user.js', '_blank');
    });

    // apis for download
    // https://video-download-api.com
    // 4kdownload

  // --- Background Image Customization ---
  const inputFile = $id('background_image');
  const preview = $id('background-image-preview');
  const removeBtn = $id('remove-background-image');

  // show preview
  const storedImage = localStorage.getItem('backgroundImage');
  if (storedImage) {
    preview.style.backgroundImage = `url(${storedImage})`;
    preview.classList.add('has-image');
    removeBtn.style.display = 'flex';
  } else {
    preview.style.backgroundImage = '';
    preview.classList.remove('has-image');
    removeBtn.style.display = 'none';
  }


  preview.addEventListener('click', (e) => {
    if (e.target === removeBtn) return;
    inputFile.click();
  });

    // add background image (bind once)
    inputFile.addEventListener('change', (e) => {
      const file = e.target.files[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = function (ev) {
        const dataUrl = ev.target.result;
        preview.style.backgroundImage = `url(${dataUrl})`;
        preview.classList.add('has-image');
        localStorage.setItem('backgroundImage', dataUrl);
        removeBtn.style.display = 'flex';
      };
      reader.readAsDataURL(file);
    });

    // Remove background image (bind once)
    if (removeBtn && removeBtn.dataset.ytToolsBound !== '1') {
      removeBtn.dataset.ytToolsBound = '1';
      removeBtn.addEventListener('click', (e) => {
        e.preventDefault();
        e.stopPropagation();
        // Only allow real user click to remove stored background
        if (e.isTrusted === false) return;
        preview.style.backgroundImage = '';
        preview.classList.remove('has-image');
        localStorage.removeItem('backgroundImage');
        removeBtn.style.display = 'none';
      });
    }


})();