<script lang="ts">
	import { onMount, onDestroy } from 'svelte';

	// ── Types ──
	interface Show {
		id: string;
		title: string;
		author: string;
		artwork_url: string;
		feed_url: string;
		episode_count: number;
		unplayed_count: number;
	}

	interface Episode {
		id: string;
		show_id: string;
		show_title: string;
		title: string;
		description: string;
		artwork_url: string;
		audio_url: string;
		duration: number;
		published_at: string;
		status: 'unplayed' | 'in-progress' | 'played';
		progress_seconds: number;
	}

	interface QueueItem {
		position: number;
		episode: Episode;
	}

	// ── State ──
	let shows = $state<Show[]>([]);
	let episodes = $state<Episode[]>([]);
	let selectedShowId = $state<string | null>(null);
	let loading = $state(true);
	let loadingEpisodes = $state(false);
	let error = $state('');

	// Player state
	let currentEpisode = $state<Episode | null>(null);
	let isPlaying = $state(false);
	let currentTime = $state(0);
	let duration = $state(0);
	let playbackRate = $state(1);
	let isSeeking = $state(false);

	// Queue state
	let queue = $state<QueueItem[]>([]);
	let showQueue = $state(false);

	// Add show
	let showAddForm = $state(false);
	let feedUrl = $state('');
	let addingShow = $state(false);

	// Mobile state
	let mobileShowSidebar = $state(false);

	// Audio element
	let audio: HTMLAudioElement;
	let progressReportInterval: ReturnType<typeof setInterval> | null = null;

	// ── Derived ──
	const selectedShow = $derived(shows.find(s => s.id === selectedShowId) ?? null);
	const totalUnplayed = $derived(shows.reduce((sum, s) => sum + s.unplayed_count, 0));

	// ── Lifecycle ──
	onMount(() => {
		audio = new Audio();
		audio.preload = 'metadata';

		const savedRate = localStorage.getItem('podcast-playback-rate');
		if (savedRate) playbackRate = parseFloat(savedRate);

		audio.addEventListener('timeupdate', () => {
			if (!isSeeking) currentTime = audio.currentTime;
		});
		audio.addEventListener('durationchange', () => {
			if (audio.duration && isFinite(audio.duration)) duration = audio.duration;
		});
		audio.addEventListener('play', () => { isPlaying = true; });
		audio.addEventListener('pause', () => { isPlaying = false; });
		audio.addEventListener('ended', handleEpisodeEnd);
		audio.addEventListener('loadedmetadata', () => {
			if (audio.duration && isFinite(audio.duration)) duration = audio.duration;
		});

		loadShows();
		loadEpisodes();
		loadQueue();
		loadNowPlaying();

		progressReportInterval = setInterval(reportProgress, 30000);
	});

	onDestroy(() => {
		if (progressReportInterval) clearInterval(progressReportInterval);
		if (audio) {
			reportProgress();
			audio.pause();
			audio.src = '';
		}
	});

	// ── API helpers ──
	async function apiFetch(url: string, opts: RequestInit = {}) {
		const res = await fetch(url, { credentials: 'include', ...opts });
		if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
		return res.json();
	}

	async function apiPost(url: string, body?: unknown) {
		return apiFetch(url, {
			method: 'POST',
			headers: body ? { 'Content-Type': 'application/json' } : undefined,
			body: body ? JSON.stringify(body) : undefined,
		});
	}

	// ── Data loading ──
	async function loadShows() {
		try {
			const data = await apiFetch('/api/media/shows');
			shows = data.shows ?? data ?? [];
		} catch { shows = []; }
	}

	async function loadEpisodes(showId?: string | null) {
		loadingEpisodes = true;
		try {
			const params = new URLSearchParams({ limit: '50', offset: '0' });
			if (showId) params.set('show_id', showId);
			const data = await apiFetch(`/api/media/episodes?${params}`);
			episodes = data.episodes ?? data ?? [];
		} catch { episodes = []; }
		loadingEpisodes = false;
		loading = false;
	}

	async function loadQueue() {
		try {
			const data = await apiFetch('/api/media/queue');
			queue = data.items ?? data ?? [];
		} catch { queue = []; }
	}

	async function loadNowPlaying() {
		try {
			const data = await apiFetch('/api/media/playback/now-playing');
			if (data?.episode) {
				currentEpisode = data.episode;
				duration = data.episode.duration || 0;
				currentTime = data.position_seconds || data.episode.progress_seconds || 0;
				// Don't auto-play, just load it
				audio.src = getAudioUrl(data.episode);
				audio.currentTime = currentTime;
			}
		} catch { /* no episode playing */ }
	}

	// ── Show management ──
	async function addShow() {
		if (!feedUrl.trim()) return;
		addingShow = true;
		error = '';
		try {
			await apiPost('/api/media/shows', { feed_url: feedUrl.trim() });
			feedUrl = '';
			showAddForm = false;
			await loadShows();
			await loadEpisodes(selectedShowId);
		} catch (e: any) {
			error = e.message || 'Failed to add podcast';
		}
		addingShow = false;
	}

	async function removeShow(id: string) {
		try {
			await apiFetch(`/api/media/shows/${id}`, { method: 'DELETE' });
			if (selectedShowId === id) { selectedShowId = null; }
			await loadShows();
			await loadEpisodes(selectedShowId);
		} catch { /* silent */ }
	}

	async function refreshShow(id: string) {
		try {
			await apiPost(`/api/media/shows/${id}/refresh`);
			await loadShows();
			await loadEpisodes(selectedShowId);
		} catch { /* silent */ }
	}

	function selectShow(id: string | null) {
		selectedShowId = id;
		mobileShowSidebar = false;
		loadEpisodes(id);
	}

	// ── Audio playback ──
	function getAudioUrl(ep: Episode): string {
		if (ep.audio_url.startsWith('http')) return ep.audio_url;
		return `/api/media/episodes/${ep.id}/stream`;
	}

	async function playEpisode(ep: Episode) {
		currentEpisode = ep;
		duration = ep.duration || 0;
		currentTime = ep.progress_seconds || 0;

		audio.src = getAudioUrl(ep);
		audio.playbackRate = playbackRate;
		if (ep.progress_seconds > 0) {
			audio.currentTime = ep.progress_seconds;
		}
		await audio.play();

		apiPost('/api/media/playback/play', {
			episode_id: ep.id,
			position_seconds: ep.progress_seconds || 0,
		}).catch(() => {});
	}

	function togglePlayPause() {
		if (!currentEpisode) return;
		if (isPlaying) {
			audio.pause();
			apiPost('/api/media/playback/pause', {
				episode_id: currentEpisode.id,
				position_seconds: Math.floor(audio.currentTime),
			}).catch(() => {});
		} else {
			audio.play();
			apiPost('/api/media/playback/play', {
				episode_id: currentEpisode.id,
				position_seconds: Math.floor(audio.currentTime),
			}).catch(() => {});
		}
	}

	function seek(e: MouseEvent | TouchEvent) {
		const bar = (e.currentTarget as HTMLElement);
		const rect = bar.getBoundingClientRect();
		const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
		const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
		const newTime = pct * (duration || audio.duration || 0);
		audio.currentTime = newTime;
		currentTime = newTime;

		if (currentEpisode) {
			apiPost('/api/media/playback/seek', {
				episode_id: currentEpisode.id,
				position_seconds: Math.floor(newTime),
			}).catch(() => {});
		}
	}

	function setPlaybackRate(rate: number) {
		playbackRate = rate;
		audio.playbackRate = rate;
		localStorage.setItem('podcast-playback-rate', String(rate));
	}

	function skipBack() {
		audio.currentTime = Math.max(0, audio.currentTime - 15);
		currentTime = audio.currentTime;
	}

	function skipForward() {
		audio.currentTime = Math.min(audio.duration || 0, audio.currentTime + 30);
		currentTime = audio.currentTime;
	}

	async function handleEpisodeEnd() {
		if (currentEpisode) {
			await apiPost('/api/media/playback/complete', { episode_id: currentEpisode.id }).catch(() => {});
		}
		// Auto-advance queue
		if (queue.length > 0) {
			const next = queue[0];
			await playEpisode(next.episode);
			queue = queue.slice(1);
			await apiFetch(`/api/media/queue/${next.episode.id}`, { method: 'DELETE' }).catch(() => {});
		} else {
			isPlaying = false;
			currentEpisode = null;
		}
		loadEpisodes(selectedShowId);
	}

	async function reportProgress() {
		if (currentEpisode && isPlaying && audio.currentTime > 0) {
			apiPost('/api/media/playback/seek', {
				episode_id: currentEpisode.id,
				position_seconds: Math.floor(audio.currentTime),
			}).catch(() => {});
		}
	}

	// ── Queue management ──
	async function addToQueue(ep: Episode) {
		try {
			await apiPost('/api/media/queue/add', { episode_id: ep.id });
			await loadQueue();
		} catch { /* silent */ }
	}

	async function playNext(ep: Episode) {
		try {
			await apiPost('/api/media/queue/play-next', { episode_id: ep.id });
			await loadQueue();
		} catch { /* silent */ }
	}

	async function playNow(ep: Episode) {
		try {
			await apiPost('/api/media/queue/play-now', { episode_id: ep.id });
			await playEpisode(ep);
			await loadQueue();
		} catch { /* silent */ }
	}

	async function removeFromQueue(episodeId: string) {
		try {
			await apiFetch(`/api/media/queue/${episodeId}`, { method: 'DELETE' });
			queue = queue.filter(q => q.episode.id !== episodeId);
		} catch { /* silent */ }
	}

	async function clearQueue() {
		try {
			await apiFetch('/api/media/queue', { method: 'DELETE' });
			queue = [];
		} catch { /* silent */ }
	}

	async function moveQueueItem(fromIdx: number, toIdx: number) {
		if (toIdx < 0 || toIdx >= queue.length) return;
		const items = [...queue];
		const [moved] = items.splice(fromIdx, 1);
		items.splice(toIdx, 0, moved);
		queue = items;

		try {
			await apiPost('/api/media/queue/reorder', {
				episode_ids: items.map(q => q.episode.id),
			});
		} catch { /* silent */ }
	}

	// ── Formatters ──
	function formatDuration(seconds: number): string {
		if (!seconds || seconds <= 0) return '--:--';
		const h = Math.floor(seconds / 3600);
		const m = Math.floor((seconds % 3600) / 60);
		if (h > 0) return `${h}h ${m}m`;
		return `${m} min`;
	}

	function formatTime(seconds: number): string {
		if (!seconds || !isFinite(seconds) || seconds < 0) return '0:00';
		const h = Math.floor(seconds / 3600);
		const m = Math.floor((seconds % 3600) / 60);
		const s = Math.floor(seconds % 60);
		if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
		return `${m}:${String(s).padStart(2, '0')}`;
	}

	function formatDate(dateStr: string): string {
		if (!dateStr) return '';
		const d = new Date(dateStr);
		const now = new Date();
		const diff = now.getTime() - d.getTime();
		const days = Math.floor(diff / 86400000);
		if (days === 0) return 'Today';
		if (days === 1) return 'Yesterday';
		if (days < 7) return `${days}d ago`;
		if (days < 30) return `${Math.floor(days / 7)}w ago`;
		return d.toLocaleDateString('en-GB', { day: 'numeric', month: 'short' });
	}

	function progressPct(ep: Episode): number {
		if (!ep.duration || ep.duration <= 0) return 0;
		return Math.min(100, (ep.progress_seconds / ep.duration) * 100);
	}

	function artworkFor(ep: Episode): string {
		if (ep.artwork_url) return ep.artwork_url;
		const show = shows.find(s => s.id === ep.show_id);
		return show?.artwork_url || '';
	}

	const rates = [0.5, 1, 1.25, 1.5, 2];
	let showRateMenu = $state(false);
</script>

<div style="display:flex; min-height:calc(100vh - 60px); font-family:var(--font); position:relative;">

	<!-- ═══ Desktop Sidebar ═══ -->
	<aside style="
		width:248px; flex-shrink:0; min-height:0;
		background:rgba(245,237,228,0.82);
		border-right:1px solid rgba(35,26,17,0.08);
		display:flex; flex-direction:column;
		overflow-y:auto; padding:16px 0 12px;
		backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
	" class="desktop-sidebar">

		<!-- Sidebar header -->
		<div style="display:flex; align-items:center; justify-content:space-between; padding:0 18px 14px;">
			<div style="display:flex; align-items:center; gap:8px;">
				<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#1e1812" stroke-width="2"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
				<span style="font-size:1rem; font-weight:700; color:#1e1812; letter-spacing:-0.03em;">Podcasts</span>
			</div>
			<button
				style="width:28px; height:28px; border-radius:8px; border:none; background:none; color:#8c7b69; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 140ms; padding:0;"
				onclick={() => { showAddForm = !showAddForm; }}
				title="Add podcast"
				onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.72)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
				onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#8c7b69'; }}
			>
				<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
			</button>
		</div>

		<!-- Add form -->
		{#if showAddForm}
			<form style="display:flex; gap:4px; padding:0 12px 10px;" onsubmit={(e) => { e.preventDefault(); addShow(); }}>
				<input
					type="url"
					bind:value={feedUrl}
					placeholder="RSS feed URL..."
					style="flex:1; min-width:0; padding:7px 10px; border-radius:12px; border:1px solid rgba(35,26,17,0.12); background:rgba(255,255,255,0.7); font-size:0.78rem; font-family:var(--font); color:#1e1812; outline:none; transition:border-color 160ms;"
				/>
				<button
					type="submit"
					disabled={addingShow || !feedUrl.trim()}
					style="flex-shrink:0; padding:7px 10px; border-radius:12px; border:none; background:#1e1812; color:white; font-size:0.72rem; font-weight:600; font-family:var(--font); cursor:pointer; transition:opacity 160ms; opacity:{addingShow || !feedUrl.trim() ? '0.4' : '1'};"
				>
					{addingShow ? 'Adding...' : 'Add'}
				</button>
			</form>
			{#if error}
				<p style="color:#DC2626; font-size:0.72rem; padding:0 18px 8px; margin:0;">{error}</p>
			{/if}
		{/if}

		<!-- Section label -->
		<div style="padding:0 18px 6px;">
			<span style="font-size:0.68rem; font-weight:700; text-transform:uppercase; letter-spacing:0.14em; color:#8c7b69;">Shows</span>
		</div>

		<!-- Show list -->
		<div style="flex:1; overflow-y:auto; padding:0 8px 8px; display:flex; flex-direction:column; gap:1px;">
			<!-- All Episodes -->
			<button
				style="
					display:flex; align-items:center; gap:10px; width:100%; padding:9px 10px;
					border:none; border-radius:14px; cursor:pointer; text-align:left; font-family:var(--font);
					transition:all 160ms;
					background:{!selectedShowId ? 'rgba(255,248,241,0.92)' : 'none'};
					{!selectedShowId ? 'box-shadow:inset 0 0 0 1px rgba(35,26,17,0.08); border-left:3px solid rgba(179,92,50,0.6);' : 'border-left:3px solid transparent;'}
				"
				onclick={() => selectShow(null)}
				onmouseenter={(e) => { if (selectedShowId) (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.72)'; }}
				onmouseleave={(e) => { if (selectedShowId) (e.currentTarget as HTMLElement).style.background = 'none'; }}
			>
				<div style="width:36px; height:36px; border-radius:10px; background:rgba(179,92,50,0.08); display:flex; align-items:center; justify-content:center; flex-shrink:0; color:#7f5f3d;">
					<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
				</div>
				<div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:1px;">
					<span style="font-size:0.85rem; font-weight:{!selectedShowId ? '600' : '500'}; color:#1e1812; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">All Episodes</span>
					<span style="font-size:0.72rem; color:#8c7b69;">{shows.length} show{shows.length !== 1 ? 's' : ''}</span>
				</div>
				{#if totalUnplayed > 0}
					<span style="font-size:10px; font-weight:700; background:#059669; color:white; min-width:18px; height:18px; border-radius:999px; display:flex; align-items:center; justify-content:center; padding:0 5px; flex-shrink:0; font-family:var(--mono);">
						{totalUnplayed}
					</span>
				{/if}
			</button>

			{#each shows as show (show.id)}
				<button
					style="
						display:flex; align-items:center; gap:10px; width:100%; padding:9px 10px;
						border:none; border-radius:14px; cursor:pointer; text-align:left; font-family:var(--font);
						transition:all 160ms;
						background:{selectedShowId === show.id ? 'rgba(255,248,241,0.92)' : 'none'};
						{selectedShowId === show.id ? 'box-shadow:inset 0 0 0 1px rgba(35,26,17,0.08); border-left:3px solid rgba(179,92,50,0.6);' : 'border-left:3px solid transparent;'}
					"
					onclick={() => selectShow(show.id)}
					onmouseenter={(e) => { if (selectedShowId !== show.id) (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.72)'; }}
					onmouseleave={(e) => { if (selectedShowId !== show.id) (e.currentTarget as HTMLElement).style.background = 'none'; }}
				>
					{#if show.artwork_url}
						<img src={show.artwork_url} alt="" loading="lazy" style="width:36px; height:36px; border-radius:10px; object-fit:cover; flex-shrink:0;" />
					{:else}
						<div style="width:36px; height:36px; border-radius:10px; background:rgba(35,26,17,0.06); display:flex; align-items:center; justify-content:center; flex-shrink:0; color:#8c7b69;">
							<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
						</div>
					{/if}
					<div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:1px;">
						<span style="font-size:0.85rem; font-weight:{selectedShowId === show.id ? '600' : '500'}; color:#1e1812; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{show.title}</span>
						<span style="font-size:0.72rem; color:#8c7b69; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{show.author || `${show.episode_count} episodes`}</span>
					</div>
					{#if show.unplayed_count > 0}
						<span style="font-size:10px; font-weight:700; background:#059669; color:white; min-width:18px; height:18px; border-radius:999px; display:flex; align-items:center; justify-content:center; padding:0 5px; flex-shrink:0; font-family:var(--mono);">
							{show.unplayed_count}
						</span>
					{/if}
				</button>
			{/each}
		</div>
	</aside>

	<!-- ═══ Main Content ═══ -->
	<main style="flex:1; min-width:0; overflow-y:auto; max-height:calc(100vh - 60px); padding-bottom:{currentEpisode ? '100px' : '0'};" class="episodes-main">

		<!-- Mobile show pills (horizontal scroll) -->
		<div class="mobile-pills">
			<button
				class="show-pill"
				style="
					display:inline-flex; align-items:center; gap:6px; padding:6px 14px;
					border-radius:999px; border:1px solid {!selectedShowId ? 'rgba(179,92,50,0.3)' : 'rgba(35,26,17,0.08)'};
					background:{!selectedShowId ? 'rgba(179,92,50,0.12)' : 'rgba(255,252,248,0.82)'};
					color:{!selectedShowId ? '#7f5f3d' : '#2f2116'};
					font-size:0.78rem; font-weight:{!selectedShowId ? '700' : '500'}; font-family:var(--font);
					cursor:pointer; white-space:nowrap; flex-shrink:0; transition:all 160ms;
				"
				onclick={() => selectShow(null)}
			>
				All
				{#if totalUnplayed > 0}
					<span style="font-size:9px; font-weight:700; background:#059669; color:white; min-width:16px; height:16px; border-radius:999px; display:inline-flex; align-items:center; justify-content:center; padding:0 4px; font-family:var(--mono);">{totalUnplayed}</span>
				{/if}
			</button>
			{#each shows as show (show.id)}
				<button
					class="show-pill"
					style="
						display:inline-flex; align-items:center; gap:6px; padding:6px 14px;
						border-radius:999px; border:1px solid {selectedShowId === show.id ? 'rgba(179,92,50,0.3)' : 'rgba(35,26,17,0.08)'};
						background:{selectedShowId === show.id ? 'rgba(179,92,50,0.12)' : 'rgba(255,252,248,0.82)'};
						color:{selectedShowId === show.id ? '#7f5f3d' : '#2f2116'};
						font-size:0.78rem; font-weight:{selectedShowId === show.id ? '700' : '500'}; font-family:var(--font);
						cursor:pointer; white-space:nowrap; flex-shrink:0; transition:all 160ms;
					"
					onclick={() => selectShow(show.id)}
				>
					{#if show.artwork_url}
						<img src={show.artwork_url} alt="" style="width:16px; height:16px; border-radius:4px; object-fit:cover;" />
					{:else}
						<span style="width:16px; height:16px; border-radius:4px; background:rgba(35,26,17,0.08); display:inline-flex; align-items:center; justify-content:center;">
							<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="#8c7b69" stroke-width="2"><circle cx="5" cy="20" r="1"/></svg>
						</span>
					{/if}
					{show.title}
					{#if show.unplayed_count > 0}
						<span style="font-size:9px; font-weight:700; background:#059669; color:white; min-width:16px; height:16px; border-radius:999px; display:inline-flex; align-items:center; justify-content:center; padding:0 4px; font-family:var(--mono);">{show.unplayed_count}</span>
					{/if}
				</button>
			{/each}
			<!-- Mobile add button -->
			<button
				class="show-pill"
				style="display:inline-flex; align-items:center; gap:4px; padding:6px 12px; border-radius:999px; border:1px dashed rgba(35,26,17,0.15); background:none; color:#8c7b69; font-size:0.78rem; font-family:var(--font); cursor:pointer; white-space:nowrap; flex-shrink:0;"
				onclick={() => showAddForm = !showAddForm}
			>
				<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
				Add
			</button>
		</div>

		<!-- Mobile add form -->
		<div class="mobile-add-form">
			{#if showAddForm}
				<form style="display:flex; gap:6px; padding:0 16px 12px;" onsubmit={(e) => { e.preventDefault(); addShow(); }}>
					<input
						type="url"
						bind:value={feedUrl}
						placeholder="RSS feed URL..."
						style="flex:1; min-width:0; padding:9px 12px; border-radius:14px; border:1px solid rgba(35,26,17,0.12); background:rgba(255,255,255,0.7); font-size:0.82rem; font-family:var(--font); color:#1e1812; outline:none;"
					/>
					<button
						type="submit"
						disabled={addingShow || !feedUrl.trim()}
						style="flex-shrink:0; padding:9px 16px; border-radius:14px; border:none; background:#1e1812; color:white; font-size:0.78rem; font-weight:600; font-family:var(--font); cursor:pointer; opacity:{addingShow || !feedUrl.trim() ? '0.4' : '1'};"
					>
						{addingShow ? '...' : 'Add'}
					</button>
				</form>
				{#if error}
					<p style="color:#DC2626; font-size:0.72rem; padding:0 18px 8px; margin:0;">{error}</p>
				{/if}
			{/if}
		</div>

		<!-- Show banner (when a show is selected) -->
		{#if selectedShow}
			<div style="padding:24px 28px; border-bottom:1px solid rgba(35,26,17,0.08); background:rgba(250,246,239,0.6);" class="show-banner">
				<div style="display:flex; align-items:center; gap:18px;">
					{#if selectedShow.artwork_url}
						<img src={selectedShow.artwork_url} alt="" style="width:72px; height:72px; border-radius:16px; object-fit:cover; flex-shrink:0; box-shadow:0 4px 16px rgba(42,30,19,0.08);" />
					{/if}
					<div style="flex:1; min-width:0;">
						<h2 style="font-size:1.1rem; font-weight:700; color:#1e1812; line-height:1.3; margin:0; letter-spacing:-0.02em;">{selectedShow.title}</h2>
						<p style="font-size:0.85rem; color:#6b6256; margin:3px 0 0;">{selectedShow.author}</p>
						<p style="font-size:0.72rem; color:#8c7b69; margin:4px 0 0;">{selectedShow.episode_count} episodes &middot; {selectedShow.unplayed_count} unplayed</p>
					</div>
					<div style="display:flex; gap:6px; flex-shrink:0;">
						<button
							style="width:32px; height:32px; border-radius:10px; border:1px solid rgba(35,26,17,0.08); background:rgba(255,252,248,0.82); color:#6b6256; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 160ms; padding:0;"
							onclick={() => refreshShow(selectedShow.id)}
							title="Refresh feed"
							onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
							onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,252,248,0.82)'; (e.currentTarget as HTMLElement).style.color = '#6b6256'; }}
						>
							<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 4v6h-6"/><path d="M1 20v-6h6"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>
						</button>
						<button
							style="width:32px; height:32px; border-radius:10px; border:1px solid rgba(35,26,17,0.08); background:rgba(255,252,248,0.82); color:#6b6256; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 160ms; padding:0;"
							onclick={() => removeShow(selectedShow.id)}
							title="Unsubscribe"
							onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(220,38,38,0.06)'; (e.currentTarget as HTMLElement).style.color = '#DC2626'; }}
							onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,252,248,0.82)'; (e.currentTarget as HTMLElement).style.color = '#6b6256'; }}
						>
							<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
						</button>
					</div>
				</div>
			</div>
		{:else}
			<!-- Header for "All Episodes" -->
			<div style="padding:20px 28px 12px;" class="main-header">
				<div style="font-size:0.68rem; font-weight:700; text-transform:uppercase; letter-spacing:0.14em; color:#8c7b69;">Library</div>
				<div style="display:flex; align-items:baseline; justify-content:space-between; gap:16px;">
					<h2 style="font-size:1.3rem; font-weight:700; color:#1e1812; margin:4px 0 0; letter-spacing:-0.03em;">All Episodes</h2>
					<span style="font-size:0.82rem; color:#8c7b69;">{episodes.length} episodes</span>
				</div>
			</div>
		{/if}

		<!-- Episode list -->
		{#if loading}
			<div style="padding:20px 28px; display:flex; flex-direction:column; gap:12px;">
				{#each Array(6) as _, i}
					<div class="skeleton-card" style="display:flex; gap:14px; padding:16px; border-radius:18px; background:rgba(35,26,17,0.03);">
						<div style="width:56px; height:56px; border-radius:12px; background:rgba(35,26,17,0.06); flex-shrink:0;" class="shimmer"></div>
						<div style="flex:1; display:flex; flex-direction:column; gap:8px;">
							<div style="width:70%; height:14px; border-radius:6px; background:rgba(35,26,17,0.06);" class="shimmer"></div>
							<div style="width:40%; height:12px; border-radius:6px; background:rgba(35,26,17,0.06);" class="shimmer"></div>
						</div>
					</div>
				{/each}
			</div>
		{:else if episodes.length === 0}
			<div style="display:flex; flex-direction:column; align-items:center; justify-content:center; padding:80px 20px; color:#8c7b69; text-align:center; gap:12px;">
				<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="opacity:0.35;"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
				<p style="font-size:0.92rem; margin:0; color:rgba(93,72,55,0.76);">{shows.length === 0 ? 'No podcasts yet. Add a show to get started.' : 'No episodes found.'}</p>
			</div>
		{:else}
			<div style="padding:8px 16px 16px; display:flex; flex-direction:column; gap:8px;" class="episode-grid">
				{#each episodes as ep (ep.id)}
					{@const art = artworkFor(ep)}
					{@const pct = progressPct(ep)}
					{@const isActive = currentEpisode?.id === ep.id}
					<div
						class="episode-card"
						style="
							display:flex; align-items:center; gap:14px;
							padding:14px 16px; border-radius:18px;
							border:1px solid {isActive ? 'rgba(179,92,50,0.25)' : 'rgba(35,26,17,0.08)'};
							background:{isActive ? 'rgba(179,92,50,0.06)' : 'rgba(255,252,248,0.82)'};
							transition:all 160ms; cursor:pointer; position:relative;
							{isActive ? 'box-shadow:0 0 0 1px rgba(179,92,50,0.12), 0 4px 16px rgba(179,92,50,0.06);' : ''}
						"
						onmouseenter={(e) => { if (!isActive) { (e.currentTarget as HTMLElement).style.transform = 'translateY(-2px)'; (e.currentTarget as HTMLElement).style.boxShadow = '0 8px 24px rgba(42,30,19,0.08)'; } }}
						onmouseleave={(e) => { if (!isActive) { (e.currentTarget as HTMLElement).style.transform = 'none'; (e.currentTarget as HTMLElement).style.boxShadow = 'none'; } }}
						role="button"
						tabindex="0"
						onclick={() => playEpisode(ep)}
						onkeydown={(e) => { if (e.key === 'Enter') playEpisode(ep); }}
					>
						<!-- Artwork -->
						<div style="position:relative; width:56px; height:56px; flex-shrink:0;">
							{#if art}
								<img src={art} alt="" loading="lazy" style="width:56px; height:56px; border-radius:12px; object-fit:cover;" />
							{:else}
								<div style="width:56px; height:56px; border-radius:12px; background:rgba(35,26,17,0.06); display:flex; align-items:center; justify-content:center; color:#8c7b69;">
									<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
								</div>
							{/if}
							<!-- Play overlay -->
							<div class="play-hover" style="
								position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
								background:rgba(30,24,18,0.5); border-radius:12px; opacity:0; transition:opacity 160ms; color:white;
							">
								{#if isActive && isPlaying}
									<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>
								{:else}
									<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><polygon points="5,3 19,12 5,21"/></svg>
								{/if}
							</div>
						</div>

						<!-- Body -->
						<div style="flex:1; min-width:0;">
							<div style="font-size:0.92rem; font-weight:{ep.status === 'unplayed' ? '600' : '400'}; color:#1e1812; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; line-height:1.35;">
								{ep.title}
							</div>
							<div style="display:flex; align-items:center; gap:5px; margin-top:3px; font-size:0.78rem; color:#8c7b69;">
								{#if !selectedShowId}
									<span style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:140px;">{ep.show_title}</span>
									<span style="opacity:0.4;">&middot;</span>
								{/if}
								<span>{formatDate(ep.published_at)}</span>
								<span style="opacity:0.4;">&middot;</span>
								<span>{formatDuration(ep.duration)}</span>
								{#if ep.status === 'in-progress' && pct > 0}
									<span style="opacity:0.4;">&middot;</span>
									<span style="color:#7f5f3d; font-weight:600;">{Math.round(pct)}%</span>
								{/if}
							</div>
							{#if ep.status === 'in-progress' && pct > 0}
								<div style="width:100%; height:3px; background:rgba(35,26,17,0.08); border-radius:999px; margin-top:8px; overflow:hidden;">
									<div style="height:100%; background:#5d4737; border-radius:999px; width:{pct}%; transition:width 0.3s ease;"></div>
								</div>
							{/if}
						</div>

						<!-- Actions -->
						<div class="ep-actions" style="display:flex; gap:4px; flex-shrink:0; opacity:0; transition:opacity 160ms;" onclick={(e) => e.stopPropagation()}>
							<button
								style="width:32px; height:32px; border-radius:10px; border:none; background:none; color:#6b6256; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 160ms; padding:0;"
								onclick={(e) => { e.stopPropagation(); addToQueue(ep); }}
								title="Add to queue"
								onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
								onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#6b6256'; }}
							>
								<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
							</button>
							<button
								style="width:32px; height:32px; border-radius:10px; border:none; background:none; color:#6b6256; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 160ms; padding:0;"
								onclick={(e) => { e.stopPropagation(); playNext(ep); }}
								title="Play next"
								onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
								onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#6b6256'; }}
							>
								<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="5,4 15,12 5,20"/><line x1="19" y1="5" x2="19" y2="19"/></svg>
							</button>
						</div>
					</div>
				{/each}
			</div>
		{/if}
	</main>
</div>

<!-- ═══ Player Bar (sticky bottom, glassmorphic) ═══ -->
{#if currentEpisode}
	{@const playerArt = artworkFor(currentEpisode)}
	<div style="
		position:fixed; bottom:0; left:0; right:0; z-index:50;
		background:rgba(250,246,239,0.82); backdrop-filter:blur(24px); -webkit-backdrop-filter:blur(24px);
		border-top:1px solid rgba(35,26,17,0.08);
		box-shadow:0 -4px 24px rgba(42,30,19,0.06);
		padding:10px 20px; padding-bottom:calc(10px + env(safe-area-inset-bottom, 0px));
	" class="player-bar">
		<div style="display:flex; align-items:center; gap:14px; max-width:1280px; margin:0 auto;" class="player-inner">
			<!-- Episode info -->
			<div style="display:flex; align-items:center; gap:12px; min-width:0; flex:0 1 220px;" class="player-info">
				{#if playerArt}
					<img src={playerArt} alt="" style="width:48px; height:48px; border-radius:12px; object-fit:cover; flex-shrink:0; box-shadow:0 2px 8px rgba(42,30,19,0.1);" />
				{:else}
					<div style="width:48px; height:48px; border-radius:12px; background:rgba(35,26,17,0.06); display:flex; align-items:center; justify-content:center; color:#8c7b69; flex-shrink:0;">
						<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 11a9 9 0 0 1 9 9"/><path d="M4 4a16 16 0 0 1 16 16"/><circle cx="5" cy="20" r="1"/></svg>
					</div>
				{/if}
				<div style="min-width:0; display:flex; flex-direction:column; gap:2px;">
					<span style="font-size:0.85rem; font-weight:600; color:#1e1812; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{currentEpisode.title}</span>
					<span style="font-size:0.72rem; color:#8c7b69; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{currentEpisode.show_title}</span>
				</div>
			</div>

			<!-- Controls -->
			<div style="display:flex; align-items:center; gap:6px; flex-shrink:0;" class="player-controls">
				<button
					style="position:relative; width:36px; height:36px; border:none; background:none; cursor:pointer; color:#2f2116; display:flex; align-items:center; justify-content:center; border-radius:999px; transition:all 160ms; padding:0;"
					onclick={skipBack}
					title="Back 15s"
					onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; }}
					onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; }}
				>
					<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 4v6h6"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>
					<span style="position:absolute; font-size:8px; font-weight:700; color:inherit; font-family:var(--mono); bottom:4px;">15</span>
				</button>

				<button
					style="width:44px; height:44px; border-radius:999px; border:none; background:#1e1812; color:#faf6ef; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:all 160ms; flex-shrink:0;"
					onclick={togglePlayPause}
					class="play-main-btn"
				>
					{#if isPlaying}
						<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>
					{:else}
						<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><polygon points="5,3 19,12 5,21"/></svg>
					{/if}
				</button>

				<button
					style="position:relative; width:36px; height:36px; border:none; background:none; cursor:pointer; color:#2f2116; display:flex; align-items:center; justify-content:center; border-radius:999px; transition:all 160ms; padding:0;"
					onclick={skipForward}
					title="Forward 30s"
					onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; }}
					onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; }}
				>
					<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 4v6h-6"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
					<span style="position:absolute; font-size:8px; font-weight:700; color:inherit; font-family:var(--mono); bottom:4px;">30</span>
				</button>
			</div>

			<!-- Progress -->
			<div style="display:flex; align-items:center; gap:8px; flex:1; min-width:0;" class="player-progress">
				<span style="font-size:11px; font-family:var(--mono); color:#8c7b69; min-width:40px; text-align:center; flex-shrink:0; user-select:none;">{formatTime(currentTime)}</span>
				<div
					class="progress-bar-track"
					style="flex:1; height:3px; background:rgba(35,26,17,0.1); border-radius:999px; cursor:pointer; position:relative; transition:height 160ms;"
					onclick={seek}
					role="slider"
					tabindex="0"
					aria-valuenow={currentTime}
					aria-valuemin={0}
					aria-valuemax={duration}
				>
					<div style="height:100%; background:#5d4737; border-radius:999px; position:relative; transition:width 0.1s linear; max-width:100%; width:{duration > 0 ? (currentTime / duration) * 100 : 0}%;">
						<div class="progress-thumb" style="position:absolute; right:-5px; top:50%; transform:translateY(-50%); width:12px; height:12px; border-radius:999px; background:#5d4737; box-shadow:0 2px 6px rgba(42,30,19,0.18); opacity:0; transition:opacity 160ms;"></div>
					</div>
				</div>
				<span style="font-size:11px; font-family:var(--mono); color:#8c7b69; min-width:40px; text-align:center; flex-shrink:0; user-select:none;">{formatTime(duration)}</span>
			</div>

			<!-- Right actions -->
			<div style="display:flex; align-items:center; gap:6px; flex-shrink:0;" class="player-right">
				<!-- Speed -->
				<div style="position:relative;">
					<button
						style="padding:4px 10px; border-radius:999px; border:1px solid rgba(35,26,17,0.1); background:none; font-size:0.72rem; font-weight:600; font-family:var(--mono); color:#2f2116; cursor:pointer; transition:all 160ms;"
						onclick={() => showRateMenu = !showRateMenu}
						onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; }}
						onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; }}
					>
						{playbackRate}x
					</button>
					{#if showRateMenu}
						<div style="
							position:absolute; bottom:calc(100% + 8px); right:0;
							background:rgba(255,252,248,0.96); border:1px solid rgba(35,26,17,0.1);
							border-radius:14px; box-shadow:0 12px 32px rgba(42,30,19,0.12);
							padding:4px; display:flex; flex-direction:column; z-index:60;
							backdrop-filter:blur(20px); -webkit-backdrop-filter:blur(20px);
						">
							{#each rates as rate}
								<button
									style="padding:7px 16px; font-size:0.85rem; font-family:var(--mono); border:none; background:none; color:{playbackRate === rate ? '#7f5f3d' : '#2f2116'}; cursor:pointer; border-radius:10px; text-align:left; white-space:nowrap; transition:all 160ms; font-weight:{playbackRate === rate ? '700' : '500'};"
									onclick={() => { setPlaybackRate(rate); showRateMenu = false; }}
									onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; }}
									onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; }}
								>
									{rate}x
								</button>
							{/each}
						</div>
					{/if}
				</div>

				<!-- Queue -->
				<button
					style="position:relative; width:36px; height:36px; border:none; background:none; cursor:pointer; color:#6b6256; display:flex; align-items:center; justify-content:center; border-radius:10px; transition:all 160ms; padding:0;"
					onclick={() => showQueue = !showQueue}
					title="Queue"
					onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
					onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#6b6256'; }}
				>
					<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
					{#if queue.length > 0}
						<span style="position:absolute; top:2px; right:2px; min-width:14px; height:14px; border-radius:999px; background:#059669; color:white; font-size:9px; font-weight:700; display:flex; align-items:center; justify-content:center; padding:0 3px; font-family:var(--mono);">
							{queue.length}
						</span>
					{/if}
				</button>
			</div>
		</div>
	</div>
{/if}

<!-- ═══ Queue Panel (slide from right) ═══ -->
{#if showQueue}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div
		style="position:fixed; inset:0; background:rgba(17,13,10,0.3); z-index:80;"
		onclick={() => showQueue = false}
	></div>
	<aside style="
		position:fixed; top:0; right:0; bottom:0; width:380px; max-width:90vw;
		background:rgba(250,246,239,0.96); backdrop-filter:blur(24px); -webkit-backdrop-filter:blur(24px);
		border-left:1px solid rgba(35,26,17,0.08);
		box-shadow:-8px 0 32px rgba(42,30,19,0.1);
		z-index:90; display:flex; flex-direction:column;
		animation:queueSlideIn 0.22s ease;
	">
		<!-- Queue header -->
		<div style="display:flex; align-items:center; justify-content:space-between; padding:20px 20px 16px; border-bottom:1px solid rgba(35,26,17,0.08);">
			<div>
				<div style="font-size:0.68rem; font-weight:700; text-transform:uppercase; letter-spacing:0.14em; color:#8c7b69;">Up next</div>
				<span style="font-size:1rem; font-weight:700; color:#1e1812; letter-spacing:-0.03em;">Queue</span>
			</div>
			<div style="display:flex; align-items:center; gap:8px;">
				{#if queue.length > 0}
					<button
						style="padding:5px 12px; border-radius:999px; border:1px solid rgba(35,26,17,0.1); background:none; color:#6b6256; font-size:0.72rem; font-weight:600; font-family:var(--font); cursor:pointer; transition:all 160ms;"
						onclick={clearQueue}
						onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.95)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
						onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#6b6256'; }}
					>Clear</button>
				{/if}
				<button
					style="width:28px; height:28px; border-radius:8px; border:none; background:none; color:#8c7b69; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 140ms; padding:0;"
					onclick={() => showQueue = false}
					onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.72)'; (e.currentTarget as HTMLElement).style.color = '#1e1812'; }}
					onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#8c7b69'; }}
				>
					<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
				</button>
			</div>
		</div>

		{#if queue.length === 0}
			<div style="flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; color:#8c7b69; gap:6px; padding:40px;">
				<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="opacity:0.3;"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
				<p style="font-size:0.92rem; font-weight:600; margin:0; color:#6b6256;">Queue is empty</p>
				<span style="font-size:0.82rem; color:#8c7b69;">Add episodes from the list</span>
			</div>
		{:else}
			<div style="flex:1; overflow-y:auto; padding:8px 10px;">
				{#each queue as item, idx (item.episode.id)}
					{@const qArt = artworkFor(item.episode)}
					<div style="
						display:flex; align-items:center; gap:10px; padding:10px;
						border-radius:14px; transition:background 160ms;
						{idx > 0 ? 'margin-top:2px;' : ''}
					"
						onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(255,248,241,0.72)'; }}
						onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'transparent'; }}
					>
						<!-- Reorder -->
						<div style="display:flex; flex-direction:column; gap:1px; flex-shrink:0;">
							<button
								disabled={idx === 0}
								onclick={() => moveQueueItem(idx, idx - 1)}
								title="Move up"
								style="width:22px; height:16px; border:none; background:none; cursor:{idx === 0 ? 'default' : 'pointer'}; color:#8c7b69; display:flex; align-items:center; justify-content:center; padding:0; border-radius:4px; transition:all 160ms; opacity:{idx === 0 ? '0.2' : '1'};"
							>
								<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"/></svg>
							</button>
							<button
								disabled={idx === queue.length - 1}
								onclick={() => moveQueueItem(idx, idx + 1)}
								title="Move down"
								style="width:22px; height:16px; border:none; background:none; cursor:{idx === queue.length - 1 ? 'default' : 'pointer'}; color:#8c7b69; display:flex; align-items:center; justify-content:center; padding:0; border-radius:4px; transition:all 160ms; opacity:{idx === queue.length - 1 ? '0.2' : '1'};"
							>
								<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>
							</button>
						</div>

						<!-- Artwork -->
						{#if qArt}
							<img src={qArt} alt="" loading="lazy" style="width:40px; height:40px; border-radius:10px; object-fit:cover; flex-shrink:0;" />
						{:else}
							<div style="width:40px; height:40px; border-radius:10px; background:rgba(35,26,17,0.06); display:flex; align-items:center; justify-content:center; color:#8c7b69; flex-shrink:0;">
								<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="5" cy="20" r="1"/></svg>
							</div>
						{/if}

						<!-- Info -->
						<div style="flex:1; min-width:0; display:flex; flex-direction:column; gap:2px;">
							<span style="font-size:0.82rem; font-weight:600; color:#1e1812; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{item.episode.title}</span>
							<span style="font-size:0.7rem; color:#8c7b69; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{item.episode.show_title}</span>
						</div>

						<!-- Remove -->
						<button
							style="width:28px; height:28px; border-radius:8px; border:none; background:none; color:#8c7b69; display:flex; align-items:center; justify-content:center; cursor:pointer; transition:all 140ms; padding:0; flex-shrink:0;"
							onclick={() => removeFromQueue(item.episode.id)}
							title="Remove"
							onmouseenter={(e) => { (e.currentTarget as HTMLElement).style.background = 'rgba(220,38,38,0.08)'; (e.currentTarget as HTMLElement).style.color = '#DC2626'; }}
							onmouseleave={(e) => { (e.currentTarget as HTMLElement).style.background = 'none'; (e.currentTarget as HTMLElement).style.color = '#8c7b69'; }}
						>
							<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
						</button>
					</div>
				{/each}
			</div>
		{/if}
	</aside>
{/if}

<style>
	/* ═══ Queue slide animation ═══ */
	@keyframes queueSlideIn {
		from { transform: translateX(100%); }
		to { transform: translateX(0); }
	}

	/* ═══ Shimmer animation ═══ */
	.shimmer {
		animation: shimmer 1.6s infinite;
	}
	@keyframes shimmer {
		0%, 100% { opacity: 0.6; }
		50% { opacity: 1; }
	}

	/* ═══ Episode card hover ═══ */
	.episode-card:hover .ep-actions { opacity: 1 !important; }
	.episode-card:hover .play-hover { opacity: 1 !important; }

	/* ═══ Progress bar hover ═══ */
	.progress-bar-track:hover { height: 6px !important; }
	.progress-bar-track:hover .progress-thumb { opacity: 1 !important; }

	/* ═══ Play button hover ═══ */
	.play-main-btn:hover { opacity: 0.9; transform: scale(1.05); }
	.play-main-btn:active { transform: scale(0.95); }

	/* ═══ Mobile pills — hidden on desktop ═══ */
	.mobile-pills {
		display: none;
	}
	.mobile-add-form {
		display: none;
	}

	/* ═══ Desktop sidebar — visible on desktop ═══ */
	.desktop-sidebar {
		display: flex !important;
	}

	/* ═══ Mobile breakpoint ═══ */
	@media (max-width: 768px) {
		.desktop-sidebar {
			display: none !important;
		}

		.mobile-pills {
			display: flex;
			gap: 8px;
			padding: 12px 16px 6px;
			overflow-x: auto;
			-webkit-overflow-scrolling: touch;
			scrollbar-width: none;
		}
		.mobile-pills::-webkit-scrollbar { display: none; }

		.mobile-add-form {
			display: block;
		}

		.episodes-main {
			max-height: none !important;
		}

		.show-banner {
			padding: 18px 16px !important;
		}

		.main-header {
			padding: 14px 16px 8px !important;
		}

		.episode-grid {
			padding: 8px 12px 16px !important;
		}

		.episode-card .ep-actions {
			opacity: 1 !important;
		}

		/* Player bar responsive */
		.player-inner {
			flex-wrap: wrap !important;
			gap: 6px !important;
		}
		.player-info {
			flex: 1 1 100% !important;
			order: 1;
		}
		.player-progress {
			flex: 1 1 100% !important;
			order: 2;
		}
		.player-controls {
			order: 3;
		}
		.player-right {
			order: 4;
			margin-left: auto;
		}
	}

	@media (max-width: 480px) {
		.player-info {
			flex-basis: auto !important;
		}
		.player-inner {
			gap: 4px !important;
		}
	}
</style>
