YouTube Plus4

YouTube tema, ozellik ve oynatici yoneticisi (reklam engelleme icermez)

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

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

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

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

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

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

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

Advertisement:

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

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

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

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

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

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

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

Advertisement:

// ==UserScript==
// @name         YouTube Plus4
// @namespace    http://tampermonkey.net/
// @version      12001
// @description  YouTube tema, ozellik ve oynatici yoneticisi (reklam engelleme icermez)
// @author       Mustafa Hakan
// @match        *://*.youtube.com/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';
    let LANG  = localStorage.getItem('yt-lang')  || 'tr';
    let THEME = localStorage.getItem('yt-theme') || '__default__';
    function getFeature(key, def) {
        if (def === undefined) def = true;
        var v = localStorage.getItem('yt-feat-' + key);
        return v === null ? def : v === '1';
    }
    function setFeature(key, val) {
        localStorage.setItem('yt-feat-' + key, val ? '1' : '0');
    }
    function getSetting(key, def) {
        var v = localStorage.getItem('yt-set-' + key);
        return v === null ? def : v;
    }
    function setSetting(key, val) {
        localStorage.setItem('yt-set-' + key, val);
    }
    var T = {
        tr: {
            panelTitle:    'AYARLAR',
            themeSection:  'TEMA',
            featSection:   'OZELLIKLER',
            charSection:   'KARAKTER',
            trailSection:  'IZ (TRAIL) RENGI',
            shortcutSection: 'KISAYOLLAR',
            labelText:     'YT+',
            defaultTheme:  'YouTube Varsayilan',
            langBtn:       'Switch to English',
            shortcut:      'Ctrl + Shift + D',
            copied:        'Kopyalandi',
            noneTrail:     'Yok',
            features: {
                loop:        'Dongu Butonu',
                character:   'Karakter (Scrubber)',
                trail:       'Oynatma Cubugu Izi',
                label:       'YT+ Etiketi',
                scroll:      'Kaydirma ile Ses',
                pip:         'Picture-in-Picture',
                speed:       'Hiz Secici',
                cinema:      'Sinema Modu',
                timestamp:   'Zaman Damgasi Kopyala',
                autoQuality: 'Otomatik Maks. Kalite',
                subtitleStyle: 'Ozel Altyazi Stili',
                chapterJump: 'Bolum Atlama Tuslari',
                clipSave:    'Klip / Not Kaydet',
                miniPlayerDrag: 'Surukle-Birak Karakter',
            },
            characters: {
                snoopy:   'Snoopy',
                pikachu:  'Pikachu',
                kirby:    'Kirby',
                cat:      'Kedi',
                alien:    'Uzayli',
                rocket:   'Roket',
                ghost:    'Hayalet',
                star:     'Yildiz',
            },
            colors: {
                'Midnight':  'Gece Yarisi',
                'Obsidian':  'Obsidyen',
                'Slate':     'Arduvaz',
                'Forest':    'Orman',
                'Abyss':     'Derin Deniz',
                'Velvet':    'Kadife',
                'Espresso':  'Espresso',
                'Graphite':  'Grafit',
                'Steel':     'Celik',
                'Moss':      'Yosun',
                'Burgundy':  'Bordo',
                'Petroleum': 'Petrol',
                'Aurora':    'Kuzey Isigi',
                'Sand':      'Kum',
                'Rose':      'Gul Kurusu',
                'Ice':       'Buz',
            },
            shortcutsList: [
                ['Ctrl+Shift+D', 'Ayar panelini ac/kapat'],
                ['Ctrl+Shift+L', 'Donguyu ac/kapat'],
                ['Ctrl+Shift+C', 'Zaman damgasini kopyala'],
                ['Ctrl+Shift+,', 'Onceki bolume atla'],
                ['Ctrl+Shift+.', 'Sonraki bolume atla'],
                ['Ctrl+Shift+K', 'Bu anda not/klip kaydet'],
            ],
            clipSaved: 'Not kaydedildi',
            clipPanelTitle: 'KAYITLI NOTLAR',
            clipEmpty: 'Henuz not yok. Ctrl+Shift+K ile ekleyebilirsin.',
            clipDelete: 'Sil',
            clipGoto: 'Git',
        },
        en: {
            panelTitle:    'SETTINGS',
            themeSection:  'THEME',
            featSection:   'FEATURES',
            charSection:   'CHARACTER',
            trailSection:  'TRAIL COLOR',
            shortcutSection: 'SHORTCUTS',
            labelText:     'YT+',
            defaultTheme:  'YouTube Default',
            langBtn:       'Turkceye Gec',
            shortcut:      'Ctrl + Shift + D',
            copied:        'Copied',
            noneTrail:     'None',
            features: {
                loop:        'Loop Button',
                character:   'Character (Scrubber)',
                trail:       'Progress Bar Trail',
                label:       'YT+ Badge',
                scroll:      'Scroll to Volume',
                pip:         'Picture-in-Picture',
                speed:       'Speed Selector',
                cinema:      'Cinema Mode',
                timestamp:   'Copy Timestamp',
                autoQuality: 'Auto Max Quality',
                subtitleStyle: 'Custom Subtitle Style',
                chapterJump: 'Chapter Jump Keys',
                clipSave:    'Save Clip / Note',
                miniPlayerDrag: 'Draggable Character',
            },
            characters: {
                snoopy:   'Snoopy',
                pikachu:  'Pikachu',
                kirby:    'Kirby',
                cat:      'Cat',
                alien:    'Alien',
                rocket:   'Rocket',
                ghost:    'Ghost',
                star:     'Star',
            },
            colors: {
                'Midnight':  'Midnight',
                'Obsidian':  'Obsidian',
                'Slate':     'Slate',
                'Forest':    'Forest',
                'Abyss':     'Abyss',
                'Velvet':    'Velvet',
                'Espresso':  'Espresso',
                'Graphite':  'Graphite',
                'Steel':     'Steel',
                'Moss':      'Moss',
                'Burgundy':  'Burgundy',
                'Petroleum': 'Petroleum',
                'Aurora':    'Aurora',
                'Sand':      'Sand',
                'Rose':      'Rose',
                'Ice':       'Ice',
            },
            shortcutsList: [
                ['Ctrl+Shift+D', 'Toggle settings panel'],
                ['Ctrl+Shift+L', 'Toggle loop'],
                ['Ctrl+Shift+C', 'Copy timestamp'],
                ['Ctrl+Shift+,', 'Jump to previous chapter'],
                ['Ctrl+Shift+.', 'Jump to next chapter'],
                ['Ctrl+Shift+K', 'Save note/clip at current time'],
            ],
            clipSaved: 'Note saved',
            clipPanelTitle: 'SAVED NOTES',
            clipEmpty: 'No notes yet. Press Ctrl+Shift+K to add one.',
            clipDelete: 'Delete',
            clipGoto: 'Go to',
        }
    };
    var THEMES = {
        'Midnight':  ['#0d0d12', '#4a6fa5'],
        'Obsidian':  ['#0f0f0f', '#555555'],
        'Slate':     ['#1c2128', '#6e7c8c'],
        'Forest':    ['#0e1a12', '#3a6b45'],
        'Abyss':     ['#050d1a', '#1a4a7a'],
        'Velvet':    ['#160d1a', '#6b3a7a'],
        'Espresso':  ['#140e0b', '#7a4a30'],
        'Graphite':  ['#141414', '#4a4a4a'],
        'Steel':     ['#0f1418', '#3a5a6a'],
        'Moss':      ['#111a0f', '#4a6a30'],
        'Burgundy':  ['#14080a', '#6a2030'],
        'Petroleum': ['#091518', '#1a5a5a'],
        'Aurora':    ['#0a0f1a', '#2d7a6a'],
        'Sand':      ['#1a1710', '#8a7a50'],
        'Rose':      ['#1a0f12', '#8a4a5a'],
        'Ice':       ['#0f1520', '#5a8aaa'],
    };
    var TRAIL_COLORS = {
        'none':    null,
        'red':     '#ff0033',
        'orange':  '#ff8800',
        'gold':    '#ffd24a',
        'green':   '#3ddc84',
        'cyan':    '#3ad6e0',
        'blue':    '#4a90d9',
        'purple':  '#a14ad9',
        'pink':    '#ff5fa2',
        'rainbow': 'rainbow',
    };
    function getSVG(name) {
        var svgs = {
            snoopy: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<ellipse cx="10" cy="9" rx="4" ry="6" fill="#111" transform="rotate(-15,10,9)"/>' +
                '<ellipse cx="22" cy="8" rx="3.5" ry="5.5" fill="#111" transform="rotate(10,22,8)"/>' +
                '<ellipse cx="16" cy="16" rx="10" ry="9" fill="#f5f5f5"/>' +
                '<ellipse cx="16" cy="20" rx="6" ry="4" fill="#111"/>' +
                '<circle cx="12.5" cy="13.5" r="1.5" fill="#111"/>' +
                '<circle cx="19.5" cy="13.5" r="1.5" fill="#111"/>' +
                '<circle cx="13" cy="13" r="0.5" fill="#fff"/>' +
                '<circle cx="20" cy="13" r="0.5" fill="#fff"/>' +
                '<ellipse cx="16" cy="18.5" rx="2.5" ry="1.5" fill="#222"/>' +
                '<path d="M13.5 21.5 Q16 23 18.5 21.5" stroke="#f5f5f5" stroke-width="1.2" fill="none" stroke-linecap="round"/>' +
                '</svg>',
            pikachu: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<ellipse cx="16" cy="18" rx="12" ry="11" fill="#FFD700"/>' +
                '<ellipse cx="8" cy="8" rx="4" ry="7" fill="#FFD700" transform="rotate(-20,8,8)"/>' +
                '<ellipse cx="8" cy="5" rx="2" ry="3.5" fill="#111" transform="rotate(-20,8,5)"/>' +
                '<ellipse cx="24" cy="8" rx="4" ry="7" fill="#FFD700" transform="rotate(20,24,8)"/>' +
                '<ellipse cx="24" cy="5" rx="2" ry="3.5" fill="#111" transform="rotate(20,24,5)"/>' +
                '<circle cx="11.5" cy="15" r="2" fill="#111"/>' +
                '<circle cx="20.5" cy="15" r="2" fill="#111"/>' +
                '<circle cx="12" cy="14.3" r="0.7" fill="#fff"/>' +
                '<circle cx="21" cy="14.3" r="0.7" fill="#fff"/>' +
                '<ellipse cx="9" cy="20" rx="3" ry="2" fill="#FF6060" opacity="0.8"/>' +
                '<ellipse cx="23" cy="20" rx="3" ry="2" fill="#FF6060" opacity="0.8"/>' +
                '<path d="M13 22 Q16 24.5 19 22" stroke="#111" stroke-width="1.2" fill="none" stroke-linecap="round"/>' +
                '<ellipse cx="16" cy="21.5" rx="1.5" ry="1" fill="#FF8888"/>' +
                '</svg>',
            kirby: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<ellipse cx="16" cy="17" rx="13" ry="13" fill="#FFB7D5"/>' +
                '<ellipse cx="10" cy="23" rx="4" ry="3" fill="#FF85B3" transform="rotate(-20,10,23)"/>' +
                '<ellipse cx="22" cy="23" rx="4" ry="3" fill="#FF85B3" transform="rotate(20,22,23)"/>' +
                '<circle cx="12" cy="14" r="2.5" fill="#111"/>' +
                '<circle cx="20" cy="14" r="2.5" fill="#111"/>' +
                '<circle cx="12.7" cy="13" r="1" fill="#fff"/>' +
                '<circle cx="20.7" cy="13" r="1" fill="#fff"/>' +
                '<ellipse cx="12" cy="14" rx="1" ry="1.5" fill="#3a5af0" opacity="0.6"/>' +
                '<ellipse cx="20" cy="14" rx="1" ry="1.5" fill="#3a5af0" opacity="0.6"/>' +
                '<ellipse cx="16" cy="19.5" rx="2.5" ry="1.5" fill="#e0609a"/>' +
                '<path d="M13.5 22 Q16 24 18.5 22" stroke="#e0609a" stroke-width="1.5" fill="none" stroke-linecap="round"/>' +
                '</svg>',
            cat: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<polygon points="6,12 2,3 10,9" fill="#888"/>' +
                '<polygon points="26,12 30,3 22,9" fill="#888"/>' +
                '<ellipse cx="16" cy="18" rx="12" ry="11" fill="#aaa"/>' +
                '<ellipse cx="16" cy="18" rx="8" ry="7" fill="#eee"/>' +
                '<ellipse cx="12" cy="15" rx="2" ry="2.5" fill="#111"/>' +
                '<ellipse cx="20" cy="15" rx="2" ry="2.5" fill="#111"/>' +
                '<circle cx="12.7" cy="14" r="0.8" fill="#fff"/>' +
                '<circle cx="20.7" cy="14" r="0.8" fill="#fff"/>' +
                '<ellipse cx="16" cy="19" rx="1.5" ry="1" fill="#ffaaaa"/>' +
                '<path d="M13.5 21 Q16 23 18.5 21" stroke="#999" stroke-width="1.2" fill="none" stroke-linecap="round"/>' +
                '<line x1="6" y1="19" x2="1" y2="17" stroke="#888" stroke-width="0.8"/>' +
                '<line x1="6" y1="20" x2="1" y2="20" stroke="#888" stroke-width="0.8"/>' +
                '<line x1="6" y1="21" x2="1" y2="23" stroke="#888" stroke-width="0.8"/>' +
                '<line x1="26" y1="19" x2="31" y2="17" stroke="#888" stroke-width="0.8"/>' +
                '<line x1="26" y1="20" x2="31" y2="20" stroke="#888" stroke-width="0.8"/>' +
                '<line x1="26" y1="21" x2="31" y2="23" stroke="#888" stroke-width="0.8"/>' +
                '</svg>',
            alien: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<ellipse cx="16" cy="17" rx="11" ry="13" fill="#7aee88"/>' +
                '<ellipse cx="11" cy="14" rx="4.5" ry="3.5" fill="#111" opacity="0.85"/>' +
                '<ellipse cx="21" cy="14" rx="4.5" ry="3.5" fill="#111" opacity="0.85"/>' +
                '<ellipse cx="11" cy="14" rx="2.5" ry="2" fill="#6688ff"/>' +
                '<ellipse cx="21" cy="14" rx="2.5" ry="2" fill="#6688ff"/>' +
                '<circle cx="11.8" cy="13.3" r="0.9" fill="#fff"/>' +
                '<circle cx="21.8" cy="13.3" r="0.9" fill="#fff"/>' +
                '<path d="M12 22 Q16 20 20 22" stroke="#5acc66" stroke-width="1.5" fill="none" stroke-linecap="round"/>' +
                '<line x1="10" y1="4" x2="7" y2="1" stroke="#7aee88" stroke-width="1.5"/>' +
                '<circle cx="7" cy="1" r="1.5" fill="#aaffaa"/>' +
                '<line x1="22" y1="4" x2="25" y2="1" stroke="#7aee88" stroke-width="1.5"/>' +
                '<circle cx="25" cy="1" r="1.5" fill="#aaffaa"/>' +
                '</svg>',
            rocket: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<path d="M16 2 C10 8 8 16 8 22 L16 26 L24 22 C24 16 22 8 16 2Z" fill="#dde8ff"/>' +
                '<ellipse cx="16" cy="13" rx="4" ry="4" fill="#4a8aff"/>' +
                '<path d="M8 22 L4 28 L10 25Z" fill="#ff6030"/>' +
                '<path d="M24 22 L28 28 L22 25Z" fill="#ff6030"/>' +
                '<path d="M12 26 Q16 30 20 26" fill="#ff8050"/>' +
                '<circle cx="16" cy="13" r="2" fill="#cce0ff" opacity="0.7"/>' +
                '</svg>',
            ghost: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<path d="M6 26 V14 a10 10 0 0 1 20 0 V26 L22 22 L18 26 L14 22 L10 26 Z" fill="#f0f3ff" opacity="0.95"/>' +
                '<ellipse cx="12" cy="14" rx="2" ry="2.6" fill="#222"/>' +
                '<ellipse cx="20" cy="14" rx="2" ry="2.6" fill="#222"/>' +
                '<ellipse cx="16" cy="19" rx="2.2" ry="1.6" fill="#aab4e0" opacity="0.7"/>' +
                '</svg>',
            star: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="34" height="34">' +
                '<path d="M16 2 L20 12 L31 12.5 L22 19.5 L25 30 L16 23.5 L7 30 L10 19.5 L1 12.5 L12 12 Z" fill="#ffd84a"/>' +
                '<circle cx="13" cy="14.5" r="1.6" fill="#222"/>' +
                '<circle cx="19" cy="14.5" r="1.6" fill="#222"/>' +
                '<path d="M13 19 Q16 21.2 19 19" stroke="#222" stroke-width="1.3" fill="none" stroke-linecap="round"/>' +
                '</svg>',
        };
        return svgs[name] || svgs['snoopy'];
    }
    function isDefaultTheme(t) {
        return !t || t === '__default__' || !THEMES[t];
    }
    function applyTheme(themeName) {
        THEME = isDefaultTheme(themeName) ? '__default__' : themeName;
        localStorage.setItem('yt-theme', THEME);
        var s = document.getElementById('yt-custom-style');
        if (isDefaultTheme(THEME)) {
            if (s) s.remove();
            return;
        }
        var pair   = THEMES[THEME];
        var bg     = pair[0];
        var accent = pair[1];
        if (!s) {
            s = document.createElement('style');
            s.id = 'yt-custom-style';
            document.head.appendChild(s);
        }
        s.textContent = [
            'html, body, ytd-app, #content, #page-manager, ytd-browse, ytd-watch-flexy,',
            'ytd-search, ytd-two-column-browse-results-renderer, ytd-rich-grid-renderer,',
            '#primary, #secondary, ytd-mini-guide-renderer, ytd-guide-renderer,',
            '#guide-content, tp-yt-app-drawer, #contentContainer, ytd-masthead {',
            '    background-color: ' + bg + ' !important;',
            '    background-image: none !important;',
            '}',
            'ytd-rich-item-renderer, ytd-video-renderer, ytd-compact-video-renderer,',
            'ytd-playlist-renderer, ytd-shelf-renderer, ytd-item-section-renderer,',
            '#dismissible, ytd-comment-thread-renderer, ytd-comment-renderer {',
            '    background-color: transparent !important;',
            '}',
            'ytd-guide-entry-renderer:hover, ytd-mini-guide-entry-renderer:hover {',
            '    background-color: ' + accent + '22 !important;',
            '}',
            '.ytp-play-progress { background: ' + accent + ' !important; }',
            '.ytp-scrubber-button { background-color: ' + accent + ' !important; }',
            '#yt-loop-btn { opacity: 0.45; transition: opacity 0.2s; }',
            '#yt-loop-btn.yt-active { opacity: 1 !important; }',
            '#yt-loop-btn svg path, #yt-loop-btn svg polyline { stroke: ' + accent + ' !important; }',
            '#yt-pip-btn { opacity: 0.7; transition: opacity 0.2s; }',
            '#yt-pip-btn:hover { opacity: 1; }',
            '#yt-speed-select {',
            '    background: ' + bg + '; color: #fff; border: 1px solid ' + accent + '66;',
            '    border-radius: 4px; font-size: 11px; font-weight: 700; cursor: pointer;',
            '    padding: 2px 4px; margin: 0 4px;',
            '}',
        ].join('\n');
    }
    function addLabel() {
        if (!getFeature('label')) {
            var old = document.getElementById('yt-premium-label');
            if (old) old.remove();
            return;
        }
        if (document.getElementById('yt-premium-label')) return;
        var logo = document.querySelector('#logo, ytd-logo');
        if (!logo) return;
        var label = document.createElement('span');
        label.id = 'yt-premium-label';
        label.textContent = T[LANG].labelText;
        label.title = T[LANG].shortcut;
        label.style.cssText = [
            'color: #ffffff !important;',
            'font-size: 13px;',
            'font-weight: 800;',
            'font-style: italic;',
            'cursor: pointer;',
            'margin-left: 8px;',
            'letter-spacing: 0.3px;',
            'opacity: 0.92;',
            'transition: opacity 0.2s;',
            'background: none;',
            'border: none;',
            'padding: 0;',
            'text-shadow: 0 1px 6px rgba(0,0,0,0.7);',
        ].join('');
        label.onmouseenter = function () { label.style.opacity = '0.55'; };
        label.onmouseleave = function () { label.style.opacity = '0.92'; };
        label.onclick = function (e) { e.stopPropagation(); openPanel(); };
        logo.parentNode.insertBefore(label, logo.nextSibling);
    }
    var charPosRAF = null;
    var charDragOffset = null;
    function getPlayerEls() {
        return {
            player: document.querySelector('.html5-video-player, #movie_player'),
            scrubber: document.querySelector('.ytp-scrubber-button'),
            progressBar: document.querySelector('.ytp-progress-bar'),
            video: document.querySelector('video'),
        };
    }
    function positionCharacter() {
        var charEl = document.getElementById('yt-char-el');
        if (!charEl) return;
        if (charEl.getAttribute('data-dragging') === '1') return;
        var els = getPlayerEls();
        if (!els.player || !els.scrubber || !els.progressBar) return;
        var playerRect = els.player.getBoundingClientRect();
        var scRect     = els.scrubber.getBoundingClientRect();
        if (scRect.width === 0 && scRect.height === 0) return;
        var leftPx = scRect.left - playerRect.left + scRect.width / 2 - 17;
        var topPx  = scRect.top  - playerRect.top  - 44;
        charEl.style.left = leftPx + 'px';
        charEl.style.top  = topPx  + 'px';
    }
    function startCharLoop() {
        if (charPosRAF) return;
        function loop() {
            positionCharacter();
            charPosRAF = requestAnimationFrame(loop);
        }
        charPosRAF = requestAnimationFrame(loop);
    }
    function stopCharLoop() {
        if (charPosRAF) {
            cancelAnimationFrame(charPosRAF);
            charPosRAF = null;
        }
    }
    function makeCharDraggable(charEl) {
        charEl.style.pointerEvents = 'auto';
        charEl.style.cursor = 'grab';
        charEl.onmousedown = function (e) {
            if (!getFeature('miniPlayerDrag')) return;
            e.preventDefault();
            charEl.setAttribute('data-dragging', '1');
            charEl.style.cursor = 'grabbing';
            var els = getPlayerEls();
            var playerRect = els.player ? els.player.getBoundingClientRect() : { left: 0, top: 0 };
            var startLeft = parseFloat(charEl.style.left) || 0;
            var startTop  = parseFloat(charEl.style.top)  || 0;
            var startX = e.clientX, startY = e.clientY;
            function onMove(ev) {
                charEl.style.left = (startLeft + (ev.clientX - startX)) + 'px';
                charEl.style.top  = (startTop  + (ev.clientY - startY)) + 'px';
            }
            function onUp() {
                document.removeEventListener('mousemove', onMove);
                document.removeEventListener('mouseup', onUp);
                charEl.style.cursor = 'grab';
                setTimeout(function () { charEl.removeAttribute('data-dragging'); }, 600);
            }
            document.addEventListener('mousemove', onMove);
            document.addEventListener('mouseup', onUp);
        };
    }
    function injectCharacter() {
        var charKey = localStorage.getItem('yt-character') || 'snoopy';
        if (!getFeature('character')) {
            var old = document.getElementById('yt-char-el');
            if (old) old.remove();
            stopCharLoop();
            return;
        }
        var els = getPlayerEls();
        if (!els.player || !els.scrubber || !els.progressBar) return;
        var charEl = document.getElementById('yt-char-el');
        if (!charEl) {
            charEl = document.createElement('div');
            charEl.id = 'yt-char-el';
            charEl.innerHTML = getSVG(charKey);
            charEl.setAttribute('data-char', charKey);
            charEl.style.cssText = [
                'position: absolute;',
                'pointer-events: none;',
                'z-index: 2147483600;',
                'width: 36px;',
                'height: 36px;',
                'filter: drop-shadow(0 2px 6px rgba(0,0,0,0.95));',
                'will-change: left, top;',
            ].join('');
            els.player.style.overflow = 'visible';
            els.player.appendChild(charEl);
            makeCharDraggable(charEl);
        } else {
            var currentChar = charEl.getAttribute('data-char');
            if (currentChar !== charKey) {
                charEl.innerHTML = getSVG(charKey);
                charEl.setAttribute('data-char', charKey);
                makeCharDraggable(charEl);
            }
        }
        startCharLoop();
    }
    function ensureTrailEl() {
        var els = getPlayerEls();
        if (!els.progressBar) return null;
        var trail = els.progressBar.querySelector('#yt-trail-el');
        if (!trail) {
            trail = document.createElement('div');
            trail.id = 'yt-trail-el';
            trail.style.cssText = [
                'position: absolute;',
                'left: 0; top: 0; bottom: 0;',
                'pointer-events: none;',
                'z-index: 30;',
                'border-radius: 2px;',
                'transition: width 0.08s linear;',
            ].join('');
            els.progressBar.style.position = els.progressBar.style.position || 'relative';
            els.progressBar.appendChild(trail);
        }
        return trail;
    }
    function updateTrail() {
        var trail = document.getElementById('yt-trail-el');
        var trailKey = getSetting('trail-color', 'gold');
        if (!getFeature('trail') || trailKey === 'none') {
            if (trail) trail.remove();
            return;
        }
        var els = getPlayerEls();
        if (!els.video || !els.progressBar) return;
        trail = ensureTrailEl();
        if (!trail) return;
        var pct = els.video.duration ? (els.video.currentTime / els.video.duration) * 100 : 0;
        trail.style.width = pct + '%';
        if (trailKey === 'rainbow') {
            trail.style.background = 'linear-gradient(90deg, #ff0033, #ff8800, #ffd24a, #3ddc84, #3ad6e0, #4a90d9, #a14ad9, #ff5fa2)';
            trail.style.backgroundSize = (els.progressBar.offsetWidth || 600) + 'px 100%';
        } else {
            var color = TRAIL_COLORS[trailKey] || TRAIL_COLORS['gold'];
            trail.style.background = color;
            trail.style.boxShadow = '0 0 6px ' + color + 'aa';
        }
    }
    function addLoopButton() {
        if (!getFeature('loop')) {
            var existing = document.getElementById('yt-loop-btn');
            if (existing) existing.remove();
            return;
        }
        if (document.getElementById('yt-loop-btn')) return;
        var ctrl = document.querySelector('.ytp-right-controls');
        if (!ctrl) return;
        var btn = document.createElement('button');
        btn.id = 'yt-loop-btn';
        btn.className = 'ytp-button';
        btn.title = T[LANG].features.loop;
        btn.innerHTML = '<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg">' +
            '<polyline points="17,1 21,5 17,9" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>' +
            '<path d="M3 11V9a4 4 0 0 1 4-4h14" stroke="#fff" stroke-width="2" stroke-linecap="round"/>' +
            '<polyline points="7,23 3,19 7,15" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>' +
            '<path d="M21 13v2a4 4 0 0 1-4 4H3" stroke="#fff" stroke-width="2" stroke-linecap="round"/>' +
            '</svg>';
        btn.style.cssText = 'display:flex;align-items:center;justify-content:center;width:36px;height:36px;';
        btn.onclick = function () { toggleLoop(); };
        ctrl.prepend(btn);
    }
    function toggleLoop() {
        var v = document.querySelector('video');
        if (!v) return;
        v.loop = !v.loop;
        var btn = document.getElementById('yt-loop-btn');
        if (btn) btn.classList.toggle('yt-active', v.loop);
    }
    function addPipButton() {
        if (!getFeature('pip')) {
            var existing = document.getElementById('yt-pip-btn');
            if (existing) existing.remove();
            return;
        }
        if (document.getElementById('yt-pip-btn')) return;
        var ctrl = document.querySelector('.ytp-right-controls');
        if (!ctrl) return;
        var btn = document.createElement('button');
        btn.id = 'yt-pip-btn';
        btn.className = 'ytp-button';
        btn.title = 'Picture-in-Picture';
        btn.innerHTML = '<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg">' +
            '<rect x="2" y="4" width="20" height="14" rx="2" stroke="#fff" stroke-width="2"/>' +
            '<rect x="12" y="11" width="9" height="6" rx="1" fill="#fff"/>' +
            '</svg>';
        btn.style.cssText = 'display:flex;align-items:center;justify-content:center;width:36px;height:36px;';
        btn.onclick = function () {
            var v = document.querySelector('video');
            if (!v) return;
            if (document.pictureInPictureElement) {
                document.exitPictureInPicture().catch(function () {});
            } else if (document.pictureInPictureEnabled) {
                v.requestPictureInPicture().catch(function () {});
            }
        };
        ctrl.prepend(btn);
    }
    function addSpeedSelector() {
        if (!getFeature('speed')) {
            var existing = document.getElementById('yt-speed-select');
            if (existing) existing.remove();
            return;
        }
        if (document.getElementById('yt-speed-select')) return;
        var ctrl = document.querySelector('.ytp-right-controls');
        if (!ctrl) return;
        var sel = document.createElement('select');
        sel.id = 'yt-speed-select';
        sel.title = LANG === 'tr' ? 'Oynatma Hizi' : 'Playback Speed';
        var speeds = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3];
        var v = document.querySelector('video');
        var current = v ? v.playbackRate : 1;
        speeds.forEach(function (s) {
            var opt = document.createElement('option');
            opt.value = s;
            opt.textContent = s + 'x';
            if (s === current) opt.selected = true;
            sel.appendChild(opt);
        });
        sel.onclick = function (e) { e.stopPropagation(); };
        sel.onchange = function () {
            var vid = document.querySelector('video');
            if (vid) vid.playbackRate = parseFloat(sel.value);
        };
        ctrl.prepend(sel);
    }
    function applyCinemaMode() {
        var s = document.getElementById('yt-cinema-style');
        if (!getFeature('cinema')) {
            if (s) s.remove();
            return;
        }
        if (s) return;
        s = document.createElement('style');
        s.id = 'yt-cinema-style';
        s.textContent = [
            '#secondary { display: none !important; }',
            '#primary { max-width: 100% !important; }',
            'ytd-watch-flexy[theater] #primary-inner { max-width: 100% !important; }',
            '#below { max-width: 100% !important; }',
        ].join('\n');
        document.head.appendChild(s);
    }
    function formatTimestamp(t) {
        t = Math.floor(t);
        var h = Math.floor(t / 3600);
        var m = Math.floor((t % 3600) / 60);
        var s = t % 60;
        var mStr = h > 0 ? String(m).padStart(2, '0') : String(m);
        var sStr = String(s).padStart(2, '0');
        return (h > 0 ? h + ':' : '') + mStr + ':' + sStr;
    }
    function copyTimestamp() {
        var v = document.querySelector('video');
        if (!v) return;
        var t = Math.floor(v.currentTime);
        var ts = formatTimestamp(t);
        var url = window.location.href.split('&t=')[0].split('?t=')[0] + (window.location.href.indexOf('?') > -1 ? '&t=' : '?t=') + t + 's';
        navigator.clipboard.writeText(url).catch(function () {});
        var btn = document.getElementById('yt-ts-btn');
        if (btn) {
            var prevTitle = T[LANG].features.timestamp;
            btn.title = T[LANG].copied + ': ' + ts;
            setTimeout(function () { btn.title = prevTitle; }, 2000);
        }
        return ts;
    }
    function addTimestampButton() {
        if (!getFeature('timestamp')) {
            var existing = document.getElementById('yt-ts-btn');
            if (existing) existing.remove();
            return;
        }
        if (document.getElementById('yt-ts-btn')) return;
        var ctrl = document.querySelector('.ytp-right-controls');
        if (!ctrl) return;
        var btn = document.createElement('button');
        btn.id = 'yt-ts-btn';
        btn.className = 'ytp-button';
        btn.title = T[LANG].features.timestamp;
        btn.innerHTML = '<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg">' +
            '<circle cx="12" cy="12" r="9" stroke="#fff" stroke-width="2"/>' +
            '<path d="M12 7v5l3 3" stroke="#fff" stroke-width="2" stroke-linecap="round"/>' +
            '</svg>';
        btn.style.cssText = 'display:flex;align-items:center;justify-content:center;width:36px;height:36px;opacity:0.7;transition:opacity 0.2s;';
        btn.onmouseenter = function () { btn.style.opacity = '1'; };
        btn.onmouseleave = function () { btn.style.opacity = '0.7'; };
        btn.onclick = function () { copyTimestamp(); };
        ctrl.prepend(btn);
    }
    var scrollEnabled = false;
    function enableScrollVolume() {
        if (!getFeature('scroll')) { scrollEnabled = false; return; }
        if (scrollEnabled) return;
        var player = document.querySelector('.html5-video-player');
        if (!player) return;
        scrollEnabled = true;
        player.addEventListener('wheel', function (e) {
            if (!getFeature('scroll')) return;
            var v = document.querySelector('video');
            if (!v) return;
            e.preventDefault();
            var delta = e.deltaY < 0 ? 0.05 : -0.05;
            v.volume = Math.min(1, Math.max(0, v.volume + delta));
        }, { passive: false });
    }
    var qualityTriedFor = null;
    function applyAutoQuality() {
        if (!getFeature('autoQuality')) return;
        var player = document.getElementById('movie_player');
        if (!player || typeof player.getAvailableQualityLevels !== 'function') return;
        var videoId = (new URLSearchParams(location.search)).get('v') || location.pathname;
        if (qualityTriedFor === videoId) return;
        var levels = player.getAvailableQualityLevels();
        if (levels && levels.length) {
            try {
                player.setPlaybackQualityRange(levels[0], levels[0]);
                qualityTriedFor = videoId;
            } catch (e) {  }
        }
    }
    function applySubtitleStyle() {
        var s = document.getElementById('yt-subtitle-style');
        if (!getFeature('subtitleStyle')) {
            if (s) s.remove();
            return;
        }
        if (s) return;
        s = document.createElement('style');
        s.id = 'yt-subtitle-style';
        s.textContent = [
            '.ytp-caption-segment {',
            '    background-color: rgba(0,0,0,0.55) !important;',
            '    color: #ffffff !important;',
            '    font-size: 105% !important;',
            '    padding: 2px 6px !important;',
            '    border-radius: 4px !important;',
            '    text-shadow: none !important;',
            '}',
            '.caption-window { bottom: 8% !important; }',
        ].join('\n');
        document.head.appendChild(s);
    }
    function getChapterMarkers() {
        return Array.prototype.slice.call(document.querySelectorAll('.ytp-chapter-hover-container, .ytp-progress-bar-padding .ytp-chapter-title'));
    }
    function getChapterTimesFromMarkers() {
        var bar = document.querySelector('.ytp-progress-bar');
        if (!bar) return [];
        var markers = bar.querySelectorAll('.ytp-chapter-hover-container');
        var dur = (document.querySelector('video') || {}).duration || 0;
        if (!markers.length || !dur) return [];
        var barWidth = bar.getBoundingClientRect().width || 1;
        var times = [0];
        markers.forEach(function (m) {
            var left = parseFloat(m.style.left) || 0;
            var pct = left / barWidth;
            times.push(pct * dur);
        });
        return times.sort(function (a, b) { return a - b; });
    }
    function jumpChapter(direction) {
        if (!getFeature('chapterJump')) return;
        var v = document.querySelector('video');
        if (!v) return;
        var times = getChapterTimesFromMarkers();
        if (!times.length) {
            v.currentTime = Math.max(0, v.currentTime + direction * 10);
            return;
        }
        var cur = v.currentTime;
        if (direction > 0) {
            var next = times.find(function (t) { return t > cur + 0.5; });
            v.currentTime = next !== undefined ? next : v.duration;
        } else {
            var prevTimes = times.filter(function (t) { return t < cur - 0.5; });
            v.currentTime = prevTimes.length ? prevTimes[prevTimes.length - 1] : 0;
        }
    }
    function getVideoId() {
        return (new URLSearchParams(location.search)).get('v') || location.href;
    }
    function getNotesForVideo(videoId) {
        try {
            var raw = localStorage.getItem('yt-notes-' + videoId);
            return raw ? JSON.parse(raw) : [];
        } catch (e) { return []; }
    }
    function saveNoteForVideo(videoId, note) {
        var notes = getNotesForVideo(videoId);
        notes.push(note);
        localStorage.setItem('yt-notes-' + videoId, JSON.stringify(notes));
    }
    function deleteNoteForVideo(videoId, index) {
        var notes = getNotesForVideo(videoId);
        notes.splice(index, 1);
        localStorage.setItem('yt-notes-' + videoId, JSON.stringify(notes));
    }
    function quickSaveNote() {
        if (!getFeature('clipSave')) return;
        var v = document.querySelector('video');
        if (!v) return;
        var videoId = getVideoId();
        var t = Math.floor(v.currentTime);
        saveNoteForVideo(videoId, { t: t, label: formatTimestamp(t), created: Date.now() });
        flashToast(T[LANG].clipSaved + ' (' + formatTimestamp(t) + ')');
    }
    function flashToast(text) {
        var old = document.getElementById('yt-toast');
        if (old) old.remove();
        var toast = document.createElement('div');
        toast.id = 'yt-toast';
        toast.textContent = text;
        toast.style.cssText = [
            'position:fixed;bottom:24px;left:50%;transform:translateX(-50%);',
            'background:#0d0d14;color:#fff;font-size:12px;font-weight:700;',
            'padding:9px 16px;border-radius:8px;z-index:2147483647;',
            'border:1px solid #2a2a3a;box-shadow:0 8px 24px rgba(0,0,0,0.6);',
            'opacity:0;transition:opacity 0.2s;',
        ].join('');
        document.body.appendChild(toast);
        requestAnimationFrame(function () { toast.style.opacity = '1'; });
        setTimeout(function () {
            toast.style.opacity = '0';
            setTimeout(function () { toast.remove(); }, 250);
        }, 1800);
    }
    function mk(tag, style, text) {
        var e = document.createElement(tag);
        if (style) e.style.cssText = style;
        if (text !== undefined) e.textContent = text;
        return e;
    }
    function secLabel(text) {
        return mk('div', 'color:#3a3a55;font-size:9px;font-weight:900;letter-spacing:2px;text-transform:uppercase;margin:12px 0 6px 2px;', text);
    }
    function buildToggle(active) {
        var wrap  = mk('div', 'display:flex;align-items:center;flex-shrink:0;');
        var track = mk('div', 'width:32px;height:17px;border-radius:9px;background:' + (active ? '#4a90d9' : '#2a2a3a') + ';position:relative;transition:background 0.2s;');
        track.className = 'yt-toggle-track';
        var thumb = mk('div', 'position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:#fff;transform:' + (active ? 'translateX(15px)' : 'translateX(0)') + ';transition:transform 0.2s;box-shadow:0 1px 3px rgba(0,0,0,0.5);');
        thumb.className = 'yt-toggle-thumb';
        track.appendChild(thumb);
        wrap.appendChild(track);
        return wrap;
    }
    function openNotesPanel() {
        var existingSettings = document.getElementById('yt-settings-panel');
        if (existingSettings) existingSettings.remove();
        var existing = document.getElementById('yt-notes-panel');
        if (existing) { existing.remove(); return; }
        var videoId = getVideoId();
        var notes = getNotesForVideo(videoId);
        var p = mk('div', [
            'position:fixed;top:58px;right:14px;',
            'background:#0d0d14;border:1px solid #1e1e2e;border-radius:14px;',
            'padding:14px 14px 12px;z-index:2147483647;width:280px;max-height:70vh;',
            'overflow-y:auto;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;',
            'box-shadow:0 16px 48px rgba(0,0,0,0.85);user-select:none;',
        ].join(''));
        p.id = 'yt-notes-panel';
        var header = mk('div', 'display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;');
        header.appendChild(mk('span', 'color:#fff;font-size:11px;font-weight:900;letter-spacing:2px;', T[LANG].clipPanelTitle));
        var closeBtn = mk('span', 'color:#333;font-size:16px;cursor:pointer;line-height:1;padding:2px 4px;', 'x');
        closeBtn.onclick = function () { p.remove(); };
        header.appendChild(closeBtn);
        p.appendChild(header);
        if (!notes.length) {
            p.appendChild(mk('div', 'color:#555;font-size:11px;text-align:center;padding:18px 6px;line-height:1.5;', T[LANG].clipEmpty));
        } else {
            notes.slice().reverse().forEach(function (note, revIdx) {
                var realIdx = notes.length - 1 - revIdx;
                var row = mk('div', 'display:flex;align-items:center;justify-content:space-between;padding:7px 9px;border-radius:8px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.06);margin-bottom:5px;');
                row.appendChild(mk('span', 'color:#aaa;font-size:11px;font-weight:700;', note.label));
                var btnWrap = mk('div', 'display:flex;gap:6px;');
                var gotoBtn = mk('span', 'color:#4a90d9;font-size:10px;font-weight:700;cursor:pointer;', T[LANG].clipGoto);
                gotoBtn.onclick = function () {
                    var v = document.querySelector('video');
                    if (v) v.currentTime = note.t;
                };
                var delBtn = mk('span', 'color:#777;font-size:10px;font-weight:700;cursor:pointer;', T[LANG].clipDelete);
                delBtn.onclick = function () {
                    deleteNoteForVideo(videoId, realIdx);
                    p.remove();
                    openNotesPanel();
                };
                btnWrap.appendChild(gotoBtn);
                btnWrap.appendChild(delBtn);
                row.appendChild(btnWrap);
                p.appendChild(row);
            });
        }
        document.body.appendChild(p);
        requestAnimationFrame(function () {
            document.addEventListener('mousedown', function outsideClick(e) {
                if (!p.contains(e.target)) {
                    p.remove();
                    document.removeEventListener('mousedown', outsideClick);
                }
            });
        });
    }
    function openPanel() {
        var existingNotes = document.getElementById('yt-notes-panel');
        if (existingNotes) existingNotes.remove();
        var existing = document.getElementById('yt-settings-panel');
        if (existing) { existing.remove(); return; }
        var p = mk('div', [
            'position:fixed;top:58px;right:14px;',
            'background:#0d0d14;',
            'border:1px solid #1e1e2e;',
            'border-radius:14px;',
            'padding:14px 14px 12px;',
            'z-index:2147483647;',
            'width:300px;',
            'max-height:88vh;',
            'overflow-y:auto;',
            'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;',
            'box-shadow:0 16px 48px rgba(0,0,0,0.85),0 0 0 1px rgba(255,255,255,0.04);',
            'user-select:none;',
            'scrollbar-width:thin;scrollbar-color:#222 transparent;',
        ].join(''));
        p.id = 'yt-settings-panel';
        var header = mk('div', 'display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;');
        header.appendChild(mk('span', 'color:#fff;font-size:11px;font-weight:900;letter-spacing:2px;', T[LANG].panelTitle));
        var closeBtn = mk('span', 'color:#333;font-size:16px;cursor:pointer;line-height:1;padding:2px 4px;', 'x');
        closeBtn.onmouseenter = function () { closeBtn.style.color = '#aaa'; };
        closeBtn.onmouseleave = function () { closeBtn.style.color = '#333'; };
        closeBtn.onclick = function () { p.remove(); };
        header.appendChild(closeBtn);
        p.appendChild(header);
        p.appendChild(secLabel(T[LANG].themeSection));
        var themeGrid = mk('div', 'display:grid;grid-template-columns:1fr 1fr;gap:5px;margin-bottom:4px;');
        var isDefActive = isDefaultTheme(THEME);
        var defCard = mk('div',
            'grid-column:span 2;padding:8px 12px;border-radius:8px;cursor:pointer;text-align:center;font-size:10px;font-weight:700;letter-spacing:0.5px;' +
            'border:1px solid ' + (isDefActive ? 'rgba(255,255,255,0.3)' : 'rgba(255,255,255,0.07)') + ';' +
            'background:' + (isDefActive ? 'rgba(255,255,255,0.09)' : 'rgba(255,255,255,0.02)') + ';' +
            'color:' + (isDefActive ? '#fff' : '#444') + ';',
            T[LANG].defaultTheme
        );
        defCard.onclick = function () { applyTheme('__default__'); p.remove(); };
        themeGrid.appendChild(defCard);
        Object.keys(THEMES).forEach(function (key) {
            var pair   = THEMES[key];
            var bg     = pair[0];
            var accent = pair[1];
            var isAct  = key === THEME;
            var name   = (T[LANG].colors && T[LANG].colors[key]) || key;
            var card = mk('div',
                'display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:8px;cursor:pointer;' +
                'border:1px solid ' + (isAct ? accent + 'aa' : 'rgba(255,255,255,0.06)') + ';' +
                'background:' + (isAct ? bg + 'dd' : 'rgba(255,255,255,0.025)') + ';' +
                'transition:border-color 0.15s;'
            );
            var preview = mk('div',
                'width:20px;height:20px;border-radius:50%;flex-shrink:0;' +
                'background:conic-gradient(' + bg + ' 0deg 180deg,' + accent + ' 180deg 360deg);' +
                'border:1px solid rgba(255,255,255,0.12);'
            );
            var lbl = mk('span', 'font-size:10px;font-weight:700;color:' + (isAct ? '#fff' : '#555') + ';', name);
            card.appendChild(preview);
            card.appendChild(lbl);
            card.onclick = function () { applyTheme(key); p.remove(); };
            themeGrid.appendChild(card);
        });
        p.appendChild(themeGrid);
        p.appendChild(secLabel(T[LANG].charSection));
        var currentChar = localStorage.getItem('yt-character') || 'snoopy';
        var charGrid = mk('div', 'display:grid;grid-template-columns:repeat(4,1fr);gap:5px;margin-bottom:4px;');
        var charKeys = ['snoopy', 'pikachu', 'kirby', 'cat', 'alien', 'rocket', 'ghost', 'star'];
        charKeys.forEach(function (ck) {
            var isAct = ck === currentChar;
            var card = mk('div',
                'display:flex;flex-direction:column;align-items:center;gap:4px;padding:7px 3px;border-radius:8px;cursor:pointer;' +
                'border:1px solid ' + (isAct ? 'rgba(255,255,255,0.35)' : 'rgba(255,255,255,0.07)') + ';' +
                'background:' + (isAct ? 'rgba(255,255,255,0.09)' : 'rgba(255,255,255,0.02)') + ';'
            );
            var svgWrap = mk('div', 'width:30px;height:30px;display:flex;align-items:center;justify-content:center;');
            svgWrap.innerHTML = getSVG(ck);
            var name = mk('span', 'font-size:8px;font-weight:700;color:' + (isAct ? '#fff' : '#444') + ';white-space:nowrap;', T[LANG].characters[ck]);
            card.appendChild(svgWrap);
            card.appendChild(name);
            card.onclick = function () {
                localStorage.setItem('yt-character', ck);
                var old = document.getElementById('yt-char-el');
                if (old) old.remove();
                p.remove();
                openPanel();
            };
            charGrid.appendChild(card);
        });
        p.appendChild(charGrid);
        p.appendChild(secLabel(T[LANG].trailSection));
        var trailGrid = mk('div', 'display:grid;grid-template-columns:repeat(5,1fr);gap:5px;margin-bottom:4px;');
        var currentTrail = getSetting('trail-color', 'gold');
        Object.keys(TRAIL_COLORS).forEach(function (key) {
            var isAct = key === currentTrail;
            var swatch;
            if (key === 'none') {
                swatch = mk('div', 'width:22px;height:22px;border-radius:50%;border:1px dashed #555;display:flex;align-items:center;justify-content:center;color:#555;font-size:11px;', 'x');
            } else if (key === 'rainbow') {
                swatch = mk('div', 'width:22px;height:22px;border-radius:50%;background:conic-gradient(red,orange,yellow,green,cyan,blue,violet,red);');
            } else {
                swatch = mk('div', 'width:22px;height:22px;border-radius:50%;background:' + TRAIL_COLORS[key] + ';');
            }
            var card = mk('div',
                'display:flex;flex-direction:column;align-items:center;gap:3px;padding:6px 2px;border-radius:8px;cursor:pointer;' +
                'border:1px solid ' + (isAct ? 'rgba(255,255,255,0.35)' : 'rgba(255,255,255,0.07)') + ';' +
                'background:' + (isAct ? 'rgba(255,255,255,0.09)' : 'rgba(255,255,255,0.02)') + ';'
            );
            card.appendChild(swatch);
            card.onclick = function () {
                setSetting('trail-color', key);
                updateTrail();
                p.remove();
                openPanel();
            };
            trailGrid.appendChild(card);
        });
        p.appendChild(trailGrid);
        p.appendChild(secLabel(T[LANG].featSection));
        var featKeys = ['loop', 'character', 'trail', 'label', 'scroll', 'pip', 'speed', 'cinema', 'timestamp', 'autoQuality', 'subtitleStyle', 'chapterJump', 'clipSave', 'miniPlayerDrag'];
        var featContainer = mk('div', 'display:flex;flex-direction:column;gap:4px;margin-bottom:8px;');
        featKeys.forEach(function (key) {
            var row = mk('div',
                'display:flex;align-items:center;justify-content:space-between;' +
                'padding:8px 10px;border-radius:8px;cursor:pointer;' +
                'background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.055);' +
                'transition:background 0.15s;'
            );
            row.onmouseenter = function () { row.style.background = 'rgba(255,255,255,0.06)'; };
            row.onmouseleave = function () { row.style.background = 'rgba(255,255,255,0.03)'; };
            var name = mk('span', 'font-size:11px;font-weight:600;color:#aaa;', T[LANG].features[key]);
            var toggle = buildToggle(getFeature(key));
            row.appendChild(name);
            row.appendChild(toggle);
            row.onclick = function () {
                var newVal = !getFeature(key);
                setFeature(key, newVal);
                toggle.querySelector('.yt-toggle-thumb').style.transform = newVal ? 'translateX(15px)' : 'translateX(0)';
                toggle.querySelector('.yt-toggle-track').style.background = newVal ? '#4a90d9' : '#2a2a3a';
                applyFeatures();
            };
            featContainer.appendChild(row);
        });
        p.appendChild(featContainer);
        p.appendChild(secLabel(T[LANG].shortcutSection));
        var scWrap = mk('div', 'display:flex;flex-direction:column;gap:3px;margin-bottom:6px;');
        T[LANG].shortcutsList.forEach(function (pair) {
            var row = mk('div', 'display:flex;align-items:center;justify-content:space-between;padding:4px 6px;');
            row.appendChild(mk('span', 'font-size:10px;color:#666;', pair[1]));
            row.appendChild(mk('span', 'font-size:9px;font-weight:800;color:#4a90d9;letter-spacing:0.3px;', pair[0]));
            scWrap.appendChild(row);
        });
        p.appendChild(scWrap);
        var notesRow = mk('div',
            'display:flex;align-items:center;justify-content:center;' +
            'padding:8px 10px;border-radius:8px;cursor:pointer;margin-bottom:6px;' +
            'background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.055);' +
            'font-size:11px;font-weight:700;color:#555;letter-spacing:0.5px;',
            T[LANG].clipPanelTitle
        );
        notesRow.onmouseenter = function () { notesRow.style.color = '#aaa'; };
        notesRow.onmouseleave = function () { notesRow.style.color = '#555'; };
        notesRow.onclick = function () { p.remove(); openNotesPanel(); };
        p.appendChild(notesRow);
        var divider = mk('div', 'border-top:1px solid #191926;margin-bottom:8px;');
        p.appendChild(divider);
        var langRow = mk('div',
            'display:flex;align-items:center;justify-content:center;' +
            'padding:8px 10px;border-radius:8px;cursor:pointer;' +
            'background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.055);' +
            'font-size:11px;font-weight:700;color:#555;letter-spacing:0.5px;',
            T[LANG].langBtn
        );
        langRow.onmouseenter = function () { langRow.style.color = '#aaa'; };
        langRow.onmouseleave = function () { langRow.style.color = '#555'; };
        langRow.onclick = function () {
            localStorage.setItem('yt-lang', LANG === 'tr' ? 'en' : 'tr');
            location.reload();
        };
        p.appendChild(langRow);
        var hint = mk('div', 'text-align:center;color:#252535;font-size:9px;font-weight:700;margin-top:8px;letter-spacing:1px;', T[LANG].shortcut);
        p.appendChild(hint);
        document.body.appendChild(p);
        requestAnimationFrame(function () {
            document.addEventListener('mousedown', function outsideClick(e) {
                if (!p.contains(e.target) && e.target.id !== 'yt-premium-label') {
                    p.remove();
                    document.removeEventListener('mousedown', outsideClick);
                }
            });
        });
    }
    function applyFeatures() {
        addLabel();
        addLoopButton();
        addPipButton();
        addSpeedSelector();
        addTimestampButton();
        applyCinemaMode();
        applySubtitleStyle();
        enableScrollVolume();
        if (!getFeature('character')) {
            var ch = document.getElementById('yt-char-el');
            if (ch) ch.remove();
            stopCharLoop();
        }
        if (!getFeature('trail')) {
            var tr = document.getElementById('yt-trail-el');
            if (tr) tr.remove();
        }
    }
    function isTypingTarget(el) {
        if (!el) return false;
        var tag = el.tagName ? el.tagName.toLowerCase() : '';
        if (tag === 'input' || tag === 'textarea' || tag === 'select') return true;
        if (el.isContentEditable) return true;
        return false;
    }
    document.addEventListener('keydown', function (e) {
        if (!(e.ctrlKey && e.shiftKey)) return;
        if (isTypingTarget(e.target)) return;
        var key = e.key.toLowerCase();
        if (key === 'd') {
            e.preventDefault();
            openPanel();
        } else if (key === 'l') {
            e.preventDefault();
            toggleLoop();
        } else if (key === 'c') {
            e.preventDefault();
            copyTimestamp();
        } else if (key === ',') {
            e.preventDefault();
            jumpChapter(-1);
        } else if (key === '.') {
            e.preventDefault();
            jumpChapter(1);
        } else if (key === 'k') {
            e.preventDefault();
            quickSaveNote();
        }
    });
    function init() {
        applyTheme(THEME);
        applyFeatures();
        injectCharacter();
    }
    setTimeout(init, 1200);
    setInterval(function () {
        injectCharacter();
        addLabel();
        addLoopButton();
        addPipButton();
        addSpeedSelector();
        addTimestampButton();
        applyCinemaMode();
        applySubtitleStyle();
        enableScrollVolume();
        applyAutoQuality();
        updateTrail();
    }, 800);
    window.addEventListener('resize', positionCharacter);
    document.addEventListener('fullscreenchange', function () {
        setTimeout(positionCharacter, 50);
    });
    document.addEventListener('timeupdate', function (e) {
        if (e.target && e.target.tagName === 'VIDEO') {
            updateTrail();
        }
    }, true);
    new MutationObserver(function () {
        setTimeout(function () {
            addLabel();
            addLoopButton();
            addPipButton();
            addSpeedSelector();
            addTimestampButton();
            injectCharacter();
            applySubtitleStyle();
            applyAutoQuality();
        }, 400);
    }).observe(document.body, { childList: true, subtree: false });
})();