(() => { const SHOW_AUDIO_CONTROL = true const AUDIO_SOURCE = '/Locil%20Forecast%20-%20Elevator.mp3' const style = document.createElement('style') style.textContent = ` #mclive-floating-controls { --mclive-control-night: #041117; --mclive-control-ice: #d7f1e8; --mclive-control-mist: #8fafb2; --mclive-control-gold: #c6a15b; --mclive-control-online: #72aa86; --mclive-control-line: rgba(166, 209, 203, 0.22); position: fixed; z-index: 2147483647; top: 94px; right: clamp(20px, 3vw, 44px); width: 190px; display: flex; flex-direction: column; align-items: stretch; border: 1px solid var(--mclive-control-line); background: rgba(4, 17, 23, 0.92); box-shadow: 0 18px 52px rgba(0, 0, 0, 0.3); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); pointer-events: none; } #mclive-floating-controls:has(.mclive-countdown-restore:not(.is-visible)) .mclive-audio-control { border-bottom: 0; } .mclive-floating-control { width: 100%; min-height: 46px; padding: 0 13px; display: inline-flex; align-items: center; justify-content: flex-start; gap: 9px; border: 0; border-bottom: 1px solid var(--mclive-control-line); color: var(--mclive-control-ice); background: transparent; cursor: pointer; font-family: 'IBM Plex Mono', ui-monospace, monospace; font-size: 8px; letter-spacing: 0.14em; text-transform: uppercase; pointer-events: auto; } .mclive-floating-control:hover { background: rgba(198, 161, 91, 0.08); } .mclive-floating-control:focus-visible { outline: 2px solid var(--mclive-control-gold); outline-offset: 4px; } .mclive-floating-control svg { width: 14px; height: 14px; fill: currentColor; } .mclive-control-status { width: 6px; height: 6px; flex: 0 0 auto; background: var(--mclive-control-mist); box-shadow: 0 0 0 transparent; transition: background 0.2s ease, box-shadow 0.2s ease; } .mclive-audio-control.is-playing .mclive-control-status { background: var(--mclive-control-online); box-shadow: 0 0 10px rgba(114, 170, 134, 0.7); } .mclive-control-name { min-width: 0; flex: 1; color: var(--mclive-control-mist); text-align: left; } .mclive-control-value { color: var(--mclive-control-ice); font-variant-numeric: tabular-nums; text-align: right; } .mclive-audio-icon { width: 14px; height: 14px; display: grid; place-items: center; color: var(--mclive-control-gold); } @media (max-width: 620px) { #mclive-floating-controls { top: auto; right: 16px; bottom: 16px; width: 168px; } .mclive-floating-control { min-height: 44px; padding: 0 11px; } } ` let controls = document.getElementById('mclive-floating-controls') if (!controls) { controls = document.createElement('div') controls.id = 'mclive-floating-controls' document.body.appendChild(controls) } const audioButton = document.createElement('button') audioButton.className = 'mclive-floating-control mclive-audio-control' audioButton.type = 'button' audioButton.hidden = !SHOW_AUDIO_CONTROL audioButton.setAttribute('aria-label', '播放背景音乐') audioButton.innerHTML = ` AUDIO OFF ` controls.appendChild(audioButton) document.head.appendChild(style) const audioIcon = audioButton.querySelector('.mclive-audio-icon') const audioLabel = audioButton.querySelector('.mclive-audio-label') const audio = new Audio(AUDIO_SOURCE) audio.loop = true audio.preload = 'auto' const playIcon = '' const pauseIcon = '' function updateAudioControl() { const playing = !audio.paused audioIcon.innerHTML = playing ? pauseIcon : playIcon audioLabel.textContent = playing ? 'ON' : 'OFF' audioButton.classList.toggle('is-playing', playing) audioButton.setAttribute('aria-label', playing ? '暂停背景音乐' : '播放背景音乐') } async function startAudio() { if (!audio.paused) return try { await audio.play() } catch { // Browsers may reject playback until a qualifying user gesture occurs. } updateAudioControl() } function handleFirstInteraction(event) { if (audioButton.contains(event.target)) return startAudio() } audioButton.addEventListener('click', async () => { if (audio.paused) await startAudio() else audio.pause() updateAudioControl() }) audio.addEventListener('play', updateAudioControl) audio.addEventListener('pause', updateAudioControl) document.addEventListener('pointerdown', handleFirstInteraction, { passive: true }) document.addEventListener('touchstart', handleFirstInteraction, { passive: true }) document.addEventListener('keydown', handleFirstInteraction) updateAudioControl() })()