адаптируй main.js для index.html и css
вот main.js  // public/js/main.js

const socket = io();

// DOM Elements
const mainContainer = document.getElementById('mainContainer');
const welcomeScreen = document.getElementById('welcomeScreen');
const streamerScreen = document.getElementById('streamerScreen');
const viewerScreen = document.getElementById('viewerScreen');
const streamScreen = document.getElementById('streamScreen');

const startStreamerBtn = document.getElementById('startStreamerBtn');
const startViewerBtn = document.getElementById('startViewerBtn');

// Стример элементы
const startStreamBtn = document.getElementById('startStreamBtn');
const endStreamBtn = document.getElementById('endStreamBtn');
const streamInfo = document.getElementById('streamInfo');
const streamLinkInput = document.getElementById('streamLink');
const localVideo = document.getElementById('localVideo');
const uploadedVideo = document.getElementById('uploadedVideo');
const sourceRadios = document.getElementsByName('source');
const fileInputContainer = document.getElementById('fileInputContainer');
const videoFileInput = document.getElementById('videoFileInput');
const videoProgress = document.getElementById('videoProgress');
const progressLabel = document.getElementById('progressLabel');

// Чат элементы
const chatContainers = document.querySelectorAll('.chatContainer');
const chatMessagesElements = document.querySelectorAll('.chatMessages');
const chatForms = document.querySelectorAll('.chatForm');
const chatInputs = document.querySelectorAll('.chatInput');

// Зритель элементы
const streamsList = document.getElementById('streamsList');
const remoteVideo = document.getElementById('remoteVideo');

// Навигация
startStreamerBtn.addEventListener('click', () => {
    welcomeScreen.style.display = 'none';
    streamerScreen.style.display = 'block';
});

startViewerBtn.addEventListener('click', () => {
    welcomeScreen.style.display = 'none';
    viewerScreen.style.display = 'block';
    fetchStreams();
});

// Общие переменные
let streamId = null;
let isStreamer = false;

// Чат функциональность
let currentStreamId = null;

// WebRTC Variables
let localStream = null;
let videoStream = null; // Используется для передачи потоков
const peers = {};
let peerConnection = null;

// Current Source: 'camera' или 'file'
let currentSource = 'camera';

// Обработка выбора источника трансляции
if (sourceRadios) {
    Array.from(sourceRadios).forEach(radio => {
        radio.addEventListener('change', () => {
            currentSource = radio.value;
            if (currentSource === 'file') {
                fileInputContainer.style.display = 'block';
            } else {
                fileInputContainer.style.display = 'none';
                // Останавливаем видео-файл при переключении обратно на камеру
                if (uploadedVideo.src) {
                    uploadedVideo.pause();
                    uploadedVideo.src = '';
                    videoStream = null;
                    uploadedVideo.style.display = 'none';
                }
            }
        });
    });
}

// Обработка загрузки видео-файла
if (videoFileInput) {
    videoFileInput.addEventListener('change', () => {
        const file = videoFileInput.files[0];
        if (file) {
            const fileURL = URL.createObjectURL(file);
            uploadedVideo.src = fileURL;
            uploadedVideo.style.display = 'block';
            uploadedVideo.load();
            uploadedVideo.play();
            uploadedVideo.onplaying = () => {
                // Захватываем поток после начала воспроизведения
                videoStream = uploadedVideo.captureStream();
                console.log('Видео-файл захвачен:', videoStream);
                // Если стрим уже начат, добавляем видео-файл к существующим соединениям
                if (streamInfo.style.display === 'block') {
                    addVideoStreamToPeers();
                }
            };

            // Обновление прогресс-бара
            uploadedVideo.ontimeupdate = () => {
                if (uploadedVideo.duration) { // Проверка на существование duration
                    const percentage = (uploadedVideo.currentTime / uploadedVideo.duration) * 100;
                    videoProgress.value = percentage;
                    progressLabel.textContent = `${Math.floor(percentage)}%`;
                }
            };

            uploadedVideo.onended = () => {
                // Автоматически останавливаем трансляцию при окончании видео-файла
                endStream();
            };
        }
    });
}

// Чат отправка сообщений для каждой формы чата
chatForms.forEach((form, index) => {
    form.addEventListener('submit', (e) => {
        e.preventDefault();
        const chatInput = chatInputs[index];
        const messageText = chatInput.value.trim();
        if (messageText) {
            const message = {
                sender: isStreamer ? 'Стример' : 'Зритель',
                text: messageText
            };
            socket.emit('chat-message', { streamId: currentStreamId, message });
            chatInput.value = '';
            // Не вызываем addChatMessage() здесь, поскольку сообщения приходят через сокеты
        }
    });
});

// Отображение сообщения в чате
function addChatMessage(chatMessages, message) {
    const messageElem = document.createElement('div');
    messageElem.className = 'chat-message';
    messageElem.innerHTML = `<strong>${message.sender}:</strong> ${message.text}`;
    chatMessages.appendChild(messageElem);
    chatMessages.scrollTop = chatMessages.scrollHeight;
}

// Приём сообщений чата
socket.on('chat-message', (message) => {
    chatMessagesElements.forEach(chatMessages => {
        addChatMessage(chatMessages, message);
    });
});

// Приём истории чата
socket.on('chat-history', (messages) => {
    chatMessagesElements.forEach(chatMessages => {
        chatMessages.innerHTML = '';
        messages.forEach(message => {
            addChatMessage(chatMessages, message);
        });
    });
});

// Стример функциональность

// Start Stream
if (startStreamBtn) {
    startStreamBtn.addEventListener('click', async () => {
        streamId = await createStream();
        if (streamId) {
            streamInfo.style.display = 'block';
            startStreamBtn.style.display = 'none';
            endStreamBtn.style.display = 'inline-block';
            streamLinkInput.value = `${window.location.origin}?streamId=${streamId}`;
            currentStreamId = streamId;
            isStreamer = true;

            if (currentSource === 'camera') {
                // Захват видео с веб-камеры
                startLocalVideo();
            } else if (currentSource === 'file') {
                // Воспроизведение видео-файла и захват потока
                if (uploadedVideo.src) {
                    if (videoStream) {
                        // Ничего не делаем, поток уже захвачен в обработчике onplaying
                    } else {
                        alert('Ожидание захвата видео-файла...');
                    }
                } else {
                    alert('Пожалуйста, выберите видео-файл для трансляции.');
                }
            }
        }
    });
}

// End Stream
if (endStreamBtn) {
    endStreamBtn.addEventListener('click', () => {
        endStream();
    });
}

// Create Stream on Server
function createStream() {
    return new Promise((resolve) => {
        socket.emit('create-stream', (generatedStreamId) => {
            resolve(generatedStreamId);
        });
    });
}

// Start Local Video
async function startLocalVideo() {
    try {
        localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
        localVideo.srcObject = localStream;
        videoStream = localStream; // Используется для передачи в Peer Connections
        console.log('Локальный поток захвачен:', videoStream);
    } catch (err) {
        console.error('Ошибка доступа к камере/микрофону:', err);
        alert('Не удалось получить доступ к камере/микрофону.');
    }
}

// Добавление видео-файла к существующим Peer Connections
function addVideoStreamToPeers() {
    for (const viewerId in peers) {
        const peer = peers[viewerId];
        if (videoStream) {
            videoStream.getTracks().forEach(track => {
                peer.pc.addTrack(track, videoStream);
            });
            // Инициируем повторную сигнализацию
            renegotiate(peer.pc, viewerId);
        } else {
            console.warn('Нет видео-потока для добавления к Peer Connection:', viewerId);
        }
    }
}

// Повторная сигнализация
async function renegotiate(pc, viewerSocketId) {
    try {
        const offer = await pc.createOffer();
        await pc.setLocalDescription(offer);
        socket.emit('signal', { to: viewerSocketId, from: socket.id, description: pc.localDescription });
    } catch (err) {
        console.error('Ошибка повторной сигнализации:', err);
    }
}

// Handle Viewer Joined
socket.on('viewer-joined', (viewerSocketId) => {
    console.log('Новый зритель присоединился:', viewerSocketId);
    createPeerConnection(viewerSocketId, true);
});

// Handle Signaling Data
socket.on('signal', async (data) => {
    const { from, candidate, description } = data;
    if (isStreamer) {
        if (!peers[from]) {
            createPeerConnection(from, false);
        }
        const peer = peers[from];

        if (description) {
            if (description.type === 'answer') {
                await peer.pc.setRemoteDescription(new RTCSessionDescription(description));
            }
        } else if (candidate) {
            try {
                await peer.pc.addIceCandidate(new RTCIceCandidate(candidate));
            } catch (err) {
                console.error('Ошибка добавления ICE-кандидата:', err);
            }
        }
    } else {
        // Для зрителя
        if (!peerConnection) {
            createViewerPeerConnection(from);
        }

        if (description) {
            if (description.type === 'offer') {
                await peerConnection.setRemoteDescription(new RTCSessionDescription(description));
                const answer = await peerConnection.createAnswer();
                await peerConnection.setLocalDescription(answer);
                socket.emit('signal', { to: from, from: socket.id, description: peerConnection.localDescription });
            }
        } else if (candidate) {
            try {
                await peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
            } catch (err) {
                console.error('Ошибка добавления ICE-кандидата:', err);
            }
        }
    }
});

// Создание Peer Connection для стримера
function createPeerConnection(viewerSocketId, isInitiator) {
    const peer = {};
    peer.pc = new RTCPeerConnection({
        iceServers: [
            { urls: 'stun:stun.l.google.com:19302' },
            // Добавьте TURN-серверы здесь при необходимости
        ]
    });

    peers[viewerSocketId] = peer;

    // Добавление треков из videoStream в Peer Connection
    if (videoStream) {
        videoStream.getTracks().forEach(track => peer.pc.addTrack(track, videoStream));
    } else {
        console.warn('Нет видео-потока для передачи зрителю:', viewerSocketId);
    }

    // Обработка ICE-кандидатов
    peer.pc.onicecandidate = (event) => {
        if (event.candidate) {
            socket.emit('signal', { to: viewerSocketId, from: socket.id, candidate: event.candidate });
        }
    };

    // Обработка событий соединения
    peer.pc.onconnectionstatechange = () => {
        console.log(`Состояние соединения с ${viewerSocketId}:`, peer.pc.connectionState);
        if (peer.pc.connectionState === 'disconnected' || peer.pc.connectionState === 'failed' || peer.pc.connectionState === 'closed') {
            peer.pc.close();
            delete peers[viewerSocketId];
            console.log(`Соединение с ${viewerSocketId} закрыто.`);
        }
    };

    // Создание предложения, если инициатор
    if (isInitiator) {
        createOffer(peer.pc, viewerSocketId);
    }
}

// Функция для создания и отправки предложения
async function createOffer(pc, viewerSocketId) {
    try {
        const offer = await pc.createOffer();
        await pc.setLocalDescription(offer);
        socket.emit('signal', { to: viewerSocketId, from: socket.id, description: pc.localDescription });
    } catch (err) {
        console.error('Ошибка создания предложения:', err);
    }
}

// Закрытие всех Peer Connections и остановка трансляции
function endStream() {
    // Закрытие всех peer connections
    for (const viewerId in peers) {
        peers[viewerId].pc.close();
        delete peers[viewerId];
    }

    // Остановить все локальные треки
    if (localStream) {
        localStream.getTracks().forEach(track => track.stop());
        localStream = null;
        localVideo.srcObject = null;
    }

    // Останавливаем видео-файл
    if (uploadedVideo.src) {
        uploadedVideo.pause();
        uploadedVideo.src = '';
        videoStream = null;
        uploadedVideo.style.display = 'none';
    }

    // Уведомление сервера о завершении трансляции
    socket.emit('end-stream', streamId);

    // Сброс UI
    streamInfo.style.display = 'none';
    startStreamBtn.style.display = 'inline-block';
    endStreamBtn.style.display = 'none';
    streamLinkInput.value = '';
    videoProgress.value = 0;
    progressLabel.textContent = '0%';
    chatMessagesElements.forEach(chatMessages => {
        chatMessages.innerHTML = '';
    });

    isStreamer = false;
    currentStreamId = null;
}

// Зритель функциональность

function fetchStreams() {
    fetch(`/streams`)
        .then(response => response.json())
        .then(data => {
            renderStreams(data);
        })
        .catch(err => {
            console.error('Ошибка при получении списка трансляций:', err);
        });
}

// Render streams list
function renderStreams(streams) {
    streamsList.innerHTML = '';
    if (streams.length === 0) {
        streamsList.innerHTML = '<p>Нет активных трансляций в данный момент.</p>';
        return;
    }
    streams.forEach(streamId => {
        const listItem = document.createElement('li');
        listItem.className = 'stream-item';

        const button = document.createElement('button');
        button.textContent = `Трансляция #${streamId}`;
        button.addEventListener('click', () => {
            joinStream(streamId);
        });

        listItem.appendChild(button);
        streamsList.appendChild(listItem);
    });
}

// Обновление списка трансляций в реальном времени
socket.on('update-streams', (activeStreams) => {
    if (viewerScreen.style.display === 'block') {
        renderStreams(activeStreams);
    }
});

// Присоединение к трансляции
function joinStream(streamId) {
    currentStreamId = streamId;
    isStreamer = false;

    viewerScreen.style.display = 'none';
    streamScreen.style.display = 'block';

    socket.emit('join-stream', streamId, (response) => {
        if (response.success) {
            console.log('Присоединился к трансляции:', streamId);
        } else {
            alert(response.message);
            window.location.reload();
        }
    });
}

// Создание Peer Connection для зрителя
function createViewerPeerConnection(streamerId) {
    peerConnection = new RTCPeerConnection({
        iceServers: [
            { urls: 'stun:stun.l.google.com:19302' },
            // Добавьте TURN-серверы здесь при необходимости
        ]
    });

    // Обработка ICE-кандидатов
    peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
            socket.emit('signal', { to: streamerId, from: socket.id, candidate: event.candidate });
        }
    };

    // Получение удалённого потока
    peerConnection.ontrack = (event) => {
        if (remoteVideo.srcObject !== event.streams[0]) {
            remoteVideo.srcObject = event.streams[0];
            console.log('Получен удалённый поток:', event.streams[0]);
        }
    };

    // Обработка состояний соединения
    peerConnection.onconnectionstatechange = () => {
        console.log(`Состояние соединения:`, peerConnection.connectionState);
        if (peerConnection.connectionState === 'disconnected' || peerConnection.connectionState === 'failed' || peerConnection.connectionState === 'closed') {
            remoteVideo.srcObject = null;
            peerConnection.close();
            peerConnection = null;
            alert('Соединение было прервано.');
            window.location.reload();
        }
    };
}

// Handle stream ended
socket.on('stream-ended', () => {
    alert('Трансляция завершена.');
    window.location.reload();
});

// Обработка ссылок на прямой переход к трансляции
window.addEventListener('load', () => {
    const urlParams = new URLSearchParams(window.location.search);
    const streamIdParam = urlParams.get('streamId');
    if (streamIdParam) {
        // Автоматически присоединяемся к трансляции
        welcomeScreen.style.display = 'none';
        joinStream(streamIdParam);
    }
}); вот index.html <!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Платформа трансляций</title>
    <link rel="stylesheet" href="css/styles.css">
    <!-- Подключение Google Fonts для лучшей типографики -->
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
    <!-- Подключение иконок Font Awesome -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
    <div class="container" id="mainContainer">
        <!-- Навигационная панель -->
        <nav class="navbar">
            <div class="navbar-brand">
                <i class="fas fa-stream"></i> Платформа Трансляций
            </div>
            <div class="navbar-buttons">
                <button id="startStreamerBtn" class="btn">Начать трансляцию</button>
                <button id="startViewerBtn" class="btn">Смотреть трансляции</button>
            </div>
        </nav>

        <!-- Главный экран -->
        <div id="welcomeScreen" class="screen active">
            <div class="welcome-content">
                <h1>Добро пожаловать на платформу трансляций</h1>
                <p>Начните свою трансляцию или присоединяйтесь к зрителям</p>
                <div class="buttons">
                    <button id="startStreamerBtnMain" class="btn primary">Начать трансляцию</button>
                    <button id="startViewerBtnMain" class="btn secondary">Смотреть трансляции</button>
                </div>
            </div>
        </div>

        <!-- Экран стримера -->
        <div id="streamerScreen" class="screen">
            <div class="streamer-header">
                <h2>Начать трансляцию</h2>
                <button id="backToMainFromStreamer" class="btn-icon"><i class="fas fa-arrow-left"></i></button>
            </div>
            <div class="streamer-content">
                <!-- Выбор источника трансляции -->
                <div class="source-selection">
                    <label class="radio-label">
                        <input type="radio" name="source" value="camera" checked>
                        <i class="fas fa-video"></i> Веб-камера
                    </label>
                    <label class="radio-label">
                        <input type="radio" name="source" value="file">
                        <i class="fas fa-file-video"></i> Видео-файл
                    </label>
                </div>

                <!-- Загрузка видео-файла -->
                <div id="fileInputContainer" class="file-input-container">
                    <input type="file" id="videoFileInput" accept="video/*">
                </div>

                <!-- Выбор категории трансляции -->
                <div class="category-selection">
                    <label for="category">Категория:</label>
                    <select id="category">
                        <option value="gaming">Игры</option>
                        <option value="music">Музыка</option>
                        <option value="education">Образование</option>
                        <option value="other">Другое</option>
                    </select>
                </div>

                <!-- Кнопки управления трансляцией -->
                <div class="buttons">
                    <button id="startStreamBtn" class="btn primary">Начать стрим</button>
                    <button id="endStreamBtn" class="btn danger" style="display:none;">Закончить стрим</button>
                </div>

                <!-- Информация о трансляции -->
                <div id="streamInfo" class="stream-info">
                    <p>Трансляция активна! Ссылка для зрителей:</p>
                    <input type="text" id="streamLink" readonly>
                    <!-- Прогресс-бар -->
                    <div id="progressContainer">
                        <progress id="videoProgress" value="0" max="100"></progress>
                        <span id="progressLabel">0%</span>
                    </div>
                    <!-- Чат -->
                    <div class="chatContainer">
                        <div class="chatMessages"></div>
                        <form class="chatForm">
                            <input type="text" class="chatInput" placeholder="Введите сообщение...">
                            <button type="submit" class="btn send-btn"><i class="fas fa-paper-plane"></i></button>
                        </form>
                    </div>
                </div>
            </div>
        </div>

        <!-- Экран зрителя -->
        <div id="viewerScreen" class="screen">
            <div class="viewer-header">
                <h2>Активные трансляции</h2>
                <button id="backToMainFromViewer" class="btn-icon"><i class="fas fa-arrow-left"></i></button>
            </div>
            <!-- Фильтр по категориям -->
            <div class="filter-section">
                <label for="filterCategory">Фильтр по категории:</label>
                <select id="filterCategory">
                    <option value="all">Все</option>
                    <option value="gaming">Игры</option>
                    <option value="music">Музыка</option>
                    <option value="education">Образование</option>
                    <option value="other">Другое</option>
                </select>
            </div>
            <ul id="streamsList" class="streams-list">
                <!-- Список активных стримов будет динамически заполнен -->
            </ul>
        </div>

        <!-- Экран просмотра трансляции -->
        <div id="streamScreen" class="screen">
            <div class="stream-header">
                <h2>Просмотр трансляции</h2>
                <button id="backToViewer" class="btn-icon"><i class="fas fa-arrow-left"></i></button>
            </div>
            <div id="streamContainer" class="stream-container">
                <video id="remoteVideo" autoplay playsinline controls></video>
                <!-- Чат -->
                <div class="chatContainer">
                    <div class="chatMessages"></div>
                    <form class="chatForm">
                        <input type="text" class="chatInput" placeholder="Введите сообщение...">
                        <button type="submit" class="btn send-btn"><i class="fas fa-paper-plane"></i></button>
                    </form>
                </div>
            </div>
        </div>
    </div>

    <!-- Подключение Socket.IO -->
    <script src="/socket.io/socket.io.js"></script>
    <!-- Подключение основного скрипта -->
    <script src="js/main.js"></script>
</body>
</html> вот css/* Общие стили */
body {
    margin: 0;
    font-family: 'Roboto', sans-serif;
    background-color: #18181B;
    color: #FFFFFF;
    transition: background-color 0.3s ease;
}

.container {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* Навигационная панель */
.navbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: #6441A5;
    padding: 10px 20px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.3);
    animation: slideDown 0.5s ease;
}

.navbar-brand {
    font-size: 1.5em;
    display: flex;
    align-items: center;
}

.navbar-brand i {
    margin-right: 10px;
    color: #4B0082;
}

.navbar-buttons .btn {
    margin-left: 10px;
}

@keyframes slideDown {
    from { top: -50px; opacity: 0; }
    to { top: 0; opacity: 1; }
}

/* Кнопки */
.btn {
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s ease, transform 0.2s ease;
    font-size: 1em;
}

.btn.primary {
    background-color: #9147FF;
    color: #FFFFFF;
}

.btn.primary:hover {
    background-color: #772CE8;
}

.btn.secondary {
    background-color: #2F3136;
    color: #FFFFFF;
}

.btn.secondary:hover {
    background-color: #202225;
}

.btn.danger {
    background-color: #FF4242;
    color: #FFFFFF;
}

.btn.danger:hover {
    background-color: #E63939;
}

.btn-icon {
    background: none;
    color: #FFFFFF;
    font-size: 1.2em;
}

.btn-icon:hover {
    color: #BBBBBB;
}

.btn.send-btn {
    background-color: #9147FF;
    color: #FFFFFF;
    border-radius: 50%;
    padding: 10px;
    margin-left: 5px;
}

.btn.send-btn:hover {
    background-color: #772CE8;
}

.btn:active {
    transform: scale(0.98);
}

/* Экраны */
.screen {
    flex: 1;
    padding: 20px;
    display: none;
    animation: fadeIn 0.5s ease;
}

.screen.active {
    display: block;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* Главный экран */
#welcomeScreen .welcome-content {
    text-align: center;
    margin-top: 100px;
}

#welcomeScreen h1 {
    font-size: 2.5em;
    margin-bottom: 20px;
    animation: fadeInDown 1s ease;
}

#welcomeScreen p {
    font-size: 1.2em;
    margin-bottom: 40px;
}

@keyframes fadeInDown {
    from { opacity: 0; transform: translateY(-20px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Экран стримера */
.streamer-header, .viewer-header, .stream-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.streamer-content, .viewer-content, .stream-content {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.source-selection {
    display: flex;
    gap: 20px;
    margin-bottom: 20px;
}

.radio-label {
    display: flex;
    align-items: center;
    cursor: pointer;
    font-size: 1em;
}

.radio-label i {
    margin-right: 8px;
    color: #9147FF;
}

.file-input-container {
    width: 100%;
    max-width: 400px;
}

.file-input-container input[type="file"] {
    width: 100%;
    padding: 10px;
    background-color: #2F3136;
    border: 1px solid #444;
    border-radius: 4px;
    color: #FFFFFF;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.file-input-container input[type="file"]:hover {
    background-color: #3A3D42;
}

.category-selection {
    width: 100%;
    max-width: 400px;
    margin-bottom: 20px;
}

.category-selection label {
    display: block;
    margin-bottom: 5px;
}

.category-selection select {
    width: 100%;
    padding: 10px;
    background-color: #2F3136;
    border: 1px solid #444;
    border-radius: 4px;
    color: #FFFFFF;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.category-selection select:hover {
    background-color: #3A3D42;
}

.buttons .btn {
    margin: 10px;
    width: 200px;
}

.stream-info {
    width: 100%;
    max-width: 600px;
    background-color: #2F3136;
    padding: 20px;
    border-radius: 8px;
    margin-top: 20px;
    animation: slideUp 0.5s ease;
}

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

.stream-info input[type="text"] {
    width: 100%;
    padding: 10px;
    background-color: #1E1E1E;
    border: 1px solid #444;
    border-radius: 4px;
    color: #FFFFFF;
    margin-bottom: 20px;
}

#progressContainer {
    display: flex;
    align-items: center;
    gap: 10px;
}

#videoProgress {
    width: 100%;
    height: 10px;
    appearance: none;
    border-radius: 5px;
    overflow: hidden;
}

#videoProgress::-webkit-progress-bar {
    background-color: #555;
}

#videoProgress::-webkit-progress-value {
    background-color: #9147FF;
}

.chatContainer {
    width: 100%;
    max-width: 600px;
    background-color: #2F3136;
    border-radius: 8px;
    padding: 10px;
    margin-top: 20px;
    display: flex;
    flex-direction: column;
    height: 300px;
    animation: fadeInUp 0.5s ease;
}

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

.chatMessages {
    flex: 1;
    overflow-y: auto;
    padding: 10px;
    border-bottom: 1px solid #444;
}

.chatForm {
    display: flex;
    padding: 10px 0;
}

.chatInput {
    flex: 1;
    padding: 10px;
    background-color: #1E1E1E;
    border: 1px solid #444;
    border-radius: 4px;
    color: #FFFFFF;
    margin-right: 10px;
}

.chatInput::placeholder {
    color: #888;
}

.streams-list {
    list-style: none;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 20px;
}

.stream-item {
    background-color: #2F3136;
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.stream-item:hover {
    transform: scale(1.02);
    box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}

.stream-item img {
    width: 100%;
    height: 140px;
    object-fit: cover;
}

.stream-item .stream-info {
    padding: 10px;
}

.stream-item .stream-info h3 {
    margin: 0 0 10px 0;
    font-size: 1.2em;
}

.stream-item .stream-info p {
    margin: 0;
    color: #BBBBBB;
    font-size: 0.9em;
}

/* Экран просмотра трансляции */
.stream-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.stream-container video {
    width: 100%;
    max-width: 800px;
    border-radius: 8px;
    margin-bottom: 20px;
}

/* Темы (опционально) */
/* Можно добавить переключение тем (светлая/тёмная) для большего удобства */

@media (max-width: 768px) {
    .navbar {
        flex-direction: column;
        align-items: flex-start;
    }

    .navbar-buttons {
        margin-top: 10px;
    }

    .streams-list {
        grid-template-columns: 1fr;
    }
}