// Small helpers shared by the web player's modules.
export const $ = (s, r = document) => r.querySelector(s);
export const $$ = (s, r = document) => [...r.querySelectorAll(s)];
export const esc = s => String(s ?? "").replace(/[&<>"']/g, c => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
export const fmtTime = s => { s = Math.max(0, Math.floor(s || 0)); return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`; };
export const fmtBytes = n => n >= 1e9 ? (n / 1e9).toFixed(1) + " GB" : (n / 1e6).toFixed(n >= 1e8 ? 0 : 1) + " MB";
export const plural = (n, w) => `${n.toLocaleString()} ${w}${n === 1 ? "" : "s"}`;
export const shuffled = a => { a = a.slice(); for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; };
export const clone = o => JSON.parse(JSON.stringify(o ?? null));
// crypto.randomUUID only exists on HTTPS pages, and the player is usually opened over plain HTTP.
export const uuid = () => crypto.randomUUID ? crypto.randomUUID() : Date.now().toString(36) + Math.random().toString(36).slice(2);
export function load(k) { try { return JSON.parse(localStorage.getItem(k)); } catch { return null; } }
export function store(k, v) { try { localStorage.setItem(k, JSON.stringify(v)); } catch {} }
// Lets the player tell the UI what changed without importing it.
const bus = {};
export const on = (ev, fn) => { (bus[ev] ||= []).push(fn); };
export const emit = (ev, ...args) => { for (const fn of bus[ev] || []) fn(...args); };
export function toast(msg, ms = 2400) {
let t = $("#toast");
if (!t) {
t = document.createElement("div");
t.id = "toast";
document.body.append(t);
}
t.textContent = msg;
t.classList.add("show");
clearTimeout(t._h);
t._h = setTimeout(() => t.classList.remove("show"), ms);
}
export const ICON = {
play: '',
pause: '',
prev: '',
next: '',
shuffle: '',
repeat: '',
repeat1: '',
mixer: '',
queue: '',
lyrics: '',
more: '',
download: '',
busy: '',
};