YouTube ✨ Enhancer Pro

Themes, cursors, effects, drawing!

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name YouTube ✨ Enhancer Pro
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Themes, cursors, effects, drawing!
// @author Bveery
// @match https://www.youtube.com/*
// @license GPL-3.0-or-later
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @run-at document-idle
// ==/UserScript==
(function () {
  'use strict';

  const cfg = {
    theme: GM_getValue('theme', 'none'),
    rbSpeed: GM_getValue('rbSpeed', 6),
    cursor: GM_getValue('cursor', 'none'),
    cursorEffect: GM_getValue('cursorEffect', 'none'),
    cinema: GM_getValue('cinema', false),
    menuColor: GM_getValue('menuColor', 'default'),
    menuBlur: GM_getValue('menuBlur', false),
    menuTransparent: GM_getValue('menuTransparent', false),
    pauseOnMenu: GM_getValue('pauseOnMenu', false),
    language: GM_getValue('language', 'en'),
    seasonal: GM_getValue('seasonal', 'none'),
    videoSpeed: GM_getValue('videoSpeed', 1),
    videoVolume: GM_getValue('videoVolume', 100),
    rememberPosition: GM_getValue('rememberPosition', false),
    drawMode: GM_getValue('drawMode', false),
    drawColor: GM_getValue('drawColor', '#ff2060'),
    drawSize: GM_getValue('drawSize', 4),
  };

  function save(k, v) { cfg[k] = v; GM_setValue(k, v); }

  const LANG = {
    en: {
      title: '✨ YT Enhancer Pro',
      categories: { youtube: '▶️ YouTube', menu: '▶️ Menu', design: '▶️ Design', cursor: '▶️ Cursor' },
      youtube: {
        speedSection: 'Playback Speed',
        speed: '⚡ Speed',
        volumeSection: 'Volume',
        volume: '▶️ Volume',
        rememberSection: 'Remember Position',
        remember: '▶️ Remember where I stopped',
      },
      menu: {
        colorTitle: 'Menu Color',
        blur: 'Blur Background',
        transparent: 'Glass Effect',
        pauseOnMenu: 'Pause on Menu',
        lang: 'Language',
        langEn: 'English',
        langRu: 'Russian',
      },
      design: {
        rbSection: 'Rainbow',
        rainbow: 'Rainbow',
        speed: 'Speed',
        seasonal: 'Seasonal Theme',
        s_none: 'None',
        s_ny: 'New Year',
        s_hw: 'Halloween',
        cinSection: 'Cinema',
        cinema: 'Cinema Mode',
      },
      cursor: {
        drawSection: 'Drawing Mode',
        drawMode: '▶️ Drawing Mode',
        drawColor: '▶️ Brush Color',
        drawSize: '▶️ Brush Size',
        drawClear: '▶️ Clear Canvas',
        cursorSection: 'Cursor Style',
        none: 'Default',
        heart: '❤️ Heart',
        crosshair: '➕ Crosshair',
        custom: '⭐ Star',
        diamond: '💎 Diamond',
        electro: '⚡ Electro',
        effectSection: 'Cursor Effect',
        fx_none: 'None',
        fx_sparks: '✨ Sparks',
        fx_hearts: '❤️ Hearts',
        fx_snow: '❄️ Snow',
        fx_rainbow: '🌈 Rainbow',
        fx_stars: '⭐ Stars',
      }
    },
    ru: {
      title: '✨ YT Enhancer Pro',
      categories: { youtube: '▶️ YouTube', menu: '▶️ Меню', design: '▶️ Дизайн', cursor: '▶️ Курсор' },
      youtube: {
        speedSection: 'Скорость воспроизведения',
        speed: '⚡ Скорость',
        volumeSection: 'Громкость',
        volume: '▶️ Громкость',
        rememberSection: 'Запомнить позицию',
        remember: '▶️ Запомнить где остановился',
      },
      menu: {
        colorTitle: 'Цвет меню',
        blur: 'Блюр фона',
        transparent: 'Эффект стекла',
        pauseOnMenu: 'Пауза при меню',
        lang: 'Язык',
        langEn: 'English',
        langRu: 'Русский',
      },
      design: {
        rbSection: 'Радуга',
        rainbow: 'Радуга',
        speed: 'Скорость',
        seasonal: 'Сезонная тема',
        s_none: 'Выкл',
        s_ny: 'Новый год',
        s_hw: 'Хеллоуин',
        cinSection: 'Кинотеатр',
        cinema: 'Кинотеатр',
      },
      cursor: {
        drawSection: 'Режим рисования',
        drawMode: '▶️ Режим рисования',
        drawColor: '▶️ Цвет кисти',
        drawSize: '▶️ Размер кисти',
        drawClear: '▶️ Очистить холст',
        cursorSection: 'Стиль курсора',
        none: 'Стандартный',
        heart: '❤️ Сердечко',
        crosshair: '➕ Перекрестие',
        custom: '⭐ Звезда',
        diamond: '💎 Алмаз',
        electro: '⚡ Электро',
        effectSection: 'Эффект курсора',
        fx_none: 'Выкл',
        fx_sparks: '✨ Искры',
        fx_hearts: '❤️ Сердечки',
        fx_snow: '❄️ Снег',
        fx_rainbow: '🌈 Радуга',
        fx_stars: '⭐ Звёзды',
      }
    }
  };

  function t(key) {
    const keys = key.split('.');
    let val = LANG[cfg.language] || LANG.en;
    for (const k of keys) val = val?.[k];
    return val ?? key;
  }

  const MENU_COLORS = {
    default: { bg: 'linear-gradient(160deg,rgba(14,14,26,.95),rgba(19,19,42,.95))', text: '#eef', border: 'rgba(255,255,255,.2)' },
    pink:    { bg: 'linear-gradient(160deg,rgba(26,10,20,.95),rgba(42,16,32,.95))', text: '#ffd6e7', border: 'rgba(255,120,180,.35)' },
    blue:    { bg: 'linear-gradient(160deg,rgba(10,16,26,.95),rgba(16,26,42,.95))', text: '#d6e7ff', border: 'rgba(120,180,255,.35)' },
    green:   { bg: 'linear-gradient(160deg,rgba(10,26,16,.95),rgba(16,42,24,.95))', text: '#d6ffe0', border: 'rgba(120,255,180,.35)' },
    purple:  { bg: 'linear-gradient(160deg,rgba(26,10,31,.95),rgba(42,16,48,.95))', text: '#e7d6ff', border: 'rgba(180,120,255,.35)' },
    orange:  { bg: 'linear-gradient(160deg,rgba(26,18,10,.95),rgba(42,28,16,.95))', text: '#ffe7d6', border: 'rgba(255,180,120,.35)' },
    red:     { bg: 'linear-gradient(160deg,rgba(26,8,8,.95),rgba(42,16,16,.95))',   text: '#ffd6d6', border: 'rgba(255,120,120,.35)' },
    cyan:    { bg: 'linear-gradient(160deg,rgba(10,26,31,.95),rgba(16,42,48,.95))', text: '#d6ffff', border: 'rgba(120,255,255,.35)' },
  };

  const COLOR_CHIPS = {
    default: '#8888ff', pink: '#ff78b4', blue: '#78b4ff', green: '#78ffb4',
    purple: '#b478ff', orange: '#ffb478', red: '#ff7878', cyan: '#78ffff',
  };

  // ══════════════════════════════════════════════════════════════
  // КУРСОРЫ
  // ══════════════════════════════════════════════════════════════
  function getCursorStyle(key) {
    if (key === 'none') return '';
    if (key === 'crosshair') return 'crosshair';

    if (key === 'heart') {
      const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">'
        + '<path d="M16 28s-14-9-14-18a8 8 0 0 1 14-5.3A8 8 0 0 1 30 10c0 9-14 18-14 18z" fill="#ff2060" stroke="#ff80a0" stroke-width="1.5"/>'
        + '</svg>';
      return 'url("data:image/svg+xml,' + encodeURIComponent(svg) + '") 16 28, auto';
    }

    if (key === 'custom') {
      const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">'
        + '<polygon points="16,2 20,12 30,12 22,19 25,30 16,23 7,30 10,19 2,12 12,12" fill="gold" stroke="orange" stroke-width="1"/>'
        + '</svg>';
      return 'url("data:image/svg+xml,' + encodeURIComponent(svg) + '") 16 16, auto';
    }

    if (key === 'diamond') {
      const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="36" viewBox="0 0 32 36">'
        + '<defs><linearGradient id="dg" x1="0" y1="0" x2="1" y2="1">'
        + '<stop offset="0%" stop-color="#a0f0ff" stop-opacity="0.7"/>'
        + '<stop offset="50%" stop-color="#00c8ff" stop-opacity="0.5"/>'
        + '<stop offset="100%" stop-color="#0055aa" stop-opacity="0.7"/>'
        + '</linearGradient></defs>'
        + '<polygon points="16,2 30,12 16,34 2,12" fill="url(#dg)" opacity="0.85"/>'
        + '<polygon points="16,2 30,12 16,34 2,12" fill="none" stroke="#00eeff" stroke-width="1.5" opacity="0.9"/>'
        + '<polygon points="16,2 30,12 16,12" fill="rgba(180,240,255,0.55)"/>'
        + '<polygon points="2,12 16,12 16,34" fill="rgba(0,180,220,0.45)"/>'
        + '<polygon points="30,12 16,12 16,34" fill="rgba(0,120,180,0.45)"/>'
        + '<line x1="2" y1="12" x2="30" y2="12" stroke="#00eeff" stroke-width="1" opacity="0.7"/>'
        + '<line x1="16" y1="2" x2="2" y2="12" stroke="#aaf8ff" stroke-width="0.8" opacity="0.6"/>'
        + '<line x1="16" y1="2" x2="30" y2="12" stroke="#aaf8ff" stroke-width="0.8" opacity="0.6"/>'
        + '<circle cx="16" cy="10" r="2.5" fill="white" opacity="0.9"/>'
        + '</svg>';
      return 'url("data:image/svg+xml,' + encodeURIComponent(svg) + '") 16 2, auto';
    }

    if (key === 'electro') {
      const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">'
        + '<defs>'
        + '<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">'
        + '<feGaussianBlur stdDeviation="1.5" result="blur"/>'
        + '<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>'
        + '</filter>'
        + '<linearGradient id="eg" x1="0" y1="0" x2="0" y2="1">'
        + '<stop offset="0%" stop-color="#ffffff" stop-opacity="0.9"/>'
        + '<stop offset="100%" stop-color="#ff9900" stop-opacity="0.3"/>'
        + '</linearGradient>'
        + '</defs>'
        + '<g filter="url(#glow)">'
        + '<polygon points="19,2 10,16 16,16 13,30 23,14 17,14" fill="#ffe44d" stroke="#ffffff" stroke-width="0.5" opacity="0.95"/>'
        + '<polygon points="19,2 10,16 16,16 13,30 23,14 17,14" fill="url(#eg)" opacity="0.6"/>'
        + '</g>'
        + '</svg>';
      return 'url("data:image/svg+xml,' + encodeURIComponent(svg) + '") 16 2, auto';
    }

    return '';
  }

  const CURSOR_KEYS = ['none', 'heart', 'crosshair', 'custom', 'diamond', 'electro'];

  // ══════════════════════════════════════════════════════════════
  // РЕЖИМ РИСОВАНИЯ
  // ══════════════════════════════════════════════════════════════
  let drawCanvas = null;
  let drawCtx = null;
  let isDrawing = false;
  let lastX = 0;
  let lastY = 0;

  const DRAW_COLORS = [
    { color: '#ff2060' }, { color: '#ff8c00' },
    { color: '#ffdd00' }, { color: '#00dd44' },
    { color: '#0088ff' }, { color: '#8855ff' },
    { color: '#ffffff' }, { color: '#000000' },
  ];

  function ensureDrawCanvas() {
    if (drawCanvas) return;
    drawCanvas = document.createElement('canvas');
    drawCanvas.id = 'yt-draw-canvas';
    drawCanvas.width = window.innerWidth;
    drawCanvas.height = window.innerHeight;
    drawCanvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483644;pointer-events:none;';
    document.documentElement.appendChild(drawCanvas);
    drawCtx = drawCanvas.getContext('2d');
    window.addEventListener('resize', () => {
      const img = drawCtx.getImageData(0, 0, drawCanvas.width, drawCanvas.height);
      drawCanvas.width = window.innerWidth;
      drawCanvas.height = window.innerHeight;
      drawCtx.putImageData(img, 0, 0);
    });
  }

  function startDrawMode() {
    ensureDrawCanvas();
    drawCanvas.style.pointerEvents = 'all';
    drawCanvas.style.cursor = 'crosshair';
    drawCanvas.addEventListener('mousedown', onDrawStart);
    drawCanvas.addEventListener('mousemove', onDrawMove);
    drawCanvas.addEventListener('mouseup', onDrawEnd);
    drawCanvas.addEventListener('mouseleave', onDrawEnd);
    showToast('✏️ Drawing ON — hold LMB to draw!');
  }

  function stopDrawMode() {
    if (!drawCanvas) return;
    drawCanvas.style.pointerEvents = 'none';
    drawCanvas.removeEventListener('mousedown', onDrawStart);
    drawCanvas.removeEventListener('mousemove', onDrawMove);
    drawCanvas.removeEventListener('mouseup', onDrawEnd);
    drawCanvas.removeEventListener('mouseleave', onDrawEnd);
    isDrawing = false;
    showToast('⏹️ Drawing OFF');
  }

  function clearDrawCanvas() {
    if (!drawCtx || !drawCanvas) return;
    drawCtx.clearRect(0, 0, drawCanvas.width, drawCanvas.height);
    showToast('🧹 Canvas cleared!');
  }

  function onDrawStart(e) {
    isDrawing = true;
    lastX = e.clientX; lastY = e.clientY;
    drawCtx.beginPath();
    drawCtx.arc(lastX, lastY, cfg.drawSize / 2, 0, Math.PI * 2);
    drawCtx.fillStyle = cfg.drawColor;
    drawCtx.shadowBlur = cfg.drawSize;
    drawCtx.shadowColor = cfg.drawColor;
    drawCtx.fill();
  }

  function onDrawMove(e) {
    if (!isDrawing) return;
    drawCtx.beginPath();
    drawCtx.moveTo(lastX, lastY);
    drawCtx.lineTo(e.clientX, e.clientY);
    drawCtx.strokeStyle = cfg.drawColor;
    drawCtx.lineWidth = cfg.drawSize;
    drawCtx.lineCap = 'round';
    drawCtx.lineJoin = 'round';
    drawCtx.shadowBlur = cfg.drawSize * 0.8;
    drawCtx.shadowColor = cfg.drawColor;
    drawCtx.stroke();
    lastX = e.clientX; lastY = e.clientY;
  }

  function onDrawEnd() {
    isDrawing = false;
    if (drawCtx) drawCtx.shadowBlur = 0;
  }

  function applyDrawMode() {
    const on = cfg.drawMode === true || cfg.drawMode === 'true';
    if (on) startDrawMode(); else stopDrawMode();
  }

  // ══════════════════════════════════════════════════════════════
  // ЭФФЕКТЫ КУРСОРА
  // ══════════════════════════════════════════════════════════════
  let fxCanvas = null, fxCtx = null, fxRAF = null;
  let fxParticles = [], fxMouseX = 0, fxMouseY = 0;
  let fxMouseMoved = false, fxMoveHandler = null;
  let fxActive = false, fxType = 'none';

  function ensureFxCanvas() {
    if (fxCanvas) return;
    fxCanvas = document.createElement('canvas');
    fxCanvas.id = 'yt-cursor-fx';
    fxCanvas.width = window.innerWidth;
    fxCanvas.height = window.innerHeight;
    fxCanvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:2147483643;';
    document.documentElement.appendChild(fxCanvas);
    fxCtx = fxCanvas.getContext('2d');
    window.addEventListener('resize', () => {
      fxCanvas.width = window.innerWidth;
      fxCanvas.height = window.innerHeight;
    });
  }

  function spawnFxParticles(x, y) {
    switch (fxType) {
      case 'sparks': {
        const colors = ['#ff2060','#ff8c00','#ffdd00','#ff4488','#ff6600','#ffffff'];
        for (let i = 0; i < 3 + Math.floor(Math.random()*4); i++) {
          const a = Math.random()*Math.PI*2, s = 2+Math.random()*4;
          fxParticles.push({ x, y, vx:Math.cos(a)*s, vy:Math.sin(a)*s-2, life:1,
            decay:0.035+Math.random()*0.035, size:2+Math.random()*3,
            color:colors[Math.floor(Math.random()*colors.length)], type:'spark' });
        }
        break;
      }
      case 'hearts':
        if (Math.random()>0.35) break;
        fxParticles.push({ x:x+(Math.random()-0.5)*24, y, vx:(Math.random()-0.5)*1.2,
          vy:-(1.5+Math.random()*2.5), life:1, decay:0.018+Math.random()*0.018,
          size:12+Math.random()*14, type:'heart' });
        break;
      case 'snow':
        if (Math.random()>0.3) break;
        fxParticles.push({ x:x+(Math.random()-0.5)*20, y, vx:(Math.random()-0.5)*0.6,
          vy:0.8+Math.random()*1.5, life:1, decay:0.012+Math.random()*0.012,
          size:10+Math.random()*12, type:'snow' });
        break;
      case 'rainbow': {
        for (let i = 0; i < 2+Math.floor(Math.random()*3); i++) {
          const hue=Math.random()*360, a=Math.random()*Math.PI*2, s=0.8+Math.random()*1.5;
          fxParticles.push({ x:x+(Math.random()-0.5)*8, y:y+(Math.random()-0.5)*8,
            vx:Math.cos(a)*s, vy:Math.sin(a)*s-0.5, life:1, decay:0.012+Math.random()*0.012,
            size:6+Math.random()*8, color:'hsl('+hue+',100%,65%)', type:'dot' });
        }
        break;
      }
      case 'stars':
        if (Math.random()>0.4) break;
        fxParticles.push({ x:x+(Math.random()-0.5)*24, y:y+(Math.random()-0.5)*24,
          vx:(Math.random()-0.5)*1, vy:-(0.5+Math.random()*1.5), life:1,
          decay:0.015+Math.random()*0.015, size:12+Math.random()*16, type:'star' });
        break;
    }
  }

  function renderParticle(p) {
    fxCtx.save();
    fxCtx.globalAlpha = Math.max(0, p.life);
    switch (p.type) {
      case 'spark':
        fxCtx.shadowBlur=12; fxCtx.shadowColor=p.color; fxCtx.strokeStyle=p.color;
        fxCtx.lineWidth=p.size*p.life; fxCtx.lineCap='round';
        fxCtx.beginPath(); fxCtx.moveTo(p.x,p.y); fxCtx.lineTo(p.x-p.vx*3,p.y-p.vy*3); fxCtx.stroke();
        fxCtx.fillStyle='#fff'; fxCtx.shadowBlur=6;
        fxCtx.beginPath(); fxCtx.arc(p.x,p.y,p.size*p.life*0.6,0,Math.PI*2); fxCtx.fill();
        break;
      case 'dot': {
        const g = fxCtx.createRadialGradient(p.x,p.y,0,p.x,p.y,p.size);
        g.addColorStop(0,p.color); g.addColorStop(1,'transparent');
        fxCtx.fillStyle=g; fxCtx.beginPath(); fxCtx.arc(p.x,p.y,p.size,0,Math.PI*2); fxCtx.fill();
        break;
      }
      default:
        fxCtx.font=p.size+'px serif'; fxCtx.textAlign='center'; fxCtx.textBaseline='middle';
        fxCtx.fillText(
          p.type==='heart' ? '❤️' : p.type==='snow' ? '❄️' : '⭐',
          p.x, p.y
        );
    }
    fxCtx.restore();
  }

  function fxLoop() {
    fxRAF = requestAnimationFrame(fxLoop);
    fxCtx.clearRect(0,0,fxCanvas.width,fxCanvas.height);
    if (fxActive && fxMouseMoved && fxType!=='none') {
      spawnFxParticles(fxMouseX, fxMouseY);
      fxMouseMoved = false;
    }
    const alive = [];
    for (const p of fxParticles) {
      p.x+=p.vx; p.y+=p.vy; p.vy+=0.06; p.life-=p.decay;
      if (p.life>0) { renderParticle(p); alive.push(p); }
    }
    fxParticles = alive;
  }

  function stopCursorEffect() {
    fxActive=false; fxType='none';
    if (fxMoveHandler) { document.removeEventListener('mousemove',fxMoveHandler); fxMoveHandler=null; }
    fxParticles=[];
    if (fxCtx&&fxCanvas) fxCtx.clearRect(0,0,fxCanvas.width,fxCanvas.height);
  }

  function startCursorEffect(type) {
    stopCursorEffect();
    if (type==='none') return;
    ensureFxCanvas();
    fxType=type; fxActive=true;
    if (!fxRAF) fxLoop();
    fxMoveHandler = e => { fxMouseX=e.clientX; fxMouseY=e.clientY; fxMouseMoved=true; };
    document.addEventListener('mousemove',fxMoveHandler);
  }

  // ══════════════════════════════════════════════════════════════
  // ЗАПОМНИТЬ ПОЗИЦИЮ
  // ══════════════════════════════════════════════════════════════
  const POSITIONS_KEY = 'yt_pro_positions';
  function loadPositions() { try { return JSON.parse(GM_getValue(POSITIONS_KEY,'{}')); } catch(e) { return {}; } }
  function savePosition(id,t) { const p=loadPositions(); p[id]=t; const k=Object.keys(p); if(k.length>200) delete p[k[0]]; GM_setValue(POSITIONS_KEY,JSON.stringify(p)); }
  function getSavedPosition(id) { return loadPositions()[id]||0; }
  let positionRestored=false;

  function startPositionWatcher() {
    setInterval(()=>{
      if (!(cfg.rememberPosition===true||cfg.rememberPosition==='true')) return;
      const id=new URLSearchParams(window.location.search).get('v');
      const v=document.querySelector('video');
      if (id&&v&&!v.paused&&v.currentTime>3) savePosition(id,v.currentTime);
    },1000);
    let lastUrl=location.href;
    new MutationObserver(()=>{
      if (location.href!==lastUrl) { lastUrl=location.href; positionRestored=false; setTimeout(restorePosition,2000); }
    }).observe(document.documentElement,{childList:true,subtree:true});
    setTimeout(restorePosition,2500);
  }

  function restorePosition() {
    if (!(cfg.rememberPosition===true||cfg.rememberPosition==='true')) return;
    if (positionRestored) return;
    const id=new URLSearchParams(window.location.search).get('v');
    if (!id) return;
    const saved=getSavedPosition(id);
    if (saved<3) return;
    const v=document.querySelector('video');
    if (!v) { setTimeout(restorePosition,1000); return; }
    if (v.duration&&saved<v.duration-10) { v.currentTime=saved; positionRestored=true; showToast('🕒 Resumed from '+formatTime(saved)); }
  }

  function formatTime(sec) {
    sec=Math.floor(sec);
    const h=Math.floor(sec/3600), m=Math.floor((sec%3600)/60), s=sec%60;
    if (h>0) return h+':'+String(m).padStart(2,'0')+':'+String(s).padStart(2,'0');
    return m+':'+String(s).padStart(2,'0');
  }

  // ══════════════════════════════════════════════════════════════
  // TOAST
  // ══════════════════════════════════════════════════════════════
  function showToast(msg) {
    let toast=document.getElementById('yt-pro-toast');
    if (!toast) { toast=document.createElement('div'); toast.id='yt-pro-toast'; document.documentElement.appendChild(toast); }
    toast.textContent=msg;
    toast.style.opacity='1';
    toast.style.transform='translateX(-50%) translateY(0)';
    clearTimeout(toast._timer);
    toast._timer=setTimeout(()=>{ toast.style.opacity='0'; toast.style.transform='translateX(-50%) translateY(20px)'; },3000);
  }

  // ══════════════════════════════════════════════════════════════
  // ВИДЕО
  // ══════════════════════════════════════════════════════════════
  let audioCtx=null, gainNode=null, mediaSource=null;

  function setupAudioBoost(v) {
    if (!v||v._ytProBoosted) return;
    try {
      if (!audioCtx) audioCtx=new (window.AudioContext||window.webkitAudioContext)();
      if (gainNode) { try{gainNode.disconnect();}catch(e){} }
      if (mediaSource) { try{mediaSource.disconnect();}catch(e){} }
      mediaSource=audioCtx.createMediaElementSource(v);
      gainNode=audioCtx.createGain();
      mediaSource.connect(gainNode); gainNode.connect(audioCtx.destination);
      v._ytProBoosted=true; applyVideoVolume(cfg.videoVolume);
    } catch(e) { console.warn('[YT Pro]',e); }
  }

  function applyVideoSpeed(val) { const v=document.querySelector('video'); if(v) v.playbackRate=parseFloat(val); }

  function applyVideoVolume(val) {
    const pct=parseFloat(val), v=document.querySelector('video');
    if (!v) return;
    if (pct<=100) { v.volume=pct/100; if(gainNode) gainNode.gain.value=1; }
    else { if(!v._ytProBoosted) setupAudioBoost(v); v.volume=1; if(gainNode) gainNode.gain.value=pct/100; }
  }

  function watchVideo() {
    new MutationObserver(()=>{
      const v=document.querySelector('video');
      if (v) { if(!v._ytProBoosted&&cfg.videoVolume>100) setupAudioBoost(v); v.playbackRate=parseFloat(cfg.videoSpeed); applyVideoVolume(cfg.videoVolume); }
    }).observe(document.body,{childList:true,subtree:true});
    document.addEventListener('loadeddata',()=>{
      const v=document.querySelector('video');
      if (v) { if(!v._ytProBoosted) setupAudioBoost(v); applyVideoSpeed(cfg.videoSpeed); applyVideoVolume(cfg.videoVolume); }
    },true);
  }

  let wePaused=false;
  function pauseVideo() { const v=document.querySelector('video'); if(v&&!v.paused){v.pause();return true;} return false; }
  function resumeVideo() { const v=document.querySelector('video'); if(v&&v.paused) v.play(); }

  // ══════════════════════════════════════════════════════════════
  // СЕЗОННЫЕ ТЕМЫ
  // ══════════════════════════════════════════════════════════════
  const PARTICLE_CONFIG = {
    ny:{ count:60, emojis:['❄️','❅','❆','⛄','🌨️'], sizes:[14,18,22,26], speed:[6,14],
      css:`html.yt-ny ytd-app,html.yt-ny #content{background:linear-gradient(180deg,#0a1628 0%,#0d2044 40%,#0a1628 100%)!important}
html.yt-ny #masthead{background:linear-gradient(90deg,#0d2a5e,#1a4a8a,#0d2a5e)!important;border-bottom:2px solid #4af!important;box-shadow:0 2px 20px rgba(100,180,255,0.4)!important}
html.yt-ny ytd-guide-renderer,html.yt-ny #guide-inner-content{background:linear-gradient(180deg,#0a1e40,#0d2855)!important}
html.yt-ny yt-formatted-string,html.yt-ny #video-title,html.yt-ny .title{color:#c8e8ff!important}
html.yt-ny ytd-thumbnail{border-radius:10px!important;box-shadow:0 0 12px rgba(150,210,255,0.25)!important}` },
    hw:{ count:40, emojis:['🎃','👻','🕷️','🦇','💀'], sizes:[18,22,28,34], speed:[5,12],
      css:`html.yt-hw ytd-app,html.yt-hw #content{background:linear-gradient(180deg,#0d0500 0%,#1a0a00 40%,#0d0500 100%)!important}
html.yt-hw #masthead{background:linear-gradient(90deg,#1a0a00,#2d1200,#1a0a00)!important;border-bottom:2px solid #c05000!important;box-shadow:0 2px 20px rgba(200,80,0,0.5)!important}
html.yt-hw ytd-guide-renderer,html.yt-hw #guide-inner-content{background:linear-gradient(180deg,#120600,#1e0e00)!important}
html.yt-hw yt-formatted-string,html.yt-hw #video-title,html.yt-hw .title{color:#ffb060!important}
html.yt-hw ytd-thumbnail{border-radius:10px!important;box-shadow:0 0 14px rgba(200,80,0,0.3)!important}` }
  };

  let particleContainer=null, particleInterval=null;
  function clearParticles() { particleContainer?.remove(); particleContainer=null; if(particleInterval){clearInterval(particleInterval);particleInterval=null;} }

  function spawnParticle(pcfg) {
    if (!particleContainer) return;
    const span=document.createElement('span');
    const emoji=pcfg.emojis[Math.floor(Math.random()*pcfg.emojis.length)];
    const size=pcfg.sizes[Math.floor(Math.random()*pcfg.sizes.length)];
    const left=Math.random()*100, dur=pcfg.speed[0]+Math.random()*(pcfg.speed[1]-pcfg.speed[0]);
    const delay=Math.random()*-dur, wobbleX=(Math.random()-0.5)*80;
    span.textContent=emoji;
    span.style.cssText=['position:fixed','top:-60px','left:'+left+'vw','font-size:'+size+'px',
      'opacity:'+(0.6+Math.random()*0.4),'pointer-events:none','z-index:2147483630','user-select:none',
      'animation:yt-particle-fall '+dur+'s linear '+delay+'s infinite','--wobble:'+wobbleX+'px'].join(';');
    particleContainer.appendChild(span);
    if (particleContainer.children.length>pcfg.count+10) particleContainer.children[0].remove();
  }

  function startParticles(type) {
    clearParticles(); if(type==='none') return;
    const pcfg=PARTICLE_CONFIG[type]; if(!pcfg) return;
    particleContainer=document.createElement('div');
    particleContainer.id='yt-particles';
    particleContainer.style.cssText='position:fixed;inset:0;pointer-events:none;z-index:2147483630;overflow:hidden';
    document.documentElement.appendChild(particleContainer);
    for (let i=0;i<pcfg.count;i++) setTimeout(()=>spawnParticle(pcfg),i*150);
    particleInterval=setInterval(()=>spawnParticle(pcfg),600);
  }

  let seasonStyleEl=null;
  function setSeasonStyle() {
    if (!seasonStyleEl) { seasonStyleEl=document.createElement('style'); seasonStyleEl.id='yt-season-style'; document.head.appendChild(seasonStyleEl); }
    document.documentElement.classList.remove('yt-ny','yt-hw');
    if (cfg.seasonal==='ny') {
      seasonStyleEl.textContent=PARTICLE_CONFIG.ny.css+'@keyframes yt-particle-fall{0%{transform:translateY(0) translateX(0) rotate(0deg);opacity:1}50%{transform:translateY(50vh) translateX(var(--wobble)) rotate(180deg)}100%{transform:translateY(110vh) translateX(0) rotate(360deg);opacity:0.3}}';
      document.documentElement.classList.add('yt-ny'); startParticles('ny');
    } else if (cfg.seasonal==='hw') {
      seasonStyleEl.textContent=PARTICLE_CONFIG.hw.css+'@keyframes yt-particle-fall{0%{transform:translateY(0) translateX(0) rotate(-10deg);opacity:1}25%{transform:translateY(25vh) translateX(var(--wobble)) rotate(10deg)}50%{transform:translateY(50vh) translateX(0) rotate(-15deg)}75%{transform:translateY(75vh) translateX(calc(var(--wobble)*-0.5)) rotate(8deg)}100%{transform:translateY(110vh) translateX(0) rotate(-5deg);opacity:0.2}}';
      document.documentElement.classList.add('yt-hw'); startParticles('hw');
    } else { seasonStyleEl.textContent=''; clearParticles(); }
  }

  let rbStyleEl=null;
  function setRainbowStyle() {
    if (!rbStyleEl) { rbStyleEl=document.createElement('style'); rbStyleEl.id='yt-rb-style'; document.head.appendChild(rbStyleEl); }
    if (cfg.theme!=='rainbow') { rbStyleEl.textContent=''; return; }
    const spd=Number(cfg.rbSpeed)+'s';
    rbStyleEl.textContent=[
      '@keyframes yt-rb-hue{0%{filter:hue-rotate(0deg)}100%{filter:hue-rotate(360deg)}}',
      '@keyframes yt-rb-pos{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}',
      'html.yt-rb-on{animation:yt-rb-hue '+spd+' linear infinite!important}',
      '#yt-rb-overlay{position:fixed!important;inset:0!important;z-index:2147483640!important;pointer-events:none!important;background:linear-gradient(135deg,rgba(255,0,0,.15),rgba(255,120,0,.15),rgba(255,255,0,.15),rgba(0,255,80,.15),rgba(0,200,255,.15),rgba(80,0,255,.15),rgba(255,0,200,.15),rgba(255,0,0,.15))!important;background-size:400% 400%!important;animation:yt-rb-pos '+spd+' ease infinite!important;mix-blend-mode:color!important;}'
    ].join('');
  }

  function syncRainbowOverlay() {
    let ov=document.getElementById('yt-rb-overlay');
    if (cfg.theme==='rainbow') {
      if(!ov){ov=document.createElement('div');ov.id='yt-rb-overlay';document.documentElement.appendChild(ov);}
      document.documentElement.classList.add('yt-rb-on');
    } else { ov?.remove(); document.documentElement.classList.remove('yt-rb-on'); }
  }

  // ══════════════════════════════════════════════════════════════
  // СТИЛИ
  // ══════════════════════════════════════════════════════════════
  GM_addStyle([
    "@import url('https://fonts.googleapis.com/css2?family=Exo+2:wght@400;600;900&display=swap');",
    '#yt-proroot{position:fixed!important;top:0!important;left:0!important;width:0!important;height:0!important;overflow:visible!important;z-index:2147483647!important;pointer-events:none!important;transform:none!important;}',
    '#yt-pro-menu{position:fixed!important;border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,0.9);display:flex;visibility:hidden;opacity:0;pointer-events:none;flex-direction:row;overflow:hidden;font-family:"Exo 2",sans-serif;color:#eef;z-index:2147483647;transition:opacity .35s ease,visibility 0s linear .35s;border:1px solid rgba(255,255,255,0.15);width:650px;height:530px;}',
    '#yt-pro-menu.active{visibility:visible!important;opacity:1!important;pointer-events:all!important;transition:opacity .35s ease,visibility 0s linear 0s;}',
    '#yt-pro-menu.dragging{transition:none!important;user-select:none!important;}',
    '.yt-sidebar{width:180px;background:rgba(0,0,0,0.3);border-right:1px solid rgba(255,255,255,0.08);padding:20px 10px;display:flex;flex-direction:column;gap:10px;flex-shrink:0;}',
    '.yt-sidebar-credit{margin-top:auto;padding-top:10px;font-size:10px;color:rgba(255,255,255,0.2);text-align:center;line-height:1.5;user-select:none;letter-spacing:0.3px;}',
    '.yt-nav-btn{padding:12px;border-radius:10px;cursor:pointer;font-weight:600;color:#888;transition:all .25s;display:flex;align-items:center;gap:10px;user-select:none;}',
    '.yt-nav-btn:hover{color:#ccc;background:rgba(255,255,255,0.05);}',
    '.yt-nav-btn.sel{background:linear-gradient(90deg,rgba(255,32,96,0.2),rgba(136,85,255,0.2));color:#fff;border-left:3px solid #ff2060;}',
    '.yt-content{flex:1;padding:20px;overflow-y:auto;}',
    '.yt-content::-webkit-scrollbar{width:4px;}',
    '.yt-content::-webkit-scrollbar-track{background:transparent;}',
    '.yt-content::-webkit-scrollbar-thumb{background:rgba(136,85,255,0.5);border-radius:2px;}',
    '.yt-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;border-bottom:1px solid rgba(255,255,255,0.1);padding-bottom:10px;cursor:grab;user-select:none;}',
    '.yt-header:active{cursor:grabbing;}',
    '.yt-title{font-size:20px;font-weight:900;background:linear-gradient(90deg,#ff2060,#8855ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent;pointer-events:none;}',
    '.yt-close{cursor:pointer!important;font-size:24px;line-height:1;opacity:0.7;transition:opacity .2s;pointer-events:all!important;}',
    '.yt-close:hover{opacity:1;}',
    '.yt-section{display:none;}',
    '.yt-section.show{display:block;}',
    '.yt-row{display:flex;align-items:center;justify-content:space-between;padding:12px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:12px;margin-bottom:8px;cursor:pointer;transition:border-color .2s,background .2s;user-select:none;}',
    '.yt-row:hover{background:rgba(255,255,255,0.07);}',
    '.yt-row.active{border-color:#8855ff;background:rgba(136,85,255,0.13);}',
    '.yt-draw-colors{display:flex;flex-wrap:wrap;gap:8px;padding:10px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:12px;margin-bottom:8px;}',
    '.yt-draw-color{width:28px;height:28px;border-radius:50%;cursor:pointer;border:3px solid transparent;transition:all .2s;flex-shrink:0;}',
    '.yt-draw-color:hover{transform:scale(1.2);}',
    '.yt-draw-color.active{border-color:#fff!important;transform:scale(1.25);box-shadow:0 0 10px rgba(255,255,255,0.5);}',
    '.yt-clear-btn{width:100%;padding:10px;border-radius:12px;border:1.5px solid rgba(255,80,80,0.4);background:rgba(255,50,50,0.08);color:#ff8080;font-family:"Exo 2",sans-serif;font-size:13px;font-weight:700;cursor:pointer;transition:all .2s;margin-bottom:8px;letter-spacing:0.5px;}',
    '.yt-clear-btn:hover{background:rgba(255,50,50,0.2);border-color:rgba(255,80,80,0.8);color:#fff;box-shadow:0 0 12px rgba(255,50,50,0.3);}',
    '.yt-fx-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin-bottom:8px;}',
    '.yt-fx-card{border-radius:12px;border:2px solid rgba(255,255,255,0.08);padding:12px 6px;text-align:center;cursor:pointer;transition:all .25s;user-select:none;background:rgba(255,255,255,0.03);}',
    '.yt-fx-card:hover{background:rgba(255,255,255,0.07);border-color:rgba(255,255,255,0.2);}',
    '.yt-fx-card.active{border-color:#ff2060;background:rgba(255,32,96,0.13);box-shadow:0 0 14px rgba(255,32,96,0.2);}',
    '.yt-fx-icon{font-size:24px;display:block;margin-bottom:4px;}',
    '.yt-fx-label{font-size:11px;font-weight:700;letter-spacing:.3px;color:#aaa;}',
    '.yt-fx-card.active .yt-fx-label{color:#ff8099;}',
    '.yt-slider-row{padding:14px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:12px;margin-bottom:8px;}',
    '.yt-slider-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;}',
    '.yt-slider-label{font-size:13px;font-weight:600;}',
    '.yt-slider-val{font-size:13px;font-weight:700;background:linear-gradient(90deg,#ff2060,#8855ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent;min-width:50px;text-align:right;}',
    '.yt-lang-block{background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);border-radius:12px;margin-bottom:8px;overflow:hidden;}',
    '.yt-lang-header{display:flex;align-items:center;justify-content:space-between;padding:12px;cursor:pointer;user-select:none;transition:background .2s;}',
    '.yt-lang-header:hover{background:rgba(255,255,255,0.04);}',
    '.yt-lang-header-left{display:flex;align-items:center;gap:8px;}',
    '.yt-lang-arrow{font-size:10px;color:#666;transition:transform .3s;display:inline-block;}',
    '.yt-lang-arrow.open{transform:rotate(180deg);}',
    '.yt-lang-body{max-height:0;overflow:hidden;transition:max-height .35s cubic-bezier(0.4,0,0.2,1);}',
    '.yt-lang-body.open{max-height:200px;}',
    '.yt-lang-options{padding:6px 10px 12px;display:flex;flex-direction:column;gap:6px;}',
    '.yt-lang-option{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;cursor:pointer;transition:background .2s,border-color .2s;border:1.5px solid rgba(255,255,255,0.06);user-select:none;}',
    '.yt-lang-option:hover{background:rgba(255,255,255,0.06);}',
    '.yt-lang-option.active{border-color:#8855ff;background:rgba(136,85,255,0.13);}',
    '.yt-lang-flag{font-size:20px;}',
    '.yt-lang-name{font-weight:600;font-size:14px;}',
    '.yt-lang-check{margin-left:auto;color:#8855ff;font-size:16px;}',
    '.yt-season-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-bottom:8px;}',
    '.yt-season-card{border-radius:14px;border:2px solid rgba(255,255,255,0.08);padding:14px 8px;text-align:center;cursor:pointer;transition:all .25s;user-select:none;position:relative;overflow:hidden;}',
    '.yt-season-card::before{content:"";position:absolute;inset:0;opacity:0;transition:opacity .25s;}',
    '.yt-season-card:hover::before{opacity:1;}',
    '.yt-season-card .sc-icon{font-size:32px;display:block;margin-bottom:6px;}',
    '.yt-season-card .sc-label{font-size:12px;font-weight:700;letter-spacing:.5px;}',
    '.yt-season-card.sc-none{background:rgba(255,255,255,0.03);}',
    '.yt-season-card.sc-none::before{background:rgba(255,255,255,0.04);}',
    '.yt-season-card.sc-none.active{border-color:#8855ff;background:rgba(136,85,255,0.15);}',
    '.yt-season-card.sc-ny{background:linear-gradient(145deg,rgba(10,30,80,0.8),rgba(20,60,120,0.8));}',
    '.yt-season-card.sc-ny::before{background:linear-gradient(145deg,rgba(100,180,255,0.1),rgba(200,240,255,0.05));}',
    '.yt-season-card.sc-ny.active{border-color:#4af;box-shadow:0 0 20px rgba(80,180,255,0.4),inset 0 0 20px rgba(80,180,255,0.1);}',
    '.yt-season-card.sc-ny .sc-label{color:#9cf;}',
    '.yt-season-card.sc-hw{background:linear-gradient(145deg,rgba(40,15,0,0.9),rgba(80,30,0,0.9));}',
    '.yt-season-card.sc-hw::before{background:linear-gradient(145deg,rgba(255,100,0,0.1),rgba(255,60,0,0.05));}',
    '.yt-season-card.sc-hw.active{border-color:#f80;box-shadow:0 0 20px rgba(255,120,0,0.4),inset 0 0 20px rgba(255,80,0,0.1);}',
    '.yt-season-card.sc-hw .sc-label{color:#f90;}',
    '.yt-switch{width:38px;height:20px;background:rgba(255,255,255,0.15);border-radius:20px;position:relative;transition:background .3s;flex-shrink:0;}',
    '.yt-switch.on{background:linear-gradient(90deg,#ff2060,#8855ff);}',
    '.yt-switch::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;background:#fff;border-radius:50%;transition:left .3s;box-shadow:0 1px 3px rgba(0,0,0,0.4);}',
    '.yt-switch.on::after{left:20px;}',
    'input.yt-range{-webkit-appearance:none;width:100%;height:4px;background:linear-gradient(90deg,#ff2060,#8855ff);border-radius:2px;outline:none;cursor:pointer;}',
    'input.yt-range::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;background:#fff;border-radius:50%;cursor:pointer;box-shadow:0 0 8px rgba(255,32,96,0.8);}',
    '.yt-color-chip{width:18px;height:18px;border-radius:50%;border:2px solid rgba(255,255,255,0.3);flex-shrink:0;}',
    '#yt-blur-overlay{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483646;opacity:0;visibility:hidden;pointer-events:none;backdrop-filter:blur(8px);background:rgba(0,0,0,0.35);cursor:pointer;transition:opacity .35s ease,visibility 0s linear .35s;}',
    '#yt-blur-overlay.on{opacity:1;visibility:visible;pointer-events:all;transition:opacity .35s ease,visibility 0s linear 0s;}',
    'body.yt-cinema #masthead{opacity:0!important;pointer-events:none!important;transition:opacity .5s!important;}',
    'body.yt-cinema ytd-guide-renderer{opacity:0!important;pointer-events:none!important;transition:opacity .5s!important;}',
    'body.yt-cinema #secondary{opacity:0!important;pointer-events:none!important;transition:opacity .5s!important;}',
    'body.yt-cinema #below{opacity:0!important;pointer-events:none!important;transition:opacity .5s!important;}',
    'body.yt-cinema ytd-app{background:#000!important;}',
    '.yt-sep{height:1px;background:rgba(255,255,255,0.08);margin:10px 0;}',
    '.yt-section-label{font-size:11px;font-weight:700;letter-spacing:1px;color:#666;text-transform:uppercase;margin-bottom:8px;padding-left:4px;}',
    '#yt-pro-toast{position:fixed;bottom:80px;left:50%;transform:translateX(-50%) translateY(20px);background:linear-gradient(135deg,rgba(255,32,96,0.95),rgba(136,85,255,0.95));color:#fff;padding:10px 20px;border-radius:30px;font-family:"Exo 2",sans-serif;font-size:14px;font-weight:600;z-index:2147483647;opacity:0;transition:opacity .4s ease,transform .4s ease;pointer-events:none;box-shadow:0 4px 20px rgba(255,32,96,0.4);letter-spacing:0.3px;}',
  ].join(''));

  // ─── Хелперы ──────────────────────────────────────────────────
  function el(tag, cls, txt) {
    const e = document.createElement(tag);
    if (cls) e.className = cls;
    if (txt !== undefined) e.textContent = txt;
    return e;
  }
  function sep() { return el('div','yt-sep'); }
  function lbl(txt) { return el('div','yt-section-label',txt); }

  function makeSwitch(row, active, onToggle) {
    const sw = el('div','yt-switch'+(active?' on':''));
    row.addEventListener('click', e => { e.stopPropagation(); onToggle(sw.classList.toggle('on')); });
    row.appendChild(sw);
    return sw;
  }

  function makeSlider({ label, min, max, step, value, unit, onChange }) {
    const row=el('div','yt-slider-row'), top=el('div','yt-slider-top');
    const lblEl=el('span','yt-slider-label',label), valEl=el('span','yt-slider-val',value+unit);
    top.append(lblEl,valEl);
    const input=document.createElement('input');
    input.type='range'; input.min=min; input.max=max; input.step=step; input.value=value; input.className='yt-range';
    input.addEventListener('input', e => { e.stopPropagation(); const v=parseFloat(input.value); valEl.textContent=v+unit; onChange(v); });
    row.append(top,input);
    return { row, input, valEl };
  }

  function applySettings() {
    setRainbowStyle(); syncRainbowOverlay(); setSeasonStyle();
    document.body.classList.toggle('yt-cinema', cfg.cinema===true||cfg.cinema==='true');
    document.documentElement.style.setProperty('cursor', getCursorStyle(cfg.cursor), 'important');
    updateMenuStyle(); applyVideoSpeed(cfg.videoSpeed); applyVideoVolume(cfg.videoVolume);
    startCursorEffect(cfg.cursorEffect); applyDrawMode();
  }

  function updateMenuStyle() {
    const menu=document.getElementById('yt-pro-menu');
    if (!menu) return;
    const isGlass=cfg.menuTransparent===true||cfg.menuTransparent==='true';
    if (isGlass) {
      menu.style.background='rgba(200,200,220,0.06)';
      menu.style.backdropFilter='blur(28px) saturate(150%) brightness(1.15)';
      menu.style.borderColor='rgba(255,255,255,0.3)';
      menu.style.color='#fff';
      menu.style.boxShadow='0 8px 32px rgba(0,0,0,0.4),inset 0 0 0 1px rgba(255,255,255,0.15)';
    } else {
      const color=MENU_COLORS[cfg.menuColor]||MENU_COLORS.default;
      menu.style.background=color.bg; menu.style.backdropFilter='none';
      menu.style.borderColor=color.border; menu.style.color=color.text;
      menu.style.boxShadow='0 20px 60px rgba(0,0,0,0.9)';
    }
  }

  function syncOverlay(menuOpen) {
    const ov=document.getElementById('yt-blur-overlay');
    if (!ov) return;
    ov.classList.toggle('on', menuOpen&&(cfg.menuBlur===true||cfg.menuBlur==='true'));
  }

  // ─── Построение меню ──────────────────────────────────────────
  function createMenu() {
    if (document.getElementById('yt-pro-menu')) return;
    const root=el('div'); root.id='yt-pro-root';
    document.documentElement.appendChild(root);

    const overlay=el('div'); overlay.id='yt-blur-overlay';
    overlay.addEventListener('click', closeMenu);
    root.appendChild(overlay);

    const menu=el('div'); menu.id='yt-pro-menu';
    const startX = Math.round(window.innerWidth / 2 - 325);
    const startY = Math.round(window.innerHeight / 2 - 265);
    menu.style.left = startX + 'px';
    menu.style.top  = startY + 'px';

    const sidebar=el('div','yt-sidebar');
    const content=el('div','yt-content');

    const tabs=[
      {id:'y', label:t('categories.youtube')},
      {id:'m', label:t('categories.menu')},
      {id:'d', label:t('categories.design')},
      {id:'c', label:t('categories.cursor')},
    ];
    const sections={};
    tabs.forEach((tab,i)=>{
      const btn=el('div','yt-nav-btn'+(i===0?' sel':''),tab.label);
      btn.addEventListener('click',()=>{
        sidebar.querySelectorAll('.yt-nav-btn').forEach(b=>b.classList.remove('sel'));
        btn.classList.add('sel');
        Object.values(sections).forEach(s=>s.classList.remove('show'));
        sections[tab.id].classList.add('show');
      });
      sidebar.appendChild(btn);
      const sec=el('div','yt-section'+(i===0?' show':''));
      sec.id='tab-'+tab.id; sections[tab.id]=sec;
    });

    const credit=el('div','yt-sidebar-credit','YouTube menu\nby ');
    credit.style.whiteSpace='pre';
    const creditLink=document.createElement('a');
    creditLink.textContent='Bveery';
    creditLink.href='https://www.youtube.com/@Bveery';
    creditLink.target='_blank';
    creditLink.style.cssText='color:rgba(255,100,120,0.6);text-decoration:none;transition:color .2s;cursor:pointer;';
    creditLink.addEventListener('mouseenter',()=>{creditLink.style.color='#ff2060';creditLink.style.textShadow='0 0 8px rgba(255,32,96,0.6)';});
    creditLink.addEventListener('mouseleave',()=>{creditLink.style.color='rgba(255,100,120,0.6)';creditLink.style.textShadow='none';});
    credit.appendChild(creditLink);
    sidebar.appendChild(credit);

    const header=el('div','yt-header');
    const titleEl=el('div','yt-title',t('title'));
    const closeBtn=el('div','yt-close','×');
    closeBtn.addEventListener('click', closeMenu);
    header.append(titleEl, closeBtn);
    content.appendChild(header);

    // Перетаскивание
    let dragActive=false, dragOffX=0, dragOffY=0;
    header.addEventListener('mousedown', e => {
      if (e.target === closeBtn) return;
      dragActive = true;
      menu.classList.add('dragging');
      const rect = menu.getBoundingClientRect();
      dragOffX = e.clientX - rect.left;
      dragOffY = e.clientY - rect.top;
      e.preventDefault();
    });
    document.addEventListener('mousemove', e => {
      if (!dragActive) return;
      let nx = e.clientX - dragOffX;
      let ny = e.clientY - dragOffY;
      nx = Math.max(0, Math.min(window.innerWidth  - menu.offsetWidth,  nx));
      ny = Math.max(0, Math.min(window.innerHeight - menu.offsetHeight, ny));
      menu.style.left = nx + 'px';
      menu.style.top  = ny + 'px';
    });
    document.addEventListener('mouseup', () => {
      if (!dragActive) return;
      dragActive = false;
      menu.classList.remove('dragging');
    });

    // ══ TAB: YOUTUBE ══════════════════════════════════════════
    const tabY=sections.y;
    tabY.appendChild(lbl(t('youtube.speedSection')));
    const {row:speedRow}=makeSlider({label:t('youtube.speed'),min:0.25,max:16,step:0.25,value:cfg.videoSpeed,unit:'x',onChange:v=>{save('videoSpeed',v);applyVideoSpeed(v);}});
    tabY.appendChild(speedRow);
    tabY.appendChild(sep());
    tabY.appendChild(lbl(t('youtube.volumeSection')));
    const {row:volRow}=makeSlider({label:t('youtube.volume'),min:0,max:300,step:1,value:cfg.videoVolume,unit:'%',onChange:v=>{save('videoVolume',v);applyVideoVolume(v);}});
    tabY.appendChild(volRow);
    const volHint=el('div','','⚠️ Values above 100% may distort audio');
    volHint.style.cssText='font-size:10px;color:rgba(255,180,0,0.6);padding:4px 4px 8px;';
    tabY.appendChild(volHint);
    tabY.appendChild(sep());
    tabY.appendChild(lbl(t('youtube.rememberSection')));
    const remRow=el('div','yt-row',t('youtube.remember'));
    makeSwitch(remRow,cfg.rememberPosition,on=>{save('rememberPosition',on);if(on){showToast('🕒 Position memory ON');restorePosition();}else showToast('⏹️ Position memory OFF');});
    tabY.appendChild(remRow);

    // ══ TAB: MENU ═════════════════════════════════════════════
    const tabM=sections.m;
    const langBlock=el('div','yt-lang-block');
    const langHeader=el('div','yt-lang-header');
    const langLeft=el('div','yt-lang-header-left');
    langLeft.append(el('span','','⚙️'),el('span','',t('menu.lang')));
    const langArrow=el('span','yt-lang-arrow','▼');
    langHeader.append(langLeft,langArrow);
    const langBody=el('div','yt-lang-body');
    const langOptions=el('div','yt-lang-options');
    [{code:'en',flag:'🇬🇧',name:t('menu.langEn')},{code:'ru',flag:'🇷🇺',name:t('menu.langRu')}].forEach(lang=>{
      const opt=el('div','yt-lang-option'+(cfg.language===lang.code?' active':''));
      opt.append(el('span','yt-lang-flag',lang.flag),el('span','yt-lang-name',lang.name),el('span','yt-lang-check',cfg.language===lang.code?'✓':''));
      opt.addEventListener('click',()=>{if(cfg.language===lang.code)return;save('language',lang.code);location.reload();});
      langOptions.appendChild(opt);
    });
    langBody.appendChild(langOptions);
    langBlock.append(langHeader,langBody);
    let langOpen=false;
    langHeader.addEventListener('click',()=>{langOpen=!langOpen;langBody.classList.toggle('open',langOpen);langArrow.classList.toggle('open',langOpen);});
    tabM.appendChild(langBlock);

    const blurRow=el('div','yt-row',t('menu.blur'));
    makeSwitch(blurRow,cfg.menuBlur,on=>{save('menuBlur',on);syncOverlay(isVisible);});
    tabM.appendChild(blurRow);
    const glassRow=el('div','yt-row',t('menu.transparent'));
    makeSwitch(glassRow,cfg.menuTransparent,on=>{save('menuTransparent',on);updateMenuStyle();});
    tabM.appendChild(glassRow);
    const pauseRow=el('div','yt-row',t('menu.pauseOnMenu'));
    makeSwitch(pauseRow,cfg.pauseOnMenu,on=>{save('pauseOnMenu',on);});
    tabM.appendChild(pauseRow);
    tabM.appendChild(sep());
    tabM.appendChild(lbl(t('menu.colorTitle')));
    Object.keys(MENU_COLORS).forEach(c=>{
      const row=el('div','yt-row'+(cfg.menuColor===c?' active':''));
      const name=el('span','',c.charAt(0).toUpperCase()+c.slice(1));
      const chip=el('div','yt-color-chip'); chip.style.background=COLOR_CHIPS[c]||'#888';
      row.append(name,chip);
      row.addEventListener('click',()=>{save('menuColor',c);tabM.querySelectorAll('.yt-row').forEach(r=>r.classList.remove('active'));row.classList.add('active');updateMenuStyle();});
      tabM.appendChild(row);
    });

    // ══ TAB: DESIGN ═══════════════════════════════════════════
    const tabD=sections.d;
    tabD.appendChild(lbl(t('design.rbSection')));
    const rbRow=el('div','yt-row',t('design.rainbow'));
    makeSwitch(rbRow,cfg.theme==='rainbow',on=>{save('theme',on?'rainbow':'none');applySettings();});
    tabD.appendChild(rbRow);
    const {row:rbSpeedRow}=makeSlider({label:t('design.speed'),min:1,max:20,step:1,value:cfg.rbSpeed,unit:'s',onChange:v=>{save('rbSpeed',v);setRainbowStyle();}});
    tabD.appendChild(rbSpeedRow);
    tabD.appendChild(sep());
    tabD.appendChild(lbl(t('design.seasonal')));
    const grid=el('div','yt-season-grid');
    [{key:'none',cls:'sc-none',icon:'⚪',label:t('design.s_none')},{key:'ny',cls:'sc-ny',icon:'❄️',label:t('design.s_ny')},{key:'hw',cls:'sc-hw',icon:'🎃',label:t('design.s_hw')}].forEach(sc=>{
      const card=el('div','yt-season-card '+sc.cls+(cfg.seasonal===sc.key?' active':''));
      card.append(el('span','sc-icon',sc.icon),el('span','sc-label',sc.label));
      card.addEventListener('click',()=>{save('seasonal',sc.key);grid.querySelectorAll('.yt-season-card').forEach(c=>c.classList.remove('active'));card.classList.add('active');setSeasonStyle();});
      grid.appendChild(card);
    });
    tabD.appendChild(grid);
    tabD.appendChild(sep());
    tabD.appendChild(lbl(t('design.cinSection')));
    const cinRow=el('div','yt-row',t('design.cinema'));
    makeSwitch(cinRow,cfg.cinema,on=>{save('cinema',on);applySettings();});
    tabD.appendChild(cinRow);

    // ══ TAB: CURSOR ═══════════════════════════════════════════
    const tabC=sections.c;

    // Рисование
    tabC.appendChild(lbl(t('cursor.drawSection')));
    const drawRow=el('div','yt-row',t('cursor.drawMode'));
    makeSwitch(drawRow,cfg.drawMode,on=>{save('drawMode',on);applyDrawMode();});
    tabC.appendChild(drawRow);
    tabC.appendChild(lbl(t('cursor.drawColor')));
    const colorPicker=el('div','yt-draw-colors');
    DRAW_COLORS.forEach(dc=>{
      const chip=el('div','yt-draw-color'+(cfg.drawColor===dc.color?' active':''));
      chip.style.background=dc.color;
      chip.addEventListener('click',()=>{
        save('drawColor',dc.color);
        colorPicker.querySelectorAll('.yt-draw-color').forEach(c=>c.classList.remove('active'));
        chip.classList.add('active');
      });
      colorPicker.appendChild(chip);
    });
    tabC.appendChild(colorPicker);
    const {row:sizeRow}=makeSlider({label:t('cursor.drawSize'),min:1,max:40,step:1,value:cfg.drawSize,unit:'px',onChange:v=>{save('drawSize',v);}});
    tabC.appendChild(sizeRow);
    const clearBtn=document.createElement('button');
    clearBtn.className='yt-clear-btn';
    clearBtn.textContent=t('cursor.drawClear');
    clearBtn.addEventListener('click',e=>{e.stopPropagation();clearDrawCanvas();});
    tabC.appendChild(clearBtn);
    tabC.appendChild(sep());

    // Стиль курсора
    tabC.appendChild(lbl(t('cursor.cursorSection')));
    CURSOR_KEYS.forEach(key=>{
      const row=el('div','yt-row'+(cfg.cursor===key?' active':''),t('cursor.'+key));
      row.addEventListener('click',()=>{
        save('cursor',key);
        tabC.querySelectorAll('.yt-row').forEach(r=>r.classList.remove('active'));
        row.classList.add('active');
        applySettings();
      });
      tabC.appendChild(row);
    });
    tabC.appendChild(sep());

    // Эффекты курсора
    tabC.appendChild(lbl(t('cursor.effectSection')));
    const fxData=[
      {key:'none',   icon:'⚪', label:t('cursor.fx_none')},
      {key:'sparks', icon:'✨', label:t('cursor.fx_sparks')},
      {key:'hearts', icon:'❤️', label:t('cursor.fx_hearts')},
      {key:'snow',   icon:'❄️', label:t('cursor.fx_snow')},
      {key:'rainbow',icon:'🌈', label:t('cursor.fx_rainbow')},
      {key:'stars',  icon:'⭐', label:t('cursor.fx_stars')},
    ];
    const fxGrid=el('div','yt-fx-grid');
    fxData.forEach(fx=>{
      const card=el('div','yt-fx-card'+(cfg.cursorEffect===fx.key?' active':''));
      card.append(el('span','yt-fx-icon',fx.icon),el('span','yt-fx-label',fx.label));
      card.addEventListener('click',()=>{
        save('cursorEffect',fx.key);
        fxGrid.querySelectorAll('.yt-fx-card').forEach(c=>c.classList.remove('active'));
        card.classList.add('active');
        startCursorEffect(fx.key);
      });
      fxGrid.appendChild(card);
    });
    tabC.appendChild(fxGrid);

    Object.values(sections).forEach(s=>content.appendChild(s));
    menu.append(sidebar,content);
    root.appendChild(menu);
    applySettings();
  }

  // ─── Открытие / Закрытие ──────────────────────────────────────
  let isVisible=false;

  function openMenu() {
    if (!document.getElementById('yt-pro-menu')) createMenu();
    isVisible=true;
    document.getElementById('yt-pro-menu').classList.add('active');
    updateMenuStyle();
    syncOverlay(true);
    if (cfg.pauseOnMenu===true||cfg.pauseOnMenu==='true') wePaused=pauseVideo();
  }

  function closeMenu() {
    isVisible=false;
    document.getElementById('yt-pro-menu')?.classList.remove('active');
    syncOverlay(false);
    if (wePaused&&(cfg.pauseOnMenu===true||cfg.pauseOnMenu==='true')) resumeVideo();
    wePaused=false;
  }

  function toggleMenu() { isVisible?closeMenu():openMenu(); }
  window.addEventListener('keyup', e => { if (e.code==='ShiftRight') toggleMenu(); });

  watchVideo();
  startPositionWatcher();
  applySettings();
})();