Switcher Stream Channel 1.27.10.2025

Replace video feed with specified channel's video stream (Twitch, YouTube, or Kick) and provide draggable control panel functionality

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Switcher Stream Channel 1.27.10.2025
// @version      1.27.10.2025
// @license      MIT
// @description  Replace video feed with specified channel's video stream (Twitch, YouTube, or Kick) and provide draggable control panel functionality
// @author       Gullampis810
// @match        https://www.twitch.tv/*
// @icon         https://wwwcdn.cincopa.com/blogres/wp-content/uploads/2019/08/bigstock-247687237.jpg
// @run-at       document-end
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/hls.min.js 
// @namespace http://tampermonkey.net/
// ==/UserScript==
  
(function () {
    'use strict';

    const state = {
        channelName: 'tapa_tapa_mateo',
        favoriteChannels: JSON.parse(localStorage.getItem('favoriteChannels')) || [],
        channelHistory: JSON.parse(localStorage.getItem('channelHistory')) || [],
        panelColor: localStorage.getItem('panelColor') || 'rgba(255, 255, 255, 0.15)',
        buttonColor: localStorage.getItem('buttonColor') || 'rgba(255, 255, 255, 0.3)',
        panelPosition: JSON.parse(localStorage.getItem('panelPosition')) || { top: '20px', left: '20px' },
        isPanelHidden: false
    };
    let customPlayerControls = null;
    let currentVideo = null;  // Для ссылки на <video> или iframe
    state.favoriteChannels.sort((a, b) => a.localeCompare(b));
    state.channelHistory.sort((a, b) => a.localeCompare(b));

    const panel = createControlPanel();
    const toggleButton = createToggleButton();
    document.body.appendChild(panel);
    document.body.appendChild(toggleButton);

    setPanelPosition(panel, state.panelPosition);
    enableDrag(panel);
    window.addEventListener('load', loadStream);

    // Вспомогательная функция для извлечения YouTube ID из ссылки
    function getYouTubeVideoId(url) {
        const regex = /(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=))([\w-]{11})/;
        const match = url.match(regex);
        return match ? match[1] : null;
    }

    // Вспомогательная функция для извлечения имени канала Kick из ссылки
    function getKickChannelName(url) {
        const regex = /(?:https?:\/\/)?(?:www\.)?kick\.com\/([\w-]+)/;
        const match = url.match(regex);
        return match ? match[1] : null;
    }

    // Обновленная функция loadStream
  function loadStream() {
    setTimeout(() => {
        const player = document.querySelector('.video-player__container');
        if (player) {
            player.innerHTML = '';

            // Проверка на HLS (.m3u8) поток
            if (state.channelName.endsWith('.m3u8') || state.channelName.includes('.m3u8')) {
            // Принудительная замена http на https для обхода Mixed Content
                state.channelName = state.channelName.replace(/^http:/, 'https:');
                const video = document.createElement('video');
                video.style.cssText = 'width: 100%; height: 100%; border-radius: 0px;';
                video.controls = false;
                video.autoplay = true; // Добавляем автозапуск
                video.muted = false; // Не muted по умолчанию

                if (Hls.isSupported()) {
                    const hls = new Hls({
                        enableWorker: true,
                        debug: true, // Включаем отладку для логов в консоли (отключите позже, если не нужно)
                                                 lowLatencyMode: true, // Для live-стримов, как Twitch
                        backBufferLength: 90, // Увеличиваем back-buffer для обхода "дыр"
                        maxBufferHole: 0.5, // ТOLERANCE для дыр в буфере
                        manifestLoadPolicy: {
                            default: {
                                maxTimeToFirstByteMs: Infinity,
                                maxLoadTimeMs: 10000,
                                timeoutRetry: { maxNumRetry: 2, retryDelayMs: 0, maxRetryDelayMs: 0 },
                                errorRetry: { maxNumRetry: 1, retryDelayMs: 1000, maxRetryDelayMs: 8000 }
                            }
                        },
                        playlistLoadPolicy: {
                            default: {
                                maxTimeToFirstByteMs: Infinity,
                                maxLoadTimeMs: 10000,
                                timeoutRetry: { maxNumRetry: 2, retryDelayMs: 0, maxRetryDelayMs: 0 },
                                errorRetry: { maxNumRetry: 2, retryDelayMs: 1000, maxRetryDelayMs: 8000 }
                            }
                        },
                        fragLoadPolicy: {
                            default: {
                                maxTimeToFirstByteMs: Infinity,
                                maxLoadTimeMs: 20000,
                                timeoutRetry: { maxNumRetry: 4, retryDelayMs: 0, maxRetryDelayMs: 0 },
                                errorRetry: { maxNumRetry: 6, retryDelayMs: 1000, maxRetryDelayMs: 8000 }
                            }
                        },
                    });
                    hls.loadSource(state.channelName);
                    hls.attachMedia(video);
                    hls.on(Hls.Events.MANIFEST_PARSED, () => {
                        video.play().catch(error => console.error('Play error:', error)); // Обработка ошибок автозапуска
                    });
                    hls.on(Hls.Events.ERROR, (event, data) => {
                        console.error('HLS error:', data.type, data.details, data.fatal); // Детальные логи ошибок
                        if (data.fatal) {
                            switch (data.type) {
                                case Hls.ErrorTypes.NETWORK_ERROR:
                                    console.error('Fatal network error - trying to recover');
                                    hls.startLoad();
                                    break;
                                case Hls.ErrorTypes.MEDIA_ERROR:
                                    console.error('Fatal media error - trying to recover');
                                    hls.recoverMediaError();
                                    break;
                                default:
                                    hls.destroy();
                                    break;
                            }
                        }
                    });
                    hls.on(Hls.Events.FRAG_LOADING, (event, data) => {
                        console.log('Loading fragment:', data.frag.url); // Лог для отслеживания циклов
                    });
                } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
                    video.src = state.channelName;
                    video.addEventListener('loadedmetadata', () => {
                        video.play().catch(error => console.error('Native play error:', error));
                    });
                } else {
                    console.error('HLS не поддерживается в этом браузере.');
                }

                player.appendChild(video);
                currentVideo = video;
               customPlayerControls = createCustomControls(video);
               player.style.position = 'relative';  // Для overlay
               player.appendChild(customPlayerControls);
            } else {
                // Оригинальная логика для Twitch, YouTube, Kick
                const iframe = document.createElement('iframe');
                iframe.style.cssText = 'width: 100%; height: 100%; border-radius: 12px;';
                iframe.allowFullscreen = true;

                const youtubeId = getYouTubeVideoId(state.channelName);
                const kickChannel = getKickChannelName(state.channelName);
                if (youtubeId) {
                    iframe.src = `https://www.youtube.com/embed/${youtubeId}?autoplay=1&mute=0`;
                } else if (kickChannel) {
                    iframe.src = `https://kick.com/${kickChannel}?autoplay=true&muted=false`;
                } else {
                    iframe.src = `https://player.twitch.tv/?channel=${state.channelName}&parent=twitch.tv&quality=1080p&muted=false`;
                }
                player.appendChild(iframe);

            }
        }
    }, 3000); // Увеличили задержку до 3 сек для стабильности
}

function createCustomControls(mediaElement) {
    const controls = document.createElement('div');
    controls.id = 'strmx87x78ht-controls-Panel-e67jmxhj'; // Задаём id для заголовка
    controls.style.cssText = `
        position: absolute;
        bottom: 0;
        left: 30px;
        padding: 0 10px;
        box-sizing:
        border-box;
        z-index: 10;
        opacity: 0;
        transition: opacity 0.3s ease;
        background: #3a1d44;
        border: 2px solid #bf94ff;
        color: rgb(176, 226, 196);
        cursor: pointer;
        margin-right: 8px;
        height: 55px;
        width: 95%;
        display: flex;
        align-content: center;
        justify-content: center;
        align-items: center;
        border-radius: 18px;
        box-shadow: #b081ba 1px -2px 10px 2px;
    `;
    controls.addEventListener('mouseenter', () => controls.style.opacity = '1');
    controls.addEventListener('mouseleave', () => controls.style.opacity = '0');

    // Кнопка play/pause
    const playBtn = document.createElement('button');
    playBtn.id = 'playBattn-controls-panel-e67jmxhj'; // Задаём id для заголовка
    playBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24"><path fill="white" d="M8 5v14l11-7z"/></svg>';  // Иконка play
    playBtn.style.cssText = 'background: none; border: none; color: white; cursor: pointer; margin-right: 10px;';
    playBtn.addEventListener('click', () => {
        if (mediaElement.paused) {
            mediaElement.play();
            playBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24"><path fill="white" d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>';  // Pause
        } else {
            mediaElement.pause();
            playBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24"><path fill="white" d="M8 5v14l11-7z"/></svg>';
        }
    });

    // Полоса прогресса
    const progress = document.createElement('div');
    progress.id = 'progress-67hd5re-controls-panel-e67jmxhj'; // Задаём id для заголовка
    progress.style.cssText = 'flex: 1; height: 4px; background:  #bf94ff; margin: 0 10px; border-radius: 2px; position: relative;';
    const progressBar = document.createElement('div');
    progressBar.id = 'progressbar-67hd5re-controls-panel-e67jmxhj'; // Задаём id для заголовка
    progressBar.style.cssText = 'height: 100%; background: white; width: 0%; border-radius: 15px;';
    progress.appendChild(progressBar);
    // Элемент для текущего времени (слева от прогресса)
const currentTime = document.createElement('span');
currentTime.id = 'current-time-controls-panel-e67jmxhj';
currentTime.style.cssText = 'color: white; font-size: 12px; margin-right: 10px; min-width: 40px; text-align: right;';
currentTime.textContent = '0:00';

// Элемент для общей длительности (справа от прогресса)
const duration = document.createElement('span');
duration.id = 'duration-controls-panel-e67jmxhj';
duration.style.cssText = 'color: white; font-size: 12px; margin-left: 10px; min-width: 40px;';
duration.textContent = '0:00';

    //============== Слайдер громкости
    const volumeContainer = document.createElement('div');
    volumeContainer.id = 'volumeContainer-hexhg5-controls-e67jmxhj'; // Задаём id для заголовка
    volumeContainer.style.cssText = 'display: flex; align-items: center; margin-left: 10px; position: relative;';
    const volumeBtn = document.createElement('button');
    volumeBtn.id = 'volumeMuteBttn-mute-67hd5re-e67jmxhj'; // Задаём id для заголовка
    volumeBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24"><path fill="white" d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></svg>';  // Volume on
    volumeBtn.style.cssText = 'background: none; border: none; color: white; cursor: pointer; margin-right: 5px;';
    volumeBtn.addEventListener('click', () => {
        if (mediaElement.muted) {
            mediaElement.muted = false;
            volumeBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24"><path fill="white" d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></svg>';
        } else {
            mediaElement.muted = true;
            volumeBtn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24"><path fill="white" d="M12 4.59c.04-.01.08-.02.12-.02.03 0 .06.01.09.02 1.32.66 2.3 2.01 2.7 3.59H17c.55 0 1 .45 1 1v6c0 .55-.45 1-1 1h-1.91c-.4 1.58-1.38 2.93-2.7 3.59-.03.01-.06.02-.09.02-.04 0-.08-.01-.12-.02-.66-.33-1.18-.98-1.42-1.76H9c-.55 0-1-.45-1-1V9c0-.55.45-1 1-1h1.91c.24-.78.76-1.43 1.42-1.76zM19 12c0-3.87-3.13-7-7-7s-7 3.13-7 7 3.13 7 7 7 7-3.13 7-7z"/></svg>';  // Mute
        }
    });

    const volumeSlider = document.createElement('input');
    volumeSlider.id = 'volume-jeh5-Slider-hexhg5-e67jmxhj'; // Задаём id для заголовка
    volumeSlider.type = 'range';
    volumeSlider.min = 0; volumeSlider.max = 1; volumeSlider.step = 0.01; volumeSlider.value = mediaElement.volume || 1;
    volumeSlider.style.cssText = 'height: 4px; border-radius: 15px; cursor: pointer; width: 80px;';

    // Кастомные стили для ползунка (thumb)
const sliderStyle = document.createElement('style');
sliderStyle.textContent = `
    #volume-jeh5-Slider-hexhg5-e67jmxhj::-webkit-slider-thumb {
        appearance: none;
        width: 21px;
        height: 21px;
        background: #bf94ff;
        border-radius: 50%;
        cursor: pointer;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }
    #volume-jeh5-Slider-hexhg5-e67jmxhj::-moz-range-thumb {
        width: 21px;
        height: 21px;
        background: #bf94ff;
        border-radius: 50%;
        cursor: pointer;
        border: none;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }
    #volume-jeh5-Slider-hexhg5-e67jmxhj::-ms-thumb {
        width: 21px;
        height: 21px;
        background: #bf94ff;
        border-radius: 50%;
        cursor: pointer;
        box-shadow: 0 2px 4px rgba(0,0,0,0.3);
    }
`;
document.head.appendChild(sliderStyle);

    // тултип
    const tooltip = document.createElement('div');
    tooltip.style.cssText = `
      position: absolute;
      bottom: 100%;
      left: 0;
      transform: translateX(-50%);
      padding: 2px 6px;
      background: rgb(16, 68, 70);
      color: rgb(87, 235, 240) !important;
      font-size: 20px;
      border-radius: 12px;
      white-space: nowrap;
      display: none;
    `;

    // добавляем
    volumeContainer.append(volumeSlider, tooltip);

    // показываем тултип при наведении
    let tooltipTimeout;  // Для debounce скрытия

// Функция обновления тултипа
function updateTooltip(e) {
    const percent = Math.round(e.target.value * 100);
    tooltip.textContent = `${percent}%`;

    const sliderRect = e.target.getBoundingClientRect();
    const offsetX = ((e.target.value - e.target.min) / (e.target.max - e.target.min)) * sliderRect.width;
    tooltip.style.left = `${offsetX}px`;
}

// Показываем/обновляем тултип при наведении
volumeSlider.addEventListener('mouseenter', (e) => {
    updateTooltip(e);
    tooltip.style.display = 'block';
});

// Скрываем с debounce при уходе
volumeSlider.addEventListener('mouseleave', () => {
    clearTimeout(tooltipTimeout);
    tooltipTimeout = setTimeout(() => {
        tooltip.style.display = 'none';
    }, 500);  // 500 мс задержки
});

// Обновляем при перетаскивании (динамически)
volumeSlider.addEventListener('input', (e) => {
    mediaElement.volume = e.target.value;
    if (tooltip.style.display === 'block') {  // Только если видим
        updateTooltip(e);
    }
});

// Показываем сразу при клике/перетаскивании
volumeSlider.addEventListener('mousedown', (e) => {
    updateTooltip(e);
    tooltip.style.display = 'block';
    clearTimeout(tooltipTimeout);  // Отменяем скрытие
});

// Скрываем после отпускания мыши с debounce
volumeSlider.addEventListener('mouseup', () => {
    clearTimeout(tooltipTimeout);
    tooltipTimeout = setTimeout(() => {
        tooltip.style.display = 'none';
    }, 500);
});

    // Обновление прогресса
    // Обновление прогресса и времени
mediaElement.addEventListener('timeupdate', () => {
    const percent = (mediaElement.currentTime / mediaElement.duration) * 100 || 0;
    progressBar.style.width = percent + '%';

    // Форматирование времени (MM:SS)
    function formatTime(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins}:${secs.toString().padStart(2, '0')}`;
    }

    currentTime.textContent = formatTime(mediaElement.currentTime);
    if (mediaElement.duration && !isNaN(mediaElement.duration)) {
        duration.textContent = formatTime(mediaElement.duration);
    }
});

// Инициализация длительности при загрузке метаданных
mediaElement.addEventListener('loadedmetadata', () => {
    function formatTime(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins}:${secs.toString().padStart(2, '0')}`;
    }
    duration.textContent = formatTime(mediaElement.duration);
});
    progress.addEventListener('click', (e) => {
        const rect = progress.getBoundingClientRect();
        const pos = (e.clientX - rect.left) / rect.width;
        mediaElement.currentTime = pos * mediaElement.duration;
    });

    controls.append(playBtn, currentTime, progress, duration, volumeContainer);
    volumeContainer.append(volumeBtn);
    return controls;
}
    // Обновление функции createChannelInput для поддержки YouTube и Kick ссылок
    function createChannelInput() {
        const input = document.createElement('input');
        input.type = 'text';
        input.placeholder = 'Enter channel name, YouTube URL, or Kick URL';
        Object.assign(input.style, {
            width: '100%',
            marginBottom: '16px',
            padding: '12px 16px',
            borderRadius: '12px',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            backgroundColor: 'rgba(255, 255, 255, 0.1)',
            color: 'rgba(95, 255, 194, 0.9)',
            fontSize: '20px',
            backdropFilter: 'blur(10px)',
            boxShadow: '0 4px 15px rgba(0, 0, 0, 0.05)',
            transition: 'all 0.2s ease'
        });
        input.addEventListener('input', (e) => state.channelName = e.target.value.trim());
        input.addEventListener('focus', () => input.style.borderColor = 'rgba(255, 255, 255, 0.4)');
        input.addEventListener('blur', () => input.style.borderColor = 'rgba(255, 255, 255, 0.2)');
        return input;
    }

    // Остальные функции остаются без изменений
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.className = 'switcher-panel';
        Object.assign(panel.style, {
            position: 'fixed',
            width: '340px',
            padding: '20px',
            background: 'linear-gradient(45deg, #235550, #211831)',
            borderRadius: '20px',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            boxShadow: '0 8px 32px rgba(0, 0, 0, 0.1)',
            zIndex: '9999',
            transition: 'transform 0.3s ease, opacity 0.3s ease',
            cursor: 'move'
        });
        panel.style.setProperty('background', 'linear-gradient(45deg, #235550, #211831)', 'important');

        state.panelColor = 'linear-gradient(45deg, #235550, #211831)';
        localStorage.setItem('panelColor', state.panelColor);

        const content = document.createElement('div');

        const header = document.createElement('div');
        Object.assign(header.style, {
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            marginBottom: '20px',
        });

        const title = createTitle('Channel Switcher v1.27.10.2025');
        const hideBtn = document.createElement('button');
        hideBtn.textContent = '×';
        Object.assign(hideBtn.style, {
            width: '40px',
            height: '40px',
            border: 'none',
            borderRadius: '50%',
            fontSize: '24px',
            color: 'rgba(255, 255, 255, 0.8)',
            cursor: 'pointer',
            backdropFilter: 'blur(10px)',
            boxShadow: '0 4px 15px rgba(0, 0, 0, 0.1)',
            transition: 'all 0.2s ease',
            display: 'flex',
            justifyContent: 'center'
        });
        hideBtn.addEventListener('click', togglePanel);
        hideBtn.addEventListener('mouseover', () => hideBtn.style.backgroundColor = 'rgba(255, 255, 255, 0.3)');
        hideBtn.addEventListener('mouseout', () => hideBtn.style.backgroundColor = 'rgba(255, 255, 255, 0.2)');

        header.append(title, hideBtn);

        content.append(
            createChannelInput(),
            createButton('Play Channel', loadInputChannel, 'play-btn'),
            createSelect(state.favoriteChannels, 'Favorites', 'favorites-select'),
            createSelect(state.channelHistory, 'History', 'history-select'),
            createButton('Play Selected', loadSelectedChannel, 'play-selected-btn'),
            createButton('Add to Favorites', addChannelToFavorites, 'add-fav-btn'),
            createButton('Remove Favorite', removeChannelFromFavorites, 'remove-fav-btn'),
            createButton('Clear History', clearHistory, 'clear-history-btn'),
            createColorPicker('Button Color', 'button-color-picker', updateButtonColor)
        );

        panel.append(header, content);
        return panel;
    }

    function updatePanelColor(e) {
        const hex = e.target.value;
        state.panelColor = hex;
        panel.style.setProperty('background', hex, 'important');
        localStorage.setItem('panelColor', state.panelColor);
    }

    function createToggleButton() {
        const button = document.createElement('button');
        button.className = 'toggle-visibility';
        Object.assign(button.style, {
            position: 'fixed',
            top: '16px',
            left: '490px',
            width: '40px',
            height: '40px',
            backgroundColor: 'rgba(27, 173, 117, 0.2)',
            borderRadius: '50%',
            border: '1px solid rgba(80, 245, 203, 0.66)',
            cursor: 'pointer',
            zIndex: '10000',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            backdropFilter: 'blur(10px)',
            boxShadow: '0 4px 15px rgba(0, 255, 76, 0.1)',
            transition: 'all 0.2s ease'
        });
  const eyeShowSvg = `
           <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
           <title>Eye-outline SVG Icon</title>
           <g fill="currentColor" fill-rule="evenodd" clip-rule="evenodd">
           <path d="M8.25 12a3.75 3.75 0 1 1 7.5 0a3.75 3.75 0 0 1-7.5 0M12 9.75a2.25 2.25 0 1 0 0 4.5a2.25 2.25 0 0 0 0-4.5"/>
           <path d="M4.323 10.646c-.419.604-.573 1.077-.573 1.354c0 .277.154.75.573 1.354c.406.583 1.008 1.216 1.77 1.801C7.62 16.327 9.713 17.25 12 17.25s4.38-.923 5.907-2.095c.762-.585 1.364-1.218 1.77-1.801c.419-.604.573-1.077.573-1.354c0-.277-.154-.75-.573-1.354c-.406-.583-1.008-1.216-1.77-1.801C16.38 7.673 14.287 6.75 12 6.75s-4.38.923-5.907 2.095c-.762.585-1.364 1.218-1.77 1.801m.856-2.991C6.91 6.327 9.316 5.25 12 5.25s5.09 1.077 6.82 2.405c.867.665 1.583 1.407 2.089 2.136c.492.709.841 1.486.841 2.209c0 .723-.35 1.5-.841 2.209c-.506.729-1.222 1.47-2.088 2.136c-1.73 1.328-4.137 2.405-6.821 2.405s-5.09-1.077-6.82-2.405c-.867-.665-1.583-1.407-2.089-2.136C2.6 13.5 2.25 12.723 2.25 12c0-.723.35-1.5.841-2.209c.506-.729 1.222-1.47 2.088-2.136"/>
           </g>
           </svg>
        `;

        const eyeHideSvg = `
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
        <title>Eye-closed-solid SVG Icon</title>
        <path fill="currentColor" fill-rule="evenodd" d="M20.53 4.53a.75.75 0 0 0-1.06-1.06l-16 16a.75.75 0 1 0 1.06 1.06l3.035-3.035C8.883 18.103 10.392 18.5 12 18.5c2.618 0 4.972-1.051 6.668-2.353c.85-.652 1.547-1.376 2.035-2.08c.48-.692.797-1.418.797-2.067c0-.649-.317-1.375-.797-2.066c-.488-.705-1.185-1.429-2.035-2.08c-.27-.208-.558-.41-.86-.601zm-5.4 5.402l-1.1 1.098a2.25 2.25 0 0 1-3 3l-1.1 1.1a3.75 3.75 0 0 0 5.197-5.197" clip-rule="evenodd"/>
<path fill="currentColor" d="M12.67 8.31a.26.26 0 0 0 .23-.07l1.95-1.95a.243.243 0 0 0-.104-.407A10.214 10.214 0 0 0 12 5.5c-2.618 0-4.972 1.051-6.668 2.353c-.85.652-1.547 1.376-2.036 2.08c-.48.692-.796 1.418-.796 2.067c0 .649.317 1.375.796 2.066a9.287 9.287 0 0 0 1.672 1.79a.246.246 0 0 0 .332-.017l2.94-2.94a.26.26 0 0 0 .07-.23a3.75 3.75 0 0 1 4.36-4.36"/>
        </svg>
        `;

        const svgContainer = document.createElement('div');
        svgContainer.innerHTML = state.isPanelHidden ? eyeHideSvg : eyeShowSvg;
        Object.assign(svgContainer.style, {
            width: '28px',
            height: '28px',
            filter: 'brightness(100)'
        });

        button.appendChild(svgContainer);

        button.addEventListener('click', () => {
            togglePanelVisibility();
            svgContainer.innerHTML = state.isPanelHidden ? eyeHideSvg : eyeShowSvg;
        });
        button.addEventListener('mouseover', () => button.style.backgroundColor = 'rgba(255, 255, 255, 0.3)');
        button.addEventListener('mouseout', () => button.style.backgroundColor = 'rgba(255, 255, 255, 0.2)');

        return button;
    }

    function createTitle(text) {
        const title = document.createElement('h3');
        title.textContent = text;
        Object.assign(title.style, {
            margin: '0',
            fontSize: '20px',
            fontWeight: '500',
            color: 'rgba(255, 255, 255, 0.9)'
        });
        return title;
    }

    function createSelect(options, labelText, className) {
        const container = document.createElement('div');
        container.className = className;
        container.style.marginBottom = '16px';
        container.style.position = 'relative';

        const label = document.createElement('label');
        label.textContent = labelText;
        Object.assign(label.style, {
            display: 'block',
            marginBottom: '4px',
            fontSize: '12px',
            color: 'rgba(255, 255, 255, 0.7)',
            fontWeight: '500'
        });

        const selectBox = document.createElement('div');
        Object.assign(selectBox.style, {
    width: '100%',
    padding: '12px 16px',
    borderRadius: '12px',
    backgroundColor: 'rgba(255, 255, 255, 0.05)',
    color: 'rgba(255, 255, 255, 0.9)',
    border: '1px solid rgba(255, 255, 255, 0.2)',
    fontSize: '16px',
    backdropFilter: 'blur(15px)',
    boxShadow: '0 4px 15px rgba(0, 0, 0, 0.05)',
    cursor: 'pointer',
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    flexWrap: 'nowrap',  // Новое: запрещает перенос
    overflow: 'hidden'   // Новое: скрывает переполнение
});

        const selectedText = document.createElement('span');
        selectedText.textContent = options.length ? options[0] : 'No items';
        Object.assign(selectedText.style, {
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
            width: 'calc(100% - 20px)',  // Учитываем ширину стрелки (около 20px) и отступы
            display: 'block'  // Чтобы ellipsis работал корректно
        });

        const arrow = document.createElement('span');
        arrow.innerHTML = '<svg width="12" height="12" viewBox="0 0 16 16" fill="rgba(255,255,255,0.7)"><path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z"/></svg>';

        const dropdown = document.createElement('div');
        Object.assign(dropdown.style, {
            position: 'absolute',
            top: '100%',
            left: '0',
            width: '100%',
            maxHeight: '200px',
            overflowY: 'auto',
            backgroundColor: 'rgba(255, 255, 255, 0.1)',
            borderRadius: '12px',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            backdropFilter: 'blur(15px)',
            boxShadow: '0 4px 15px rgba(0, 0, 0, 0.1)',
            display: 'none',
            zIndex: '10001'
        });

        options.forEach(option => {
            const item = document.createElement('div');
            Object.assign(item.style, {
                 padding: '10px 16px',
                 color: 'rgba(255, 255, 255, 0.9)',
                 cursor: 'pointer',
                 transition: 'background-color 0.2s ease',
                 overflow: 'hidden',
                 textOverflow: 'ellipsis',
                 whiteSpace: 'nowrap',
                 width: '100%',
                 display: 'flex',
                 justifyContent: 'space-between',
                 alignItems: 'center'
             });

             const textSpan = document.createElement('span');
Object.assign(textSpan.style, {
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    flex: '1'
});
textSpan.textContent = option;

const deleteBtn = document.createElement('button');
 deleteBtn.innerHTML = `
    <svg xmlns="http://www.w3.org/2000/svg"
         width="16"
         height="16"
         shape-rendering="geometricPrecision"
         text-rendering="geometricPrecision"
         image-rendering="optimizeQuality"
         fill-rule="evenodd"
         clip-rule="evenodd"
         viewBox="0 0 456 511.82">
         <path fill="rgba(255, 117, 117, 0.83)"
               d="M48.42 140.13h361.99c17.36 0 29.82 9.78 28.08 28.17l-30.73 317.1c-1.23 13.36-8.99 26.42-25.3 26.42H76.34c-13.63-.73-23.74-9.75-25.09-24.14L20.79 168.99c-1.74-18.38 9.75-28.86 27.63-28.86zM24.49 38.15h136.47V28.1c0-15.94 10.2-28.1 27.02-28.1h81.28c17.3 0 27.65 11.77 27.65 28.01v10.14h138.66c.57 0 1.11.07 1.68.13 10.23.93 18.15 9.02 18.69 19.22.03.79.06 1.39.06 2.17v42.76c0 5.99-4.73 10.89-10.62 11.19-.54 0-1.09.03-1.63.03H11.22c-5.92 0-10.77-4.6-11.19-10.38 0-.72-.03-1.47-.03-2.23v-39.5c0-10.93 4.21-20.71 16.82-23.02 2.53-.45 5.09-.37 7.67-.37zm83.78 208.38c-.51-10.17 8.21-18.83 19.53-19.31 11.31-.49 20.94 7.4 21.45 17.57l8.7 160.62c.51 10.18-8.22 18.84-19.53 19.32-11.32.48-20.94-7.4-21.46-17.57l-8.69-160.63zm201.7-1.74c.51-10.17 10.14-18.06 21.45-17.57 11.32.48 20.04 9.14 19.53 19.31l-8.66 160.63c-.52 10.17-10.14 18.05-21.46 17.57-11.31-.48-20.04-9.14-19.53-19.32l8.67-160.62zm-102.94.87c0-10.23 9.23-18.53 20.58-18.53 11.34 0 20.58 8.3 20.58 18.53v160.63c0 10.23-9.24 18.53-20.58 18.53-11.35 0-20.58-8.3-20.58-18.53V245.66z"/>
    </svg>
`;
Object.assign(deleteBtn.style, {
    width: '20px',
    height: '20px',
    border: 'none',
    borderRadius: '50%',
    backgroundColor: 'transparent',
    color: 'rgba(255, 255, 255, 0.7)',
    fontSize: '16px',
    cursor: 'pointer',
    marginLeft: '8px',
    transition: 'color 0.2s ease'
});
deleteBtn.addEventListener('click', (e) => {
    e.stopPropagation();  // Предотвращаем клик по item
    const container = item.closest('.favorites-select, .history-select');
    const listType = container.className.includes('favorites') ? 'favorites' : 'history';
    removeFromList(option, listType);
});
deleteBtn.addEventListener('mouseover', () => deleteBtn.style.color = 'rgba(255, 255, 255, 1)');
deleteBtn.addEventListener('mouseout', () => deleteBtn.style.color = 'rgba(255, 255, 255, 0.7)');

item.appendChild(textSpan);
item.appendChild(deleteBtn);
            item.addEventListener('click', (e) => {
            if (e.target.tagName !== 'BUTTON') {
        state.channelName = option;
        selectedText.textContent = option;
        dropdown.style.display = 'none';
            }
        });
            item.addEventListener('mouseover', () => item.style.backgroundColor = 'rgba(255, 255, 255, 0.2)');
            item.addEventListener('mouseout', () => item.style.backgroundColor = 'transparent');
            dropdown.appendChild(item);
        });

        selectBox.append(selectedText, arrow);
        container.append(label, selectBox, dropdown);

        selectBox.addEventListener('click', () => {
            dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
        });

        document.addEventListener('click', (e) => {
            if (!container.contains(e.target)) {
                dropdown.style.display = 'none';
            }
        });

        return container;
    }

    function createButton(text, onClick, className) {
        const button = document.createElement('button');
        button.textContent = text;
        button.className = className;
        Object.assign(button.style, {
            width: '100%',
            marginBottom: '12px',
            padding: '14px 16px',
            backgroundColor: state.buttonColor,
            color: 'rgba(255, 255, 255, 0.9)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            borderRadius: '12px',
            fontSize: '16px',
            fontWeight: '500',
            cursor: 'pointer',
            backdropFilter: 'blur(10px)',
            boxShadow: '0 4px 15px rgba(0, 0, 0, 0.1)',
            transition: 'all 0.2s ease'
        });
        button.addEventListener('click', onClick);
        button.addEventListener('mouseover', () => button.style.backgroundColor = 'rgba(255, 255, 255, 0.4)');
        button.addEventListener('mouseout', () => button.style.backgroundColor = state.buttonColor);
        button.addEventListener('mousedown', () => button.style.transform = 'scale(0.98)');
        button.addEventListener('mouseup', () => button.style.transform = 'scale(1)');
        return button;
    }

    function createColorPicker(labelText, className, onChange) {
        const container = document.createElement('div');
        container.style.marginBottom = '16px';

        const label = document.createElement('label');
        label.textContent = labelText;
        Object.assign(label.style, {
            display: 'block',
            marginBottom: '4px',
            fontSize: '12px',
            color: 'rgba(255, 255, 255, 0.7)',
            fontWeight: '500'
        });

        const picker = document.createElement('input');
        picker.type = 'color';
        picker.className = className;
        picker.value = labelText.includes('Panel') ? rgbaToHex(state.panelColor) : rgbaToHex(state.buttonColor);
        Object.assign(picker.style, {
            width: '100%',
            height: '48px',
            padding: '0',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            borderRadius: '12px',
            cursor: 'pointer',
            backdropFilter: 'blur(10px)',
            boxShadow: '0 4px 15px rgba(0, 0, 0, 0.05)',
            transition: 'all 0.2s ease',
            background: '#8b008b00',
        });
        picker.addEventListener('input', onChange);

        container.append(label, picker);
        return container;
    }

    function rgbaToHex(rgba) {
        const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/);
        if (!match) return rgba;
        const r = parseInt(match[1]).toString(16).padStart(2, '0');
        const g = parseInt(match[2]).toString(16).padStart(2, '0');
        const b = parseInt(match[3]).toString(16).padStart(2, '0');
        return `#${r}${g}${b}`;
    }

    function updateButtonColor(e) {
        const hex = e.target.value;
        state.buttonColor = `${hex}4D`;
        localStorage.setItem('buttonColor', state.buttonColor);
        panel.querySelectorAll('button:not(.toggle-visibility)').forEach(button => {
            button.style.backgroundColor = state.buttonColor;
        });
    }

    function togglePanel() {
        state.isPanelHidden = !state.isPanelHidden;
        panel.style.transform = state.isPanelHidden ? 'scale(0.95)' : 'scale(1)';
        panel.style.opacity = state.isPanelHidden ? '0' : '1';
        panel.style.pointerEvents = state.isPanelHidden ? 'none' : 'auto';
    }

    function togglePanelVisibility() {
        const svgContainer = document.querySelector('.toggle-visibility div');
        const isHidden = panel.style.opacity === '0' || !panel.style.opacity;

        if (isHidden) {
            panel.style.transform = 'scale(1)';
            panel.style.opacity = '1';
            panel.style.pointerEvents = 'auto';
            state.isPanelHidden = false;
            svgContainer.innerHTML = `
                <svg width="28" height="28" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                    <path d="M8 4a4 4 0 0 1 4 4 4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4zm0 1.5A2.5 2.5 0 0 0 5.5 8 2.5 2.5 0 0 0 8 10.5 2.5 2.5 0 0 0 10.5 8 2.5 2.5 0 0 0 8 5.5zM16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zm-1.5 0s-2.5-4-6.5-4S1.5 8 1.5 8s2.5 4 6.5 4 6.5-4 6.5-4z"/>
                </svg>
            `;
        } else {
            panel.style.transform = 'scale(0.95)';
            panel.style.opacity = '0';
            panel.style.pointerEvents = 'none';
            state.isPanelHidden = true;
            svgContainer.innerHTML = `
                <svg width="28" height="28" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                    <path d="M2.146 2.854a.5.5 0 1 1 .708-.708l10 10a.5.5 0 0 1-.708.708l-10-10zM8 4a4 4 0 0 1 4 4 4 4 0 0 1-.672 2.176l-.672-.672A2.5 2.5 0 0 0 10.5 8 2.5 2.5 0 0 0 8 5.5a2.5 2.5 0 0 0-1.672.672l-.672-.672A4 4 0 0 1 8 4zm6.5 4s-2.5-4-6.5-4c-.89 0-1.74.192-2.52.536l-.672-.672C5.74 3.298 6.81 3 8 3c5 0 8 5.5 8 5.5s-1.896 3.446-5 4.674l-.672-.672C12.604 11.274 14.5 8.828 14.5 8zM1.5 8s2.5-4 6.5-4c.89 0 1.74.192 2.52.536l.672.672C10.26 3.298 9.19 3 8 3 3 3 0 8.5 0 8.5s1.896 3.446 5 4.674l.672-.672C3.396 11.274 1.5 8.828 1.5 8z"/>
                </svg>
            `;
        }
    }

    function loadInputChannel() {
        if (state.channelName) {
            loadStream();
            addChannelToHistory(state.channelName);
        } else {
            alert('Пожалуйста, введите имя канала, YouTube-ссылку или Kick-ссылку.');
        }
    }

    function loadSelectedChannel() {
        if (state.channelName) {
            loadStream();
            addChannelToHistory(state.channelName);
        } else {
            alert('Пожалуйста, выберите канал, YouTube-ссылку или Kick-ссылку.');
        }
    }

    function addChannelToFavorites() {
        if (state.channelName && !state.favoriteChannels.includes(state.channelName)) {
            state.favoriteChannels.push(state.channelName);
            state.favoriteChannels.sort((a, b) => a.localeCompare(b));
            localStorage.setItem('favoriteChannels', JSON.stringify(state.favoriteChannels));
            alert(`Добавлено ${state.channelName} в избранное!`);
            updateOptions(document.querySelector('.favorites-select'), state.favoriteChannels);
        } else if (!state.channelName) {
            alert('Пожалуйста, введите имя канала, YouTube-ссылку или Kick-ссылку.');
        }
    }

    function removeChannelFromFavorites() {
        if (!state.channelName) {
            alert('Пожалуйста, выберите канал, YouTube-ссылку или Kick-ссылку для удаления.');
            return;
        }
        if (!state.favoriteChannels.includes(state.channelName)) {
            alert(`${state.channelName} отсутствует в избранном.`);
            return;
        }
        state.favoriteChannels = state.favoriteChannels.filter(ch => ch !== state.channelName);
        state.favoriteChannels.sort((a, b) => a.localeCompare(b));
        localStorage.setItem('favoriteChannels', JSON.stringify(state.favoriteChannels));
        updateOptions(document.querySelector('.favorites-select'), state.favoriteChannels);
    }

    function clearHistory() {
        state.channelHistory = [];
        localStorage.setItem('channelHistory', JSON.stringify(state.channelHistory));
        updateOptions(document.querySelector('.history-select'), state.channelHistory);
    }

    function addChannelToHistory(channel) {
        if (channel && !state.channelHistory.includes(channel)) {
            state.channelHistory.push(channel);
            state.channelHistory.sort((a, b) => a.localeCompare(b));
            localStorage.setItem('channelHistory', JSON.stringify(state.channelHistory));
            updateOptions(document.querySelector('.history-select'), state.channelHistory);
        }
    }

    function updateOptions(select, options) {
           const dropdown = select.querySelector('div[style*="position: absolute"]'); // Ищем dropdown по стилю (можно добавить class для точности)
    if (!dropdown) {
        console.error('Dropdown not found in select container');
        return;
    }
    dropdown.innerHTML = '';
    const selectedText = select.querySelector('span'); // Обновляем текст выбранного, если нужно
    if (options.length === 0) {
        if (selectedText) selectedText.textContent = 'No items';
        return;
    }
    if (selectedText) selectedText.textContent = options[0]; // Устанавливаем первый как выбранный по умолчанию
    options.forEach(option => {
        const item = document.createElement('div');
Object.assign(item.style, {
     padding: '10px 16px',
     color: 'rgba(255, 255, 255, 0.9)',
     cursor: 'pointer',
     transition: 'background-color 0.2s ease',
     overflow: 'hidden',
     textOverflow: 'ellipsis',
     whiteSpace: 'nowrap',
     width: '100%',
     display: 'flex',
     justifyContent: 'space-between',
     alignItems: 'center'
 });

 const textSpan = document.createElement('span');
 Object.assign(textSpan.style, {
     overflow: 'hidden',
     textOverflow: 'ellipsis',
     whiteSpace: 'nowrap',
     flex: '1'
 });
 textSpan.textContent = option;

 const deleteBtn = document.createElement('button');
 deleteBtn.innerHTML = `
     <svg xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          shape-rendering="geometricPrecision"
          text-rendering="geometricPrecision"
          image-rendering="optimizeQuality"
          fill-rule="evenodd"
          clip-rule="evenodd"
          viewBox="0 0 456 511.82">
          <path fill="rgba(255, 117, 117, 0.83)"
                d="M48.42 140.13h361.99c17.36 0 29.82 9.78 28.08 28.17l-30.73 317.1c-1.23 13.36-8.99 26.42-25.3 26.42H76.34c-13.63-.73-23.74-9.75-25.09-24.14L20.79 168.99c-1.74-18.38 9.75-28.86 27.63-28.86zM24.49 38.15h136.47V28.1c0-15.94 10.2-28.1 27.02-28.1h81.28c17.3 0 27.65 11.77 27.65 28.01v10.14h138.66c.57 0 1.11.07 1.68.13 10.23.93 18.15 9.02 18.69 19.22.03.79.06 1.39.06 2.17v42.76c0 5.99-4.73 10.89-10.62 11.19-.54 0-1.09.03-1.63.03H11.22c-5.92 0-10.77-4.6-11.19-10.38 0-.72-.03-1.47-.03-2.23v-39.5c0-10.93 4.21-20.71 16.82-23.02 2.53-.45 5.09-.37 7.67-.37zm83.78 208.38c-.51-10.17 8.21-18.83 19.53-19.31 11.31-.49 20.94 7.4 21.45 17.57l8.7 160.62c.51 10.18-8.22 18.84-19.53 19.32-11.32.48-20.94-7.4-21.46-17.57l-8.69-160.63zm201.7-1.74c.51-10.17 10.14-18.06 21.45-17.57 11.32.48 20.04 9.14 19.53 19.31l-8.66 160.63c-.52 10.17-10.14 18.05-21.46 17.57-11.31-.48-20.04-9.14-19.53-19.32l8.67-160.62zm-102.94.87c0-10.23 9.23-18.53 20.58-18.53 11.34 0 20.58 8.3 20.58 18.53v160.63c0 10.23-9.24 18.53-20.58 18.53-11.35 0-20.58-8.3-20.58-18.53V245.66z"/>
     </svg>
 `;
 Object.assign(deleteBtn.style, {
     width: '20px',
     height: '20px',
     border: 'none',
     borderRadius: '50%',
     backgroundColor: 'transparent',
     color: 'rgba(255, 255, 255, 0.7)',
     fontSize: '16px',
     cursor: 'pointer',
     marginLeft: '8px',
     transition: 'color 0.2s ease'
 });
 deleteBtn.addEventListener('click', (e) => {
     e.stopPropagation();
     const container = dropdown.closest('.favorites-select, .history-select');
     const listType = container.className.includes('favorites') ? 'favorites' : 'history';
     removeFromList(option, listType);
 });
 deleteBtn.addEventListener('mouseover', () => deleteBtn.style.color = 'rgba(255, 255, 255, 1)');
 deleteBtn.addEventListener('mouseout', () => deleteBtn.style.color = 'rgba(255, 255, 255, 0.7)');

 item.appendChild(textSpan);
 item.appendChild(deleteBtn);
 item.addEventListener('click', (e) => {
    if (e.target.tagName !== 'BUTTON') {
        state.channelName = option;
        selectedText.textContent = option;
        dropdown.style.display = 'none';
    }
});
item.addEventListener('mouseover', () => item.style.backgroundColor = 'rgba(255, 255, 255, 0.2)');
item.addEventListener('mouseout', () => item.style.backgroundColor = 'transparent');
dropdown.appendChild(item);
    });
    }

    function enableDrag(element) {
        let isDragging = false, offsetX, offsetY;
        element.addEventListener('mousedown', (e) => {
            if (e.target.tagName !== 'BUTTON' && e.target.tagName !== 'INPUT' && e.target.tagName !== 'SELECT') {
                isDragging = true;
                offsetX = e.clientX - element.getBoundingClientRect().left;
                offsetY = e.clientY - element.getBoundingClientRect().top;
                element.style.transition = 'none';
            }
        });

        document.addEventListener('mousemove', (e) => {
            if (isDragging) {
                const newLeft = e.clientX - offsetX;
                const newTop = e.clientY - offsetY;
                element.style.left = `${newLeft}px`;
                element.style.top = `${newTop}px`;
                localStorage.setItem('panelPosition', JSON.stringify({ top: `${newTop}px`, left: `${newLeft}px` }));
            }
        });

        document.addEventListener('mouseup', () => {
            isDragging = false;
            element.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
        });
    }

    function setPanelPosition(element, position) {
        element.style.top = position.top;
        element.style.left = position.left;
    }
    function removeFromList(channel, listType) {
    if (listType === 'favorites') {
        if (state.favoriteChannels.includes(channel)) {
            state.favoriteChannels = state.favoriteChannels.filter(ch => ch !== channel);
            state.favoriteChannels.sort((a, b) => a.localeCompare(b));
            localStorage.setItem('favoriteChannels', JSON.stringify(state.favoriteChannels));
            updateOptions(document.querySelector('.favorites-select'), state.favoriteChannels);
            alert(`Удалено из избранного: ${channel}`);
        }
    } else if (listType === 'history') {
        if (state.channelHistory.includes(channel)) {
            state.channelHistory = state.channelHistory.filter(ch => ch !== channel);
            state.channelHistory.sort((a, b) => a.localeCompare(b));
            localStorage.setItem('channelHistory', JSON.stringify(state.channelHistory));
            updateOptions(document.querySelector('.history-select'), state.channelHistory);
            alert(`Удалено из истории: ${channel}`);
        }
    }
}
const style = document.createElement('style');
style.textContent = `
  iframe::-webkit-media-controls {
     display: none !important;
 }
  iframe::cue {
     display: none !important;
 }
 #playBattn-controls-panel-e67jmxhj {
    box-shadow: #bf94ff 1px -3px 10px 2px  !important;
    border-radius: 18px  !important;
    padding: 5px  !important;
    background: #26163e !important;
}

#progress-67hd5re-controls-panel-e67jmxhj {
    height: 15px !important;
    background: #624888 !important;
    border-radius: 35px !important;
}

#progressbar-67hd5re-controls-panel-e67jmxhj {
    border-radius: 51px !important;
    background: #73a48a !important;
}
input#volume-jeh5-Slider-hexhg5-e67jmxhj {
    background: #836493 !important;
    appearance: none !important;
    height: 15px !important;
}


button#volumeMuteBttn-mute-67hd5re-e67jmxhj {
    box-shadow: #bf94ff 1px -3px 10px 2px  !important;
    border-radius: 18px  !important;
    padding: 5px  !important;
    background: #26163e !important;
}
 #current-time-controls-panel-e67jmxhj {
    color: rgb(125 229 247) !important;
    font-size: 18px !important;
    margin-right: 10px;
    min-width: 40px;
    text-align: right;
}

#duration-controls-panel-e67jmxhj {
    color: rgb(125 229 247) !important;
    font-size: 18px !important;
    margin-right: 10px;
    min-width: 40px;
    text-align: right;
}
`;
document.head.appendChild(style);
})();