(function(){
	var initCoverFlow = function(){
		var roots = document.querySelectorAll('.thespl-player[data-template-slug="cover-flow"]');
		if (!roots || !roots.forEach) { return; }
		roots.forEach(function(root){
			try {
				if (window.THESPL_Player_Store && typeof window.THESPL_Player_Store.init === 'function') {
					window.THESPL_Player_Store.init(root);
				}
			} catch(e){}

			var attempts = 0;
			var MAX = 30;

			var tryBind = function(){
				var api = null;
				try { api = root._thesplPlayerApi || null; } catch(e){}

				try { if (window.THESPL_Player_UI && typeof window.THESPL_Player_UI.bindAudioInfo  === 'function') window.THESPL_Player_UI.bindAudioInfo(root);            } catch(e){}
				try { if (window.THESPL_Player_UI && typeof window.THESPL_Player_UI.setInfotextMode === 'function') window.THESPL_Player_UI.setInfotextMode(root, 'scroll'); } catch(e){}
				try { if (window.THESPL_Player_UI && typeof window.THESPL_Player_UI.bindInfotext    === 'function') window.THESPL_Player_UI.bindInfotext(root);              } catch(e){}
				bindAudioInfoToggle(root);

				if (!api) {
					if (attempts >= MAX) { return; }
					attempts++;
					window.setTimeout(tryBind, 100);
					return;
				}

				try { if (window.THESPL_Player_UI && typeof window.THESPL_Player_UI.bindVariants  === 'function') window.THESPL_Player_UI.bindVariants(root, api);  } catch(e){}
				try { if (window.THESPL_Player_UI && typeof window.THESPL_Player_UI.bindTransport === 'function') window.THESPL_Player_UI.bindTransport(root, api); } catch(e){}
				try { if (window.THESPL_Player_UI && typeof window.THESPL_Player_UI.renderStatus  === 'function') window.THESPL_Player_UI.renderStatus(root);        } catch(e){}

				bindControls(root, api);
				buildCoverflow(root, api);
				initWaveformCanvas(root, api);
			};
			tryBind();
		});
	};

	var bindAudioInfoToggle = function(root){
		var bt    = root.querySelector('.thespl-player__audio-info-toggle');
		var panel = root.querySelector('.thespl-player__audio-info-panel');
		if (!bt || !panel) { return; }
		if (bt.getAttribute('data-thespl-toggle-bound') === '1') { return; }
		bt.setAttribute('data-thespl-toggle-bound', '1');
		var label = bt.querySelector('.thespl-player__audio-info-toggle-label');
		var txtOpen = String(bt.getAttribute('data-label-open') || 'Show Audio Info');
		var txtClose = String(bt.getAttribute('data-label-close') || 'Hide Audio Info');
		var setState = function(open){
			bt.setAttribute('aria-expanded', open ? 'true' : 'false');
			panel.classList.toggle('is-collapsed', !open);
			panel.setAttribute('aria-hidden', open ? 'false' : 'true');
			if (label) {
				label.textContent = open ? txtClose : txtOpen;
			}
		};
		setState(false);
		bt.addEventListener('click', function(){
			var open = bt.getAttribute('aria-expanded') === 'true';
			setState(!open);
		});
	};

	var bindControls = function(root, api){
		var audio = root.querySelector('.thespl-player__audio');
		var bt = root.querySelector('.thespl-player__btn--toggle');
		var labelEl = bt ? bt.querySelector('.thespl-player__btn-label') : null;

		var setToggleState = function(isPlaying){
			if (!bt) { return; }
			bt.setAttribute('aria-pressed', isPlaying ? 'true' : 'false');
			bt.setAttribute('data-state', isPlaying ? 'pause' : 'play');
			bt.setAttribute('aria-label', isPlaying ? 'Pause' : 'Play');
			if (labelEl) { labelEl.textContent = isPlaying ? 'Pause' : 'Play'; }
		};

		setToggleState(false);

		if (audio) {
			audio.addEventListener('play', function(){ setToggleState(true); });
			audio.addEventListener('pause', function(){ setToggleState(false); });
			audio.addEventListener('ended', function(){ setToggleState(false); });
		}
	};

	var buildCoverflow = function(root, api){
		var store    = window.THESPL_Player_Store || null;
		var playlist = store && typeof store.getPlaylist === 'function' ? store.getPlaylist(root) : null;
		var tracks   = (playlist && Array.isArray(playlist.tracks)) ? playlist.tracks : [];
		var wrap     = root.querySelector('.thespl-player__playlist');
		if (!wrap) { return; }
		wrap.innerHTML = '';
		if (!tracks.length) {
			if (store && typeof store.subscribe === 'function'){
				var bootstrapped = false;
				store.subscribe(root, function(){
					if (bootstrapped) { return; }
					var livePlaylist = typeof store.getPlaylist === 'function' ? store.getPlaylist(root) : null;
					var liveTracks = (livePlaylist && Array.isArray(livePlaylist.tracks)) ? livePlaylist.tracks : [];
					if (liveTracks.length) {
						bootstrapped = true;
						try { buildCoverflow(root, api); } catch(e){}
					}
				});
			}
			return;
		}

		var cfg         = window.thesplPlayer || {};
		var fallbackUrl = typeof cfg.defaultCoverUrl === 'string' ? cfg.defaultCoverUrl : '';
		var current     = 0;
		var titleEl     = root.querySelector('.thespl-cf-track-title');
		var artistEl    = root.querySelector('.thespl-cf-track-artist');

		var updateMeta = function(idx){
			var t = tracks[idx] || null;
			if (titleEl)  titleEl.textContent  = t ? (t.title  || '') : '';
			if (artistEl) artistEl.textContent = t ? (t.artist || '') : '';
		};

		var applyTransforms = function(){
			var items = wrap.querySelectorAll('.thespl-cf-item');
			for (var i = 0; i < items.length; i++){
				var el     = items[i];
				var idx    = parseInt(el.getAttribute('data-index') || '0', 10);
				var offset = idx - current;
				var abs    = Math.abs(offset);
				var scale  = Math.max(0.52, 1 - abs * 0.15);
				var rotY   = offset === 0 ? 0 : (offset < 0 ? 44 : -44);
				var tx     = offset * 64;
				var tz     = offset === 0 ? 0 : -Math.min(90, abs * 60);
				var op     = Math.max(0.25, 1 - abs * 0.24);
				el.style.zIndex    = String(100 - abs);
				el.style.transform = 'translateX(' + tx + '%) translateZ(' + tz + 'px) rotateY(' + rotY + 'deg) scale(' + scale + ')';
				el.style.opacity   = String(op);
				el.setAttribute('aria-selected', idx === current ? 'true' : 'false');
			}
		};

		var selectTrack = function(idx, autoPlay){
			idx     = Math.max(0, Math.min(tracks.length - 1, idx));
			current = idx;
			applyTransforms();
			updateMeta(idx);
			if (autoPlay) {
				try { api.playTrack(current); } catch(e){
					try { api.play(); } catch(ee){}
				}
			}
		};

		for (var i = 0; i < tracks.length; i++){
			(function(idx){
				var t    = tracks[idx];
				var item = document.createElement('button');
				item.type      = 'button';
				item.className = 'thespl-cf-item';
				item.setAttribute('role', 'option');
				item.setAttribute('data-index', String(idx));
				item.setAttribute('aria-selected', idx === current ? 'true' : 'false');
				var img = document.createElement('img');
				img.className = 'thespl-cf-img';
				img.alt = '';
				img.src = (t.cover && t.cover.url) ? t.cover.url : fallbackUrl;
				item.appendChild(img);
				item.addEventListener('click', function(e){
					e.stopPropagation();
					selectTrack(idx, true);
				});
				item.addEventListener('keydown', function(e){
					if (e.key === 'Enter' || e.key === ' '){ e.preventDefault(); selectTrack(idx, true); }
					if (e.key === 'ArrowRight'){ e.preventDefault(); selectTrack(current + 1, true); }
					if (e.key === 'ArrowLeft' ){ e.preventDefault(); selectTrack(current - 1, true); }
				});
				wrap.appendChild(item);
			})(i);
		}

		applyTransforms();
		updateMeta(0);

		var arPrev = root.querySelector('.thespl-cf-arrow--prev');
		var arNext = root.querySelector('.thespl-cf-arrow--next');
		if (arPrev) arPrev.addEventListener('click', function(){ selectTrack(current - 1, true); });
		if (arNext) arNext.addEventListener('click', function(){ selectTrack(current + 1, true); });

		var stage     = root.querySelector('.thespl-cf-stage');
		var pDown     = false;
		var pStartX   = 0;
		var pCurX     = 0;
		var threshold = 44;

		if (stage){
			stage.addEventListener('pointerdown', function(e){
				if (e.button !== 0) { return; }
				pDown = true; pStartX = e.clientX; pCurX = e.clientX;
				try { stage.setPointerCapture(e.pointerId); } catch(err){}
			});
			stage.addEventListener('pointermove', function(e){
				if (!pDown) { return; }
				pCurX = e.clientX;
			});
			var endPointer = function(e){
				if (!pDown) { return; }
				pDown = false;
				try { stage.releasePointerCapture(e.pointerId); } catch(err){}
				var dx = pCurX - pStartX;
				if (Math.abs(dx) > threshold){ selectTrack(dx < 0 ? current + 1 : current - 1, true); }
			};
			stage.addEventListener('pointerup',     endPointer);
			stage.addEventListener('pointercancel', endPointer);

			var tStartX = 0, tCurX = 0;
			stage.addEventListener('touchstart', function(e){
				var t = e.touches[0]; if (!t) { return; }
				tStartX = t.clientX; tCurX = t.clientX;
			}, { passive: true });
			stage.addEventListener('touchmove', function(e){
				var t = e.touches[0]; if (!t) { return; }
				tCurX = t.clientX;
			}, { passive: true });
			stage.addEventListener('touchend', function(){
				var dx = tCurX - tStartX;
				if (Math.abs(dx) > threshold){ selectTrack(dx < 0 ? current + 1 : current - 1, true); }
			}, { passive: true });
		}

		if (store && typeof store.subscribe === 'function'){
			store.subscribe(root, function(){
				var live = store.getLive(root);
				if (!live || typeof live.trackIndex !== 'number') { return; }
				var ti = live.trackIndex;
				if (ti === current || ti < 0 || ti >= tracks.length) { return; }
				current = ti;
				applyTransforms();
				updateMeta(current);
			});
		}
	};

	var initWaveformCanvas = function(root, api){
		var canvas = root.querySelector('.thespl-player__canvas');
		var audio  = root.querySelector('.thespl-player__audio');
		if (!canvas || !audio || !canvas.getContext) { return; }
		var ctx = canvas.getContext('2d');
		if (!ctx) { return; }

		var store    = window.THESPL_Player_Store || null;
		var W        = canvas.width  || 900;
		var H        = canvas.height || 140;
		var midY     = H / 2;
		var barW     = 2;
		var barStep  = barW + 1;

		var targetProgress   = 0;
		var drawProgress     = 0;
		var targetBuffered   = 0;
		var drawBuffered     = 0;
		var isDragging       = false;
		var dragProgress     = 0;
		var lastScrubMs      = 0;
		var touchStartX      = 0;
		var touchStartY      = 0;
		var touchMode        = 'idle';
		var waveformCache    = {};
		var currentWaveforms = [];
		var waveReqId        = 0;
		var lastTrackKey     = '';

		var clamp01 = function(v){
			v = typeof v === 'number' && isFinite(v) ? v : 0;
			return v < 0 ? 0 : v > 1 ? 1 : v;
		};

		var getCssProp = function(prop){
			try {
				var v = window.getComputedStyle(root).getPropertyValue(prop);
				return v ? v.trim() : '';
			} catch(e){ return ''; }
		};

		var parseRgb = function(color){
			if (!color) { return null; }
			var c = String(color).trim();
			var m = c.match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/i);
			if (m) {
				return [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10)];
			}
			var h = c.replace(/^#/, '');
			if (/^[0-9a-fA-F]{3}$/.test(h)) {
				return [
					parseInt(h.charAt(0) + h.charAt(0), 16),
					parseInt(h.charAt(1) + h.charAt(1), 16),
					parseInt(h.charAt(2) + h.charAt(2), 16)
				];
			}
			if (/^[0-9a-fA-F]{6}$/.test(h)) {
				return [
					parseInt(h.slice(0, 2), 16),
					parseInt(h.slice(2, 4), 16),
					parseInt(h.slice(4, 6), 16)
				];
			}
			return null;
		};

		var getTheme = function(){
			var accent   = getCssProp('--thespl-accent')   || getCssProp('--thespl-cf-accent');
			var buffered = getCssProp('--thespl-buffered')  || getCssProp('--thespl-cf-buffered');
			var waveform = getCssProp('--thespl-waveform')  || getCssProp('--thespl-wave') || getCssProp('--thespl-cf-waveform');
			if (!buffered && accent) {
				var rgb = parseRgb(accent);
				if (rgb && rgb.length === 3) {
					var alpha = parseFloat(getCssProp('--thespl-cf-buffer-alpha') || '0.22');
					if (!isFinite(alpha) || alpha < 0) { alpha = 0.22; }
					if (alpha > 1) { alpha = 1; }
					buffered = 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + alpha + ')';
				}
			}
			return {
				accent:   accent   || '#22d3ee',
				buffered: buffered || 'rgba(34,211,238,0.22)',
				waveform: waveform || '#5a5a5a'
			};
		};

		var formatTime = function(s){
			s = isFinite(s) && s > 0 ? Math.floor(s) : 0;
			var m  = Math.floor(s / 60);
			var ss = String(s % 60);
			if (ss.length < 2) { ss = '0' + ss; }
			return m + ':' + ss;
		};

		var getBufferedEnd = function(){
			try {
				var b = audio.buffered;
				if (!b || !b.length) { return 0; }
				var mx = 0;
				for (var i = 0; i < b.length; i++) { var e = b.end(i); if (e > mx) mx = e; }
				return mx;
			} catch(e){ return 0; }
		};

		var drawFrame = function(){
			if (!ctx || !canvas) { return; }
			var theme = getTheme();
			drawProgress = drawProgress + (targetProgress - drawProgress) * 0.18;
			drawBuffered = drawBuffered + (targetBuffered - drawBuffered) * 0.18;

			ctx.clearRect(0, 0, W, H);

			var wf = [];
			try {
				var sel = store && typeof store.getSelection === 'function' ? store.getSelection(root) : null;
				var vi  = sel && typeof sel.variantIndex === 'number' ? sel.variantIndex : 0;
				wf = (currentWaveforms[vi] || currentWaveforms[0]) || [];
			} catch(e){ wf = currentWaveforms[0] || []; }

			var n         = wf ? wf.length : 0;
			var totalBars = Math.floor(W / barStep);

			for (var bi = 0; bi < totalBars; bi++){
				var t   = bi / (totalBars - 1 || 1);
				var bx  = bi * barStep;
				var amp = n > 0 ? (wf[Math.floor(t * (n - 1))] || 0) : 0.18;
				var bh  = Math.max(2, amp * (midY - 4));

				if (t <= drawProgress) {
					ctx.fillStyle = theme.accent;
				} else if (t <= drawBuffered) {
					ctx.fillStyle = theme.buffered;
				} else {
					ctx.fillStyle = theme.waveform;
				}
				ctx.fillRect(bx, midY - bh, barW, bh);
				ctx.globalAlpha = 0.32;
				ctx.fillRect(bx, midY, barW, bh);
				ctx.globalAlpha = 1;
			}

			var headX = Math.round(drawProgress * W);
			ctx.save();
			ctx.beginPath();
			ctx.moveTo(headX, 4);
			ctx.lineTo(headX, H - 4);
			ctx.strokeStyle = theme.accent;
			ctx.lineWidth   = 2;
			ctx.stroke();
			ctx.beginPath();
			ctx.arc(headX, midY, 5, 0, Math.PI * 2);
			ctx.fillStyle   = theme.accent;
			ctx.shadowColor = theme.accent;
			ctx.shadowBlur  = 8;
			ctx.fill();
			ctx.restore();

			var curEl = root.querySelector('.thespl-cf-time-current');
			var durEl = root.querySelector('.thespl-cf-time-total');
			if (curEl) curEl.textContent = formatTime(audio && isFinite(audio.currentTime) ? audio.currentTime : 0);
			if (durEl) durEl.textContent = formatTime(audio && isFinite(audio.duration) && audio.duration > 0 ? audio.duration : 0);

			try { window.requestAnimationFrame(drawFrame); } catch(e){}
		};

		var progressFromX = function(clientX){
			var rect = canvas.getBoundingClientRect();
			if (!rect.width) { return null; }
			return clamp01((clientX - rect.left) / rect.width);
		};

		var commitSeek = function(p){
			var d = audio.duration;
			if (!d || !isFinite(d)) { return; }
			try { audio.currentTime = clamp01(p) * d; } catch(e){}
			targetProgress = clamp01(p);
		};

		if (audio){
			audio.addEventListener('timeupdate', function(){
				if (!audio.duration || !isFinite(audio.duration)) { return; }
				targetProgress = clamp01(audio.currentTime / audio.duration);
			});
			audio.addEventListener('progress', function(){
				var d = audio.duration;
				if (!d || !isFinite(d)) { targetBuffered = 0; return; }
				targetBuffered = clamp01(getBufferedEnd() / d);
			});
		}

		canvas.addEventListener('touchstart', function(e){
			var t = e.touches && e.touches[0] ? e.touches[0] : null;
			if (!t) { return; }
			touchStartX = t.clientX;
			touchStartY = t.clientY;
			touchMode   = 'pending';
			isDragging  = false;
		}, { passive: false });

		canvas.addEventListener('touchmove', function(e){
			if (touchMode === 'idle' || touchMode === 'scroll') { return; }
			var t = e.touches && e.touches[0] ? e.touches[0] : null;
			if (!t) { return; }
			var dx = t.clientX - touchStartX;
			var dy = t.clientY - touchStartY;
			var adx = Math.abs(dx);
			var ady = Math.abs(dy);
			if (touchMode === 'pending') {
				if (adx < 8 && ady < 8) { return; }
				if (ady > adx) {
					touchMode = 'scroll';
					isDragging = false;
					return;
				}
				touchMode = 'scrub';
				isDragging = true;
			}
			if (touchMode !== 'scrub') { return; }
			var p = progressFromX(t.clientX);
			if (p === null) { return; }
			dragProgress = p; targetProgress = p;
			try { e.preventDefault(); } catch(err){}
		}, { passive: false });

		var endTouchScrub = function(e){
			if (touchMode !== 'scrub' || !isDragging) {
				touchMode = 'idle';
				isDragging = false;
				return;
			}
			isDragging = false;
			touchMode = 'idle';
			commitSeek(dragProgress);
			lastScrubMs = (typeof performance !== 'undefined' && performance.now) ? performance.now() : Date.now();
			if (api && typeof api.play === 'function') { try{ api.play(); }catch(err){} }
			if (e && e.changedTouches && e.changedTouches.length) { try{ e.preventDefault(); }catch(err){} }
		};
		canvas.addEventListener('touchend',    endTouchScrub, { passive: false });
		canvas.addEventListener('touchcancel', endTouchScrub, { passive: false });

		canvas.addEventListener('pointerdown', function(e){
			var p = progressFromX(e.clientX);
			if (p === null) { return; }
			isDragging = true; dragProgress = p; targetProgress = p;
			try { canvas.setPointerCapture(e.pointerId); } catch(err){}
		});
		canvas.addEventListener('pointermove', function(e){
			if (!isDragging) { return; }
			var p = progressFromX(e.clientX);
			if (p === null) { return; }
			dragProgress = p; targetProgress = p;
		});
		var stopScrub = function(e){
			if (!isDragging) { return; }
			isDragging = false;
			try { canvas.releasePointerCapture(e.pointerId); } catch(err){}
			commitSeek(dragProgress);
			lastScrubMs = (typeof performance !== 'undefined' && performance.now) ? performance.now() : Date.now();
			if (api && typeof api.play === 'function') { try{ api.play(); }catch(err){} }
		};
		canvas.addEventListener('pointerup',          stopScrub);
		canvas.addEventListener('pointercancel',      stopScrub);
		canvas.addEventListener('lostpointercapture', stopScrub);

		canvas.addEventListener('click', function(e){
			if (isDragging) { return; }
			var now = (typeof performance !== 'undefined' && performance.now) ? performance.now() : Date.now();
			if (now - lastScrubMs < 350) { return; }
			var p = progressFromX(e.clientX);
			if (p === null) { return; }
			commitSeek(p);
			if ((audio.paused || audio.ended) && api && typeof api.play === 'function') {
				try{ api.play(); }catch(err){}
			}
		});

		var loadWaveform = function(track, ti){
			if (!track) {
				currentWaveforms = [];
				return;
			}
			var hasWaveformUrl = !!(track.waveform && typeof track.waveform.url === 'string' && track.waveform.url);
			if (!hasWaveformUrl) {
				currentWaveforms = [];
				return;
			}
			var key = '';
			if (track.audio && typeof track.audio.attachment_id !== 'undefined' && track.audio.attachment_id !== null) {
				key = String(track.audio.attachment_id);
			} else {
				key = track.waveform.url;
			}
			if (!key) {
				currentWaveforms = [];
				return;
			}
			if (waveformCache[key]) {
				currentWaveforms = waveformCache[key] || [];
				return;
			}
			currentWaveforms = [];
			waveReqId++;
			var myId = waveReqId;
			try {
				fetch(track.waveform.url, { method: 'GET', headers: { 'Accept': 'application/json' } }).then(function(res){
					if (!res || !res.ok) {
						try {
							if (res && res.status === 404 && window.THESPL_Player_UI && typeof window.THESPL_Player_UI.setTrackWaveformNotice === 'function') {
								window.THESPL_Player_UI.setTrackWaveformNotice(root, ti, 'error-waveform-not-found');
							}
						} catch (e) {}
						return null;
					}
					return res.json();
				}).then(function(data){
					if (!data || waveReqId !== myId) {
						return;
					}
					var perVariant = [];
					if (data && Object.prototype.hasOwnProperty.call(data, 'pairs') && Array.isArray(data.pairs) && data.pairs.length) {
						perVariant = data.pairs.map(function(p){
							var src = null;
							if (p && Array.isArray(p.pairComposite)) {
								src = p.pairComposite;
							} else if (p && Array.isArray(p.composite)) {
								src = p.composite;
							}
							if (!src || !src.length) {
								return new Float32Array(0);
							}
							var out = new Float32Array(src.length);
							var max = 0;
							for (var i = 0; i < src.length; i++) {
								var v = typeof src[i] === 'number' ? src[i] : 0;
								var a = Math.abs(v);
								out[i] = a;
								if (a > max) {
									max = a;
								}
							}
							if (max > 0) {
								var inv = 1 / max;
								for (var j = 0; j < out.length; j++) {
									out[j] *= inv;
								}
							}
							return out;
						});
					}
					if (!perVariant || waveReqId !== myId) {
						return;
					}
					waveformCache[key] = perVariant;
					currentWaveforms = perVariant;
				}).catch(function(){
				});
			} catch (e) {}
		};

		var refreshWaveform = function(){
			if (!store) {
				return;
			}
			var pl = typeof store.getPlaylist === 'function' ? store.getPlaylist(root) : null;
			var sel = typeof store.getSelection === 'function' ? store.getSelection(root) : null;
			if (!pl || !Array.isArray(pl.tracks) || !pl.tracks.length) {
				currentWaveforms = [];
				lastTrackKey = '';
				return;
			}
			var ti = sel && typeof sel.trackIndex === 'number' ? sel.trackIndex : 0;
			if (ti < 0 || ti >= pl.tracks.length) {
				ti = 0;
			}
			var track = pl.tracks[ti];
			var key = '';
			if (track && track.audio && typeof track.audio.attachment_id !== 'undefined' && track.audio.attachment_id !== null) {
				key = String(track.audio.attachment_id);
			} else if (track && track.waveform && typeof track.waveform.url === 'string' && track.waveform.url) {
				key = track.waveform.url;
			}
			if (!key) {
				currentWaveforms = [];
				lastTrackKey = '';
				return;
			}
			if (key === lastTrackKey) {
				return;
			}
			lastTrackKey = key;
			loadWaveform(track, ti);
		};

		if (store && typeof store.subscribe === 'function'){
			store.subscribe(root, function(){ refreshWaveform(); });
		}
		refreshWaveform();
		try { window.requestAnimationFrame(drawFrame); } catch(e){}
	};

	if (document.readyState === 'loading'){
		document.addEventListener('DOMContentLoaded', initCoverFlow);
	} else {
		initCoverFlow();
	}
})();
