{"project":{"id":"EE5oRky","userId":"raj.shah.uk@gmail.com","username":null,"userPicture":null,"name":"Audio Player","visible":true,"contributors":"","githubRepo":null,"forkedFrom":null,"isTemplate":false,"tags":"","files":{"folder":"","files":[{"name":"index.html","content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Untitled</title>\n  <link rel=\"stylesheet\" href=\"style.css\">\n<script src=\"https://unpkg.com/lucide@latest/dist/umd/lucide.js\"></script>\n</head>\n<body>\n<div class=\"player\" role=\"region\" aria-label=\"Audio Player\">\n\t<div class=\"player__body\">\n\t\t<div class=\"player__screws\" aria-hidden=\"true\">\n\t\t\t<div class=\"player__screw\"></div>\n\t\t\t<div class=\"player__screw\"></div>\n\t\t\t<div class=\"player__screw\"></div>\n\t\t\t<div class=\"player__screw\"></div>\n\t\t</div>\n\n\t\t<div class=\"player__display\" role=\"status\" aria-live=\"polite\">\n\t\t\t<div class=\"player__display-inner\">\n\t\t\t\t<div class=\"player__lcd\">\n\t\t\t\t\t<div class=\"player__lcd-scanlines\" aria-hidden=\"true\"></div>\n\t\t\t\t\t<div class=\"player__info\">\n\t\t\t\t\t\t<span class=\"player__status\" id=\"playerStatus\" aria-label=\"Playback status\">STOPPED</span>\n\t\t\t\t\t\t<span class=\"player__format\" id=\"playerFormat\" aria-label=\"Audio format\">--</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"player__title\" id=\"trackTitle\" aria-label=\"Track name\">No Track Loaded</div>\n\t\t\t\t\t<div class=\"player__time-row\">\n\t\t\t\t\t\t<span class=\"player__time\" id=\"currentTime\" aria-label=\"Current time\">0:00</span>\n\t\t\t\t\t\t<div class=\"player__meter\" id=\"meterContainer\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter1\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter2\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter3\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter4\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter5\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter6\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter7\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter8\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter9\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter10\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter11\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter12\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter13\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter14\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter15\"></div>\n\t\t\t\t\t\t\t<div class=\"player__meter-bar\" id=\"meter16\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<span class=\"player__duration\" id=\"duration\" aria-label=\"Total duration\">0:00</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"player__progress-track\">\n\t\t\t\t\t\t<div class=\"player__progress-fill\" id=\"progressFill\" aria-hidden=\"true\"></div>\n\t\t\t\t\t\t<input type=\"range\" class=\"player__progress-input\" id=\"progressInput\" min=\"0\" max=\"100\" value=\"0\" step=\"0.1\" aria-label=\"Seek through track\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"0\">\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"player__brand\" aria-hidden=\"true\">\n\t\t\t<span class=\"player__brand-name\">SONARC</span>\n\t\t\t<span class=\"player__brand-model\">DX-7200</span>\n\t\t</div>\n\n\t\t<div class=\"player__controls\">\n\t\t\t<div class=\"player__transport\" role=\"group\" aria-label=\"Transport controls\">\n\t\t\t\t<button class=\"player__btn player__btn--prev\" id=\"btnPrev\" aria-label=\"Skip back 10 seconds\">\n\t\t\t\t\t<i data-lucide=\"skip-back\" aria-hidden=\"true\"></i>\n\t\t\t\t</button>\n\t\t\t\t<button class=\"player__btn player__btn--play\" id=\"btnPlay\" aria-label=\"Play\">\n\t\t\t\t\t<i data-lucide=\"play\" id=\"playIcon\" aria-hidden=\"true\"></i>\n\t\t\t\t</button>\n\t\t\t\t<button class=\"player__btn player__btn--stop\" id=\"btnStop\" aria-label=\"Stop\">\n\t\t\t\t\t<i data-lucide=\"square\" id=\"stopIcon\" aria-hidden=\"true\"></i>\n\t\t\t\t</button>\n\t\t\t\t<button class=\"player__btn player__btn--next\" id=\"btnNext\" aria-label=\"Skip forward 10 seconds\">\n\t\t\t\t\t<i data-lucide=\"skip-forward\" aria-hidden=\"true\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"player__knobs\" role=\"group\" aria-label=\"Audio adjustments\">\n\t\t\t\t<div class=\"player__knob-group\">\n\t\t\t\t\t<div class=\"player__knob\" id=\"volumeKnob\" role=\"slider\" aria-label=\"Volume\" aria-valuemin=\"0\"\n\t\t\t\t\t\taria-valuemax=\"100\" aria-valuenow=\"75\" tabindex=\"0\">\n\t\t\t\t\t\t<div class=\"player__knob-body\">\n\t\t\t\t\t\t\t<div class=\"player__knob-indicator\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"player__knob-label\" id=\"volumeLabel\">VOLUME</span>\n\t\t\t\t\t<span class=\"player__knob-value\" id=\"volumeValue\" aria-live=\"polite\">75%</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"player__knob-group\">\n\t\t\t\t\t<div class=\"player__knob\" id=\"bassKnob\" role=\"slider\" aria-label=\"Bass\" aria-valuemin=\"0\"\n\t\t\t\t\t\taria-valuemax=\"100\" aria-valuenow=\"50\" tabindex=\"0\">\n\t\t\t\t\t\t<div class=\"player__knob-body\">\n\t\t\t\t\t\t\t<div class=\"player__knob-indicator\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"player__knob-label\" id=\"bassLabel\">BASS</span>\n\t\t\t\t\t<span class=\"player__knob-value\" id=\"bassValue\" aria-live=\"polite\">50%</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"player__knob-group\">\n\t\t\t\t\t<div class=\"player__knob\" id=\"trebleKnob\" role=\"slider\" aria-label=\"Treble\" aria-valuemin=\"0\"\n\t\t\t\t\t\taria-valuemax=\"100\" aria-valuenow=\"50\" tabindex=\"0\">\n\t\t\t\t\t\t<div class=\"player__knob-body\">\n\t\t\t\t\t\t\t<div class=\"player__knob-indicator\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span class=\"player__knob-label\" id=\"trebleLabel\">TREBLE</span>\n\t\t\t\t\t<span class=\"player__knob-value\" id=\"trebleValue\" aria-live=\"polite\">50%</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"player__bottom\">\n\t\t\t<label class=\"player__load-btn\" for=\"audioFileInput\" role=\"button\" tabindex=\"0\">\n\t\t\t\t<i data-lucide=\"folder-open\" aria-hidden=\"true\"></i>\n\t\t\t\t<span>LOAD FILE</span>\n\t\t\t</label>\n\t\t\t<input type=\"file\" id=\"audioFileInput\" accept=\"audio/*\" hidden aria-label=\"Load audio file\">\n\n\t\t\t<div class=\"player__toggles\" role=\"group\" aria-label=\"Playback options\">\n\t\t\t\t<button class=\"player__toggle\" id=\"btnRepeat\" aria-label=\"Repeat\" aria-pressed=\"false\">\n\t\t\t\t\t<i data-lucide=\"repeat\" aria-hidden=\"true\"></i>\n\t\t\t\t</button>\n\t\t\t\t<button class=\"player__toggle\" id=\"btnShuffle\" aria-label=\"Shuffle\" aria-pressed=\"false\">\n\t\t\t\t\t<i data-lucide=\"shuffle\" aria-hidden=\"true\"></i>\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div class=\"player__led-group\" aria-hidden=\"true\">\n\t\t\t\t<div class=\"player__led player__led--power player__led--on\"></div>\n\t\t\t\t<span class=\"player__led-label\">PWR</span>\n\t\t\t\t<div class=\"player__led player__led--signal\" id=\"signalLed\"></div>\n\t\t\t\t<span class=\"player__led-label\">SIG</span>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<div class=\"player__speaker-grilles\" aria-hidden=\"true\">\n\t\t\t<div class=\"player__grille player__grille--left\">\n\t\t\t\t<div class=\"player__grille-holes\"></div>\n\t\t\t</div>\n\t\t\t<div class=\"player__grille player__grille--right\">\n\t\t\t\t<div class=\"player__grille-holes\"></div>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n  <script type=\"module\" src=\"main.js\"></script>\n</body>\n</html>"},{"name":"main.js","content":"// Initialize Lucide icons\nlucide.createIcons();\n\n// State\nconst state = {\n\taudio: new Audio(),\n\tisPlaying: false,\n\trepeat: false,\n\tshuffle: false,\n\tvolume: 0.75,\n\tbass: 0.5,\n\ttreble: 0.5,\n\tknobAngles: {\n\t\tvolumeKnob: 200,\n\t\tbassKnob: 135,\n\t\ttrebleKnob: 135\n\t},\n\taudioContext: null,\n\tanalyser: null,\n\tsource: null,\n\tanimFrame: null\n};\n\n// DOM refs\nconst els = {\n\tstatus: document.getElementById('playerStatus'),\n\tformat: document.getElementById('playerFormat'),\n\ttitle: document.getElementById('trackTitle'),\n\tcurrentTime: document.getElementById('currentTime'),\n\tduration: document.getElementById('duration'),\n\tprogressFill: document.getElementById('progressFill'),\n\tprogressInput: document.getElementById('progressInput'),\n\tbtnPlay: document.getElementById('btnPlay'),\n\tplayIcon: document.getElementById('playIcon'),\n\tbtnStop: document.getElementById('btnStop'),\n\tbtnPrev: document.getElementById('btnPrev'),\n\tbtnNext: document.getElementById('btnNext'),\n\tbtnRepeat: document.getElementById('btnRepeat'),\n\tbtnShuffle: document.getElementById('btnShuffle'),\n\tfileInput: document.getElementById('audioFileInput'),\n\tsignalLed: document.getElementById('signalLed'),\n\tmeterBars: Array.from({\n\t\tlength: 16\n\t}, (_, i) => document.getElementById(`meter${i + 1}`))\n};\n\n// Helpers\nfunction formatTime(s) {\n\tif (isNaN(s)) return '0:00';\n\tconst m = Math.floor(s / 60);\n\tconst sec = Math.floor(s % 60);\n\treturn `${m}:${sec.toString().padStart(2, '0')}`;\n}\n\nfunction getFileExtension(name) {\n\tconst ext = name.split('.').pop().toUpperCase();\n\treturn ext.length <= 5 ? ext : '--';\n}\n\n// Audio Context & Analyser\nfunction initAudioContext() {\n\tif (state.audioContext) return;\n\tstate.audioContext = new(window.AudioContext || window.webkitAudioContext)();\n\tstate.analyser = state.audioContext.createAnalyser();\n\tstate.analyser.fftSize = 64;\n\tstate.source = state.audioContext.createMediaElementSource(state.audio);\n\tstate.source.connect(state.analyser);\n\tstate.analyser.connect(state.audioContext.destination);\n}\n\n// Meter animation\nfunction animateMeter() {\n\tif (!state.analyser || !state.isPlaying) {\n\t\tels.meterBars.forEach(bar => {\n\t\t\tbar.style.height = '2px';\n\t\t\tbar.classList.remove('active', 'hot');\n\t\t});\n\t\treturn;\n\t}\n\n\tconst data = new Uint8Array(state.analyser.frequencyBinCount);\n\tstate.analyser.getByteFrequencyData(data);\n\n\tels.meterBars.forEach((bar, i) => {\n\t\tconst val = data[i] || 0;\n\t\tconst pct = Math.max(8, (val / 255) * 100);\n\t\tbar.style.height = pct + '%';\n\t\tbar.classList.toggle('active', val > 30);\n\t\tbar.classList.toggle('hot', val > 200);\n\t});\n\n\t// Signal LED\n\tconst avg = data.reduce((a, b) => a + b, 0) / data.length;\n\tels.signalLed.classList.toggle('player__led--on', avg > 20);\n\n\tstate.animFrame = requestAnimationFrame(animateMeter);\n}\n\n// File loading\nels.fileInput.addEventListener('change', (e) => {\n\tconst file = e.target.files[0];\n\tif (!file) return;\n\n\tstop();\n\tconst url = URL.createObjectURL(file);\n\tstate.audio.src = url;\n\tels.title.textContent = file.name.replace(/\\.[^/.]+$/, '');\n\tels.format.textContent = getFileExtension(file.name);\n\tels.status.textContent = 'READY';\n\n\tstate.audio.addEventListener('loadedmetadata', () => {\n\t\tels.duration.textContent = formatTime(state.audio.duration);\n\t\tels.progressInput.max = state.audio.duration;\n\t\tels.progressInput.setAttribute('aria-valuemax', Math.round(state.audio.duration));\n\t}, {\n\t\tonce: true\n\t});\n});\n\n// Transport controls\nfunction play() {\n\tif (!state.audio.src) return;\n\tinitAudioContext();\n\tif (state.audioContext.state === 'suspended') state.audioContext.resume();\n\tstate.audio.play();\n\tstate.isPlaying = true;\n\tels.status.textContent = 'PLAYING';\n\tels.btnPlay.classList.add('playing');\n\tels.btnPlay.setAttribute('aria-label', 'Pause');\n\tels.playIcon.setAttribute('data-lucide', 'pause');\n\tlucide.createIcons();\n\tanimateMeter();\n}\n\nfunction pause() {\n\tstate.audio.pause();\n\tstate.isPlaying = false;\n\tels.status.textContent = 'PAUSED';\n\tels.btnPlay.classList.remove('playing');\n\tels.btnPlay.setAttribute('aria-label', 'Play');\n\tels.playIcon.setAttribute('data-lucide', 'play');\n\tlucide.createIcons();\n\tcancelAnimationFrame(state.animFrame);\n\tels.signalLed.classList.remove('player__led--on');\n}\n\nfunction stop() {\n\tstate.audio.pause();\n\tstate.audio.currentTime = 0;\n\tstate.isPlaying = false;\n\tels.status.textContent = 'STOPPED';\n\tels.btnPlay.classList.remove('playing');\n\tels.btnPlay.setAttribute('aria-label', 'Play');\n\tels.playIcon.setAttribute('data-lucide', 'play');\n\tlucide.createIcons();\n\tels.progressFill.style.width = '0%';\n\tels.currentTime.textContent = '0:00';\n\tels.progressInput.value = 0;\n\tels.progressInput.setAttribute('aria-valuenow', '0');\n\tcancelAnimationFrame(state.animFrame);\n\tels.meterBars.forEach(bar => {\n\t\tbar.style.height = '2px';\n\t\tbar.classList.remove('active', 'hot');\n\t});\n\tels.signalLed.classList.remove('player__led--on');\n}\n\nels.btnPlay.addEventListener('click', () => {\n\tstate.isPlaying ? pause() : play();\n});\n\nels.btnStop.addEventListener('click', stop);\n\nels.btnPrev.addEventListener('click', () => {\n\tstate.audio.currentTime = Math.max(0, state.audio.currentTime - 10);\n});\n\nels.btnNext.addEventListener('click', () => {\n\tstate.audio.currentTime = Math.min(state.audio.duration || 0, state.audio.currentTime + 10);\n});\n\n// Progress\nstate.audio.addEventListener('timeupdate', () => {\n\tif (!state.audio.duration) return;\n\tconst pct = (state.audio.currentTime / state.audio.duration) * 100;\n\tels.progressFill.style.width = pct + '%';\n\tels.currentTime.textContent = formatTime(state.audio.currentTime);\n\tels.progressInput.value = state.audio.currentTime;\n\tels.progressInput.setAttribute('aria-valuenow', Math.round(state.audio.currentTime));\n});\n\nels.progressInput.addEventListener('input', (e) => {\n\tstate.audio.currentTime = parseFloat(e.target.value);\n});\n\nstate.audio.addEventListener('ended', () => {\n\tif (state.repeat) {\n\t\tstate.audio.currentTime = 0;\n\t\tstate.audio.play();\n\t} else {\n\t\tstop();\n\t}\n});\n\n// Toggles\nels.btnRepeat.addEventListener('click', () => {\n\tstate.repeat = !state.repeat;\n\tels.btnRepeat.classList.toggle('active', state.repeat);\n\tels.btnRepeat.setAttribute('aria-pressed', state.repeat.toString());\n});\n\nels.btnShuffle.addEventListener('click', () => {\n\tstate.shuffle = !state.shuffle;\n\tels.btnShuffle.classList.toggle('active', state.shuffle);\n\tels.btnShuffle.setAttribute('aria-pressed', state.shuffle.toString());\n});\n\n// Load button keyboard support\nconst loadBtn = document.querySelector('.player__load-btn');\nloadBtn.addEventListener('keydown', (e) => {\n\tif (e.key === 'Enter' || e.key === ' ') {\n\t\te.preventDefault();\n\t\tels.fileInput.click();\n\t}\n});\n\n// Knobs - rotary drag with keyboard support\nfunction initKnob(knobId, valueElId, onChange) {\n\tconst knob = document.getElementById(knobId);\n\tconst body = knob.querySelector('.player__knob-body');\n\tconst valueEl = document.getElementById(valueElId);\n\tlet dragging = false;\n\tlet startY, startAngle;\n\n\tconst minAngle = 30;\n\tconst maxAngle = 330;\n\n\tfunction setAngle(angle) {\n\t\tangle = Math.max(minAngle, Math.min(maxAngle, angle));\n\t\tstate.knobAngles[knobId] = angle;\n\t\tbody.style.transform = `rotate(${angle}deg)`;\n\t\tconst normalized = (angle - minAngle) / (maxAngle - minAngle);\n\t\tconst pctVal = Math.round(normalized * 100);\n\t\tif (valueEl) valueEl.textContent = pctVal + '%';\n\t\tknob.setAttribute('aria-valuenow', pctVal);\n\t\tonChange(normalized);\n\t}\n\n\tsetAngle(state.knobAngles[knobId]);\n\n\tknob.addEventListener('mousedown', (e) => {\n\t\tdragging = true;\n\t\tstartY = e.clientY;\n\t\tstartAngle = state.knobAngles[knobId];\n\t\te.preventDefault();\n\t});\n\n\tknob.addEventListener('touchstart', (e) => {\n\t\tdragging = true;\n\t\tstartY = e.touches[0].clientY;\n\t\tstartAngle = state.knobAngles[knobId];\n\t\te.preventDefault();\n\t}, {\n\t\tpassive: false\n\t});\n\n\twindow.addEventListener('mousemove', (e) => {\n\t\tif (!dragging) return;\n\t\tconst delta = startY - e.clientY;\n\t\tsetAngle(startAngle + delta * 0.8);\n\t});\n\n\twindow.addEventListener('touchmove', (e) => {\n\t\tif (!dragging) return;\n\t\tconst delta = startY - e.touches[0].clientY;\n\t\tsetAngle(startAngle + delta * 0.8);\n\t});\n\n\twindow.addEventListener('mouseup', () => {\n\t\tdragging = false;\n\t});\n\twindow.addEventListener('touchend', () => {\n\t\tdragging = false;\n\t});\n\n\t// Mouse wheel support\n\tknob.addEventListener('wheel', (e) => {\n\t\te.preventDefault();\n\t\tconst delta = e.deltaY > 0 ? -8 : 8;\n\t\tsetAngle(state.knobAngles[knobId] + delta);\n\t}, {\n\t\tpassive: false\n\t});\n\n\t// Keyboard support for knobs\n\tknob.addEventListener('keydown', (e) => {\n\t\tconst step = 10;\n\t\tif (e.key === 'ArrowUp' || e.key === 'ArrowRight') {\n\t\t\te.preventDefault();\n\t\t\tsetAngle(state.knobAngles[knobId] + step);\n\t\t} else if (e.key === 'ArrowDown' || e.key === 'ArrowLeft') {\n\t\t\te.preventDefault();\n\t\t\tsetAngle(state.knobAngles[knobId] - step);\n\t\t} else if (e.key === 'Home') {\n\t\t\te.preventDefault();\n\t\t\tsetAngle(minAngle);\n\t\t} else if (e.key === 'End') {\n\t\t\te.preventDefault();\n\t\t\tsetAngle(maxAngle);\n\t\t}\n\t});\n}\n\ninitKnob('volumeKnob', 'volumeValue', (val) => {\n\tstate.volume = val;\n\tstate.audio.volume = val;\n});\n\ninitKnob('bassKnob', 'bassValue', (val) => {\n\tstate.bass = val;\n});\n\ninitKnob('trebleKnob', 'trebleValue', (val) => {\n\tstate.treble = val;\n});\n\n// Set initial volume\nstate.audio.volume = state.volume;"},{"name":"style.css","content":"@import url('https://fonts.googleapis.com/css2?family=VT323&family=Orbitron:wght@400;700;900&family=Michroma&display=swap');\n\n:root {\n\tcolor-scheme: dark;\n\t--chassis: #2a2a2e;\n\t--chassis-light: #3a3a40;\n\t--chassis-dark: #1a1a1e;\n\t--display-bg: #0a1a0a;\n\t--display-text: #33ff66;\n\t--display-dim: #1a6633;\n\t--accent: #ff6633;\n\t--accent-glow: #ff663366;\n\t--btn-face: #3a3a40;\n\t--btn-highlight: #55555a;\n\t--btn-shadow: #111114;\n\t--knob-body: #444448;\n\t--knob-edge: #2a2a2e;\n\t--led-green: #33ff66;\n\t--led-red: #ff3333;\n\t--screw: #888;\n}\n\n* {\n\tbox-sizing: border-box;\n\tmargin: 0;\n\tpadding: 0;\n}\n\nbody {\n\tmin-height: 100vh;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbackground: #111;\n\tbackground-image:\n\t\tradial-gradient(ellipse at 30% 20%, #1a1a2e 0%, transparent 50%),\n\t\tradial-gradient(ellipse at 70% 80%, #1e1a1a 0%, transparent 50%);\n\tfont-family: 'Michroma', sans-serif;\n\tpadding: 20px;\n}\n\n.player {\n\twidth: 100%;\n\tmax-width: 580px;\n\tperspective: 800px;\n}\n\n.player__body {\n\tposition: relative;\n\tbackground: var(--chassis);\n\tborder-radius: 18px;\n\tpadding: 28px 24px 20px;\n\tbox-shadow:\n\t\t0 2px 0 var(--chassis-light),\n\t\t0 -2px 0 var(--chassis-dark),\n\t\tinset 0 1px 0 rgba(255, 255, 255, 0.06),\n\t\t0 20px 60px rgba(0, 0, 0, 0.7),\n\t\t0 2px 8px rgba(0, 0, 0, 0.5);\n\tbackground-image:\n\t\trepeating-linear-gradient(0deg,\n\t\t\ttransparent,\n\t\t\ttransparent 2px,\n\t\t\trgba(255, 255, 255, 0.008) 2px,\n\t\t\trgba(255, 255, 255, 0.008) 4px),\n\t\tlinear-gradient(180deg, var(--chassis-light) 0%, var(--chassis) 15%, var(--chassis-dark) 100%);\n\tborder: 1px solid #444;\n\tborder-bottom-color: #111;\n}\n\n/* Screws */\n.player__screws {\n\tposition: absolute;\n\tinset: 0;\n\tpointer-events: none;\n}\n\n.player__screw {\n\tposition: absolute;\n\twidth: 10px;\n\theight: 10px;\n\tborder-radius: 50%;\n\tbackground: radial-gradient(circle at 35% 35%, #999, #555 60%, #333);\n\tbox-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n\n.player__screw::after {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\twidth: 6px;\n\theight: 1px;\n\tbackground: #333;\n\ttransform: translate(-50%, -50%) rotate(35deg);\n\tbox-shadow: 0 0 1px rgba(0, 0, 0, 0.5);\n}\n\n.player__screw:nth-child(1) {\n\ttop: 10px;\n\tleft: 14px;\n}\n\n.player__screw:nth-child(2) {\n\ttop: 10px;\n\tright: 14px;\n}\n\n.player__screw:nth-child(3) {\n\tbottom: 10px;\n\tleft: 14px;\n}\n\n.player__screw:nth-child(4) {\n\tbottom: 10px;\n\tright: 14px;\n}\n\n/* Display */\n.player__display {\n\tbackground: #111;\n\tborder-radius: 8px;\n\tpadding: 4px;\n\tbox-shadow:\n\t\tinset 0 3px 8px rgba(0, 0, 0, 0.8),\n\t\tinset 0 1px 2px rgba(0, 0, 0, 0.5),\n\t\t0 1px 0 rgba(255, 255, 255, 0.05);\n}\n\n.player__display-inner {\n\tborder: 1px solid #0a0a0a;\n\tborder-radius: 6px;\n\toverflow: hidden;\n}\n\n.player__lcd {\n\tposition: relative;\n\tbackground: var(--display-bg);\n\tpadding: 16px 18px 14px;\n\tmin-height: 130px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.player__lcd-scanlines {\n\tposition: absolute;\n\tinset: 0;\n\tbackground: repeating-linear-gradient(0deg,\n\t\t\ttransparent,\n\t\t\ttransparent 1px,\n\t\t\trgba(0, 0, 0, 0.15) 1px,\n\t\t\trgba(0, 0, 0, 0.15) 2px);\n\tpointer-events: none;\n\tz-index: 1;\n}\n\n.player__info {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\tfont-family: 'VT323', monospace;\n\tfont-size: 13px;\n\tcolor: var(--display-dim);\n\tletter-spacing: 2px;\n}\n\n.player__status {\n\tcolor: var(--display-text);\n\ttext-shadow: 0 0 8px var(--display-text);\n}\n\n.player__title {\n\tfont-family: 'VT323', monospace;\n\tfont-size: 22px;\n\tcolor: var(--display-text);\n\ttext-shadow: 0 0 10px rgba(51, 255, 102, 0.5);\n\tletter-spacing: 1px;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\tmargin: 4px 0;\n}\n\n.player__time-row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n}\n\n.player__time,\n.player__duration {\n\tfont-family: 'Orbitron', monospace;\n\tfont-size: 13px;\n\tfont-weight: 700;\n\tcolor: var(--display-text);\n\ttext-shadow: 0 0 6px rgba(51, 255, 102, 0.4);\n\tmin-width: 42px;\n}\n\n.player__duration {\n\ttext-align: right;\n}\n\n/* VU Meter */\n.player__meter {\n\tdisplay: flex;\n\talign-items: flex-end;\n\tgap: 2px;\n\tflex: 1;\n\theight: 20px;\n\tpadding: 2px 0;\n}\n\n.player__meter-bar {\n\tflex: 1;\n\theight: 20%;\n\tmin-height: 2px;\n\tbackground: var(--display-dim);\n\tborder-radius: 1px;\n\ttransition: height 0.08s ease, background 0.08s ease;\n}\n\n.player__meter-bar.active {\n\tbackground: var(--display-text);\n\tbox-shadow: 0 0 4px rgba(51, 255, 102, 0.4);\n}\n\n.player__meter-bar.hot {\n\tbackground: var(--accent);\n\tbox-shadow: 0 0 4px var(--accent-glow);\n}\n\n/* Progress */\n.player__progress-track {\n\tposition: relative;\n\theight: 6px;\n\tbackground: rgba(51, 255, 102, 0.1);\n\tborder-radius: 3px;\n\tmargin-top: 6px;\n\toverflow: visible;\n}\n\n.player__progress-fill {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\theight: 100%;\n\twidth: 0%;\n\tbackground: var(--display-text);\n\tborder-radius: 3px;\n\tbox-shadow: 0 0 6px rgba(51, 255, 102, 0.4);\n\ttransition: width 0.1s linear;\n}\n\n.player__progress-input {\n\tposition: absolute;\n\ttop: -6px;\n\tleft: 0;\n\twidth: 100%;\n\theight: 18px;\n\topacity: 0;\n\tcursor: pointer;\n\tz-index: 2;\n\tmargin: 0;\n}\n\n/* Brand */\n.player__brand {\n\tdisplay: flex;\n\talign-items: baseline;\n\tgap: 12px;\n\tmargin: 14px 0 6px;\n\tpadding: 0 4px;\n}\n\n.player__brand-name {\n\tfont-family: 'Orbitron', sans-serif;\n\tfont-weight: 900;\n\tfont-size: 18px;\n\tletter-spacing: 6px;\n\tcolor: #999;\n\ttext-shadow: 0 1px 0 rgba(255, 255, 255, 0.1), 0 -1px 0 rgba(0, 0, 0, 0.3);\n}\n\n.player__brand-model {\n\tfont-family: 'Michroma', sans-serif;\n\tfont-size: 9px;\n\tletter-spacing: 3px;\n\tcolor: #666;\n}\n\n/* Transport Controls */\n.player__controls {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 24px;\n\tmargin: 10px 0;\n}\n\n.player__transport {\n\tdisplay: flex;\n\tgap: 8px;\n}\n\n.player__btn {\n\tposition: relative;\n\twidth: 48px;\n\theight: 44px;\n\tborder: none;\n\tborder-radius: 6px;\n\tbackground: linear-gradient(180deg, var(--btn-highlight) 0%, var(--btn-face) 40%, var(--btn-shadow) 100%);\n\tcolor: #ccc;\n\tcursor: pointer;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbox-shadow:\n\t\t0 3px 6px rgba(0, 0, 0, 0.4),\n\t\t0 1px 2px rgba(0, 0, 0, 0.3),\n\t\tinset 0 1px 0 rgba(255, 255, 255, 0.12);\n\ttransition: all 0.08s ease;\n}\n\n.player__btn:active {\n\ttransform: translateY(2px);\n\tbox-shadow:\n\t\t0 1px 2px rgba(0, 0, 0, 0.4),\n\t\tinset 0 2px 4px rgba(0, 0, 0, 0.3);\n\tbackground: linear-gradient(180deg, var(--btn-face) 0%, var(--btn-shadow) 100%);\n}\n\n.player__btn svg {\n\twidth: 18px;\n\theight: 18px;\n}\n\n.player__btn--play {\n\twidth: 56px;\n\theight: 48px;\n\tborder-radius: 8px;\n\tbackground: linear-gradient(180deg, #555 0%, #444 40%, #222 100%);\n\tcolor: var(--display-text);\n\tbox-shadow:\n\t\t0 3px 8px rgba(0, 0, 0, 0.5),\n\t\t0 1px 2px rgba(0, 0, 0, 0.3),\n\t\tinset 0 1px 0 rgba(255, 255, 255, 0.15);\n}\n\n.player__btn--play:active {\n\tbackground: linear-gradient(180deg, #444 0%, #222 100%);\n}\n\n.player__btn--play svg {\n\twidth: 22px;\n\theight: 22px;\n}\n\n.player__btn--play.playing {\n\tcolor: var(--accent);\n}\n\n/* Knobs */\n.player__knobs {\n\tdisplay: flex;\n\tgap: 20px;\n\tmargin-left: auto;\n}\n\n.player__knob-group {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 6px;\n}\n\n.player__knob {\n\twidth: 44px;\n\theight: 44px;\n\tborder-radius: 50%;\n\tbackground: radial-gradient(circle at 35% 35%, #555, #2a2a2e 70%);\n\tbox-shadow:\n\t\t0 3px 8px rgba(0, 0, 0, 0.5),\n\t\tinset 0 1px 0 rgba(255, 255, 255, 0.1),\n\t\t0 1px 0 rgba(255, 255, 255, 0.05);\n\tpadding: 4px;\n\tcursor: pointer;\n\tuser-select: none;\n}\n\n.player__knob-body {\n\twidth: 100%;\n\theight: 100%;\n\tborder-radius: 50%;\n\tbackground:\n\t\tconic-gradient(from 220deg, #555, #333, #555, #333, #555);\n\tbox-shadow:\n\t\tinset 0 2px 4px rgba(0, 0, 0, 0.5),\n\t\tinset 0 -1px 2px rgba(255, 255, 255, 0.05);\n\tposition: relative;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.player__knob-indicator {\n\tposition: absolute;\n\ttop: 3px;\n\tleft: 50%;\n\twidth: 2px;\n\theight: 10px;\n\tbackground: var(--accent);\n\tborder-radius: 1px;\n\ttransform: translateX(-50%);\n\tbox-shadow: 0 0 4px var(--accent-glow);\n}\n\n.player__knob-label {\n\tfont-size: 8px;\n\tletter-spacing: 2px;\n\tcolor: #777;\n\ttext-transform: uppercase;\n}\n\n.player__knob-value {\n\tfont-family: 'Orbitron', monospace;\n\tfont-size: 10px;\n\tfont-weight: 700;\n\tcolor: var(--accent);\n\ttext-shadow: 0 0 6px var(--accent-glow);\n\tletter-spacing: 1px;\n\tmin-width: 32px;\n\ttext-align: center;\n}\n\n/* Bottom Controls */\n.player__bottom {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 16px;\n\tmargin-top: 8px;\n\tpadding-top: 12px;\n\tborder-top: 1px solid rgba(255, 255, 255, 0.04);\n}\n\n.player__load-btn {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 8px 14px;\n\tborder-radius: 5px;\n\tbackground: linear-gradient(180deg, var(--btn-highlight) 0%, var(--btn-face) 40%, var(--btn-shadow) 100%);\n\tcolor: #aaa;\n\tfont-family: 'Michroma', sans-serif;\n\tfont-size: 9px;\n\tletter-spacing: 2px;\n\tcursor: pointer;\n\tbox-shadow:\n\t\t0 2px 4px rgba(0, 0, 0, 0.4),\n\t\tinset 0 1px 0 rgba(255, 255, 255, 0.1);\n\ttransition: all 0.08s ease;\n}\n\n.player__load-btn:active {\n\ttransform: translateY(1px);\n\tbox-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), inset 0 2px 4px rgba(0, 0, 0, 0.3);\n}\n\n.player__load-btn svg {\n\twidth: 14px;\n\theight: 14px;\n}\n\n.player__toggles {\n\tdisplay: flex;\n\tgap: 6px;\n}\n\n.player__toggle {\n\twidth: 36px;\n\theight: 32px;\n\tborder: none;\n\tborder-radius: 5px;\n\tbackground: linear-gradient(180deg, var(--btn-highlight) 0%, var(--btn-face) 40%, var(--btn-shadow) 100%);\n\tcolor: #666;\n\tcursor: pointer;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbox-shadow:\n\t\t0 2px 4px rgba(0, 0, 0, 0.4),\n\t\tinset 0 1px 0 rgba(255, 255, 255, 0.08);\n\ttransition: all 0.08s ease;\n}\n\n.player__toggle:active {\n\ttransform: translateY(1px);\n}\n\n.player__toggle.active {\n\tcolor: var(--accent);\n\tbox-shadow:\n\t\t0 2px 4px rgba(0, 0, 0, 0.4),\n\t\tinset 0 2px 6px rgba(0, 0, 0, 0.3),\n\t\t0 0 8px var(--accent-glow);\n}\n\n.player__toggle svg {\n\twidth: 14px;\n\theight: 14px;\n}\n\n/* LEDs */\n.player__led-group {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tmargin-left: auto;\n}\n\n.player__led {\n\twidth: 8px;\n\theight: 8px;\n\tborder-radius: 50%;\n\tbackground: #333;\n\tbox-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5);\n}\n\n.player__led--on.player__led--power {\n\tbackground: var(--led-green);\n\tbox-shadow: 0 0 6px var(--led-green), 0 0 12px rgba(51, 255, 102, 0.3);\n}\n\n.player__led--on.player__led--signal {\n\tbackground: var(--accent);\n\tbox-shadow: 0 0 6px var(--accent), 0 0 12px var(--accent-glow);\n}\n\n.player__led-label {\n\tfont-size: 7px;\n\tletter-spacing: 1px;\n\tcolor: #555;\n}\n\n/* Speaker Grilles */\n.player__speaker-grilles {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\tmargin-top: 14px;\n\tgap: 20px;\n}\n\n.player__grille {\n\tflex: 1;\n\theight: 24px;\n\tbackground: var(--chassis-dark);\n\tborder-radius: 4px;\n\tbox-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.03);\n\toverflow: hidden;\n}\n\n.player__grille-holes {\n\twidth: 100%;\n\theight: 100%;\n\tbackground-image:\n\t\tradial-gradient(circle, #111 1.2px, transparent 1.2px);\n\tbackground-size: 8px 8px;\n\tbackground-position: 2px 2px;\n}\n\n/* Responsive */\n@media (max-width: 500px) {\n\t.player__controls {\n\t\tflex-direction: column;\n\t\tgap: 14px;\n\t}\n\n\t.player__knobs {\n\t\tmargin-left: 0;\n\t}\n\n\t.player__body {\n\t\tpadding: 22px 16px 16px;\n\t}\n}"}],"folders":[]},"variants":null,"createdAt":"2026-02-07T12:34:00.546Z","updatedAt":"2026-03-07T08:29:29.237Z","hasThumbnail":true}}