🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

Maximizar Video (Mejorado)

Maximiza todos los reproductores de video. Soporta imagen en imagen.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name                Maximizar Video (Mejorado)
// @name:en             Maximize Video (Improved)
// @namespace           AkioBrian
// @description         Maximiza todos los reproductores de video. Soporta imagen en imagen.
// @description:en      Maximize all video players. Support Picture-in-picture.
// @author              冻猫, ryomahan, AkioBrian
// @icon                https://i.imgur.com/3K7CBab.png
// @include             *
// @version             13.0.6
// @run-at              document-end
// @license             MIT
// ==/UserScript==

(() => {
  'use strict';

  // Variables globales
  const estado = {
    esPantallaCompleta: false,
    esIframe: false,
    conteoVerificacionAuto: 0,
    reproductor: null,
    padres: [],
    hijos: [],
    elementoSobreRaton: null,
    // Botones
    botonControl: null,
    botonPip: null,
    botonIzquierdo: null,
    botonDerecho: null,
    // Estados anteriores
    idHtmlAnterior: '',
    idBodyAnterior: '',
    controlesAnteriores: false,
    cambioEtapaYoutube: false,
    // Timers
    timerArregloScroll: null,
    timerOcultarBotones: null
  };

  // Configuración de idioma
  const idioma = navigator.language.toLowerCase().includes('es') ? 'es' : 'en';

  const textos = {
    es: {
      maximizar: "⛶ Max",
      pip: "⧉ PiP",
      consejo: "Video en iframe. Haz clic en el video e intenta de nuevo",
      listo: "Listo"
    },
    en: {
      maximizar: "⛶ Max",
      pip: "⧉ PiP",
      consejo: "Iframe video. Please click on the video and try again",
      listo: "Ready"
    }
  };

  const txt = textos[idioma];

  // Reglas específicas para sitios web
  const reglasHtml5 = {
    "www.acfun.cn": [".player-container .player"],
    "www.bilibili.com": ["#bilibiliPlayer"],
    "www.douyu.com": ["#js-player-video-case"],
    "www.huya.com": ["#videoContainer"],
    "www.twitch.tv": [".player"],
    "www.youtube.com": ["#ytd-player"],
    "www.miguvideo.com": ["#mod-player"],
    "www.yy.com": ["#player"],
    "*weibo.com": ['[aria-label="Video Player"]', ".html5-video-live .html5-video"],
    "v.huya.com": ["#video_embed_flash>div"],
    "www.netflix.com": [".VideoContainer"],
    "www.primevideo.com": [".dv-player-fullscreen"],
    "www.hulu.com": [".player-container"],
    "www.crunchyroll.com": ["#vilos-player"],
    "www.vimeo.com": [".player"],
    "www.dailymotion.com": [".player"],
    "www.facebook.com": ['[data-video-feature="video-player"]']
  };

  // Reglas para reproductores genéricos
  const reglasReproductorGeneral = [
    ".dplayer",
    ".video-js",
    ".jwplayer",
    "[data-player]",
    ".plyr",
    ".flowplayer",
    ".videojs",
    ".jw-media"
  ];

  // Verificar si estamos en un iframe
  if (window.top !== window.self) {
    estado.esIframe = true;
  }

  // Utilidades
  const utilidades = {
    log(mensaje) {
      const ahora = new Date();
      const marca = `[${ahora.toLocaleString()}]`;
      console.log(`${marca}[Maximizar Video] > ${mensaje}`);
    },

    obtenerRect(elemento) {
      const rect = elemento.getBoundingClientRect();
      const scroll = this.obtenerScroll();
      return {
        paginaX: rect.left + scroll.izquierda,
        paginaY: rect.top + scroll.arriba,
        pantallaX: rect.left,
        pantallaY: rect.top,
      };
    },

    esMedioPantallaCompleta(elemento) {
      const cliente = this.obtenerCliente();
      const rect = this.obtenerRect(elemento);

      const anchoSimilar = Math.abs(cliente.ancho - elemento.offsetWidth) < 25;
      const altoSimilar = Math.abs(cliente.alto - elemento.offsetHeight) < 25;
      const posicionCerca = rect.pantallaX < 25 && rect.pantallaY < 15;

      if ((anchoSimilar && rect.pantallaX < 25) || (altoSimilar && rect.pantallaY < 15)) {
        const centroX = Math.abs(elemento.offsetWidth / 2 + rect.pantallaX - cliente.ancho / 2) < 25;
        const centroY = Math.abs(elemento.offsetHeight / 2 + rect.pantallaY - cliente.alto / 2) < 25;
        return centroX && centroY;
      }
      return false;
    },

    esPantallaCompletaTotal(elemento) {
      const cliente = this.obtenerCliente();
      const rect = this.obtenerRect(elemento);

      return Math.abs(cliente.ancho - elemento.offsetWidth) < 25 &&
             rect.pantallaX < 25 &&
             Math.abs(cliente.alto - elemento.offsetHeight) < 25 &&
             rect.pantallaY < 15;
    },

    obtenerScroll() {
      return {
        izquierda: document.documentElement.scrollLeft || document.body.scrollLeft,
        arriba: document.documentElement.scrollTop || document.body.scrollTop,
      };
    },

    obtenerCliente() {
      const esCompatible = document.compatMode === "CSS1Compat";
      return {
        ancho: esCompatible ? document.documentElement.clientWidth : document.body.clientWidth,
        alto: esCompatible ? document.documentElement.clientHeight : document.body.clientHeight,
      };
    },

    agregarEstilo(css) {
      const estilo = document.createElement("style");
      estilo.type = "text/css";
      estilo.textContent = css;
      document.head.appendChild(estilo);
      return estilo;
    },

    coincideRegla(cadena, regla) {
      const patron = new RegExp("^" + regla.split("*").join(".*") + "$");
      return patron.test(cadena);
    },

    crearBoton(id, texto) {
      const boton = document.createElement("div");
      boton.id = id;
      boton.className = "boton-video-maximizado";
      boton.textContent = texto;
      document.body.appendChild(boton);
      return boton;
    },

    async mostrarConsejo(mensaje) {
      if (document.getElementById("consejoVideo")) return;

      const consejo = document.createElement("div");
      consejo.id = "consejoVideo";
      consejo.textContent = mensaje;
      consejo.style.cssText = `
        position: fixed;
        bottom: 100px;
        right: -400px;
        background: #27a9d8;
        color: white;
        padding: 12px 20px;
        border-radius: 6px;
        font: 14px "Segoe UI", Arial, sans-serif;
        z-index: 2147483647;
        transition: right 0.5s ease;
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        max-width: 300px;
      `;

      document.body.appendChild(consejo);

      // Animación de entrada
      setTimeout(() => consejo.style.right = "25px", 100);

      // Animación de salida
      setTimeout(() => consejo.style.right = "-400px", 3500);

      // Eliminar elemento
      setTimeout(() => {
        if (consejo.parentNode) {
          document.body.removeChild(consejo);
        }
      }, 4000);
    },

    estaEnViewport(elemento) {
      const rect = elemento.getBoundingClientRect();
      return rect.top >= 0 &&
             rect.left >= 0 &&
             rect.bottom <= window.innerHeight &&
             rect.right <= window.innerWidth;
    },

    esVideoValido(video) {
      return video.offsetWidth > 320 &&
             video.offsetHeight > 180 &&
             video.duration > 0;
    }
  };

  // Configuración de botones
  const configurarBotones = {
    inicializar() {
      if (!document.getElementById("botonControlReproductor")) {
        inicializar();
      }

      if (estado.esIframe && utilidades.esMedioPantallaCompleta(estado.reproductor)) {
        window.parent.postMessage("videoIframe", "*");
        return;
      }

      this.mostrar();
    },

mostrar() {
  // Cancelar ocultamiento si el mouse vuelve
  manejadores.cancelarOcultamiento();

  // Remover listeners anteriores para evitar duplicados
  estado.reproductor.removeEventListener("mouseleave", manejadores.salirReproductor, false);
  estado.reproductor.removeEventListener("mouseenter", manejadores.cancelarOcultamiento, false);

  // Agregar nuevos listeners
  estado.reproductor.addEventListener("mouseleave", manejadores.salirReproductor, false);
  estado.reproductor.addEventListener("mouseenter", manejadores.cancelarOcultamiento, false);

  if (!estado.esPantallaCompleta) {
    document.removeEventListener("scroll", manejadores.arreglarScroll, false);
    document.addEventListener("scroll", manejadores.arreglarScroll, false);
  }

  estado.botonControl.style.display = "block";
  estado.botonControl.style.visibility = "visible";

  if (document.pictureInPictureEnabled &&
      estado.reproductor.nodeName !== "OBJECT" &&
      estado.reproductor.nodeName !== "EMBED") {
    estado.botonPip.style.display = "block";
    estado.botonPip.style.visibility = "visible";
  }

  this.posicionar();

  // Iniciar timer de ocultamiento automático después de mostrar
  manejadores.iniciarTemporizadorOcultamiento();
},

posicionar() {
  const rectReproductor = utilidades.obtenerRect(estado.reproductor);

  // Calcular posición relativa al reproductor
  const anchoReproductor = estado.reproductor.offsetWidth;
  const altoReproductor = estado.reproductor.offsetHeight;

  // Posición vertical: 20px desde arriba del reproductor
  const arribaY = rectReproductor.pantallaY + 20;

  // Botón maximizar - esquina superior derecha del reproductor
  estado.botonControl.style.opacity = "0.8";
  estado.botonControl.style.top = `${arribaY}px`;
  estado.botonControl.style.left = `${rectReproductor.pantallaX + anchoReproductor - 150}px`; // 130px desde el borde derecho del video
  estado.botonControl.style.right = "auto"; // Resetear right

  // Botón imagen en imagen - a la izquierda del botón maximizar
  if (estado.botonPip.style.display === "block") {
    estado.botonPip.style.opacity = "0.8";
    estado.botonPip.style.top = `${arribaY}px`;
    estado.botonPip.style.left = `${rectReproductor.pantallaX + anchoReproductor - 215}px`; // 240px desde el borde derecho del video
    estado.botonPip.style.right = "auto"; // Resetear right
  }
}
  };

  // Manejadores de eventos
  const manejadores = {
    obtenerReproductor(evento) {
      if (estado.esPantallaCompleta) return;

      estado.elementoSobreRaton = evento.target;
      const hostname = document.location.hostname;
      let reproductores = [];

      // Buscar reproductores específicos del sitio
      for (const sitio in reglasHtml5) {
        if (utilidades.coincideRegla(hostname, sitio)) {
          for (const regla of reglasHtml5[sitio]) {
            const elementos = document.querySelectorAll(regla);
            reproductores.push(...elementos);
          }
          break;
        }
      }

      // Buscar reproductores genéricos si no se encontraron específicos
      if (reproductores.length === 0) {
        for (const regla of reglasReproductorGeneral) {
          const elementos = document.querySelectorAll(regla);
          reproductores.push(...elementos);
        }
      }

      // Búsqueda automática de videos
      if (reproductores.length === 0 && evento.target.nodeName !== "VIDEO") {
        const videos = document.querySelectorAll("video");
        for (const video of videos) {
          if (this.estaVideoSobreRaton(evento, video) && utilidades.esVideoValido(video)) {
            reproductores = [this.verificacionAutomatica(video)];
            estado.conteoVerificacionAuto = 1;
            break;
          }
        }
      }

      // Verificar si el evento ocurrió dentro de algún reproductor
      if (reproductores.length > 0) {
        const ruta = evento.composedPath?.() || evento.path || [];
        for (const reproductor of reproductores) {
          if (ruta.includes(reproductor)) {
            estado.reproductor = reproductor;
            configurarBotones.inicializar();
            return;
          }
        }
      }

      // Manejo directo de elementos de video
      this.manejarElementoDirecto(evento);
    },

    estaVideoSobreRaton(evento, video) {
      const rect = video.getBoundingClientRect();
      return evento.clientX >= rect.x - 5 &&
             evento.clientX <= rect.x + rect.width + 5 &&
             evento.clientY >= rect.y - 5 &&
             evento.clientY <= rect.y + rect.height + 5;
    },

    manejarElementoDirecto(evento) {
      const elemento = evento.target;
      switch (elemento.nodeName) {
        case "VIDEO":
        case "OBJECT":
        case "EMBED":
          if (utilidades.esVideoValido(elemento)) {
            estado.reproductor = elemento;
            configurarBotones.inicializar();
          }
          break;
        default:
          this.salirReproductor();
      }
    },

    verificacionAutomatica(video) {
      let reproductorTemporal = video;
      let elemento = video;

      estado.hijos = [video];

      while ((elemento = elemento.parentNode)) {
        const diferenciaAncho = Math.abs(video.offsetWidth - elemento.offsetWidth);
        const diferenciaAlto = Math.abs(video.offsetHeight - elemento.offsetHeight);

        if (diferenciaAncho < 20 && diferenciaAlto < 20) {
          reproductorTemporal = elemento;
          estado.hijos.push(elemento);
        } else {
          break;
        }
      }

      return reproductorTemporal;
    },

salirReproductor() {
  // Iniciar temporizador de ocultamiento inmediatamente al salir del reproductor
  manejadores.iniciarTemporizadorOcultamiento();
},

// Nueva función para cancelar el ocultamiento cuando el mouse vuelve
cancelarOcultamiento() {
  clearTimeout(estado.timerOcultarBotones);
  estado.timerOcultarBotones = null;
},

// Nueva función para iniciar el temporizador de ocultamiento
iniciarTemporizadorOcultamiento() {
  // Limpiar timer anterior si existe
  clearTimeout(estado.timerOcultarBotones);

  // Agregar delay de 2 segundos antes de ocultar los botones
  estado.timerOcultarBotones = setTimeout(() => {
    if (estado.botonControl && estado.botonControl.style.visibility === "visible") {
      estado.botonControl.style.visibility = "hidden";
      estado.botonControl.style.opacity = "0";

      if (estado.botonPip) {
        estado.botonPip.style.visibility = "hidden";
        estado.botonPip.style.opacity = "0";
      }

      document.removeEventListener("scroll", manejadores.arreglarScroll, false);
    }
  }, 2000); // 2 segundos de delay
},

    arreglarScroll() {
      clearTimeout(estado.timerArregloScroll);
      estado.timerArregloScroll = setTimeout(() => {
        configurarBotones.posicionar();
      }, 50);
    },

    teclaRapida(evento) {
      // ESC para salir de pantalla/ventana completa
      if (evento.keyCode === 27) {
        maximizar.controlarReproductor();
      }
      // F2 para imagen en imagen
      if (evento.keyCode === 113) {
        this.imagenEnImagen();
      }
    },

    async recibirMensaje(evento) {
      const acciones = {
        async imagenEnImagenIframe() {
          utilidades.log("Mensaje: imagenEnImagenIframe");
          if (!document.pictureInPictureElement) {
            try {
              await document.querySelector("video").requestPictureInPicture();
            } catch (error) {
              utilidades.mostrarConsejo(txt.consejo);
            }
          } else {
            await document.exitPictureInPicture();
          }
        },

        videoIframe() {
          utilidades.log("Mensaje: videoIframe");
          if (!estado.esPantallaCompleta) {
            estado.reproductor = estado.elementoSobreRaton;
            configurarBotones.inicializar();
          }
        },

        padreCompleto() {
          utilidades.log("Mensaje: padreCompleto");
          estado.reproductor = estado.elementoSobreRaton;
          if (estado.esIframe) {
            window.parent.postMessage("padreCompleto", "*");
          }
          maximizar.verificarPadre();
          maximizar.pantallaCompleta();
          estado.esPantallaCompleta = true;
        },

        padrePequeno() {
          utilidades.log("Mensaje: padrePequeno");
          if (estado.esIframe) {
            window.parent.postMessage("padrePequeno", "*");
          }
          maximizar.pantallaNormal();
        },

        interiorCompleto() {
          utilidades.log("Mensaje: interiorCompleto");
          if (estado.reproductor?.nodeName === "IFRAME") {
            estado.reproductor.contentWindow.postMessage("interiorCompleto", "*");
          }
          maximizar.verificarPadre();
          maximizar.pantallaCompleta();
        },

        interiorPequeno() {
          utilidades.log("Mensaje: interiorPequeno");
          if (estado.reproductor?.nodeName === "IFRAME") {
            estado.reproductor.contentWindow.postMessage("interiorPequeno", "*");
          }
          maximizar.pantallaNormal();
        }
      };

      const accion = acciones[evento.data];
      if (accion) {
        await accion();
      }
    },

    imagenEnImagen() {
      if (!document.pictureInPictureElement) {
        if (estado.reproductor) {
          if (estado.reproductor.nodeName === "IFRAME") {
            estado.reproductor.contentWindow.postMessage("imagenEnImagenIframe", "*");
          } else {
            const video = estado.reproductor.querySelector("video") ||
                         estado.reproductor.parentNode.querySelector("video");
            if (video) {
              video.requestPictureInPicture().catch(error => {
                utilidades.mostrarConsejo(txt.consejo);
              });
            }
          }
        } else {
          const video = document.querySelector("video");
          if (video) {
            video.requestPictureInPicture().catch(error => {
              utilidades.mostrarConsejo(txt.consejo);
            });
          }
        }
      } else {
        document.exitPictureInPicture();
      }
    }
  };

  // Funciones de maximización
  const maximizar = {
    controlarReproductor() {
      if (!estado.reproductor) return;

      this.verificarPadre();

      if (!estado.esPantallaCompleta) {
        if (estado.esIframe) {
          window.parent.postMessage("padreCompleto", "*");
        }
        if (estado.reproductor.nodeName === "IFRAME") {
          estado.reproductor.contentWindow.postMessage("interiorCompleto", "*");
        }

        this.pantallaCompleta();
        this.manejarVerificacionAuto();
      } else {
        if (estado.esIframe) {
          window.parent.postMessage("padrePequeno", "*");
        }
        if (estado.reproductor.nodeName === "IFRAME") {
          estado.reproductor.contentWindow.postMessage("interiorPequeno", "*");
        }

        this.pantallaNormal();
      }
    },

    manejarVerificacionAuto() {
      if (estado.conteoVerificacionAuto > 0 &&
          !utilidades.esMedioPantallaCompleta(estado.hijos[0])) {

        if (estado.conteoVerificacionAuto > 10) {
          estado.hijos.forEach(elemento => {
            elemento.classList.add("videoMaximizado");
          });
          return;
        }

        const reproductorTemp = manejadores.verificacionAutomatica(estado.hijos[0]);
        estado.conteoVerificacionAuto++;
        this.controlarReproductor();
        estado.reproductor = reproductorTemp;
        this.controlarReproductor();
      } else {
        estado.conteoVerificacionAuto = 0;
      }
    },

    verificarPadre() {
      if (estado.esPantallaCompleta) return;

      estado.padres = [];
      let elemento = estado.reproductor;

      while ((elemento = elemento.parentNode)) {
        if (elemento.nodeName === "BODY") break;
        if (elemento.getAttribute) {
          estado.padres.push(elemento);
        }
      }
    },

    pantallaCompleta() {
      if (estado.esPantallaCompleta) return;

      document.removeEventListener("mouseover", manejadores.obtenerReproductor, false);

      // Guardar estados anteriores
      estado.idHtmlAnterior = document.documentElement.id;
      estado.idBodyAnterior = document.body.id;

      // Mostrar botones de control
      estado.botonIzquierdo.style.display = "block";
      estado.botonDerecho.style.display = "block";
      estado.botonPip.style.display = "none";
      estado.botonControl.style.display = "none";

      this.aplicarClases();
      this.manejarSitiosEspeciales();

      estado.esPantallaCompleta = true;
    },

    aplicarClases() {
      document.documentElement.id = "htmlMaximizado";
      document.body.id = "bodyMaximizado";

      estado.padres.forEach(padre => {
        padre.classList.add("padreMaximizado");
        if (getComputedStyle(padre).position === "fixed") {
          padre.classList.add("absolutoMaximizado");
        }
      });

      estado.reproductor.classList.add("reproductorMaximizado");

      if (estado.reproductor.nodeName === "VIDEO") {
        estado.controlesAnteriores = estado.reproductor.controls;
        estado.reproductor.controls = true;
      }

      // Disparar evento de redimensionado
      window.dispatchEvent(new Event("resize"));
    },

    manejarSitiosEspeciales() {
      const hostname = document.location.hostname;

      // YouTube
      if (hostname.includes("youtube.com")) {
        const reproductor = document.querySelector("#movie_player");
        const botonTamaño = document.querySelector("#movie_player .ytp-size-button");
        const contenedorVideo = document.querySelector(".html5-video-container");
        const barraInferior = document.querySelector(".ytp-chrome-bottom");

        if (reproductor && botonTamaño && contenedorVideo && barraInferior &&
            !document.querySelector("#player-theater-container #movie_player") &&
            contenedorVideo.clientWidth - barraInferior.clientWidth > 30) {
          botonTamaño.click();
          estado.cambioEtapaYoutube = true;
        }
      }

      // Bilibili
      if (hostname.includes("bilibili.com")) {
        const contenedorDerecho = document.querySelector(".right-container");
        const encabezado = document.querySelector("#biliMainHeader");

        if (contenedorDerecho) contenedorDerecho.style.display = "none";
        if (encabezado) encabezado.style.display = "none";
      }

      // Netflix
      if (hostname.includes("netflix.com")) {
        const controles = document.querySelector(".PlayerControlsNeo__all-controls");
        if (controles) controles.style.zIndex = "2147483647";
      }

      // Twitch
      if (hostname.includes("twitch.tv")) {
        const chat = document.querySelector(".chat-shell");
        if (chat) chat.style.display = "none";
      }
    },

    pantallaNormal() {
      // Restaurar IDs
      document.documentElement.id = estado.idHtmlAnterior;
      document.body.id = estado.idBodyAnterior;

      // Remover clases
      estado.padres.forEach(padre => {
        padre.classList.remove("padreMaximizado", "absolutoMaximizado");
      });

      estado.reproductor.classList.remove("reproductorMaximizado");

      // Manejar sitios especiales al salir
      this.restaurarSitiosEspeciales();

      // Restaurar controles de video
      if (estado.reproductor.nodeName === "VIDEO") {
        estado.reproductor.controls = estado.controlesAnteriores;
      }

      // Ocultar botones de control
      estado.botonIzquierdo.style.display = "none";
      estado.botonDerecho.style.display = "none";
      estado.botonControl.style.display = "none";

      // Reactivar detección de mouse
      document.addEventListener("mouseover", manejadores.obtenerReproductor, false);

      // Disparar evento de redimensionado
      window.dispatchEvent(new Event("resize"));

      estado.esPantallaCompleta = false;
    },

    restaurarSitiosEspeciales() {
      const hostname = document.location.hostname;

      // YouTube
      if (hostname.includes("youtube.com") && estado.cambioEtapaYoutube) {
        const reproductor = document.querySelector("#player-theater-container #movie_player");
        const botonTamaño = document.querySelector("#movie_player .ytp-size-button");

        if (reproductor && botonTamaño) {
          botonTamaño.click();
        }
        estado.cambioEtapaYoutube = false;
      }

      // Bilibili
      if (hostname.includes("bilibili.com")) {
        const contenedorDerecho = document.querySelector(".right-container");
        const encabezado = document.querySelector("#biliMainHeader");

        if (contenedorDerecho) contenedorDerecho.style.removeProperty("display");
        if (encabezado) encabezado.style.removeProperty("display");
      }

      // Twitch
      if (hostname.includes("twitch.tv")) {
        const chat = document.querySelector(".chat-shell");
        if (chat) chat.style.removeProperty("display");
      }
    }
  };

  // Función de inicialización
  function inicializar() {
    // Crear botones
    estado.botonControl = utilidades.crearBoton("botonControlReproductor", txt.maximizar);
    estado.botonControl.onclick = () => maximizar.controlarReproductor();

    estado.botonPip = utilidades.crearBoton("botonImagenEnImagen", txt.pip);
    estado.botonPip.onclick = () => manejadores.imagenEnImagen();

    estado.botonIzquierdo = utilidades.crearBoton("botonIzquierdoPantalla", "");
    estado.botonDerecho = utilidades.crearBoton("botonDerechoPantalla", "");

    // Aplicar estilos CSS
    const estilos = `
      /* Estilos para maximización */
      #htmlMaximizado, #bodyMaximizado {
        overflow: hidden !important;
        zoom: 100% !important;
        margin: 0 !important;
        padding: 0 !important;
      }

      #htmlMaximizado #bodyMaximizado .padreMaximizado {
        overflow: visible !important;
        z-index: auto !important;
        transform: none !important;
        -webkit-transform-style: flat !important;
        transition: none !important;
        contain: none !important;
      }

      #htmlMaximizado #bodyMaximizado .absolutoMaximizado {
        position: absolute !important;
      }

      #htmlMaximizado #bodyMaximizado .reproductorMaximizado {
        position: fixed !important;
        top: 0 !important;
        left: 0 !important;
        width: 100vw !important;
        height: 100vh !important;
        max-width: none !important;
        max-height: none !important;
        min-width: 0 !important;
        min-height: 0 !important;
        margin: 0 !important;
        padding: 0 !important;
        z-index: 2147483646 !important;
        border: none !important;
        background-color: #000 !important;
        transform: none !important;
        border-radius: 0 !important;
      }

      #htmlMaximizado #bodyMaximizado .padreMaximizado video {
        object-fit: contain !important;
      }

      #htmlMaximizado #bodyMaximizado .padreMaximizado .videoMaximizado {
        width: 100vw !important;
        height: 100vh !important;
      }

      /* Estilos para botones */
       .boton-video-maximizado {
        position: fixed;
        z-index: 2147483647;
        cursor: pointer;
        user-select: none;
        font: 12px "Segoe UI", Arial, sans-serif;
        transition: all 0.3s ease;
        border: 1px solid #777777 !important;
        border-radius: 9px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.3);
        visibility: hidden;
        opacity: 0;
        display: none;
}

        #botonControlReproductor {
          background: rgba(0, 0, 0, 0.9);
          color: white !important;
          padding: 6px 12px;
          font-weight: 500;
          text-shadow: none;
          min-width: 60px;
          height: 32px;
          line-height: center;
          text-align: center;
          white-space: nowrap;
          box-sizing: border-box;
}

      #botonControlReproductor:hover {
        background: rgba(70, 70, 70, 1);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}

        #botonImagenEnImagen {
          background: rgba(0, 0, 0, 0.9);
          color: white !important;
          padding: 6px 12px;
          font-weight: 500;
          text-shadow: none;
          min-width: 60px;
          height: 32px;
          line-height: center;
          text-align: center;
          white-space: nowrap;
          box-sizing: border-box;
      }

#botonImagenEnImagen:hover {
  background: rgba(70, 70, 70, 1);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
}

      #botonIzquierdoPantalla, #botonDerechoPantalla {
        width: 2px;
        height: 100vh;
        top: 0;
        background: #000;
        display: none;
      }

      #botonIzquierdoPantalla {
        left: 0;
      }

      #botonDerechoPantalla {
        right: 0;
      }

      /* Estilos específicos para sitios */
      #htmlMaximizado #bodyMaximizado .padreMaximizado .bilibili-player-video {
        margin: 0 !important;
      }

      /* Mejoras para diferentes reproductores */
      #htmlMaximizado #bodyMaximizado .reproductorMaximizado iframe {
        width: 100% !important;
        height: 100% !important;
      }

      #htmlMaximizado #bodyMaximizado .reproductorMaximizado .plyr {
        width: 100% !important;
        height: 100% !important;
      }

      #htmlMaximizado #bodyMaximizado .reproductorMaximizado .video-js {
        width: 100% !important;
        height: 100% !important;
      }

      /* Animaciones suaves */
      .reproductorMaximizado {
        animation: expandirReproductor 0.3s ease-out;
      }

      @keyframes expandirReproductor {
        from {
          transform: scale(0.95);
          opacity: 0.8;
        }
        to {
          transform: scale(1);
          opacity: 1;
        }
      }

      /* Responsive design */
      @media (max-width: 768px) {
        #botonControlReproductor, #botonImagenEnImagen {
          font-size: 11px;
          padding: 6px 10px;
          min-width: 60px;
          height: 24px;
        }
      }

      /* Modo oscuro */
      @media (prefers-color-scheme: dark) {
        #botonControlReproductor {
          background: rgba(0, 0, 0, 0.9);
        }

        #botonControlReproductor:hover {
          background: rgba(70, 70, 70, 1);
        }
      }
    `;

    utilidades.agregarEstilo(estilos);

    // Configurar event listeners
    document.addEventListener("mouseover", manejadores.obtenerReproductor, false);
    document.addEventListener("keydown", manejadores.teclaRapida, false);
    window.addEventListener("message", manejadores.recibirMensaje, false);

    // Event listeners adicionales para mejor detección
    document.addEventListener("mouseenter", manejadores.obtenerReproductor, true);
    document.addEventListener("focusin", manejadores.obtenerReproductor, false);

    // Observador de mutaciones para detectar nuevos videos
    const observador = new MutationObserver((mutaciones) => {
      let hayNuevosVideos = false;

      mutaciones.forEach((mutacion) => {
        mutacion.addedNodes.forEach((nodo) => {
          if (nodo.nodeType === Node.ELEMENT_NODE) {
            if (nodo.tagName === 'VIDEO' || nodo.querySelector('video')) {
              hayNuevosVideos = true;
            }
          }
        });
      });

      if (hayNuevosVideos) {
        // Pequeño delay para permitir que el DOM se estabilice
        setTimeout(() => {
          // Reactivar detección si no estamos en pantalla completa
          if (!estado.esPantallaCompleta) {
            document.removeEventListener("mouseover", manejadores.obtenerReproductor, false);
            document.addEventListener("mouseover", manejadores.obtenerReproductor, false);
          }
        }, 500);
      }
    });

    // Iniciar observación
    observador.observe(document.body, {
      childList: true,
      subtree: true
    });

    // Detección automática inicial
    setTimeout(() => {
      detectarVideosAutomaticamente();
    }, 1000);

    utilidades.log(txt.listo);
  }

  // Función para detectar videos automáticamente al cargar la página
  function detectarVideosAutomaticamente() {
    const hostname = document.location.hostname;

    // Sitios conocidos que cargan videos dinámicamente
    const sitiosDinamicos = [
      'youtube.com',
      'netflix.com',
      'primevideo.com',
      'hulu.com',
      'twitch.tv',
      'bilibili.com'
    ];

    if (sitiosDinamicos.some(sitio => hostname.includes(sitio))) {
      // Intentar detectar reproductores después de un delay
      setTimeout(() => {
        const videos = document.querySelectorAll('video');
        videos.forEach(video => {
          if (utilidades.esVideoValido(video) && utilidades.estaEnViewport(video)) {
            // Crear evento sintético para activar la detección
            const eventoSintetico = new MouseEvent('mouseover', {
              bubbles: true,
              cancelable: true,
              clientX: video.getBoundingClientRect().left + 10,
              clientY: video.getBoundingClientRect().top + 10
            });

            video.dispatchEvent(eventoSintetico);
          }
        });
      }, 2000);
    }
  }

  // Función para manejar cambios de página en SPAs
  function manejarNavegacionSPA() {
    let urlAnterior = location.href;

    const verificarCambioURL = () => {
      if (location.href !== urlAnterior) {
        urlAnterior = location.href;

        // Resetear estado si cambiamos de página
        if (estado.esPantallaCompleta) {
          maximizar.pantallaNormal();
        }

        // Detectar nuevos videos después de un delay
        setTimeout(detectarVideosAutomaticamente, 1500);
      }
    };

    // Observar cambios de URL en SPAs
    window.addEventListener('popstate', verificarCambioURL);

    // También observar cambios en el título (común en SPAs)
    const observadorTitulo = new MutationObserver(verificarCambioURL);
    observadorTitulo.observe(document.querySelector('title') || document.head, {
      childList: true,
      subtree: true
    });
  }

  // Función para manejar errores
  function manejarErrores() {
    window.addEventListener('error', (evento) => {
      if (evento.message.includes('Maximizar Video')) {
        utilidades.log(`Error capturado: ${evento.message}`);

        // Intentar recuperación básica
        if (estado.esPantallaCompleta) {
          try {
            maximizar.pantallaNormal();
          } catch (e) {
            utilidades.log('Error en recuperación: ' + e.message);
          }
        }
      }
    });
  }

  // Función para mejorar la accesibilidad
  function mejorarAccesibilidad() {
    // Agregar atributos ARIA a los botones
    if (estado.botonControl) {
      estado.botonControl.setAttribute('role', 'button');
      estado.botonControl.setAttribute('aria-label', txt.maximizar);
      estado.botonControl.setAttribute('tabindex', '0');

      // Soporte para teclado
      estado.botonControl.addEventListener('keydown', (evento) => {
        if (evento.key === 'Enter' || evento.key === ' ') {
          evento.preventDefault();
          maximizar.controlarReproductor();
        }
      });
    }

    if (estado.botonPip) {
      estado.botonPip.setAttribute('role', 'button');
      estado.botonPip.setAttribute('aria-label', txt.pip);
      estado.botonPip.setAttribute('tabindex', '0');

      estado.botonPip.addEventListener('keydown', (evento) => {
        if (evento.key === 'Enter' || evento.key === ' ') {
          evento.preventDefault();
          manejadores.imagenEnImagen();
        }
      });
    }
  }

  // Inicialización principal
  try {
    inicializar();
    manejarNavegacionSPA();
    manejarErrores();

    // Mejorar accesibilidad después de que los botones estén creados
    setTimeout(mejorarAccesibilidad, 100);

  } catch (error) {
    utilidades.log('Error en inicialización: ' + error.message);
  }

})();