@php
    $audioUrl   = route('videos.stream', $video);
    $coverUrl   = $video->thumbnail ? route('media.thumbnail', $video->thumbnail) : asset('storage/images/logo.png');
    $nextUrl    = isset($nextVideo, $playlist) ? route('videos.show', $nextVideo).'?playlist='.$playlist->share_token : null;
    $prevUrl    = isset($previousVideo, $playlist) ? route('videos.show', $previousVideo).'?playlist='.$playlist->share_token : null;
    $slideUrls  = $video->slides->count() > 1
        ? $video->slides->map(fn($s) => route('media.thumbnail', $s->filename))->values()->all()
        : [];
@endphp

<div class="ytp-wrap" id="ytpWrap">
<div class="ytp audio-ytp" id="audioContainer" tabindex="0">

    {{-- Cover art / slideshow --}}
    @if(count($slideUrls) > 1)
    <div class="slideshow-wrap" id="slideshowWrap">
        <img src="{{ $slideUrls[0] }}" alt="" class="slide-img slide-a" id="slideA">
        <img src="{{ $slideUrls[1] }}" alt="" class="slide-img slide-b" id="slideB">
    </div>
    @else
    <img src="{{ $coverUrl }}" alt="{{ $video->title }}" class="audio-cover-img" id="audioCoverImg">
    @endif

    {{-- Bars canvas overlay --}}
    <canvas id="audioAnimCanvas" style="position:absolute;inset:0;width:100%;height:100%;pointer-events:none;display:none;z-index:3;"></canvas>

    {{-- Gradient --}}
    <div class="ytp-gradient-bottom"></div>

    {{-- Large play overlay --}}
    <div class="ytp-large-play-btn" id="ytpLargePlay">
        <i class="bi bi-play-fill"></i>
    </div>

    {{-- Controls --}}
    <div class="ytp-chrome-bottom" id="ytpControls">

        <div class="ytp-progress-bar-container" id="ytpProgressContainer">
            <div class="ytp-progress-bar" id="ytpProgressBar">
                <div class="ytp-play-progress" id="ytpPlayed"></div>
                <div class="ytp-scrubber-container">
                    <div class="ytp-scrubber-button" id="ytpScrubber"></div>
                </div>
                <div class="ytp-hover-time" id="ytpHoverTime"></div>
            </div>
        </div>

        <div class="ytp-chrome-controls">

            <div class="ytp-left-controls">

                <button class="ytp-button ytp-play-btn" id="ytpPlayBtn" title="Play (k)">
                    <svg class="ytp-svg-play"  viewBox="0 0 24 24"><path d="M8 5v14l11-7z"/></svg>
                    <svg class="ytp-svg-pause" viewBox="0 0 24 24" style="display:none"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
                </button>

                @if(isset($previousVideo) && $prevUrl)
                <button class="ytp-button" title="Previous" onclick="window.location.href='{{ $prevUrl }}'">
                    <svg viewBox="0 0 24 24"><path d="M6 6h2v12H6zm3.5 6 8.5 6V6z"/></svg>
                </button>
                @endif

                @if(isset($nextVideo) && $nextUrl)
                <button class="ytp-button" title="Next" onclick="window.location.href='{{ $nextUrl }}'">
                    <svg viewBox="0 0 24 24"><path d="m6 18 8.5-6L6 6v12zM16 6v12h2V6h-2z"/></svg>
                </button>
                @endif

                <div class="ytp-volume-area">
                    <button class="ytp-button ytp-mute-btn" id="ytpMuteBtn" title="Mute (m)">
                        <svg class="ytp-svg-vol3" viewBox="0 0 24 24"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></svg>
                        <svg class="ytp-svg-vol0" viewBox="0 0 24 24" style="display:none"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3 3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4 9.91 6.09 12 8.18V4z"/></svg>
                    </button>
                    <div class="ytp-volume-slider-wrap">
                        <input type="range" class="ytp-volume-range" id="ytpVolume" min="0" max="100" step="1" value="50">
                    </div>
                </div>

                <div class="ytp-time-display">
                    <span id="ytpCurrent">0:00</span>
                    <span class="ytp-time-sep"> / </span>
                    <span id="ytpDuration">0:00</span>
                </div>

            </div>

            <div class="ytp-right-controls">

                <div class="ytp-settings-wrap" id="ytpSettingsWrap">
                    <button class="ytp-button ytp-settings-btn" id="ytpSettingsBtn" title="Settings">
                        <svg viewBox="0 0 24 24"><path d="M19.14 12.94c.04-.3.06-.61.06-.94s-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/></svg>
                    </button>
                    <div class="ytp-settings-panel" id="ytpSettingsPanel">
                        <div class="ytp-settings-item" id="ytpSpeedRow">
                            <svg viewBox="0 0 24 24"><path d="M10 8v8l6-4-6-4zm6.5 4A6.5 6.5 0 1 1 9 6.04V4.02A8.5 8.5 0 1 0 18.5 12H16.5z"/></svg>
                            <span>Playback speed</span>
                            <span class="ytp-settings-val" id="ytpSpeedLabel">Normal</span>
                            <svg class="ytp-chevron" viewBox="0 0 24 24"><path d="M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
                        </div>
                        <div class="ytp-speed-panel" id="ytpSpeedPanel">
                            <div class="ytp-speed-back" id="ytpSpeedBack">
                                <svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
                                Playback speed
                            </div>
                            @foreach([['0.25','0.25'],['0.5','0.5'],['0.75','0.75'],['1','Normal'],['1.25','1.25'],['1.5','1.5'],['1.75','1.75'],['2','2']] as [$val,$label])
                            <div class="ytp-speed-option {{ $val === '1' ? 'active' : '' }}" data-speed="{{ $val }}">
                                <svg class="ytp-speed-check" viewBox="0 0 24 24"><path d="M9 16.17 4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
                                {{ $label }}
                            </div>
                            @endforeach
                        </div>
                        {{-- Loop toggle --}}
                        <div class="ytp-settings-item ytp-toggle-row" id="ytpLoopRow">
                            <svg viewBox="0 0 24 24"><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z"/></svg>
                            <span>Loop</span>
                            <span class="ytp-settings-val ytp-toggle-val" id="ytpLoopVal">Off</span>
                            <div class="ytp-toggle-switch"><div class="ytp-toggle-thumb"></div></div>
                        </div>
                    </div>
                </div>

                {{-- Bars visualiser toggle --}}
                <button class="ytp-button audio-bars-btn" id="ytpBarsBtn" title="Visualiser: Off">
                    <svg viewBox="0 0 24 24">
                        <rect x="2"  y="14" width="4" height="8" rx="1" fill="white"/>
                        <rect x="8"  y="8"  width="4" height="14" rx="1" fill="white"/>
                        <rect x="14" y="11" width="4" height="11" rx="1" fill="white"/>
                        <rect x="20" y="5"  width="2" height="17" rx="1" fill="white"/>
                    </svg>
                </button>

                <button class="ytp-button ytp-fs-btn" id="ytpFsBtn" title="Full screen (f)">
                    <svg class="ytp-svg-fs-enter" viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>
                    <svg class="ytp-svg-fs-exit"  viewBox="0 0 24 24" style="display:none"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></svg>
                </button>

            </div>
        </div>
    </div>

</div>
</div>

{{-- Hidden audio element --}}
<audio id="audioEl" src="{{ $audioUrl }}" preload="metadata"></audio>

{{-- ══ CSS ══ --}}
<style>
.audio-ytp { cursor: default; }
.audio-cover-img {
    position: absolute;
    inset: 0; width: 100%; height: 100%;
    object-fit: cover; display: block;
}

/* Slideshow */
.slideshow-wrap { position: absolute; inset: 0; background: #000; }
.slide-img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; display: block;
    transition: opacity 1s ease-in-out;
}
.slide-img.portrait { object-fit: contain; }
.slide-a { opacity: 1; z-index: 1; }
.slide-b { opacity: 0; z-index: 0; }

.audio-ytp .ytp-gradient-bottom,
.audio-ytp .ytp-chrome-bottom,
.audio-ytp .ytp-large-play-btn { z-index: 4; }

/* Bars button: dim when off, red when on */
.audio-bars-btn svg { opacity: .45; transition: opacity .15s; }
.audio-bars-btn.bars-on svg { opacity: 1; fill: #f00 !important; }
.audio-bars-btn.bars-on rect { fill: #f00 !important; }

/* ══ Full ytp styles ══ */
.ytp-wrap {
    position: relative; width: 100%; background: #000;
    border-radius: 12px; overflow: hidden;
    aspect-ratio: 16/9; max-height: 70vh;
}
.ytp {
    position: relative; width: 100%; height: 100%;
    background: #000; outline: none;
    user-select: none; overflow: hidden;
    font-family: Roboto, Arial, sans-serif;
}
.ytp:focus { outline: none; }
.ytp-gradient-bottom {
    position: absolute; bottom: 0; left: 0; right: 0;
    height: 98px;
    background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,.75));
    pointer-events: none; transition: opacity .25s;
}
.ytp-large-play-btn {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    pointer-events: none; opacity: 0; transition: opacity .2s;
}
.ytp-large-play-btn i { font-size: 72px; color: rgba(255,255,255,.9); text-shadow: 0 0 30px rgba(0,0,0,.6); }
.ytp-large-play-btn.visible { opacity: 1; }

.ytp-chrome-bottom {
    position: absolute; bottom: 0; left: 0; right: 0;
    padding: 0 12px 8px;
    transition: opacity .25s, transform .25s;
}
.ytp.controls-hidden .ytp-chrome-bottom { opacity: 0; transform: translateY(4px); pointer-events: none; }
.ytp.controls-hidden .ytp-gradient-bottom { opacity: 0; }

.ytp-progress-bar-container { padding: 4px 0; cursor: pointer; margin-bottom: 4px; }
.ytp-progress-bar {
    position: relative; height: 3px;
    background: rgba(255,255,255,.2); border-radius: 2px; transition: height .1s;
}
.ytp-progress-bar-container:hover .ytp-progress-bar,
.ytp-progress-bar.dragging { height: 5px; }
.ytp-play-progress {
    position: absolute; top: 0; left: 0; bottom: 0;
    background: #f00; border-radius: 2px; width: 0; pointer-events: none;
}
.ytp-scrubber-container {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 0; pointer-events: none;
}
.ytp-scrubber-button {
    width: 13px; height: 13px; border-radius: 50%; background: #f00;
    transform: translate(-50%, 0) scale(0); transition: transform .1s; margin-top: -4px;
}
.ytp-progress-bar-container:hover .ytp-scrubber-button,
.ytp-progress-bar.dragging .ytp-scrubber-button { transform: translate(-50%, 0) scale(1); }
.ytp-hover-time {
    position: absolute; bottom: 16px;
    background: rgba(28,28,28,.9); color: #fff;
    font-size: 12px; padding: 3px 6px; border-radius: 4px;
    pointer-events: none; opacity: 0;
    transform: translateX(-50%); white-space: nowrap; transition: opacity .1s;
}
.ytp-progress-bar-container:hover .ytp-hover-time { opacity: 1; }

.ytp-chrome-controls {
    display: flex; align-items: center; justify-content: space-between; height: 36px;
}
.ytp-left-controls, .ytp-right-controls { display: flex; align-items: center; gap: 4px; }

.ytp-button {
    background: none; border: none; color: #fff; cursor: pointer;
    padding: 0; width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; transition: background .15s; flex-shrink: 0;
}
.ytp-button:hover { background: rgba(255,255,255,.1); }
.ytp-button svg { width: 22px; height: 22px; fill: #fff; pointer-events: none; }
.ytp-button:focus { outline: none; }
.ytp-play-btn svg { width: 26px; height: 26px; }

.ytp-volume-area { display: flex; align-items: center; }
.ytp-volume-slider-wrap {
    overflow: hidden; width: 0; transition: width .2s;
    display: flex; align-items: center;
}
.ytp-volume-area:hover .ytp-volume-slider-wrap,
.ytp-volume-area:focus-within .ytp-volume-slider-wrap { width: 60px; }
.ytp-volume-range {
    -webkit-appearance: none; appearance: none;
    width: 52px; height: 3px; border-radius: 2px;
    background: linear-gradient(to right, #fff var(--vol,50%), rgba(255,255,255,.3) var(--vol,50%));
    outline: none; cursor: pointer; margin: 0 4px;
}
.ytp-volume-range::-webkit-slider-thumb { -webkit-appearance: none; width: 13px; height: 13px; border-radius: 50%; background: #fff; cursor: pointer; }
.ytp-volume-range::-moz-range-thumb { width: 13px; height: 13px; border-radius: 50%; background: #fff; border: none; cursor: pointer; }

.ytp-time-display { font-size: 13px; color: #fff; white-space: nowrap; padding: 0 6px; line-height: 36px; }
.ytp-time-sep { opacity: .6; margin: 0 2px; }

.ytp-settings-wrap { position: relative; }
.ytp-settings-panel {
    display: none; position: absolute; bottom: 44px; right: 0;
    background: rgba(28,28,28,.95); border-radius: 12px;
    min-width: 200px; overflow: hidden;
    box-shadow: 0 4px 24px rgba(0,0,0,.6); z-index: 100;
}
.ytp-settings-panel.open { display: block; }
.ytp-settings-item {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 16px; color: #fff; font-size: 13px;
    cursor: pointer; transition: background .15s; white-space: nowrap;
}
.ytp-settings-item:hover { background: rgba(255,255,255,.1); }
.ytp-settings-item svg { width: 20px; height: 20px; fill: #fff; flex-shrink: 0; }
.ytp-settings-item .ytp-settings-val { margin-left: auto; color: rgba(255,255,255,.7); font-size: 12px; margin-right: 4px; }
.ytp-chevron { width: 18px; height: 18px; flex-shrink: 0; }

.ytp-speed-panel { display: none; }
.ytp-speed-panel.open { display: block; }
.ytp-speed-back {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 16px; color: #fff; font-size: 13px; font-weight: 600;
    cursor: pointer; border-bottom: 1px solid rgba(255,255,255,.15);
}
.ytp-speed-back:hover { background: rgba(255,255,255,.1); }
.ytp-speed-back svg { width: 20px; height: 20px; fill: #fff; }
.ytp-speed-option {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 16px; color: #fff; font-size: 13px;
    cursor: pointer; transition: background .15s;
}
.ytp-speed-option:hover { background: rgba(255,255,255,.1); }
.ytp-speed-check { width: 18px; height: 18px; fill: #fff; opacity: 0; flex-shrink: 0; }
.ytp-speed-option.active .ytp-speed-check { opacity: 1; }

.ytp-wrap.ytp-fullscreen {
    position: fixed !important; inset: 0; z-index: 99999;
    max-height: 100vh; height: 100vh; width: 100vw;
    border-radius: 0; aspect-ratio: unset; margin: 0 !important;
}

.ytp-toggle-row { border-top: 1px solid rgba(255,255,255,.08); }
.ytp-toggle-row svg { opacity: .75; }
.ytp-toggle-val { font-size: 11px !important; opacity: .6; transition: color .15s, opacity .15s; }
.ytp-toggle-row.is-on .ytp-toggle-val { color: #f00; opacity: 1; }
.ytp-toggle-row.is-on svg { fill: #f00; opacity: 1; }
.ytp-toggle-switch {
    width: 28px; height: 16px; background: rgba(255,255,255,.2);
    border-radius: 8px; position: relative; flex-shrink: 0;
    transition: background .2s; margin-left: 6px;
}
.ytp-toggle-row.is-on .ytp-toggle-switch { background: #e61e1e; }
.ytp-toggle-thumb {
    position: absolute; top: 2px; left: 2px;
    width: 12px; height: 12px; background: #fff;
    border-radius: 50%; transition: transform .2s;
    box-shadow: 0 1px 3px rgba(0,0,0,.4);
}
.ytp-toggle-row.is-on .ytp-toggle-thumb { transform: translateX(12px); }

@media (max-width: 576px) {
    .ytp-wrap { border-radius: 0; max-height: 56vw; }
    .ytp-button { width: 32px; height: 32px; }
    .ytp-button svg { width: 18px; height: 18px; }
    .ytp-time-display { font-size: 11px; padding: 0 4px; }
}
</style>

{{-- ══ JS ══ --}}
<script>
(function () {

const wrap      = document.getElementById('ytpWrap');
const player    = document.getElementById('audioContainer');
const audio     = document.getElementById('audioEl');
const playBtn   = document.getElementById('ytpPlayBtn');
const muteBtn   = document.getElementById('ytpMuteBtn');
const volRange  = document.getElementById('ytpVolume');
const timeCur   = document.getElementById('ytpCurrent');
const timeDur   = document.getElementById('ytpDuration');
const progCont  = document.getElementById('ytpProgressContainer');
const progBar   = document.getElementById('ytpProgressBar');
const played    = document.getElementById('ytpPlayed');
const scrubber  = document.getElementById('ytpScrubber');
const hoverTime = document.getElementById('ytpHoverTime');
const largePlay = document.getElementById('ytpLargePlay');
const settingsBtn   = document.getElementById('ytpSettingsBtn');
const settingsPanel = document.getElementById('ytpSettingsPanel');
const speedRow      = document.getElementById('ytpSpeedRow');
const speedPanel    = document.getElementById('ytpSpeedPanel');
const speedBack     = document.getElementById('ytpSpeedBack');
const speedLabel    = document.getElementById('ytpSpeedLabel');
const speedOpts     = document.querySelectorAll('.ytp-speed-option');
const fsBtn         = document.getElementById('ytpFsBtn');
const loopRow       = document.getElementById('ytpLoopRow');
const loopVal       = document.getElementById('ytpLoopVal');
const barsBtn       = document.getElementById('ytpBarsBtn');
const animCanvas    = document.getElementById('audioAnimCanvas');

const NEXT_URL = @json($nextUrl ?? null);
let hideTimer            = null;
let isDragging           = false;
let userSeeking          = false;
let wasPlayingBeforeSeek = false;

// ── Helpers ──────────────────────────────────────────────────
function fmt(s) {
    if (!isFinite(s) || isNaN(s)) return '0:00';
    s = Math.floor(s);
    const m = Math.floor(s / 60), sec = s % 60;
    return m + ':' + String(sec).padStart(2, '0');
}

function updatePlayIcon() {
    playBtn.querySelector('.ytp-svg-play').style.display  = audio.paused ? '' : 'none';
    playBtn.querySelector('.ytp-svg-pause').style.display = audio.paused ? 'none' : '';
    player.classList.toggle('playing', !audio.paused);
}

function updateVolumeIcon() {
    const muted = audio.muted || audio.volume === 0;
    muteBtn.querySelector('.ytp-svg-vol3').style.display = muted ? 'none' : '';
    muteBtn.querySelector('.ytp-svg-vol0').style.display = muted ? '' : 'none';
    const v = muted ? 0 : Math.round(audio.volume * 100);
    volRange.value = v;
    volRange.style.setProperty('--vol', v + '%');
}

function updateProgress() {
    if (!audio.duration) return;
    const pct = (audio.currentTime / audio.duration) * 100;
    played.style.width = pct + '%';
    scrubber.parentElement.style.left = pct + '%';
    timeCur.textContent = fmt(audio.currentTime);
}

// ── Controls visibility ──────────────────────────────────────
function showControls() {
    player.classList.remove('controls-hidden');
    clearTimeout(hideTimer);
    if (!audio.paused) hideTimer = setTimeout(() => player.classList.add('controls-hidden'), 3000);
}

// ── Play / Pause ─────────────────────────────────────────────
function togglePlay() {
    if (audio.paused) { audio.play(); } else { audio.pause(); }
}
playBtn.addEventListener('click', e => { e.stopPropagation(); togglePlay(); showControls(); });
player.addEventListener('click', e => {
    if (settingsPanel.contains(e.target) || settingsBtn === e.target) return;
    if (progCont.contains(e.target)) return;
    togglePlay();
});
player.addEventListener('mousemove', showControls);

// ── Volume ───────────────────────────────────────────────────
muteBtn.addEventListener('click', e => {
    e.stopPropagation();
    audio.muted = !audio.muted;
    if (!audio.muted && audio.volume === 0) audio.volume = 0.5;
    updateVolumeIcon();
    localStorage.setItem('ytpMuted', audio.muted ? '1' : '0');
});
volRange.addEventListener('input', e => {
    e.stopPropagation();
    const v = parseInt(e.target.value) / 100;
    audio.volume = v;
    audio.muted  = v === 0;
    updateVolumeIcon();
    localStorage.setItem('ytpVolume', e.target.value);
});
volRange.addEventListener('click', e => e.stopPropagation());

// ── Progress bar ─────────────────────────────────────────────
function seekTo(pct) {
    if (!audio.duration) return;
    if (!userSeeking) wasPlayingBeforeSeek = !audio.paused;
    userSeeking = true;
    audio.currentTime = Math.max(0, Math.min(1, pct)) * audio.duration;
    updateProgress();
}
function progressPct(clientX) {
    const rect = progBar.getBoundingClientRect();
    return Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
}

progCont.addEventListener('mousemove', e => {
    hoverTime.textContent = fmt(progressPct(e.clientX) * (audio.duration || 0));
    hoverTime.style.left  = (progressPct(e.clientX) * 100) + '%';
    if (isDragging) seekTo(progressPct(e.clientX));
});
progCont.addEventListener('mousedown', e => {
    e.preventDefault(); isDragging = true;
    progBar.classList.add('dragging'); seekTo(progressPct(e.clientX));
});
document.addEventListener('mousemove', e => { if (isDragging) seekTo(progressPct(e.clientX)); });
document.addEventListener('mouseup',   () => { if (isDragging) { isDragging = false; progBar.classList.remove('dragging'); } });
progCont.addEventListener('touchstart', e => { isDragging = true; progBar.classList.add('dragging'); seekTo(progressPct(e.touches[0].clientX)); }, { passive: true });
progCont.addEventListener('touchmove',  e => { if (isDragging) seekTo(progressPct(e.touches[0].clientX)); }, { passive: true });
progCont.addEventListener('touchend',   e => { e.preventDefault(); isDragging = false; progBar.classList.remove('dragging'); });

// ── Settings / Speed ─────────────────────────────────────────
settingsBtn.addEventListener('click', e => {
    e.stopPropagation();
    const open = settingsPanel.classList.toggle('open');
    if (!open) { speedPanel.classList.remove('open'); speedRow.style.display = ''; }
    clearTimeout(hideTimer);
});
document.addEventListener('click', e => {
    if (!document.getElementById('ytpSettingsWrap').contains(e.target)) {
        settingsPanel.classList.remove('open');
        speedPanel.classList.remove('open');
        speedRow.style.display = '';
    }
});
speedRow.addEventListener('click', e => { e.stopPropagation(); speedRow.style.display = 'none'; speedPanel.classList.add('open'); });
speedBack.addEventListener('click', e => { e.stopPropagation(); speedPanel.classList.remove('open'); speedRow.style.display = ''; });
speedOpts.forEach(opt => {
    opt.addEventListener('click', e => {
        e.stopPropagation();
        const s = parseFloat(opt.dataset.speed);
        audio.playbackRate = s;
        speedOpts.forEach(o => o.classList.remove('active'));
        opt.classList.add('active');
        speedLabel.textContent = s === 1 ? 'Normal' : s;
        settingsPanel.classList.remove('open');
        speedPanel.classList.remove('open');
        speedRow.style.display = '';
    });
});

// ── Fullscreen ───────────────────────────────────────────────
fsBtn.addEventListener('click', e => {
    e.stopPropagation();
    document.fullscreenElement ? document.exitFullscreen() : wrap.requestFullscreen();
    showControls();
});
document.addEventListener('fullscreenchange', () => {
    const fs = !!document.fullscreenElement;
    wrap.classList.toggle('ytp-fullscreen', fs);
    fsBtn.querySelector('.ytp-svg-fs-enter').style.display = fs ? 'none' : '';
    fsBtn.querySelector('.ytp-svg-fs-exit').style.display  = fs ? '' : 'none';
});

// ── Keyboard shortcuts ────────────────────────────────────────
document.addEventListener('keydown', e => {
    const tag = document.activeElement.tagName;
    if (tag === 'INPUT' || tag === 'TEXTAREA' || document.activeElement.isContentEditable) return;
    switch (e.key) {
        case ' ': case 'k': case 'K': e.preventDefault(); togglePlay(); showControls(); break;
        case 'm': case 'M':
            e.preventDefault();
            audio.muted = !audio.muted;
            if (!audio.muted && audio.volume === 0) audio.volume = 0.5;
            updateVolumeIcon(); showControls(); break;
        case 'f': case 'F': e.preventDefault(); fsBtn.click(); break;
        case 'ArrowLeft':  e.preventDefault(); if (audio.duration) audio.currentTime = Math.max(0, audio.currentTime - 5); showControls(); break;
        case 'ArrowRight': e.preventDefault(); if (audio.duration) audio.currentTime = Math.min(audio.duration, audio.currentTime + 5); showControls(); break;
        case 'ArrowUp':   e.preventDefault(); audio.volume = Math.min(1, audio.volume + 0.05); audio.muted = false; updateVolumeIcon(); showControls(); break;
        case 'ArrowDown': e.preventDefault(); audio.volume = Math.max(0, audio.volume - 0.05); updateVolumeIcon(); showControls(); break;
        default:
            if (e.key >= '0' && e.key <= '9') {
                e.preventDefault();
                if (audio.duration) audio.currentTime = (parseInt(e.key) / 10) * audio.duration;
                showControls();
            }
    }
});

// ── Audio events ─────────────────────────────────────────────
audio.addEventListener('play',           () => { updatePlayIcon(); startBars(); showControls(); largePlay.classList.remove('visible'); requestWakeLock(); });
audio.addEventListener('pause',          () => {
    if (userSeeking) return; // suppress mid-seek pause events
    updatePlayIcon(); stopBars(); showControls(); largePlay.classList.add('visible'); clearTimeout(hideTimer); releaseWakeLock();
});
audio.addEventListener('seeked', () => {
    userSeeking = false;
    if (wasPlayingBeforeSeek) {
        if (audio.paused) audio.play().catch(() => {});
        largePlay.classList.remove('visible');
    }
});
audio.addEventListener('timeupdate',     updateProgress);
audio.addEventListener('durationchange', () => { timeDur.textContent = fmt(audio.duration); });
audio.addEventListener('ended', () => { releaseWakeLock(); if (window._plOnTrackEnd) { window._plOnTrackEnd(); } else if (NEXT_URL) { window.location.href = NEXT_URL; } });
audio.addEventListener('volumechange', updateVolumeIcon);

// ── Loop ─────────────────────────────────────────────────────
let isLooping = localStorage.getItem('ytpLoop') === '1';
audio.loop = isLooping;
function applyLoopState() {
    if (!loopRow) return;
    loopRow.classList.toggle('is-on', isLooping);
    if (loopVal) loopVal.textContent = isLooping ? 'On' : 'Off';
}
applyLoopState();
if (loopRow) {
    loopRow.addEventListener('click', e => {
        e.stopPropagation();
        isLooping = !isLooping;
        audio.loop = isLooping;
        localStorage.setItem('ytpLoop', isLooping ? '1' : '0');
        applyLoopState();
    });
}

// ── Wake Lock ─────────────────────────────────────────────────
let wakeLock = null;
async function requestWakeLock() {
    if (!('wakeLock' in navigator) || wakeLock) return;
    try { wakeLock = await navigator.wakeLock.request('screen'); } catch(e) {}
}
function releaseWakeLock() {
    if (wakeLock) { wakeLock.release(); wakeLock = null; }
}
document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'visible' && !audio.paused) requestWakeLock();
});

// ── Bars visualiser ───────────────────────────────────────────
let audioCtx = null, analyser = null, dataArray = null, rafId = null;
let barsOn = localStorage.getItem('audioBarsOn') === '1';

// Extract dominant colors from cover art for bar gradients
let imgColors = ['rgb(255,255,255)', 'rgb(200,200,200)', 'rgb(170,170,170)'];

function colorWithAlpha(col, a) {
    return col.replace('rgb(', 'rgba(').replace(')', ',' + a + ')');
}

function extractColors(img) {
    try {
        const cv = document.createElement('canvas');
        cv.width = cv.height = 24;
        const cx = cv.getContext('2d');
        cx.drawImage(img, 0, 0, 24, 24);
        const px = cx.getImageData(0, 0, 24, 24).data;
        const buckets = {};
        for (let i = 0; i < px.length; i += 4) {
            const r = px[i], g = px[i+1], b = px[i+2];
            const bright = (r + g + b) / 3;
            if (bright < 25 || bright > 230) continue;
            const max = Math.max(r,g,b), min = Math.min(r,g,b);
            if (max === 0 || (max - min) / max < 0.25) continue;
            const key = `${r>>2},${g>>2},${b>>2}`;
            buckets[key] = (buckets[key] || { r:0, g:0, b:0, n:0 });
            buckets[key].r += r; buckets[key].g += g; buckets[key].b += b; buckets[key].n++;
        }
        const sorted = Object.values(buckets).sort((a,b) => b.n - a.n);
        if (!sorted.length) return;
        const chosen = [sorted[0]];
        for (let i = 1; i < sorted.length && chosen.length < 3; i++) {
            const c = sorted[i];
            const far = chosen.every(e => {
                const dr = e.r/e.n - c.r/c.n, dg = e.g/e.n - c.g/c.n, db = e.b/e.n - c.b/c.n;
                return Math.sqrt(dr*dr + dg*dg + db*db) > 60;
            });
            if (far) chosen.push(c);
        }
        imgColors = chosen.map(c => `rgb(${Math.round(c.r/c.n)},${Math.round(c.g/c.n)},${Math.round(c.b/c.n)})`);
        while (imgColors.length < 3) imgColors.push(imgColors[0]);
    } catch(e) {}
}

const coverImg = document.getElementById('audioCoverImg');
if (coverImg) {
    if (coverImg.complete && coverImg.naturalWidth) {
        extractColors(coverImg);
        if (coverImg.naturalHeight > coverImg.naturalWidth) coverImg.style.objectFit = 'contain';
    } else {
        coverImg.addEventListener('load', () => {
            extractColors(coverImg);
            if (coverImg.naturalHeight > coverImg.naturalWidth) coverImg.style.objectFit = 'contain';
        }, { once: true });
    }
}

function applyBarsState() {
    barsBtn.classList.toggle('bars-on', barsOn);
    barsBtn.title = barsOn ? 'Visualiser: On' : 'Visualiser: Off';
    animCanvas.style.display = barsOn ? 'block' : 'none';
}
applyBarsState();

barsBtn.addEventListener('click', e => {
    e.stopPropagation();
    barsOn = !barsOn;
    localStorage.setItem('audioBarsOn', barsOn ? '1' : '0');
    applyBarsState();
    if (barsOn && !audio.paused) startBars(); else stopBars();
    showControls();
});

function initAnalyser() {
    if (audioCtx) { audioCtx.resume(); return; }
    try {
        audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        const src = audioCtx.createMediaElementSource(audio);
        analyser  = audioCtx.createAnalyser();
        analyser.fftSize = 256;
        analyser.smoothingTimeConstant = 0.75;
        src.connect(analyser);
        analyser.connect(audioCtx.destination);
        dataArray = new Uint8Array(analyser.frequencyBinCount);
    } catch (e) { console.warn('Web Audio unavailable:', e); }
}

function drawBars() {
    if (!analyser) return;
    analyser.getByteFrequencyData(dataArray);
    const ctx = animCanvas.getContext('2d');
    const w   = animCanvas.offsetWidth;
    const h   = animCanvas.offsetHeight;
    if (animCanvas.width !== w)  animCanvas.width  = w;
    if (animCanvas.height !== h) animCanvas.height = h;
    ctx.clearRect(0, 0, w, h);
    const bins = 48;
    const barW = (w / bins) * 0.7;
    const gap  = (w / bins) * 0.3;
    const maxH = h * 0.25;
    for (let i = 0; i < bins; i++) {
        const val  = dataArray[i + 2] / 255;
        const barH = Math.max(3, val * maxH);
        const x    = i * (barW + gap) + gap / 2;
        const y    = h - barH;
        const col  = imgColors[Math.floor((i / bins) * imgColors.length)];
        const grad = ctx.createLinearGradient(0, y, 0, h);
        grad.addColorStop(0, colorWithAlpha(col, (0.5 + val * 0.5).toFixed(2)));
        grad.addColorStop(1, colorWithAlpha(col, 0.12));
        ctx.fillStyle = grad;
        ctx.beginPath();
        ctx.roundRect(x, y, barW, barH, [3, 3, 0, 0]);
        ctx.fill();
    }
}

function barsLoop() {
    rafId = requestAnimationFrame(barsLoop);
    drawBars();
}

function startBars() {
    if (!barsOn) return;
    initAnalyser();
    if (!rafId) rafId = requestAnimationFrame(barsLoop);
}
function stopBars() {
    if (rafId) { cancelAnimationFrame(rafId); rafId = null; }
    if (animCanvas.getContext) animCanvas.getContext('2d').clearRect(0, 0, animCanvas.width, animCanvas.height);
}

// ── Crossfade slideshow ───────────────────────────────────────
const SLIDE_URLS = @json($slideUrls);
if (SLIDE_URLS.length > 1) {
    const slideA = document.getElementById('slideA');
    const slideB = document.getElementById('slideB');
    let currentSlide = 0;
    let aIsTop = true; // slideA starts on top (opacity 1)

    // Preload all images and detect portrait orientation
    const slideOrientations = new Array(SLIDE_URLS.length).fill(false); // true = portrait
    SLIDE_URLS.forEach((url, idx) => {
        const img = new Image();
        img.onload = () => { slideOrientations[idx] = img.naturalHeight > img.naturalWidth; };
        img.src = url;
    });

    function applyOrientation(el, idx) {
        el.classList.toggle('portrait', !!slideOrientations[idx]);
    }

    function getSlideInterval() {
        return audio.duration ? (audio.duration / SLIDE_URLS.length) * 1000 : 8000;
    }

    function advanceSlide() {
        currentSlide = (currentSlide + 1) % SLIDE_URLS.length;
        const next = SLIDE_URLS[currentSlide];

        if (aIsTop) {
            slideB.src = next;
            applyOrientation(slideB, currentSlide);
            slideB.style.zIndex = '2';
            slideB.style.opacity = '1';
            slideA.style.opacity = '0';
            slideA.style.zIndex = '1';
        } else {
            slideA.src = next;
            applyOrientation(slideA, currentSlide);
            slideA.style.zIndex = '2';
            slideA.style.opacity = '1';
            slideB.style.opacity = '0';
            slideB.style.zIndex = '1';
        }
        aIsTop = !aIsTop;
    }

    let slideshowTimer = null;

    function startSlideshow() {
        if (slideshowTimer || SLIDE_URLS.length <= 1) return;
        slideshowTimer = setInterval(advanceSlide, getSlideInterval());
    }
    function stopSlideshow() {
        clearInterval(slideshowTimer);
        slideshowTimer = null;
    }

    audio.addEventListener('play',  startSlideshow);
    audio.addEventListener('pause', stopSlideshow);
    audio.addEventListener('ended', stopSlideshow);

    // Seek: jump to the correct slide instantly (no transition flash)
    audio.addEventListener('seeked', () => {
        if (!audio.duration) return;
        stopSlideshow();
        const idx = Math.min(
            Math.floor((audio.currentTime / audio.duration) * SLIDE_URLS.length),
            SLIDE_URLS.length - 1
        );
        currentSlide = idx;
        // Reset: show correct slide without animation
        slideA.style.transition = 'none';
        slideB.style.transition = 'none';
        slideA.src = SLIDE_URLS[idx];
        applyOrientation(slideA, idx);
        slideA.style.opacity = '1'; slideA.style.zIndex = '2';
        slideB.style.opacity = '0'; slideB.style.zIndex = '1';
        const nextIdx = (idx + 1) % SLIDE_URLS.length;
        slideB.src = SLIDE_URLS[nextIdx];
        applyOrientation(slideB, nextIdx);
        aIsTop = true;
        requestAnimationFrame(() => {
            slideA.style.transition = '';
            slideB.style.transition = '';
        });
        if (!audio.paused) startSlideshow();
    });

    // Extract colors + apply orientation for first slide
    function initSlideA() {
        extractColors(slideA);
        const portrait = slideA.naturalHeight > slideA.naturalWidth;
        slideA.classList.toggle('portrait', portrait);
        slideOrientations[0] = portrait;
    }
    if (slideA.complete && slideA.naturalWidth) {
        initSlideA();
    } else {
        slideA.addEventListener('load', initSlideA, { once: true });
    }
}

// ── Init ─────────────────────────────────────────────────────
const savedVol   = localStorage.getItem('ytpVolume');
const savedMuted = localStorage.getItem('ytpMuted');
audio.volume = savedVol ? parseInt(savedVol) / 100 : 0.8;
audio.muted  = true; // start muted so autoplay always works
updateVolumeIcon();
largePlay.classList.add('visible');
showControls();

// Once playing, restore user's mute preference
audio.addEventListener('playing', function restoreSound() {
    audio.removeEventListener('playing', restoreSound);
    if (savedMuted !== '1') {
        audio.muted = false;
        updateVolumeIcon();
    }
}, { once: true });

audio.addEventListener('loadedmetadata', () => {
    timeDur.textContent = fmt(audio.duration);
    const p = audio.play();
    if (p) p.catch(() => {
        audio.muted = true;
        audio.play().catch(() => {});
    });
});

})();
</script>
