we are creating free web versions of common apps based on their UI, functionality and UX, here is a json file example divided into html,css and js, create a similar json with full fuctionality of a video player, start by writing yourself a spec which includes multiple fucns and UI and UX including internet tv free stations in 2 drop downs 1 for country and another for tv station use only OECD countires and israel internet tv stations)

{
    "html": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Pro Music Player</title>\n    <link rel=\"stylesheet\" href=\"styles.css\">\n</head>\n<body>\n    <div class=\"player-container\">\n        <div class=\"player-header\">\n            <h2>Pro Music Player</h2>\n        </div>\n        <div class=\"now-playing\">\n            <div class=\"track-info\">\n                <span id=\"track-title\">No track selected</span>\n            </div>\n        </div>\n        <div class=\"controls\">\n            <button class=\"btn\" id=\"prev-btn\" title=\"Previous\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/skip-to-start.png\" alt=\"Previous\">\n            </button>\n            <button class=\"btn\" id=\"play-btn\" title=\"Play\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/play--v1.png\" alt=\"Play\">\n            </button>\n            <button class=\"btn\" id=\"pause-btn\" title=\"Pause\" style=\"display: none;\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/pause--v1.png\" alt=\"Pause\">\n            </button>\n            <button class=\"btn\" id=\"stop-btn\" title=\"Stop\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/stop.png\" alt=\"Stop\">\n            </button>\n            <button class=\"btn\" id=\"next-btn\" title=\"Next\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/end.png\" alt=\"Next\">\n            </button>\n            <button class=\"btn\" id=\"shuffle-btn\" title=\"Shuffle\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/shuffle.png\" alt=\"Shuffle\">\n            </button>\n            <button class=\"btn\" id=\"repeat-btn\" title=\"Repeat\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/repeat.png\" alt=\"Repeat\">\n            </button>\n            <button class=\"btn\" id=\"random-btn\" title=\"Random\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/questions.png\" alt=\"Random\">\n            </button>\n        </div>\n        <div class=\"progress-container\">\n            <span id=\"current-time\">0:00</span>\n            <input type=\"range\" id=\"progress-bar\" value=\"0\" min=\"0\" max=\"100\">\n            <span id=\"total-duration\">0:00</span>\n            <img src=\"https://img.icons8.com/ios-filled/24/ffffff/infinity.png\" alt=\"Infinity\" id=\"infinity-icon\">\n        </div>\n        <div class=\"volume-container\">\n            <img src=\"https://img.icons8.com/ios-filled/50/ffffff/high-volume.png\" alt=\"Volume Icon\">\n            <input type=\"range\" id=\"volume-slider\" min=\"0\" max=\"1\" step=\"0.01\" value=\"0.6\">\n            <button class=\"btn\" id=\"add-files-btn\" title=\"Open Audio File or Playlist\">\n                <img src=\"https://img.icons8.com/ios-filled/50/ffffff/add-folder.png\" alt=\"Add Files\">\n            </button>\n        </div>\n        <div class=\"radio-container\">\n            <h3>Internet Radio</h3>\n            <div class=\"radio-selection\">\n                <div class=\"genre-select\">\n                    <label for=\"genre-select\">Genre:</label>\n                    <select id=\"genre-select\">\n                        <option value=\"\">--Select Genre--</option>\n                        <option value=\"Rock\">Rock</option>\n                        <option value=\"Jazz\">Jazz</option>\n                        <option value=\"Pop\">Pop</option>\n                        <option value=\"Classical\">Classical</option>\n                        <option value=\"Electronic\">Electronic</option>\n                        <option value=\"Hip-Hop\">Hip-Hop</option>\n                        <option value=\"Country\">Country</option>\n                        <option value=\"Reggae\">Reggae</option>\n                        <option value=\"Metal\">Metal</option>\n                        <option value=\"Blues\">Blues</option>\n                    </select>\n                </div>\n                <div class=\"station-select\">\n                    <label for=\"station-select\">Station:</label>\n                    <select id=\"station-select\">\n                        <option value=\"\">--Select Station--</option>\n                    </select>\n                </div>\n            </div>\n            <div class=\"radio-inputs\">\n                <button class=\"btn\" id=\"add-radio-btn\" title=\"Add Radio\">\n                    <img src=\"https://img.icons8.com/ios-filled/50/ffffff/radio.png\" alt=\"Add Radio\">\n                </button>\n                <input type=\"text\" id=\"radio-url\" placeholder=\"Enter Radio/Podcast URL\">\n            </div>\n        </div>\n        <div class=\"playlist-container\">\n            <h3>Playlist</h3>\n            <ul id=\"playlist\">\n                <!-- Tracks will be dynamically added here -->\n            </ul>\n        </div>\n    </div>\n    <input type=\"file\" id=\"file-input\" accept=\"audio/*\" multiple style=\"display: none;\">\n    <audio id=\"audio\"></audio>\n    <script src=\"script.js\"></script>\n</body>\n</html>",
    "css": "body {\n    margin: 0;\n    padding: 0;\n    font-family: Arial, sans-serif;\n    background-color: #2c3e50;\n    color: #ecf0f1;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    height: 100vh;\n}\n.player-container {\n    background-color: #34495e;\n    padding: 20px;\n    border-radius: 10px;\n    width: 600px;\n    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);\n}\n.player-header {\n    text-align: center;\n    margin-bottom: 20px;\n    color: #ecf0f1;\n}\n.now-playing {\n    text-align: center;\n    margin-bottom: 20px;\n}\n.track-info {\n    font-size: 1.1em;\n    color: #ecf0f1;\n}\n.controls {\n    display: flex;\n    justify-content: space-around;\n    align-items: center;\n    margin-bottom: 20px;\n}\n.btn {\n    background: transparent;\n    border: none;\n    cursor: pointer;\n    margin: 0 5px;\n    outline: none;\n    position: relative;\n    border-radius: 5px;\n    padding: 5px;\n}\n.btn img {\n    width: 30px;\n    height: 30px;\n    transition: transform 0.2s;\n}\n.btn:hover img {\n    transform: scale(1.1);\n}\n.progress-container {\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    margin-bottom: 20px;\n    color: #ecf0f1;\n}\n#progress-bar {\n    width: 100%;\n    margin: 0 10px;\n    -webkit-appearance: none;\n    height: 5px;\n    background: #2c3e50;\n    border-radius: 5px;\n    outline: none;\n    cursor: pointer;\n}\n#progress-bar::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 12px;\n    height: 12px;\n    background: #ecf0f1;\n    border-radius: 50%;\n    cursor: pointer;\n}\n#progress-bar::-moz-range-thumb {\n    width: 12px;\n    height: 12px;\n    background: #ecf0f1;\n    border: none;\n    border-radius: 50%;\n    cursor: pointer;\n}\n#infinity-icon {\n    width: 24px;\n    height: 24px;\n    cursor: pointer;\n}\n.volume-container {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    margin-bottom: 20px;\n}\n.volume-container img {\n    width: 20px;\n    height: 20px;\n}\n#volume-slider {\n    width: 100px;\n    margin-left: 10px;\n    -webkit-appearance: none;\n    height: 5px;\n    background: #2c3e50;\n    border-radius: 5px;\n    outline: none;\n    cursor: pointer;\n}\n#volume-slider::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 12px;\n    height: 12px;\n    background: #ecf0f1;\n    border-radius: 50%;\n    cursor: pointer;\n}\n#volume-slider::-moz-range-thumb {\n    width: 12px;\n    height: 12px;\n    background: #ecf0f1;\n    border: none;\n    border-radius: 50%;\n    cursor: pointer;\n}\n.radio-container {\n    margin-bottom: 20px;\n}\n.radio-selection {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 10px;\n}\n.radio-selection .genre-select, .radio-selection .station-select {\n    flex: 1;\n    display: flex;\n    flex-direction: column;\n    margin-right: 10px;\n}\n.radio-selection .genre-select:last-child {\n    margin-right: 0;\n}\n.radio-selection .genre-select label, .radio-selection .station-select label {\n    margin-bottom: 5px;\n}\n.radio-selection .genre-select select, .radio-selection .station-select select {\n    padding: 5px;\n    border: 1px solid #2c3e50;\n    border-radius: 5px;\n    outline: none;\n    background-color: #ecf0f1;\n    color: #2c3e50;\n}\n.radio-inputs {\n    display: flex;\n    align-items: center;\n}\n.radio-inputs button {\n    width: 35px;\n    height: 35px;\n    padding: 5px;\n    background: transparent;\n    border: none;\n    cursor: pointer;\n    margin-right: 10px;\n    border-radius: 5px;\n}\n.radio-inputs button img {\n    width: 100%;\n    height: 100%;\n}\n.radio-inputs input {\n    flex: 1;\n    padding: 5px;\n    border: 1px solid #2c3e50;\n    border-radius: 5px;\n    outline: none;\n    color: #2c3e50;\n}\n.playlist-container {\n    max-height: 250px;\n    overflow-y: auto;\n    border: 1px solid #2c3e50;\n    border-radius: 5px;\n    padding: 10px;\n}\n.playlist-container h3 {\n    text-align: center;\n    margin-bottom: 10px;\n}\n#playlist {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n}\n#playlist li {\n    padding: 8px;\n    cursor: pointer;\n    border-bottom: 1px solid #2c3e50;\n    color: #ecf0f1;\n}\n#playlist li:hover, #playlist li.active {\n    background-color: #2c3e50;\n    color: #2ecc71;\n    font-weight: bold;\n}\n/* Scrollbar Styling */\n.playlist-container::-webkit-scrollbar {\n    width: 8px;\n}\n.playlist-container::-webkit-scrollbar-track {\n    background: #34495e;\n}\n.playlist-container::-webkit-scrollbar-thumb {\n    background-color: #2c3e50;\n    border-radius: 4px;\n}\n/* Active and Single Repeat Styles */\n.shuffle-btn.active, .repeat-btn.active, .random-btn.active {\n    filter: brightness(1.2);\n}\n.repeat-btn.single {\n    filter: brightness(1.2);\n}\n",
    "js": "(function() {\n    const audio = document.getElementById('audio');\n    const playBtn = document.getElementById('play-btn');\n    const pauseBtn = document.getElementById('pause-btn');\n    const stopBtn = document.getElementById('stop-btn');\n    const prevBtn = document.getElementById('prev-btn');\n    const nextBtn = document.getElementById('next-btn');\n    const shuffleBtn = document.getElementById('shuffle-btn');\n    const repeatBtn = document.getElementById('repeat-btn');\n    const randomBtn = document.getElementById('random-btn');\n    const addFilesBtn = document.getElementById('add-files-btn');\n    const fileInput = document.getElementById('file-input');\n    const progressBar = document.getElementById('progress-bar');\n    const currentTimeEl = document.getElementById('current-time');\n    const totalDurationEl = document.getElementById('total-duration');\n    const volumeSlider = document.getElementById('volume-slider');\n    const playlist = document.getElementById('playlist');\n    const trackTitle = document.getElementById('track-title');\n    const addRadioBtn = document.getElementById('add-radio-btn');\n    const radioUrlInput = document.getElementById('radio-url');\n    const genreSelect = document.getElementById('genre-select');\n    const stationSelect = document.getElementById('station-select');\n    const infinityIcon = document.getElementById('infinity-icon');\n\n    let tracks = [];\n    let currentTrack = 0;\n    let isShuffle = false;\n    let shuffleOrder = [];\n    let repeatMode = 'none'; // none, one, all\n    let errorHandledTracks = new Set();\n    let genres = {\n        \"Rock\": [\n            { name: \"BBC Radio 1\", url: \"https://icecast.omroep.nl/radio1-bb-mp3\" },\n            { name: \"Groove Salad\", url: \"http://icecast.somafm.com/groovesalad-128-mp3\" },\n            { name: \"Rock Antenne\", url: \"https://listen.rockantenne.de/rockantenne-high.mp3\" },\n            { name: \"Classic Rock FM\", url: \"https://stream.classicrock.com/classicrock.mp3\" },\n            { name: \"Indie Rock Radio\", url: \"https://stream.indierock.com/indierock.mp3\" }\n        ],\n        \"Jazz\": [\n            { name: \"Smooth Jazz\", url: \"http://icecast.somafm.com/groovesalad-128-mp3\" },\n            { name: \"Classic Jazz\", url: \"http://stream.publicradio.net/pnodeb/pubjazz_mp3\" },\n            { name: \"Jazz Fusion\", url: \"https://stream.jazzfusion.com/jazzfusion.mp3\" },\n            { name: \"Bebop Jazz\", url: \"https://stream.bebopjazz.com/bebopjazz.mp3\" },\n            { name: \"Vocal Jazz\", url: \"https://stream.vocaljazz.com/vocaljazz.mp3\" }\n        ],\n        \"Pop\": [\n            { name: \"Top Hits\", url: \"https://stream.pophits.com/pophits.mp3\" },\n            { name: \"Pop Classics\", url: \"https://stream.popclassics.com/popclassics.mp3\" },\n            { name: \"Teen Pop\", url: \"https://stream.teenpop.com/teenpop.mp3\" },\n            { name: \"Dance Pop\", url: \"https://stream.dancepop.com/dancepop.mp3\" },\n            { name: \"K-Pop\", url: \"https://stream.kpop.com/kpop.mp3\" }\n        ],\n        \"Classical\": [\n            { name: \"Symphony Radio\", url: \"https://stream.symphonyradio.com/symphony.mp3\" },\n            { name: \"Opera Live\", url: \"https://stream.operalive.com/opera.mp3\" },\n            { name: \"Baroque Classics\", url: \"https://stream.baroqueclassics.com/baroque.mp3\" },\n            { name: \"Contemporary Classical\", url: \"https://stream.contemporaryclassical.com/contemporary.mp3\" },\n            { name: \"Chamber Music\", url: \"https://stream.chambermusic.com/chamber.mp3\" }\n        ],\n        \"Electronic\": [\n            { name: \"EDM Radio\", url: \"https://stream.edmradio.com/edm.mp3\" },\n            { name: \"House Beats\", url: \"https://stream.housebeats.com/housebeats.mp3\" },\n            { name: \"Techno Pulse\", url: \"https://stream.technopulse.com/techno.mp3\" },\n            { name: \"Trance Waves\", url: \"https://stream.trancewaves.com/trance.mp3\" },\n            { name: \"Dubstep Zone\", url: \"https://stream.dubstepzone.com/dubstep.mp3\" }\n        ],\n        \"Hip-Hop\": [\n            { name: \"Rap Beats\", url: \"https://stream.rapbeats.com/rapbeats.mp3\" },\n            { name: \"Old School Hip-Hop\", url: \"https://stream.oldschoolhiphop.com/oldschool.mp3\" },\n            { name: \"Trap Radio\", url: \"https://stream.trapradio.com/trap.mp3\" },\n            { name: \"Freestyle Hip-Hop\", url: \"https://stream.freestylehiphop.com/freestyle.mp3\" },\n            { name: \"Underground Hip-Hop\", url: \"https://stream.undergroundhiphop.com/underground.mp3\" }\n        ],\n        \"Country\": [\n            { name: \"Country Hits\", url: \"https://stream.countryhits.com/countryhits.mp3\" },\n            { name: \"Classic Country\", url: \"https://stream.classiccountry.com/classic.mp3\" },\n            { name: \"Bluegrass Radio\", url: \"https://stream.bluegrassradio.com/bluegrass.mp3\" },\n            { name: \"Country Pop\", url: \"https://stream.countrypop.com/countrypop.mp3\" },\n            { name: \"Americana\", url: \"https://stream.americana.com/americana.mp3\" }\n        ],\n        \"Reggae\": [\n            { name: \"Reggae Vibes\", url: \"https://stream.reggaevibes.com/reggae.mp3\" },\n            { name: \"Dancehall Radio\", url: \"https://stream.dancehallradio.com/dancehall.mp3\" },\n            { name: \"Roots Reggae\", url: \"https://stream.rootsreggae.com/roots.mp3\" },\n            { name: \"Lovers Rock\", url: \"https://stream.loversrock.com/loversrock.mp3\" },\n            { name: \"Dub Reggae\", url: \"https://stream.dubreggae.com/dub.mp3\" }\n        ],\n        \"Metal\": [\n            { name: \"Heavy Metal\", url: \"https://stream.heavymetal.com/heavy.mp3\" },\n            { name: \"Thrash Metal\", url: \"https://stream.thrashmetal.com/thrash.mp3\" },\n            { name: \"Death Metal\", url: \"https://stream.deathmetal.com/death.mp3\" },\n            { name: \"Black Metal\", url: \"https://stream.blackmetal.com/black.mp3\" },\n            { name: \"Power Metal\", url: \"https://stream.powermetal.com/power.mp3\" }\n        ],\n        \"Blues\": [\n            { name: \"Blues Classics\", url: \"https://stream.bluesclassics.com/bluesclassic.mp3\" },\n            { name: \"Modern Blues\", url: \"https://stream.modernblues.com/modern.mp3\" },\n            { name: \"Chicago Blues\", url: \"https://stream.chicagoblues.com/chicago.mp3\" },\n            { name: \"Electric Blues\", url: \"https://stream.electricblues.com/electric.mp3\" },\n            { name: \"Delta Blues\", url: \"https://stream.deltablues.com/delta.mp3\" }\n        ]\n    };\n\n    // Initialize the player\n    function init() {\n        setDefaultVolume();\n        populateGenreSelect();\n        attachEventListeners();\n    }\n\n    // Set Default Volume to 60%\n    function setDefaultVolume() {\n        audio.volume = 0.6;\n        volumeSlider.value = 0.6;\n    }\n\n    // Populate Genre Dropdown\n    function populateGenreSelect() {\n        for (let genre in genres) {\n            const option = document.createElement('option');\n            option.value = genre;\n            option.textContent = genre;\n            genreSelect.appendChild(option);\n        }\n    }\n\n    // Populate Station Dropdown based on Genre\n    function populateStationSelect(selectedGenre) {\n        stationSelect.innerHTML = '<option value=\"\">--Select Station--</option>';\n        if (selectedGenre && genres[selectedGenre]) {\n            genres[selectedGenre].forEach(station => {\n                const option = document.createElement('option');\n                option.value = station.url;\n                option.textContent = station.name;\n                stationSelect.appendChild(option);\n            });\n        }\n    }\n\n    // Attach Event Listeners\n    function attachEventListeners() {\n        playBtn.addEventListener('click', playTrack);\n        pauseBtn.addEventListener('click', pauseTrack);\n        stopBtn.addEventListener('click', stopTrack);\n        nextBtn.addEventListener('click', nextTrack);\n        prevBtn.addEventListener('click', prevTrack);\n        shuffleBtn.addEventListener('click', toggleShuffle);\n        repeatBtn.addEventListener('click', toggleRepeat);\n        randomBtn.addEventListener('click', toggleRandom);\n        addFilesBtn.addEventListener('click', () => fileInput.click());\n        addRadioBtn.addEventListener('click', addRadio);\n        genreSelect.addEventListener('change', (e) => populateStationSelect(e.target.value));\n        stationSelect.addEventListener('change', selectStation);\n        fileInput.addEventListener('change', handleFileSelect);\n        audio.addEventListener('timeupdate', updateProgress);\n        progressBar.addEventListener('input', setProgress);\n        volumeSlider.addEventListener('input', updateVolume);\n        audio.addEventListener('ended', handleTrackEnd);\n        playlist.addEventListener('click', handlePlaylistClick);\n        audio.addEventListener('error', handleAudioError);\n        infinityIcon.addEventListener('click', toggleRepeat);\n    }\n\n    // Play Track\n    function playTrack() {\n        if (tracks.length === 0) return;\n        audio.play().then(() => {\n            playBtn.style.display = 'none';\n            pauseBtn.style.display = 'inline';\n            markTrackAsActive();\n        }).catch(error => {\n            console.error('Playback failed:', error);\n            if (!errorHandledTracks.has(currentTrack)) {\n                alert('Cannot play the selected media.');\n                errorHandledTracks.add(currentTrack);\n                nextTrack();\n            }\n        });\n    }\n\n    // Pause Track\n    function pauseTrack() {\n        audio.pause();\n        playBtn.style.display = 'inline';\n        pauseBtn.style.display = 'none';\n    }\n\n    // Stop Track\n    function stopTrack() {\n        audio.pause();\n        audio.currentTime = 0;\n        playBtn.style.display = 'inline';\n        pauseBtn.style.display = 'none';\n    }\n\n    // Next Track\n    function nextTrack() {\n        if (repeatMode === 'one') {\n            audio.currentTime = 0;\n            playTrack();\n            return;\n        }\n        if (isShuffle) {\n            currentTrack = getRandomTrack();\n        } else {\n            currentTrack = (currentTrack + 1) % tracks.length;\n        }\n        loadTrack(currentTrack);\n        playTrack();\n    }\n\n    // Previous Track\n    function prevTrack() {\n        if (audio.currentTime > 5) {\n            audio.currentTime = 0;\n            return;\n        }\n        if (isShuffle) {\n            currentTrack = getRandomTrack();\n        } else {\n            currentTrack = (currentTrack - 1 + tracks.length) % tracks.length;\n        }\n        loadTrack(currentTrack);\n        playTrack();\n    }\n\n    // Shuffle Track\n    function toggleShuffle() {\n        isShuffle = !isShuffle;\n        shuffleBtn.classList.toggle('active', isShuffle);\n        if (isShuffle) {\n            generateShuffleOrder();\n        } else {\n            shuffleOrder = [];\n        }\n    }\n\n    // Generate Shuffle Order\n    function generateShuffleOrder() {\n        shuffleOrder = Array.from(Array(tracks.length).keys());\n        for (let i = shuffleOrder.length - 1; i > 0; i--) {\n            const j = Math.floor(Math.random() * (i + 1));\n            [shuffleOrder[i], shuffleOrder[j]] = [shuffleOrder[j], shuffleOrder[i]];\n        }\n        currentTrack = shuffleOrder[0];\n    }\n\n    // Get Random Track\n    function getRandomTrack() {\n        return Math.floor(Math.random() * tracks.length);\n    }\n\n    // Repeat Mode\n    function toggleRepeat() {\n        if (repeatMode === 'none') {\n            repeatMode = 'all';\n            repeatBtn.title = 'Repeat All';\n            infinityIcon.style.transform = 'rotate(0deg)';\n        } else if (repeatMode === 'all') {\n            repeatMode = 'one';\n            repeatBtn.title = 'Repeat One';\n            infinityIcon.style.transform = 'rotate(90deg)';\n        } else {\n            repeatMode = 'none';\n            repeatBtn.title = 'No Repeat';\n            infinityIcon.style.transform = 'rotate(180deg)';\n        }\n        repeatBtn.classList.toggle('active', repeatMode !== 'none');\n    }\n\n    // Toggle Random (Distinct from Shuffle)\n    function toggleRandom() {\n        isRandom = !isRandom;\n        randomBtn.classList.toggle('active', isRandom);\n        // Additional logic can be implemented here if needed\n    }\n\n    // Load Track\n    function loadTrack(index) {\n        if(index >= 0 && index < tracks.length) {\n            audio.src = tracks[index].src;\n            trackTitle.textContent = tracks[index].title;\n            updateActiveTrack();\n            if (tracks[index].type === 'radio') {\n                totalDurationEl.textContent = '—';\n                currentTimeEl.textContent = '0:00';\n            } else {\n                audio.addEventListener('loadedmetadata', () => {\n                    totalDurationEl.textContent = formatTime(audio.duration);\n                }, { once: true });\n            }\n        }\n    }\n\n    // Update Active Track in Playlist\n    function updateActiveTrack() {\n        Array.from(playlist.children).forEach((li, idx) => {\n            li.classList.toggle('active', idx === currentTrack);\n        });\n    }\n\n    // Update Progress Bar\n    function updateProgress() {\n        if (tracks[currentTrack].type === 'radio') {\n            const elapsedSeconds = Math.floor(audio.currentTime);\n            const mins = Math.floor(elapsedSeconds / 60);\n            const secs = elapsedSeconds % 60;\n            currentTimeEl.textContent = `${mins}:${secs < 10 ? '0' : ''}${secs}`;\n            totalDurationEl.textContent = '—';\n            progressBar.value = 0;\n            return;\n        }\n        if(audio.duration) {\n            const progressPercent = (audio.currentTime / audio.duration) * 100;\n            progressBar.value = progressPercent;\n            currentTimeEl.textContent = formatTime(audio.currentTime);\n            totalDurationEl.textContent = formatTime(audio.duration);\n        }\n    }\n\n    // Set Progress\n    function setProgress() {\n        if(audio.duration && tracks[currentTrack].type !== 'radio') {\n            const newTime = (progressBar.value / 100) * audio.duration;\n            audio.currentTime = newTime;\n        }\n    }\n\n    // Format Time in mm:ss\n    function formatTime(seconds) {\n        if (seconds === Infinity || isNaN(seconds)) return '—';\n        const mins = Math.floor(seconds / 60);\n        const secs = Math.floor(seconds % 60);\n        return `${mins}:${secs < 10 ? '0' : ''}${secs}`;\n    }\n\n    // Update Volume\n    function updateVolume() {\n        audio.volume = volumeSlider.value;\n    }\n\n    // Handle Track End\n    function handleTrackEnd() {\n        if (tracks[currentTrack].type === 'radio') {\n            // Do not attempt to play next track for radio streams\n            return;\n        }\n        if (repeatMode !== 'one') {\n            nextTrack();\n        } else {\n            audio.currentTime = 0;\n            playTrack();\n        }\n    }\n\n    // Handle Playlist Click\n    function handlePlaylistClick(event) {\n        if(event.target && event.target.nodeName === 'LI') {\n            const index = Array.from(playlist.children).indexOf(event.target);\n            if(index !== -1) {\n                currentTrack = index;\n                loadTrack(currentTrack);\n                playTrack();\n            }\n        }\n    }\n\n    // Handle Audio Errors\n    function handleAudioError() {\n        console.error('Audio playback error:', audio.error);\n        if (!errorHandledTracks.has(currentTrack)) {\n            alert('Cannot play the selected media.');\n            errorHandledTracks.add(currentTrack);\n            nextTrack();\n        }\n    }\n\n    // Handle File Selection\n    function handleFileSelect(event) {\n        const files = Array.from(event.target.files);\n        files.forEach(file => {\n            const url = URL.createObjectURL(file);\n            const track = {\n                title: file.name,\n                src: url,\n                type: 'local'\n            };\n            tracks.push(track);\n            addTrackToPlaylist(track);\n        });\n        if(currentTrack === 0 && tracks.length > 0) {\n            loadTrack(currentTrack);\n        }\n    }\n\n    // Add Track to Playlist UI\n    function addTrackToPlaylist(track) {\n        const li = document.createElement('li');\n        li.textContent = track.title;\n        playlist.appendChild(li);\n    }\n\n    // Add Radio Stream\n    function addRadio() {\n        const url = radioUrlInput.value.trim();\n        if(url && isValidURL(url)) {\n            const track = {\n                title: `Radio: ${url}`,\n                src: url,\n                type: 'radio'\n            };\n            tracks.push(track);\n            addTrackToPlaylist(track);\n            radioUrlInput.value = '';\n            loadTrack(tracks.length - 1);\n            playTrack();\n        } else {\n            alert('Please enter a valid URL.');\n        }\n    }\n\n    // Select Station from Dropdown\n    function selectStation() {\n        const url = stationSelect.value;\n        if(url && isValidURL(url)) {\n            const stationName = stationSelect.options[stationSelect.selectedIndex].text;\n            const track = {\n                title: `Radio: ${stationName}`,\n                src: url,\n                type: 'radio'\n            };\n            tracks.push(track);\n            addTrackToPlaylist(track);\n            stationSelect.value = '';\n            loadTrack(tracks.length - 1);\n            playTrack();\n        } else {\n            if (url) {\n                alert('Selected station is not available or the URL is invalid.');\n            }\n        }\n    }\n\n    // Validate URL\n    function isValidURL(string) {\n        try {\n            new URL(string);\n            return true;\n        } catch (_) {\n            return false;\n        }\n    }\n\n    // Mark Track as Active (Bold)\n    function markTrackAsActive() {\n        Array.from(playlist.children).forEach((li, idx) => {\n            li.classList.toggle('active', idx === currentTrack);\n        });\n    }\n\n    // Initialize Player\n    init();\n})();\n"
  }